Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add texture partial update method #80164

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Redwarx008
Copy link
Contributor

@Redwarx008 Redwarx008 commented Aug 2, 2023

Due to some operational errors, I had to resubmit the pr.
Add texture_2d_update_partial method for RenderingServer.
Compressed textures are not supported, they are usually not present in use cases for this function.

Bugsquad edit:

@akien-mga
Copy link
Member

akien-mga commented Aug 2, 2023

Your branch is a couple of months behind the current master, and thus has merge conflicts. Could you rebase?

Edit: I see you pushed a merge commit at the same time I wrote this. Please rebase instead to keep a single commit in the PR. See PR workflow.

@Redwarx008 Redwarx008 force-pushed the add-texture-partial-update branch 17 times, most recently from d94a0cc to 316e86b Compare August 4, 2023 17:01
@Redwarx008
Copy link
Contributor Author

Reference #80781, fixed this issue

@Redwarx008 Redwarx008 force-pushed the add-texture-partial-update branch 3 times, most recently from d75283b to 30aed6b Compare August 22, 2023 03:10
@Redwarx008 Redwarx008 force-pushed the add-texture-partial-update branch 2 times, most recently from 7f07049 to 46003e4 Compare August 22, 2023 11:45
Copy link
Member

@clayjohn clayjohn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you have lost a few of the changes you made in the last PR, particularly, it looks like this has lost the ability to specify a sub region of the source image

ERR_FAIL_COND(p_data.is_null() || p_data->is_empty());

