Browse Source

PDB Utils returns hash struct and handles DXIL program header. (#3318)

Adam Yang 4 years ago
parent
commit
3ae6c7df39
2 changed files with 329 additions and 265 deletions
  1. 176 135
      tools/clang/tools/dxcompiler/dxcpdbutils.cpp
  2. 153 130
      tools/clang/unittests/HLSL/CompilerTest.cpp

+ 176 - 135
tools/clang/tools/dxcompiler/dxcpdbutils.cpp

@@ -91,7 +91,7 @@ private:
   };
 
   CComPtr<IDxcBlob> m_InputBlob;
-  CComPtr<IDxcBlobEncoding> m_pDxilPartBlob;
+  CComPtr<IDxcBlob> m_pDxilPartBlob;
   CComPtr<IDxcBlob> m_ContainerBlob;
   std::vector<Source_File> m_SourceFiles;
   std::vector<std::wstring> m_Defines;
@@ -118,50 +118,119 @@ private:
     m_HashBlob = nullptr;
   }
 
-public:
-  DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL()
-  DXC_MICROCOM_TM_ALLOC(DxcPdbUtils)
+  HRESULT HandleDebugProgramHeaderLegacy(IDxcBlob *pProgramBlob) {
+    UINT32 bitcode_size = 0;
+    const char *bitcode = nullptr;
 
-  DxcPdbUtils(IMalloc *pMalloc) : m_dwRef(0), m_pMalloc(pMalloc) {}
+    if (!hlsl::IsValidDxilProgramHeader((hlsl::DxilProgramHeader *)pProgramBlob->GetBufferPointer(), pProgramBlob->GetBufferSize()))
+      return E_FAIL;
 
-  HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) override {
-    return DoBasicQueryInterface<IDxcPdbUtils, IDxcPixDxilDebugInfoFactory>(this, iid, ppvObject);
-  }
+    hlsl::GetDxilProgramBitcode((hlsl::DxilProgramHeader *)pProgramBlob->GetBufferPointer(), &bitcode, &bitcode_size);
 
