Browse Source

PIX: Add new API to retrieve info about compilation options (macros, target profile etc) (#2758)

This lets PIX call a much better-matched API than DIA to retrieve these things.
Jeff Noyle 5 năm trước cách đây
mục cha
commit
816f3141d4

+ 21 - 0
include/dxc/dxcpix.h

@@ -152,11 +152,32 @@ IDxcPixDxilDebugInfo : public IUnknown
       _Out_ DWORD* StackDepth) = 0;
       _Out_ DWORD* StackDepth) = 0;
 };
 };
 
 
+struct __declspec(uuid("61b16c95-8799-4ed8-bdb0-3b6c08a141b4"))
+IDxcPixCompilationInfo : public IUnknown
+{
+  virtual STDMETHODIMP GetSourceFile(
+      _In_ DWORD SourceFileOrdinal,
+      _Outptr_result_z_ BSTR *pSourceName,
+      _Outptr_result_z_ BSTR *pSourceContents) = 0;
+  virtual STDMETHODIMP GetArguments(
+      _Outptr_result_z_ BSTR *pArguments) = 0;
+  virtual STDMETHODIMP GetMacroDefinitions(
+      _Outptr_result_z_ BSTR *pMacroDefinitions) = 0;
+  virtual STDMETHODIMP GetEntryPointFile(
+    _Outptr_result_z_ BSTR *pEntryPointFile) = 0;
+  virtual STDMETHODIMP GetHlslTarget(
+    _Outptr_result_z_ BSTR *pHlslTarget) = 0;
+  virtual STDMETHODIMP GetEntryPoint(
+    _Outptr_result_z_ BSTR *pEntryPoint) = 0;
+};
+
 struct __declspec(uuid("9c2a040d-8068-44ec-8c68-8bfef1b43789"))
 struct __declspec(uuid("9c2a040d-8068-44ec-8c68-8bfef1b43789"))
 IDxcPixDxilDebugInfoFactory : public IUnknown
 IDxcPixDxilDebugInfoFactory : public IUnknown
 {
 {
   virtual STDMETHODIMP NewDxcPixDxilDebugInfo(
   virtual STDMETHODIMP NewDxcPixDxilDebugInfo(
       _COM_Outptr_ IDxcPixDxilDebugInfo **ppDxilDebugInfo) = 0;
       _COM_Outptr_ IDxcPixDxilDebugInfo **ppDxilDebugInfo) = 0;
+  virtual STDMETHODIMP NewDxcPixCompilationInfo(
+      _COM_Outptr_ IDxcPixCompilationInfo **ppCompilationInfo) = 0;
 };
 };
 
 
 #ifndef CLSID_SCOPE
 #ifndef CLSID_SCOPE

+ 1 - 0
lib/DxilDia/CMakeLists.txt

