-
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
[WIP] Simplify texture names and support more than two textures in the shaders. #534
Conversation
This is a work in progress (do not land), I haven't yet figured out all of the places where to use generic names versus specific (for example I have a hunch that mask_texture_id in prim_store.rs may used as a non-mask texture but I am not sure). Feedback welcome! |
This redirection would allow us to use less texture slots, so can be useful if we see the problem with the texture slots on the horizon. Alternatively, If we don't anticipate the problem, we can continue using pre-defined slots for stuff, just make it more clean (i.e. add |
I'm all for not aliasing the sampler names if we have the budget to do so. As long as I can trust the variable names when I read the code I am happy. we'd have:
It would not be too bad to reuse "color" for the yuv planes so we could have instead:
That's for the shaders. The rust side of things has the same naming issue (even harder to understand in my opinion) which my patch doesn't properly address yet. |
I'd prefer not to alias the names right now - we can deal with that if/when we hit it. Having sColor0-2 and sMask seems good to me. |
☔ The latest upstream changes (presumably #527) made this pull request unmergeable. Please resolve the merge conflicts. |
Sounds good to me, I'll update the PR. |
The latest version is still a work in progress. Shaders can receive up to 3 color textures plus 1 mask. AlphaBatchKey specifies the four textures (instead of a color and something that is either a mask or a color but is called mask), I haven't gotten to the primitive store yet, but something similar needs to happen there. Note that these four SourceTexture enums end up taking a lot more space that two texture ids. If that's an issue we can optimize the SourceTexture data structure (for example encode the external key in the TextureId using some of the spare bits in the target member to differentiate between the two). |
Things are starting to come together. I have removed the SourceTexture/ExternalImage part, which I'll come back with in a separate pull request. This PR now does the following things:
|
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.
Looks good! Got a few non-critical nits to address.
@@ -58,7 +58,7 @@ float do_clip(vec2 pos) { | |||
vec2 clamped_mask_uv = repeat_mask ? fract(vMaskUv) : | |||
clamp(vMaskUv, vec2(0.0, 0.0), vec2(1.0, 1.0)); | |||
vec2 source_uv = clamped_mask_uv * vClipMaskUvRect.zw + vClipMaskUvRect.xy; | |||
float mask_alpha = texture(sMask, source_uv).r; //careful: texture has type A8 | |||
float mask_alpha = texture(sMask, source_uv).r; //careful: texture has type A8 |
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.
accidental spacing?
@@ -341,6 +341,8 @@ impl TextureId { | |||
target: gl::TEXTURE_2D, | |||
} | |||
} | |||
|
|||
pub fn is_invalid(&self) -> bool { *self == TextureId::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.
while certainly useful, I think it would be better to avoid double-negative, and have is_valid()
method instead
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 originally had is_valid, but all call sites were negating it if !texture.is_valid() { ...
so I ended up bundling the negation in the function. I don't mind either way, whichever you prefer works for me.
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.
Perf-wise, marking it #[inline]
makes both equally efficient, and !texture.is_valid()
takes even 1 less char than texture.is_invalid()
, so it's not like we are sacrificing compactness for clarity here :)
} | ||
|
||
// In some places we need to temporarily bind a texture to any slot. | ||
pub const DEFAULT_SAMPLER: TextureSampler = TextureSampler::Color0; |
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, we can lean more to the "texture" part of the concept, since eventually we'll have separate samplers from textures, and this term (DEFAULT_SAMPLER
) will be misleading. Maybe DEFAULT_TEXTURE
?
/// Optional textures that can be used as a source in the shaders. | ||
/// Textures that are not used by the batch are equal to TextureId::invalid(). | ||
#[derive(Copy, Clone, Debug)] | ||
pub struct PrimitiveBatchTextures { |
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.
that's nice! Although, FYI the mask
one may be gone soon.
@@ -93,7 +93,7 @@ pub enum ImagePrimitiveKind { | |||
#[derive(Debug)] | |||
pub struct ImagePrimitiveCpu { | |||
pub kind: ImagePrimitiveKind, | |||
pub color_texture_id: TextureId, | |||
pub color_texture: TextureId, |
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.
any reason you didn't like the _id
at the end?
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.
that's an artifact from when I had replaced some of the TextureId by the SourceTexture enum (and thus removed the _id suffix) before splitting that out for a future PR. I'll correct that.
self.device.bind_texture(TextureSampler::Mask, mask_texture_id); | ||
|
||
// TODO(nical): This will force all unused slots to be bound to the invalid | ||
// TextureId. Should we just leave them out? |
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.
yeah, no need to touch what is not used
if a texture is used and not provided (thus forcing us to bind invalid()
), that's a bug we should be chasing and fixing
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.
FWIW we already explicitly bind to TextureId::invalid in some places such as
webrender/webrender/src/renderer.rs
Line 1157 in 74a21e9
self.device.bind_texture(TextureSampler::Mask, TextureId::invalid()); |
The renderer currently also does that for the color and mask textures every time.
In practice it unbinds the texture since the "invalid" gl handle is 0 under the hood.
I don't know if unbinding an unused texture slot after a pass that used it has any noticeable overhead so I added the comment bu it's probably not a big deal.
} | ||
|
||
impl PrimitiveBatchTextures { | ||
pub fn no_texture() -> Self { |
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 just empty()
?
self.device.delete_buffer(ubo); | ||
} | ||
let max_prim_items = self.max_prim_blends; | ||
self.draw_ubo_batch(ubo_data, shader, |
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.
interesting. @glennw do you remember why draw_ubo_batch
wasn't used here in the first place?
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.
Hmmm, I'm not sure - possibly just an oversight.
self.color_texture_id == other.color_texture_id) && | ||
(self.mask_texture_id == TextureId::invalid() || other.mask_texture_id == TextureId::invalid() || | ||
self.mask_texture_id == other.mask_texture_id) | ||
(self.textures.colors[0].is_invalid() || other.textures.colors[0].is_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.
could use some iteration here for DRY
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.
@nical This looks great, it tidies up the code a lot and adds support for the extra texture slots we need.
I was a little confused why you had come across usage of sMask as a color texture - then I realised there are a heap of old, unused shaders in the resource dir. I've removed them in #542.
So you'll need to rebase after that lands, which should be easy. Apart from that and the couple of minor comments, this should be good to merge if you're happy with it after that?
self.device.delete_buffer(ubo); | ||
} | ||
let max_prim_items = self.max_prim_blends; | ||
self.draw_ubo_batch(ubo_data, shader, |
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.
Hmmm, I'm not sure - possibly just an oversight.
self.color_texture_id == other.color_texture_id) && | ||
(self.mask_texture_id == TextureId::invalid() || other.mask_texture_id == TextureId::invalid() || | ||
self.mask_texture_id == other.mask_texture_id) | ||
(!self.textures.colors[0].is_valid() || !other.textures.colors[0].is_valid() || |
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.
Can we add a (inline) function to check if two textures are compatible? That would make this function a lot easier to read.
☔ The latest upstream changes (presumably #542) made this pull request unmergeable. Please resolve the merge conflicts. |
@nical BTW, I've finished up the work I was doing for text-shadow to allow me to work on the texture cache. This is mostly related to improvements for handling the glyph cache, but is likely to overlap quite a bit with the SourceTexture / ExternalTexture stuff you mentioned - so we should discuss that at some point. In the meantime, let's get this PR finished up and merged as soon as we can :) |
6a379df
to
c2bf9c9
Compare
I rebased everything on top of current master (which was epic, I should have squashed the commits before rather than after doing that), and squashed it down to one commit. |
☔ The latest upstream changes (presumably #546) made this pull request unmergeable. Please resolve the merge conflicts. |
@bors-servo r+ |
📌 Commit 5b8f55f has been approved by |
[WIP] Simplify texture names and support more than two textures in the shaders. WebRender currently mostly assumes two reusable texture slots: the color and mask textures, which are sometimes used as color and color, and will soon be also used for other purposes like the Y, U and V planes (requiring an extra slot). The way some shaders refer to the mask texture (sMask) as an extra color texture is confusing, and while it is most often used as a mask, the fact that it is sometimes not used as such means one can never know for sure until careful review of the corresponding shader code. We also need more samplers for some effects such as YUV images. I propose that the reusable samplers have generic names (sTexture0, sTexture1, etc.) which are used in the generic places (for example the device mostly does not know whether a texture is used as a color, a mask or a YUV plane), with a collection of specific name aliases (COLOR_TEXTURE_0, MASK_TEXTURE, Y_TEXTURE, etc.) for the code manipulating the samplers for specific purposes. This applies to both the shaders and the various data structures generated in the render backend. <!-- 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/534) <!-- Reviewable:end -->
☀️ Test successful - status-travis |
WebRender currently mostly assumes two reusable texture slots: the color and mask textures, which are sometimes used as color and color, and will soon be also used for other purposes like the Y, U and V planes (requiring an extra slot).
The way some shaders refer to the mask texture (sMask) as an extra color texture is confusing, and while it is most often used as a mask, the fact that it is sometimes not used as such means one can never know for sure until careful review of the corresponding shader code.
We also need more samplers for some effects such as YUV images.
I propose that the reusable samplers have generic names (sTexture0, sTexture1, etc.) which are used in the generic places (for example the device mostly does not know whether a texture is used as a color, a mask or a YUV plane), with a collection of specific name aliases (COLOR_TEXTURE_0, MASK_TEXTURE, Y_TEXTURE, etc.) for the code manipulating the samplers for specific purposes. This applies to both the shaders and the various data structures generated in the render backend.
This change is![Reviewable](https://camo.githubusercontent.com/1541c4039185914e83657d3683ec25920c672c6c5c7ab4240ee7bff601adec0b/68747470733a2f2f72657669657761626c652e696f2f7265766965775f627574746f6e2e737667)