vkd3d-shader: sm1 constants.
Most of the interesting part is the API (first patch); the rest is implementation. The basic idea is that we have predefined fixed numbers for the float, integer, and boolean constant arrays, and treat each of the three like a constant buffer.
Implementation-wise, we lower sm1-style constant registers to sm4-style constant buffers and immediate constants, which are capable of expressing a strict superset of the same functionality.
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?
Relative addressing is not yet implemented. In theory it should be simple enough to either translate it directly, for external constants, or use sm4-style immediate constant buffers, for internal constants. There may be a snag if an application depends on relative addressing to cover a range of both internal and external constants; this surely would require manual assembly or an application bug, but we could implement it by copying to a temporary array using a private TEMP-like register type.
--
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
The vkd3d branch contains some extra commits necessary to compile basic shaders; I intend to submit these as soon as possible after the important API parts have been reviewed. I tested this patch series by building a mingw vkd3d tree with that branch, and running the shader runner through Wine, with a test that uses both internal and external constants:
make tests/shader_runner.exe && WINE_D3D_CONFIG=renderer=vulkan wine tests/shader_runner.exe ../vkd3d/tests/hlsl/writemask-assignop-0.shader_test
I actually originally wrote the API without a user in mind, and later hooked up the implementation in Wine, and was surprised to find how straightforward it ended up being, so I think that speaks quite strongly in favour of this API. Granted, I had already written "wined3d: Store push constants in wined3d_buffers in struct wined3d_state." by that point, but that was something I anticipated needing for Wine anyway, without thinking of vkd3d.
--
I actually originally did the implementation all in spirv.c, mostly because this was before we had infrastructure in place to do passes on the middle IR. I much prefer this version, it's quite centralized in one place and I think ends up being simpler than the spirv.c version anyway, but I can retrieve the spirv.c version if anyone wants to see it.
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).
The actual declaration of flat constants is kept in spirv. I suppose the alternative here is to instead declare buffers from the reflection information and simply ignore dcl_constantbuffer. I submitted the patch as-is since it seemed simple enough and I didn't want to block this work further on rewriting that part, but we may want to rewrite it in the future regardless.
After the torchlight red on sweaty faces
After the frosty silence in the gardens
After the agony in stony places
The shouting and the crying
Prison and palace and reverberation
Of thunder of spring over distant mountains