The text here ties this fairly strongly to the input format, as well as the specifics of DXBC containers. I'm not going to object too much, but I'm not sure that's entirely warranted; I could imagine the the target format/API making a difference for what we return here, as well as compilation options. I could also imagine e.g. compiling HLSL to GLSL, and still wanting information about the input/output interface. Perhaps notably, the API tests here use HLSL as actual source.
Is there a notion of shader signature which is at the same time sufficiently general so that it applies to all (or at least most) shader formats and sufficiently specific so that it's actually usable for something?
I think the current vkd3d_shader_signature structure should work for most purposes, although an argument could be made for extending it with some of the additional DXIL and SPIR-V features.
Taking a step back though, signatures provide information about the interface between shaders and their environment:
- For a vertex shader input signature, that's mainly the mapping of shader input registers to vertex attributes in the target API (i.e., OpenGL/Vulkan/Direct3D/Metal). - For a vertex shader output signature, that's the mapping of shader output registers to the interstage interface with the next shader. - For a root signature, that's the mapping of shader resources (CBV/SRV/UAV) and samplers to the corresponding bind points in the target API.
That means there are broadly two kinds of usage for this information:
- Setting up bindings (attributes, resources, samplers, etc.) in the target environment. - Matching up the interstage interface during shader translation.
Due to differences in target APIs, it can sometimes be useful to specify the interface from the point of view of the target environment as well. For example, this is the case when translating Direct3D 11 shaders to SPIR-V/Vulkan; Direct3D 11 has fixed API bind points for resources, while Vulkan has the more flexible descriptor sets/layouts.
The approach taken for descriptor bindings is that the vkd3d_shader_scan_descriptor_info structure returns information about the descriptors used by the shader, while the vkd3d_shader_interface_info structure provides information about how to map these to the target environment. (And by contrast, vkd3d_shader_parse_root_signature() and vkd3d_shader_parse_input_signature() just parse the raw data.)
There's probably an argument to be made for not lumping input attribute binding information and interstage interface information together as well...