Closed Rewlion closed 1 month ago
Thanks for this! Internal folks at EA that use Gigi are excited about this feature going in. I've skimmed over the changes, and they look good at first blush. I'll take a deeper look today or tomorrow and should get this merged in and cut a new version of Gigi to include it.
Code flows from the internal repo to external, so I put your changes in the internal repo before merging them into this public one. This work is changelist e5b5fc449eefb49807881bd3c1393cd64b5ff6a2 and is part of release and tag v0.99.2.
I was impressed by your attention to detail. Thanks for this feature!
[CONTEXT]
New token is introduced: /$(Assert: condition [,fmt] [...])/
whenever condition is failed an error is printed to the interpreter log
It's mostly useful for the compute shaders to catch OOB access.
There are up to 6 formatting arguments supported. They are expected to be a type of 'float'. If assert has condition expression only then it becomes the message itself.
Right now there is only one assert fired per node-shader. It's done to exclude errors spamming. It means that an assert has identifier related to the shader and only the new unseen asserts are printed to the log.
This assert identifier is node name related. But it can be improved to be 'line' related this way each we can distinguish each /$(Assert)/ even if it has the same format string.
Asserts are available for the Interpreter backend only. It would be nice to have a toggle in the 'settings' that enables\disables asserts processing. To exclude addition of the nodes resources and processing when it's not required.
Supported action nodes: [X] DrawCall [X] ComputeShader
[IMPLEMENTATION] Preparations:
ShaderReferenceFixupVisitor execution is moved right after PostLoad because current commit requires a valid reference.shader pointer to be able to visit shaders from the Action Nodes.
Shader struct now has an addition field with array of token replacements. This way it's possible to add new visitors which able to generate hlsl code. And potentially track which visitor produced what code. Later on all token replacements will be added to shaderSpecificStringReplacementMap
New logic: Idea is simple.
New visitor 'ShaderAssertsVisitor' is added it processes action nodes and their shaders.
For each shader with assert token it adds a token replacement (to replace token on function call) and remembers a formatting string.
new UAV buffer with assert info is added to the each action node that has a shader with assert. For simplicity reasons there is a UAV buffer per each shader. It can be redone as one UAV buffer per action node if required.
UAV FORMAT (32byte): uint isFired uint fmtId uint v1 uint v2 uint v3 uint v4 uint v5 uint v6
thus we have +32byte overhead per each shader with assert in the action node.
UAV buffer per node/shader is useful because we don't need to write an extra processing logic for the readback. after each shader execution we already have before,after resources.
Unique formatting strings and fired asserts are stored in the rendergraph. Because they are specific to the RG and this way will be reset on new RG creation.
Asserts buffers are marked for readback in the RenderFrame (viewer's main.cpp) and further on get collected and printed to the UI log.
Information about fired asserts are mainly done in the way it can be easily verified in the unit test.