Prechádzať zdrojové kódy

PIX: Modify root sigs in place (plus fix root sig memory leak) (#4876)

PIX is unique in that it needs to deserialize, modify and then reserialize root sigs. The focus of this checkin is adding such modifications to PixPassHelpers.cpp. (This closes a gap in PIX support: PIX can now support shaders that use dxil-defined and attribute-style root signatures.)

But this required some work outside of the purely PIX-focused areas. Deserialized root sigs are described by a C-like structure with embedded arrays that are new/delete-ed by routines in DxilRootSignature.cpp. Since modifying these structs requires more new/delete calls, I chose to add a new entry point in DxilRootSignature.cpp to do the bare minimum that PIX needs: extend root params by one descriptor. This approach keeps all those raw new/deletes in one file.

I found a leak in DxilRootSignatureSerialzier.cpp, which I fixed. There appear to be no unit tests that exercise this path. I welcome feedback on adding one.

There were other leaks in class CVersionedRootSignatureDeserializer, but this class is unused so I deleted it.

Oh, and there are bazillions of commits because I was cherry-picking from a recent change (#4845) as it eveolved, since I needed that change and this to test PIX.
Jeff Noyle 2 rokov pred
rodič
commit
20bb3d0228

+ 37 - 0
include/dxc/DxilRootSignature/DxilRootSignature.h

@@ -385,6 +385,43 @@ bool VerifyRootSignature(_In_ const DxilVersionedRootSignatureDesc *pDesc,
                          _In_ llvm::raw_ostream &DiagStream,
                          _In_ llvm::raw_ostream &DiagStream,
                          _In_ bool bAllowReservedRegisterSpace);
                          _In_ bool bAllowReservedRegisterSpace);
 
 
+class DxilVersionedRootSignature {
+  DxilVersionedRootSignatureDesc *m_pRootSignature;
+
+public:
+    // Non-copyable:
+  DxilVersionedRootSignature(DxilVersionedRootSignature const &) = delete;
+  DxilVersionedRootSignature const &
+  operator=(DxilVersionedRootSignature const &) = delete;
+
+  // but movable:
+  DxilVersionedRootSignature(DxilVersionedRootSignature &&) = default;
+  DxilVersionedRootSignature &
+  operator=(DxilVersionedRootSignature &&) = default;
+
+  DxilVersionedRootSignature() : m_pRootSignature(nullptr) {}
+  explicit DxilVersionedRootSignature(
+      const DxilVersionedRootSignatureDesc *pRootSignature)
+      : m_pRootSignature(
+            const_cast<DxilVersionedRootSignatureDesc *> (pRootSignature)) {}
+  ~DxilVersionedRootSignature() { 
+      DeleteRootSignature(m_pRootSignature);
+  }
+  const DxilVersionedRootSignatureDesc* operator -> () const {
+    return m_pRootSignature;
+  }
+  const DxilVersionedRootSignatureDesc ** get_address_of() {
+    if (m_pRootSignature != nullptr)
+      return nullptr; // You're probably about to leak...
+    return const_cast<const DxilVersionedRootSignatureDesc **> (&m_pRootSignature);
+  }
+  const DxilVersionedRootSignatureDesc* get() const { 
+      return m_pRootSignature;
+  }
+  DxilVersionedRootSignatureDesc* get_mutable() const { 
+      return m_pRootSignature;
+  }
+};
 } // namespace hlsl
 } // namespace hlsl
 
 
 #endif // __DXC_ROOTSIGNATURE__
 #endif // __DXC_ROOTSIGNATURE__

+ 98 - 1
lib/DxilPIXPasses/PixPassHelpers.cpp

@@ -9,10 +9,12 @@
 
 
 #include "dxc/DXIL/DxilOperations.h"
 #include "dxc/DXIL/DxilOperations.h"
 #include "dxc/DXIL/DxilInstructions.h"
 #include "dxc/DXIL/DxilInstructions.h"
+#include "dxc/DXIL/DxilFunctionProps.h"
 #include "dxc/DXIL/DxilModule.h"
 #include "dxc/DXIL/DxilModule.h"
 #include "dxc/DXIL/DxilResourceBinding.h"
 #include "dxc/DXIL/DxilResourceBinding.h"
 #include "dxc/DXIL/DxilResourceProperties.h"
 #include "dxc/DXIL/DxilResourceProperties.h"
 #include "dxc/HLSL/DxilSpanAllocator.h"
 #include "dxc/HLSL/DxilSpanAllocator.h"