-  HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pPdbOrDxil) override {
-    DxcThreadMalloc TM(m_pMalloc);
+    llvm::LLVMContext context;
+    std::unique_ptr<llvm::Module> pModule;
 
-    ::llvm::sys::fs::MSFileSystem *msfPtr = nullptr;
-    IFT(CreateMSFileSystemForDisk(&msfPtr));
-    std::unique_ptr<::llvm::sys::fs::MSFileSystem> msf(msfPtr);
-  
-    ::llvm::sys::fs::AutoPerThreadSystem pts(msf.get());
-    IFTLLVM(pts.error_code());
+    // NOTE: this doesn't copy the memory, just references it.
+    std::unique_ptr<llvm::MemoryBuffer> mb = llvm::MemoryBuffer::getMemBuffer(StringRef(bitcode, bitcode_size), "-", /*RequiresNullTerminator*/ false);
 
-    if (!pPdbOrDxil)
-      return E_POINTER;
+    // Lazily parse the module
+    std::string DiagStr;
+    pModule = hlsl::dxilutil::LoadModuleFromBitcodeLazy(std::move(mb), context, DiagStr);
+    if (!pModule)
+      return E_FAIL;
 
-    // Remove all the data
-    Reset();
+    // Materialize only the stuff we need, so it's fast
+    {
+      llvm::StringRef DebugMetadataList[] = {
+        hlsl::DxilMDHelper::kDxilSourceContentsMDName,
+        hlsl::DxilMDHelper::kDxilSourceDefinesMDName,
+        hlsl::DxilMDHelper::kDxilSourceArgsMDName,
+        hlsl::DxilMDHelper::kDxilVersionMDName,
+        hlsl::DxilMDHelper::kDxilShaderModelMDName,
+        hlsl::DxilMDHelper::kDxilEntryPointsMDName,
+        hlsl::DxilMDHelper::kDxilSourceMainFileNameMDName,
+      };
+      pModule->materializeSelectNamedMetadata(DebugMetadataList);
+    }
 
-    m_InputBlob = pPdbOrDxil;
+    hlsl::DxilModule &DM = pModule->GetOrCreateDxilModule();
+    m_EntryPoint = ToWstring(DM.GetEntryFunctionName());
+    m_TargetProfile = ToWstring(DM.GetShaderModel()->GetName());
 
-    // Right now, what we do here is just to support the current PDB formats.
-    // Note: this API only supports PDB blob, and DXIL container, not DXIL module or program header,
-    // because we're moving away from that.
-    //
-    {
-      CComPtr<IStream> pStream;
-      IFR(hlsl::CreateReadOnlyBlobStream(pPdbOrDxil, &pStream));
-      if (SUCCEEDED(hlsl::pdb::LoadDataFromStream(m_pMalloc, pStream, &m_ContainerBlob))) {}
-      else if (hlsl::IsValidDxilContainer((const hlsl::DxilContainerHeader *)pPdbOrDxil->GetBufferPointer(), pPdbOrDxil->GetBufferSize())) {
-        m_ContainerBlob = pPdbOrDxil;
+    // For each all the named metadata node in the module
+    for (llvm::NamedMDNode &node : pModule->named_metadata()) {
+      llvm::StringRef node_name = node.getName();
+
+      // dx.source.content
+      if (node_name == hlsl::DxilMDHelper::kDxilSourceContentsMDName ||
+          node_name == hlsl::DxilMDHelper::kDxilSourceContentsOldMDName)
+      {
+        for (unsigned i = 0; i < node.getNumOperands(); i++) {
+          llvm::MDTuple *tup = cast<llvm::MDTuple>(node.getOperand(i));
+          MDString *md_name = cast<MDString>(tup->getOperand(0));
+          MDString *md_content = cast<MDString>(tup->getOperand(1));
+
+          // File name
+          Source_File file;
+          file.Name = ToWstring(md_name->getString());
+
+          // File content
+          IFR(hlsl::DxcCreateBlobWithEncodingOnHeapCopy(
+            md_content->getString().data(),
+            md_content->getString().size(),
+            CP_ACP, // NOTE: ACP instead of UTF8 because it's possible for compiler implementations to
+                    // inject non-UTF8 data here.
+            &file.Content));
+
+          m_SourceFiles.push_back(std::move(file));
+        }
       }
-      else {
-        return E_INVALIDARG;
+      // dx.source.defines
+      else if (node_name == hlsl::DxilMDHelper::kDxilSourceDefinesMDName ||
+               node_name == hlsl::DxilMDHelper::kDxilSourceDefinesOldMDName)
+      {
+        MDTuple *tup = cast<MDTuple>(node.getOperand(0));
+        for (unsigned i = 0; i < tup->getNumOperands(); i++) {
+          StringRef define = cast<MDString>(tup->getOperand(i))->getString();
+          m_Defines.push_back(ToWstring(define));
+        }
+      }
+      // dx.source.mainFileName
+      else if (node_name == hlsl::DxilMDHelper::kDxilSourceMainFileNameMDName ||
+               node_name == hlsl::DxilMDHelper::kDxilSourceMainFileNameOldMDName)
+      {
+        MDTuple *tup = cast<MDTuple>(node.getOperand(0));
+        MDString *str = cast<MDString>(tup->getOperand(0));
+        m_MainFileName = ToWstring(str->getString());
+      }
+      // dx.source.args
+      else if (node_name == hlsl::DxilMDHelper::kDxilSourceArgsMDName ||
+               node_name == hlsl::DxilMDHelper::kDxilSourceArgsOldMDName)
+      {
+        MDTuple *tup = cast<MDTuple>(node.getOperand(0));
+        // Args
+        for (unsigned i = 0; i < tup->getNumOperands(); i++) {
+          StringRef arg = cast<MDString>(tup->getOperand(i))->getString();
+          m_Args.push_back(ToWstring(arg));
+        }
+
+        // Flags - which exclude entry point, target profile, and defines
+        for (unsigned i = 0; i < tup->getNumOperands(); i++) {
+          StringRef arg = cast<MDString>(tup->getOperand(i))->getString();
+          bool skip_another_arg = false;
+          if (ShouldIncludeInFlags(arg, &skip_another_arg)) {
+            m_Flags.push_back(ToWstring(arg));
+          }
+          if (skip_another_arg)
+            i++;
+        }
       }
     }
 
+    return S_OK;
+  }
+
+  HRESULT HandleDxilContainer(IDxcBlob *pContainer, IDxcBlob **ppDebugProgramBlob) {
     const hlsl::DxilContainerHeader *header = (hlsl::DxilContainerHeader *)m_ContainerBlob->GetBufferPointer();
     for (auto it = hlsl::begin(header); it != hlsl::end(header); it++) {
       const hlsl::DxilPartHeader *part = *it;
@@ -172,7 +241,7 @@ public:
       case hlsl::DFCC_ShaderHash:
       {
         const hlsl::DxilShaderHash *hash_header = (hlsl::DxilShaderHash *)(part+1);
-        IFR(hlsl::DxcCreateBlobOnHeapCopy(hash_header->Digest, sizeof(hash_header->Digest), &m_HashBlob));
+        IFR(hlsl::DxcCreateBlobOnHeapCopy(hash_header, sizeof(*hash_header), &m_HashBlob));
       } break;
 
       case hlsl::DFCC_ShaderDebugName:
@@ -186,115 +255,87 @@ public:
       {
         hlsl::DxilProgramHeader *program_header = (hlsl::DxilProgramHeader *)(part+1);
 
-        IFR(hlsl::DxcCreateBlobWithEncodingFromPinned(program_header, program_header->SizeInUint32*sizeof(UINT32), CP_ACP, &m_pDxilPartBlob));
+        CComPtr<IDxcBlobEncoding> pProgramHeaderBlob;
+        IFR(hlsl::DxcCreateBlobWithEncodingFromPinned(program_header, program_header->SizeInUint32*sizeof(UINT32), CP_ACP, &pProgramHeaderBlob));
+        IFR(pProgramHeaderBlob.QueryInterface(ppDebugProgramBlob));
+
+      } break; // hlsl::DFCC_ShaderDebugInfoDXIL
+      } // switch (four_cc)
+    } // For each part
+
+    return S_OK;
+  }
 
-        UINT32 bitcode_size = 0;
-        const char *bitcode = nullptr;
-        hlsl::GetDxilProgramBitcode(program_header, &bitcode, &bitcode_size);
+public:
+  DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL()
+  DXC_MICROCOM_TM_ALLOC(DxcPdbUtils)
 
-        llvm::LLVMContext context;
-        std::unique_ptr<llvm::Module> pModule;
+  DxcPdbUtils(IMalloc *pMalloc) : m_dwRef(0), m_pMalloc(pMalloc) {}
 
-        // NOTE: this doesn't copy the memory, just references it.
-        std::unique_ptr<llvm::MemoryBuffer> mb = llvm::MemoryBuffer::getMemBuffer(StringRef(bitcode, bitcode_size), "-", /*RequiresNullTerminator*/ false);
+  HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) override {
+    return DoBasicQueryInterface<IDxcPdbUtils, IDxcPixDxilDebugInfoFactory>(this, iid, ppvObject);
+  }
 
-        // Lazily parse the module
-        std::string DiagStr;
-        pModule = hlsl::dxilutil::LoadModuleFromBitcodeLazy(std::move(mb), context, DiagStr);
-        if (!pModule)
-          return E_FAIL;
+  HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pPdbOrDxil) override {
+    DxcThreadMalloc TM(m_pMalloc);
 
-        // Materialize only the stuff we need, so it's fast
-        {
-          llvm::StringRef DebugMetadataList[] = {
-            hlsl::DxilMDHelper::kDxilSourceContentsMDName,
-            hlsl::DxilMDHelper::kDxilSourceDefinesMDName,
-            hlsl::DxilMDHelper::kDxilSourceArgsMDName,
-            hlsl::DxilMDHelper::kDxilVersionMDName,
-            hlsl::DxilMDHelper::kDxilShaderModelMDName,
-            hlsl::DxilMDHelper::kDxilEntryPointsMDName,
-            hlsl::DxilMDHelper::kDxilSourceMainFileNameMDName,
-          };
-          pModule->materializeSelectNamedMetadata(DebugMetadataList);
-        }
+    ::llvm::sys::fs::MSFileSystem *msfPtr = nullptr;
+    IFT(CreateMSFileSystemForDisk(&msfPtr));
+    std::unique_ptr<::llvm::sys::fs::MSFileSystem> msf(msfPtr);
+  
+    ::llvm::sys::fs::AutoPerThreadSystem pts(msf.get());
+    IFTLLVM(pts.error_code());
 
-        hlsl::DxilModule &DM = pModule->GetOrCreateDxilModule();
-        m_EntryPoint = ToWstring(DM.GetEntryFunctionName());
-        m_TargetProfile = ToWstring(DM.GetShaderModel()->GetName());
-
-        // For each all the named metadata node in the module
-        for (llvm::NamedMDNode &node : pModule->named_metadata()) {
-          llvm::StringRef node_name = node.getName();
-
-          // dx.source.content
-          if (node_name == hlsl::DxilMDHelper::kDxilSourceContentsMDName ||
-              node_name == hlsl::DxilMDHelper::kDxilSourceContentsOldMDName)
-          {
-            for (unsigned i = 0; i < node.getNumOperands(); i++) {
-              llvm::MDTuple *tup = cast<llvm::MDTuple>(node.getOperand(i));
-              MDString *md_name = cast<MDString>(tup->getOperand(0));
-              MDString *md_content = cast<MDString>(tup->getOperand(1));
-
-              // File name
-              Source_File file;
-              file.Name = ToWstring(md_name->getString());
-
-              // File content
-              IFR(hlsl::DxcCreateBlobWithEncodingOnHeapCopy(
-                md_content->getString().data(),
-                md_content->getString().size(),
-                CP_ACP, // NOTE: ACP instead of UTF8 because it's possible for compiler implementations to
-                        // inject non-UTF8 data here.
-                &file.Content));
-
-              m_SourceFiles.push_back(std::move(file));
-            }
-          }
-          // dx.source.defines
-          else if (node_name == hlsl::DxilMDHelper::kDxilSourceDefinesMDName ||
-                   node_name == hlsl::DxilMDHelper::kDxilSourceDefinesOldMDName)
-          {
-            MDTuple *tup = cast<MDTuple>(node.getOperand(0));
-            for (unsigned i = 0; i < tup->getNumOperands(); i++) {
-              StringRef define = cast<MDString>(tup->getOperand(i))->getString();
-              m_Defines.push_back(ToWstring(define));
-            }
-          }
-          // dx.source.mainFileName
-          else if (node_name == hlsl::DxilMDHelper::kDxilSourceMainFileNameMDName ||
-                   node_name == hlsl::DxilMDHelper::kDxilSourceMainFileNameOldMDName)
-          {
-            MDTuple *tup = cast<MDTuple>(node.getOperand(0));
-            MDString *str = cast<MDString>(tup->getOperand(0));
-            m_MainFileName = ToWstring(str->getString());
-          }
-          // dx.source.args
-          else if (node_name == hlsl::DxilMDHelper::kDxilSourceArgsMDName ||
-                   node_name == hlsl::DxilMDHelper::kDxilSourceArgsOldMDName)
-          {
-            MDTuple *tup = cast<MDTuple>(node.getOperand(0));
-            // Args
-            for (unsigned i = 0; i < tup->getNumOperands(); i++) {
-              StringRef arg = cast<MDString>(tup->getOperand(i))->getString();
-              m_Args.push_back(ToWstring(arg));
-            }
-
-            // Flags - which exclude entry point, target profile, and defines
-            for (unsigned i = 0; i < tup->getNumOperands(); i++) {
-              StringRef arg = cast<MDString>(tup->getOperand(i))->getString();
-              bool skip_another_arg = false;
-              if (ShouldIncludeInFlags(arg, &skip_another_arg)) {
-                m_Flags.push_back(ToWstring(arg));
-              }
-              if (skip_another_arg)
-                i++;
-            }
-          }
+    if (!pPdbOrDxil)
+      return E_POINTER;
+
+    // Remove all the data
+    Reset();
+
+    m_InputBlob = pPdbOrDxil;
+
+    // Right now, what we do here is just to support the current PDB formats.
+    {
+      CComPtr<IStream> pStream;
+      IFR(hlsl::CreateReadOnlyBlobStream(pPdbOrDxil, &pStream));
+
+      // PDB
+      if (SUCCEEDED(hlsl::pdb::LoadDataFromStream(m_pMalloc, pStream, &m_ContainerBlob))) {
+        IFR(HandleDxilContainer(m_ContainerBlob, &m_pDxilPartBlob));
+        if (m_pDxilPartBlob) {
+          IFR(HandleDebugProgramHeaderLegacy(m_pDxilPartBlob));
+        }
+        else {
+          // Must have a dxil part
+          return E_FAIL;
+        }
+      }
+      // DXIL Container
+      else if (hlsl::IsValidDxilContainer((const hlsl::DxilContainerHeader *)pPdbOrDxil->GetBufferPointer(), pPdbOrDxil->GetBufferSize())) {
+        m_ContainerBlob = pPdbOrDxil;
+        IFR(HandleDxilContainer(m_ContainerBlob, &m_pDxilPartBlob));
+        if (m_pDxilPartBlob) {
+          IFR(HandleDebugProgramHeaderLegacy(m_pDxilPartBlob));
+        }
+        else {
+          // Must have a dxil part
+          return E_FAIL;
         }
+      }
+      // DXIL program header
+      else if (hlsl::IsValidDxilProgramHeader((hlsl::DxilProgramHeader *)pPdbOrDxil->GetBufferPointer(), pPdbOrDxil->GetBufferSize())) {
+        CComPtr<IDxcBlobEncoding> pProgramHeaderBlob;
+        IFR(hlsl::DxcCreateBlobWithEncodingFromPinned(
+          (hlsl::DxilProgramHeader *)pPdbOrDxil->GetBufferPointer(),
+          pPdbOrDxil->GetBufferSize(), CP_ACP, &pProgramHeaderBlob));
+        IFR(pProgramHeaderBlob.QueryInterface(&m_pDxilPartBlob));
+        IFR(HandleDebugProgramHeaderLegacy(m_pDxilPartBlob));
+      }
+      else {
+        return E_INVALIDARG;
+      }
+    }
 
-      } break; // hlsl::DFCC_ShaderDebugInfoDXIL
-      } // switch (four_cc)
-    } // For each part
 
     return S_OK;
   }

