KhronosGroup / Vulkan-ValidationLayers

Vulkan Validation Layers (VVL)
https://vulkan.lunarg.com/doc/sdk/latest/linux/khronos_validation_layer.html
Other
731 stars 397 forks source link

shader instrumentation: Ability to add custom code at the beginning of the main function #8121

Closed arno-lunarg closed 1 month ago

arno-lunarg commented 1 month ago

This would allow to group code common to all validation function calls. For instance for the inst_buffer_device_address validation function found in gpu_shaders/instrumentation/buffer_device_address.comp, stage_info is the same for every function calls. This feature will be needed to redo buffer address validation, if the new logic is to only store the address and not print errors: we would need to store shader invocation parameters in a different logic than the error message creation logic. Idea would be to do it once at the top of main.

spencer-lunarg commented 1 month ago

note inst_num is which SPIR-V instruction number we added the "check" too, so that is very unqiue

spencer-lunarg commented 1 month ago

So for stage_info we currently will only create it once per function block, so it will look like the following

void inst_buffer_device_address(uvec4 stage_info) {

}

void bar() {
   uvec4 stage_info;
   inst_buffer_device_address(stage_info);
}

void foo() {
   uvec4 stage_info;
   inst_buffer_device_address(stage_info);
}

void main() {
   uvec4 stage_info;
   inst_buffer_device_address(stage_info);

   foo();
   bar();
}

I adjusted it so it would look like

void inst_buffer_device_address(uvec4 stage_info) {

}

void bar() {
   inst_buffer_device_address();
}

void foo() {
   inst_buffer_device_address();
}

void main() {
   inst_buffer_device_address();

   foo();
   bar();
}

On Intel Mesa, they both take the same time to compile a large stress shader

They also both get turned into the exact same amount of native instructions, so seems moving this around will have no effects

spencer-lunarg commented 1 month ago

Ability to add custom code at the beginning of the main function

So 2 things about this,

if you have

void foo() { 
    inst_buffer_device_address();
}

void main() {
   foo();
   inst_buffer_device_address();
}

you are allowed to have a constant value across functions scopes, but if you need to do any logic at the top of main you will not be able to legally access it in foo (unless you use shared memory which is only found on compute shaders and has non-free access time)


If you want something that will let you write GLSL and inject it at the top of main (or any function) it won't be easy... currently the reason we can easily link the GLSL function into SPIR-V is because it is an isolated function scope...

currently I inject the stage_info at the top of main (and other function) so the ability to do this is there, but it will only be using C++ to write the SPIR-V logic

arno-lunarg commented 1 month ago

Oh I did not think about a couple of things that make what I want to do not feasible. With what I want, logic would be executed for every vertex, every fragment, etc... And I do not actually want that. And they are additional sync issues I did not think about. So closing the issue, and sorry for wasting your time (〜 ̄▽ ̄)〜

spencer-lunarg commented 1 month ago

sorry for wasting your time

no, this was a good experiment to show that the stage_info is good where it is and that the approach was right