@@ -6,6 +6,7 @@ if (WIN32)
 endif (WIN32)
 endif (WIN32)
 
 
 add_llvm_library(LLVMDxilDia
 add_llvm_library(LLVMDxilDia
+  DxcPixCompilationInfo.cpp
   DxcPixDxilDebugInfo.cpp
   DxcPixDxilDebugInfo.cpp
   DxcPixDxilStorage.cpp
   DxcPixDxilStorage.cpp
   DxcPixEntrypoints.cpp
   DxcPixEntrypoints.cpp

+ 264 - 0
lib/DxilDia/DxcPixCompilationInfo.cpp

@@ -0,0 +1,264 @@
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// DxcPixCompilationInfo.cpp                                                 //
+// Copyright (C) Microsoft Corporation. All rights reserved.                 //
+// This file is distributed under the University of Illinois Open Source     //
+// License. See LICENSE.TXT for details.                                     //
+//                                                                           //
+// Defines all of the entrypoints for DXC's PIX interfaces for returning     //
+// compilation parameters such as target profile, entry point, etc.          //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+#include "dxc/Support/WinIncludes.h"
+
+#include "dxc/dxcapi.h"
+#include "dxc/dxcpix.h"
+
+#include "dxc/Support/FileIOHelper.h"
+#include "dxc/Support/Global.h"
+#include "dxc/Support/microcom.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MSFileSystem.h"
+
+#include "DxcPixBase.h"
+#include "DxcPixDxilDebugInfo.h"
+
+#include <functional>
+
+#include "dxc/Support/WinIncludes.h"
+
+#include "DxcPixCompilationInfo.h"
+#include "DxcPixDxilDebugInfo.h"
+
+#include "dxc/Support/Global.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/Module.h"
+
+#include "DxilDiaSession.h"
+
+#include <unordered_map>
+
+namespace dxil_debug_info {
+
+struct CompilationInfo : public IDxcPixCompilationInfo {
+private:
+  DXC_MICROCOM_TM_REF_FIELDS();
+
+  dxil_dia::Session *m_pSession;
+  llvm::NamedMDNode *m_contents;
+  llvm::NamedMDNode *m_defines;
+  llvm::NamedMDNode *m_mainFileName;
+  llvm::NamedMDNode *m_arguments;
+
+public:
+  CompilationInfo(IMalloc *pMalloc, dxil_dia::Session *pSession);
+
+  DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL();
+  DXC_MICROCOM_TM_ALLOC(CompilationInfo);
+
+  HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) final {
+    return DoBasicQueryInterface<IDxcPixCompilationInfo>(this, iid, ppvObject);
+  }
+  virtual STDMETHODIMP
+  GetSourceFile(_In_ DWORD SourceFileOrdinal,
+                _Outptr_result_z_ BSTR *pSourceName,
+                _Outptr_result_z_ BSTR *pSourceContents) override;
+  virtual STDMETHODIMP
+  GetArguments(_Outptr_result_z_ BSTR *pArguments) override;
+  virtual STDMETHODIMP
+  GetMacroDefinitions(_Outptr_result_z_ BSTR *pMacroDefinitions) override;
+  virtual STDMETHODIMP
+  GetEntryPointFile(_Outptr_result_z_ BSTR *pEntryPointFile) override;
+  virtual STDMETHODIMP
+  GetHlslTarget(_Outptr_result_z_ BSTR *pHlslTarget) override;
+  virtual STDMETHODIMP
+  GetEntryPoint(_Outptr_result_z_ BSTR *pEntryPoint) override;
+};
+
+CompilationInfo::CompilationInfo(IMalloc *pMalloc, dxil_dia::Session *pSession)
+    : m_pSession(pSession), m_pMalloc(pMalloc) {
+  auto *Module = m_pSession->DxilModuleRef().GetModule();
+  m_contents =
+      Module->getNamedMetadata(hlsl::DxilMDHelper::kDxilSourceContentsMDName);
+  if (!m_contents)
+    m_contents = Module->getNamedMetadata("llvm.dbg.contents");
+
+  m_defines =
+      Module->getNamedMetadata(hlsl::DxilMDHelper::kDxilSourceDefinesMDName);
+  if (!m_defines)
+    m_defines = Module->getNamedMetadata("llvm.dbg.defines");
+
+  m_mainFileName = Module->getNamedMetadata(
+      hlsl::DxilMDHelper::kDxilSourceMainFileNameMDName);
+  if (!m_mainFileName)
+    m_mainFileName = Module->getNamedMetadata("llvm.dbg.mainFileName");
+
+  m_arguments =
+      Module->getNamedMetadata(hlsl::DxilMDHelper::kDxilSourceArgsMDName);
+  if (!m_arguments)
+    m_arguments = Module->getNamedMetadata("llvm.dbg.args");
+}
+
+static void MDStringOperandToBSTR(llvm::MDOperand const &mdOperand,
+                                  BSTR *pBStr) {
+  llvm::StringRef MetadataAsStringRef =
+      llvm::dyn_cast<llvm::MDString>(mdOperand)->getString();
+  std::string StringWithTerminator(MetadataAsStringRef.begin(),
+                                   MetadataAsStringRef.size());
+  CA2W cv(StringWithTerminator.c_str(), CP_UTF8);
+  CComBSTR BStr;
+  BStr.Append(cv);
+  BStr.Append(L"\0", 1);
+  *pBStr = BStr.Detach();
+}
+
+STDMETHODIMP
+CompilationInfo::GetSourceFile(_In_ DWORD SourceFileOrdinal,
+                               _Outptr_result_z_ BSTR *pSourceName,
+                               _Outptr_result_z_ BSTR *pSourceContents) {
+  *pSourceName = nullptr;
+  *pSourceContents = nullptr;
+
+  if (SourceFileOrdinal >= m_contents->getNumOperands()) {
+    return E_INVALIDARG;
+  }
+
+  llvm::MDTuple *FileTuple =
+      llvm::cast<llvm::MDTuple>(m_contents->getOperand(SourceFileOrdinal));
+
+  MDStringOperandToBSTR(FileTuple->getOperand(0), pSourceName);
+  MDStringOperandToBSTR(FileTuple->getOperand(1), pSourceContents);
+
+  return S_OK;
+}
+
+STDMETHODIMP CompilationInfo::GetArguments(_Outptr_result_z_ BSTR *pArguments) {
+  llvm::MDNode *argsNode = m_arguments->getOperand(0);
+
+  // Don't return any arguments that denote things that are returned via
+  // other methods in this class (and that PIX isn't expecting to see
+  // in the arguments list):
+  const char *specialCases[] = {
+      "/T", "-T", "-D", "/D", "-E", "/E",
+  };
+
+  // Concatenate arguments into one string
+  CComBSTR pBSTR;
+  for (llvm::MDNode::op_iterator it = argsNode->op_begin();
+       it != argsNode->op_end(); ++it) {
+    llvm::StringRef strRef = llvm::dyn_cast<llvm::MDString>(*it)->getString();
+
+    bool skip = false;
+    bool skipTwice = false;
+    for (unsigned i = 0; i < _countof(specialCases); i++) {
+      // It's legal for users to specify, for example, /Emain or /E main:
+      if (strRef == specialCases[i]) {
+        skipTwice = true;
+        skip = true;
+        break;
+      } else if (strRef.startswith(specialCases[i])) {
+        skip = true;
+        break;
+      }
+    }
+
+    if (skip) {
+      if (skipTwice)
+        ++it;
+      continue;
+    }
+
+    std::string str(strRef.begin(), strRef.size());
+    CA2W cv(str.c_str(), CP_UTF8);
+    pBSTR.Append(cv);
+    pBSTR.Append(L" ", 1);
+  }
+  pBSTR.Append(L"\0", 1);
+  *pArguments = pBSTR.Detach();
+  return S_OK;
+}
+
+STDMETHODIMP CompilationInfo::GetMacroDefinitions(
+    _Outptr_result_z_ BSTR *pMacroDefinitions) {
+  llvm::MDNode *definesNode = m_defines->getOperand(0);
+  // Concatenate definitions into one string separated by spaces
+  CComBSTR pBSTR;
+  for (llvm::MDNode::op_iterator it = definesNode->op_begin();
+       it != definesNode->op_end(); ++it) {
+    llvm::StringRef strRef = llvm::dyn_cast<llvm::MDString>(*it)->getString();
+    std::string str(strRef.begin(), strRef.size());
+
+    // PIX is expecting quoted strings as the definitions. So if no quotes were
+    // given, add them now:
+    auto findEquals = str.find_first_of("=");
+    if (findEquals != std::string::npos && findEquals + 1 < str.length()) {
+      std::string definition = str.substr(findEquals + 1);
+      if (definition.front() != '\"') {
+        definition.insert(definition.begin(), '\"');
+      }
+      if (definition.back() != '\"') {
+        definition.push_back('\"');
+      }
+      std::string name = str.substr(0, findEquals);
+      str = name + "=" + definition;
+    }
+
+    CA2W cv(str.c_str(), CP_UTF8);
+    pBSTR.Append(L"-D", 2);
+    pBSTR.Append(cv);
+    pBSTR.Append(L" ", 1);
+  }
+  pBSTR.Append(L"\0", 1);
+  *pMacroDefinitions = pBSTR.Detach();
+  return S_OK;
+}
+
+STDMETHODIMP
+CompilationInfo::GetEntryPointFile(_Outptr_result_z_ BSTR *pEntryPointFile) {
+  llvm::StringRef strRef = llvm::dyn_cast<llvm::MDString>(
+                               m_mainFileName->getOperand(0)->getOperand(0))
+                               ->getString();
+  std::string str(strRef.begin(),
+                  strRef.size()); // To make sure str is null terminated
+  CA2W cv(str.c_str(), CP_UTF8);
+  CComBSTR pBSTR;
+  pBSTR.Append(cv);
+  *pEntryPointFile = pBSTR.Detach();
+  return S_OK;
+}
+
+STDMETHODIMP
+CompilationInfo::GetHlslTarget(_Outptr_result_z_ BSTR *pHlslTarget) {
+  CA2W cv(m_pSession->DxilModuleRef().GetShaderModel()->GetName(), CP_UTF8);
+  CComBSTR pBSTR;
+  pBSTR.Append(cv);
+  *pHlslTarget = pBSTR.Detach();
+  return S_OK;
+}
+
+STDMETHODIMP
+CompilationInfo::GetEntryPoint(_Outptr_result_z_ BSTR *pEntryPoint) {
+  auto name = m_pSession->DxilModuleRef().GetEntryFunctionName();
+  CA2W cv(name.c_str(), CP_UTF8);
+  CComBSTR pBSTR;
+  pBSTR.Append(cv);
+  *pEntryPoint = pBSTR.Detach();
+  return S_OK;
+}
+
+} // namespace dxil_debug_info
+
+HRESULT
+dxil_debug_info::CreateDxilCompilationInfo(IMalloc *pMalloc,
+                                           dxil_dia::Session *pSession,
+                                           IDxcPixCompilationInfo **ppResult) {
+  return NewDxcPixDxilDebugInfoObjectOrThrow<CompilationInfo>(ppResult, pMalloc,
+                                                              pSession);
+}

+ 28 - 0
lib/DxilDia/DxcPixCompilationInfo.h

@@ -0,0 +1,28 @@
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// DxcPixCompilationInfo.h                                                   //
+// Copyright (C) Microsoft Corporation. All rights reserved.                 //
+// This file is distributed under the University of Illinois Open Source     //
+// License. See LICENSE.TXT for details.                                     //
+//                                                                           //
+// Retrieves compilation info such as HLSL entry point, macro defs, etc.     //
+// from llvm debug metadata                                                  //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+#include "dxc/Support/WinIncludes.h"
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "DxcPixDxilDebugInfo.h"
+
+namespace dxil_debug_info {
+
+HRESULT
+CreateDxilCompilationInfo(IMalloc *pMalloc, dxil_dia::Session *pSession,
+                          IDxcPixCompilationInfo **ppResult);
+
+} // namespace dxil_debug_info

+ 74 - 0
lib/DxilDia/DxcPixEntrypoints.cpp

@@ -26,6 +26,7 @@
 
 
 #include "DxcPixBase.h"
 #include "DxcPixBase.h"
 #include "DxcPixDxilDebugInfo.h"
 #include "DxcPixDxilDebugInfo.h"
+#include "DxcPixCompilationInfo.h"
 
 
 #include <functional>
 #include <functional>
 
 
@@ -720,6 +721,55 @@ struct IDxcPixDxilDebugInfoEntrypoint : public Entrypoint<IDxcPixDxilDebugInfo>
 };
 };
 DEFINE_ENTRYPOINT_WRAPPER_TRAIT(IDxcPixDxilDebugInfo);
 DEFINE_ENTRYPOINT_WRAPPER_TRAIT(IDxcPixDxilDebugInfo);
 
 
