Преглед на файлове

Support ID3DLibraryReflection

- function parameter reflection not supported
Tex Riddell преди 7 години
родител
ревизия
c1b6627843
променени са 2 файла, в които са добавени 690 реда и са изтрити 31 реда
  1. 383 31
      lib/HLSL/DxilContainerReflection.cpp
  2. 307 0
      tools/clang/unittests/HLSL/DxilContainerTest.cpp

+ 383 - 31
lib/HLSL/DxilContainerReflection.cpp

@@ -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();
+}
+

+ 307 - 0
tools/clang/unittests/HLSL/DxilContainerTest.cpp

@@ -75,6 +75,7 @@ public:
   TEST_METHOD(CompileWhenDebugSourceThenSourceMatters)
   TEST_METHOD(CompileWhenOkThenCheckRDAT)
   TEST_METHOD(CompileWhenOkThenCheckRDAT2)
+  TEST_METHOD(CompileWhenOkThenCheckReflection1)
   TEST_METHOD(CompileWhenOKThenIncludesFeatureInfo)
   TEST_METHOD(CompileWhenOKThenIncludesSignatures)
   TEST_METHOD(CompileWhenSigSquareThenIncludeSplit)
@@ -870,6 +871,312 @@ TEST_F(DxilContainerTest, CompileWhenOkThenCheckRDAT2) {
   IFTBOOLMSG(blobFound, E_FAIL, "failed to find RDAT blob after compiling");
 }
 
