Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upHandle big size image #1564
Handle big size image #1564
Conversation
|
I'm working on a large refactoring of the texture cache at the moment - if possible, I'd like to hold off on merging this until that's done. Is that going to be OK? (I would expect it to be done early next week). Handling this case should be much simpler with the changes I'm working on, too. |
|
|
|
@glennw |
|
@JerryShih The texture cache refactor has landed now. Instead of trying to use a dummy texture for this case, could we just not add the item to any batches when we find an invalid texture? |
@glennw |
|
I think the simplest approach will be to early exit from |
56d88b5
to
d58c2ff
|
@glennw r? And I need the help for the wrench reftest. I got the different result from the standalone yaml replay and the reftest result. standalone: reftest: I don't know the difference between them. |
|
|
45c30a8
to
09a5c21
|
@glennw r? again. |
|
@JerryShih I'm not really sure why it would be different between standalone and reftest. Perhaps the wrong texture is getting bound or something like that? I wrote up a prototype of what I was discussing above here glennw@9ca1214 I think if we use a solution like this, where it doesn't involve the texture cache at all, the code is quite a bit simpler. And when we want to display the bad texture, we could do that as a follow up in the renderer (handle the case where a texture resolves to SourceTexture::Invalid during batching). What do you think? |
Your prototype is much simpler than me. So, yours is a better solution. I add a comment in glennw/webrender@9ca1214. I will create another follow up if we need to show the skipped image. |
|
@JerryShih Sounds good, thanks! Do you want me to follow up your comments and open a PR, or should I leave that for you? |
|
@glennw |
|
@glennw has a better solution. Close this pr. |
09a5c21
to
152401b
| // just early out and drop the image. | ||
| if tile_size as u32 > self.texture_cache.max_texture_size() { | ||
| warn!("Dropping image, tile size:{} is too big for hardware!", tile_size); | ||
| return; |
This comment has been minimized.
This comment has been minimized.
kvark
Sep 6, 2017
Member
I'm a bit uncomfortable with these return statements as they are different from other return code paths from this method in that they are failures, while others are successes.
How about we return true/false (at least), and then also modify prepare_prim_for_render to return Option<Metadata> so that a primitive that failed to prepare can be discarded in time?
This comment has been minimized.
This comment has been minimized.
JerryShih
Sep 7, 2017
Author
Contributor
@kvark
I'm not familiar with the frame_builder::build process. The prepare_prim_for_render() is called by frame_builder::handle_primitive_run()[1]. And the handle_primitive_run() looks like to handle the mask and clip related thing. Are you thinking about skipping the render-task creation in handle_primitive_run() for the case of None Option return value?
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
JerryShih
Oct 11, 2017
Author
Contributor
The prepare_prim_for_render() is changed. The "Metadata" can't be remove now.
From the first comment:
I'm a bit uncomfortable with these return statements as they are different from other return code paths from this method in that they are failures, while others are successes.
We still have a case with a failure at [1] in request_image(). So, the new return statements are not just the new failed case. If they are still not looked good, I need to check the prepare_prim_for_render() for the "Metadata" removing.
[1]
webrender/webrender/src/resource_cache.rs
Line 553 in e11297a
| debug_assert!(texture_id == None || | ||
| texture_id == Some(cache_item.texture_id)); | ||
| texture_id = Some(cache_item.texture_id); | ||
| if let Some(glyph) = glyph_key_cache.get(key) { |
This comment has been minimized.
This comment has been minimized.
kvark
Sep 6, 2017
Member
We need to handle the case of failure here. Does it make sense to return as usual if some of the glyphs failed to be obtained?
| // | ||
| // TODO(Jerry): add a debug option to fill the corresponding area for | ||
| // that invalid CacheItem. | ||
| image_info.map_or(CacheItem::invalid(), |image_info| { |
This comment has been minimized.
This comment has been minimized.
kvark
Sep 6, 2017
Member
we call get_glyphs when populating batches. Wouldn't it be simpler to just return an error here, so that a corresponding instance can be discarded?
This comment has been minimized.
This comment has been minimized.
JerryShih
Oct 11, 2017
Author
Contributor
We call get_glyphs at [1]. If there is any error inside get_glyphs()[2], the lambda expression at [3] will not be called(which will push the instance to draw list).
[1]
webrender/webrender/src/tiling.rs
Line 513 in e11297a
[2]
https://github.com/servo/webrender/pull/1564/files#diff-77cbdf7ba9ebae81feb38a64c21b8454R630
[3]
webrender/webrender/src/tiling.rs
Line 518 in e11297a
|
|
|
@JerryShih @kvark What's the status of this? |
|
@glennw I'm check an animation artifact problem with WR. I will go back to finish this soon. |
152401b
to
58a136f
| @@ -813,6 +817,11 @@ impl ClipBatcher { | |||
| ClipSource::Image(ref mask) => { | |||
| let cache_item = | |||
| resource_cache.get_cached_image(mask.image, ImageRendering::Auto, None); | |||
| // Skip the invalid image mask. | |||
| if cache_item.texture_id == SourceTexture::Invalid { | |||
This comment has been minimized.
This comment has been minimized.
JerryShih
Oct 11, 2017
Author
Contributor
This image mask will be rendered at [1]. So, I think we should skip this image if the texture id is not valid.
[1]
webrender/webrender/src/renderer.rs
Line 2912 in e11297a
|
Thanks for updating the PR! |
| self.resources | ||
| .get(key) | ||
| .expect("Didn't find a cached resource with that ID!") | ||
| /// In some cases, we can't handle the resource request(e.g. the user |
This comment has been minimized.
This comment has been minimized.
kvark
Oct 11, 2017
Member
I think we should still differentiate between keys that didn't end up in the map for some other logical reasons, and keys that were just failing to be added. Perhaps, the resources map should contain Result<V> instead of V, so that we can handle those failures in a more explicit way?
58a136f
to
867da17
| @@ -1057,7 +1057,6 @@ impl PrimitiveStore { | |||
| } | |||
| } | |||
|
|
|||
| /// Returns true if the bounding box needs to be updated. | |||
This comment has been minimized.
This comment has been minimized.
| pub struct ResourceClassCache<K, V> { | ||
| resources: FastHashMap<K, V>, | ||
| resources: FastHashMap<K, ResourceCacheCacheResult<V>>, |
This comment has been minimized.
This comment has been minimized.
| // just early out and drop the image. | ||
| if tile_size as u32 > self.texture_cache.max_texture_size() { | ||
| warn!("Dropping image, tile size:{} is too big for hardware!", tile_size); | ||
| self.cached_images.insert(request, Err(ResourceClassCacheError::OverLimitSize)); |
This comment has been minimized.
This comment has been minimized.
JerryShih
Oct 12, 2017
Author
Contributor
If we hit the size limitation, just insert an Err() entry.
|
@kvark r? |
|
I haven't handled the Err() case for each get/get_mut() call, but I will just add some logs for these paths if we need to have these logs. |
|
Thanks @JerryShih ! A few more things to fix before we proceed. |
| OverLimitSize, | ||
| } | ||
|
|
||
| pub type ResourceCacheCacheResult<V> = Result<V, ResourceClassCacheError>; |
This comment has been minimized.
This comment has been minimized.
| @@ -159,7 +174,7 @@ where | |||
| .cloned() | |||
| .collect::<Vec<_>>(); | |||
| for key in resources_to_destroy { | |||
| self.resources.remove(&key).unwrap(); | |||
This comment has been minimized.
This comment has been minimized.
kvark
Oct 12, 2017
Member
why is this removed? I assume we get a warning about unused Result or Option
| } | ||
| } else { | ||
| // The image is too big for hardware texture size. | ||
| if template.descriptor.width > self.texture_cache.max_texture_size() || |
This comment has been minimized.
This comment has been minimized.
kvark
Oct 12, 2017
Member
should probably merge this block with the one above, using let side_size = image.tiling.unwrap_or(cmp::max(template.descriptor.width, template.descriptor.height));
| // If this image exists in the texture cache, *and* the epoch | ||
| // in the cache matches that of the template, then it is | ||
| // valid to use as-is. | ||
| let (entry, needs_update) = match self.cached_images.entry(request) { | ||
| Occupied(entry) => { | ||
| let needs_update = entry.get().epoch != template.epoch; | ||
| let needs_update = entry.get().as_ref().ok().unwrap().epoch != template.epoch; |
This comment has been minimized.
This comment has been minimized.
| true, | ||
| ), | ||
| }; | ||
|
|
||
| let needs_upload = self.texture_cache | ||
| .request(&mut entry.texture_cache_handle, gpu_cache); | ||
| .request(&mut entry.as_mut().ok().unwrap().texture_cache_handle, gpu_cache); |
This comment has been minimized.
This comment has been minimized.
| @@ -656,7 +692,15 @@ impl ResourceCache { | |||
| tile, | |||
| }; | |||
| let image_info = &self.cached_images.get(&key); | |||
This comment has been minimized.
This comment has been minimized.
| @@ -816,7 +860,7 @@ impl ResourceCache { | |||
| image_template.descriptor.clone() | |||
| }; | |||
|
|
|||
| let entry = self.cached_images.get_mut(&request).unwrap(); | |||
| let entry = self.cached_images.get_mut(&request).as_mut().ok().unwrap(); | |||
This comment has been minimized.
This comment has been minimized.
| @@ -516,6 +517,8 @@ impl AlphaRenderItem { | |||
| glyph_fetch_buffer, | |||
| gpu_cache, | |||
| |texture_id, glyphs| { | |||
| debug_assert!(texture_id != SourceTexture::Invalid); | |||
This comment has been minimized.
This comment has been minimized.
| // | ||
| // TODO(Jerry): add a debug option to fill the corresponding area for | ||
| // that invalid CacheItem. | ||
| image_info.as_ref().ok().map_or(CacheItem::invalid(), |image_info| { |
This comment has been minimized.
This comment has been minimized.
kvark
Oct 12, 2017
Member
let's just return Result<CacheItem, _> from this function and match it on the other side, there is no need for nullable CacheItem semantic (that invalid() does here)
867da17
to
d68cf51
| @@ -174,7 +167,7 @@ where | |||
| .cloned() | |||
| .collect::<Vec<_>>(); | |||
| for key in resources_to_destroy { | |||
| self.resources.remove(&key); | |||
| self.resources.remove(&key).unwrap(); | |||
This comment has been minimized.
This comment has been minimized.
JerryShih
Oct 13, 2017
Author
Contributor
I revert the change, but the CI test is failed.
error: unused std::result::Result which must be used
--> src/resource_cache.rs:170:13
|
170 | self.resources.remove(&key).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: -D unused-must-use implied by -D warnings
|
Thank you for addressing my comments!
Let's do Please squash the commits together, and we can merge once CI is happy. |
d68cf51
to
f903161
…it image request. WR can't handle the image request if it's bigger than the hardware limit. Please check texture_cache::max_texture_size(). Skip the image request for a big size image in resource_cache::request_image(). Return an Err() for a big size image in resource_cache::get_cached_image().
|
@kvark |
|
@JerryShih awesome, |
|
|
Handle big size image @nical @glennw @kvark @sotaroikeda r? This patch try to handle the #1405. If we hit the maximum texture size, turn to use a 1x1 rgba(255,255,255,255) dummy texture. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/1564) <!-- Reviewable:end -->
|
|
JerryShih commentedAug 9, 2017
•
edited by larsbergstrom
@nical @glennw @kvark @sotaroikeda
r?
This patch try to handle the #1405.
If we hit the maximum texture size, turn to use a 1x1 rgba(255,255,255,255) dummy texture.
This change is