+
+struct IDxcPixCompilationInfoEntrypoint
+    : public Entrypoint<IDxcPixCompilationInfo>
+{
+  DEFINE_ENTRYPOINT_BOILERPLATE(IDxcPixCompilationInfoEntrypoint);
+  virtual STDMETHODIMP
+  GetSourceFile(_In_ DWORD SourceFileOrdinal,
+                _Outptr_result_z_ BSTR *pSourceName,
+                _Outptr_result_z_ BSTR *pSourceContents) override {
+    return InvokeOnReal(&IInterface::GetSourceFile, SourceFileOrdinal,
+                        CheckNotNull(OutParam(pSourceName)),
+                        CheckNotNull(OutParam(pSourceContents))
+      );
+  }
+
+  virtual STDMETHODIMP GetArguments(_Outptr_result_z_ BSTR* pArguments) override 
+  {
+    return InvokeOnReal(&IInterface::GetArguments, CheckNotNull(OutParam(pArguments)));
+  }
+  virtual STDMETHODIMP
+    GetMacroDefinitions(_Outptr_result_z_ BSTR* pMacroDefinitions) override 
+  {
+    return InvokeOnReal(&IInterface::GetMacroDefinitions,
+                        CheckNotNull(OutParam(pMacroDefinitions)));
+
+  }
+  virtual STDMETHODIMP
+    GetEntryPointFile(_Outptr_result_z_ BSTR* pEntryPointFile) override {
+    return InvokeOnReal(&IInterface::GetEntryPointFile,
+                        CheckNotNull(OutParam(pEntryPointFile)));
+
+  }
+  virtual STDMETHODIMP
+    GetHlslTarget(_Outptr_result_z_ BSTR* pHlslTarget) override {
+    return InvokeOnReal(&IInterface::GetHlslTarget,
+                        CheckNotNull(OutParam(pHlslTarget)));
+
+  }
+  virtual STDMETHODIMP
+    GetEntryPoint(_Outptr_result_z_ BSTR* pEntryPoint) override
+  {
+    return InvokeOnReal(&IInterface::GetEntryPoint,
+                        CheckNotNull(OutParam(pEntryPoint)));
+
+  }
+};
+DEFINE_ENTRYPOINT_WRAPPER_TRAIT(IDxcPixCompilationInfo);
+
+
 HRESULT CreateEntrypointWrapper(
 HRESULT CreateEntrypointWrapper(
     IMalloc* pMalloc,
     IMalloc* pMalloc,
     IUnknown* pReal,
     IUnknown* pReal,
@@ -747,6 +797,7 @@ HRESULT CreateEntrypointWrapper(
   HANDLE_INTERFACE(IDxcPixVariable);
   HANDLE_INTERFACE(IDxcPixVariable);
   HANDLE_INTERFACE(IDxcPixDxilLiveVariables);
   HANDLE_INTERFACE(IDxcPixDxilLiveVariables);
   HANDLE_INTERFACE(IDxcPixDxilDebugInfo);
   HANDLE_INTERFACE(IDxcPixDxilDebugInfo);
+  HANDLE_INTERFACE(IDxcPixCompilationInfo);
 
 
   return E_FAIL;
   return E_FAIL;
 }
 }
@@ -779,3 +830,26 @@ STDMETHODIMP dxil_dia::Session::NewDxcPixDxilDebugInfo(
       ThisPtr(this),
       ThisPtr(this),
       CheckNotNull(OutParam(ppDxilDebugInfo)));
       CheckNotNull(OutParam(ppDxilDebugInfo)));
 }
 }
