From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-utils/reflection.c | 105 +++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d-utils/reflection.c b/libs/vkd3d-utils/reflection.c index 2f604864b..38b26afb4 100644 --- a/libs/vkd3d-utils/reflection.c +++ b/libs/vkd3d-utils/reflection.c @@ -1,6 +1,7 @@ /* * Copyright 2009 Henri Verbeet for CodeWeavers * Copyright 2010 Rico Schüller + * Copyright 2024 Zebediah Figura for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,14 +22,82 @@ #include <vkd3d_d3dcommon.h> #include <vkd3d_d3d12shader.h>
+struct d3d12_buffer +{ + ID3D12ShaderReflectionConstantBuffer ID3D12ShaderReflectionConstantBuffer_iface; + const struct vkd3d_shader_d3d_buffer *buffer; +}; + struct d3d12_reflection { ID3D12ShaderReflection ID3D12ShaderReflection_iface; unsigned int refcount;
struct vkd3d_shader_scan_signature_info signature_info; + struct vkd3d_shader_scan_d3d_buffer_info buffer_info; + + 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->Name = buffer->buffer->name; + desc->Type = (D3D_CBUFFER_TYPE)buffer->buffer->type; + desc->Variables = buffer->buffer->variable_count; + desc->Size = buffer->buffer->size; + desc->uFlags = buffer->buffer->flags; + 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 +141,7 @@ static ULONG STDMETHODCALLTYPE d3d12_reflection_Release(ID3D12ShaderReflection *
if (!refcount) { + vkd3d_shader_free_scan_d3d_buffer_info(&reflection->buffer_info); vkd3d_shader_free_scan_signature_info(&reflection->signature_info); free(reflection); } @@ -87,9 +157,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_reflection_GetDesc(ID3D12ShaderReflection
FIXME("iface %p, desc %p partial stub!\n", iface, desc);
+ memset(desc, 0, sizeof(*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->ConstantBuffers = reflection->buffer_info.buffer_count;
return S_OK; } @@ -97,9 +169,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->buffer_info.buffer_count) + { + 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 +367,16 @@ static const struct ID3D12ShaderReflectionVtbl d3d12_reflection_vtbl = d3d12_reflection_GetRequiresFlags, };
+static void d3d12_buffer_init(struct d3d12_buffer *buffer, const struct vkd3d_shader_d3d_buffer *vkd3d_buffer) +{ + buffer->ID3D12ShaderReflectionConstantBuffer_iface.lpVtbl = &d3d12_buffer_vtbl; + buffer->buffer = vkd3d_buffer; +} + 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}; + HRESULT hr;
reflection->ID3D12ShaderReflection_iface.lpVtbl = &d3d12_reflection_vtbl; reflection->refcount = 1; @@ -301,7 +388,19 @@ 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)); + reflection->signature_info.next = &reflection->buffer_info; + reflection->buffer_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_D3D_BUFFER_INFO; + + if (FAILED(hr = hresult_from_vkd3d_result(vkd3d_shader_scan(&compile_info, NULL)))) + return hr; + + if (!(reflection->buffers = vkd3d_calloc(reflection->buffer_info.buffer_count, sizeof(*reflection->buffers)))) + return E_OUTOFMEMORY; + + for (uint32_t i = 0; i < reflection->buffer_info.buffer_count; ++i) + d3d12_buffer_init(&reflection->buffers[i], &reflection->buffer_info.buffers[i]); + + return S_OK; }
HRESULT WINAPI D3DReflect(const void *data, SIZE_T data_size, REFIID iid, void **reflection)