-
Notifications
You must be signed in to change notification settings - Fork 282
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
Handle 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. |
☔ The latest upstream changes (presumably #1563) made this pull request unmergeable. Please resolve the merge conflicts. |
@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
Compare
@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. |
☔ The latest upstream changes (presumably #1585) made this pull request unmergeable. Please resolve the merge conflicts. |
45c30a8
to
09a5c21
Compare
@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
Compare
webrender/src/resource_cache.rs
Outdated
// 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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
None => { |
webrender/src/resource_cache.rs
Outdated
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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?
webrender/src/resource_cache.rs
Outdated
// | ||
// TODO(Jerry): add a debug option to fill the corresponding area for | ||
// that invalid CacheItem. | ||
image_info.map_or(CacheItem::invalid(), |image_info| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
ctx.resource_cache.fetch_glyphs( |
[2]
https://github.com/servo/webrender/pull/1564/files#diff-77cbdf7ba9ebae81feb38a64c21b8454R630
[3]
webrender/webrender/src/tiling.rs
Line 518 in e11297a
|texture_id, glyphs| { |
☔ The latest upstream changes (presumably #1689) made this pull request unmergeable. Please resolve the merge conflicts. |
@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
Compare
webrender/src/tiling.rs
Outdated
@@ -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 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
for (mask_texture_id, items) in target.clip_batcher.images.iter() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for updating the PR!
I think my only concern is that we still need the key to be present in the resources map, while turning value into Result
.
webrender/src/resource_cache.rs
Outdated
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
Compare
@@ -1057,7 +1057,6 @@ impl PrimitiveStore { | |||
} | |||
} | |||
|
|||
/// Returns true if the bounding box needs to be updated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is not correct now.
webrender/src/resource_cache.rs
Outdated
pub struct ResourceClassCache<K, V> { | ||
resources: FastHashMap<K, V>, | ||
resources: FastHashMap<K, ResourceCacheCacheResult<V>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use Result instead of V.
webrender/src/resource_cache.rs
Outdated
// 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)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @JerryShih ! A few more things to fix before we proceed.
webrender/src/resource_cache.rs
Outdated
OverLimitSize, | ||
} | ||
|
||
pub type ResourceCacheCacheResult<V> = Result<V, ResourceClassCacheError>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps you meant ResourceClassCacheResult
?
@@ -159,7 +174,7 @@ where | |||
.cloned() | |||
.collect::<Vec<_>>(); | |||
for key in resources_to_destroy { | |||
self.resources.remove(&key).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this removed? I assume we get a warning about unused Result
or Option
webrender/src/resource_cache.rs
Outdated
} | ||
} else { | ||
// The image is too big for hardware texture size. | ||
if template.descriptor.width > self.texture_cache.max_texture_size() || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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));
webrender/src/resource_cache.rs
Outdated
// 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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for ok()
here
webrender/src/resource_cache.rs
Outdated
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here - no need for ok()
webrender/src/resource_cache.rs
Outdated
@@ -656,7 +692,15 @@ impl ResourceCache { | |||
tile, | |||
}; | |||
let image_info = &self.cached_images.get(&key); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would probably be cleaner with a simple match
statement
webrender/src/resource_cache.rs
Outdated
@@ -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(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for ok()
webrender/src/tiling.rs
Outdated
@@ -516,6 +517,8 @@ impl AlphaRenderItem { | |||
glyph_fetch_buffer, | |||
gpu_cache, | |||
|texture_id, glyphs| { | |||
debug_assert!(texture_id != SourceTexture::Invalid); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: debug_assert_ne!()
webrender/src/resource_cache.rs
Outdated
// | ||
// 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| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
Compare
webrender/src/resource_cache.rs
Outdated
@@ -174,7 +167,7 @@ where | |||
.cloned() | |||
.collect::<Vec<_>>(); | |||
for key in resources_to_destroy { | |||
self.resources.remove(&key); | |||
self.resources.remove(&key).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
Compare
…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, ! 👍 |
📌 Commit f903161 has been approved by |
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 -->
☀️ Test successful - status-appveyor, status-travis |
@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