Note that use of immediate constants is *not* the way that wined3d currently handles DEF instructions, but rather those are uploaded via uniforms. Is there a reason for this?
We do use immediates when we can, see the "if (!shader->load_local_constsF)" block at the end of shader_generate_glsl_declarations(). There are a couple of cases where we can't use immediates though; relative addressing of constants is one case, and having non-finite values without GL_ARB_shader_bit_encoding is another.
It's perhaps also worth pointing out that Direct3D 8 can load shader constants from the vertex declaration using "D3DVSD_CONST"; we have a couple of examples of that in the Wine d3d8 tests.
Because API is easiest to review when there's a concrete user, I have functional patches hooking this up to wined3d, in the following branches:
https://gitlab.winehq.org/zfigura/vkd3d/-/commits/himavant5
https://gitlab.winehq.org/zfigura/wine/-/commits/himavant_cb
"wined3d: Compile sm1 bytecode to spirv." isn't quite right; determining the source type is slightly more complicated because of things like Aon9. See also shader_init(); my "glsl-vkd3d" series just stores "source_type" from that function in struct wined3d_shader.
That said, we may not want to lower to VKD3DSPR_CONSTBUFFER for GLSL without UBOs (but then again, we could also just emit VKD3DSPR_CONSTBUFFER registers as plain GLSL arrays).
I imagine the latter is what we'd want to do, yes. I.e., support translating CBVs to GLSL uniform arrays.
+/** + * Symbolic register indices for mapping uniform constants in legacy Direct3D + * bytecode to uniform buffers in the target environment. + * + * Members of this enumeration are used in + * \ref vkd3d_shader_resource_binding.register_index. + */ +enum vkd3d_shader_d3dbc_constant_register +{ + /** The float constant register set, c# in Direct3D assembly. */ + VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER = 0x0, + /** The integer constant register set, i# in Direct3D assembly. */ + VKD3D_SHADER_D3DBC_INT_CONSTANT_REGISTER = 0x1, + /** The boolean constant register set, b# in Direct3D assembly. */ + VKD3D_SHADER_D3DBC_BOOL_CONSTANT_REGISTER = 0x2, +};
Seems reasonable enough. We'll probably want a \since as well. For better or worse, the terminology we use in vkd3d-shader is "constant buffer view" instead of "uniform buffers".
+ /** + * Register index of the Direct3D resource. + * + * When mapping legacy Direct3D constants to constant buffers in the target + * environment, this parameter instead names the register set to map, and + * must be a member of enum vkd3d_shader_d3dbc_constant_register. + */
The clarification here seems helpful, but I'm not sure I agree with "instead". From the point of view of struct vkd3d_shader_resource_binding this is consistent with the existing usage of the structure; we map the different d3dbc constant files to CBVs, and then simply specify the register indices of those CBVs here.
+ * When scanning a legacy Direct3D shader, vkd3d-shader enumerates each + * constant register set used by the shader as a single constant buffer + * descriptor, as follows: + * - The \ref vkd3d_shader_descriptor_info.type field is set to + * VKD3D_SHADER_DESCRIPTOR_TYPE_CBV. + * - The \ref vkd3d_shader_descriptor_info.register_space field is set to zero. + * - The \ref vkd3d_shader_descriptor_info.register_index field is set to a + * member of enum vkd3d_shader_d3dbc_constant_register denoting which set + * is used. + * - The \ref vkd3d_shader_descriptor_info.resource_type field is set to + * VKD3D_SHADER_RESOURCE_BUFFER. + * - The \ref vkd3d_shader_descriptor_info.resource_data_type field is set to + * VKD3D_SHADER_RESOURCE_DATA_FLOAT. + * - The \ref vkd3d_shader_descriptor_info.flags field is set to zero. + * - The \ref vkd3d_shader_descriptor_info.count field is set to one. + * + * In summary, there may be up to three such descriptors, one for each register + * set used by the shader: float, integer, and boolean.
Is there a particular reason for going for VKD3D_SHADER_RESOURCE_DATA_FLOAT here? In principle "resource_data_type" is meaningless for CBVs, but we currently use VKD3D_SHADER_RESOURCE_DATA_UINT in vkd3d_shader_scan_constant_buffer_declaration(). One consequence is that we'd get different results if we ran scan_with_parser() after running instruction_array_normalise_flat_constants().
+static void record_constant_register(struct vkd3d_shader_sm1_parser *sm1, + enum vkd3d_shader_d3dbc_constant_register set, uint32_t index, bool from_def) { + struct vkd3d_shader_desc *desc = &sm1->p.shader_desc; + + desc->flat_constant_count[set].used = max(desc->flat_constant_count[set].used, index + 1); + if (from_def) + { + assert((index / 32) <= ARRAY_SIZE(sm1->constant_def_mask[set])); + bitmap_set(sm1->constant_def_mask[set], index); + } +}
I think that assert is right, but it's perhaps also obscure enough to warrant a comment. (The maximum d3dbc register index is 0x7ff; there are 4 float constant files, giving a maximum of 8192 float constants.)