+#include "dxc/DxilRootSignature/DxilRootSignature.h"
 
 
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/Module.h"
@@ -21,6 +23,10 @@
 
 
 #include "PixPassHelpers.h"
 #include "PixPassHelpers.h"
 
 
+#include "dxc/Support/Global.h"
+#include "dxc/Support/WinIncludes.h"
+#include "dxc/dxcapi.h"
+
 #ifdef PIX_DEBUG_DUMP_HELPER
 #ifdef PIX_DEBUG_DUMP_HELPER
 #include <iostream>
 #include <iostream>
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DebugInfo.h"
@@ -159,7 +165,93 @@ llvm::CallInst *CreateHandleForResource(hlsl::DxilModule &DM,
   }
   }
 }
 }
 
 
-// Set up a UAV with structure of a single int
+static std::vector<uint8_t> SerializeRootSignatureToVector(DxilVersionedRootSignatureDesc const *rootSignature) {
+  CComPtr<IDxcBlob> serializedRootSignature;
+  CComPtr<IDxcBlobEncoding> errorBlob;
+  constexpr bool allowReservedRegisterSpace = true;
+  SerializeRootSignature(rootSignature, &serializedRootSignature, &errorBlob,
+                         allowReservedRegisterSpace);
+  std::vector<uint8_t> ret;
+  auto const *serializedData = reinterpret_cast<const uint8_t *>(
+      serializedRootSignature->GetBufferPointer());
+  ret.assign(serializedData,
+             serializedData + serializedRootSignature->GetBufferSize());
+
+  return ret;
+}
+
+constexpr uint32_t toolsRegisterSpace = static_cast<uint32_t>(-2);
+constexpr uint32_t toolsUAVRegister = 0;
+
+template<typename RootSigDesc, typename RootParameterDesc>
+void ExtendRootSig(RootSigDesc &rootSigDesc) {
+  auto *existingParams = rootSigDesc.pParameters;
+  auto *newParams = new RootParameterDesc[rootSigDesc.NumParameters + 1];
+  if (existingParams != nullptr) {
+    memcpy(newParams, existingParams,
+           rootSigDesc.NumParameters * sizeof(RootParameterDesc));
+    delete[] existingParams;
+  }
+  rootSigDesc.pParameters = newParams;
+  rootSigDesc.pParameters[rootSigDesc.NumParameters].ParameterType = DxilRootParameterType::UAV;
+  rootSigDesc.pParameters[rootSigDesc.NumParameters].Descriptor.RegisterSpace = toolsRegisterSpace;
+  rootSigDesc.pParameters[rootSigDesc.NumParameters].Descriptor.ShaderRegister = toolsUAVRegister;
+  rootSigDesc.pParameters[rootSigDesc.NumParameters].ShaderVisibility = DxilShaderVisibility::All;
+  rootSigDesc.NumParameters++;
+} 
+
+static std::vector<uint8_t> AddUAVParamterToRootSignature(const void *Data,
+                                                       uint32_t Size) {
+  DxilVersionedRootSignature rootSignature;
+  DeserializeRootSignature(Data, Size, rootSignature.get_address_of());
+  auto *rs = rootSignature.get_mutable();
+  switch (rootSignature->Version) {
+  case DxilRootSignatureVersion::Version_1_0:
+    ExtendRootSig<DxilRootSignatureDesc, DxilRootParameter>(rs->Desc_1_0);
+    break;
+  case DxilRootSignatureVersion::Version_1_1:
+    ExtendRootSig<DxilRootSignatureDesc1, DxilRootParameter1>(rs->Desc_1_1);
+    rs->Desc_1_1.pParameters[rs->Desc_1_1.NumParameters - 1].Descriptor.Flags =
+        hlsl::DxilRootDescriptorFlags::None;
+    break;
+  }
+  return SerializeRootSignatureToVector(rs);
+}
+
+static void AddUAVToShaderAttributeRootSignature(DxilModule &DM) {
+  auto rs = DM.GetSerializedRootSignature();
+  if(!rs.empty()) {
+    std::vector<uint8_t> asVector = AddUAVParamterToRootSignature(rs.data(), static_cast<uint32_t>(rs.size()));
+    DM.ResetSerializedRootSignature(asVector);
+  }
+}
+
+static void AddUAVToDxilDefinedGlobalRootSignatures(DxilModule& DM) {
+  auto *subObjects = DM.GetSubobjects();
+  if (subObjects != nullptr) {
+    for (auto const &subObject : subObjects->GetSubobjects()) {
+      if (subObject.second->GetKind() ==
+          DXIL::SubobjectKind::GlobalRootSignature) {
+        const void *Data = nullptr;
+        uint32_t Size = 0;
+        constexpr bool notALocalRS = false;
+        if (subObject.second->GetRootSignature(notALocalRS, Data, Size,
+                                               nullptr)) {
+          auto extendedRootSig = AddUAVParamterToRootSignature(Data, Size);
+          auto rootSignatureSubObjectName = subObject.first;
+          subObjects->RemoveSubobject(rootSignatureSubObjectName);
+          subObjects->CreateRootSignature(rootSignatureSubObjectName,
+                                          notALocalRS,
+                                          extendedRootSig.data(),
+                                          static_cast<uint32_t>(extendedRootSig.size()));
+          break;
+        }
+      }
+    }
+  }
+}
+
+    // Set up a UAV with structure of a single int
 llvm::CallInst *CreateUAV(DxilModule &DM, IRBuilder<> &Builder,
 llvm::CallInst *CreateUAV(DxilModule &DM, IRBuilder<> &Builder,
                           unsigned int registerId, const char *name) {
                           unsigned int registerId, const char *name) {
   LLVMContext &Ctx = DM.GetModule()->getContext();
   LLVMContext &Ctx = DM.GetModule()->getContext();
@@ -170,6 +262,11 @@ llvm::CallInst *CreateUAV(DxilModule &DM, IRBuilder<> &Builder,
   if (UAVStructTy == nullptr) {
   if (UAVStructTy == nullptr) {
     SmallVector<llvm::Type *, 1> Elements{Type::getInt32Ty(Ctx)};
     SmallVector<llvm::Type *, 1> Elements{Type::getInt32Ty(Ctx)};
     UAVStructTy = llvm::StructType::create(Elements, PIXStructTypeName);
     UAVStructTy = llvm::StructType::create(Elements, PIXStructTypeName);
+
+    // Since we only have to do this once per module, we can do it now when
+    // we're adding the singular UAV structure type to the module:
+    AddUAVToDxilDefinedGlobalRootSignatures(DM);
+    AddUAVToShaderAttributeRootSignature(DM);
   }
   }
 
 
   std::unique_ptr<DxilResource> pUAV = llvm::make_unique<DxilResource>();
   std::unique_ptr<DxilResource> pUAV = llvm::make_unique<DxilResource>();

+ 0 - 87
lib/DxilRootSignature/DxilRootSignatureSerializer.cpp

@@ -332,93 +332,6 @@ void SerializeRootSignature(const DxilVersionedRootSignatureDesc *pRootSignature
   }
   }
 }
 }
 
 