+ 153 - 130
tools/clang/unittests/HLSL/CompilerTest.cpp

@@ -975,12 +975,143 @@ TEST_F(CompilerTest, CompileThenAddCustomDebugName) {
   VERIFY_IS_NULL(pPartHeader);
 }
 
+static void VerifyPdbUtil(IDxcPdbUtils *pPdbUtils, bool HasHashAndPdbName, IDxcBlob *pBlob, const std::string &main_source, const std::string &included_File) {
+  VERIFY_SUCCEEDED(pPdbUtils->Load(pBlob));
+
+  // Target profile
+  {
+    CComBSTR str;
+    VERIFY_SUCCEEDED(pPdbUtils->GetTargetProfile(&str));
+    VERIFY_ARE_EQUAL(str, L"ps_6_0");
+  }
+
+  // Entry point
+  {
+    CComBSTR str;
+    VERIFY_SUCCEEDED(pPdbUtils->GetEntryPoint(&str));
+    VERIFY_ARE_EQUAL(str, L"PSMain");
+  }
+
+  // PDB file path
+  if (HasHashAndPdbName) {
+    CComBSTR pName;
+    VERIFY_SUCCEEDED(pPdbUtils->GetName(&pName));
+    std::wstring suffix = L".pdb";
+    VERIFY_IS_TRUE(pName.Length() >= suffix.size());
+    VERIFY_IS_TRUE(
+      0 == std::memcmp(suffix.c_str(), &pName[pName.Length() - suffix.size()], suffix.size()));
+  }
+
+  // Main file name
+  {
+    CComBSTR pMainFileName;
+    VERIFY_SUCCEEDED(pPdbUtils->GetMainFileName(&pMainFileName));
+    VERIFY_ARE_EQUAL(pMainFileName, L"source.hlsl");
+  }
+
+  // This is a full PDB
+  {
+    VERIFY_IS_TRUE(pPdbUtils->IsFullPDB());
+    CComPtr<IDxcBlob> pPDBBlob;
+    VERIFY_SUCCEEDED(pPdbUtils->GetFullPDB(&pPDBBlob));
+  }
+
+  // There is hash and hash is not empty
+  if (HasHashAndPdbName) {
+    CComPtr<IDxcBlob> pHash;
+    VERIFY_SUCCEEDED(pPdbUtils->GetHash(&pHash));
+    hlsl::DxilShaderHash EmptyHash = {};
+    VERIFY_ARE_EQUAL(pHash->GetBufferSize(), sizeof(EmptyHash));
+    VERIFY_IS_FALSE(0 == std::memcmp(pHash->GetBufferPointer(), &EmptyHash, sizeof(EmptyHash)));
+  }
+
+  // Source files
+  {
+    UINT32 uSourceCount = 0;
+    VERIFY_SUCCEEDED(pPdbUtils->GetSourceCount(&uSourceCount));
+    for (UINT32 i = 0; i < uSourceCount; i++) {
+      CComBSTR pFileName;
+      CComPtr<IDxcBlobEncoding> pFileContent;
+      VERIFY_SUCCEEDED(pPdbUtils->GetSourceName(i, &pFileName));
+      VERIFY_SUCCEEDED(pPdbUtils->GetSource(i, &pFileContent));
+      if (0 == wcscmp(pFileName, L"source.hlsl")) {
+        VERIFY_IS_TRUE(pFileContent->GetBufferSize() == main_source.size());
+        VERIFY_IS_TRUE(0 == std::memcmp(pFileContent->GetBufferPointer(), main_source.data(), main_source.size()));
+      }
+      else {
+        VERIFY_IS_TRUE(0 == std::memcmp(pFileContent->GetBufferPointer(), included_File.data(), included_File.size()));
+      }
+    }
+  }
+
+  // Defines
+  {
+    UINT32 uDefineCount = 0;
+    std::map<std::wstring, int> pdb_defines;
+    VERIFY_SUCCEEDED(pPdbUtils->GetDefineCount(&uDefineCount));
+    VERIFY_IS_TRUE(uDefineCount == 2);
+    for (UINT32 i = 0; i < uDefineCount; i++) {
+      CComBSTR def;
+      VERIFY_SUCCEEDED(pPdbUtils->GetDefine(i, &def));
+      pdb_defines[std::wstring(def)]++;
+    }
+    VERIFY_IS_TRUE(1 == pdb_defines[L"THIS_IS_A_DEFINE=HELLO"]);
+    VERIFY_IS_TRUE(1 == pdb_defines[L"THIS_IS_ANOTHER_DEFINE=1"]);
+  }
+
+  // Flags
+  {
+    const WCHAR *pExpectedFlags[] = { L"/Zi", L"/Od", L"-flegacy-macro-expansion", L"-Qembed_debug", };
+
+    UINT32 uCount = 0;
+    std::map<std::wstring, int> tally;
+    VERIFY_SUCCEEDED(pPdbUtils->GetFlagCount(&uCount));
+    VERIFY_IS_TRUE(uCount == _countof(pExpectedFlags));
+    for (UINT32 i = 0; i < uCount; i++) {
+      CComBSTR def;
+      VERIFY_SUCCEEDED(pPdbUtils->GetFlag(i, &def));
+      tally[std::wstring(def)]++;
+    }
+    for (unsigned i = 0; i < _countof(pExpectedFlags); i++) {
+      VERIFY_IS_TRUE(1 == tally[pExpectedFlags[i]]);
+    }
+  }
+
+  // Args
+  {
+    UINT32 uCount = 0;
+    std::map<std::wstring, int> tally;
+    VERIFY_SUCCEEDED(pPdbUtils->GetArgCount(&uCount));
+    for (UINT32 i = 0; i < uCount; i++) {
+      CComBSTR def;
+      VERIFY_SUCCEEDED(pPdbUtils->GetArg(i, &def));
+      tally[std::wstring(def)]++;
+    }
+    VERIFY_IS_TRUE(1 == tally[L"/Zi"]);
+    VERIFY_IS_TRUE(1 == tally[L"/Od"]);
+    VERIFY_IS_TRUE(1 == tally[L"-flegacy-macro-expansion"]);
+    VERIFY_IS_TRUE(1 == tally[L"-Qembed_debug"]);
+    VERIFY_IS_TRUE(1 == tally[L"/DTHIS_IS_A_DEFINE=HELLO"]);
+  }
+
+  // Make the pix debug info
+  {
+    CComPtr<IDxcPixDxilDebugInfoFactory> pFactory;
+    VERIFY_SUCCEEDED(pPdbUtils->QueryInterface(&pFactory));
+    CComPtr<IDxcPixCompilationInfo> pCompInfo;
+    VERIFY_ARE_EQUAL(E_NOTIMPL, pFactory->NewDxcPixCompilationInfo(&pCompInfo));
+    CComPtr<IDxcPixDxilDebugInfo> pDebugInfo;
+    VERIFY_SUCCEEDED(pFactory->NewDxcPixDxilDebugInfo(&pDebugInfo));
+    VERIFY_ARE_NOT_EQUAL(pDebugInfo, nullptr);
+  }
+}
+
 #ifdef _WIN32
 TEST_F(CompilerTest, CompileThenTestPdbUtils) {
   CComPtr<TestIncludeHandler> pInclude;
   CComPtr<IDxcCompiler> pCompiler;
   CComPtr<IDxcBlobEncoding> pSource;
-  CComPtr<IDxcOperationResult> pResult;
+  CComPtr<IDxcOperationResult> pOperationResult;
 
   std::string main_source = "#include \"helper.h\"\r\n"
     "float4 PSMain() : SV_Target { return ZERO; }";
@@ -996,148 +1127,40 @@ TEST_F(CompilerTest, CompileThenTestPdbUtils) {
   const DxcDefine pDefines[] = { L"THIS_IS_ANOTHER_DEFINE", L"1" };
 
   VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"PSMain",
-    L"ps_6_0", pArgs, _countof(pArgs), pDefines, _countof(pDefines), pInclude, &pResult));
+    L"ps_6_0", pArgs, _countof(pArgs), pDefines, _countof(pDefines), pInclude, &pOperationResult));
 
   HRESULT CompileStatus = S_OK;
