Constant buffer reflection
This is an attempt to invent a vkd3d-shader interface, and begin to implement the relevant parts of ID3D12ShaderReflection in vkd3d-utils.
This series is missing most Doxygen documentation, mostly because I feel very uncertain about this interface and don't want to put in the significant effort to write documentation until I'm sure it's settled.
This series also has tests for bindings but not the implementation, mainly because I didn't want to bother splitting those tests out to a separate patch right now, and I see no harm in having them already there and marked todo...
Here is a long list of already open questions:
-
As always, should anything be named differently?
-
In particular, I've decided to give the variables names that make it clear this is d3d-specific code. I think trying to make this generic enough to work for other shader types is a fool's errand.
-
Should we even try to use this interface for sm1? It's mostly already a subset of dxbc; the only addition is the constant register set...
-
Should we bother with interfaces? These count as "constant buffers", they have a distinct type, and they have some extra data that we'd need to account for.
-
Should we bother with lib_* targets? This mostly means allowing for a single shader to hold multiple sets of reflection data. Note that this would also affect descriptor info and STAT info, although not signature info.
-
I've tried to pass through most data directly, partly out of a concern that that's what d3dcompiler probably does, and so trying to interpret it could break an extremely hypothetical and unlikely application. More saliently, converting to a more sensible representation just to convert back is extra work that I'm not really sure I see a point for.
But if we want to change the interface regardless, here are some ideas:
-
enum vkd3d_shader_d3d_buffer_type could just be more flags.
-
I think a buffer's size is redundant and can be calculated from its contained variables. Same for field offsets (unless packoffset affects this?)
-
"constant_register" could be flags too? But we already have a type for them, so I don't think that's better.
-
The kind/type interface is weird in several ways. Majority could be a type or var flag; objects could be classes...
-
-
Fields of struct vkd3d_shader_d3d_type could be 16-bit (like they are in the RDEF section). The main reason I didn't do this is because we can't force a 16-bit enum, although we could define the field as uint16_t. But we could also just define the other "count" fields as 16-bit.
-
I suspect I already know the answer to this one, but... If this is all going to be d3d specific anyway... do we really care about having this in vkd3d-shader?
Or, alternatively, we could provide an interface that's friendlier than COM, but still use the d3d struct types instead of copy-pasting and changing all the names to vkd3d-shader (which is a bit exhausting, honestly—not just because of rewriting but because of documentation. The latter is certainly a self-created problem, but so is the former.)
-
vkd3d_shader_d3d_field currently has a hole in it on LP64; is that a problem? (I think it's the only structure with a hole in it.)
-
As long as this is a d3d interface, should we go ahead and make it "scan_d3d_info" and add all the d3d-specific STAT block stuff?
One extra anticipatory note on how this differs from Wine's implementation: This implementation does not store types in an rbtree, nor deduplicate them. The main reason for this is that native doesn't deduplicate types (I have tests for this, later in my local branch) and it avoids what seems like a significant complication to the vkd3d-shader interface.