-//=============================================================================
-//
-// CVersionedRootSignatureDeserializer.
-//
-//=============================================================================
-class CVersionedRootSignatureDeserializer {
-protected:
-  const DxilVersionedRootSignatureDesc *m_pRootSignature;
-  const DxilVersionedRootSignatureDesc *m_pRootSignature10;
-  const DxilVersionedRootSignatureDesc *m_pRootSignature11;
-
-public:
-  CVersionedRootSignatureDeserializer();
-  ~CVersionedRootSignatureDeserializer();
-
-  void Initialize(_In_reads_bytes_(SrcDataSizeInBytes) const void *pSrcData,
-                  _In_ uint32_t SrcDataSizeInBytes);
-
-  const DxilVersionedRootSignatureDesc *GetRootSignatureDescAtVersion(DxilRootSignatureVersion convertToVersion);
-
-  const DxilVersionedRootSignatureDesc *GetUnconvertedRootSignatureDesc();
-};
-
-CVersionedRootSignatureDeserializer::CVersionedRootSignatureDeserializer()
-  : m_pRootSignature(nullptr)
-  , m_pRootSignature10(nullptr)
-  , m_pRootSignature11(nullptr) {
-}
-
-CVersionedRootSignatureDeserializer::~CVersionedRootSignatureDeserializer() {
-  DeleteRootSignature(m_pRootSignature10);
-  DeleteRootSignature(m_pRootSignature11);
-}
-
-void CVersionedRootSignatureDeserializer::Initialize(_In_reads_bytes_(SrcDataSizeInBytes) const void *pSrcData,
-                                                     _In_ uint32_t SrcDataSizeInBytes) {
-  const DxilVersionedRootSignatureDesc *pRootSignature = nullptr;
-  DeserializeRootSignature(pSrcData, SrcDataSizeInBytes, &pRootSignature);
-
-  switch (pRootSignature->Version) {
-  case DxilRootSignatureVersion::Version_1_0:
-    m_pRootSignature10 = pRootSignature;
-    break;
-
-  case DxilRootSignatureVersion::Version_1_1:
-    m_pRootSignature11 = pRootSignature;
-    break;
-
-  default:
-    DeleteRootSignature(pRootSignature);
-    return;
-  }
-
-  m_pRootSignature = pRootSignature;
-}
-
-const DxilVersionedRootSignatureDesc *
-CVersionedRootSignatureDeserializer::GetUnconvertedRootSignatureDesc() {
-  return m_pRootSignature;
-}
-
-const DxilVersionedRootSignatureDesc *
-CVersionedRootSignatureDeserializer::GetRootSignatureDescAtVersion(DxilRootSignatureVersion ConvertToVersion) {
-  switch (ConvertToVersion) {
-  case DxilRootSignatureVersion::Version_1_0:
-    if (m_pRootSignature10 == nullptr) {
-      ConvertRootSignature(m_pRootSignature,
-                           ConvertToVersion,
-                           (const DxilVersionedRootSignatureDesc **)&m_pRootSignature10);
-    }
-    return m_pRootSignature10;
-
-  case DxilRootSignatureVersion::Version_1_1:
-    if (m_pRootSignature11 == nullptr) {
-      ConvertRootSignature(m_pRootSignature,
-                           ConvertToVersion,
-                           (const DxilVersionedRootSignatureDesc **)&m_pRootSignature11);
-    }
-    return m_pRootSignature11;
-
-  default:
-    IFTBOOL(false, E_FAIL);
-  }
-
-  return nullptr;
-}
-
 template<typename T_ROOT_SIGNATURE_DESC,
 template<typename T_ROOT_SIGNATURE_DESC,
          typename T_ROOT_PARAMETER,
          typename T_ROOT_PARAMETER,
          typename T_ROOT_DESCRIPTOR,
          typename T_ROOT_DESCRIPTOR,