-  VERIFY_SUCCEEDED(pResult->GetStatus(&CompileStatus));
+  VERIFY_SUCCEEDED(pOperationResult->GetStatus(&CompileStatus));
   VERIFY_SUCCEEDED(CompileStatus);
 
   CComPtr<IDxcBlob> pCompiledBlob;
-  VERIFY_SUCCEEDED(pResult->GetResult(&pCompiledBlob));
+  VERIFY_SUCCEEDED(pOperationResult->GetResult(&pCompiledBlob));
 
-  CComPtr<IDxcPdbUtils> pPdbUtils;
-  VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcPdbUtils, &pPdbUtils));
-
-  {
-    VERIFY_SUCCEEDED(pPdbUtils->Load(pCompiledBlob));
-
-    // Target profile
-    {
-      CComBSTR str;
-      VERIFY_SUCCEEDED(pPdbUtils->GetTargetProfile(&str));
-      VERIFY_ARE_EQUAL(str, L"ps_6_0");
-    }
-
-    // Entry point
-    {
-      CComBSTR str;
-      VERIFY_SUCCEEDED(pPdbUtils->GetEntryPoint(&str));
-      VERIFY_ARE_EQUAL(str, L"PSMain");
-    }
+  CComPtr<IDxcResult> pResult;
+  VERIFY_SUCCEEDED(pOperationResult.QueryInterface(&pResult));
 
-    // PDB file path
-    {
-      CComBSTR pName;
-      VERIFY_SUCCEEDED(pPdbUtils->GetName(&pName));
-      std::wstring suffix = L".pdb";
-      VERIFY_IS_TRUE(pName.Length() >= suffix.size());
-      VERIFY_IS_TRUE(
-        0 == std::memcmp(suffix.c_str(), &pName[pName.Length() - suffix.size()], suffix.size()));
-    }
-
-    // Main file name
-    {
-      CComBSTR pMainFileName;
-      VERIFY_SUCCEEDED(pPdbUtils->GetMainFileName(&pMainFileName));
-      VERIFY_ARE_EQUAL(pMainFileName, L"source.hlsl");
-    }
-
-    // This is a full PDB
-    {
-      VERIFY_IS_TRUE(pPdbUtils->IsFullPDB());
-      CComPtr<IDxcBlob> pPDBBlob;
-      VERIFY_SUCCEEDED(pPdbUtils->GetFullPDB(&pPDBBlob));
-    }
-
-    // There is hash and hash is not empty
-    {
-      CComPtr<IDxcBlob> pHash;
-      VERIFY_SUCCEEDED(pPdbUtils->GetHash(&pHash));
-      BYTE EmptyHash[16] = {};
-      VERIFY_ARE_EQUAL(pHash->GetBufferSize(), _countof(EmptyHash));
-      VERIFY_IS_FALSE(0 == std::memcmp(pHash->GetBufferPointer(), EmptyHash, _countof(EmptyHash)));
-    }
+  CComPtr<IDxcBlob> pPdbBlob;
+  VERIFY_SUCCEEDED(pResult->GetOutput(DXC_OUT_PDB, IID_PPV_ARGS(&pPdbBlob), nullptr));
 
-    // Source files
-    {
-      UINT32 uSourceCount = 0;
-      VERIFY_SUCCEEDED(pPdbUtils->GetSourceCount(&uSourceCount));
-      for (UINT32 i = 0; i < uSourceCount; i++) {
-        CComBSTR pFileName;
-        CComPtr<IDxcBlobEncoding> pFileContent;
-        VERIFY_SUCCEEDED(pPdbUtils->GetSourceName(i, &pFileName));
-        VERIFY_SUCCEEDED(pPdbUtils->GetSource(i, &pFileContent));
-        if (0 == wcscmp(pFileName, L"source.hlsl")) {
-          VERIFY_IS_TRUE(pFileContent->GetBufferSize() == main_source.size());
-          VERIFY_IS_TRUE(0 == std::memcmp(pFileContent->GetBufferPointer(), main_source.data(), main_source.size()));
-        }
-        else {
-          VERIFY_IS_TRUE(0 == std::memcmp(pFileContent->GetBufferPointer(), included_File.data(), included_File.size()));
-        }
-      }
-    }
 
-    // Defines
-    {
-      UINT32 uDefineCount = 0;
-      std::map<std::wstring, int> pdb_defines;
-      VERIFY_SUCCEEDED(pPdbUtils->GetDefineCount(&uDefineCount));
-      VERIFY_IS_TRUE(uDefineCount == 2);
-      for (UINT32 i = 0; i < uDefineCount; i++) {
-        CComBSTR def;
-        VERIFY_SUCCEEDED(pPdbUtils->GetDefine(i, &def));
-        pdb_defines[std::wstring(def)]++;
-      }
-      VERIFY_IS_TRUE(1 == pdb_defines[L"THIS_IS_A_DEFINE=HELLO"]);
-      VERIFY_IS_TRUE(1 == pdb_defines[L"THIS_IS_ANOTHER_DEFINE=1"]);
-    }
+  CComPtr<IDxcPdbUtils> pPdbUtils;
+  VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcPdbUtils, &pPdbUtils));
 