Texture *texture = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND_MSG(p_data->is_compressed() || texture->compressed, "Compressed texture is not supported.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ERR_FAIL_COND_MSG(p_data->is_compressed() || texture->compressed, "Compressed texture is not supported.");
ERR_FAIL_COND_MSG(p_data->is_compressed() || texture->compressed, "Compressed texture is not supported for partial texture updates. Please use an uncompressed image instead.");


Texture *texture = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND_MSG(p_data->is_compressed() || texture->format > Image::FORMAT_RGBE9995, "Compressed texture is not supported.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ERR_FAIL_COND_MSG(p_data->is_compressed() || texture->format > Image::FORMAT_RGBE9995, "Compressed texture is not supported.");
ERR_FAIL_COND_MSG(p_data->is_compressed() || texture->format > Image::FORMAT_RGBE9995, "Compressed texture is not supported for partial texture updates. Please use an uncompressed image instead");

@Redwarx008
Copy link
Contributor Author

Redwarx008 commented Aug 22, 2023

It looks like you have lost a few of the changes you made in the last PR, particularly, it looks like this has lost the ability to specify a sub region of the source image

After thinking, I changed the api, now the parameter data:Image is a wrapper for the target area data. This makes the api clearer.

@Redwarx008
Copy link
Contributor Author

Redwarx008 commented Aug 22, 2023

If the texture is updated from a specific sub region of the src image, when the texture is three-channel, it will be converted to four-channel. This is very expensive if the texture is large

@Redwarx008 Redwarx008 force-pushed the add-texture-partial-update branch from 46003e4 to 6864e88 Compare August 22, 2023 13:34
@AThousandShips AThousandShips modified the milestones: 4.2, 4.3 Oct 31, 2023
@npip99
Copy link

npip99 commented Nov 23, 2023

Can I know what's holding this PR back? I can try to help contribute; it was rebased but never merged.

There's no solution or alternative to this functionality not existing; there's just no way to edit terrains or modify images without FPS dropping significantly when updating the entire image.

@AThousandShips
Copy link
Member

If hasn't been approved so it can't be merged, we are currently in feature freeze and this can't be considered before 4.2 has been released

@Calinou
Copy link
Member

Calinou commented Nov 23, 2023

@npip99 I suggest testing this pull request and uploading a testing project that makes use of it to demonstrate it's working.

@KoBeWi
Copy link
Member

KoBeWi commented Nov 23, 2023

We are using this PR in a custom fork for a new project (with terrain destruction like in Lumencraft, but in Godot 4), so I can confirm it works.

Copy link
Member

@clayjohn clayjohn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this PR lost some of the work done in #75892

We should get the API back to the state it was in before (i.e. users should be able to specify a sub-region). There is no performance benefit to removing that ability from the API. The code can easily do the following:

  1. If the sub-region is the size of p_image, copy directly (as you have now)
  2. If the sub-region is smaller than p_image, grab a slice of the image (like we did in 3.x)
    Ref<Image> p_sub_img = p_image;
    if (src_x > 0 || src_y > 0 || src_w != p_image->get_width() || src_h != p_image->get_height()) {
    p_sub_img = p_image->get_rect(Rect2(src_x, src_y, src_w, src_h));
    }
  3. If the sub-region is larger than p_image, error

If we remove the sub-region from the API, we just force the user to do step 2. We don't actually save any performance and we make the API harder for users to use. Further, users will see the change as a regression, because something that was easy to do in 3.x is now hard

@@ -109,6 +109,7 @@ class RenderingServer : public Object {
virtual RID texture_proxy_create(RID p_base) = 0;

virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0;
virtual void texture_2d_update_partial(RID p_texture, const Ref<Image> &p_data, Vector2i p_dst_pos, int p_dst_mipmap = 0, int p_layer = 0) = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just linking back to the previous PR's reviews #75892 (comment)

It seems like you have lost some of the API changes suggested by reviewers.

@Redwarx008
Copy link
Contributor Author

Redwarx008 commented Nov 24, 2023

Looks like this PR lost some of the work done in #75892

This is done intentionally and is not some work lost.
Actually, a three-channel texture is not available, so here it will be converted into a four-channel texture. If subregions are used, the entire p_image will be converted, which has a significant impact on performance if its dimensions are very large. We can perform special processing for all three-channel textures here, but this is a hack. We can avoid this situation by forcing the user to obtain the sub-area outside first in the design of the API.
Many APIs have changed from 3.x to 4.x, why not include this? What's more, it is not a commonly used API.

@npip99
Copy link

npip99 commented Nov 25, 2023

Why would the whole p_image have to be converted? If the src_rect is 10x10, but the src_image is 2048x2048, can't it be possible to just copy and convert the data from the 10x10 source subregion, without copying or converting the entire 2048x2048 image.

We can avoid this situation by forcing the user to obtain the sub-area outside first in the design of the API.

That's true, the user can call Image.get_region in GDScript, and then pass that into the new function signature. But, it might be possible to write code that makes texture_2d_update_partial(src_image, src_rect) faster than in GDScript calling Image.get_region and passing that. Given that it's a low-level function given exclusively for acceleration and speed, it would be useful to leave every opportunity available for it to be as efficient as it can be.

In my case, I'm keeping an "Image" instance in GDScript and editing it every single frame, and then I simply wish to blit a subrectangle back to the ImageTexture every single frame so that the 3D Model's texture updates in realtime. I personally track and update the minX/maxX/minY/maxY for every pixel update, so that I can give the src_rect during the blits. In this case, even if src_rect as an argument isn't more efficient (yet), it's also a much simpler API for this type of usage. I imagine my usage is in-general the most common usage for this exact function.

I think for now, with the current solution, it should be possible to just call Image.get_region internally, making it no faster than the user doing GDScript Image.get_region, but it also shouldn't be any slower either. And leave any future optimizations to the future (Any future optimizations wouldn't affect the Big-O or anything fundamental, it would just be slightly faster). In my case, I'd appreciate the opportunity for optimization in a future PR to be beneficial, as every incremental slight improvement allows me to increase the resolution of the modifiable texture in my game.

@Redwarx008
Copy link
Contributor Author

Why would the whole p_image have to be converted? If the src_rect is 10x10, but the src_image is 2048x2048, can't it be possible to just copy and convert the data from the 10x10 source subregion, without copying or converting the entire 2048x2048 image.

Since this only needs to be done for all three-channel textures, the special processing is inelegant.

@nackata
Copy link

nackata commented Jul 6, 2024

Hello, this issue also can be fixed by this PR! Zylann/godot_heightmap_plugin#445

@clayjohn clayjohn modified the milestones: 4.3, 4.4 Jul 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

RenderingServer.texture_2d_update_partial() missing
8 participants