+static uint32_t EncodedVersion_lib_6_3 = hlsl::EncodeVersion(hlsl::DXIL::ShaderKind::Library, 6, 3);
+static uint32_t EncodedVersion_vs_6_3 = hlsl::EncodeVersion(hlsl::DXIL::ShaderKind::Vertex, 6, 3);
+
+static void Ref1_CheckCBuffer_Globals(ID3D12ShaderReflectionConstantBuffer *pCBReflection, D3D12_SHADER_BUFFER_DESC &cbDesc) {
+  std::string cbName = cbDesc.Name;
+  VERIFY_IS_TRUE(cbName.compare("$Globals") == 0);
+  VERIFY_ARE_EQUAL(cbDesc.Size, 16);
+  VERIFY_ARE_EQUAL(cbDesc.Type, D3D_CT_CBUFFER);
+  VERIFY_ARE_EQUAL(cbDesc.Variables, 1);
+
+  // cbval1
+  ID3D12ShaderReflectionVariable *pVar = pCBReflection->GetVariableByIndex(0);
+  D3D12_SHADER_VARIABLE_DESC varDesc;
+  VERIFY_SUCCEEDED(pVar->GetDesc(&varDesc));
+  VERIFY_ARE_EQUAL_STR(varDesc.Name, "cbval1");
+  VERIFY_ARE_EQUAL(varDesc.StartOffset, 0);
+  VERIFY_ARE_EQUAL(varDesc.Size, 4);
+  // TODO: verify rest of variable
+  ID3D12ShaderReflectionType *pType = pVar->GetType();
+  D3D12_SHADER_TYPE_DESC tyDesc;
+  VERIFY_SUCCEEDED(pType->GetDesc(&tyDesc));
+  VERIFY_ARE_EQUAL(tyDesc.Class, D3D_SVC_SCALAR);
+  VERIFY_ARE_EQUAL(tyDesc.Type, D3D_SVT_FLOAT);
+  // TODO: verify rest of type
+}
+
+static void Ref1_CheckCBuffer_MyCB(ID3D12ShaderReflectionConstantBuffer *pCBReflection, D3D12_SHADER_BUFFER_DESC &cbDesc) {
+  std::string cbName = cbDesc.Name;
+  VERIFY_IS_TRUE(cbName.compare("MyCB") == 0);
+  VERIFY_ARE_EQUAL(cbDesc.Size, 32);
+  VERIFY_ARE_EQUAL(cbDesc.Type, D3D_CT_CBUFFER);
+  VERIFY_ARE_EQUAL(cbDesc.Variables, 2);
+
+  // cbval2
+  {
+    ID3D12ShaderReflectionVariable *pVar =  pCBReflection->GetVariableByIndex(0);
+    D3D12_SHADER_VARIABLE_DESC varDesc;
+    VERIFY_SUCCEEDED(pVar->GetDesc(&varDesc));
+    VERIFY_ARE_EQUAL_STR(varDesc.Name, "cbval2");
+    VERIFY_ARE_EQUAL(varDesc.StartOffset, 0);
+    VERIFY_ARE_EQUAL(varDesc.Size, 16);
+    // TODO: verify rest of variable
+    ID3D12ShaderReflectionType *pType = pVar->GetType();
+    D3D12_SHADER_TYPE_DESC tyDesc;
+    VERIFY_SUCCEEDED(pType->GetDesc(&tyDesc));
+    VERIFY_ARE_EQUAL(tyDesc.Class, D3D_SVC_VECTOR);
+    VERIFY_ARE_EQUAL(tyDesc.Type, D3D_SVT_INT);
+    // TODO: verify rest of type
+  }
+
+  // cbval3
+  {
+    ID3D12ShaderReflectionVariable *pVar = pCBReflection->GetVariableByIndex(1);
+    D3D12_SHADER_VARIABLE_DESC varDesc;
+    VERIFY_SUCCEEDED(pVar->GetDesc(&varDesc));
+    VERIFY_ARE_EQUAL_STR(varDesc.Name, "cbval3");
+    VERIFY_ARE_EQUAL(varDesc.StartOffset, 16);
+    VERIFY_ARE_EQUAL(varDesc.Size, 16);
+    // TODO: verify rest of variable
+    ID3D12ShaderReflectionType *pType = pVar->GetType();
+    D3D12_SHADER_TYPE_DESC tyDesc;
+    VERIFY_SUCCEEDED(pType->GetDesc(&tyDesc));
+    VERIFY_ARE_EQUAL(tyDesc.Class, D3D_SVC_VECTOR);
+    VERIFY_ARE_EQUAL(tyDesc.Type, D3D_SVT_INT);
+    // TODO: verify rest of type
+  }
+}
+
+static void Ref1_CheckBinding_Globals(D3D12_SHADER_INPUT_BIND_DESC &resDesc) {
+  std::string resName = resDesc.Name;
+  VERIFY_IS_TRUE(resName.compare("$Globals") == 0);
+  VERIFY_ARE_EQUAL(resDesc.Type, D3D_SIT_CBUFFER);
+  // not explicitly bound:
+  VERIFY_ARE_EQUAL(resDesc.BindPoint, 4294967295);
+  VERIFY_ARE_EQUAL(resDesc.Space, 0);
+  VERIFY_ARE_EQUAL(resDesc.BindCount, 1);
+}
+
+static void Ref1_CheckBinding_MyCB(D3D12_SHADER_INPUT_BIND_DESC &resDesc) {
+  std::string resName = resDesc.Name;
+  VERIFY_IS_TRUE(resName.compare("MyCB") == 0);
+  VERIFY_ARE_EQUAL(resDesc.Type, D3D_SIT_CBUFFER);
+  VERIFY_ARE_EQUAL(resDesc.BindPoint, 11);
+  VERIFY_ARE_EQUAL(resDesc.Space, 2);
+  VERIFY_ARE_EQUAL(resDesc.BindCount, 1);
+}
+
+static void Ref1_CheckBinding_tex(D3D12_SHADER_INPUT_BIND_DESC &resDesc) {
+  std::string resName = resDesc.Name;
+  VERIFY_IS_TRUE(resName.compare("tex") == 0);
+  VERIFY_ARE_EQUAL(resDesc.Type, D3D_SIT_UAV_RWTYPED);
+  VERIFY_ARE_EQUAL(resDesc.BindPoint, 5);
+  VERIFY_ARE_EQUAL(resDesc.Space, 0);
+  VERIFY_ARE_EQUAL(resDesc.BindCount, 1);
+}
+
+static void Ref1_CheckBinding_tex2(D3D12_SHADER_INPUT_BIND_DESC &resDesc) {
+  std::string resName = resDesc.Name;
+  VERIFY_IS_TRUE(resName.compare("tex2") == 0);
+  VERIFY_ARE_EQUAL(resDesc.Type, D3D_SIT_TEXTURE);
+  VERIFY_ARE_EQUAL(resDesc.BindPoint, 0);
+  VERIFY_ARE_EQUAL(resDesc.Space, 0);
+  VERIFY_ARE_EQUAL(resDesc.BindCount, 1);
+}
+
+static void Ref1_CheckBinding_samp(D3D12_SHADER_INPUT_BIND_DESC &resDesc) {
+  std::string resName = resDesc.Name;
+  VERIFY_IS_TRUE(resName.compare("samp") == 0);
+  VERIFY_ARE_EQUAL(resDesc.Type, D3D_SIT_SAMPLER);
+  VERIFY_ARE_EQUAL(resDesc.BindPoint, 7);
+  VERIFY_ARE_EQUAL(resDesc.Space, 0);
+  VERIFY_ARE_EQUAL(resDesc.BindCount, 1);
+}
+
+static void Ref1_CheckBinding_b_buf(D3D12_SHADER_INPUT_BIND_DESC &resDesc) {
+  std::string resName = resDesc.Name;
+  VERIFY_IS_TRUE(resName.compare("b_buf") == 0);
+  VERIFY_ARE_EQUAL(resDesc.Type, D3D_SIT_UAV_RWBYTEADDRESS);
+  // not explicitly bound:
+  VERIFY_ARE_EQUAL(resDesc.BindPoint, 4294967295);
+  VERIFY_ARE_EQUAL(resDesc.Space, 0);
+  VERIFY_ARE_EQUAL(resDesc.BindCount, 1);
+}
+
+
+TEST_F(DxilContainerTest, CompileWhenOkThenCheckReflection1) {
+  if (m_ver.SkipDxilVersion(1, 3)) return;
+  const char *shader =
+    "float cbval1;"
+    "cbuffer MyCB : register(b11, space2) { int4 cbval2, cbval3; }"
+    "RWTexture1D<int4> tex : register(u5);"
+    "Texture1D<float4> tex2 : register(t0);"
+    "SamplerState samp : register(s7);"
+    "RWByteAddressBuffer b_buf;"
+    "float function0(min16float x) { "
+    "  return x + cbval2.x + tex[0].x; }"
+    "float function1(float x, min12int i) {"
+    "  return x + cbval1 + b_buf.Load(x) + tex2.Sample(samp, x).x; }"
+    "[shader(\"vertex\")]"
+    "float function2(float4 x : POSITION) : SV_Position { return x + cbval1 + cbval3.x; }";
+
+  CComPtr<IDxcCompiler> pCompiler;
+  CComPtr<IDxcBlobEncoding> pSource;
+  CComPtr<IDxcBlob> pProgram;
+  CComPtr<IDxcBlobEncoding> pDisassembly;
+  CComPtr<IDxcOperationResult> pResult;
+  CComPtr<ID3D12LibraryReflection> pLibraryReflection;
+
+  VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
+  CreateBlobFromText(shader, &pSource);
+  VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"",
+    L"lib_6_3", nullptr, 0, nullptr, 0,
+    nullptr, &pResult));
+  VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
+  CComPtr<IDxcContainerReflection> containerReflection;
+  uint32_t partCount;
+  VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcContainerReflection, &containerReflection));
+  VERIFY_SUCCEEDED(containerReflection->Load(pProgram));
+  VERIFY_SUCCEEDED(containerReflection->GetPartCount(&partCount));
+  bool blobFound = false;
+
+  for (uint32_t i = 0; i < partCount; ++i) {
+    uint32_t kind;
+    VERIFY_SUCCEEDED(containerReflection->GetPartKind(i, &kind));
+    if (kind == (uint32_t)hlsl::DxilFourCC::DFCC_DXIL) {
+      blobFound = true;
+      VERIFY_SUCCEEDED(containerReflection->GetPartReflection(i, IID_PPV_ARGS(&pLibraryReflection)));
+      D3D12_LIBRARY_DESC LibDesc;
+      VERIFY_SUCCEEDED(pLibraryReflection->GetDesc(&LibDesc));
+      VERIFY_ARE_EQUAL(LibDesc.FunctionCount, 4);
+      for (INT iFn = 0; iFn < (INT)LibDesc.FunctionCount; iFn++) {
+        ID3D12FunctionReflection *pFunctionReflection = pLibraryReflection->GetFunctionByIndex(iFn);
+        D3D12_FUNCTION_DESC FnDesc;
+        pFunctionReflection->GetDesc(&FnDesc);
+        std::string Name = FnDesc.Name;
+        if (Name.compare("\01?function0@@YAM$f16@@Z") == 0) {
+          VERIFY_ARE_EQUAL(FnDesc.Version, EncodedVersion_lib_6_3);
+          VERIFY_ARE_EQUAL(FnDesc.ConstantBuffers, 1);
+          VERIFY_ARE_EQUAL(FnDesc.BoundResources, 2);
+          D3D12_SHADER_BUFFER_DESC cbDesc;
+          ID3D12ShaderReflectionConstantBuffer *pCBReflection = pFunctionReflection->GetConstantBufferByIndex(0);
+          VERIFY_SUCCEEDED(pCBReflection->GetDesc(&cbDesc));
+          std::string cbName = cbDesc.Name;
+          (void)(cbName);
+          Ref1_CheckCBuffer_MyCB(pCBReflection, cbDesc);
+
+          for (INT iRes = 0; iRes < (INT)FnDesc.BoundResources; iRes++) {
+            D3D12_SHADER_INPUT_BIND_DESC resDesc;
+            pFunctionReflection->GetResourceBindingDesc(iRes, &resDesc);
+            std::string resName = resDesc.Name;
+            if (resName.compare("$Globals") == 0) {
+              Ref1_CheckBinding_Globals(resDesc);
+            } else if (resName.compare("MyCB") == 0) {
+              Ref1_CheckBinding_MyCB(resDesc);
+            } else if (resName.compare("samp") == 0) {
+              Ref1_CheckBinding_samp(resDesc);
+            } else if (resName.compare("tex") == 0) {
+              Ref1_CheckBinding_tex(resDesc);
+            } else if (resName.compare("tex2") == 0) {
+              Ref1_CheckBinding_tex2(resDesc);
+            } else if (resName.compare("b_buf") == 0) {
+              Ref1_CheckBinding_b_buf(resDesc);
+            } else {
+              VERIFY_FAIL(L"Unexpected resource used");
+            }
+          }
+        } else if (Name.compare("\01?function1@@YAMMF@Z") == 0) {
+          VERIFY_ARE_EQUAL(FnDesc.Version, EncodedVersion_lib_6_3);
+          VERIFY_ARE_EQUAL(FnDesc.ConstantBuffers, 1);
+          VERIFY_ARE_EQUAL(FnDesc.BoundResources, 4);
+          D3D12_SHADER_BUFFER_DESC cbDesc;
+          ID3D12ShaderReflectionConstantBuffer *pCBReflection = pFunctionReflection->GetConstantBufferByIndex(0);
+          VERIFY_SUCCEEDED(pCBReflection->GetDesc(&cbDesc));
+          std::string cbName = cbDesc.Name;
+          (void)(cbName);
+          Ref1_CheckCBuffer_Globals(pCBReflection, cbDesc);
+
+          for (INT iRes = 0; iRes < (INT)FnDesc.BoundResources; iRes++) {
+            D3D12_SHADER_INPUT_BIND_DESC resDesc;
+            pFunctionReflection->GetResourceBindingDesc(iRes, &resDesc);
+            std::string resName = resDesc.Name;
+            if (resName.compare("$Globals") == 0) {
+              Ref1_CheckBinding_Globals(resDesc);
+            } else if (resName.compare("MyCB") == 0) {
+              Ref1_CheckBinding_MyCB(resDesc);
+            } else if (resName.compare("samp") == 0) {
+              Ref1_CheckBinding_samp(resDesc);
+            } else if (resName.compare("tex") == 0) {
+              Ref1_CheckBinding_tex(resDesc);
+            } else if (resName.compare("tex2") == 0) {
+              Ref1_CheckBinding_tex2(resDesc);
+            } else if (resName.compare("b_buf") == 0) {
+              Ref1_CheckBinding_b_buf(resDesc);
+            } else {
+              VERIFY_FAIL(L"Unexpected resource used");
+            }
+          }
+        } else if (Name.compare("\01?function2@@YAMV?$vector@M$03@@@Z") == 0) {
+          // library version of shader function is mangled
+          VERIFY_ARE_EQUAL(FnDesc.Version, EncodedVersion_lib_6_3);
+          VERIFY_ARE_EQUAL(FnDesc.ConstantBuffers, 2);
+          VERIFY_ARE_EQUAL(FnDesc.BoundResources, 2);
+          for (INT iCB = 0; iCB < (INT)FnDesc.BoundResources; iCB++) {
+            D3D12_SHADER_BUFFER_DESC cbDesc;
+            ID3D12ShaderReflectionConstantBuffer *pCBReflection = pFunctionReflection->GetConstantBufferByIndex(0);
+            VERIFY_SUCCEEDED(pCBReflection->GetDesc(&cbDesc));
+            std::string cbName = cbDesc.Name;
+            if (cbName.compare("$Globals") == 0) {
+              Ref1_CheckCBuffer_Globals(pCBReflection, cbDesc);
+            } else if (cbName.compare("MyCB") == 0) {
+              Ref1_CheckCBuffer_MyCB(pCBReflection, cbDesc);
+            }
+          }
+
+          for (INT iRes = 0; iRes < (INT)FnDesc.BoundResources; iRes++) {
+            D3D12_SHADER_INPUT_BIND_DESC resDesc;
+            pFunctionReflection->GetResourceBindingDesc(iRes, &resDesc);
+            std::string resName = resDesc.Name;
+            if (resName.compare("$Globals") == 0) {
+              Ref1_CheckBinding_Globals(resDesc);
+            } else if (resName.compare("MyCB") == 0) {
+              Ref1_CheckBinding_MyCB(resDesc);
+            } else {
+              VERIFY_FAIL(L"Unexpected resource used");
+            }
+          }
+        } else if (Name.compare("function2") == 0) {
+          // shader function with unmangled name
+          VERIFY_ARE_EQUAL(FnDesc.Version, EncodedVersion_vs_6_3);
+          VERIFY_ARE_EQUAL(FnDesc.ConstantBuffers, 2);
+          VERIFY_ARE_EQUAL(FnDesc.BoundResources, 2);
+          for (INT iCB = 0; iCB < (INT)FnDesc.BoundResources; iCB++) {
+            D3D12_SHADER_BUFFER_DESC cbDesc;
+            ID3D12ShaderReflectionConstantBuffer *pCBReflection = pFunctionReflection->GetConstantBufferByIndex(0);
+            VERIFY_SUCCEEDED(pCBReflection->GetDesc(&cbDesc));
+            std::string cbName = cbDesc.Name;
+            if (cbName.compare("$Globals") == 0) {
+              Ref1_CheckCBuffer_Globals(pCBReflection, cbDesc);
+            } else if (cbName.compare("MyCB") == 0) {
+              Ref1_CheckCBuffer_MyCB(pCBReflection, cbDesc);
+            }
+          }
+
+          for (INT iRes = 0; iRes < (INT)FnDesc.BoundResources; iRes++) {
+            D3D12_SHADER_INPUT_BIND_DESC resDesc;
+            pFunctionReflection->GetResourceBindingDesc(iRes, &resDesc);
+            std::string resName = resDesc.Name;
+            if (resName.compare("$Globals") == 0) {
+              Ref1_CheckBinding_Globals(resDesc);
+            } else if (resName.compare("MyCB") == 0) {
+              Ref1_CheckBinding_MyCB(resDesc);
+            } else {
+              VERIFY_FAIL(L"Unexpected resource used");
+            }
+          }
+        } else {
+          VERIFY_FAIL(L"Unexpected function");
+        }
+      }
+
+      // TODO: FINISH THIS
+    }
+  }
+  IFTBOOLMSG(blobFound, E_FAIL, "failed to find RDAT blob after compiling");
+}
+
 TEST_F(DxilContainerTest, CompileWhenOKThenIncludesFeatureInfo) {
   CComPtr<IDxcCompiler> pCompiler;
   CComPtr<IDxcBlobEncoding> pSource;