+ 5 - 4
lib/HLSL/DxilValidation.cpp

@@ -5850,13 +5850,14 @@ HRESULT ValidateDxilBitcode(
     IFT(CreateMemoryStream(DxcGetThreadMallocNoRef(), &pOutputStream));
     IFT(CreateMemoryStream(DxcGetThreadMallocNoRef(), &pOutputStream));
     pOutputStream->Reserve(pWriter->size());
     pOutputStream->Reserve(pWriter->size());
     pWriter->write(pOutputStream);
     pWriter->write(pOutputStream);
+    DxilVersionedRootSignature desc;
     try {
     try {
-      const DxilVersionedRootSignatureDesc* pDesc = nullptr;
-      DeserializeRootSignature(SerializedRootSig.data(), SerializedRootSig.size(), &pDesc);
-      if (!pDesc) {
+      DeserializeRootSignature(SerializedRootSig.data(),
+                               SerializedRootSig.size(), desc.get_address_of());
+      if (!desc.get()) {
         return DXC_E_INCORRECT_ROOT_SIGNATURE;
         return DXC_E_INCORRECT_ROOT_SIGNATURE;
       }
       }
-      IFTBOOL(VerifyRootSignatureWithShaderPSV(pDesc,
+      IFTBOOL(VerifyRootSignatureWithShaderPSV(desc.get(),
                                                dxilModule.GetShaderModel()->GetKind(),
                                                dxilModule.GetShaderModel()->GetKind(),
                                                pOutputStream->GetPtr(), pWriter->size(),
                                                pOutputStream->GetPtr(), pWriter->size(),
                                                DiagStream), DXC_E_INCORRECT_ROOT_SIGNATURE);
                                                DiagStream), DXC_E_INCORRECT_ROOT_SIGNATURE);

+ 244 - 67
tools/clang/unittests/HLSL/PixTest.cpp

@@ -25,7 +25,12 @@
 #include <sstream>
 #include <sstream>
 #include <algorithm>
 #include <algorithm>
 #include <cfloat>
 #include <cfloat>
+
+#include "dxc/Support/WinIncludes.h"
+
 #include "dxc/DxilContainer/DxilContainer.h"
 #include "dxc/DxilContainer/DxilContainer.h"
+#include "dxc/DxilContainer/DxilRuntimeReflection.h"
+#include "dxc/DxilRootSignature/DxilRootSignature.h"
 #include "dxc/Support/WinIncludes.h"
 #include "dxc/Support/WinIncludes.h"
 #include "dxc/dxcapi.h"
 #include "dxc/dxcapi.h"
 #include "dxc/dxcpix.h"
 #include "dxc/dxcpix.h"
@@ -195,10 +200,6 @@ public:
   TEST_METHOD(DiaCompileArgs)
   TEST_METHOD(DiaCompileArgs)
   TEST_METHOD(PixDebugCompileInfo)
   TEST_METHOD(PixDebugCompileInfo)
 
 
-  TEST_METHOD(CheckSATPassFor66_NoDynamicAccess)
-  TEST_METHOD(CheckSATPassFor66_DynamicFromRootSig)
-  TEST_METHOD(CheckSATPassFor66_DynamicFromHeap)
-
   TEST_METHOD(AddToASPayload)
   TEST_METHOD(AddToASPayload)
 
 
   TEST_METHOD(PixStructAnnotation_Lib_DualRaygen)
   TEST_METHOD(PixStructAnnotation_Lib_DualRaygen)
@@ -223,6 +224,9 @@ public:
 
 
   TEST_METHOD(VirtualRegisters_InstructionCounts)
   TEST_METHOD(VirtualRegisters_InstructionCounts)
 
 
+  TEST_METHOD(RootSignatureUpgrade_SubObjects)
+  TEST_METHOD(RootSignatureUpgrade_Annotation)
+
   dxc::DxcDllSupport m_dllSupport;
   dxc::DxcDllSupport m_dllSupport;
   VersionSupportInfo m_ver;
   VersionSupportInfo m_ver;
 
 
@@ -1003,8 +1007,9 @@ public:
                                            bool validateCoverage = true,
                                            bool validateCoverage = true,
                                            const wchar_t *profile = L"as_6_5");
                                            const wchar_t *profile = L"as_6_5");
   void ValidateAllocaWrite(std::vector<AllocaWrite> const& allocaWrites, size_t index, const char* name);
   void ValidateAllocaWrite(std::vector<AllocaWrite> const& allocaWrites, size_t index, const char* name);
-  std::string RunShaderAccessTrackingPassAndReturnOutputMessages(IDxcBlob* blob);
-  std::string RunDxilPIXAddTidToAmplificationShaderPayloadPass(IDxcBlob* blob);
+  CComPtr<IDxcBlob> RunShaderAccessTrackingPass(IDxcBlob* blob);
+  std::string RunDxilPIXAddTidToAmplificationShaderPayloadPass(IDxcBlob *
+                                                                 blob);
   CComPtr<IDxcBlob> RunDxilPIXMeshShaderOutputPass(IDxcBlob* blob);
   CComPtr<IDxcBlob> RunDxilPIXMeshShaderOutputPass(IDxcBlob* blob);
 };
 };
 
 