+
+static STDMETHODIMP NewDxcPixCompilationInfoImpl(
+    IMalloc *pMalloc,
+    dxil_dia::Session *pSession,
+    IDxcPixCompilationInfo** ppCompilationInfo
+)
+{
+  return dxil_debug_info::CreateDxilCompilationInfo(
+      pMalloc,
+      pSession,
+      ppCompilationInfo);
+}
+
+STDMETHODIMP dxil_dia::Session::NewDxcPixCompilationInfo(
+    _COM_Outptr_ IDxcPixCompilationInfo **ppCompilationInfo)
+{
+  return SetupAndRun(
+      m_pMalloc,
+      &NewDxcPixCompilationInfoImpl,
+      m_pMalloc,
+      ThisPtr(this), 
+      CheckNotNull(OutParam(ppCompilationInfo)));
+}

+ 3 - 0
lib/DxilDia/DxilDiaSession.h

@@ -379,6 +379,9 @@ public:
   STDMETHODIMP NewDxcPixDxilDebugInfo(
   STDMETHODIMP NewDxcPixDxilDebugInfo(
       _COM_Outptr_ IDxcPixDxilDebugInfo** ppDxilDebugInfo) override;
       _COM_Outptr_ IDxcPixDxilDebugInfo** ppDxilDebugInfo) override;
 
 
