Unlike previous vkd3d-utils interfaces, ID3D12ShaderReflection is rather more large and complex, and will probably end up needing several new individual scan interfaces from vkd3d-shader, which are themselves not exactly trivial to design.
Therefore, instead of implementing everything in vkd3d-shader and then hooking up the vkd3d-utils interfaces on top of that, this patch series copies the existing implementation of reflection and then begins the process of moving its implementation to vkd3d-shader.
The primary motivation here is to add reflection crosstests (primarily for the benefit of the HLSL compiler) without being blocked on API design. Part 2 of this patch series does this.
-- v3: tests: Test signature reflection via D3DReflect(). tests: Test VKD3D_SHADER_COMPILE_OPTION_BACKCOMPAT_MAP_SEMANTIC_NAMES. vkd3d-utils: Implement input and output signature reflection. vkd3d-utils: Add D3DReflect(). include: Add vkd3d_d3d12shader.idl.
From: Zebediah Figura zfigura@codeweavers.com
--- Makefile.am | 2 + include/vkd3d_d3d12shader.idl | 306 ++++++++++++++++++++++++++++++++++ include/vkd3d_d3dcommon.idl | 72 ++++++++ 3 files changed, 380 insertions(+) create mode 100644 include/vkd3d_d3d12shader.idl
diff --git a/Makefile.am b/Makefile.am index 648dfb255..a2378eae8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,6 +6,7 @@ AM_LDFLAGS = -no-undefined widl_headers = \ include/vkd3d_d3d12.h \ include/vkd3d_d3d12sdklayers.h \ + include/vkd3d_d3d12shader.h \ include/vkd3d_d3dcommon.h \ include/vkd3d_d3dx9shader.h \ include/vkd3d_dxgi.h \ @@ -21,6 +22,7 @@ vkd3d_public_headers = \ include/vkd3d.h \ include/vkd3d_d3d12.h \ include/vkd3d_d3d12sdklayers.h \ + include/vkd3d_d3d12shader.h \ include/vkd3d_d3d9types.h \ include/vkd3d_d3dcommon.h \ include/vkd3d_d3dcompiler.h \ diff --git a/include/vkd3d_d3d12shader.idl b/include/vkd3d_d3d12shader.idl new file mode 100644 index 000000000..ba42a9458 --- /dev/null +++ b/include/vkd3d_d3d12shader.idl @@ -0,0 +1,306 @@ +/* + * Copyright 2020 Paul Gofman for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +import "vkd3d_windows.h"; +import "vkd3d_d3dcommon.idl"; + +typedef enum D3D12_SHADER_VERSION_TYPE +{ + D3D12_SHVER_PIXEL_SHADER = 0x0, + D3D12_SHVER_VERTEX_SHADER = 0x1, + D3D12_SHVER_GEOMETRY_SHADER = 0x2, + D3D12_SHVER_HULL_SHADER = 0x3, + D3D12_SHVER_DOMAIN_SHADER = 0x4, + D3D12_SHVER_COMPUTE_SHADER = 0x5, + D3D12_SHVER_RESERVED0 = 0xfff0, +} D3D12_SHADER_VERSION_TYPE; + +typedef struct _D3D12_SHADER_DESC +{ + UINT Version; + const char *Creator; + UINT Flags; + UINT ConstantBuffers; + UINT BoundResources; + UINT InputParameters; + UINT OutputParameters; + UINT InstructionCount; + UINT TempRegisterCount; + UINT TempArrayCount; + UINT DefCount; + UINT DclCount; + UINT TextureNormalInstructions; + UINT TextureLoadInstructions; + UINT TextureCompInstructions; + UINT TextureBiasInstructions; + UINT TextureGradientInstructions; + UINT FloatInstructionCount; + UINT IntInstructionCount; + UINT UintInstructionCount; + UINT StaticFlowControlCount; + UINT DynamicFlowControlCount; + UINT MacroInstructionCount; + UINT ArrayInstructionCount; + UINT CutInstructionCount; + UINT EmitInstructionCount; + D3D_PRIMITIVE_TOPOLOGY GSOutputTopology; + UINT GSMaxOutputVertexCount; + D3D_PRIMITIVE InputPrimitive; + UINT PatchConstantParameters; + UINT cGSInstanceCount; + UINT cControlPoints; + D3D_TESSELLATOR_OUTPUT_PRIMITIVE HSOutputPrimitive; + D3D_TESSELLATOR_PARTITIONING HSPartitioning; + D3D_TESSELLATOR_DOMAIN TessellatorDomain; + UINT cBarrierInstructions; + UINT cInterlockedInstructions; + UINT cTextureStoreInstructions; +} D3D12_SHADER_DESC; + +typedef struct _D3D12_SHADER_VARIABLE_DESC +{ + const char *Name; + UINT StartOffset; + UINT Size; + UINT uFlags; + void *DefaultValue; + UINT StartTexture; + UINT TextureSize; + UINT StartSampler; + UINT SamplerSize; +} D3D12_SHADER_VARIABLE_DESC; + +typedef struct _D3D12_SHADER_TYPE_DESC +{ + D3D_SHADER_VARIABLE_CLASS Class; + D3D_SHADER_VARIABLE_TYPE Type; + UINT Rows; + UINT Columns; + UINT Elements; + UINT Members; + UINT Offset; + const char *Name; +} D3D12_SHADER_TYPE_DESC; + +typedef struct _D3D12_SHADER_BUFFER_DESC +{ + const char *Name; + D3D_CBUFFER_TYPE Type; + UINT Variables; + UINT Size; + UINT uFlags; +} D3D12_SHADER_BUFFER_DESC; + +typedef struct _D3D12_SHADER_INPUT_BIND_DESC +{ + const char *Name; + D3D_SHADER_INPUT_TYPE Type; + UINT BindPoint; + UINT BindCount; + UINT uFlags; + D3D_RESOURCE_RETURN_TYPE ReturnType; + D3D_SRV_DIMENSION Dimension; + UINT NumSamples; + UINT Space; + UINT uID; +} D3D12_SHADER_INPUT_BIND_DESC; + +typedef struct _D3D12_SIGNATURE_PARAMETER_DESC +{ + const char *SemanticName; + UINT SemanticIndex; + UINT Register; + D3D_NAME SystemValueType; + D3D_REGISTER_COMPONENT_TYPE ComponentType; + BYTE Mask; + BYTE ReadWriteMask; + UINT Stream; + D3D_MIN_PRECISION MinPrecision; +} D3D12_SIGNATURE_PARAMETER_DESC; + +typedef struct _D3D12_PARAMETER_DESC +{ + const char *Name; + const char *SemanticName; + D3D_SHADER_VARIABLE_TYPE Type; + D3D_SHADER_VARIABLE_CLASS Class; + UINT Rows; + UINT Columns; + D3D_INTERPOLATION_MODE InterpolationMode; + D3D_PARAMETER_FLAGS Flags; + UINT FirstInRegister; + UINT FirstInComponent; + UINT FirstOutRegister; + UINT FirstOutComponent; +} D3D12_PARAMETER_DESC; + +typedef struct _D3D12_FUNCTION_DESC +{ + UINT Version; + const char *Creator; + UINT Flags; + UINT ConstantBuffers; + UINT BoundResources; + UINT InstructionCount; + UINT TempRegisterCount; + UINT TempArrayCount; + UINT DefCount; + UINT DclCount; + UINT TextureNormalInstructions; + UINT TextureLoadInstructions; + UINT TextureCompInstructions; + UINT TextureBiasInstructions; + UINT TextureGradientInstructions; + UINT FloatInstructionCount; + UINT IntInstructionCount; + UINT UintInstructionCount; + UINT StaticFlowControlCount; + UINT DynamicFlowControlCount; + UINT MacroInstructionCount; + UINT ArrayInstructionCount; + UINT MovInstructionCount; + UINT MovcInstructionCount; + UINT ConversionInstructionCount; + UINT BitwiseInstructionCount; + D3D_FEATURE_LEVEL MinFeatureLevel; + UINT64 RequiredFeatureFlags; + const char *Name; + INT FunctionParameterCount; + BOOL HasReturn; + BOOL Has10Level9VertexShader; + BOOL Has10Level9PixelShader; +} D3D12_FUNCTION_DESC; + +typedef struct _D3D12_LIBRARY_DESC +{ + const char *Creator; + UINT Flags; + UINT FunctionCount; +} D3D12_LIBRARY_DESC; + +interface ID3D12ShaderReflectionConstantBuffer; + +[ + uuid(e913c351-783d-48ca-a1d1-4f306284ad56), + object, + local, +] +interface ID3D12ShaderReflectionType +{ + HRESULT GetDesc(D3D12_SHADER_TYPE_DESC *desc); + ID3D12ShaderReflectionType *GetMemberTypeByIndex(UINT index); + ID3D12ShaderReflectionType *GetMemberTypeByName(const char *name); + const char *GetMemberTypeName(UINT index); + HRESULT IsEqual(ID3D12ShaderReflectionType *type); + ID3D12ShaderReflectionType *GetSubType(); + ID3D12ShaderReflectionType *GetBaseClass(); + UINT GetNumInterfaces(); + ID3D12ShaderReflectionType *GetInterfaceByIndex(UINT index); + HRESULT IsOfType(ID3D12ShaderReflectionType *type); + HRESULT ImplementsInterface(ID3D12ShaderReflectionType *base); +} + +[ + uuid(8337a8a6-a216-444a-b2f4-314733a73aea), + object, + local, +] +interface ID3D12ShaderReflectionVariable +{ + HRESULT GetDesc(D3D12_SHADER_VARIABLE_DESC *desc); + ID3D12ShaderReflectionType *GetType(); + ID3D12ShaderReflectionConstantBuffer *GetBuffer(); + UINT GetInterfaceSlot(UINT index); +} + +[ + uuid(c59598b4-48b3-4869-b9b1-b1618b14a8b7), + object, + local, +] +interface ID3D12ShaderReflectionConstantBuffer +{ + HRESULT GetDesc(D3D12_SHADER_BUFFER_DESC *desc); + ID3D12ShaderReflectionVariable *GetVariableByIndex(UINT index); + ID3D12ShaderReflectionVariable *GetVariableByName(const char *name); +} + +[ + uuid(5a58797d-a72c-478d-8ba2-efc6b0efe88e), + object, + local, +] +interface ID3D12ShaderReflection : IUnknown +{ + HRESULT GetDesc(D3D12_SHADER_DESC *desc); + ID3D12ShaderReflectionConstantBuffer *GetConstantBufferByIndex(UINT index); + ID3D12ShaderReflectionConstantBuffer *GetConstantBufferByName(const char *name); + HRESULT GetResourceBindingDesc(UINT index, D3D12_SHADER_INPUT_BIND_DESC *desc); + HRESULT GetInputParameterDesc(UINT index, D3D12_SIGNATURE_PARAMETER_DESC *desc); + HRESULT GetOutputParameterDesc(UINT index, D3D12_SIGNATURE_PARAMETER_DESC *desc); + HRESULT GetPatchConstantParameterDesc(UINT index, D3D12_SIGNATURE_PARAMETER_DESC *desc); + ID3D12ShaderReflectionVariable *GetVariableByName(const char *name); + HRESULT GetResourceBindingDescByName(const char *name, D3D12_SHADER_INPUT_BIND_DESC *desc); + UINT GetMovInstructionCount(); + UINT GetMovcInstructionCount(); + UINT GetConversionInstructionCount(); + UINT GetBitwiseInstructionCount(); + D3D_PRIMITIVE GetGSInputPrimitive(); + BOOL IsSampleFrequencyShader(); + UINT GetNumInterfaceSlots(); + HRESULT GetMinFeatureLevel(D3D_FEATURE_LEVEL *level); + UINT GetThreadGroupSize(UINT *sizex, UINT *sizey, UINT *sizez); + UINT64 GetRequiresFlags(); +} + +[ + uuid(ec25f42d-7006-4f2b-b33e-02cc3375733f), + object, + local, +] +interface ID3D12FunctionParameterReflection +{ + HRESULT GetDesc(D3D12_PARAMETER_DESC *desc); +} + +[ + uuid(1108795c-2772-4ba9-b2a8-d464dc7e2799), + object, + local, +] +interface ID3D12FunctionReflection +{ + HRESULT GetDesc(D3D12_FUNCTION_DESC *desc); + ID3D12ShaderReflectionConstantBuffer *GetConstantBufferByIndex(UINT index); + ID3D12ShaderReflectionConstantBuffer *GetConstantBufferByName(const char *name); + HRESULT GetResourceBindingDesc(UINT index, D3D12_SHADER_INPUT_BIND_DESC *desc); + ID3D12ShaderReflectionVariable *GetVariableByName(const char *name); + HRESULT GetResourceBindingDescByName(const char *name, D3D12_SHADER_INPUT_BIND_DESC *desc); + ID3D12FunctionParameterReflection *GetFunctionParameter(INT index); +} + +[ + uuid(8e349d19-54db-4a56-9dc9-119d87bdb804), + object, + local, +] +interface ID3D12LibraryReflection : IUnknown +{ + HRESULT GetDesc(D3D12_LIBRARY_DESC *desc); + ID3D12FunctionReflection *GetFunctionByIndex(INT index); +} diff --git a/include/vkd3d_d3dcommon.idl b/include/vkd3d_d3dcommon.idl index ab5dd01f1..0b6fdebd7 100644 --- a/include/vkd3d_d3dcommon.idl +++ b/include/vkd3d_d3dcommon.idl @@ -353,6 +353,78 @@ typedef enum _D3D_SHADER_VARIABLE_TYPE D3D_SVT_FORCE_DWORD = 0x7fffffff, } D3D_SHADER_VARIABLE_TYPE;
+typedef enum D3D_TESSELLATOR_DOMAIN +{ + D3D_TESSELLATOR_DOMAIN_UNDEFINED, + D3D_TESSELLATOR_DOMAIN_ISOLINE, + D3D_TESSELLATOR_DOMAIN_TRI, + D3D_TESSELLATOR_DOMAIN_QUAD, + D3D11_TESSELLATOR_DOMAIN_UNDEFINED = 0, + D3D11_TESSELLATOR_DOMAIN_ISOLINE, + D3D11_TESSELLATOR_DOMAIN_TRI, + D3D11_TESSELLATOR_DOMAIN_QUAD, +} D3D_TESSELLATOR_DOMAIN; + +typedef enum D3D_TESSELLATOR_PARTITIONING +{ + D3D_TESSELLATOR_PARTITIONING_UNDEFINED, + D3D_TESSELLATOR_PARTITIONING_INTEGER, + D3D_TESSELLATOR_PARTITIONING_POW2, + D3D_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD, + D3D_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN, + D3D11_TESSELLATOR_PARTITIONING_UNDEFINED = 0, + D3D11_TESSELLATOR_PARTITIONING_INTEGER, + D3D11_TESSELLATOR_PARTITIONING_POW2, + D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD, + D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN, +} D3D_TESSELLATOR_PARTITIONING; + +typedef enum D3D_TESSELLATOR_OUTPUT_PRIMITIVE +{ + D3D_TESSELLATOR_OUTPUT_UNDEFINED, + D3D_TESSELLATOR_OUTPUT_POINT, + D3D_TESSELLATOR_OUTPUT_LINE, + D3D_TESSELLATOR_OUTPUT_TRIANGLE_CW, + D3D_TESSELLATOR_OUTPUT_TRIANGLE_CCW, + D3D11_TESSELLATOR_OUTPUT_UNDEFINED = 0, + D3D11_TESSELLATOR_OUTPUT_POINT, + D3D11_TESSELLATOR_OUTPUT_LINE, + D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CW, + D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CCW, +} D3D_TESSELLATOR_OUTPUT_PRIMITIVE; + +typedef enum D3D_MIN_PRECISION +{ + D3D_MIN_PRECISION_DEFAULT = 0, + D3D_MIN_PRECISION_FLOAT_16 = 1, + D3D_MIN_PRECISION_FLOAT_2_8 = 2, + D3D_MIN_PRECISION_RESERVED = 3, + D3D_MIN_PRECISION_SINT_16 = 4, + D3D_MIN_PRECISION_UINT_16 = 5, + D3D_MIN_PRECISION_ANY_16 = 0xf0, + D3D_MIN_PRECISION_ANY_10 = 0xf1, +} D3D_MIN_PRECISION; + +typedef enum _D3D_INTERPOLATION_MODE +{ + D3D_INTERPOLATION_UNDEFINED, + D3D_INTERPOLATION_CONSTANT, + D3D_INTERPOLATION_LINEAR, + D3D_INTERPOLATION_LINEAR_CENTROID, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID, + D3D_INTERPOLATION_LINEAR_SAMPLE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, +} D3D_INTERPOLATION_MODE; + +typedef enum _D3D_PARAMETER_FLAGS +{ + D3D_PF_NONE, + D3D_PF_IN, + D3D_PF_OUT, + D3D_PF_FORCE_DWORD = 0x7fffffff, +} D3D_PARAMETER_FLAGS; + [ uuid(8ba5fb08-5195-40e2-ac58-0d989c3a0102), object,
From: Zebediah Figura zfigura@codeweavers.com
--- Makefile.am | 1 + include/vkd3d_utils.h | 1 + libs/vkd3d-common/blob.c | 1 + libs/vkd3d-utils/reflection.c | 285 +++++++++++++++++++++++++++++++ libs/vkd3d-utils/vkd3d_utils.map | 1 + 5 files changed, 289 insertions(+) create mode 100644 libs/vkd3d-utils/reflection.c
diff --git a/Makefile.am b/Makefile.am index a2378eae8..f2977c70b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -354,6 +354,7 @@ EXTRA_libvkd3d_la_DEPENDENCIES = $(srcdir)/libs/vkd3d/vkd3d.map endif
libvkd3d_utils_la_SOURCES = \ + libs/vkd3d-utils/reflection.c \ libs/vkd3d-utils/vkd3d_utils.map \ libs/vkd3d-utils/vkd3d_utils_main.c \ libs/vkd3d-utils/vkd3d_utils_private.h diff --git a/include/vkd3d_utils.h b/include/vkd3d_utils.h index 686ddf386..845894c22 100644 --- a/include/vkd3d_utils.h +++ b/include/vkd3d_utils.h @@ -86,6 +86,7 @@ VKD3D_UTILS_API HRESULT WINAPI D3DCreateBlob(SIZE_T data_size, ID3DBlob **blob); VKD3D_UTILS_API HRESULT WINAPI D3DPreprocess(const void *data, SIZE_T size, const char *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *include, ID3DBlob **shader, ID3DBlob **error_messages); +VKD3D_UTILS_API HRESULT WINAPI D3DReflect(const void *data, SIZE_T data_size, REFIID iid, void **reflection);
/** * Set a callback to be called when vkd3d-utils outputs debug logging. diff --git a/libs/vkd3d-common/blob.c b/libs/vkd3d-common/blob.c index 0f6d5a5ee..59e9834d4 100644 --- a/libs/vkd3d-common/blob.c +++ b/libs/vkd3d-common/blob.c @@ -23,6 +23,7 @@ #include "vkd3d_blob.h" #include "vkd3d_debug.h" #include "vkd3d_memory.h" +#include "vkd3d_d3d12shader.h"
struct vkd3d_blob { diff --git a/libs/vkd3d-utils/reflection.c b/libs/vkd3d-utils/reflection.c new file mode 100644 index 000000000..1f8e6e9d1 --- /dev/null +++ b/libs/vkd3d-utils/reflection.c @@ -0,0 +1,285 @@ +/* + * Copyright 2009 Henri Verbeet for CodeWeavers + * Copyright 2010 Rico Schüller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "vkd3d_utils_private.h" +#include <vkd3d_d3dcommon.h> +#include <vkd3d_d3d12shader.h> + +struct d3d12_reflection +{ + ID3D12ShaderReflection ID3D12ShaderReflection_iface; + LONG refcount; +}; + +static struct d3d12_reflection *impl_from_ID3D12ShaderReflection(ID3D12ShaderReflection *iface) +{ + return CONTAINING_RECORD(iface, struct d3d12_reflection, ID3D12ShaderReflection_iface); +} + +static HRESULT STDMETHODCALLTYPE d3d12_reflection_QueryInterface( + ID3D12ShaderReflection *iface, REFIID riid, void **object) +{ + TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object); + + if (IsEqualGUID(riid, &IID_ID3D12ShaderReflection) + || IsEqualGUID(riid, &IID_IUnknown)) + { + IUnknown_AddRef(iface); + *object = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + + *object = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE d3d12_reflection_AddRef(ID3D12ShaderReflection *iface) +{ + struct d3d12_reflection *reflection = impl_from_ID3D12ShaderReflection(iface); + ULONG refcount = InterlockedIncrement(&reflection->refcount); + + TRACE("%p increasing refcount to %u.\n", reflection, refcount); + + return refcount; +} + +static ULONG STDMETHODCALLTYPE d3d12_reflection_Release(ID3D12ShaderReflection *iface) +{ + struct d3d12_reflection *reflection = impl_from_ID3D12ShaderReflection(iface); + ULONG refcount = InterlockedDecrement(&reflection->refcount); + + TRACE("%p decreasing refcount to %u.\n", reflection, refcount); + + if (!refcount) + { + free(reflection); + } + + return refcount; +} + +/* ID3D12ShaderReflection methods */ + +static HRESULT STDMETHODCALLTYPE d3d12_reflection_GetDesc(ID3D12ShaderReflection *iface, D3D12_SHADER_DESC *desc) +{ + FIXME("iface %p, desc %p partial stub!\n", iface, desc); + + return E_NOTIMPL; +} + +static struct ID3D12ShaderReflectionConstantBuffer * STDMETHODCALLTYPE d3d12_reflection_GetConstantBufferByIndex( + ID3D12ShaderReflection *iface, UINT index) +{ + FIXME("iface %p, index %u stub!\n", iface, index); + + return NULL; +} + +static struct ID3D12ShaderReflectionConstantBuffer * STDMETHODCALLTYPE d3d12_reflection_GetConstantBufferByName( + ID3D12ShaderReflection *iface, const char *name) +{ + FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name)); + + return NULL; +} + +static HRESULT STDMETHODCALLTYPE d3d12_reflection_GetResourceBindingDesc( + ID3D12ShaderReflection *iface, UINT index, D3D12_SHADER_INPUT_BIND_DESC *desc) +{ + FIXME("iface %p, index %u, desc %p stub!\n", iface, index, desc); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE d3d12_reflection_GetInputParameterDesc( + ID3D12ShaderReflection *iface, UINT index, D3D12_SIGNATURE_PARAMETER_DESC *desc) +{ + FIXME("iface %p, index %u, desc %p stub!\n", iface, index, desc); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE d3d12_reflection_GetOutputParameterDesc( + ID3D12ShaderReflection *iface, UINT index, D3D12_SIGNATURE_PARAMETER_DESC *desc) +{ + FIXME("iface %p, index %u, desc %p stub!\n", iface, index, desc); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE d3d12_reflection_GetPatchConstantParameterDesc( + ID3D12ShaderReflection *iface, UINT index, D3D12_SIGNATURE_PARAMETER_DESC *desc) +{ + FIXME("iface %p, index %u, desc %p stub!\n", iface, index, desc); + + return E_NOTIMPL; +} + +static struct ID3D12ShaderReflectionVariable * STDMETHODCALLTYPE d3d12_reflection_GetVariableByName( + ID3D12ShaderReflection *iface, const char *name) +{ + FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name)); + + return NULL; +} + +static HRESULT STDMETHODCALLTYPE d3d12_reflection_GetResourceBindingDescByName( + ID3D12ShaderReflection *iface, const char *name, D3D12_SHADER_INPUT_BIND_DESC *desc) +{ + FIXME("iface %p, name %s, desc %p stub!\n", iface, debugstr_a(name), desc); + + return E_NOTIMPL; +} + +static UINT STDMETHODCALLTYPE d3d12_reflection_GetMovInstructionCount(ID3D12ShaderReflection *iface) +{ + FIXME("iface %p stub!\n", iface); + + return 0; +} + +static UINT STDMETHODCALLTYPE d3d12_reflection_GetMovcInstructionCount(ID3D12ShaderReflection *iface) +{ + FIXME("iface %p stub!\n", iface); + + return 0; +} + +static UINT STDMETHODCALLTYPE d3d12_reflection_GetConversionInstructionCount(ID3D12ShaderReflection *iface) +{ + FIXME("iface %p stub!\n", iface); + + return 0; +} + +static UINT STDMETHODCALLTYPE d3d12_reflection_GetBitwiseInstructionCount(ID3D12ShaderReflection *iface) +{ + FIXME("iface %p stub!\n", iface); + + return 0; +} + +static D3D_PRIMITIVE STDMETHODCALLTYPE d3d12_reflection_GetGSInputPrimitive(ID3D12ShaderReflection *iface) +{ + FIXME("iface %p stub!\n", iface); + + return 0; +} + +static BOOL STDMETHODCALLTYPE d3d12_reflection_IsSampleFrequencyShader(ID3D12ShaderReflection *iface) +{ + FIXME("iface %p stub!\n", iface); + + return FALSE; +} + +static UINT STDMETHODCALLTYPE d3d12_reflection_GetNumInterfaceSlots(ID3D12ShaderReflection *iface) +{ + FIXME("iface %p stub!\n", iface); + + return 0; +} + +static HRESULT STDMETHODCALLTYPE d3d12_reflection_GetMinFeatureLevel( + ID3D12ShaderReflection *iface, D3D_FEATURE_LEVEL *level) +{ + FIXME("iface %p, level %p stub!\n", iface, level); + + return E_NOTIMPL; +} + +static UINT STDMETHODCALLTYPE d3d12_reflection_GetThreadGroupSize( + ID3D12ShaderReflection *iface, UINT *sizex, UINT *sizey, UINT *sizez) +{ + FIXME("iface %p, sizex %p, sizey %p, sizez %p stub!\n", iface, sizex, sizey, sizez); + + return 0; +} + +static UINT64 STDMETHODCALLTYPE d3d12_reflection_GetRequiresFlags(ID3D12ShaderReflection *iface) +{ + FIXME("iface %p stub!\n", iface); + + return 0; +} + +static const struct ID3D12ShaderReflectionVtbl d3d12_reflection_vtbl = +{ + /* IUnknown methods */ + d3d12_reflection_QueryInterface, + d3d12_reflection_AddRef, + d3d12_reflection_Release, + /* ID3D12ShaderReflection methods */ + d3d12_reflection_GetDesc, + d3d12_reflection_GetConstantBufferByIndex, + d3d12_reflection_GetConstantBufferByName, + d3d12_reflection_GetResourceBindingDesc, + d3d12_reflection_GetInputParameterDesc, + d3d12_reflection_GetOutputParameterDesc, + d3d12_reflection_GetPatchConstantParameterDesc, + d3d12_reflection_GetVariableByName, + d3d12_reflection_GetResourceBindingDescByName, + d3d12_reflection_GetMovInstructionCount, + d3d12_reflection_GetMovcInstructionCount, + d3d12_reflection_GetConversionInstructionCount, + d3d12_reflection_GetBitwiseInstructionCount, + d3d12_reflection_GetGSInputPrimitive, + d3d12_reflection_IsSampleFrequencyShader, + d3d12_reflection_GetNumInterfaceSlots, + d3d12_reflection_GetMinFeatureLevel, + d3d12_reflection_GetThreadGroupSize, + d3d12_reflection_GetRequiresFlags, +}; + +static HRESULT d3d12_reflection_init(struct d3d12_reflection *reflection, const void *data, size_t data_size) +{ + reflection->ID3D12ShaderReflection_iface.lpVtbl = &d3d12_reflection_vtbl; + reflection->refcount = 1; + + return S_OK; +} + +HRESULT WINAPI D3DReflect(const void *data, SIZE_T data_size, REFIID iid, void **reflection) +{ + struct d3d12_reflection *object; + HRESULT hr; + + TRACE("data %p, data_size %lu, iid %s, reflection %p.\n", data, data_size, debugstr_guid(iid), reflection); + + if (!IsEqualGUID(iid, &IID_ID3D12ShaderReflection)) + { + WARN("Invalid iid %s.\n", debugstr_guid(iid)); + return E_INVALIDARG; + } + + if (!(object = vkd3d_calloc(1, sizeof(*object)))) + return E_OUTOFMEMORY; + + if (FAILED(hr = d3d12_reflection_init(object, data, data_size))) + { + free(object); + return hr; + } + + *reflection = &object->ID3D12ShaderReflection_iface; + TRACE("Created reflection %p.\n", object); + return S_OK; +} diff --git a/libs/vkd3d-utils/vkd3d_utils.map b/libs/vkd3d-utils/vkd3d_utils.map index 8cf102dde..8dad9cc3a 100644 --- a/libs/vkd3d-utils/vkd3d_utils.map +++ b/libs/vkd3d-utils/vkd3d_utils.map @@ -17,6 +17,7 @@ global: D3DGetInputSignatureBlob; D3DGetOutputSignatureBlob; D3DPreprocess; + D3DReflect; D3DStripShader; vkd3d_create_event; vkd3d_destroy_event;
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-utils/reflection.c | 59 +++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 6 deletions(-)
diff --git a/libs/vkd3d-utils/reflection.c b/libs/vkd3d-utils/reflection.c index 1f8e6e9d1..388733dca 100644 --- a/libs/vkd3d-utils/reflection.c +++ b/libs/vkd3d-utils/reflection.c @@ -25,6 +25,8 @@ struct d3d12_reflection { ID3D12ShaderReflection ID3D12ShaderReflection_iface; LONG refcount; + + struct vkd3d_shader_scan_signature_info signature_info; };
static struct d3d12_reflection *impl_from_ID3D12ShaderReflection(ID3D12ShaderReflection *iface) @@ -70,6 +72,7 @@ static ULONG STDMETHODCALLTYPE d3d12_reflection_Release(ID3D12ShaderReflection *
if (!refcount) { + vkd3d_shader_free_scan_signature_info(&reflection->signature_info); free(reflection); }
@@ -80,9 +83,15 @@ static ULONG STDMETHODCALLTYPE d3d12_reflection_Release(ID3D12ShaderReflection *
static HRESULT STDMETHODCALLTYPE d3d12_reflection_GetDesc(ID3D12ShaderReflection *iface, D3D12_SHADER_DESC *desc) { + struct d3d12_reflection *reflection = impl_from_ID3D12ShaderReflection(iface); + FIXME("iface %p, desc %p partial stub!\n", iface, desc);
- return E_NOTIMPL; + 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; + + return S_OK; }
static struct ID3D12ShaderReflectionConstantBuffer * STDMETHODCALLTYPE d3d12_reflection_GetConstantBufferByIndex( @@ -109,20 +118,49 @@ static HRESULT STDMETHODCALLTYPE d3d12_reflection_GetResourceBindingDesc( return E_NOTIMPL; }
+static HRESULT get_signature_parameter(const struct vkd3d_shader_signature *signature, + unsigned int index, D3D12_SIGNATURE_PARAMETER_DESC *desc, bool output) +{ + const struct vkd3d_shader_signature_element *e; + + if (!desc || index >= signature->element_count) + { + WARN("Invalid argument specified.\n"); + return E_INVALIDARG; + } + e = &signature->elements[index]; + + desc->SemanticName = e->semantic_name; + desc->SemanticIndex = e->semantic_index; + desc->Register = e->register_index; + desc->SystemValueType = (D3D_NAME)e->sysval_semantic; + desc->ComponentType = (D3D_REGISTER_COMPONENT_TYPE)e->component_type; + desc->Mask = e->mask; + desc->ReadWriteMask = output ? (e->mask & ~e->used_mask) : e->used_mask; + desc->Stream = e->stream_index; + desc->MinPrecision = (D3D_MIN_PRECISION)e->min_precision; + + return S_OK; +} + static HRESULT STDMETHODCALLTYPE d3d12_reflection_GetInputParameterDesc( ID3D12ShaderReflection *iface, UINT index, D3D12_SIGNATURE_PARAMETER_DESC *desc) { - FIXME("iface %p, index %u, desc %p stub!\n", iface, index, desc); + struct d3d12_reflection *reflection = impl_from_ID3D12ShaderReflection(iface);
- return E_NOTIMPL; + TRACE("iface %p, index %u, desc %p.\n", iface, index, desc); + + return get_signature_parameter(&reflection->signature_info.input, index, desc, false); }
static HRESULT STDMETHODCALLTYPE d3d12_reflection_GetOutputParameterDesc( ID3D12ShaderReflection *iface, UINT index, D3D12_SIGNATURE_PARAMETER_DESC *desc) { - FIXME("iface %p, index %u, desc %p stub!\n", iface, index, desc); + struct d3d12_reflection *reflection = impl_from_ID3D12ShaderReflection(iface);
- return E_NOTIMPL; + TRACE("iface %p, index %u, desc %p.\n", iface, index, desc); + + return get_signature_parameter(&reflection->signature_info.output, index, desc, true); }
static HRESULT STDMETHODCALLTYPE d3d12_reflection_GetPatchConstantParameterDesc( @@ -251,10 +289,19 @@ static const struct ID3D12ShaderReflectionVtbl d3d12_reflection_vtbl =
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}; + reflection->ID3D12ShaderReflection_iface.lpVtbl = &d3d12_reflection_vtbl; reflection->refcount = 1;
- return S_OK; + compile_info.source.code = data; + compile_info.source.size = data_size; + compile_info.source_type = VKD3D_SHADER_SOURCE_DXBC_TPF; + + 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)); }
HRESULT WINAPI D3DReflect(const void *data, SIZE_T data_size, REFIID iid, void **reflection)
From: Zebediah Figura zfigura@codeweavers.com
--- tests/vkd3d_shader_api.c | 59 +++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 10 deletions(-)
diff --git a/tests/vkd3d_shader_api.c b/tests/vkd3d_shader_api.c index 018506a45..00dcd2248 100644 --- a/tests/vkd3d_shader_api.c +++ b/tests/vkd3d_shader_api.c @@ -441,6 +441,7 @@ static void test_scan_signatures(void) struct vkd3d_shader_scan_signature_info signature_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_SIGNATURE_INFO}; struct vkd3d_shader_hlsl_source_info hlsl_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_HLSL_SOURCE_INFO}; struct vkd3d_shader_compile_info compile_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO}; + struct vkd3d_shader_compile_option options[1]; struct vkd3d_shader_code dxbc; size_t i, j; int rc; @@ -496,6 +497,11 @@ static void test_scan_signatures(void) {"position", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 0, 0xf, 0xf}, };
+ static const struct vkd3d_shader_signature_element vs2_legacy_outputs[] = + { + {"SV_Position", 0, 0, VKD3D_SHADER_SV_POSITION, VKD3D_SHADER_COMPONENT_FLOAT, 0, 0xf, 0xf}, + }; + static const char vs3_source[] = "void main(\n" " in float4 c : position,\n" @@ -656,6 +662,27 @@ static void test_scan_signatures(void) {"VFACE", 0, 0, VKD3D_SHADER_SV_IS_FRONT_FACE, VKD3D_SHADER_COMPONENT_FLOAT, 1, 0x1, 0x1}, };
+ static const char ps5_source[] = + "void main(\n" + " inout float4 a : color2,\n" + " inout float b : depth,\n" + " in float4 c : position)\n" + "{\n" + "}"; + + static const struct vkd3d_shader_signature_element ps5_inputs[] = + { + {"color", 2, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 0, 0xf, 0xf}, + {"depth", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 1, 0x1, 0x1}, + {"SV_Position", 0, 0, VKD3D_SHADER_SV_POSITION, VKD3D_SHADER_COMPONENT_FLOAT, 2, 0xf}, + }; + + static const struct vkd3d_shader_signature_element ps5_outputs[] = + { + {"SV_Target", 2, 0, VKD3D_SHADER_SV_TARGET, VKD3D_SHADER_COMPONENT_FLOAT, 2, 0xf, 0xf}, + {"SV_Depth", 0, 0, VKD3D_SHADER_SV_DEPTH, VKD3D_SHADER_COMPONENT_FLOAT, ~0u, 0x1, 0x1}, + }; + static const char cs1_source[] = "[numthreads(1, 1, 1)]\n" "void main(\n" @@ -670,6 +697,7 @@ static void test_scan_signatures(void) const char *source; bool sm4; const char *profile; + bool compat; const struct vkd3d_shader_signature_element *inputs; size_t input_count; const struct vkd3d_shader_signature_element *outputs; @@ -679,16 +707,20 @@ static void test_scan_signatures(void) } tests[] = { - {vs1_source, true, "vs_4_0", vs1_inputs, ARRAY_SIZE(vs1_inputs), vs1_outputs, ARRAY_SIZE(vs1_outputs)}, - {vs2_source, true, "vs_4_0", vs2_inputs, ARRAY_SIZE(vs2_inputs), vs2_outputs, ARRAY_SIZE(vs2_outputs)}, - {vs3_source, false, "vs_1_1", vs3_inputs, ARRAY_SIZE(vs3_inputs), vs3_outputs, ARRAY_SIZE(vs3_outputs)}, - {vs3_source, false, "vs_2_0", vs3_inputs, ARRAY_SIZE(vs3_inputs), vs3_outputs, ARRAY_SIZE(vs3_outputs)}, - {vs4_source, false, "vs_3_0", vs4_inputs, ARRAY_SIZE(vs4_inputs), vs4_outputs, ARRAY_SIZE(vs4_outputs)}, - {ps1_source, true, "ps_4_0", ps1_inputs, ARRAY_SIZE(ps1_inputs), ps1_outputs, ARRAY_SIZE(ps1_outputs)}, - {ps2_source, false, "ps_1_1", ps2_inputs, ARRAY_SIZE(ps2_inputs), ps2_outputs, ARRAY_SIZE(ps2_outputs)}, - {ps3_source, false, "ps_2_0", ps3_inputs, ARRAY_SIZE(ps3_inputs), ps3_outputs, ARRAY_SIZE(ps3_outputs)}, - {ps4_source, false, "ps_3_0", ps4_inputs, ARRAY_SIZE(ps4_inputs), ps3_outputs, ARRAY_SIZE(ps3_outputs)}, - {cs1_source, true, "cs_5_0", NULL, 0, NULL, 0}, + {vs1_source, true, "vs_4_0", false, vs1_inputs, ARRAY_SIZE(vs1_inputs), vs1_outputs, ARRAY_SIZE(vs1_outputs)}, + {vs1_source, true, "vs_4_0", true, vs1_inputs, ARRAY_SIZE(vs1_inputs), vs1_outputs, ARRAY_SIZE(vs1_outputs)}, + {vs2_source, true, "vs_4_0", false, vs2_inputs, ARRAY_SIZE(vs2_inputs), vs2_outputs, ARRAY_SIZE(vs2_outputs)}, + {vs2_source, true, "vs_4_0", true, vs2_inputs, ARRAY_SIZE(vs2_inputs), vs2_legacy_outputs, ARRAY_SIZE(vs2_legacy_outputs)}, + {ps1_source, true, "ps_4_0", false, ps1_inputs, ARRAY_SIZE(ps1_inputs), ps1_outputs, ARRAY_SIZE(ps1_outputs)}, + {ps5_source, true, "ps_4_0", true, ps5_inputs, ARRAY_SIZE(ps5_inputs), ps5_outputs, ARRAY_SIZE(ps5_outputs)}, + {cs1_source, true, "cs_5_0", false, NULL, 0, NULL, 0}, + + {vs3_source, false, "vs_1_1", false, vs3_inputs, ARRAY_SIZE(vs3_inputs), vs3_outputs, ARRAY_SIZE(vs3_outputs)}, + {vs3_source, false, "vs_2_0", false, vs3_inputs, ARRAY_SIZE(vs3_inputs), vs3_outputs, ARRAY_SIZE(vs3_outputs)}, + {vs4_source, false, "vs_3_0", false, vs4_inputs, ARRAY_SIZE(vs4_inputs), vs4_outputs, ARRAY_SIZE(vs4_outputs)}, + {ps2_source, false, "ps_1_1", false, ps2_inputs, ARRAY_SIZE(ps2_inputs), ps2_outputs, ARRAY_SIZE(ps2_outputs)}, + {ps3_source, false, "ps_2_0", false, ps3_inputs, ARRAY_SIZE(ps3_inputs), ps3_outputs, ARRAY_SIZE(ps3_outputs)}, + {ps4_source, false, "ps_3_0", false, ps4_inputs, ARRAY_SIZE(ps4_inputs), ps3_outputs, ARRAY_SIZE(ps3_outputs)}, };
for (i = 0; i < ARRAY_SIZE(tests); ++i) @@ -700,6 +732,13 @@ static void test_scan_signatures(void) compile_info.source_type = VKD3D_SHADER_SOURCE_HLSL; compile_info.target_type = tests[i].sm4 ? VKD3D_SHADER_TARGET_DXBC_TPF : VKD3D_SHADER_TARGET_D3D_BYTECODE; compile_info.log_level = VKD3D_SHADER_LOG_INFO; + compile_info.options = options; + compile_info.option_count = 1; + + options[0].name = VKD3D_SHADER_COMPILE_OPTION_BACKWARD_COMPATIBILITY; + options[0].value = 0; + if (tests[i].compat) + options[0].value = VKD3D_SHADER_COMPILE_OPTION_BACKCOMPAT_MAP_SEMANTIC_NAMES;
compile_info.next = &hlsl_info; hlsl_info.profile = tests[i].profile;
From: Zebediah Figura zfigura@codeweavers.com
Ported from Wine. --- tests/hlsl_d3d12.c | 198 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+)
diff --git a/tests/hlsl_d3d12.c b/tests/hlsl_d3d12.c index 51010b9f5..a8e4fc9f3 100644 --- a/tests/hlsl_d3d12.c +++ b/tests/hlsl_d3d12.c @@ -19,6 +19,7 @@ #include "config.h" #include "d3d12_crosstest.h" #include "vkd3d_common.h" +#include "vkd3d_d3d12shader.h"
#ifndef D3DERR_INVALIDCALL #define D3DERR_INVALIDCALL 0x8876086c @@ -1316,6 +1317,202 @@ static void test_get_blob_part(void) ok(!refcount, "Got refcount %u.\n", refcount); }
+static void check_signature_element(const D3D12_SIGNATURE_PARAMETER_DESC *desc, + const D3D12_SIGNATURE_PARAMETER_DESC *expect) +{ + ok(!strcmp(desc->SemanticName, expect->SemanticName), "Got name "%s".\n", desc->SemanticName); + ok(desc->SemanticIndex == expect->SemanticIndex, "Got index %u.\n", desc->SemanticIndex); + ok(desc->Register == expect->Register, "Got register %u.\n", desc->Register); + ok(desc->SystemValueType == expect->SystemValueType, "Got sysval %u.\n", desc->SystemValueType); + ok(desc->ComponentType == expect->ComponentType, "Got data type %u.\n", desc->ComponentType); + ok(desc->Mask == expect->Mask, "Got mask %#x.\n", desc->Mask); + todo_if(desc->ReadWriteMask != expect->ReadWriteMask) + ok(desc->ReadWriteMask == expect->ReadWriteMask, "Got used mask %#x.\n", desc->ReadWriteMask); + ok(desc->Stream == expect->Stream, "Got stream %u.\n", desc->Stream); +} + +static void test_signature_reflection(void) +{ + D3D12_SIGNATURE_PARAMETER_DESC desc; + ID3D12ShaderReflection *reflection; + D3D12_SHADER_DESC shader_desc; + ID3D10Blob *code = NULL; + ULONG refcount; + HRESULT hr; + + static const char vs1_source[] = + "void main(\n" + " in float4 a : apple,\n" + " out float4 b : banana2,\n" + " inout float4 c : color,\n" + " inout float4 d : depth,\n" + " inout float4 e : sv_position,\n" + " in uint3 f : fruit,\n" + " inout bool2 g : grape,\n" + " in int h : honeydew,\n" + " in uint i : sv_vertexid)\n" + "{\n" + " b.yw = a.xz;\n" + "}"; + + static const D3D12_SIGNATURE_PARAMETER_DESC vs1_inputs[] = + { + {"apple", 0, 0, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_FLOAT32, 0xf, 0x5}, + {"color", 0, 1, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_FLOAT32, 0xf, 0xf}, + {"depth", 0, 2, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_FLOAT32, 0xf, 0xf}, + {"sv_position", 0, 3, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_FLOAT32, 0xf, 0xf}, + {"fruit", 0, 4, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_UINT32, 0x7}, + {"grape", 0, 5, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_UINT32, 0x3, 0x3}, + {"honeydew", 0, 6, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_SINT32, 0x1}, + {"sv_vertexid", 0, 7, D3D_NAME_VERTEX_ID, D3D_REGISTER_COMPONENT_UINT32, 0x1}, + }; + + static const D3D12_SIGNATURE_PARAMETER_DESC vs1_outputs[] = + { + {"banana", 2, 0, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_FLOAT32, 0xf, 0x5}, + {"color", 0, 1, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_FLOAT32, 0xf}, + {"depth", 0, 2, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_FLOAT32, 0xf}, + {"sv_position", 0, 3, D3D_NAME_POSITION, D3D_REGISTER_COMPONENT_FLOAT32, 0xf}, + {"grape", 0, 4, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_UINT32, 0x3, 0xc}, + }; + + static const char vs2_source[] = + "void main(inout float4 pos : position)\n" + "{\n" + "}"; + + static const D3D12_SIGNATURE_PARAMETER_DESC vs2_inputs[] = + { + {"position", 0, 0, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_FLOAT32, 0xf, 0xf}, + }; + + static const D3D12_SIGNATURE_PARAMETER_DESC vs2_outputs[] = + { + {"position", 0, 0, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_FLOAT32, 0xf}, + }; + + static const D3D12_SIGNATURE_PARAMETER_DESC vs2_legacy_outputs[] = + { + {"SV_Position", 0, 0, D3D_NAME_POSITION, D3D_REGISTER_COMPONENT_FLOAT32, 0xf}, + }; + + static const char ps1_source[] = + "void main(\n" + " in float2 a : apple,\n" + " out float4 b : sv_target2,\n" + " out float c : sv_depth,\n" + " in float4 d : position,\n" + " in float4 e : sv_position)\n" + "{\n" + " b = d;\n" + " c = 0;\n" + "}"; + + static const D3D12_SIGNATURE_PARAMETER_DESC ps1_inputs[] = + { + {"apple", 0, 0, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_FLOAT32, 0x3}, + {"position", 0, 1, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_FLOAT32, 0xf, 0xf}, + {"sv_position", 0, 2, D3D_NAME_POSITION, D3D_REGISTER_COMPONENT_FLOAT32, 0xf}, + }; + + static const D3D12_SIGNATURE_PARAMETER_DESC ps1_outputs[] = + { + {"sv_target", 2, 2, D3D_NAME_TARGET, D3D_REGISTER_COMPONENT_FLOAT32, 0xf}, + {"sv_depth", 0, ~0u, D3D_NAME_DEPTH, D3D_REGISTER_COMPONENT_FLOAT32, 0x1, 0xe}, + }; + + static const char ps2_source[] = + "void main(\n" + " inout float4 a : color2,\n" + " inout float b : depth,\n" + " in float4 c : position)\n" + "{\n" + "}"; + + static const D3D12_SIGNATURE_PARAMETER_DESC ps2_inputs[] = + { + {"color", 2, 0, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_FLOAT32, 0xf, 0xf}, + {"depth", 0, 1, D3D_NAME_UNDEFINED, D3D_REGISTER_COMPONENT_FLOAT32, 0x1, 0x1}, + {"SV_Position", 0, 2, D3D_NAME_POSITION, D3D_REGISTER_COMPONENT_FLOAT32, 0xf}, + }; + + static const D3D12_SIGNATURE_PARAMETER_DESC ps2_outputs[] = + { + {"SV_Target", 2, 2, D3D_NAME_TARGET, D3D_REGISTER_COMPONENT_FLOAT32, 0xf}, + {"SV_Depth", 0, ~0u, D3D_NAME_DEPTH, D3D_REGISTER_COMPONENT_FLOAT32, 0x1, 0xe}, + }; + + static const char cs1_source[] = + "[numthreads(1, 1, 1)]\n" + "void main(in uint a : sv_dispatchthreadid)\n" + "{\n" + "}"; + + static const struct + { + const char *source; + const char *target; + bool compat; + const D3D12_SIGNATURE_PARAMETER_DESC *inputs; + unsigned int input_count; + const D3D12_SIGNATURE_PARAMETER_DESC *outputs; + unsigned int output_count; + } + tests[] = + { + {vs1_source, "vs_4_0", false, vs1_inputs, ARRAY_SIZE(vs1_inputs), vs1_outputs, ARRAY_SIZE(vs1_outputs)}, + {vs1_source, "vs_4_0", true, vs1_inputs, ARRAY_SIZE(vs1_inputs), vs1_outputs, ARRAY_SIZE(vs1_outputs)}, + {vs2_source, "vs_4_0", false, vs2_inputs, ARRAY_SIZE(vs2_inputs), vs2_outputs, ARRAY_SIZE(vs2_outputs)}, + {vs2_source, "vs_4_0", true, vs2_inputs, ARRAY_SIZE(vs2_inputs), vs2_legacy_outputs, ARRAY_SIZE(vs2_legacy_outputs)}, + {ps1_source, "ps_4_0", false, ps1_inputs, ARRAY_SIZE(ps1_inputs), ps1_outputs, ARRAY_SIZE(ps1_outputs)}, + {ps2_source, "ps_4_0", true, ps2_inputs, ARRAY_SIZE(ps2_inputs), ps2_outputs, ARRAY_SIZE(ps2_outputs)}, + {cs1_source, "cs_5_0", false, NULL, 0, NULL, 0}, + }; + + for (unsigned int i = 0; i < ARRAY_SIZE(tests); ++i) + { + vkd3d_test_push_context("Test %u", i); + + code = compile_shader_flags(tests[i].source, tests[i].target, + tests[i].compat ? D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY : 0); + + 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.InputParameters == tests[i].input_count, + "Got %u input parameters.\n", shader_desc.InputParameters); + ok(shader_desc.OutputParameters == tests[i].output_count, + "Got %u output parameters.\n", shader_desc.OutputParameters); + + for (unsigned int j = 0; j < shader_desc.InputParameters; ++j) + { + vkd3d_test_push_context("Input %u", j); + hr = reflection->lpVtbl->GetInputParameterDesc(reflection, j, &desc); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + check_signature_element(&desc, &tests[i].inputs[j]); + vkd3d_test_pop_context(); + } + + for (unsigned int j = 0; j < shader_desc.OutputParameters; ++j) + { + vkd3d_test_push_context("Output %u", j); + hr = reflection->lpVtbl->GetOutputParameterDesc(reflection, j, &desc); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + check_signature_element(&desc, &tests[i].outputs[j]); + vkd3d_test_pop_context(); + } + + ID3D10Blob_Release(code); + refcount = reflection->lpVtbl->Release(reflection); + ok(!refcount, "Got unexpected refcount %u.\n", refcount); + + vkd3d_test_pop_context(); + } +} + START_TEST(hlsl_d3d12) { parse_args(argc, argv); @@ -1326,4 +1523,5 @@ START_TEST(hlsl_d3d12) run_test(test_thread_id); run_test(test_create_blob); run_test(test_get_blob_part); + run_test(test_signature_reflection); }
Alright, I've redone the relevant parts of this series implementing reflection from scratch. I'll try to design a reasonable API for constant buffers.
This merge request was approved by Giovanni Mascellani.
This merge request was approved by Giovanni Mascellani.
Approved, as in "I don't have strong opinions on this, but the code you wrote doesn't look particularly evil". The CI pipeline fails in seemingly minor ways, though.