Browse Source

Merged PR 72: Fix DxilRuntimeReflection issues

Tex Riddell 7 years ago
parent
commit
af5e483961

+ 20 - 43
include/dxc/HLSL/DxilRuntimeReflection.h

@@ -9,14 +9,10 @@
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-#include <windows.h>
-#include <unordered_map>
-#include <vector>
-#include <memory>
+#pragma once
 #include "DxilConstants.h"
 
 namespace hlsl {
-namespace DXIL {
 namespace RDAT {
 
 struct RuntimeDataTableHeader {
@@ -25,7 +21,7 @@ struct RuntimeDataTableHeader {
   uint32_t offset;
 };
 
-enum RuntimeDataPartType : uint32_t {
+enum class RuntimeDataPartType : uint32_t {
   Invalid = 0,
   String,
   Function,
@@ -78,6 +74,14 @@ public:
   }
 };
 
+enum class DxilResourceFlag : uint32_t {
+  None                      = 0,
+  UAVGloballyCoherent       = 1 << 0,
+  UAVCounter                = 1 << 1,
+  UAVRasterizerOrderedView  = 1 << 2,
+  DynamicIndexing           = 1 << 3,
+};
+
 struct RuntimeDataResourceInfo {
   uint32_t Class; // hlsl::DXIL::ResourceClass
   uint32_t Kind;  // hlsl::DXIL::ResourceKind
@@ -86,7 +90,7 @@ struct RuntimeDataResourceInfo {
   uint32_t LowerBound;
   uint32_t UpperBound;
   uint32_t Name;  // resource name as an offset for string table
-  uint32_t Flags; // Not implemented yet
+  uint32_t Flags; // hlsl::RDAT::DxilResourceFlag
 };
 
 struct RuntimeDataFunctionInfo {
@@ -355,14 +359,14 @@ typedef struct DXIL_RESOURCE {
   uint32_t UpperBound;
   uint32_t LowerBound;
   LPCWSTR Name;
-  uint32_t Flags;
+  uint32_t Flags; // hlsl::RDAT::DxilResourceFlag
 } DXIL_RESOURCE;
 
 typedef struct DXIL_FUNCTION {
   LPCWSTR Name;
   LPCWSTR UnmangledName;
   uint32_t NumResources;
-  const DXIL_RESOURCE *Resources;
+  const DXIL_RESOURCE * const*Resources;
   uint32_t NumFunctionDependencies;
   const LPCWSTR *FunctionDependencies;
   uint32_t ShaderKind;
@@ -388,42 +392,15 @@ typedef struct DXIL_LIBRARY_DESC {
 } DXIL_LIBRARY_DESC;
 
 class DxilRuntimeReflection {
-private:
-  typedef std::unordered_map<const char *, std::unique_ptr<wchar_t[]>> StringMap;
-  typedef std::vector<DXIL_RESOURCE> ResourceList;
-  typedef std::vector<DXIL_RESOURCE *> ResourceRefList;
-  typedef std::vector<DXIL_FUNCTION> FunctionList;
-  typedef std::vector<const wchar_t *> WStringList;
-
-  DxilRuntimeData m_RuntimeData;
-  StringMap m_StringMap;
-  ResourceList m_Resources;
-  FunctionList m_Functions;
-  std::unordered_map<DXIL_FUNCTION *, ResourceRefList> m_FuncToResMap;
-  std::unordered_map<DXIL_FUNCTION *, WStringList> m_FuncToStringMap;
-  bool m_initialized;
-
-  const wchar_t *GetWideString(const char *ptr);
-  void AddString(const char *ptr);
-  void InitializeReflection();
-  DXIL_RESOURCE *GetResourcesForFunction(DXIL_FUNCTION &function,
-                                         const FunctionReader &functionReader);
-  const wchar_t **GetDependenciesForFunction(DXIL_FUNCTION &function,
-                             const FunctionReader &functionReader);
-  DXIL_RESOURCE *AddResource(const ResourceReader &resourceReader);
-  DXIL_FUNCTION *AddFunction(const FunctionReader &functionReader);
-
 public:
-  // TODO: Implement pipeline state validation with runtime data
-  // TODO: Update BlobContainer.h to recognize 'RDAT' blob
-  DxilRuntimeReflection()
-      : m_RuntimeData(), m_StringMap(), m_Resources(), m_Functions(),
-        m_FuncToResMap(), m_FuncToStringMap(), m_initialized(false) {}
+  virtual ~DxilRuntimeReflection() {}
   // This call will allocate memory for GetLibraryReflection call
-  bool InitFromRDAT(const void *pRDAT);
-  const DXIL_LIBRARY_DESC GetLibraryReflection();
+  virtual bool InitFromRDAT(const void *pRDAT) = 0;
+  // DxilRuntimeReflection owns the memory pointed to by DXIL_LIBRARY_DESC
+  virtual const DXIL_LIBRARY_DESC GetLibraryReflection() = 0;
 };
 
-} // namespace LIB
-} // namespace DXIL
+DxilRuntimeReflection *CreateDxilRuntimeReflection();
+
+} // namespace RDAT
 } // namespace hlsl

+ 128 - 38
include/dxc/HLSL/DxilRuntimeReflection.inl

@@ -10,11 +10,22 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "dxc/hlsl/DxilRuntimeReflection.h"
+#include <windows.h>
+#include <unordered_map>
+#include <vector>
+#include <memory>
 
 namespace hlsl {
-namespace DXIL {
 namespace RDAT {
 
+struct ResourceKey {
+  uint32_t Class, ID;
+  ResourceKey(uint32_t Class, uint32_t ID) : Class(Class), ID(ID) {}
+  bool operator==(const ResourceKey& other) const {
+    return other.Class == Class && other.ID == ID;
+  }
+};
+
 DxilRuntimeData::DxilRuntimeData() : DxilRuntimeData(nullptr) {}
 
 DxilRuntimeData::DxilRuntimeData(const char *ptr)
@@ -35,7 +46,7 @@ bool DxilRuntimeData::InitFromRDAT(const void *pRDAT) {
     RuntimeDataTableHeader *records = (RuntimeDataTableHeader *)(ptr + 4);
     for (uint32_t i = 0; i < TableCount; ++i) {
       RuntimeDataTableHeader *curRecord = &records[i];
-      switch (curRecord->tableType) {
+      switch (static_cast<RuntimeDataPartType>(curRecord->tableType)) {
       case RuntimeDataPartType::Resource: {
         m_ResourceTableReader.SetResourceInfo(
             (RuntimeDataResourceInfo *)(ptr + curRecord->offset),
@@ -76,7 +87,63 @@ ResourceTableReader *DxilRuntimeData::GetResourceTableReader() {
   return &m_ResourceTableReader;
 }
 
-void DxilRuntimeReflection::AddString(const char *ptr) {
+}} // hlsl::RDAT
+
+using namespace hlsl;
+using namespace RDAT;
+
+template<>
+struct std::hash<ResourceKey> {
+public:
+  size_t operator()(const ResourceKey& key) const throw() {
+    return (std::hash<uint32_t>()(key.Class) * (size_t)16777619U)
+      ^ std::hash<uint32_t>()(key.ID);
+  }
+};
+
+namespace {
+
+class DxilRuntimeReflection_impl : public DxilRuntimeReflection {
+private:
+  typedef std::unordered_map<const char *, std::unique_ptr<wchar_t[]>> StringMap;
+  typedef std::vector<DXIL_RESOURCE> ResourceList;
+  typedef std::vector<DXIL_RESOURCE *> ResourceRefList;
+  typedef std::vector<DXIL_FUNCTION> FunctionList;
+  typedef std::vector<const wchar_t *> WStringList;
+
+  DxilRuntimeData m_RuntimeData;
+  StringMap m_StringMap;
+  ResourceList m_Resources;
+  FunctionList m_Functions;
+  std::unordered_map<ResourceKey, DXIL_RESOURCE *> m_ResourceMap;
+  std::unordered_map<DXIL_FUNCTION *, ResourceRefList> m_FuncToResMap;
+  std::unordered_map<DXIL_FUNCTION *, WStringList> m_FuncToStringMap;
+  bool m_initialized;
+
+  const wchar_t *GetWideString(const char *ptr);
+  void AddString(const char *ptr);
+  void InitializeReflection();
+  const DXIL_RESOURCE * const*GetResourcesForFunction(DXIL_FUNCTION &function,
+                             const FunctionReader &functionReader);
+  const wchar_t **GetDependenciesForFunction(DXIL_FUNCTION &function,
+                             const FunctionReader &functionReader);
+  DXIL_RESOURCE *AddResource(const ResourceReader &resourceReader);
+  DXIL_FUNCTION *AddFunction(const FunctionReader &functionReader);
+
+public:
+  // TODO: Implement pipeline state validation with runtime data
+  // TODO: Update BlobContainer.h to recognize 'RDAT' blob
+  // TODO: Add size and verification to InitFromRDAT and DxilRuntimeData
+  DxilRuntimeReflection_impl()
+      : m_RuntimeData(), m_StringMap(), m_Resources(), m_Functions(),
+        m_FuncToResMap(), m_FuncToStringMap(), m_initialized(false) {}
+  virtual ~DxilRuntimeReflection_impl() {}
+  // This call will allocate memory for GetLibraryReflection call
+  bool InitFromRDAT(const void *pRDAT) override;
+  const DXIL_LIBRARY_DESC GetLibraryReflection() override;
+};
+
+void DxilRuntimeReflection_impl::AddString(const char *ptr) {
   if (m_StringMap.find(ptr) == m_StringMap.end()) {
     int size = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, ptr, -1,
                                      nullptr, 0);
@@ -89,22 +156,22 @@ void DxilRuntimeReflection::AddString(const char *ptr) {
   }
 }
 
-const wchar_t *DxilRuntimeReflection::GetWideString(const char *ptr) {
+const wchar_t *DxilRuntimeReflection_impl::GetWideString(const char *ptr) {
   if (m_StringMap.find(ptr) == m_StringMap.end()) {
     AddString(ptr);
   }
   return m_StringMap.at(ptr).get();
 }
 
-bool DxilRuntimeReflection::InitFromRDAT(const void *pRDAT) {
+bool DxilRuntimeReflection_impl::InitFromRDAT(const void *pRDAT) {
   m_initialized = m_RuntimeData.InitFromRDAT(pRDAT);
   if (m_initialized)
     InitializeReflection();
   return m_initialized;
 }
 
-const DXIL_LIBRARY_DESC DxilRuntimeReflection::GetLibraryReflection() {
-  DXIL_LIBRARY_DESC reflection;
+const DXIL_LIBRARY_DESC DxilRuntimeReflection_impl::GetLibraryReflection() {
+  DXIL_LIBRARY_DESC reflection = {};
   if (m_initialized) {
     reflection.NumResources =
         m_RuntimeData.GetResourceTableReader()->GetNumResources();
@@ -116,53 +183,68 @@ const DXIL_LIBRARY_DESC DxilRuntimeReflection::GetLibraryReflection() {
   return reflection;
 }
 
-void DxilRuntimeReflection::InitializeReflection() {
+void DxilRuntimeReflection_impl::InitializeReflection() {
   // First need to reserve spaces for resources because functions will need to
   // reference them via pointers.
-  m_Resources.reserve(
-      m_RuntimeData.GetResourceTableReader()->GetNumResources());
-  const FunctionTableReader *tableReader =
-      m_RuntimeData.GetFunctionTableReader();
-  for (uint32_t i = 0; i < tableReader->GetNumFunctions(); ++i) {
-    FunctionReader functionReader = tableReader->GetItem(i);
+  const ResourceTableReader *resourceTableReader = m_RuntimeData.GetResourceTableReader();
+  m_Resources.reserve(resourceTableReader->GetNumResources());
+  for (uint32_t i = 0; i < resourceTableReader->GetNumResources(); ++i) {
+    ResourceReader resourceReader = resourceTableReader->GetItem(i);
+    AddString(resourceReader.GetName());
+    DXIL_RESOURCE *pResource = AddResource(resourceReader);
+    if (pResource) {
+      ResourceKey key(pResource->Class, pResource->ID);
+      m_ResourceMap[key] = pResource;
+    }
+  }
+  const FunctionTableReader *functionTableReader = m_RuntimeData.GetFunctionTableReader();
+  m_Functions.reserve(functionTableReader->GetNumFunctions());
+  for (uint32_t i = 0; i < functionTableReader->GetNumFunctions(); ++i) {
+    FunctionReader functionReader = functionTableReader->GetItem(i);
     AddString(functionReader.GetName());
     AddFunction(functionReader);
   }
 }
 
 DXIL_RESOURCE *
-DxilRuntimeReflection::AddResource(const ResourceReader &resourceReader) {
-  if (m_Resources.size() < m_Resources.capacity()) {
-    m_Resources.emplace_back(DXIL_RESOURCE({0}));
-    DXIL_RESOURCE &resource = m_Resources.back();
-    resource.Class = (uint32_t)resourceReader.GetResourceClass();
-    resource.Kind = (uint32_t)resourceReader.GetResourceKind();
-    resource.Space = resourceReader.GetSpace();
-    resource.LowerBound = resourceReader.GetLowerBound();
-    resource.UpperBound = resourceReader.GetUpperBound();
-    resource.ID = resourceReader.GetID();
-    resource.Flags = resourceReader.GetFlags();
-    resource.Name = GetWideString(resourceReader.GetName());
-    return &resource;
-  }
-  // TODO: assert here?
-  return nullptr;
+DxilRuntimeReflection_impl::AddResource(const ResourceReader &resourceReader) {
+  assert(m_Resources.size() < m_Resources.capacity() && "Otherwise, number of resources was incorrect");
+  if (!(m_Resources.size() < m_Resources.capacity()))
+    return nullptr;
+  m_Resources.emplace_back(DXIL_RESOURCE({0}));
+  DXIL_RESOURCE &resource = m_Resources.back();
+  resource.Class = (uint32_t)resourceReader.GetResourceClass();
+  resource.Kind = (uint32_t)resourceReader.GetResourceKind();
+  resource.Space = resourceReader.GetSpace();
+  resource.LowerBound = resourceReader.GetLowerBound();
+  resource.UpperBound = resourceReader.GetUpperBound();
+  resource.ID = resourceReader.GetID();
+  resource.Flags = resourceReader.GetFlags();
+  resource.Name = GetWideString(resourceReader.GetName());
+  return &resource;
 }
 
-DXIL_RESOURCE *DxilRuntimeReflection::GetResourcesForFunction(
+const DXIL_RESOURCE * const*DxilRuntimeReflection_impl::GetResourcesForFunction(
     DXIL_FUNCTION &function, const FunctionReader &functionReader) {
   if (m_FuncToResMap.find(&function) == m_FuncToResMap.end())
     m_FuncToResMap.insert(std::pair<DXIL_FUNCTION *, ResourceRefList>(
         &function, ResourceRefList()));
   ResourceRefList &resourceList = m_FuncToResMap.at(&function);
-  for (uint32_t i = 0; i < functionReader.GetNumResources(); ++i) {
-    const ResourceReader resourceReader = functionReader.GetResource(i);
-    resourceList.emplace_back(AddResource(resourceReader));
+  if (resourceList.empty()) {
+    resourceList.reserve(functionReader.GetNumResources());
+    for (uint32_t i = 0; i < functionReader.GetNumResources(); ++i) {
+      const ResourceReader resourceReader = functionReader.GetResource(i);
+      ResourceKey key((uint32_t)resourceReader.GetResourceClass(),
+                      resourceReader.GetID());
+      auto it = m_ResourceMap.find(key);
+      assert(it != m_ResourceMap.end() && it->second && "Otherwise, resource was not in map, or was null");
+      resourceList.emplace_back(it->second);
+    }
   }
-  return resourceList.empty() ? nullptr : *resourceList.data();
+  return resourceList.empty() ? nullptr : resourceList.data();
 }
 
-const wchar_t **DxilRuntimeReflection::GetDependenciesForFunction(
+const wchar_t **DxilRuntimeReflection_impl::GetDependenciesForFunction(
     DXIL_FUNCTION &function, const FunctionReader &functionReader) {
   if (m_FuncToStringMap.find(&function) == m_FuncToStringMap.end())
     m_FuncToStringMap.insert(
@@ -175,7 +257,10 @@ const wchar_t **DxilRuntimeReflection::GetDependenciesForFunction(
 }
 
 DXIL_FUNCTION *
-DxilRuntimeReflection::AddFunction(const FunctionReader &functionReader) {
+DxilRuntimeReflection_impl::AddFunction(const FunctionReader &functionReader) {
+  assert(m_Functions.size() < m_Functions.capacity() && "Otherwise, number of functions was incorrect");
+  if (!(m_Functions.size() < m_Functions.capacity()))
+    return nullptr;
   m_Functions.emplace_back(DXIL_FUNCTION({0}));
   DXIL_FUNCTION &function = m_Functions.back();
   function.Name = GetWideString(functionReader.GetName());
@@ -194,4 +279,9 @@ DxilRuntimeReflection::AddFunction(const FunctionReader &functionReader) {
   function.MinShaderTarget = functionReader.GetMinShaderTarget();
   return &function;
 }
-}}}
+
+} // namespace anon
+
+DxilRuntimeReflection *hlsl::RDAT::CreateDxilRuntimeReflection() {
+  return new DxilRuntimeReflection_impl();
+}

+ 12 - 2
lib/HLSL/DxilContainerAssembler.cpp

@@ -34,7 +34,7 @@
 
 using namespace llvm;
 using namespace hlsl;
-using namespace hlsl::DXIL::RDAT;
+using namespace hlsl::RDAT;
 
 static DxilProgramSigSemantic KindToSystemValue(Semantic::Kind kind, DXIL::TessellatorDomain domain) {
   switch (kind) {
@@ -877,6 +877,16 @@ private:
     info.UpperBound = resource.GetUpperBound();
     info.Name = stringIndex;
     info.Flags = 0;
+    if (ResourceClass::UAV == resourceClass) {
+      DxilResource *pRes = static_cast<DxilResource*>(&resource);
+      if (pRes->HasCounter())
+        info.Flags |= static_cast<uint32_t>(DxilResourceFlag::UAVCounter);
+      if (pRes->IsGloballyCoherent())
+        info.Flags |= static_cast<uint32_t>(DxilResourceFlag::UAVGloballyCoherent);
+      if (pRes->IsROV())
+        info.Flags |= static_cast<uint32_t>(DxilResourceFlag::UAVRasterizerOrderedView);
+      // TODO: add dynamic index flag
+    }
     resourceTable.Insert(info);
   }
 
@@ -1013,7 +1023,7 @@ public:
     // write records
     uint32_t curTableOffset = size * sizeof(RuntimeDataTableHeader) + 4;
     for (auto &&table : m_tables) {
-      RuntimeDataTableHeader record = { table->GetType(), table->GetPartSize(), curTableOffset };
+      RuntimeDataTableHeader record = { static_cast<uint32_t>(table->GetType()), table->GetPartSize(), curTableOffset };
       memcpy(pCur, &record, sizeof(RuntimeDataTableHeader));
       pCur += sizeof(RuntimeDataTableHeader);
       curTableOffset += record.size;

+ 2 - 1
lib/HLSL/DxilContainerReflection.cpp

@@ -23,7 +23,6 @@
 #include "dxc/Support/microcom.h"
 #include "dxc/Support/FileIOHelper.h"
 #include "dxc/Support/dxcapi.impl.h"
-#include "dxc/HLSL/DxilRuntimeReflection.inl"
 #include "dxc/HLSL/DxilFunctionProps.h"
 
 #include <unordered_set>
@@ -2317,3 +2316,5 @@ ID3D12FunctionReflection *DxilLibraryReflection::GetFunctionByIndex(INT Function
   return ((m_FunctionMap.begin() + FunctionIndex)->second).get();
 }
 
+// DxilRuntimeReflection implementation
+#include "dxc/HLSL/DxilRuntimeReflection.inl"

+ 93 - 33
tools/clang/unittests/HLSL/DxilContainerTest.cpp

@@ -674,23 +674,47 @@ TEST_F(DxilContainerTest, CompileWhenOkThenCheckRDAT) {
     "RWTexture1D<int4> tex : register(u5);"
     "Texture1D<float4> tex2 : register(t0);"
     "RWByteAddressBuffer b_buf;"
+    "struct Foo { float2 f2; int2 i2; };"
+    "AppendStructuredBuffer<Foo> append_buf;"
+    "ConsumeStructuredBuffer<Foo> consume_buf;"
+    "RasterizerOrderedByteAddressBuffer rov_buf;"
+    "globallycoherent RWByteAddressBuffer gc_buf;"
     "float function_import(float x);"
     "float function0(min16float x) { "
     "  return x + 1 + tex[0].x; }"
     "float function1(float x, min12int i) {"
     "  return x + c_buf + b_buf.Load(x) + tex2[i].x; }"
-    "float function2(float x) { return x + function_import(x); }";
+    "float function2(float x) { return x + function_import(x); }"
+    "float function3(int i) {"
+    "  Foo f = consume_buf.Consume();"
+    "  f.f2 += 0.5; append_buf.Append(f);"
+    "  rov_buf.Store(i, f.i2.x);"
+    "  gc_buf.Store(i, f.i2.y);"
+    "  b_buf.Store(i, f.i2.x + f.i2.y); }";
   CComPtr<IDxcCompiler> pCompiler;
   CComPtr<IDxcBlobEncoding> pSource;
   CComPtr<IDxcBlob> pProgram;
   CComPtr<IDxcBlobEncoding> pDisassembly;
   CComPtr<IDxcOperationResult> pResult;
 
+  struct CheckResFlagInfo { std::string name; hlsl::DXIL::ResourceKind kind; hlsl::RDAT::DxilResourceFlag flag; };
+  const unsigned numResFlagCheck = 5;
+  CheckResFlagInfo resFlags[numResFlagCheck] = {
+    { "b_buf", hlsl::DXIL::ResourceKind::RawBuffer, hlsl::RDAT::DxilResourceFlag::None },
+    { "append_buf", hlsl::DXIL::ResourceKind::StructuredBuffer, hlsl::RDAT::DxilResourceFlag::UAVCounter },
+    { "consume_buf", hlsl::DXIL::ResourceKind::StructuredBuffer, hlsl::RDAT::DxilResourceFlag::UAVCounter },
+    { "gc_buf", hlsl::DXIL::ResourceKind::RawBuffer, hlsl::RDAT::DxilResourceFlag::UAVGloballyCoherent },
+    { "rov_buf", hlsl::DXIL::ResourceKind::RawBuffer, hlsl::RDAT::DxilResourceFlag::UAVRasterizerOrderedView }
+  };
+
   VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
   CreateBlobFromText(shader, &pSource);
   VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"main",
                                       L"lib_6_3", nullptr, 0, nullptr, 0,
                                       nullptr, &pResult));
+  HRESULT hrStatus;
+  VERIFY_SUCCEEDED(pResult->GetStatus(&hrStatus));
+  VERIFY_SUCCEEDED(hrStatus);
   VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
   CComPtr<IDxcContainerReflection> containerReflection;
   uint32_t partCount;
@@ -703,7 +727,7 @@ TEST_F(DxilContainerTest, CompileWhenOkThenCheckRDAT) {
     IFT(containerReflection->GetPartKind(i, &kind));
     if (kind == (uint32_t)hlsl::DxilFourCC::DFCC_RuntimeData) {
       blobFound = true;
-      using namespace hlsl::DXIL::RDAT;
+      using namespace hlsl::RDAT;
       CComPtr<IDxcBlob> pBlob;
       IFT(containerReflection->GetPartContent(i, &pBlob));
       // Validate using DxilRuntimeData
@@ -711,7 +735,7 @@ TEST_F(DxilContainerTest, CompileWhenOkThenCheckRDAT) {
       context.InitFromRDAT((char *)pBlob->GetBufferPointer());
       FunctionTableReader *funcTableReader = context.GetFunctionTableReader();
       ResourceTableReader *resTableReader = context.GetResourceTableReader();
-      VERIFY_IS_TRUE(funcTableReader->GetNumFunctions() == 3);
+      VERIFY_ARE_EQUAL(funcTableReader->GetNumFunctions(), 4);
       std::string str("function");
       for (uint32_t j = 0; j < funcTableReader->GetNumFunctions(); ++j) {
         FunctionReader funcReader = funcTableReader->GetItem(j);
@@ -720,39 +744,55 @@ TEST_F(DxilContainerTest, CompileWhenOkThenCheckRDAT) {
         std::string cur_str = str;
         cur_str.push_back('0' + j);
         if (cur_str.compare("function0") == 0) {
-          VERIFY_IS_TRUE(funcReader.GetNumResources() == 1);
+          VERIFY_ARE_EQUAL(funcReader.GetNumResources(), 1);
           hlsl::ShaderFlags flag;
           flag.SetUAVLoadAdditionalFormats(true);
           flag.SetLowPrecisionPresent(true);
           uint64_t rawFlag = flag.GetShaderFlagsRaw();
-          VERIFY_IS_TRUE(funcReader.GetFeatureFlag() == rawFlag);
+          VERIFY_ARE_EQUAL(funcReader.GetFeatureFlag(), rawFlag);
           ResourceReader resReader = funcReader.GetResource(0);
-          VERIFY_IS_TRUE(resReader.GetResourceClass() == hlsl::DXIL::ResourceClass::UAV);
-          VERIFY_IS_TRUE(resReader.GetResourceKind() == hlsl::DXIL::ResourceKind::Texture1D);
+          VERIFY_ARE_EQUAL(resReader.GetResourceClass(), hlsl::DXIL::ResourceClass::UAV);
+          VERIFY_ARE_EQUAL(resReader.GetResourceKind(), hlsl::DXIL::ResourceKind::Texture1D);
         }
         else if (cur_str.compare("function1") == 0) {
           hlsl::ShaderFlags flag;
           flag.SetLowPrecisionPresent(true);
           uint64_t rawFlag = flag.GetShaderFlagsRaw();
-          VERIFY_IS_TRUE(funcReader.GetFeatureFlag() == rawFlag);
-          VERIFY_IS_TRUE(funcReader.GetNumResources() == 3);
+          VERIFY_ARE_EQUAL(funcReader.GetFeatureFlag(), rawFlag);
+          VERIFY_ARE_EQUAL(funcReader.GetNumResources(), 3);
         }
         else if (cur_str.compare("function2") == 0) {
-          VERIFY_IS_TRUE((funcReader.GetFeatureFlag() & 0xffffffffffffffff) == 0);
-          VERIFY_IS_TRUE(funcReader.GetNumResources() == 0);
+          VERIFY_ARE_EQUAL(funcReader.GetFeatureFlag() & 0xffffffffffffffff, 0);
+          VERIFY_ARE_EQUAL(funcReader.GetNumResources(), 0);
           std::string dependency = funcReader.GetDependency(0);
           VERIFY_IS_TRUE(dependency.find("function_import") != std::string::npos);
         }
+        else if (cur_str.compare("function3") == 0) {
+          VERIFY_ARE_EQUAL(funcReader.GetFeatureFlag() & 0xffffffffffffffff, 0);
+          VERIFY_ARE_EQUAL(funcReader.GetNumResources(), numResFlagCheck);
+          for (unsigned i = 0; i < funcReader.GetNumResources(); ++i) {
+            ResourceReader resReader = funcReader.GetResource(0);
+            VERIFY_ARE_EQUAL(resReader.GetResourceClass(), hlsl::DXIL::ResourceClass::UAV);
+            unsigned j = 0;
+            for (; j < numResFlagCheck; ++j) {
+              if (resFlags[j].name.compare(resReader.GetName()) == 0)
+                break;
+            }
+            VERIFY_IS_LESS_THAN(j, numResFlagCheck);
+            VERIFY_ARE_EQUAL(resReader.GetResourceKind(), resFlags[j].kind);
+            VERIFY_ARE_EQUAL(resReader.GetFlags(), static_cast<uint32_t>(resFlags[j].flag));
+          }
+        }
         else {
           IFTBOOLMSG(false, E_FAIL, "unknown function name");
         }
       }
-      VERIFY_IS_TRUE(resTableReader->GetNumResources() == 4);
+      VERIFY_ARE_EQUAL(resTableReader->GetNumResources(), 8);
       // This is validation test for DxilRuntimeReflection implemented on DxilRuntimeReflection.inl
-      DxilRuntimeReflection reflection;
-      VERIFY_IS_TRUE(reflection.InitFromRDAT(pBlob->GetBufferPointer()));
-      DXIL_LIBRARY_DESC lib_reflection = reflection.GetLibraryReflection();
-      VERIFY_IS_TRUE(lib_reflection.NumFunctions == 3);
+      unique_ptr<DxilRuntimeReflection> pReflection(CreateDxilRuntimeReflection());
+      VERIFY_IS_TRUE(pReflection->InitFromRDAT(pBlob->GetBufferPointer()));
+      DXIL_LIBRARY_DESC lib_reflection = pReflection->GetLibraryReflection();
+      VERIFY_ARE_EQUAL(lib_reflection.NumFunctions, 4);
       for (uint32_t j = 0; j < 3; ++j) {
         DXIL_FUNCTION function = lib_reflection.pFunction[j];
         std::string cur_str = str;
@@ -764,14 +804,14 @@ TEST_F(DxilContainerTest, CompileWhenOkThenCheckRDAT) {
           uint64_t rawFlag = flag.GetShaderFlagsRaw();
           uint64_t featureFlag = static_cast<uint64_t>(function.FeatureInfo2) << 32;
           featureFlag |= static_cast<uint64_t>(function.FeatureInfo1);
-          VERIFY_IS_TRUE(featureFlag == rawFlag);
-          VERIFY_IS_TRUE(function.NumResources == 1);
-          VERIFY_IS_TRUE(function.NumFunctionDependencies == 0);
-          const DXIL_RESOURCE resource = function.Resources[0];
-          VERIFY_IS_TRUE(resource.Class == (uint32_t)hlsl::DXIL::ResourceClass::UAV);
-          VERIFY_IS_TRUE(resource.Kind == (uint32_t)hlsl::DXIL::ResourceKind::Texture1D);
+          VERIFY_ARE_EQUAL(featureFlag, rawFlag);
+          VERIFY_ARE_EQUAL(function.NumResources, 1);
+          VERIFY_ARE_EQUAL(function.NumFunctionDependencies, 0);
+          const DXIL_RESOURCE &resource = *function.Resources[0];
+          VERIFY_ARE_EQUAL(resource.Class, (uint32_t)hlsl::DXIL::ResourceClass::UAV);
+          VERIFY_ARE_EQUAL(resource.Kind, (uint32_t)hlsl::DXIL::ResourceKind::Texture1D);
           std::wstring wName = resource.Name;
-          VERIFY_IS_TRUE(wName.compare(L"tex") == 0);
+          VERIFY_ARE_EQUAL(wName.compare(L"tex"), 0);
         }
         else if (cur_str.compare("function1") == 0) {
           hlsl::ShaderFlags flag;
@@ -779,29 +819,49 @@ TEST_F(DxilContainerTest, CompileWhenOkThenCheckRDAT) {
           uint64_t rawFlag = flag.GetShaderFlagsRaw();
           uint64_t featureFlag = static_cast<uint64_t>(function.FeatureInfo2) << 32;
           featureFlag |= static_cast<uint64_t>(function.FeatureInfo1);
-          VERIFY_IS_TRUE(featureFlag == rawFlag);
-          VERIFY_IS_TRUE(function.NumResources == 3);
-          VERIFY_IS_TRUE(function.NumFunctionDependencies == 0);
+          VERIFY_ARE_EQUAL(featureFlag, rawFlag);
+          VERIFY_ARE_EQUAL(function.NumResources, 3);
+          VERIFY_ARE_EQUAL(function.NumFunctionDependencies, 0);
           std::unordered_set<std::wstring> stringSet = { L"$Globals", L"b_buf", L"tex2" };
           for (uint32_t j = 0; j < 3; ++j) {
-            const DXIL_RESOURCE resource = function.Resources[j];
+            const DXIL_RESOURCE &resource = *function.Resources[j];
             std::wstring compareName = resource.Name;
             VERIFY_IS_TRUE(stringSet.find(compareName) != stringSet.end());
           }
         }
         else if (cur_str.compare("function2") == 0) {
-          VERIFY_IS_TRUE(function.FeatureInfo1 == 0);
-          VERIFY_IS_TRUE(function.FeatureInfo2 == 0);
-          VERIFY_IS_TRUE(function.NumResources == 0);
-          VERIFY_IS_TRUE(function.NumFunctionDependencies == 1);
+          VERIFY_ARE_EQUAL(function.FeatureInfo1, 0);
+          VERIFY_ARE_EQUAL(function.FeatureInfo2, 0);
+          VERIFY_ARE_EQUAL(function.NumResources, 0);
+          VERIFY_ARE_EQUAL(function.NumFunctionDependencies, 1);
           std::wstring dependency = function.FunctionDependencies[0];
           VERIFY_IS_TRUE(dependency.find(L"function_import") != std::wstring::npos);
         }
+        else if (cur_str.compare("function3") == 0) {
+          VERIFY_ARE_EQUAL(function.FeatureInfo1, 0);
+          VERIFY_ARE_EQUAL(function.FeatureInfo2, 0);
+          VERIFY_ARE_EQUAL(function.NumResources, numResFlagCheck);
+          VERIFY_ARE_EQUAL(function.NumFunctionDependencies, 0);
+          for (unsigned i = 0; i < function.NumResources; ++i) {
+            const DXIL_RESOURCE *res = function.Resources[i];
+            VERIFY_ARE_EQUAL(res->Class, static_cast<uint32_t>(hlsl::DXIL::ResourceClass::UAV));
+            unsigned j = 0;
+            for (; j < numResFlagCheck; ++j) {
+              CA2W WName(resFlags[j].name.c_str());
+              std::wstring compareName(WName);
+              if (compareName.compare(res->Name) == 0)
+                break;
+            }
+            VERIFY_IS_LESS_THAN(j, numResFlagCheck);
+            VERIFY_ARE_EQUAL(res->Kind, static_cast<uint32_t>(resFlags[j].kind));
+            VERIFY_ARE_EQUAL(res->Flags, static_cast<uint32_t>(resFlags[j].flag));
+          }
+        }
         else {
           IFTBOOLMSG(false, E_FAIL, "unknown function name");
         }
       }
-      VERIFY_IS_TRUE(lib_reflection.NumResources == 4);
+      VERIFY_IS_TRUE(lib_reflection.NumResources == 8);
     }
   }
   IFTBOOLMSG(blobFound, E_FAIL, "failed to find RDAT blob after compiling");
@@ -847,7 +907,7 @@ TEST_F(DxilContainerTest, CompileWhenOkThenCheckRDAT2) {
     IFT(pReflection->GetPartKind(i, &kind));
     if (kind == (uint32_t)hlsl::DxilFourCC::DFCC_RuntimeData) {
       blobFound = true;
-      using namespace hlsl::DXIL::RDAT;
+      using namespace hlsl::RDAT;
       CComPtr<IDxcBlob> pBlob;
       IFT(pReflection->GetPartContent(i, &pBlob));
       DxilRuntimeData context;