-
-
Notifications
You must be signed in to change notification settings - Fork 21.1k
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
Support CUSTOM shader attributes in 2D #86564
Support CUSTOM shader attributes in 2D #86564
Conversation
@Calinou Please elaborate what you're looking for in a testing project beyond the sample project attached. |
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
507e2b0
to
a1430df
Compare
Now solved 🙂 |
a1430df
to
385645f
Compare
I added the CUSTOM0-3 properties to 2D visual shader. Missed that initially. The code is still working for forward/mobile renderer, but stopped working for compatibility after the merge. Looks like something changed where the input_mask passed into So, I first dived into trying to add I just added the customs to the end of the input mask for every 2D mesh in GLES3: I also updated the sample project with more test cases. |
If this PR hangs for another couple of months with no input like the last one, I'm giving up. |
I called a few people to review. |
This is worth some discussion with others in the rendering team as I am unsure what to do with this. An important design goal for us is to make basic rendering features compatible across all backends. Users should be able to rely on basic features continuing to work even when switching to the compatibility renderer. We try to limit the number of things that aren't supported in all backends. For the most part, things that aren't supported by all backends are optional features that can be turned on/off without significantly breaking the visuals (i.e. SDFGI, volumetric fog, etc.). This feature is a bit different. If we move forward with it, users will be able to create assets that work only in the RD-based backends. If they convert their project to the compatibility backend, their meshes will stop working entirely and they will have to re-design their assets to continue working. I don't think that is a situation I am comfortable introducing into the engine. Accordingly, in my mind, the only acceptable options are:
Seeing as the original proposal is only asking for one custom channel. It may make sense to just expose one custom value for now, and then expose another if there is demand. The trouble with exposing as many as possible is that we can't go backwards (i.e. we can always add more custom attributes, but we can never remove custom attributes). This should be discussed with other rendering contributors in our rendering meetings |
What would be the reason to pick 2 or 3 over 1? Saving vertex attribute slots for future unknown use? |
That's right. If users only need one CUSTOM slot, then there isn't much point in exposing 2, especially if it might block us from adding a different feature down the road |
I read this when fire pinged us and I was unsure myself. How does this interact with potentially exposing instance customs for canvas items? Are they sharing this resource? Regarding the compatibly between Rd and compat renderer, I do think that having assets that work in Rd and not in compat is a big problem, especially since our default renderer is Rd and this is about 2D. I think users will stumble on this way too much: they decide to make a 2D game that has a couple of effects, start in Rd, then decide to publish on low end, switch to compat, everything breaks. For me 2d is more critical than 3D for compatibility. |
In the case of Mesh, location 5 (instance_color_custom_data) is unused and in the case of both Mesh and MultiMesh, location 6 CUSTOM0 could be used. I don't believe it makes sense to share this, because the user would run into an issue where the code allows them to define both for a MultiMesh, but one would override the other, causing confusion. The offset for CUSTOM0 needs to be at 6 either way, in order for the bit shift masks to work correctly across all renderers. |
Another possibility to do the the complex tasks behind reorganizing these attributes in the code so that we get all CUSTOM variables for compatibility renderer and the forward renderer, but it would good to estimate and get support from the rendering team about merging before doing the work. |
GLES3 is nearly at the limit for canvas item attributes even with a reorg, if there is a concern about blocking new functionality that would still apply. If all CUSTOM0-3 were supported, that leaves 1 attribute slot left over. |
We discussed this yesterday in our weekly rendering meeting. We agreed that exposing CUSTOM0 and CUSTOM1 would be a good first step. In looking at the code closer we realized that we can free up one more slot if we need to by combining VERTEX and UV into one attribute. Therefore, we can safely expose CUSTOM0 and CUSTOM1 while having room for the future (which I think we will need quite soon actually). In theory we can expose more slots if we create a fallback shader that doesn't use attributes for batching properties. However, doing so will be a good amount of work and will make the code much more complex. So we prefer to only do that if we absolutely have to. Since the current users aren't asking for more than 1 CUSTOM vector, exposing 2 should be more than enough. In summary, for this PR to be merged, it just needs to be updated to only expose CUSTOM0 and CUSTOM1 for both RD renderers and the compatibility renderer. |
385645f
to
fafc0af
Compare
I removed CUSTOM2 and CUSTOM3, updated demo project with MultiMesh and visual shader sample. Updated GLES3 material storage to build vertex_input_mask instead of it being hard-coded. |
Just wanted to leave a note here as well in case people do need more than 8 channels of custom data in 2D... Because CUSTOM0-3 can support 4-component full 32-bit floats, there is nothing stopping a developer from bitpacking attribute data from individual 16-bit half floats or even 8-bit integers (which is sufficient for colors), in which case you could possibly support 24-32 custom 8-bit channels (depending on how I can't find any examples of people using this technique in practice, I suspect because people usually don't reach attribute limits... but anyway just want to put it out there. (and as always, be careful about perforamnce of vertex operations on old mobile hardware, especially with texture coords) |
Is anyone scheduled to review this? |
Not scheduled, no. But I started reviewing it and got pulled away to other tasks. I aim to finish the review shortly |
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 great so far!
I tested locally and can confirm that it works. I left some comments on cleaning up the code a bit and optimizing out some unnecessary work. Please let me know if you have any questions or if any of my suggestions don't make sense.
servers/rendering/shader_types.cpp
Outdated
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CUSTOM0"] = ShaderLanguage::TYPE_VEC4; | ||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CUSTOM1"] = ShaderLanguage::TYPE_VEC4; |
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.
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CUSTOM0"] = ShaderLanguage::TYPE_VEC4; | |
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CUSTOM1"] = ShaderLanguage::TYPE_VEC4; | |
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CUSTOM0"] = constt(ShaderLanguage::TYPE_VEC4); | |
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CUSTOM1"] = constt(ShaderLanguage::TYPE_VEC4); |
These should likely be constant as I don't see a reason why they would be written to. Weirdly enough the CUSTOM values in the spatial shader aren't marked as being constant. But since they aren't available in the fragment shader its kind of pointless to write to them
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.
Is this wrong on the Spatial side too? That is what I based it from.
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.
In my opinion, yes its wrong. However, to make the variables constant would technically break compatibility as users could do the following:
void vertex() {
CUSTOM0 = some_vec4;
...
some_other_variable = CUSTOM0;
}
Its kind of a crappy situation as we either break compatibility or we have inconsistent behavior between the shaders
948b052
to
0b8d381
Compare
0b8d381
to
bb83c4a
Compare
@clayjohn your feedback is implemented. I believe I cleaned up all the unnecessary variables now. |
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 great to me! Good work!
Thanks for sticking through multiple discussions and suggested changes. I think we settled on a good compromise that should make everyone happy.
Thanks! |
History: #76276
Closes: godotengine/godot-proposals#6703
A general summary of changes:
CUSTOM0 and CUSTOM1 vertex attributes are placed in the same attribute slot as their 3D counterparts. This simplifies the changes, so we don't have to modify things like the bit shift mask variables, or remap them.
In OpenGL ES 3, attribute layout slots 14 & 15 should exist under the minimum GL specification, so all of the slots are shifted down to make room for slots 6 & 7 to be used for custom attributes. You can read more about this in the proposal linked above.
Sample project:
CanvasShaderTest.zip