As per discussion in 606, plumbing constant buffer reflection through vkd3d-shader requires interface design and API documentation for an interface which is inherently quite specific to one format. Instead of wasting time on this interface, just implement RDEF parsing in vkd3d-utils itself. If we change our mind about this, we can always move the implementation to vkd3d-shader anyway.
This does not copy the existing implementation from Wine, because:
* Wine does not validate offsets; adding this changes the parsing code significantly;
* Wine incorrectly handles types, deduplicating them into an rbtree;
* Wine skips several fields which I have been able to find the purpose of.
The implementation is not that complex to begin with, so reimplementing it from scratch is not much work.
-- v4: tests: Add more tests for resource and struct RDEF contents. tests: Test constant and resource reflection via D3DReflect(). vkd3d-shader/tpf: Set the user-packed flag for sm5.0 resources as well. vkd3d-shader/tpf: Write the component count as the column count for structs. vkd3d-shader/tpf: Explicitly write the class and base type for non-numeric types. vkd3d-shader/tpf: Do not write structs with no numeric fields into the RDEF. vkd3d-shader/hlsl: Allocate register reservations for structs as well. vkd3d-shader/tpf: Do not write non-numeric struct fields into the RDEF.
From: Zebediah Figura zfigura@codeweavers.com
--- include/private/vkd3d_memory.h | 9 ++ libs/vkd3d-utils/reflection.c | 242 ++++++++++++++++++++++++++++++++- 2 files changed, 245 insertions(+), 6 deletions(-)
diff --git a/include/private/vkd3d_memory.h b/include/private/vkd3d_memory.h index 8a2edb100..d89f741b5 100644 --- a/include/private/vkd3d_memory.h +++ b/include/private/vkd3d_memory.h @@ -65,6 +65,15 @@ static inline char *vkd3d_strdup(const char *string) return ptr; }
+static inline void *vkd3d_memdup(const void *mem, size_t size) +{ + void *ptr; + + if ((ptr = vkd3d_malloc(size))) + memcpy(ptr, mem, size); + return ptr; +} + bool vkd3d_array_reserve(void **elements, size_t *capacity, size_t element_count, size_t element_size);
#endif /* __VKD3D_MEMORY_H */ diff --git a/libs/vkd3d-utils/reflection.c b/libs/vkd3d-utils/reflection.c index 2f604864b..94a4ae6d7 100644 --- a/libs/vkd3d-utils/reflection.c +++ b/libs/vkd3d-utils/reflection.c @@ -21,14 +21,79 @@ #include <vkd3d_d3dcommon.h> #include <vkd3d_d3d12shader.h>
+struct d3d12_buffer +{ + ID3D12ShaderReflectionConstantBuffer ID3D12ShaderReflectionConstantBuffer_iface; + D3D12_SHADER_BUFFER_DESC desc; +}; + struct d3d12_reflection { ID3D12ShaderReflection ID3D12ShaderReflection_iface; unsigned int refcount;
struct vkd3d_shader_scan_signature_info signature_info; + + D3D12_SHADER_DESC desc; + + struct d3d12_buffer *buffers; };
+static struct d3d12_buffer null_buffer; + +static struct d3d12_buffer *impl_from_ID3D12ShaderReflectionConstantBuffer(ID3D12ShaderReflectionConstantBuffer *iface) +{ + return CONTAINING_RECORD(iface, struct d3d12_buffer, ID3D12ShaderReflectionConstantBuffer_iface); +} + +static HRESULT STDMETHODCALLTYPE d3d12_buffer_GetDesc( + ID3D12ShaderReflectionConstantBuffer *iface, D3D12_SHADER_BUFFER_DESC *desc) +{ + struct d3d12_buffer *buffer = impl_from_ID3D12ShaderReflectionConstantBuffer(iface); + + TRACE("iface %p, desc %p.\n", iface, desc); + + if (buffer == &null_buffer) + { + WARN("Null constant buffer, returning E_FAIL.\n"); + return E_FAIL; + } + + if (!desc) + { + WARN("NULL pointer, returning E_FAIL.\n"); + return E_FAIL; + } + + *desc = buffer->desc; + return S_OK; +} + +static ID3D12ShaderReflectionVariable * STDMETHODCALLTYPE d3d12_buffer_GetVariableByIndex( + ID3D12ShaderReflectionConstantBuffer *iface, UINT index) +{ + FIXME("iface %p, index %u, stub!\n", iface, index); + + return NULL; +} + +static ID3D12ShaderReflectionVariable * STDMETHODCALLTYPE d3d12_buffer_GetVariableByName( + ID3D12ShaderReflectionConstantBuffer *iface, const char *name) +{ + FIXME("iface %p, name %s, stub!\n", iface, debugstr_a(name)); + + return NULL; +} + +static const struct ID3D12ShaderReflectionConstantBufferVtbl d3d12_buffer_vtbl = +{ + d3d12_buffer_GetDesc, + d3d12_buffer_GetVariableByIndex, + d3d12_buffer_GetVariableByName, +}; + +static struct d3d12_buffer null_buffer = {{&d3d12_buffer_vtbl}}; + static struct d3d12_reflection *impl_from_ID3D12ShaderReflection(ID3D12ShaderReflection *iface) { return CONTAINING_RECORD(iface, struct d3d12_reflection, ID3D12ShaderReflection_iface); @@ -72,6 +137,10 @@ static ULONG STDMETHODCALLTYPE d3d12_reflection_Release(ID3D12ShaderReflection *
if (!refcount) { + for (UINT i = 0; i < reflection->desc.ConstantBuffers; ++i) + vkd3d_free((void *)reflection->buffers[i].desc.Name); + vkd3d_free(reflection->buffers); + vkd3d_shader_free_scan_signature_info(&reflection->signature_info); free(reflection); } @@ -87,9 +156,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_reflection_GetDesc(ID3D12ShaderReflection
FIXME("iface %p, desc %p partial stub!\n", iface, desc);
- desc->InputParameters = reflection->signature_info.input.element_count; - desc->OutputParameters = reflection->signature_info.output.element_count; - desc->PatchConstantParameters = reflection->signature_info.patch_constant.element_count; + *desc = reflection->desc;
return S_OK; } @@ -97,9 +164,17 @@ static HRESULT STDMETHODCALLTYPE d3d12_reflection_GetDesc(ID3D12ShaderReflection static struct ID3D12ShaderReflectionConstantBuffer * STDMETHODCALLTYPE d3d12_reflection_GetConstantBufferByIndex( ID3D12ShaderReflection *iface, UINT index) { - FIXME("iface %p, index %u stub!\n", iface, index); + struct d3d12_reflection *reflection = impl_from_ID3D12ShaderReflection(iface);
- return NULL; + TRACE("iface %p, index %u.\n", iface, index); + + if (index > reflection->desc.ConstantBuffers) + { + WARN("Invalid index %u.\n", index); + return &null_buffer.ID3D12ShaderReflectionConstantBuffer_iface; + } + + return &reflection->buffers[index].ID3D12ShaderReflectionConstantBuffer_iface; }
static struct ID3D12ShaderReflectionConstantBuffer * STDMETHODCALLTYPE d3d12_reflection_GetConstantBufferByName( @@ -287,9 +362,128 @@ static const struct ID3D12ShaderReflectionVtbl d3d12_reflection_vtbl = d3d12_reflection_GetRequiresFlags, };
+static bool require_space(size_t offset, size_t count, size_t size, size_t data_size) +{ + return !count || (data_size - offset) / count >= size; +} + +/* Return a pointer to data in a code blob, with bounds checking. */ +static const void *get_data_ptr(const struct vkd3d_shader_code *code, + uint32_t offset, uint32_t count, uint32_t size) +{ + if (!require_space(offset, count, size, code->size)) + { + ERR("Offset %#x and size %#x exceeds section size %#zx.\n", offset, size, code->size); + return NULL; + } + + return (const char *)code->code + offset; +} + +static HRESULT get_string(const struct vkd3d_shader_code *code, uint32_t offset, char **ret) +{ + const char *str; + char *end; + + if (offset >= code->size) + { + ERR("Offset %#x exceeds size %#zx.\n", offset, code->size); + return E_INVALIDARG; + } + + str = (const char *)code->code + offset; + if (!(end = memchr(str, 0, code->size - offset))) + { + ERR("String at %#x is not properly zero-terminated.\n", offset); + return E_INVALIDARG; + } + + if (!(*ret = vkd3d_memdup(str, end + 1 - str))) + return E_OUTOFMEMORY; + return S_OK; +} + +struct rdef_header +{ + uint32_t buffer_count; + uint32_t buffers_offset; + uint32_t binding_count; + uint32_t bindings_offset; + uint8_t minor_version; + uint8_t major_version; + uint16_t type; + uint32_t compile_flags; + uint32_t creator_offset; +}; + +struct rdef_buffer +{ + uint32_t name_offset; + uint32_t var_count; + uint32_t vars_offset; + uint32_t size; + uint32_t flags; + uint32_t type; +}; + +static HRESULT d3d12_buffer_init(struct d3d12_buffer *buffer, const struct rdef_buffer *rdef_buffer, + const struct vkd3d_shader_code *section) +{ + HRESULT hr; + char *name; + + if ((FAILED(hr = get_string(section, rdef_buffer->name_offset, &name)))) + return hr; + + buffer->ID3D12ShaderReflectionConstantBuffer_iface.lpVtbl = &d3d12_buffer_vtbl; + + buffer->desc.Type = rdef_buffer->type; + buffer->desc.Variables = rdef_buffer->var_count; + buffer->desc.Size = rdef_buffer->size; + buffer->desc.uFlags = rdef_buffer->flags; + buffer->desc.Name = name; + + return S_OK; +} + +static HRESULT parse_rdef(struct d3d12_reflection *reflection, const struct vkd3d_shader_code *section) +{ + const struct rdef_header *header; + HRESULT hr; + + if (!(header = get_data_ptr(section, 0, 1, sizeof(*header)))) + return E_INVALIDARG; + + reflection->desc.ConstantBuffers = header->buffer_count; + + if (header->buffer_count) + { + const struct rdef_buffer *rdef_buffers; + + if (!(rdef_buffers = get_data_ptr(section, header->buffers_offset, + header->buffer_count, sizeof(*rdef_buffers)))) + return E_INVALIDARG; + + if (!(reflection->buffers = vkd3d_calloc(header->buffer_count, sizeof(*reflection->buffers)))) + return E_OUTOFMEMORY; + + for (uint32_t i = 0; i < header->buffer_count; ++i) + { + if ((hr = d3d12_buffer_init(&reflection->buffers[i], &rdef_buffers[i], section))) + return hr; + } + } + + return S_OK; +} + static HRESULT d3d12_reflection_init(struct d3d12_reflection *reflection, const void *data, size_t data_size) { struct vkd3d_shader_compile_info compile_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO}; + struct vkd3d_shader_dxbc_desc dxbc_desc; + bool found_rdef = false; + enum vkd3d_result ret; + HRESULT hr;
reflection->ID3D12ShaderReflection_iface.lpVtbl = &d3d12_reflection_vtbl; reflection->refcount = 1; @@ -301,7 +495,43 @@ static HRESULT d3d12_reflection_init(struct d3d12_reflection *reflection, const compile_info.next = &reflection->signature_info; reflection->signature_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_SIGNATURE_INFO;
- return hresult_from_vkd3d_result(vkd3d_shader_scan(&compile_info, NULL)); + if (FAILED(hr = hresult_from_vkd3d_result(vkd3d_shader_scan(&compile_info, NULL)))) + return hr; + + if ((ret = vkd3d_shader_parse_dxbc(&compile_info.source, 0, &dxbc_desc, NULL))) + { + vkd3d_shader_free_scan_signature_info(&reflection->signature_info); + return hresult_from_vkd3d_result(ret); + } + + for (unsigned int i = 0; i < dxbc_desc.section_count; ++i) + { + const struct vkd3d_shader_dxbc_section_desc *section = &dxbc_desc.sections[i]; + + if (section->tag == TAG_RDEF) + { + if (found_rdef) + { + FIXME("Multiple RDEF chunks.\n"); + continue; + } + + if (FAILED(hr = parse_rdef(reflection, §ion->data))) + { + vkd3d_shader_free_scan_signature_info(&reflection->signature_info); + vkd3d_shader_free_dxbc(&dxbc_desc); + return hr; + } + } + } + + reflection->desc.InputParameters = reflection->signature_info.input.element_count; + reflection->desc.OutputParameters = reflection->signature_info.output.element_count; + reflection->desc.PatchConstantParameters = reflection->signature_info.patch_constant.element_count; + + vkd3d_shader_free_dxbc(&dxbc_desc); + + return S_OK; }
HRESULT WINAPI D3DReflect(const void *data, SIZE_T data_size, REFIID iid, void **reflection)
From: Zebediah Figura zfigura@codeweavers.com
--- include/private/vkd3d_common.h | 2 ++ libs/vkd3d-utils/reflection.c | 47 ++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+)
diff --git a/include/private/vkd3d_common.h b/include/private/vkd3d_common.h index 01e219b30..7712553a8 100644 --- a/include/private/vkd3d_common.h +++ b/include/private/vkd3d_common.h @@ -71,6 +71,8 @@ #define TAG_XNAP VKD3D_MAKE_TAG('X', 'N', 'A', 'P') #define TAG_XNAS VKD3D_MAKE_TAG('X', 'N', 'A', 'S')
+#define TAG_RD11_REVERSE 0x25441313 + static inline uint64_t align(uint64_t addr, size_t alignment) { return (addr + (alignment - 1)) & ~(alignment - 1); diff --git a/libs/vkd3d-utils/reflection.c b/libs/vkd3d-utils/reflection.c index 94a4ae6d7..2827182bd 100644 --- a/libs/vkd3d-utils/reflection.c +++ b/libs/vkd3d-utils/reflection.c @@ -416,6 +416,19 @@ struct rdef_header uint32_t creator_offset; };
+struct rdef_rd11 +{ + uint32_t magic; + uint32_t header_size; + uint32_t buffer_size; + uint32_t binding_size; + uint32_t variable_size; + uint32_t type_size; + uint32_t field_size; + /* Always zero. Possibly either padding or a null terminator? */ + uint32_t zero; +}; + struct rdef_buffer { uint32_t name_offset; @@ -449,11 +462,45 @@ static HRESULT d3d12_buffer_init(struct d3d12_buffer *buffer, const struct rdef_ static HRESULT parse_rdef(struct d3d12_reflection *reflection, const struct vkd3d_shader_code *section) { const struct rdef_header *header; + const struct rdef_rd11 *rd11; HRESULT hr;
if (!(header = get_data_ptr(section, 0, 1, sizeof(*header)))) return E_INVALIDARG;
+ if (header->major_version >= 5) + { + if (!(rd11 = get_data_ptr(section, sizeof(*header), 1, sizeof(*rd11)))) + return E_INVALIDARG; + + /* RD11 is emitted for 5.0, the reversed version for 5.1 and 6.0. + * This corresponds to a difference in the binding_size member, but + * it's not clear why the magic also changed there. */ + if (rd11->magic != TAG_RD11 && rd11->magic != TAG_RD11_REVERSE) + { + FIXME("Unknown tag %#x.\n", rd11->magic); + return E_INVALIDARG; + } + + if (rd11->header_size != sizeof(struct rdef_header) + sizeof(struct rdef_rd11)) + { + FIXME("Unexpected header size %#x.\n", rd11->header_size); + return E_INVALIDARG; + } + + if (rd11->buffer_size != sizeof(struct rdef_buffer)) + { + FIXME("Unexpected buffer size %#x.\n", rd11->buffer_size); + return E_INVALIDARG; + } + + if (rd11->zero) + { + FIXME("Unexpected field %#x.\n", rd11->zero); + return E_INVALIDARG; + } + } + reflection->desc.ConstantBuffers = header->buffer_count;
if (header->buffer_count)
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-utils/reflection.c | 179 +++++++++++++++++++++++++++++++++- 1 file changed, 174 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d-utils/reflection.c b/libs/vkd3d-utils/reflection.c index 2827182bd..ab7197b10 100644 --- a/libs/vkd3d-utils/reflection.c +++ b/libs/vkd3d-utils/reflection.c @@ -21,10 +21,19 @@ #include <vkd3d_d3dcommon.h> #include <vkd3d_d3d12shader.h>
+struct d3d12_variable +{ + ID3D12ShaderReflectionVariable ID3D12ShaderReflectionVariable_iface; + D3D12_SHADER_VARIABLE_DESC desc; + struct d3d12_buffer *buffer; +}; + struct d3d12_buffer { ID3D12ShaderReflectionConstantBuffer ID3D12ShaderReflectionConstantBuffer_iface; D3D12_SHADER_BUFFER_DESC desc; + + struct d3d12_variable *variables; };
struct d3d12_reflection @@ -40,6 +49,71 @@ struct d3d12_reflection };
static struct d3d12_buffer null_buffer; +static struct d3d12_variable null_variable; + +static struct d3d12_variable *impl_from_ID3D12ShaderReflectionVariable(ID3D12ShaderReflectionVariable *iface) +{ + return CONTAINING_RECORD(iface, struct d3d12_variable, ID3D12ShaderReflectionVariable_iface); +} + +static HRESULT STDMETHODCALLTYPE d3d12_variable_GetDesc( + ID3D12ShaderReflectionVariable *iface, D3D12_SHADER_VARIABLE_DESC *desc) +{ + struct d3d12_variable *variable = impl_from_ID3D12ShaderReflectionVariable(iface); + + TRACE("iface %p, desc %p.\n", iface, desc); + + if (variable == &null_variable) + { + WARN("Null variable, returning E_FAIL.\n"); + return E_FAIL; + } + + if (!desc) + { + WARN("NULL pointer, returning E_FAIL.\n"); + return E_FAIL; + } + + *desc = variable->desc; + return S_OK; +} + +static ID3D12ShaderReflectionType * STDMETHODCALLTYPE d3d12_variable_GetType( + ID3D12ShaderReflectionVariable *iface) +{ + FIXME("iface %p, stub!\n", iface); + + return NULL; +} + +static ID3D12ShaderReflectionConstantBuffer * STDMETHODCALLTYPE d3d12_variable_GetBuffer( + ID3D12ShaderReflectionVariable *iface) +{ + struct d3d12_variable *variable = impl_from_ID3D12ShaderReflectionVariable(iface); + + TRACE("iface %p.\n", iface); + + return &variable->buffer->ID3D12ShaderReflectionConstantBuffer_iface; +} + +static UINT STDMETHODCALLTYPE d3d12_variable_GetInterfaceSlot( + ID3D12ShaderReflectionVariable *iface, UINT index) +{ + FIXME("iface %p, index %u, stub!\n", iface, index); + + return 0; +} + +static const struct ID3D12ShaderReflectionVariableVtbl d3d12_variable_vtbl = +{ + d3d12_variable_GetDesc, + d3d12_variable_GetType, + d3d12_variable_GetBuffer, + d3d12_variable_GetInterfaceSlot, +}; + +static struct d3d12_variable null_variable = {{&d3d12_variable_vtbl}};
static struct d3d12_buffer *impl_from_ID3D12ShaderReflectionConstantBuffer(ID3D12ShaderReflectionConstantBuffer *iface) { @@ -72,9 +146,17 @@ static HRESULT STDMETHODCALLTYPE d3d12_buffer_GetDesc( static ID3D12ShaderReflectionVariable * STDMETHODCALLTYPE d3d12_buffer_GetVariableByIndex( ID3D12ShaderReflectionConstantBuffer *iface, UINT index) { - FIXME("iface %p, index %u, stub!\n", iface, index); + struct d3d12_buffer *buffer = impl_from_ID3D12ShaderReflectionConstantBuffer(iface);
- return NULL; + TRACE("iface %p, index %u.\n", iface, index); + + if (index > buffer->desc.Variables) + { + WARN("Invalid index %u.\n", index); + return &null_variable.ID3D12ShaderReflectionVariable_iface; + } + + return &buffer->variables[index].ID3D12ShaderReflectionVariable_iface; }
static ID3D12ShaderReflectionVariable * STDMETHODCALLTYPE d3d12_buffer_GetVariableByName( @@ -138,7 +220,19 @@ static ULONG STDMETHODCALLTYPE d3d12_reflection_Release(ID3D12ShaderReflection * if (!refcount) { for (UINT i = 0; i < reflection->desc.ConstantBuffers; ++i) - vkd3d_free((void *)reflection->buffers[i].desc.Name); + { + struct d3d12_buffer *buffer = &reflection->buffers[i]; + + for (UINT j = 0; j < buffer->desc.Variables; ++j) + { + struct d3d12_variable *variable = &buffer->variables[j]; + + vkd3d_free((void *)variable->desc.DefaultValue); + vkd3d_free((void *)variable->desc.Name); + } + vkd3d_free(buffer->variables); + vkd3d_free((void *)buffer->desc.Name); + } vkd3d_free(reflection->buffers);
vkd3d_shader_free_scan_signature_info(&reflection->signature_info); @@ -439,8 +533,56 @@ struct rdef_buffer uint32_t type; };
+struct rdef_variable +{ + uint32_t name_offset; + uint32_t offset; + uint32_t size; + uint32_t flags; + uint32_t type_offset; + uint32_t default_value_offset; + uint32_t resource_binding; + uint32_t resource_count; + uint32_t sampler_binding; + uint32_t sampler_count; +}; + +static HRESULT d3d12_variable_init(struct d3d12_variable *variable, + const struct rdef_variable *rdef_variable, const struct vkd3d_shader_code *section) +{ + HRESULT hr; + char *name; + + if (FAILED(hr = get_string(section, rdef_variable->name_offset, &name))) + return hr; + + variable->ID3D12ShaderReflectionVariable_iface.lpVtbl = &d3d12_variable_vtbl; + + variable->desc.Name = name; + variable->desc.StartOffset = rdef_variable->offset; + variable->desc.Size = rdef_variable->size; + variable->desc.uFlags = rdef_variable->flags; + variable->desc.StartTexture = rdef_variable->resource_binding; + variable->desc.TextureSize = rdef_variable->resource_count; + variable->desc.StartSampler = rdef_variable->sampler_binding; + variable->desc.SamplerSize = rdef_variable->sampler_count; + + if (rdef_variable->default_value_offset) + { + const void *default_value; + + if (!(default_value = get_data_ptr(section, rdef_variable->default_value_offset, 1, rdef_variable->size))) + return E_INVALIDARG; + + if (!(variable->desc.DefaultValue = vkd3d_memdup(default_value, rdef_variable->size))) + return E_OUTOFMEMORY; + } + + return S_OK; +} + static HRESULT d3d12_buffer_init(struct d3d12_buffer *buffer, const struct rdef_buffer *rdef_buffer, - const struct vkd3d_shader_code *section) + const struct vkd3d_shader_code *section, uint32_t variable_size) { HRESULT hr; char *name; @@ -456,11 +598,31 @@ static HRESULT d3d12_buffer_init(struct d3d12_buffer *buffer, const struct rdef_ buffer->desc.uFlags = rdef_buffer->flags; buffer->desc.Name = name;
+ if (!(buffer->variables = vkd3d_calloc(rdef_buffer->var_count, sizeof(*buffer->variables)))) + return E_OUTOFMEMORY; + + for (uint32_t i = 0; i < rdef_buffer->var_count; ++i) + { + struct rdef_variable normalized_variable = {0}; + const struct rdef_variable *rdef_variable; + + if (!(rdef_variable = get_data_ptr(section, rdef_buffer->vars_offset + (i * variable_size), 1, variable_size))) + return E_INVALIDARG; + + normalized_variable.resource_binding = ~0u; + normalized_variable.sampler_binding = ~0u; + memcpy(&normalized_variable, rdef_variable, variable_size); + + if ((hr = d3d12_variable_init(&buffer->variables[i], &normalized_variable, section))) + return hr; + } + return S_OK; }
static HRESULT parse_rdef(struct d3d12_reflection *reflection, const struct vkd3d_shader_code *section) { + uint32_t variable_size = offsetof(struct rdef_variable, resource_binding); const struct rdef_header *header; const struct rdef_rd11 *rd11; HRESULT hr; @@ -494,6 +656,13 @@ static HRESULT parse_rdef(struct d3d12_reflection *reflection, const struct vkd3 return E_INVALIDARG; }
+ if (rd11->variable_size != sizeof(struct rdef_variable)) + { + FIXME("Unexpected variable size %#x.\n", rd11->variable_size); + return E_INVALIDARG; + } + variable_size = rd11->variable_size; + if (rd11->zero) { FIXME("Unexpected field %#x.\n", rd11->zero); @@ -516,7 +685,7 @@ static HRESULT parse_rdef(struct d3d12_reflection *reflection, const struct vkd3
for (uint32_t i = 0; i < header->buffer_count; ++i) { - if ((hr = d3d12_buffer_init(&reflection->buffers[i], &rdef_buffers[i], section))) + if ((hr = d3d12_buffer_init(&reflection->buffers[i], &rdef_buffers[i], section, variable_size))) return hr; } }
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-utils/reflection.c | 208 ++++++++++++++++++++++++++++++++-- 1 file changed, 200 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d-utils/reflection.c b/libs/vkd3d-utils/reflection.c index ab7197b10..1c6e7d2f9 100644 --- a/libs/vkd3d-utils/reflection.c +++ b/libs/vkd3d-utils/reflection.c @@ -21,11 +21,19 @@ #include <vkd3d_d3dcommon.h> #include <vkd3d_d3d12shader.h>
+struct d3d12_type +{ + ID3D12ShaderReflectionType ID3D12ShaderReflectionType_iface; + D3D12_SHADER_TYPE_DESC desc; +}; + struct d3d12_variable { ID3D12ShaderReflectionVariable ID3D12ShaderReflectionVariable_iface; D3D12_SHADER_VARIABLE_DESC desc; struct d3d12_buffer *buffer; + + struct d3d12_type type; };
struct d3d12_buffer @@ -50,6 +58,129 @@ struct d3d12_reflection
static struct d3d12_buffer null_buffer; static struct d3d12_variable null_variable; +static struct d3d12_type null_type; + +static struct d3d12_type *impl_from_ID3D12ShaderReflectionType(ID3D12ShaderReflectionType *iface) +{ + return CONTAINING_RECORD(iface, struct d3d12_type, ID3D12ShaderReflectionType_iface); +} + +static HRESULT STDMETHODCALLTYPE d3d12_type_GetDesc( + ID3D12ShaderReflectionType *iface, D3D12_SHADER_TYPE_DESC *desc) +{ + struct d3d12_type *type = impl_from_ID3D12ShaderReflectionType(iface); + + TRACE("iface %p, desc %p.\n", iface, desc); + + if (type == &null_type) + { + WARN("Null type, returning E_FAIL.\n"); + return E_FAIL; + } + + if (!desc) + { + WARN("NULL pointer, returning E_FAIL.\n"); + return E_FAIL; + } + + *desc = type->desc; + return S_OK; +} + +static ID3D12ShaderReflectionType * STDMETHODCALLTYPE d3d12_type_GetMemberTypeByIndex( + ID3D12ShaderReflectionType *iface, UINT index) +{ + FIXME("iface %p, index %u, stub!\n", iface, index); + + return NULL; +} + +static ID3D12ShaderReflectionType * STDMETHODCALLTYPE d3d12_type_GetMemberTypeByName( + ID3D12ShaderReflectionType *iface, const char *name) +{ + FIXME("iface %p, name %s, stub!\n", iface, debugstr_a(name)); + + return NULL; +} + +static const char * STDMETHODCALLTYPE d3d12_type_GetMemberTypeName( + ID3D12ShaderReflectionType *iface, UINT index) +{ + FIXME("iface %p, index %u, stub!\n", iface, index); + + return NULL; +} + +static HRESULT STDMETHODCALLTYPE d3d12_type_IsEqual( + ID3D12ShaderReflectionType *iface, ID3D12ShaderReflectionType *other) +{ + FIXME("iface %p, other %p, stub!\n", iface, other); + return E_NOTIMPL; +} + +static ID3D12ShaderReflectionType * STDMETHODCALLTYPE d3d12_type_GetSubType( + ID3D12ShaderReflectionType *iface) +{ + FIXME("iface %p stub!\n", iface); + + return NULL; +} + +static ID3D12ShaderReflectionType * STDMETHODCALLTYPE d3d12_type_GetBaseClass( + ID3D12ShaderReflectionType *iface) +{ + FIXME("iface %p stub!\n", iface); + + return NULL; +} + +static UINT STDMETHODCALLTYPE d3d12_type_GetNumInterfaces( + ID3D12ShaderReflectionType *iface) +{ + FIXME("iface %p stub!\n", iface); + + return 0; +} + +static ID3D12ShaderReflectionType * STDMETHODCALLTYPE d3d12_type_GetInterfaceByIndex( + ID3D12ShaderReflectionType *iface, UINT index) +{ + FIXME("iface %p, index %u stub!\n", iface, index); + + return NULL; +} + +static HRESULT STDMETHODCALLTYPE d3d12_type_IsOfType( + ID3D12ShaderReflectionType *iface, ID3D12ShaderReflectionType *type) +{ + FIXME("iface %p, type %p stub!\n", iface, type); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE d3d12_type_ImplementsInterface( + ID3D12ShaderReflectionType *iface, ID3D12ShaderReflectionType *base) +{ + FIXME("iface %p, base %p stub!\n", iface, base); + + return E_NOTIMPL; +} + +static const struct ID3D12ShaderReflectionTypeVtbl d3d12_type_vtbl = +{ + d3d12_type_GetDesc, + d3d12_type_GetMemberTypeByIndex, + d3d12_type_GetMemberTypeByName, + d3d12_type_GetMemberTypeName, + d3d12_type_IsEqual, + d3d12_type_GetSubType, + d3d12_type_GetBaseClass, + d3d12_type_GetNumInterfaces, + d3d12_type_GetInterfaceByIndex, + d3d12_type_IsOfType, + d3d12_type_ImplementsInterface, +};
static struct d3d12_variable *impl_from_ID3D12ShaderReflectionVariable(ID3D12ShaderReflectionVariable *iface) { @@ -82,9 +213,14 @@ static HRESULT STDMETHODCALLTYPE d3d12_variable_GetDesc( static ID3D12ShaderReflectionType * STDMETHODCALLTYPE d3d12_variable_GetType( ID3D12ShaderReflectionVariable *iface) { - FIXME("iface %p, stub!\n", iface); + struct d3d12_variable *variable = impl_from_ID3D12ShaderReflectionVariable(iface);
- return NULL; + TRACE("iface %p.\n", iface); + + if (variable == &null_variable) + return &null_type.ID3D12ShaderReflectionType_iface; + + return &variable->type.ID3D12ShaderReflectionType_iface; }
static ID3D12ShaderReflectionConstantBuffer * STDMETHODCALLTYPE d3d12_variable_GetBuffer( @@ -210,6 +346,11 @@ static ULONG STDMETHODCALLTYPE d3d12_reflection_AddRef(ID3D12ShaderReflection *i return refcount; }
+static void free_type(struct d3d12_type *type) +{ + vkd3d_free((void *)type->desc.Name); +} + static ULONG STDMETHODCALLTYPE d3d12_reflection_Release(ID3D12ShaderReflection *iface) { struct d3d12_reflection *reflection = impl_from_ID3D12ShaderReflection(iface); @@ -227,6 +368,7 @@ static ULONG STDMETHODCALLTYPE d3d12_reflection_Release(ID3D12ShaderReflection * { struct d3d12_variable *variable = &buffer->variables[j];
+ free_type(&variable->type); vkd3d_free((void *)variable->desc.DefaultValue); vkd3d_free((void *)variable->desc.Name); } @@ -547,8 +689,50 @@ struct rdef_variable uint32_t sampler_count; };
-static HRESULT d3d12_variable_init(struct d3d12_variable *variable, - const struct rdef_variable *rdef_variable, const struct vkd3d_shader_code *section) +struct rdef_type +{ + uint16_t class; + uint16_t base_type; + uint16_t row_count; + uint16_t column_count; + uint16_t element_count; + uint16_t field_count; + uint32_t fields_offset; + /* Probably related to interfaces. */ + uint32_t unknown[4]; + uint32_t name_offset; +}; + +static HRESULT d3d12_type_init(struct d3d12_type *type, uint32_t type_offset, + uint32_t type_size, const struct vkd3d_shader_code *section) +{ + struct rdef_type normalized_type = {0}; + const struct rdef_type *rdef_type; + char *name = NULL; + HRESULT hr; + + if (!(rdef_type = get_data_ptr(section, type_offset, 1, type_size))) + return E_INVALIDARG; + memcpy(&normalized_type, rdef_type, type_size); + + if (normalized_type.name_offset && FAILED(hr = get_string(section, normalized_type.name_offset, &name))) + return hr; + + type->ID3D12ShaderReflectionType_iface.lpVtbl = &d3d12_type_vtbl; + + type->desc.Class = normalized_type.class; + type->desc.Type = normalized_type.base_type; + type->desc.Rows = normalized_type.row_count; + type->desc.Columns = normalized_type.column_count; + type->desc.Elements = normalized_type.element_count; + type->desc.Members = normalized_type.field_count; + type->desc.Name = name; + + return S_OK; +} + +static HRESULT d3d12_variable_init(struct d3d12_variable *variable, const struct rdef_variable *rdef_variable, + const struct vkd3d_shader_code *section, uint32_t type_size) { HRESULT hr; char *name; @@ -578,11 +762,11 @@ static HRESULT d3d12_variable_init(struct d3d12_variable *variable, return E_OUTOFMEMORY; }
- return S_OK; + return d3d12_type_init(&variable->type, rdef_variable->type_offset, type_size, section); }
static HRESULT d3d12_buffer_init(struct d3d12_buffer *buffer, const struct rdef_buffer *rdef_buffer, - const struct vkd3d_shader_code *section, uint32_t variable_size) + const struct vkd3d_shader_code *section, uint32_t variable_size, uint32_t type_size) { HRESULT hr; char *name; @@ -613,7 +797,7 @@ static HRESULT d3d12_buffer_init(struct d3d12_buffer *buffer, const struct rdef_ normalized_variable.sampler_binding = ~0u; memcpy(&normalized_variable, rdef_variable, variable_size);
- if ((hr = d3d12_variable_init(&buffer->variables[i], &normalized_variable, section))) + if ((hr = d3d12_variable_init(&buffer->variables[i], &normalized_variable, section, type_size))) return hr; }
@@ -623,6 +807,7 @@ static HRESULT d3d12_buffer_init(struct d3d12_buffer *buffer, const struct rdef_ static HRESULT parse_rdef(struct d3d12_reflection *reflection, const struct vkd3d_shader_code *section) { uint32_t variable_size = offsetof(struct rdef_variable, resource_binding); + uint32_t type_size = offsetof(struct rdef_type, unknown); const struct rdef_header *header; const struct rdef_rd11 *rd11; HRESULT hr; @@ -663,6 +848,13 @@ static HRESULT parse_rdef(struct d3d12_reflection *reflection, const struct vkd3 } variable_size = rd11->variable_size;
+ if (rd11->type_size != sizeof(struct rdef_type)) + { + FIXME("Unexpected type size %#x.\n", rd11->type_size); + return E_INVALIDARG; + } + type_size = rd11->type_size; + if (rd11->zero) { FIXME("Unexpected field %#x.\n", rd11->zero); @@ -685,7 +877,7 @@ static HRESULT parse_rdef(struct d3d12_reflection *reflection, const struct vkd3
for (uint32_t i = 0; i < header->buffer_count; ++i) { - if ((hr = d3d12_buffer_init(&reflection->buffers[i], &rdef_buffers[i], section, variable_size))) + if ((hr = d3d12_buffer_init(&reflection->buffers[i], &rdef_buffers[i], section, variable_size, type_size))) return hr; } }
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-utils/reflection.c | 57 ++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d-utils/reflection.c b/libs/vkd3d-utils/reflection.c index 1c6e7d2f9..fe95c89c4 100644 --- a/libs/vkd3d-utils/reflection.c +++ b/libs/vkd3d-utils/reflection.c @@ -25,6 +25,13 @@ struct d3d12_type { ID3D12ShaderReflectionType ID3D12ShaderReflectionType_iface; D3D12_SHADER_TYPE_DESC desc; + + struct d3d12_field *fields; +}; + +struct d3d12_field +{ + struct d3d12_type type; };
struct d3d12_variable @@ -91,9 +98,17 @@ static HRESULT STDMETHODCALLTYPE d3d12_type_GetDesc( static ID3D12ShaderReflectionType * STDMETHODCALLTYPE d3d12_type_GetMemberTypeByIndex( ID3D12ShaderReflectionType *iface, UINT index) { - FIXME("iface %p, index %u, stub!\n", iface, index); + struct d3d12_type *type = impl_from_ID3D12ShaderReflectionType(iface);
- return NULL; + TRACE("iface %p, index %u.\n", iface, index); + + if (index > type->desc.Members) + { + WARN("Invalid index %u.\n", index); + return &null_type.ID3D12ShaderReflectionType_iface; + } + + return &type->fields[index].type.ID3D12ShaderReflectionType_iface; }
static ID3D12ShaderReflectionType * STDMETHODCALLTYPE d3d12_type_GetMemberTypeByName( @@ -348,6 +363,9 @@ static ULONG STDMETHODCALLTYPE d3d12_reflection_AddRef(ID3D12ShaderReflection *i
static void free_type(struct d3d12_type *type) { + for (UINT i = 0; i < type->desc.Members; ++i) + free_type(&type->fields[i].type); + vkd3d_free(type->fields); vkd3d_free((void *)type->desc.Name); }
@@ -703,8 +721,15 @@ struct rdef_type uint32_t name_offset; };
-static HRESULT d3d12_type_init(struct d3d12_type *type, uint32_t type_offset, - uint32_t type_size, const struct vkd3d_shader_code *section) +struct rdef_field +{ + uint32_t name_offset; + uint32_t type_offset; + uint32_t offset; +}; + +static HRESULT d3d12_type_init(struct d3d12_type *type, uint32_t type_offset, uint32_t type_size, + const struct vkd3d_shader_code *section, uint32_t field_offset) { struct rdef_type normalized_type = {0}; const struct rdef_type *rdef_type; @@ -726,8 +751,30 @@ static HRESULT d3d12_type_init(struct d3d12_type *type, uint32_t type_offset, type->desc.Columns = normalized_type.column_count; type->desc.Elements = normalized_type.element_count; type->desc.Members = normalized_type.field_count; + type->desc.Offset = field_offset; type->desc.Name = name;
+ if (normalized_type.field_count) + { + const struct rdef_field *rdef_fields; + + if (!(rdef_fields = get_data_ptr(section, normalized_type.fields_offset, + normalized_type.field_count, sizeof(*rdef_fields)))) + return E_INVALIDARG; + + if (!(type->fields = vkd3d_calloc(normalized_type.field_count, sizeof(*type->fields)))) + return false; + + for (uint32_t i = 0; i < normalized_type.field_count; ++i) + { + const struct rdef_field *rdef_field = &rdef_fields[i]; + + if ((hr = d3d12_type_init(&type->fields[i].type, rdef_field->type_offset, + type_size, section, rdef_field->offset))) + return hr; + } + } + return S_OK; }
@@ -762,7 +809,7 @@ static HRESULT d3d12_variable_init(struct d3d12_variable *variable, const struct return E_OUTOFMEMORY; }
- return d3d12_type_init(&variable->type, rdef_variable->type_offset, type_size, section); + return d3d12_type_init(&variable->type, rdef_variable->type_offset, type_size, section, 0); }
static HRESULT d3d12_buffer_init(struct d3d12_buffer *buffer, const struct rdef_buffer *rdef_buffer,
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/tpf.c | 78 +++++++---------------------------------- 1 file changed, 12 insertions(+), 66 deletions(-)
diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index adfddd320..d4b27be7b 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -2981,18 +2981,16 @@ static D3D_SHADER_VARIABLE_CLASS sm4_class(const struct hlsl_type *type) return D3D_SVC_MATRIX_COLUMNS; else return D3D_SVC_MATRIX_ROWS; - case HLSL_CLASS_OBJECT: - return D3D_SVC_OBJECT; case HLSL_CLASS_SCALAR: return D3D_SVC_SCALAR; case HLSL_CLASS_STRUCT: return D3D_SVC_STRUCT; case HLSL_CLASS_VECTOR: return D3D_SVC_VECTOR; - default: - ERR("Invalid class %#x.\n", type->class); - vkd3d_unreachable(); + case HLSL_CLASS_OBJECT: + break; } + vkd3d_unreachable(); }
static D3D_SHADER_VARIABLE_TYPE sm4_base_type(const struct hlsl_type *type) @@ -3008,68 +3006,10 @@ static D3D_SHADER_VARIABLE_TYPE sm4_base_type(const struct hlsl_type *type) return D3D_SVT_FLOAT; case HLSL_TYPE_INT: return D3D_SVT_INT; - case HLSL_TYPE_PIXELSHADER: - return D3D_SVT_PIXELSHADER; - case HLSL_TYPE_SAMPLER: - switch (type->sampler_dim) - { - case HLSL_SAMPLER_DIM_1D: - return D3D_SVT_SAMPLER1D; - case HLSL_SAMPLER_DIM_2D: - return D3D_SVT_SAMPLER2D; - case HLSL_SAMPLER_DIM_3D: - return D3D_SVT_SAMPLER3D; - case HLSL_SAMPLER_DIM_CUBE: - return D3D_SVT_SAMPLERCUBE; - case HLSL_SAMPLER_DIM_GENERIC: - return D3D_SVT_SAMPLER; - default: - vkd3d_unreachable(); - } - break; - case HLSL_TYPE_STRING: - return D3D_SVT_STRING; - case HLSL_TYPE_TEXTURE: - switch (type->sampler_dim) - { - case HLSL_SAMPLER_DIM_1D: - return D3D_SVT_TEXTURE1D; - case HLSL_SAMPLER_DIM_2D: - return D3D_SVT_TEXTURE2D; - case HLSL_SAMPLER_DIM_2DMS: - return D3D_SVT_TEXTURE2DMS; - case HLSL_SAMPLER_DIM_3D: - return D3D_SVT_TEXTURE3D; - case HLSL_SAMPLER_DIM_CUBE: - return D3D_SVT_TEXTURECUBE; - case HLSL_SAMPLER_DIM_GENERIC: - return D3D_SVT_TEXTURE; - default: - vkd3d_unreachable(); - } - break; case HLSL_TYPE_UINT: return D3D_SVT_UINT; - case HLSL_TYPE_VERTEXSHADER: - return D3D_SVT_VERTEXSHADER; case HLSL_TYPE_VOID: return D3D_SVT_VOID; - case HLSL_TYPE_UAV: - switch (type->sampler_dim) - { - case HLSL_SAMPLER_DIM_1D: - return D3D_SVT_RWTEXTURE1D; - case HLSL_SAMPLER_DIM_2D: - return D3D_SVT_RWTEXTURE2D; - case HLSL_SAMPLER_DIM_3D: - return D3D_SVT_RWTEXTURE3D; - case HLSL_SAMPLER_DIM_1DARRAY: - return D3D_SVT_RWTEXTURE1DARRAY; - case HLSL_SAMPLER_DIM_2DARRAY: - return D3D_SVT_RWTEXTURE2DARRAY; - default: - vkd3d_unreachable(); - } default: vkd3d_unreachable(); } @@ -3095,22 +3035,28 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
if (array_type->class == HLSL_CLASS_STRUCT) { - field_count = array_type->e.record.field_count;
- for (i = 0; i < field_count; ++i) + for (i = 0; i < array_type->e.record.field_count; ++i) { struct hlsl_struct_field *field = &array_type->e.record.fields[i];
+ if (!field->type->reg_size[HLSL_REGSET_NUMERIC]) + continue; + field->name_bytecode_offset = put_string(buffer, field->name); write_sm4_type(ctx, buffer, field->type); + ++field_count; }
fields_offset = bytecode_align(buffer);
- for (i = 0; i < field_count; ++i) + for (i = 0; i < array_type->e.record.field_count; ++i) { struct hlsl_struct_field *field = &array_type->e.record.fields[i];
+ if (!field->type->reg_size[HLSL_REGSET_NUMERIC]) + continue; + put_u32(buffer, field->name_bytecode_offset); put_u32(buffer, field->type->bytecode_offset); put_u32(buffer, field->reg_offset[HLSL_REGSET_NUMERIC]);
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/hlsl_codegen.c | 3 --- tests/hlsl/register-reservations-resources.shader_test | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 6ad60e4c6..fcd6c7994 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -3424,9 +3424,6 @@ static void allocate_register_reservations(struct hlsl_ctx *ctx) { unsigned int r;
- if (!hlsl_type_is_resource(var->data_type)) - continue; - if (var->reg_reservation.reg_type) { for (r = 0; r <= HLSL_REGSET_LAST_OBJECT; ++r) diff --git a/tests/hlsl/register-reservations-resources.shader_test b/tests/hlsl/register-reservations-resources.shader_test index 22a441026..9fba329f2 100644 --- a/tests/hlsl/register-reservations-resources.shader_test +++ b/tests/hlsl/register-reservations-resources.shader_test @@ -198,7 +198,7 @@ filter linear linear linear address clamp clamp clamp
% If a struct spans many object register sets and one is reserved, all other used object register sets must be. -[pixel shader fail(sm<6) todo] +[pixel shader fail(sm<6)] struct { Texture2D tex; @@ -242,4 +242,4 @@ float4 main() : sv_target
[test] draw quad -todo(sm<6) probe all rgba (1.0, 1.0, 1.0, 99.0) +probe all rgba (1.0, 1.0, 1.0, 99.0)
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/tpf.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index d4b27be7b..50cf626a8 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -3453,8 +3453,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { - if (var->is_uniform && var->buffer == cbuffer - && var->data_type->class != HLSL_CLASS_OBJECT) + if (var->is_uniform && var->buffer == cbuffer && var->data_type->reg_size[HLSL_REGSET_NUMERIC]) ++var_count; }
@@ -3488,8 +3487,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { - if (var->is_uniform && var->buffer == cbuffer - && var->data_type->class != HLSL_CLASS_OBJECT) + if (var->is_uniform && var->buffer == cbuffer && var->data_type->reg_size[HLSL_REGSET_NUMERIC]) { uint32_t flags = 0;
@@ -3516,8 +3514,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) j = 0; LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { - if (var->is_uniform && var->buffer == cbuffer - && var->data_type->class != HLSL_CLASS_OBJECT) + if (var->is_uniform && var->buffer == cbuffer && var->data_type->reg_size[HLSL_REGSET_NUMERIC]) { const unsigned int var_size = (profile->major_version >= 5 ? 10 : 6); size_t var_offset = vars_start + j * var_size * sizeof(uint32_t);
From: Zebediah Figura zfigura@codeweavers.com
Avoid relying on that information being stored in the hlsl_type. --- libs/vkd3d-shader/tpf.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 50cf626a8..bc9349a54 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -2973,8 +2973,6 @@ static D3D_SHADER_VARIABLE_CLASS sm4_class(const struct hlsl_type *type) { switch (type->class) { - case HLSL_CLASS_ARRAY: - return sm4_class(type->e.array.type); case HLSL_CLASS_MATRIX: assert(type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK); if (type->modifiers & HLSL_MODIFIER_COLUMN_MAJOR) @@ -2983,10 +2981,11 @@ static D3D_SHADER_VARIABLE_CLASS sm4_class(const struct hlsl_type *type) return D3D_SVC_MATRIX_ROWS; case HLSL_CLASS_SCALAR: return D3D_SVC_SCALAR; - case HLSL_CLASS_STRUCT: - return D3D_SVC_STRUCT; case HLSL_CLASS_VECTOR: return D3D_SVC_VECTOR; + + case HLSL_CLASS_ARRAY: + case HLSL_CLASS_STRUCT: case HLSL_CLASS_OBJECT: break; } @@ -3008,8 +3007,6 @@ static D3D_SHADER_VARIABLE_TYPE sm4_base_type(const struct hlsl_type *type) return D3D_SVT_INT; case HLSL_TYPE_UINT: return D3D_SVT_UINT; - case HLSL_TYPE_VOID: - return D3D_SVT_VOID; default: vkd3d_unreachable(); } @@ -3061,9 +3058,14 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b put_u32(buffer, field->type->bytecode_offset); put_u32(buffer, field->reg_offset[HLSL_REGSET_NUMERIC]); } + + type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(D3D_SVC_STRUCT, D3D_SVT_VOID)); + } + else + { + type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(sm4_class(array_type), sm4_base_type(array_type))); }
- type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(sm4_class(type), sm4_base_type(type))); put_u32(buffer, vkd3d_make_u32(type->dimy, type->dimx)); put_u32(buffer, vkd3d_make_u32(array_size, field_count)); put_u32(buffer, fields_offset);
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/tpf.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index bc9349a54..93e2ab9fe 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -3017,8 +3017,8 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b const struct hlsl_type *array_type = hlsl_get_multiarray_element_type(type); const char *name = array_type->name ? array_type->name : "<unnamed>"; const struct hlsl_profile_info *profile = ctx->profile; - unsigned int field_count = 0, array_size = 0; - size_t fields_offset = 0, name_offset = 0; + unsigned int array_size = 0; + size_t name_offset = 0; size_t i;
if (type->bytecode_offset) @@ -3032,6 +3032,8 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
if (array_type->class == HLSL_CLASS_STRUCT) { + unsigned int field_count = 0; + size_t fields_offset = 0;
for (i = 0; i < array_type->e.record.field_count; ++i) { @@ -3058,18 +3060,20 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b put_u32(buffer, field->type->bytecode_offset); put_u32(buffer, field->reg_offset[HLSL_REGSET_NUMERIC]); } - type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(D3D_SVC_STRUCT, D3D_SVT_VOID)); + put_u32(buffer, vkd3d_make_u32(1, hlsl_type_component_count(array_type))); + put_u32(buffer, vkd3d_make_u32(array_size, field_count)); + put_u32(buffer, fields_offset); } else { + assert(array_type->class <= HLSL_CLASS_LAST_NUMERIC); type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(sm4_class(array_type), sm4_base_type(array_type))); + put_u32(buffer, vkd3d_make_u32(array_type->dimy, array_type->dimx)); + put_u32(buffer, vkd3d_make_u32(array_size, 0)); + put_u32(buffer, 1); }
- put_u32(buffer, vkd3d_make_u32(type->dimy, type->dimx)); - put_u32(buffer, vkd3d_make_u32(array_size, field_count)); - put_u32(buffer, fields_offset); - if (profile->major_version >= 5) { put_u32(buffer, 0); /* FIXME: unknown */
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/tpf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 93e2ab9fe..4dde929d4 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -3264,7 +3264,7 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un
extern_resources[*count].name = name; extern_resources[*count].data_type = component_type; - extern_resources[*count].is_user_packed = false; + extern_resources[*count].is_user_packed = !!var->reg_reservation.reg_type;
extern_resources[*count].regset = regset; extern_resources[*count].id = var->regs[regset].id + regset_offset;
From: Zebediah Figura zfigura@codeweavers.com
Ported from Wine. --- tests/hlsl_d3d12.c | 290 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+)
diff --git a/tests/hlsl_d3d12.c b/tests/hlsl_d3d12.c index 28007e3aa..dc347e5da 100644 --- a/tests/hlsl_d3d12.c +++ b/tests/hlsl_d3d12.c @@ -1317,6 +1317,295 @@ static void test_get_blob_part(void) ok(!refcount, "Got refcount %u.\n", refcount); }
+static void check_type_desc_(int line, const D3D12_SHADER_TYPE_DESC *type, const D3D12_SHADER_TYPE_DESC *expect) +{ + ok_(line)(type->Class == expect->Class, "Got class %#x.\n", type->Class); + ok_(line)(type->Type == expect->Type, "Got type %#x.\n", type->Type); + ok_(line)(type->Rows == expect->Rows, "Got %u rows.\n", type->Rows); + ok_(line)(type->Columns == expect->Columns, "Got %u columns.\n", type->Columns); + ok_(line)(type->Elements == expect->Elements, "Got %u elements.\n", type->Elements); + ok_(line)(type->Members == expect->Members, "Got %u members.\n", type->Members); + ok_(line)(type->Offset == expect->Offset, "Got %u members.\n", type->Members); + ok_(line)(!strcmp(type->Name, expect->Name), "Got name "%s".\n", type->Name); +} +#define check_type_desc(a, b) check_type_desc_(__LINE__, a, b) + +static void test_reflection(void) +{ + unsigned int refcount; + HRESULT hr; + + static const char vs_source[] = + "typedef uint uint_t;\n" + "float m;\n" + "\n" + "cbuffer b1\n" + "{\n" + " float a;\n" + " float2 b;\n" + " float4 c;\n" + " float d;\n" + " struct\n" + " {\n" + " float4 a;\n" + " float b;\n" + " float c;\n" + " } s;\n" + /* In direct contradiction to the documentation, this does not align. */ + " bool g;\n" + " float h[2];\n" + " int i;\n" + " uint_t j;\n" + " float3x1 k;\n" + " row_major float3x1 l;\n" + "#pragma pack_matrix(row_major)\n" + " float3x1 o;\n" + " float4 p;\n" + " float q;\n" + " struct r_name {float a;} r;\n" + " column_major float3x1 t;\n" + "};\n" + "\n" + "cbuffer b5 : register(b5)\n" + "{\n" + " float4 u;\n" + "}\n" + "\n" + "float4 main(uniform float4 n) : SV_POSITION\n" + "{\n" + " return o._31 + m + n + u;\n" + "}"; + + struct shader_variable + { + D3D12_SHADER_VARIABLE_DESC var_desc; + D3D12_SHADER_TYPE_DESC type_desc; + const D3D12_SHADER_TYPE_DESC *field_types; + }; + + struct shader_buffer + { + D3D12_SHADER_BUFFER_DESC desc; + const struct shader_variable *vars; + }; + + static const D3D12_SHADER_TYPE_DESC s_field_types[] = + { + {D3D_SVC_VECTOR, D3D_SVT_FLOAT, 1, 4, 0, 0, 0, "float4"}, + {D3D_SVC_SCALAR, D3D_SVT_FLOAT, 1, 1, 0, 0, 16, "float"}, + {D3D_SVC_SCALAR, D3D_SVT_FLOAT, 1, 1, 0, 0, 20, "float"}, + }; + + static const D3D12_SHADER_TYPE_DESC r_field_types[] = + { + {D3D_SVC_SCALAR, D3D_SVT_FLOAT, 1, 1, 0, 0, 0, "float"}, + }; + + static const struct shader_variable globals_vars = + {{"m", 0, 4, D3D_SVF_USED, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_SCALAR, D3D_SVT_FLOAT, 1, 1, 0, 0, 0, "float"}}; + static const struct shader_variable params_vars = + {{"n", 0, 16, D3D_SVF_USED, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_VECTOR, D3D_SVT_FLOAT, 1, 4, 0, 0, 0, "float4"}}; + static const struct shader_variable buffer_vars[] = + { + {{"a", 0, 4, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_SCALAR, D3D_SVT_FLOAT, 1, 1, 0, 0, 0, "float"}}, + {{"b", 4, 8, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_VECTOR, D3D_SVT_FLOAT, 1, 2, 0, 0, 0, "float2"}}, + {{"c", 16, 16, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_VECTOR, D3D_SVT_FLOAT, 1, 4, 0, 0, 0, "float4"}}, + {{"d", 32, 4, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_SCALAR, D3D_SVT_FLOAT, 1, 1, 0, 0, 0, "float"}}, + {{"s", 48, 24, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_STRUCT, D3D_SVT_VOID, 1, 6, 0, ARRAY_SIZE(s_field_types), 0, "<unnamed>"}, s_field_types}, + {{"g", 72, 4, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_SCALAR, D3D_SVT_BOOL, 1, 1, 0, 0, 0, "bool"}}, + {{"h", 80, 20, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_SCALAR, D3D_SVT_FLOAT, 1, 1, 2, 0, 0, "float"}}, + {{"i", 100, 4, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_SCALAR, D3D_SVT_INT, 1, 1, 0, 0, 0, "int"}}, + {{"j", 104, 4, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_SCALAR, D3D_SVT_UINT, 1, 1, 0, 0, 0, "uint_t"}}, + {{"k", 112, 12, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_MATRIX_COLUMNS, D3D_SVT_FLOAT, 3, 1, 0, 0, 0, "float3x1"}}, + {{"l", 128, 36, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_MATRIX_ROWS, D3D_SVT_FLOAT, 3, 1, 0, 0, 0, "float3x1"}}, + {{"o", 176, 36, D3D_SVF_USED, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_MATRIX_ROWS, D3D_SVT_FLOAT, 3, 1, 0, 0, 0, "float3x1"}}, + {{"p", 224, 16, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_VECTOR, D3D_SVT_FLOAT, 1, 4, 0, 0, 0, "float4"}}, + {{"q", 240, 4, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_SCALAR, D3D_SVT_FLOAT, 1, 1, 0, 0, 0, "float"}}, + {{"r", 256, 4, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_STRUCT, D3D_SVT_VOID, 1, 1, 0, ARRAY_SIZE(r_field_types), 0, "r_name"}, r_field_types}, + {{"t", 260, 12, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_MATRIX_COLUMNS, D3D_SVT_FLOAT, 3, 1, 0, 0, 0, "float3x1"}}, + }; + static const struct shader_variable b5_vars = + {{"u", 0, 16, D3D_SVF_USED, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_VECTOR, D3D_SVT_FLOAT, 1, 4, 0, 0, 0, "float4"}}; + + static const struct shader_buffer vs_buffers[] = + { + {{"$Globals", D3D_CT_CBUFFER, 1, 16}, &globals_vars}, + {{"$Params", D3D_CT_CBUFFER, 1, 16}, ¶ms_vars}, + {{"b1", D3D_CT_CBUFFER, ARRAY_SIZE(buffer_vars), 272}, buffer_vars}, + {{"b5", D3D_CT_CBUFFER, 1, 16}, &b5_vars}, + }; + + static const D3D12_SHADER_INPUT_BIND_DESC vs_bindings[] = + { + {"$Globals", D3D_SIT_CBUFFER, 0, 1}, + {"$Params", D3D_SIT_CBUFFER, 1, 1}, + {"b1", D3D_SIT_CBUFFER, 2, 1}, + {"b5", D3D_SIT_CBUFFER, 5, 1, D3D_SIF_USERPACKED}, + }; + + static const char ps_source[] = + "texture2D a;\n" + "sampler c {};\n" + "SamplerState d {};\n" + "sampler e\n" + "{\n" + " Texture = a;\n" + " foo = bar + 2;\n" + "};\n" + "SamplerState f\n" + "{\n" + " Texture = a;\n" + " foo = bar + 2;\n" + "};\n" + "sampler2D g;\n" + "sampler b : register(s5);\n" + "float4 main(float2 pos : texcoord) : SV_TARGET\n" + "{\n" + " return a.Sample(b, pos) + a.Sample(c, pos) + a.Sample(d, pos) + tex2D(f, pos) + tex2D(e, pos)" + " + tex2D(g, pos);\n" + "}"; + + static const D3D12_SHADER_INPUT_BIND_DESC ps_bindings[] = + { + {"c", D3D_SIT_SAMPLER, 0, 1}, + {"d", D3D_SIT_SAMPLER, 1, 1}, + {"e", D3D_SIT_SAMPLER, 2, 1}, + {"f", D3D_SIT_SAMPLER, 3, 1}, + {"g", D3D_SIT_SAMPLER, 4, 1}, + {"b", D3D_SIT_SAMPLER, 5, 1, D3D_SIF_USERPACKED}, + {"f", D3D_SIT_TEXTURE, 0, 1, D3D_SIF_TEXTURE_COMPONENTS, D3D_RETURN_TYPE_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, ~0u}, + {"e", D3D_SIT_TEXTURE, 1, 1, D3D_SIF_TEXTURE_COMPONENTS, D3D_RETURN_TYPE_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, ~0u}, + {"g", D3D_SIT_TEXTURE, 2, 1, D3D_SIF_TEXTURE_COMPONENTS, D3D_RETURN_TYPE_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, ~0u}, + {"a", D3D_SIT_TEXTURE, 3, 1, D3D_SIF_TEXTURE_COMPONENTS, D3D_RETURN_TYPE_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, ~0u}, + }; + + static const struct + { + const char *source; + const char *profile; + const D3D12_SHADER_INPUT_BIND_DESC *bindings; + size_t binding_count; + const struct shader_buffer *buffers; + size_t buffer_count; + } + tests[] = + { + {vs_source, "vs_5_0", vs_bindings, ARRAY_SIZE(vs_bindings), vs_buffers, ARRAY_SIZE(vs_buffers)}, + {ps_source, "ps_5_0", ps_bindings, ARRAY_SIZE(ps_bindings)}, + }; + + for (unsigned int t = 0; t < ARRAY_SIZE(tests); ++t) + { + ID3D10Blob *code = compile_shader_flags(tests[t].source, + tests[t].profile, D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY); + ID3D12ShaderReflection *reflection; + D3D12_SHADER_DESC shader_desc; + + hr = D3DReflect(ID3D10Blob_GetBufferPointer(code), ID3D10Blob_GetBufferSize(code), + &IID_ID3D12ShaderReflection, (void **)&reflection); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + + hr = reflection->lpVtbl->GetDesc(reflection, &shader_desc); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + ok(shader_desc.ConstantBuffers == tests[t].buffer_count, "Got %u buffers.\n", shader_desc.ConstantBuffers); + todo ok(shader_desc.BoundResources == tests[t].binding_count, "Got %u resources.\n", shader_desc.BoundResources); + + for (unsigned int i = 0; i < shader_desc.ConstantBuffers; ++i) + { + const struct shader_buffer *expect_buffer = &tests[t].buffers[i]; + ID3D12ShaderReflectionConstantBuffer *cbuffer; + D3D12_SHADER_BUFFER_DESC buffer_desc; + + vkd3d_test_push_context("Buffer %u", i); + + cbuffer = reflection->lpVtbl->GetConstantBufferByIndex(reflection, i); + hr = cbuffer->lpVtbl->GetDesc(cbuffer, &buffer_desc); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + ok(!strcmp(buffer_desc.Name, expect_buffer->desc.Name), "Got name "%s".\n", buffer_desc.Name); + ok(buffer_desc.Type == expect_buffer->desc.Type, "Got type %#x.\n", buffer_desc.Type); + ok(buffer_desc.Variables == expect_buffer->desc.Variables, "Got %u variables.\n", buffer_desc.Variables); + ok(buffer_desc.Size == expect_buffer->desc.Size, "Got size %u.\n", buffer_desc.Size); + ok(buffer_desc.uFlags == expect_buffer->desc.uFlags, "Got flags %#x.\n", buffer_desc.uFlags); + + for (unsigned int j = 0; j < buffer_desc.Variables; ++j) + { + const struct shader_variable *expect = &expect_buffer->vars[j]; + ID3D12ShaderReflectionType *type, *field; + ID3D12ShaderReflectionVariable *var; + D3D12_SHADER_VARIABLE_DESC var_desc; + D3D12_SHADER_TYPE_DESC type_desc; + + vkd3d_test_push_context("Variable %u", j); + + var = cbuffer->lpVtbl->GetVariableByIndex(cbuffer, j); + hr = var->lpVtbl->GetDesc(var, &var_desc); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + ok(!strcmp(var_desc.Name, expect->var_desc.Name), "Got name "%s".\n", var_desc.Name); + ok(var_desc.StartOffset == expect->var_desc.StartOffset, "Got offset %u.\n", var_desc.StartOffset); + ok(var_desc.Size == expect->var_desc.Size, "Got size %u.\n", var_desc.Size); + ok(var_desc.uFlags == expect->var_desc.uFlags, "Got flags %#x.\n", var_desc.uFlags); + ok(!var_desc.DefaultValue, "Got default value %p.\n", var_desc.DefaultValue); + todo ok(var_desc.StartTexture == expect->var_desc.StartTexture, + "Got texture offset %u.\n", var_desc.StartTexture); + ok(var_desc.TextureSize == expect->var_desc.TextureSize, + "Got texture size %u.\n", var_desc.TextureSize); + todo ok(var_desc.StartSampler == expect->var_desc.StartSampler, + "Got sampler offset %u.\n", var_desc.StartSampler); + ok(var_desc.SamplerSize == expect->var_desc.SamplerSize, + "Got sampler size %u.\n", var_desc.SamplerSize); + + type = var->lpVtbl->GetType(var); + hr = type->lpVtbl->GetDesc(type, &type_desc); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + check_type_desc(&type_desc, &expect->type_desc); + + for (unsigned int k = 0; k < type_desc.Members; ++k) + { + vkd3d_test_push_context("Field %u", k); + + field = type->lpVtbl->GetMemberTypeByIndex(type, k); + hr = field->lpVtbl->GetDesc(field, &type_desc); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + check_type_desc(&type_desc, &expect->field_types[k]); + + vkd3d_test_pop_context(); + } + + vkd3d_test_pop_context(); + } + + vkd3d_test_pop_context(); + } + + for (unsigned int i = 0; i < shader_desc.BoundResources; ++i) + { + const D3D12_SHADER_INPUT_BIND_DESC *expect = &tests[t].bindings[i]; + D3D12_SHADER_INPUT_BIND_DESC desc; + + vkd3d_test_push_context("Binding %u", i); + + hr = reflection->lpVtbl->GetResourceBindingDesc(reflection, i, &desc); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + + ok(!strcmp(desc.Name, expect->Name), "Got name "%s".\n", desc.Name); + ok(desc.Type == expect->Type, "Got type %#x.\n", desc.Type); + ok(desc.BindPoint == expect->BindPoint, "Got bind point %u.\n", desc.BindPoint); + ok(desc.BindCount == expect->BindCount, "Got bind count %u.\n", desc.BindCount); + todo_if ((expect->uFlags & D3D_SIF_USERPACKED) && expect->Type != D3D_SIT_CBUFFER) + ok(desc.uFlags == expect->uFlags, "Got flags %#x.\n", desc.uFlags); + ok(desc.ReturnType == expect->ReturnType, "Got return type %#x.\n", desc.ReturnType); + ok(desc.Dimension == expect->Dimension, "Got dimension %#x.\n", desc.Dimension); + ok(desc.NumSamples == expect->NumSamples, "Got multisample count %u.\n", desc.NumSamples); + + vkd3d_test_pop_context(); + } + + ID3D10Blob_Release(code); + refcount = reflection->lpVtbl->Release(reflection); + ok(!refcount, "Got unexpected refcount %u.\n", refcount); + } +} + static void check_signature_element_(int line, const D3D12_SIGNATURE_PARAMETER_DESC *desc, const D3D12_SIGNATURE_PARAMETER_DESC *expect) { @@ -1614,6 +1903,7 @@ START_TEST(hlsl_d3d12) run_test(test_thread_id); run_test(test_create_blob); run_test(test_get_blob_part); + run_test(test_reflection); run_test(test_signature_reflection); run_test(test_disassemble_shader); }
From: Zebediah Figura zfigura@codeweavers.com
--- tests/hlsl_d3d12.c | 71 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 61 insertions(+), 10 deletions(-)
diff --git a/tests/hlsl_d3d12.c b/tests/hlsl_d3d12.c index dc347e5da..76dc80638 100644 --- a/tests/hlsl_d3d12.c +++ b/tests/hlsl_d3d12.c @@ -1362,7 +1362,7 @@ static void test_reflection(void) " float3x1 o;\n" " float4 p;\n" " float q;\n" - " struct r_name {float a;} r;\n" + " struct r_name {float a; float4 b;} r;\n" " column_major float3x1 t;\n" "};\n" "\n" @@ -1399,6 +1399,7 @@ static void test_reflection(void) static const D3D12_SHADER_TYPE_DESC r_field_types[] = { {D3D_SVC_SCALAR, D3D_SVT_FLOAT, 1, 1, 0, 0, 0, "float"}, + {D3D_SVC_SCALAR, D3D_SVT_FLOAT, 1, 4, 0, 0, 0, "float4"}, };
static const struct shader_variable globals_vars = @@ -1421,8 +1422,8 @@ static void test_reflection(void) {{"o", 176, 36, D3D_SVF_USED, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_MATRIX_ROWS, D3D_SVT_FLOAT, 3, 1, 0, 0, 0, "float3x1"}}, {{"p", 224, 16, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_VECTOR, D3D_SVT_FLOAT, 1, 4, 0, 0, 0, "float4"}}, {{"q", 240, 4, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_SCALAR, D3D_SVT_FLOAT, 1, 1, 0, 0, 0, "float"}}, - {{"r", 256, 4, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_STRUCT, D3D_SVT_VOID, 1, 1, 0, ARRAY_SIZE(r_field_types), 0, "r_name"}, r_field_types}, - {{"t", 260, 12, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_MATRIX_COLUMNS, D3D_SVT_FLOAT, 3, 1, 0, 0, 0, "float3x1"}}, + {{"r", 256, 32, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_STRUCT, D3D_SVT_VOID, 1, 5, 0, ARRAY_SIZE(r_field_types), 0, "r_name"}, r_field_types}, + {{"t", 288, 12, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_MATRIX_COLUMNS, D3D_SVT_FLOAT, 3, 1, 0, 0, 0, "float3x1"}}, }; static const struct shader_variable b5_vars = {{"u", 0, 16, D3D_SVF_USED, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_VECTOR, D3D_SVT_FLOAT, 1, 4, 0, 0, 0, "float4"}}; @@ -1431,7 +1432,7 @@ static void test_reflection(void) { {{"$Globals", D3D_CT_CBUFFER, 1, 16}, &globals_vars}, {{"$Params", D3D_CT_CBUFFER, 1, 16}, ¶ms_vars}, - {{"b1", D3D_CT_CBUFFER, ARRAY_SIZE(buffer_vars), 272}, buffer_vars}, + {{"b1", D3D_CT_CBUFFER, ARRAY_SIZE(buffer_vars), 304}, buffer_vars}, {{"b5", D3D_CT_CBUFFER, 1, 16}, &b5_vars}, };
@@ -1458,11 +1459,35 @@ static void test_reflection(void) " foo = bar + 2;\n" "};\n" "sampler2D g;\n" - "sampler b : register(s5);\n" + "sampler b : register(s7);\n" + "struct\n" + "{\n" + " float a;\n" + " Texture1D<int2> b;\n" + " float c;\n" + " Texture2D d;\n" + "} h : register(t7);\n" + "struct\n" + "{\n" + " float a;\n" + " Texture2D b;\n" + " SamplerState c;\n" + "} i;\n" + "struct\n" + "{\n" + " Texture2D b;\n" + " SamplerState c;\n" + "} j;\n" + "struct\n" + "{\n" + " Texture2D a;\n" + " Texture1DArray<float> b;\n" + " struct { SamplerState a; } c;\n" + "} k;\n" "float4 main(float2 pos : texcoord) : SV_TARGET\n" "{\n" " return a.Sample(b, pos) + a.Sample(c, pos) + a.Sample(d, pos) + tex2D(f, pos) + tex2D(e, pos)" - " + tex2D(g, pos);\n" + " + tex2D(g, pos) + h.b.Load(h.c).x + k.b.Sample(k.c.a, pos);\n" "}";
static const D3D12_SHADER_INPUT_BIND_DESC ps_bindings[] = @@ -1472,11 +1497,36 @@ static void test_reflection(void) {"e", D3D_SIT_SAMPLER, 2, 1}, {"f", D3D_SIT_SAMPLER, 3, 1}, {"g", D3D_SIT_SAMPLER, 4, 1}, - {"b", D3D_SIT_SAMPLER, 5, 1, D3D_SIF_USERPACKED}, + {"k.c.a", D3D_SIT_SAMPLER, 5, 1}, + {"b", D3D_SIT_SAMPLER, 7, 1, D3D_SIF_USERPACKED}, {"f", D3D_SIT_TEXTURE, 0, 1, D3D_SIF_TEXTURE_COMPONENTS, D3D_RETURN_TYPE_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, ~0u}, {"e", D3D_SIT_TEXTURE, 1, 1, D3D_SIF_TEXTURE_COMPONENTS, D3D_RETURN_TYPE_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, ~0u}, {"g", D3D_SIT_TEXTURE, 2, 1, D3D_SIF_TEXTURE_COMPONENTS, D3D_RETURN_TYPE_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, ~0u}, {"a", D3D_SIT_TEXTURE, 3, 1, D3D_SIF_TEXTURE_COMPONENTS, D3D_RETURN_TYPE_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, ~0u}, + {"k.b", D3D_SIT_TEXTURE, 5, 1, 0, D3D_RETURN_TYPE_FLOAT, D3D_SRV_DIMENSION_TEXTURE1DARRAY, ~0u}, + {"h.b", D3D_SIT_TEXTURE, 7, 1, D3D_SIF_USERPACKED | D3D_SIF_TEXTURE_COMPONENT_0, D3D_RETURN_TYPE_SINT, D3D_SRV_DIMENSION_TEXTURE1D, ~0u}, + {"$Globals", D3D_SIT_CBUFFER, 0, 1}, + }; + + static const D3D12_SHADER_TYPE_DESC ps_h_field_types[] = + { + {D3D_SVC_SCALAR, D3D_SVT_FLOAT, 1, 1, 0, 0, 0, "float"}, + {D3D_SVC_SCALAR, D3D_SVT_FLOAT, 1, 1, 0, 0, 0, "float"}, + }; + + static const D3D12_SHADER_TYPE_DESC ps_i_field_types[] = + { + {D3D_SVC_SCALAR, D3D_SVT_FLOAT, 1, 1, 0, 0, 0, "float"}, + }; + + static const struct shader_variable ps_globals_vars[] = + { + {{"h", 0, 8, D3D_SVF_USED, NULL, 7, 1, ~0u, 0}, {D3D_SVC_STRUCT, D3D_SVT_VOID, 1, 4, 0, ARRAY_SIZE(ps_h_field_types), 0, "<unnamed>"}, ps_h_field_types}, + {{"i", 16, 4, 0, NULL, ~0u, 0, ~0u, 0}, {D3D_SVC_STRUCT, D3D_SVT_VOID, 1, 3, 0, ARRAY_SIZE(ps_i_field_types), 0, "<unnamed>"}, ps_i_field_types}, + }; + static const struct shader_buffer ps_buffers[] = + { + {{"$Globals", D3D_CT_CBUFFER, ARRAY_SIZE(ps_globals_vars), 32}, ps_globals_vars}, };
static const struct @@ -1491,7 +1541,7 @@ static void test_reflection(void) tests[] = { {vs_source, "vs_5_0", vs_bindings, ARRAY_SIZE(vs_bindings), vs_buffers, ARRAY_SIZE(vs_buffers)}, - {ps_source, "ps_5_0", ps_bindings, ARRAY_SIZE(ps_bindings)}, + {ps_source, "ps_5_0", ps_bindings, ARRAY_SIZE(ps_bindings), ps_buffers, ARRAY_SIZE(ps_buffers)}, };
for (unsigned int t = 0; t < ARRAY_SIZE(tests); ++t) @@ -1547,8 +1597,9 @@ static void test_reflection(void) ok(!var_desc.DefaultValue, "Got default value %p.\n", var_desc.DefaultValue); todo ok(var_desc.StartTexture == expect->var_desc.StartTexture, "Got texture offset %u.\n", var_desc.StartTexture); - ok(var_desc.TextureSize == expect->var_desc.TextureSize, - "Got texture size %u.\n", var_desc.TextureSize); + todo_if (expect->var_desc.TextureSize) + ok(var_desc.TextureSize == expect->var_desc.TextureSize, + "Got texture size %u.\n", var_desc.TextureSize); todo ok(var_desc.StartSampler == expect->var_desc.StartSampler, "Got sampler offset %u.\n", var_desc.StartSampler); ok(var_desc.SamplerSize == expect->var_desc.SamplerSize,
v4: Fix test failures and crosstest build warnings, hopefully.
Giovanni Mascellani (@giomasce) commented about libs/vkd3d-utils/reflection.c:
- if (FAILED(hr = hresult_from_vkd3d_result(vkd3d_shader_scan(&compile_info, NULL))))
return hr;
- if ((ret = vkd3d_shader_parse_dxbc(&compile_info.source, 0, &dxbc_desc, NULL)))
- {
vkd3d_shader_free_scan_signature_info(&reflection->signature_info);
return hresult_from_vkd3d_result(ret);
- }
- for (unsigned int i = 0; i < dxbc_desc.section_count; ++i)
- {
const struct vkd3d_shader_dxbc_section_desc *section = &dxbc_desc.sections[i];
if (section->tag == TAG_RDEF)
{
if (found_rdef)
This can never happen, `found_rdef` is never set to `true`.
Giovanni Mascellani (@giomasce) commented about libs/vkd3d-shader/tpf.c:
return D3D_SVC_MATRIX_COLUMNS; else return D3D_SVC_MATRIX_ROWS;
case HLSL_CLASS_OBJECT:
return D3D_SVC_OBJECT; case HLSL_CLASS_SCALAR: return D3D_SVC_SCALAR; case HLSL_CLASS_STRUCT: return D3D_SVC_STRUCT; case HLSL_CLASS_VECTOR: return D3D_SVC_VECTOR;
default:
ERR("Invalid class %#x.\n", type->class);
vkd3d_unreachable();
case HLSL_CLASS_OBJECT:
break;
Not that I care that much, but I'd claim that the standard construct is `case XXX: vkd3d_unreachable();` rather than breaking and then calling `vkd3d_unreachable()`.
Giovanni Mascellani (@giomasce) commented about tests/hlsl_d3d12.c:
{vs_source, "vs_5_0", vs_bindings, ARRAY_SIZE(vs_bindings), vs_buffers, ARRAY_SIZE(vs_buffers)},
{ps_source, "ps_5_0", ps_bindings, ARRAY_SIZE(ps_bindings)},
- };
- for (unsigned int t = 0; t < ARRAY_SIZE(tests); ++t)
- {
ID3D10Blob *code = compile_shader_flags(tests[t].source,
tests[t].profile, D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY);
ID3D12ShaderReflection *reflection;
D3D12_SHADER_DESC shader_desc;
hr = D3DReflect(ID3D10Blob_GetBufferPointer(code), ID3D10Blob_GetBufferSize(code),
&IID_ID3D12ShaderReflection, (void **)&reflection);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = reflection->lpVtbl->GetDesc(reflection, &shader_desc);
Any reason for explicitly browsing the vtable instead of calling the usual helpers?
On Mon Feb 19 10:58:33 2024 +0000, Giovanni Mascellani wrote:
This can never happen, `found_rdef` is never set to `true`.
Oops :-(
On Mon Feb 19 10:58:34 2024 +0000, Giovanni Mascellani wrote:
Not that I care that much, but I'd claim that the standard construct is `case XXX: vkd3d_unreachable();` rather than breaking and then calling `vkd3d_unreachable()`.
I need either vkd3d_unreachable() at the end of the function, or in a default case. I prefer the former because using 'default' makes it easier to miss when a new case is added. At that point it seems simpler to break rather than use unreachable() twice, but I'd also be satisfied with the latter.
On Mon Feb 19 10:58:35 2024 +0000, Giovanni Mascellani wrote:
Any reason for explicitly browsing the vtable instead of calling the usual helpers?
The usual helpers don't work with Microsoft headers, and IIRC they don't work with Wine's headers either. We could ditch that restriction, though.
On Mon Feb 19 18:29:24 2024 +0000, Zebediah Figura wrote:
I need either vkd3d_unreachable() at the end of the function, or in a default case. I prefer the former because using 'default' makes it easier to miss when a new case is added. At that point it seems simpler to break rather than use unreachable() twice, but I'd also be satisfied with the latter.
Ah, ok, that's fine for me.
On Mon Feb 19 18:29:25 2024 +0000, Zebediah Figura wrote:
The usual helpers don't work with Microsoft headers, and IIRC they don't work with Wine's headers either. We could ditch that restriction, though.
Hmm, I changed `reflection->lpVtbl->GetDesc` to `ID3D12ShaderReflection_GetDesc` here and it seems to build fine with GCC, MinGW and for the cross tests. Which scenario do you expect to fail? I guess we don't support building with MSVC, do we?
Hmm, I changed `reflection->lpVtbl->GetDesc` to `ID3D12ShaderReflection_GetDesc` here and it seems to build fine with GCC, MinGW and for the cross tests.
Because we're using our own headers, I think.
Which scenario do you expect to fail? I guess we don't support building with MSVC, do we?
No idea about MSVC, but Microsoft's headers are missing the C macros. Wine's d3d11shader.h is written accordingly and is also missing those macros, although d3d12shader.h is generated from an IDL and has them.
I copy-pasted most of these tests from Wine, and changed the 11 to 12, so the lpVtbl usage is retained from that. I guess as long as vkd3d is using its own headers I could replace that, though.
On Tue Feb 20 18:30:25 2024 +0000, Zebediah Figura wrote:
Hmm, I changed `reflection->lpVtbl->GetDesc` to
`ID3D12ShaderReflection_GetDesc` here and it seems to build fine with GCC, MinGW and for the cross tests. Because we're using our own headers, I think.
Which scenario do you expect to fail? I guess we don't support
building with MSVC, do we? No idea about MSVC, but Microsoft's headers are missing the C macros. Wine's d3d11shader.h is written accordingly and is also missing those macros, although d3d12shader.h is generated from an IDL and has them. I copy-pasted most of these tests from Wine, and changed the 11 to 12, so the lpVtbl usage is retained from that. I guess as long as vkd3d is using its own headers I could replace that, though.
Ah, I see. Well, given that vkd3d is mostly concerned with D3D12 (so far, at least) and that it seems that the D3D12 headers have the macros, then I'd use them in our tests. However I won't object if you or others prefer to retain the explicit vtable access.
Yeah, we're using vkd3d_d3d12shader.h here, so we're not too concerned about what the Microsoft headers do.
Ah, I see. Well, given that vkd3d is mostly concerned with D3D12 (so far, at least)
That's true for libvkd3d, but note that it's not quite the case for libvkd3d-shader and libvkd3d-utils.