|
@@ -24,8 +24,10 @@
|
|
|
#include "dxc/Support/FileIOHelper.h"
|
|
|
#include "dxc/Support/dxcapi.impl.h"
|
|
|
#include "dxc/HLSL/DxilRuntimeReflection.inl"
|
|
|
+#include "dxc/HLSL/DxilFunctionProps.h"
|
|
|
|
|
|
#include <unordered_set>
|
|
|
+#include "llvm/ADT/SetVector.h"
|
|
|
|
|
|
#include "dxc/dxcapi.h"
|
|
|
|
|
@@ -69,39 +71,60 @@ public:
|
|
|
|
|
|
class CShaderReflectionConstantBuffer;
|
|
|
class CShaderReflectionType;
|
|
|
-class DxilShaderReflection : public ID3D12ShaderReflection {
|
|
|
-private:
|
|
|
- DXC_MICROCOM_TM_REF_FIELDS()
|
|
|
+
|
|
|
+enum class PublicAPI { D3D12 = 0, D3D11_47 = 1, D3D11_43 = 2 };
|
|
|
+
|
|
|
+class DxilModuleReflection {
|
|
|
+public:
|
|
|
CComPtr<IDxcBlob> m_pContainer;
|
|
|
LLVMContext Context;
|
|
|
std::unique_ptr<Module> m_pModule; // Must come after LLVMContext, otherwise unique_ptr will over-delete.
|
|
|
DxilModule *m_pDxilModule = nullptr;
|
|
|
std::vector<CShaderReflectionConstantBuffer> m_CBs;
|
|
|
std::vector<D3D12_SHADER_INPUT_BIND_DESC> m_Resources;
|
|
|
+ std::vector<std::unique_ptr<CShaderReflectionType>> m_Types;
|
|
|
+ void CreateReflectionObjects();
|
|
|
+ void CreateReflectionObjectForResource(DxilResourceBase *R);
|
|
|
+
|
|
|
+ HRESULT LoadModule(IDxcBlob *pBlob, const DxilPartHeader *pPart);
|
|
|
+
|
|
|
+ // Common code
|
|
|
+ ID3D12ShaderReflectionConstantBuffer* _GetConstantBufferByIndex(UINT Index);
|
|
|
+ ID3D12ShaderReflectionConstantBuffer* _GetConstantBufferByName(LPCSTR Name);
|
|
|
+
|
|
|
+ HRESULT _GetResourceBindingDesc(UINT ResourceIndex,
|
|
|
+ _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc,
|
|
|
+ PublicAPI api = PublicAPI::D3D12);
|
|
|
+
|
|
|
+ ID3D12ShaderReflectionVariable* _GetVariableByName(LPCSTR Name);
|
|
|
+
|
|
|
+ HRESULT _GetResourceBindingDescByName(LPCSTR Name,
|
|
|
+ D3D12_SHADER_INPUT_BIND_DESC *pDesc,
|
|
|
+ PublicAPI api = PublicAPI::D3D12);
|
|
|
+};
|
|
|
+
|
|
|
+class DxilShaderReflection : public DxilModuleReflection, public ID3D12ShaderReflection {
|
|
|
+private:
|
|
|
+ DXC_MICROCOM_TM_REF_FIELDS()
|
|
|
std::vector<D3D12_SIGNATURE_PARAMETER_DESC> m_InputSignature;
|
|
|
std::vector<D3D12_SIGNATURE_PARAMETER_DESC> m_OutputSignature;
|
|
|
std::vector<D3D12_SIGNATURE_PARAMETER_DESC> m_PatchConstantSignature;
|
|
|
std::vector<std::unique_ptr<char[]>> m_UpperCaseNames;
|
|
|
- std::vector<std::unique_ptr<CShaderReflectionType>> m_Types;
|
|
|
- void CreateReflectionObjects();
|
|
|
void SetCBufferUsage();
|
|
|
- void CreateReflectionObjectForResource(DxilResourceBase *R);
|
|
|
void CreateReflectionObjectsForSignature(
|
|
|
const DxilSignature &Sig,
|
|
|
std::vector<D3D12_SIGNATURE_PARAMETER_DESC> &Descs);
|
|
|
LPCSTR CreateUpperCase(LPCSTR pValue);
|
|
|
void MarkUsedSignatureElements();
|
|
|
public:
|
|
|
- enum class PublicAPI { D3D12 = 0, D3D11_47 = 1, D3D11_43 = 2 };
|
|
|
PublicAPI m_PublicAPI;
|
|
|
void SetPublicAPI(PublicAPI value) { m_PublicAPI = value; }
|
|
|
static PublicAPI IIDToAPI(REFIID iid) {
|
|
|
- DxilShaderReflection::PublicAPI api =
|
|
|
- DxilShaderReflection::PublicAPI::D3D12;
|
|
|
+ PublicAPI api = PublicAPI::D3D12;
|
|
|
if (IsEqualIID(IID_ID3D11ShaderReflection_43, iid))
|
|
|
- api = DxilShaderReflection::PublicAPI::D3D11_43;
|
|
|
+ api = PublicAPI::D3D11_43;
|
|
|
else if (IsEqualIID(IID_ID3D11ShaderReflection_47, iid))
|
|
|
- api = DxilShaderReflection::PublicAPI::D3D11_47;
|
|
|
+ api = PublicAPI::D3D11_47;
|
|
|
return api;
|
|
|
}
|
|
|
DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL()
|
|
@@ -163,6 +186,34 @@ public:
|
|
|
STDMETHODIMP_(UINT64) GetRequiresFlags(THIS);
|
|
|
};
|
|
|
|
|
|
+class CFunctionReflection;
|
|
|
+class DxilLibraryReflection : public DxilModuleReflection, public ID3D12LibraryReflection {
|
|
|
+private:
|
|
|
+ DXC_MICROCOM_TM_REF_FIELDS()
|
|
|
+
|
|
|
+ typedef MapVector<StringRef, std::unique_ptr<CFunctionReflection> > FunctionMap;
|
|
|
+ typedef DenseMap<const Function*, CFunctionReflection*> FunctionsByPtr;
|
|
|
+ FunctionMap m_FunctionMap;
|
|
|
+ FunctionsByPtr m_FunctionsByPtr;
|
|
|
+
|
|
|
+ void AddResourceUseToFunctions(DxilResourceBase &resource, unsigned resIndex);
|
|
|
+ void AddResourceDependencies();
|
|
|
+
|
|
|
+public:
|
|
|
+ DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL()
|
|
|
+ DXC_MICROCOM_TM_CTOR(DxilLibraryReflection)
|
|
|
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) {
|
|
|
+ return DoBasicQueryInterface<ID3D12LibraryReflection>(this, iid, ppvObject);
|
|
|
+ }
|
|
|
+
|
|
|
+ HRESULT Load(IDxcBlob *pBlob, const DxilPartHeader *pPart);
|
|
|
+
|
|
|
+ // ID3D12LibraryReflection
|
|
|
+ STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_LIBRARY_DESC * pDesc);
|
|
|
+
|
|
|
+ STDMETHOD_(ID3D12FunctionReflection *, GetFunctionByIndex)(THIS_ _In_ INT FunctionIndex);
|
|
|
+};
|
|
|
+
|
|
|
_Use_decl_annotations_
|
|
|
HRESULT DxilContainerReflection::Load(IDxcBlob *pContainer) {
|
|
|
if (pContainer == nullptr) {
|
|
@@ -245,13 +296,28 @@ HRESULT DxilContainerReflection::GetPartReflection(UINT32 idx, REFIID iid, void
|
|
|
|
|
|
DxcThreadMalloc TM(m_pMalloc);
|
|
|
HRESULT hr = S_OK;
|
|
|
- CComPtr<DxilShaderReflection> pReflection = DxilShaderReflection::Alloc(m_pMalloc);
|
|
|
- IFCOOM(pReflection.p);
|
|
|
- DxilShaderReflection::PublicAPI api = DxilShaderReflection::IIDToAPI(iid);
|
|
|
- pReflection->SetPublicAPI(api);
|
|
|
+ const DxilProgramHeader *pProgramHeader =
|
|
|
+ reinterpret_cast<const DxilProgramHeader*>(GetDxilPartData(pPart));
|
|
|
+ if (!IsValidDxilProgramHeader(pProgramHeader, pPart->PartSize)) {
|
|
|
+ return E_INVALIDARG;
|
|
|
+ }
|
|
|
+
|
|
|
+ DXIL::ShaderKind SK = GetVersionShaderType(pProgramHeader->ProgramVersion);
|
|
|
+ if (SK == DXIL::ShaderKind::Library) {
|
|
|
+ CComPtr<DxilLibraryReflection> pReflection = DxilLibraryReflection::Alloc(m_pMalloc);
|
|
|
+ IFCOOM(pReflection.p);
|
|
|
+ IFC(pReflection->Load(m_container, pPart));
|
|
|
+ IFC(pReflection.p->QueryInterface(iid, ppvObject));
|
|
|
+ } else {
|
|
|
+ CComPtr<DxilShaderReflection> pReflection = DxilShaderReflection::Alloc(m_pMalloc);
|
|
|
+ IFCOOM(pReflection.p);
|
|
|
+ PublicAPI api = DxilShaderReflection::IIDToAPI(iid);
|
|
|
+ pReflection->SetPublicAPI(api);
|
|
|
+
|
|
|
+ IFC(pReflection->Load(m_container, pPart));
|
|
|
+ IFC(pReflection.p->QueryInterface(iid, ppvObject));
|
|
|
+ }
|
|
|
|
|
|
- IFC(pReflection->Load(m_container, pPart));
|
|
|
- IFC(pReflection.p->QueryInterface(iid, ppvObject));
|
|
|
Cleanup:
|
|
|
return hr;
|
|
|
}
|
|
@@ -411,6 +477,30 @@ class CInvalidSRConstantBuffer : public ID3D12ShaderReflectionConstantBuffer {
|
|
|
};
|
|
|
static CInvalidSRConstantBuffer g_InvalidSRConstantBuffer;
|
|
|
|
|
|
+class CInvalidFunctionParameter : public ID3D12FunctionParameterReflection {
|
|
|
+ STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_PARAMETER_DESC * pDesc) { return E_FAIL; }
|
|
|
+};
|
|
|
+CInvalidFunctionParameter g_InvalidFunctionParameter;
|
|
|
+
|
|
|
+class CInvalidFunction : public ID3D12FunctionReflection {
|
|
|
+ STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_FUNCTION_DESC * pDesc) { return E_FAIL; }
|
|
|
+
|
|
|
+ STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByIndex)(THIS_ _In_ UINT BufferIndex) { return &g_InvalidSRConstantBuffer; }
|
|
|
+ STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByName)(THIS_ _In_ LPCSTR Name) { return &g_InvalidSRConstantBuffer; }
|
|
|
+
|
|
|
+ STDMETHOD(GetResourceBindingDesc)(THIS_ _In_ UINT ResourceIndex,
|
|
|
+ _Out_ D3D12_SHADER_INPUT_BIND_DESC * pDesc) { return E_FAIL; }
|
|
|
+
|
|
|
+ STDMETHOD_(ID3D12ShaderReflectionVariable *, GetVariableByName)(THIS_ _In_ LPCSTR Name) { return nullptr; }
|
|
|
+
|
|
|
+ STDMETHOD(GetResourceBindingDescByName)(THIS_ _In_ LPCSTR Name,
|
|
|
+ _Out_ D3D12_SHADER_INPUT_BIND_DESC * pDesc) { return E_FAIL; }
|
|
|
+
|
|
|
+ // Use D3D_RETURN_PARAMETER_INDEX to get description of the return value.
|
|
|
+ STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter)(THIS_ _In_ INT ParameterIndex) { return &g_InvalidFunctionParameter; }
|
|
|
+};
|
|
|
+CInvalidFunction g_InvalidFunction;
|
|
|
+
|
|
|
void CShaderReflectionVariable::Initialize(
|
|
|
CShaderReflectionConstantBuffer *pBuffer, D3D12_SHADER_VARIABLE_DESC *pDesc,
|
|
|
CShaderReflectionType *pType, BYTE *pDefaultValue) {
|
|
@@ -1229,7 +1319,7 @@ static UINT ResourceToFlags(DxilResourceBase *RB) {
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
-void DxilShaderReflection::CreateReflectionObjectForResource(DxilResourceBase *RB) {
|
|
|
+void DxilModuleReflection::CreateReflectionObjectForResource(DxilResourceBase *RB) {
|
|
|
DxilResourceBase::Class C = RB->GetClass();
|
|
|
DxilResource *R =
|
|
|
(C == DXIL::ResourceClass::UAV || C == DXIL::ResourceClass::SRV)
|
|
@@ -1412,7 +1502,7 @@ void DxilShaderReflection::SetCBufferUsage() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void DxilShaderReflection::CreateReflectionObjects() {
|
|
|
+void DxilModuleReflection::CreateReflectionObjects() {
|
|
|
DXASSERT_NOMSG(m_pDxilModule != nullptr);
|
|
|
|
|
|
// Create constant buffers, resources and signatures.
|
|
@@ -1421,8 +1511,6 @@ void DxilShaderReflection::CreateReflectionObjects() {
|
|
|
rcb.Initialize(*m_pDxilModule, *(cb.get()), m_Types);
|
|
|
m_CBs.push_back(std::move(rcb));
|
|
|
}
|
|
|
- // Set cbuf usage.
|
|
|
- SetCBufferUsage();
|
|
|
|
|
|
// TODO: add tbuffers into m_CBs
|
|
|
for (auto && uav : m_pDxilModule->GetUAVs()) {
|
|
@@ -1455,12 +1543,6 @@ void DxilShaderReflection::CreateReflectionObjects() {
|
|
|
for (auto && uavRes : m_pDxilModule->GetUAVs()) {
|
|
|
CreateReflectionObjectForResource(uavRes.get());
|
|
|
}
|
|
|
-
|
|
|
- // Populate input/output/patch constant signatures.
|
|
|
- CreateReflectionObjectsForSignature(m_pDxilModule->GetInputSignature(), m_InputSignature);
|
|
|
- CreateReflectionObjectsForSignature(m_pDxilModule->GetOutputSignature(), m_OutputSignature);
|
|
|
- CreateReflectionObjectsForSignature(m_pDxilModule->GetPatchConstantSignature(), m_PatchConstantSignature);
|
|
|
- MarkUsedSignatureElements();
|
|
|
}
|
|
|
|
|
|
static D3D_REGISTER_COMPONENT_TYPE CompTypeToRegisterComponentType(CompType CT) {
|
|
@@ -1635,8 +1717,8 @@ LPCSTR DxilShaderReflection::CreateUpperCase(LPCSTR pValue) {
|
|
|
return m_UpperCaseNames.back().get();
|
|
|
}
|
|
|
|
|
|
-HRESULT DxilShaderReflection::Load(IDxcBlob *pBlob,
|
|
|
- const DxilPartHeader *pPart) {
|
|
|
+HRESULT DxilModuleReflection::LoadModule(IDxcBlob *pBlob,
|
|
|
+ const DxilPartHeader *pPart) {
|
|
|
DXASSERT_NOMSG(pBlob != nullptr);
|
|
|
DXASSERT_NOMSG(pPart != nullptr);
|
|
|
m_pContainer = pBlob;
|
|
@@ -1665,6 +1747,24 @@ HRESULT DxilShaderReflection::Load(IDxcBlob *pBlob,
|
|
|
CATCH_CPP_RETURN_HRESULT();
|
|
|
};
|
|
|
|
|
|
+HRESULT DxilShaderReflection::Load(IDxcBlob *pBlob,
|
|
|
+ const DxilPartHeader *pPart) {
|
|
|
+ IFR(LoadModule(pBlob, pPart));
|
|
|
+
|
|
|
+ try {
|
|
|
+ // Set cbuf usage.
|
|
|
+ SetCBufferUsage();
|
|
|
+
|
|
|
+ // Populate input/output/patch constant signatures.
|
|
|
+ CreateReflectionObjectsForSignature(m_pDxilModule->GetInputSignature(), m_InputSignature);
|
|
|
+ CreateReflectionObjectsForSignature(m_pDxilModule->GetOutputSignature(), m_OutputSignature);
|
|
|
+ CreateReflectionObjectsForSignature(m_pDxilModule->GetPatchConstantSignature(), m_PatchConstantSignature);
|
|
|
+ MarkUsedSignatureElements();
|
|
|
+ return S_OK;
|
|
|
+ }
|
|
|
+ CATCH_CPP_RETURN_HRESULT();
|
|
|
+}
|
|
|
+
|
|
|
_Use_decl_annotations_
|
|
|
HRESULT DxilShaderReflection::GetDesc(D3D12_SHADER_DESC *pDesc) {
|
|
|
IFR(ZeroMemoryToOut(pDesc));
|
|
@@ -1789,6 +1889,9 @@ void DxilShaderReflection::MarkUsedSignatureElements() {
|
|
|
|
|
|
_Use_decl_annotations_
|
|
|
ID3D12ShaderReflectionConstantBuffer* DxilShaderReflection::GetConstantBufferByIndex(UINT Index) {
|
|
|
+ return DxilModuleReflection::_GetConstantBufferByIndex(Index);
|
|
|
+}
|
|
|
+ID3D12ShaderReflectionConstantBuffer* DxilModuleReflection::_GetConstantBufferByIndex(UINT Index) {
|
|
|
if (Index >= m_CBs.size()) {
|
|
|
return &g_InvalidSRConstantBuffer;
|
|
|
}
|
|
@@ -1797,6 +1900,9 @@ ID3D12ShaderReflectionConstantBuffer* DxilShaderReflection::GetConstantBufferByI
|
|
|
|
|
|
_Use_decl_annotations_
|
|
|
ID3D12ShaderReflectionConstantBuffer* DxilShaderReflection::GetConstantBufferByName(LPCSTR Name) {
|
|
|
+ return DxilModuleReflection::_GetConstantBufferByName(Name);
|
|
|
+}
|
|
|
+ID3D12ShaderReflectionConstantBuffer* DxilModuleReflection::_GetConstantBufferByName(LPCSTR Name) {
|
|
|
if (!Name) {
|
|
|
return &g_InvalidSRConstantBuffer;
|
|
|
}
|
|
@@ -1811,9 +1917,13 @@ ID3D12ShaderReflectionConstantBuffer* DxilShaderReflection::GetConstantBufferByN
|
|
|
_Use_decl_annotations_
|
|
|
HRESULT DxilShaderReflection::GetResourceBindingDesc(UINT ResourceIndex,
|
|
|
_Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) {
|
|
|
+ return DxilModuleReflection::_GetResourceBindingDesc(ResourceIndex, pDesc, m_PublicAPI);
|
|
|
+}
|
|
|
+HRESULT DxilModuleReflection::_GetResourceBindingDesc(UINT ResourceIndex,
|
|
|
+ _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc, PublicAPI api) {
|
|
|
IFRBOOL(pDesc != nullptr, E_INVALIDARG);
|
|
|
IFRBOOL(ResourceIndex < m_Resources.size(), E_INVALIDARG);
|
|
|
- if (m_PublicAPI != PublicAPI::D3D12) {
|
|
|
+ if (api != PublicAPI::D3D12) {
|
|
|
memcpy(pDesc, &m_Resources[ResourceIndex], sizeof(D3D11_SHADER_INPUT_BIND_DESC));
|
|
|
}
|
|
|
else {
|
|
@@ -1869,6 +1979,9 @@ HRESULT DxilShaderReflection::GetPatchConstantParameterDesc(UINT ParameterIndex,
|
|
|
|
|
|
_Use_decl_annotations_
|
|
|
ID3D12ShaderReflectionVariable* DxilShaderReflection::GetVariableByName(LPCSTR Name) {
|
|
|
+ return DxilModuleReflection::_GetVariableByName(Name);
|
|
|
+}
|
|
|
+ID3D12ShaderReflectionVariable* DxilModuleReflection::_GetVariableByName(LPCSTR Name) {
|
|
|
if (Name != nullptr) {
|
|
|
// Iterate through all cbuffers to find the variable.
|
|
|
for (UINT i = 0; i < m_CBs.size(); i++) {
|
|
@@ -1885,11 +1998,15 @@ ID3D12ShaderReflectionVariable* DxilShaderReflection::GetVariableByName(LPCSTR N
|
|
|
_Use_decl_annotations_
|
|
|
HRESULT DxilShaderReflection::GetResourceBindingDescByName(LPCSTR Name,
|
|
|
D3D12_SHADER_INPUT_BIND_DESC *pDesc) {
|
|
|
+ return DxilModuleReflection::_GetResourceBindingDescByName(Name, pDesc, m_PublicAPI);
|
|
|
+}
|
|
|
+HRESULT DxilModuleReflection::_GetResourceBindingDescByName(LPCSTR Name,
|
|
|
+ D3D12_SHADER_INPUT_BIND_DESC *pDesc, PublicAPI api) {
|
|
|
IFRBOOL(Name != nullptr, E_INVALIDARG);
|
|
|
|
|
|
for (UINT i = 0; i < m_Resources.size(); i++) {
|
|
|
if (strcmp(m_Resources[i].Name, Name) == 0) {
|
|
|
- if (m_PublicAPI != PublicAPI::D3D12) {
|
|
|
+ if (api != PublicAPI::D3D12) {
|
|
|
memcpy(pDesc, &m_Resources[i], sizeof(D3D11_SHADER_INPUT_BIND_DESC));
|
|
|
}
|
|
|
else {
|
|
@@ -1951,3 +2068,238 @@ UINT64 DxilShaderReflection::GetRequiresFlags() {
|
|
|
if (features & ShaderFeatureInfo_ViewportAndRTArrayIndexFromAnyShaderFeedingRasterizer) result |= D3D_SHADER_REQUIRES_VIEWPORT_AND_RT_ARRAY_INDEX_FROM_ANY_SHADER_FEEDING_RASTERIZER;
|
|
|
return result;
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+// ID3D12FunctionReflection
|
|
|
+
|
|
|
+class CFunctionReflection : public ID3D12FunctionReflection {
|
|
|
+protected:
|
|
|
+ DxilLibraryReflection * m_pLibraryReflection = nullptr;
|
|
|
+ const Function *m_pFunction;
|
|
|
+ const DxilFunctionProps *m_pProps; // nullptr if non-shader library function or patch constant function
|
|
|
+ std::string m_Name;
|
|
|
+ typedef SmallSetVector<UINT32, 8> ResourceUseSet;
|
|
|
+ ResourceUseSet m_UsedResources;
|
|
|
+ ResourceUseSet m_UsedCBs;
|
|
|
+
|
|
|
+public:
|
|
|
+ void Initialize(DxilLibraryReflection* pLibraryReflection, Function *pFunction) {
|
|
|
+ DXASSERT_NOMSG(pLibraryReflection);
|
|
|
+ DXASSERT_NOMSG(pFunction);
|
|
|
+ m_pLibraryReflection = pLibraryReflection;
|
|
|
+ m_pFunction = pFunction;
|
|
|
+
|
|
|
+ const DxilModule &M = *m_pLibraryReflection->m_pDxilModule;
|
|
|
+ m_Name = m_pFunction->getName().str();
|
|
|
+ m_pProps = nullptr;
|
|
|
+ if (M.HasDxilFunctionProps(m_pFunction)) {
|
|
|
+ m_pProps = &M.GetDxilFunctionProps(m_pFunction);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ void AddResourceReference(UINT resIndex) {
|
|
|
+ m_UsedResources.insert(resIndex);
|
|
|
+ }
|
|
|
+ void AddCBReference(UINT cbIndex) {
|
|
|
+ m_UsedCBs.insert(cbIndex);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ID3D12FunctionReflection
|
|
|
+ STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_FUNCTION_DESC * pDesc);
|
|
|
+
|
|
|
+ // BufferIndex relative to used constant buffers here
|
|
|
+ STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByIndex)(THIS_ _In_ UINT BufferIndex);
|
|
|
+ STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByName)(THIS_ _In_ LPCSTR Name);
|
|
|
+
|
|
|
+ STDMETHOD(GetResourceBindingDesc)(THIS_ _In_ UINT ResourceIndex,
|
|
|
+ _Out_ D3D12_SHADER_INPUT_BIND_DESC * pDesc);
|
|
|
+
|
|
|
+ STDMETHOD_(ID3D12ShaderReflectionVariable *, GetVariableByName)(THIS_ _In_ LPCSTR Name);
|
|
|
+
|
|
|
+ STDMETHOD(GetResourceBindingDescByName)(THIS_ _In_ LPCSTR Name,
|
|
|
+ _Out_ D3D12_SHADER_INPUT_BIND_DESC * pDesc);
|
|
|
+
|
|
|
+ // Use D3D_RETURN_PARAMETER_INDEX to get description of the return value.
|
|
|
+ STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter)(THIS_ _In_ INT ParameterIndex) {
|
|
|
+ return &g_InvalidFunctionParameter;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+_Use_decl_annotations_
|
|
|
+HRESULT CFunctionReflection::GetDesc(D3D12_FUNCTION_DESC *pDesc) {
|
|
|
+ IFR(ZeroMemoryToOut(pDesc));
|
|
|
+
|
|
|
+ const ShaderModel* pSM = m_pLibraryReflection->m_pDxilModule->GetShaderModel();
|
|
|
+ DXIL::ShaderKind kind = DXIL::ShaderKind::Library;
|
|
|
+ if (m_pProps) {
|
|
|
+ kind = m_pProps->shaderKind;
|
|
|
+ }
|
|
|
+ pDesc->Version = EncodeVersion(kind, pSM->GetMajor(), pSM->GetMinor());
|
|
|
+
|
|
|
+ //Unset: LPCSTR Creator; // Creator string
|
|
|
+ //Unset: UINT Flags; // Shader compilation/parse flags
|
|
|
+
|
|
|
+ pDesc->ConstantBuffers = (UINT)m_UsedCBs.size();
|
|
|
+ pDesc->BoundResources = (UINT)m_UsedResources.size();
|
|
|
+
|
|
|
+ //Unset: UINT InstructionCount; // Number of emitted instructions
|
|
|
+ //Unset: UINT TempRegisterCount; // Number of temporary registers used
|
|
|
+ //Unset: UINT TempArrayCount; // Number of temporary arrays used
|
|
|
+ //Unset: UINT DefCount; // Number of constant defines
|
|
|
+ //Unset: UINT DclCount; // Number of declarations (input + output)
|
|
|
+ //Unset: UINT TextureNormalInstructions; // Number of non-categorized texture instructions
|
|
|
+ //Unset: UINT TextureLoadInstructions; // Number of texture load instructions
|
|
|
+ //Unset: UINT TextureCompInstructions; // Number of texture comparison instructions
|
|
|
+ //Unset: UINT TextureBiasInstructions; // Number of texture bias instructions
|
|
|
+ //Unset: UINT TextureGradientInstructions; // Number of texture gradient instructions
|
|
|
+ //Unset: UINT FloatInstructionCount; // Number of floating point arithmetic instructions used
|
|
|
+ //Unset: UINT IntInstructionCount; // Number of signed integer arithmetic instructions used
|
|
|
+ //Unset: UINT UintInstructionCount; // Number of unsigned integer arithmetic instructions used
|
|
|
+ //Unset: UINT StaticFlowControlCount; // Number of static flow control instructions used
|
|
|
+ //Unset: UINT DynamicFlowControlCount; // Number of dynamic flow control instructions used
|
|
|
+ //Unset: UINT MacroInstructionCount; // Number of macro instructions used
|
|
|
+ //Unset: UINT ArrayInstructionCount; // Number of array instructions used
|
|
|
+ //Unset: UINT MovInstructionCount; // Number of mov instructions used
|
|
|
+ //Unset: UINT MovcInstructionCount; // Number of movc instructions used
|
|
|
+ //Unset: UINT ConversionInstructionCount; // Number of type conversion instructions used
|
|
|
+ //Unset: UINT BitwiseInstructionCount; // Number of bitwise arithmetic instructions used
|
|
|
+ //Unset: D3D_FEATURE_LEVEL MinFeatureLevel; // Min target of the function byte code
|
|
|
+ //Unset: UINT64 RequiredFeatureFlags; // Required feature flags
|
|
|
+
|
|
|
+ pDesc->Name = m_Name.c_str();
|
|
|
+
|
|
|
+ //Unset: INT FunctionParameterCount; // Number of logical parameters in the function signature (not including return)
|
|
|
+ //Unset: BOOL HasReturn; // TRUE, if function returns a value, false - it is a subroutine
|
|
|
+ //Unset: BOOL Has10Level9VertexShader; // TRUE, if there is a 10L9 VS blob
|
|
|
+ //Unset: BOOL Has10Level9PixelShader; // TRUE, if there is a 10L9 PS blob
|
|
|
+ return S_OK;
|
|
|
+}
|
|
|
+
|
|
|
+// BufferIndex is relative to used constant buffers here
|
|
|
+ID3D12ShaderReflectionConstantBuffer *CFunctionReflection::GetConstantBufferByIndex(UINT BufferIndex) {
|
|
|
+ if (BufferIndex >= m_UsedCBs.size())
|
|
|
+ return &g_InvalidSRConstantBuffer;
|
|
|
+ return m_pLibraryReflection->_GetConstantBufferByIndex(m_UsedCBs[BufferIndex]);
|
|
|
+}
|
|
|
+
|
|
|
+ID3D12ShaderReflectionConstantBuffer *CFunctionReflection::GetConstantBufferByName(LPCSTR Name) {
|
|
|
+ return m_pLibraryReflection->_GetConstantBufferByName(Name);
|
|
|
+}
|
|
|
+
|
|
|
+HRESULT CFunctionReflection::GetResourceBindingDesc(UINT ResourceIndex,
|
|
|
+ D3D12_SHADER_INPUT_BIND_DESC * pDesc) {
|
|
|
+ if (ResourceIndex >= m_UsedResources.size())
|
|
|
+ return E_INVALIDARG;
|
|
|
+ return m_pLibraryReflection->_GetResourceBindingDesc(m_UsedResources[ResourceIndex], pDesc);
|
|
|
+}
|
|
|
+
|
|
|
+ID3D12ShaderReflectionVariable * CFunctionReflection::GetVariableByName(LPCSTR Name) {
|
|
|
+ return m_pLibraryReflection->_GetVariableByName(Name);
|
|
|
+}
|
|
|
+
|
|
|
+HRESULT CFunctionReflection::GetResourceBindingDescByName(LPCSTR Name,
|
|
|
+ D3D12_SHADER_INPUT_BIND_DESC * pDesc) {
|
|
|
+ return m_pLibraryReflection->_GetResourceBindingDescByName(Name, pDesc);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// DxilLibraryReflection
|
|
|
+
|
|
|
+// From DxilContainerAssembler:
|
|
|
+static llvm::Function *FindUsingFunction(llvm::Value *User) {
|
|
|
+ if (llvm::Instruction *I = dyn_cast<llvm::Instruction>(User)) {
|
|
|
+ // Instruction should be inside a basic block, which is in a function
|
|
|
+ return cast<llvm::Function>(I->getParent()->getParent());
|
|
|
+ }
|
|
|
+ // User can be either instruction, constant, or operator. But User is an
|
|
|
+ // operator only if constant is a scalar value, not resource pointer.
|
|
|
+ llvm::Constant *CU = cast<llvm::Constant>(User);
|
|
|
+ if (!CU->user_empty())
|
|
|
+ return FindUsingFunction(*CU->user_begin());
|
|
|
+ else
|
|
|
+ return nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+void DxilLibraryReflection::AddResourceUseToFunctions(DxilResourceBase &resource, unsigned resIndex) {
|
|
|
+ Constant *var = resource.GetGlobalSymbol();
|
|
|
+ if (var) {
|
|
|
+ for (auto user : var->users()) {
|
|
|
+ // Find the function.
|
|
|
+ if (llvm::Function *F = FindUsingFunction(user)) {
|
|
|
+ auto funcReflector = m_FunctionsByPtr[F];
|
|
|
+ funcReflector->AddResourceReference(resIndex);
|
|
|
+ if (resource.GetClass() == DXIL::ResourceClass::CBuffer) {
|
|
|
+ funcReflector->AddCBReference(resource.GetID());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void DxilLibraryReflection::AddResourceDependencies() {
|
|
|
+ for (auto &F : m_pModule->functions()) {
|
|
|
+ if (F.isDeclaration())
|
|
|
+ continue;
|
|
|
+ auto &func = m_FunctionMap[F.getName().str()];
|
|
|
+ DXASSERT(!func.get(), "otherwise duplicate named functions");
|
|
|
+ func.reset(new CFunctionReflection());
|
|
|
+ func->Initialize(this, &F);
|
|
|
+ m_FunctionsByPtr[&F] = func.get();
|
|
|
+ }
|
|
|
+ UINT resIndex = 0;
|
|
|
+ for (auto &resource : m_Resources) {
|
|
|
+ switch (resource.Type) {
|
|
|
+ case D3D_SIT_CBUFFER:
|
|
|
+ AddResourceUseToFunctions(m_pDxilModule->GetCBuffer(resource.uID), resIndex);
|
|
|
+ break;
|
|
|
+ case D3D_SIT_TBUFFER: // TODO: Handle when TBuffers are added to CB list
|
|
|
+ case D3D_SIT_TEXTURE:
|
|
|
+ case D3D_SIT_STRUCTURED:
|
|
|
+ case D3D_SIT_BYTEADDRESS:
|
|
|
+ AddResourceUseToFunctions(m_pDxilModule->GetSRV(resource.uID), resIndex);
|
|
|
+ break;
|
|
|
+ case D3D_SIT_UAV_RWTYPED:
|
|
|
+ case D3D_SIT_UAV_RWSTRUCTURED:
|
|
|
+ case D3D_SIT_UAV_RWBYTEADDRESS:
|
|
|
+ case D3D_SIT_UAV_APPEND_STRUCTURED:
|
|
|
+ case D3D_SIT_UAV_CONSUME_STRUCTURED:
|
|
|
+ case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER:
|
|
|
+ AddResourceUseToFunctions(m_pDxilModule->GetUAV(resource.uID), resIndex);
|
|
|
+ break;
|
|
|
+ case D3D_SIT_SAMPLER:
|
|
|
+ AddResourceUseToFunctions(m_pDxilModule->GetSampler(resource.uID), resIndex);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ resIndex++;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// ID3D12LibraryReflection
|
|
|
+
|
|
|
+HRESULT DxilLibraryReflection::Load(IDxcBlob *pBlob,
|
|
|
+ const DxilPartHeader *pPart) {
|
|
|
+ IFR(LoadModule(pBlob, pPart));
|
|
|
+
|
|
|
+ try {
|
|
|
+ AddResourceDependencies();
|
|
|
+ return S_OK;
|
|
|
+ }
|
|
|
+ CATCH_CPP_RETURN_HRESULT();
|
|
|
+}
|
|
|
+
|
|
|
+_Use_decl_annotations_
|
|
|
+HRESULT DxilLibraryReflection::GetDesc(D3D12_LIBRARY_DESC * pDesc) {
|
|
|
+ IFR(ZeroMemoryToOut(pDesc));
|
|
|
+ //Unset: LPCSTR Creator; // The name of the originator of the library.
|
|
|
+ //Unset: UINT Flags; // Compilation flags.
|
|
|
+ //UINT FunctionCount; // Number of functions exported from the library.
|
|
|
+ pDesc->FunctionCount = (UINT)m_FunctionMap.size();
|
|
|
+ return S_OK;
|
|
|
+}
|
|
|
+
|
|
|
+_Use_decl_annotations_
|
|
|
+ID3D12FunctionReflection *DxilLibraryReflection::GetFunctionByIndex(INT FunctionIndex) {
|
|
|
+ if (FunctionIndex >= m_FunctionMap.size())
|
|
|
+ return &g_InvalidFunction;
|
|
|
+ return ((m_FunctionMap.begin() + FunctionIndex)->second).get();
|
|
|
+}
|
|
|
+
|