+  STDMETHODIMP NewDxcPixCompilationInfo(
+      _COM_Outptr_ IDxcPixCompilationInfo **ppCompilationInfo) override;
+
 private:
 private:
   DXC_MICROCOM_TM_REF_FIELDS()
   DXC_MICROCOM_TM_REF_FIELDS()
   std::shared_ptr<llvm::LLVMContext> m_context;
   std::shared_ptr<llvm::LLVMContext> m_context;

+ 114 - 0
tools/clang/unittests/HLSL/CompilerTest.cpp

@@ -24,6 +24,7 @@
 #include "dxc/DxilContainer/DxilContainer.h"
 #include "dxc/DxilContainer/DxilContainer.h"
 #include "dxc/Support/WinIncludes.h"
 #include "dxc/Support/WinIncludes.h"
 #include "dxc/dxcapi.h"
 #include "dxc/dxcapi.h"
+#include "dxc/dxcpix.h"
 #ifdef _WIN32
 #ifdef _WIN32
 #include <atlfile.h>
 #include <atlfile.h>
 #include "dia2.h"
 #include "dia2.h"
@@ -264,6 +265,8 @@ public:
   TEST_METHOD(DiaLoadBitcodePlusExtraData)
   TEST_METHOD(DiaLoadBitcodePlusExtraData)
   TEST_METHOD(DiaCompileArgs)
   TEST_METHOD(DiaCompileArgs)
 
 