@@ -1665,81 +1670,35 @@ TEST_F(PixTest, PixDebugCompileInfo) {
   VERIFY_ARE_EQUAL(std::wstring(profile), std::wstring(hlslTarget));
   VERIFY_ARE_EQUAL(std::wstring(profile), std::wstring(hlslTarget));
 }
 }
 
 
-std::string PixTest::RunShaderAccessTrackingPassAndReturnOutputMessages(IDxcBlob* blob)
-{
-  CComPtr<IDxcBlob> dxil = FindModule(DFCC_ShaderDebugInfoDXIL, blob);
+CComPtr<IDxcBlob> PixTest::RunShaderAccessTrackingPass(IDxcBlob *blob) {
   CComPtr<IDxcOptimizer> pOptimizer;
   CComPtr<IDxcOptimizer> pOptimizer;
   VERIFY_SUCCEEDED(
   VERIFY_SUCCEEDED(
       m_dllSupport.CreateInstance(CLSID_DxcOptimizer, &pOptimizer));
       m_dllSupport.CreateInstance(CLSID_DxcOptimizer, &pOptimizer));
   std::vector<LPCWSTR> Options;
   std::vector<LPCWSTR> Options;
   Options.push_back(L"-opt-mod-passes");
   Options.push_back(L"-opt-mod-passes");
-  Options.push_back(L"-hlsl-dxil-pix-shader-access-instrumentation,config=,checkForDynamicIndexing=1");
+  Options.push_back(L"-hlsl-dxil-pix-shader-access-instrumentation,config=");
 
 
   CComPtr<IDxcBlob> pOptimizedModule;
   CComPtr<IDxcBlob> pOptimizedModule;
   CComPtr<IDxcBlobEncoding> pText;
   CComPtr<IDxcBlobEncoding> pText;
   VERIFY_SUCCEEDED(pOptimizer->RunOptimizer(
   VERIFY_SUCCEEDED(pOptimizer->RunOptimizer(
-      dxil, Options.data(), Options.size(), &pOptimizedModule, &pText));
-
-  std::string outputText;
-  if (pText->GetBufferSize() != 0) {
-    outputText = reinterpret_cast<const char *>(pText->GetBufferPointer());
-  }
+      blob, Options.data(), Options.size(), &pOptimizedModule, &pText));
 
 
-  return outputText;
-}
-
-TEST_F(PixTest, CheckSATPassFor66_NoDynamicAccess) {
-
-  const char *noDynamicAccess = R"(
-    [RootSignature("")]
-    float main(float pos : A) : SV_Target {
-      float x = abs(pos);
-      float y = sin(pos);
-      float z = x + y;
-      return z;
-    }
-  )";
-
-  auto compiled = Compile(noDynamicAccess, L"ps_6_6");
-  auto satResults = RunShaderAccessTrackingPassAndReturnOutputMessages(compiled);
-  VERIFY_IS_TRUE(satResults.empty());
-}
-
-TEST_F(PixTest, CheckSATPassFor66_DynamicFromRootSig) {
-
-  const char *dynamicTextureAccess = R"x(
-Texture1D<float4> tex[5] : register(t3);
-SamplerState SS[3] : register(s2);
-
-[RootSignature("DescriptorTable(SRV(t3, numDescriptors=5)),\
-                DescriptorTable(Sampler(s2, numDescriptors=3))")]
-float4 main(int i : A, float j : B) : SV_TARGET
-{
-  float4 r = tex[i].Sample(SS[i], i);
-  return r;
-}
-  )x";
+  CComPtr<IDxcAssembler> pAssembler;
+  VERIFY_SUCCEEDED(
+      m_dllSupport.CreateInstance(CLSID_DxcAssembler, &pAssembler));
 
 
-  auto compiled = Compile(dynamicTextureAccess, L"ps_6_6");
-  auto satResults = RunShaderAccessTrackingPassAndReturnOutputMessages(compiled);
-  VERIFY_IS_TRUE(satResults.find("FoundDynamicIndexing") != string::npos);
-}
+  CComPtr<IDxcOperationResult> pAssembleResult;
+  VERIFY_SUCCEEDED(
+      pAssembler->AssembleToContainer(pOptimizedModule, &pAssembleResult));
 
 
-TEST_F(PixTest, CheckSATPassFor66_DynamicFromHeap) {
+  HRESULT hr;
+  VERIFY_SUCCEEDED(pAssembleResult->GetStatus(&hr));
+  VERIFY_SUCCEEDED(hr);
 
 
-  const char *dynamicResourceDecriptorHeapAccess = R"(
-static sampler sampler0 = SamplerDescriptorHeap[0];
-float4 main(int input : INPUT) : SV_Target
-{
-    Texture2D texture = ResourceDescriptorHeap[input];
-    return texture.Sample(sampler0, float2(0,0));
-}
-  )";
+  CComPtr<IDxcBlob> pNewContainer;
+  VERIFY_SUCCEEDED(pAssembleResult->GetResult(&pNewContainer));
 
 
-  auto compiled = Compile(dynamicResourceDecriptorHeapAccess, L"ps_6_6");
-  auto satResults =
-      RunShaderAccessTrackingPassAndReturnOutputMessages(compiled);
-  VERIFY_IS_TRUE(satResults.find("FoundDynamicIndexing") != string::npos);
+  return pNewContainer;
 }
 }
 
 
 CComPtr<IDxcBlob> PixTest::RunDxilPIXMeshShaderOutputPass(IDxcBlob *blob) {
 CComPtr<IDxcBlob> PixTest::RunDxilPIXMeshShaderOutputPass(IDxcBlob *blob) {
@@ -3427,4 +3386,222 @@ void MyMissShader(inout RayPayload payload)
   }
   }
 }
 }
 
 