-    // Flags
-    {
-      const WCHAR *pExpectedFlags[] = { L"/Zi", L"/Od", L"-flegacy-macro-expansion", L"-Qembed_debug", };
-
-      UINT32 uCount = 0;
-      std::map<std::wstring, int> tally;
-      VERIFY_SUCCEEDED(pPdbUtils->GetFlagCount(&uCount));
-      VERIFY_IS_TRUE(uCount == _countof(pExpectedFlags));
-      for (UINT32 i = 0; i < uCount; i++) {
-        CComBSTR def;
-        VERIFY_SUCCEEDED(pPdbUtils->GetFlag(i, &def));
-        tally[std::wstring(def)]++;
-      }
-      for (unsigned i = 0; i < _countof(pExpectedFlags); i++) {
-        VERIFY_IS_TRUE(1 == tally[pExpectedFlags[i]]);
-      }
-    }
+  CComPtr<IDxcBlob> pProgramHeaderBlob;
+  {
+    CComPtr<IDxcContainerReflection> pRef;
+    VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcContainerReflection, &pRef));
+    VERIFY_SUCCEEDED(pRef->Load(pPdbBlob));
 
-    // Args
-    {
-      UINT32 uCount = 0;
-      std::map<std::wstring, int> tally;
-      VERIFY_SUCCEEDED(pPdbUtils->GetArgCount(&uCount));
-      for (UINT32 i = 0; i < uCount; i++) {
-        CComBSTR def;
-        VERIFY_SUCCEEDED(pPdbUtils->GetArg(i, &def));
-        tally[std::wstring(def)]++;
-      }
-      VERIFY_IS_TRUE(1 == tally[L"/Zi"]);
-      VERIFY_IS_TRUE(1 == tally[L"/Od"]);
-      VERIFY_IS_TRUE(1 == tally[L"-flegacy-macro-expansion"]);
-      VERIFY_IS_TRUE(1 == tally[L"-Qembed_debug"]);
-      VERIFY_IS_TRUE(1 == tally[L"/DTHIS_IS_A_DEFINE=HELLO"]);
-    }
+    UINT32 uIndex = 0;
+    VERIFY_SUCCEEDED(pRef->FindFirstPartKind(hlsl::DFCC_ShaderDebugInfoDXIL, &uIndex));
 
-    // Make the pix debug info
-    {
-      CComPtr<IDxcPixDxilDebugInfoFactory> pFactory;
-      VERIFY_SUCCEEDED(pPdbUtils.QueryInterface(&pFactory));
-      CComPtr<IDxcPixCompilationInfo> pCompInfo;
-      VERIFY_ARE_EQUAL(E_NOTIMPL, pFactory->NewDxcPixCompilationInfo(&pCompInfo));
-      CComPtr<IDxcPixDxilDebugInfo> pDebugInfo;
-      VERIFY_SUCCEEDED(pFactory->NewDxcPixDxilDebugInfo(&pDebugInfo));
-      VERIFY_ARE_NOT_EQUAL(pDebugInfo, nullptr);
-    }
+    VERIFY_SUCCEEDED(pRef->GetPartContent(uIndex, &pProgramHeaderBlob));
   }
+
+  VerifyPdbUtil(pPdbUtils, false, pProgramHeaderBlob, main_source, included_File);
+  VerifyPdbUtil(pPdbUtils, true,  pCompiledBlob, main_source, included_File);
+  VerifyPdbUtil(pPdbUtils, true,  pPdbBlob, main_source, included_File);
 }
 #endif