Second, signatures synthesized from sm1 byte code. This is conceptually a bit weird, because sm1 does not have signatures, but in terms of how these APIs are used by Wine (or other translation layers, as evidenced not least by the Vulkan test shader runner, which I have locally adapted for sm1 but not submitted yet) it fits rather nicely.
It's not that weird. Shaders have interfaces with each other and the rest of the API. For d3dbc shaders those are largely implicit interfaces, while tpf made them much more explicit. We could call this something else if you prefer, but conceptually it's very similar to the existing vkd3d_shader_scan_descriptor_info structure. In principle there's no reason we couldn't return this kind of information for SPIR-V/HLSL/GLSL/MSL shaders either.
Also, it's perhaps worth pointing out that a (fairly rudimentary) version of this exist in d3dx9 as D3DXGetShaderInputSemantics() and D3DXGetShaderOutputSemantics(); it might be worth making sure that we're able to implement those on top of this, although it doesn't look too hard.
Because this is new API, it of course deserves plenty of discussion, especially the sm1 part. Several open questions which occurred to me while writing are:
- Should we fix the mask (and used mask) for sm1 signatures as 0xf rather than 0? SPIR-V cares about this in order to declare I/O variables, which makes some amount of sense. In fact I have a patch in my local tree to change this, specifically for that purpose. However, we could also normalize it later.
- If we do fix the mask as nonzero, should single-component semantics (fog, depth, etc...) be declared as 0x1 instead of 0xf?
- Should BLENDINDICES get a UINT type? It's float in shader instructions (well, kind of, although in practice it's used as an array index of course), but the vertex attribute type is in practice "supposed" to be integer.
Could we just provide accurate information from the point of view of the user of the API? I.e., provide the actual masks and data types the shader expects and uses?
I'm not quite sure what that means in practice for BLENDINDICES; in wined3d we seem to map everything to WINED3D_TYPE_FLOAT, but it's not clear if that's correct because we have very little existing coverage for BLENDINDICES. But if e.g. Vulkan should pass the data for this as VK_FORMAT_R32_UINT, I think it should be UINT, yes.
+static bool vkd3d_shader_signature_from_shader_signature(struct vkd3d_shader_signature *signature, + const struct shader_signature *src);
I imagine we'll just want to move the function in the final version of this series and avoid the forward declaration.
+static bool add_signature_element(struct shader_signature *signature, const char *name, + unsigned int index, enum vkd3d_shader_sysval_semantic sysval, unsigned int register_index) +{ [...] + element->semantic_name = name; + element->semantic_index = index; + element->stream_index = 0; + element->sysval_semantic = sysval; + element->component_type = VKD3D_SHADER_COMPONENT_FLOAT; + element->register_index = register_index; + element->mask = 0; + element->used_mask = 0; + element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE; + + return true; +}
I think we should set the "register_count" field above. It will be largely unused for the moment, but vkd3d_shader_signature_from_shader_signature() will print a FIXME if it ends up being larger than 1.
Most of the FIXMEs should use vkd3d_parser_error()/vkd3d_parser_warning().