+static void VerifyOperationSucceeded(IDxcOperationResult *pResult) 
+{
+  HRESULT result;
+  VERIFY_SUCCEEDED(pResult->GetStatus(&result));
+  if (FAILED(result)) {
+    CComPtr<IDxcBlobEncoding> pErrors;
+    VERIFY_SUCCEEDED(pResult->GetErrorBuffer(&pErrors));
+    CA2W errorsWide(BlobToUtf8(pErrors).c_str(), CP_UTF8);
+    WEX::Logging::Log::Comment(errorsWide);
+  }
+  VERIFY_SUCCEEDED(result);
+}
+
+TEST_F(PixTest, RootSignatureUpgrade_SubObjects) {
+
+  const char *source = R"x(
+GlobalRootSignature so_GlobalRootSignature =
+{
+	"RootConstants(num32BitConstants=1, b8), "
+};
+
+StateObjectConfig so_StateObjectConfig = 
+{ 
+    STATE_OBJECT_FLAGS_ALLOW_LOCAL_DEPENDENCIES_ON_EXTERNAL_DEFINITONS
+};
+
+LocalRootSignature so_LocalRootSignature1 = 
+{
+	"RootConstants(num32BitConstants=3, b2), "
+	"UAV(u6),RootFlags(LOCAL_ROOT_SIGNATURE)" 
+};
+
+LocalRootSignature so_LocalRootSignature2 = 
+{
+	"RootConstants(num32BitConstants=3, b2), "
+	"UAV(u8, flags=DATA_STATIC), " 
+	"RootFlags(LOCAL_ROOT_SIGNATURE)"
+};
+
+RaytracingShaderConfig  so_RaytracingShaderConfig =
+{
+    128, // max payload size
+    32   // max attribute size
+};
+
+RaytracingPipelineConfig so_RaytracingPipelineConfig =
+{
+    2 // max trace recursion depth
+};
+
+TriangleHitGroup MyHitGroup =
+{
+    "MyAnyHit",       // AnyHit
+    "MyClosestHit",   // ClosestHit
+};
+
+SubobjectToExportsAssociation so_Association1 =
+{
+	"so_LocalRootSignature1", // subobject name
+	"MyRayGen"                // export association 
+};
+
+SubobjectToExportsAssociation so_Association2 =
+{
+	"so_LocalRootSignature2", // subobject name
+	"MyAnyHit"                // export association 
+};
+
+struct MyPayload
+{
+    float4 color;
+};
+
+[shader("raygeneration")]
+void MyRayGen()
+{
+}
+
+[shader("closesthit")]
+void MyClosestHit(inout MyPayload payload, in BuiltInTriangleIntersectionAttributes attr)
+{  
+}
+
+[shader("anyhit")]
+void MyAnyHit(inout MyPayload payload, in BuiltInTriangleIntersectionAttributes attr)
+{
+}
+
+[shader("miss")]
+void MyMiss(inout MyPayload payload)
+{
+}
+
+)x";
+
+  CComPtr<IDxcCompiler> pCompiler;
+  VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
+
+  CComPtr<IDxcBlobEncoding> pSource;
+  Utf8ToBlob(m_dllSupport, source, &pSource);
+
+  CComPtr<IDxcOperationResult> pResult;
+  VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"", L"lib_6_6",
+                                      nullptr, 0, nullptr, 0, nullptr,
+                                      &pResult));
+  VerifyOperationSucceeded(pResult);
+  CComPtr<IDxcBlob> compiled;
+  VERIFY_SUCCEEDED(pResult->GetResult(&compiled));
+
+  auto optimizedContainer = RunShaderAccessTrackingPass(compiled);
+
+  const char *pBlobContent =
+      reinterpret_cast<const char *>(optimizedContainer->GetBufferPointer());
+  unsigned blobSize = optimizedContainer->GetBufferSize();
+  const hlsl::DxilContainerHeader *pContainerHeader =
+      hlsl::IsDxilContainerLike(pBlobContent, blobSize);
+
+  const hlsl::DxilPartHeader *pPartHeader =
+      GetDxilPartByType(pContainerHeader, hlsl::DFCC_RuntimeData);
+  VERIFY_ARE_NOT_EQUAL(pPartHeader, nullptr);
+
+  hlsl::RDAT::DxilRuntimeData rdat(GetDxilPartData(pPartHeader),
+                                   pPartHeader->PartSize);
+
+  auto const subObjectTableReader = rdat.GetSubobjectTable();
+
+  // There are 9 subobjects in the HLSL above:
+  VERIFY_ARE_EQUAL(subObjectTableReader.Count(), 9u);
+
+  bool foundGlobalRS = false;
+  for (uint32_t i = 0; i < subObjectTableReader.Count(); ++i) {
+    auto subObject = subObjectTableReader[i];
+    hlsl::DXIL::SubobjectKind subobjectKind = subObject.getKind();
+    switch (subobjectKind) {
+    case hlsl::DXIL::SubobjectKind::GlobalRootSignature: {
+      foundGlobalRS = true;
+      VERIFY_IS_TRUE(0 ==
+                     strcmp(subObject.getName(), "so_GlobalRootSignature"));
+
+      auto rootSigReader = subObject.getRootSignature();
+      DxilVersionedRootSignatureDesc const *rootSignature = nullptr;
+      DeserializeRootSignature(rootSigReader.getData(),
+                               rootSigReader.sizeData(), &rootSignature);
+      VERIFY_ARE_EQUAL(rootSignature->Version,
+                       DxilRootSignatureVersion::Version_1_1);
+      VERIFY_ARE_EQUAL(rootSignature->Desc_1_1.NumParameters, 2);
+      VERIFY_ARE_EQUAL(rootSignature->Desc_1_1.pParameters[1].ParameterType,
+                       DxilRootParameterType::UAV);
+      VERIFY_ARE_EQUAL(rootSignature->Desc_1_1.pParameters[1].ShaderVisibility,
+                       DxilShaderVisibility::All);
+      VERIFY_ARE_EQUAL(
+          rootSignature->Desc_1_1.pParameters[1].Descriptor.RegisterSpace,
+          static_cast<uint32_t>(-2));
+      VERIFY_ARE_EQUAL(
+          rootSignature->Desc_1_1.pParameters[1].Descriptor.ShaderRegister, 0u);
+      DeleteRootSignature(rootSignature);
+      break;
+    }
+    }
+  }
+  VERIFY_IS_TRUE(foundGlobalRS);
+}
+
+TEST_F(PixTest, RootSignatureUpgrade_Annotation)
+{
+
+  const char *dynamicTextureAccess = R"x(
+Texture1D<float4> tex[5] : register(t3);
+SamplerState SS[3] : register(s2);
+
+[RootSignature("DescriptorTable(SRV(t3, numDescriptors=5)),\
+                DescriptorTable(Sampler(s2, numDescriptors=3))")]
+float4 main(int i : A, float j : B) : SV_TARGET
+{
+  float4 r = tex[i].Sample(SS[i], i);
+  return r;
+}
+  )x";
+
+  auto compiled = Compile(dynamicTextureAccess, L"ps_6_6");
+  auto pOptimizedContainer = RunShaderAccessTrackingPass(compiled);
+
+  const char *pBlobContent =
+      reinterpret_cast<const char *>(pOptimizedContainer->GetBufferPointer());
+  unsigned blobSize = pOptimizedContainer->GetBufferSize();
+  const hlsl::DxilContainerHeader *pContainerHeader =
+      hlsl::IsDxilContainerLike(pBlobContent, blobSize);
+
+  const hlsl::DxilPartHeader *pPartHeader =
+      GetDxilPartByType(pContainerHeader, hlsl::DFCC_RootSignature);
+  VERIFY_ARE_NOT_EQUAL(pPartHeader, nullptr);
+
+  hlsl::RootSignatureHandle RSH;
+  RSH.LoadSerialized((const uint8_t *)GetDxilPartData(pPartHeader),
+                     pPartHeader->PartSize);
+
+  RSH.Deserialize();
+
+  auto const *desc = RSH.GetDesc();
+  
+  bool foundGlobalRS = false;
+
+  VERIFY_ARE_EQUAL(desc->Version, hlsl::DxilRootSignatureVersion::Version_1_1);
+  VERIFY_ARE_EQUAL(desc->Desc_1_1.NumParameters, 3u);
+  for (unsigned int i = 0; i < desc->Desc_1_1.NumParameters; ++i) {
+    hlsl::DxilRootParameter1 const *param = desc->Desc_1_1.pParameters + i;
+    switch (param->ParameterType) {
+    case hlsl::DxilRootParameterType::UAV:
+      VERIFY_ARE_EQUAL(param->Descriptor.RegisterSpace, static_cast<uint32_t>(-2));
+      VERIFY_ARE_EQUAL(param->Descriptor.ShaderRegister, 0u);
+      foundGlobalRS = true;
+      break;
+    }
+  }
+
+  VERIFY_IS_TRUE(foundGlobalRS);
+}
+
 #endif
 #endif