+  TEST_METHOD(PixDebugCompileInfo)
+
   TEST_METHOD(CodeGenFloatingPointEnvironment)
   TEST_METHOD(CodeGenFloatingPointEnvironment)
   TEST_METHOD(CodeGenInclude)
   TEST_METHOD(CodeGenInclude)
   TEST_METHOD(CodeGenLibCsEntry)
   TEST_METHOD(CodeGenLibCsEntry)
@@ -2808,6 +2811,117 @@ TEST_F(CompilerTest, DiaTableIndexThenOK) {
 }
 }
 #endif // _WIN32 - exclude dia stuff
 #endif // _WIN32 - exclude dia stuff
 
 
+#ifdef _WIN32
+TEST_F(CompilerTest, PixDebugCompileInfo) {
+  static const char source[] = R"(
+    SamplerState  samp0 : register(s0);
+    Texture2DArray tex0 : register(t0);
+
+    float4 foo(Texture2DArray textures[], int idx, SamplerState samplerState, float3 uvw) {
+      return textures[NonUniformResourceIndex(idx)].Sample(samplerState, uvw);
+    }
+
+    [RootSignature( "DescriptorTable(SRV(t0)), DescriptorTable(Sampler(s0)) " )]
+    float4 main(int index : INDEX, float3 uvw : TEXCOORD) : SV_Target {
+      Texture2DArray textures[] = {
+        tex0,
+      };
+      return foo(textures, index, samp0, uvw);
+    }
+  )";
+
+  CComPtr<IDxcBlob> pPart;
+  CComPtr<IDiaDataSource> pDiaSource;
+  CComPtr<IStream> pStream;
+
+  CComPtr<IDxcLibrary> pLib;
+  VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcLibrary, &pLib));
+
+  const WCHAR *FlagList[] = {
+      L"/Zi",          L"-Zpr", L"/Qembed_debug",        L"/Fd",
+      L"F:\\my dir\\", L"-Fo",  L"F:\\my dir\\file.dxc",
+  };
+  const WCHAR *DefineList[] = {
+      L"MY_SPECIAL_DEFINE",
+      L"MY_OTHER_SPECIAL_DEFINE=\"MY_STRING\"",
+  };
+
+  std::vector<LPCWSTR> args;
+  for (unsigned i = 0; i < _countof(FlagList); i++) {
+    args.push_back(FlagList[i]);
+  }
+  for (unsigned i = 0; i < _countof(DefineList); i++) {
+    args.push_back(L"/D");
+    args.push_back(DefineList[i]);
+  }
+
+  auto CompileAndGetDebugPart = [&args](dxc::DxcDllSupport &dllSupport,
+                                        const char *source, wchar_t *profile,
+                                        IDxcBlob **ppDebugPart) {
+    CComPtr<IDxcBlob> pContainer;
+    CComPtr<IDxcLibrary> pLib;
+    CComPtr<IDxcContainerReflection> pReflection;
+    UINT32 index;
+
+    VerifyCompileOK(dllSupport, source, profile, args, &pContainer);
+    VERIFY_SUCCEEDED(dllSupport.CreateInstance(CLSID_DxcLibrary, &pLib));
+    VERIFY_SUCCEEDED(
+        dllSupport.CreateInstance(CLSID_DxcContainerReflection, &pReflection));
+    VERIFY_SUCCEEDED(pReflection->Load(pContainer));
+    VERIFY_SUCCEEDED(
+        pReflection->FindFirstPartKind(hlsl::DFCC_ShaderDebugInfoDXIL, &index));
+    VERIFY_SUCCEEDED(pReflection->GetPartContent(index, ppDebugPart));
+  };
+
+  constexpr wchar_t *profile = L"ps_6_0";
+  CompileAndGetDebugPart(m_dllSupport, source, profile, &pPart);
+
+  CComPtr<IStream> pNewProgramStream;
+  VERIFY_SUCCEEDED(
+      pLib->CreateStreamFromBlobReadOnly(pPart, &pNewProgramStream));
+
+  CComPtr<IDiaDataSource> pDiaDataSource;
+  VERIFY_SUCCEEDED(
+      m_dllSupport.CreateInstance(CLSID_DxcDiaDataSource, &pDiaDataSource));
+
+  VERIFY_SUCCEEDED(pDiaDataSource->loadDataFromIStream(pNewProgramStream));
+
+  CComPtr<IDiaSession> pSession;
+  VERIFY_SUCCEEDED(pDiaDataSource->openSession(&pSession));
+
+  CComPtr<IDxcPixDxilDebugInfoFactory> factory;
+  VERIFY_SUCCEEDED(pSession->QueryInterface(IID_PPV_ARGS(&factory)));
+
+  CComPtr<IDxcPixCompilationInfo> compilationInfo;
+  VERIFY_SUCCEEDED(factory->NewDxcPixCompilationInfo(&compilationInfo));
+
+  CComBSTR arguments;
+  VERIFY_SUCCEEDED(compilationInfo->GetArguments(&arguments));
+  for (unsigned i = 0; i < _countof(FlagList); i++) {
+    VERIFY_IS_TRUE(nullptr != wcsstr(arguments, FlagList[i]));
+  }
+
+  CComBSTR macros;
+  VERIFY_SUCCEEDED(compilationInfo->GetMacroDefinitions(&macros));
+  for (unsigned i = 0; i < _countof(DefineList); i++) {
+    std::wstring MacroDef = std::wstring(L"-D") + DefineList[i];
+    VERIFY_IS_TRUE(nullptr != wcsstr(macros, MacroDef.c_str()));
+  }
+
+  CComBSTR entryPointFile;
+  VERIFY_SUCCEEDED(compilationInfo->GetEntryPointFile(&entryPointFile));
+  VERIFY_ARE_EQUAL(std::wstring(L"source.hlsl"), std::wstring(entryPointFile));
+
+  CComBSTR entryPointFunction;
+  VERIFY_SUCCEEDED(compilationInfo->GetEntryPoint(&entryPointFunction));
+  VERIFY_ARE_EQUAL(std::wstring(L"main"), std::wstring(entryPointFunction));
+
+  CComBSTR hlslTarget;
+  VERIFY_SUCCEEDED(compilationInfo->GetHlslTarget(&hlslTarget));
+  VERIFY_ARE_EQUAL(std::wstring(profile), std::wstring(hlslTarget));
+}
+#endif // _WIN32 - exclude PIX stuff
+
 #ifdef _WIN32
 #ifdef _WIN32
 
 
 #pragma fenv_access(on)
 #pragma fenv_access(on)