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.
-- v4: tests: Test signature reflection via D3DReflect().
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. --- include/vkd3d_d3dcompiler.h | 1 + tests/hlsl_d3d12.c | 198 ++++++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+)
diff --git a/include/vkd3d_d3dcompiler.h b/include/vkd3d_d3dcompiler.h index c78cf25b9..1975f4f98 100644 --- a/include/vkd3d_d3dcompiler.h +++ b/include/vkd3d_d3dcompiler.h @@ -86,6 +86,7 @@ HRESULT WINAPI D3DGetInputSignatureBlob(const void *data, SIZE_T data_size, ID3D HRESULT WINAPI D3DGetOutputSignatureBlob(const void *data, SIZE_T data_size, ID3DBlob **blob); HRESULT WINAPI D3DPreprocess(const void *data, SIZE_T size, const char *filename, const D3D_SHADER_MACRO *macros, ID3DInclude *include, ID3DBlob **shader, ID3DBlob **error_messages); +HRESULT WINAPI D3DReflect(const void *data, SIZE_T data_size, REFIID iid, void **reflection); HRESULT WINAPI D3DStripShader(const void *data, SIZE_T data_size, UINT flags, ID3DBlob **blob);
#endif /* __D3DCOMPILER_H__ */ diff --git a/tests/hlsl_d3d12.c b/tests/hlsl_d3d12.c index 51010b9f5..827704985 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; + unsigned int 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); }