text: ///////////////////////////////////////////////////////////////////////////////
  //                                                                           //
  // DxilRootSignatureSerializer.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.                                     //
  //                                                                           //
  // Serializer for root signature structures.                                 //
  //                                                                           //
  ///////////////////////////////////////////////////////////////////////////////
  
  #include "dxc/DXIL/DxilConstants.h"
  #include "dxc/DxilRootSignature/DxilRootSignature.h"
  #include "dxc/DxilContainer/DxilPipelineStateValidation.h"
  #include "dxc/Support/Global.h"
  #include "dxc/Support/WinIncludes.h"
  #include "dxc/Support/WinFunctions.h"
  #include "dxc/Support/FileIOHelper.h"
  #include "dxc/dxcapi.h"
  
  #include "llvm/Support/raw_ostream.h"
  #include "llvm/IR/DiagnosticPrinter.h"
  
  #include <string>
  #include <algorithm>
  #include <utility>
  #include <vector>
  #include <set>
  
  #include "DxilRootSignatureHelper.h"
  
  using namespace llvm;
  using std::string;
  
  namespace hlsl {
  
  using namespace root_sig_helper;
  
  //////////////////////////////////////////////////////////////////////////////
  // Simple serializer.
  
  class SimpleSerializer {
    struct Segment {
      void *pData;
      unsigned cbSize;
      bool bOwner;
      unsigned Offset;
      Segment *pNext;
    };
  
  public:
    SimpleSerializer();
    ~SimpleSerializer();
  
    HRESULT AddBlock(void *pData, unsigned cbSize, unsigned *pOffset);
    HRESULT ReserveBlock(void **ppData, unsigned cbSize, unsigned *pOffset);
  
    HRESULT Compact(_Out_writes_bytes_(cbSize) char *pData, unsigned cbSize);
    unsigned GetSize();
  
  protected:
    unsigned m_cbSegments;
    Segment *m_pSegment;
    Segment **m_ppSegment;
  };
  
  SimpleSerializer::SimpleSerializer() {
    m_cbSegments = 0;
    m_pSegment = nullptr;
    m_ppSegment = &m_pSegment;
  }
  
  SimpleSerializer::~SimpleSerializer() {
    while (m_pSegment) {
      Segment *pSegment = m_pSegment;
      m_pSegment = pSegment->pNext;
  
      if (pSegment->bOwner) {
        delete[] (char*)pSegment->pData;
      }
  
      delete pSegment;
    }
  }
  
  HRESULT SimpleSerializer::AddBlock(void *pData, unsigned cbSize,
                                     unsigned *pOffset) {
    Segment *pSegment = nullptr;
    IFRBOOL(!(cbSize != 0 && pData == nullptr), E_FAIL);
  
    IFROOM(pSegment = new (std::nothrow) Segment);
    pSegment->pData = pData;
  
    m_cbSegments = (m_cbSegments + 3) & ~3;
    pSegment->Offset = m_cbSegments;
    pSegment->cbSize = cbSize;
    pSegment->bOwner = false;
    pSegment->pNext = nullptr;
  
    m_cbSegments += pSegment->cbSize;
    *m_ppSegment = pSegment;
    m_ppSegment = &pSegment->pNext;
  
    if (pOffset != nullptr) {
      *pOffset = pSegment->Offset;
    }
  
    return S_OK;
  }
  
  HRESULT SimpleSerializer::ReserveBlock(void **ppData, unsigned cbSize,
                                         unsigned *pOffset) {
    HRESULT hr = S_OK;
    Segment *pSegment = nullptr;
    void *pClonedData = nullptr;
  
    IFCOOM(pSegment = new (std::nothrow) Segment);
    pSegment->pData = nullptr;
  
    IFCOOM(pClonedData = new (std::nothrow) char[cbSize]);
    pSegment->pData = pClonedData;
  
    m_cbSegments = (m_cbSegments + 3) & ~3;
    pSegment->Offset = m_cbSegments;
    pSegment->cbSize = cbSize;
    pSegment->bOwner = true;
    pSegment->pNext = nullptr;
  
    m_cbSegments += pSegment->cbSize;
    *m_ppSegment = pSegment;
    m_ppSegment = &pSegment->pNext;
  
    *ppData = pClonedData;
    if (pOffset) {
      *pOffset = pSegment->Offset;
    }
  
  Cleanup:
    if (FAILED(hr)) {
      delete[] (char*)pClonedData;
      delete pSegment;
    }
    return hr;
  }
  
  HRESULT SimpleSerializer::Compact(_Out_writes_bytes_(cbSize) char *pData,
                                    unsigned cbSize) {
    unsigned cb = GetSize();
    IFRBOOL(cb <= cbSize, E_FAIL);
    DXASSERT_NOMSG(cb <= UINT32_MAX / 2);
  
    char *p = (char *)pData;
    cb = 0;
  
    for (Segment *pSegment = m_pSegment; pSegment; pSegment = pSegment->pNext) {
      unsigned cbAlign = ((cb + 3) & ~3) - cb;
  
      _Analysis_assume_(p + cbAlign <= pData + cbSize);
      memset(p, 0xab, cbAlign);
  
      p += cbAlign;
      cb += cbAlign;
  
      _Analysis_assume_(p + pSegment->cbSize <= pData + cbSize);
      memcpy(p, pSegment->pData, pSegment->cbSize);
  
      p += pSegment->cbSize;
      cb += pSegment->cbSize;
    }
  
    // Trailing zeros
    _Analysis_assume_(p + cbSize - cb <= pData + cbSize);
    memset(p, 0xab, cbSize - cb);
  
    return S_OK;
  }
  
  unsigned SimpleSerializer::GetSize() {
    // Round up to 4==sizeof(unsigned).
    return ((m_cbSegments + 3) >> 2) * 4;
  }
  
  template<typename T_ROOT_SIGNATURE_DESC,
    typename T_ROOT_PARAMETER,
    typename T_ROOT_DESCRIPTOR_INTERNAL,
    typename T_DESCRIPTOR_RANGE_INTERNAL>
  void SerializeRootSignatureTemplate(_In_ const T_ROOT_SIGNATURE_DESC* pRootSignature,
                                      DxilRootSignatureVersion DescVersion,
                                      _COM_Outptr_ IDxcBlob** ppBlob,
                                      DiagnosticPrinter &DiagPrinter,
                                      _In_ bool bAllowReservedRegisterSpace) {
    DxilContainerRootSignatureDesc RS;
    uint32_t Offset;
    SimpleSerializer Serializer;
    IFT(Serializer.AddBlock(&RS, sizeof(RS), &Offset));
    IFTBOOL(Offset == 0, E_FAIL);
  
    const T_ROOT_SIGNATURE_DESC *pRS = pRootSignature;
    RS.Version = (uint32_t)DescVersion;
    RS.Flags = (uint32_t)pRS->Flags;
    RS.NumParameters = pRS->NumParameters;
    RS.NumStaticSamplers = pRS->NumStaticSamplers;
  
    DxilContainerRootParameter *pRP;
    IFT(Serializer.ReserveBlock((void**)&pRP,
      sizeof(DxilContainerRootParameter)*RS.NumParameters, &RS.RootParametersOffset));
  
    for (uint32_t iRP = 0; iRP < RS.NumParameters; iRP++) {
      const T_ROOT_PARAMETER *pInRP = &pRS->pParameters[iRP];
      DxilContainerRootParameter *pOutRP = &pRP[iRP];
      pOutRP->ParameterType = (uint32_t)pInRP->ParameterType;
      pOutRP->ShaderVisibility = (uint32_t)pInRP->ShaderVisibility;
      switch (pInRP->ParameterType) {
      case DxilRootParameterType::DescriptorTable: {
        DxilContainerRootDescriptorTable *p1;
        IFT(Serializer.ReserveBlock((void**)&p1,
                                    sizeof(DxilContainerRootDescriptorTable),
                                    &pOutRP->PayloadOffset));
        p1->NumDescriptorRanges = pInRP->DescriptorTable.NumDescriptorRanges;
  
        T_DESCRIPTOR_RANGE_INTERNAL *p2;
        IFT(Serializer.ReserveBlock((void**)&p2,
                                    sizeof(T_DESCRIPTOR_RANGE_INTERNAL)*p1->NumDescriptorRanges,
                                    &p1->DescriptorRangesOffset));
  
        for (uint32_t i = 0; i < p1->NumDescriptorRanges; i++) {
          p2[i].RangeType = (uint32_t)pInRP->DescriptorTable.pDescriptorRanges[i].RangeType;
          p2[i].NumDescriptors = pInRP->DescriptorTable.pDescriptorRanges[i].NumDescriptors;
          p2[i].BaseShaderRegister = pInRP->DescriptorTable.pDescriptorRanges[i].BaseShaderRegister;
          p2[i].RegisterSpace = pInRP->DescriptorTable.pDescriptorRanges[i].RegisterSpace;
          p2[i].OffsetInDescriptorsFromTableStart = pInRP->DescriptorTable.pDescriptorRanges[i].OffsetInDescriptorsFromTableStart;
          DxilDescriptorRangeFlags Flags = GetFlags(pInRP->DescriptorTable.pDescriptorRanges[i]);
          SetFlags(p2[i], Flags);
        }
        break;
      }
      case DxilRootParameterType::Constants32Bit: {
        DxilRootConstants *p;
        IFT(Serializer.ReserveBlock((void**)&p, sizeof(DxilRootConstants), &pOutRP->PayloadOffset));
        p->Num32BitValues = pInRP->Constants.Num32BitValues;
        p->ShaderRegister = pInRP->Constants.ShaderRegister;
        p->RegisterSpace = pInRP->Constants.RegisterSpace;
        break;
      }
      case DxilRootParameterType::CBV:
      case DxilRootParameterType::SRV:
      case DxilRootParameterType::UAV: {
        T_ROOT_DESCRIPTOR_INTERNAL *p;
        IFT(Serializer.ReserveBlock((void**)&p, sizeof(T_ROOT_DESCRIPTOR_INTERNAL), &pOutRP->PayloadOffset));
        p->ShaderRegister = pInRP->Descriptor.ShaderRegister;
        p->RegisterSpace = pInRP->Descriptor.RegisterSpace;
        DxilRootDescriptorFlags Flags = GetFlags(pInRP->Descriptor);
        SetFlags(*p, Flags);
        break;
      }
      default:
        EAT(DiagPrinter << "D3DSerializeRootSignature: unknown root parameter type ("
                        << (uint32_t)pInRP->ParameterType << ")\n");
      }
    }
  
    DxilStaticSamplerDesc *pSS;
    unsigned StaticSamplerSize = sizeof(DxilStaticSamplerDesc)*RS.NumStaticSamplers;
    IFT(Serializer.ReserveBlock((void**)&pSS, StaticSamplerSize, &RS.StaticSamplersOffset));
    memcpy(pSS, pRS->pStaticSamplers, StaticSamplerSize);
  
    // Create the result blob.
    CDxcMallocHeapPtr<char> bytes(DxcGetThreadMallocNoRef());
    CComPtr<IDxcBlob> pBlob;
    unsigned cb = Serializer.GetSize();
    DXASSERT_NOMSG((cb & 0x3) == 0);
    IFTBOOL(bytes.Allocate(cb), E_OUTOFMEMORY);
    IFT(Serializer.Compact(bytes.m_pData, cb));
    IFT(DxcCreateBlobOnHeap(bytes.m_pData, cb, ppBlob));
    bytes.Detach(); // Ownership transfered to ppBlob.
  }
  
  _Use_decl_annotations_
  void SerializeRootSignature(const DxilVersionedRootSignatureDesc *pRootSignature,
                              IDxcBlob **ppBlob, IDxcBlobEncoding **ppErrorBlob,
                              bool bAllowReservedRegisterSpace) {
    DXASSERT_NOMSG(pRootSignature != nullptr);
    DXASSERT_NOMSG(ppBlob != nullptr);
    DXASSERT_NOMSG(ppErrorBlob != nullptr);
  
    *ppBlob = nullptr;
    *ppErrorBlob = nullptr;
  
    // TODO: change SerializeRootSignature to take raw_ostream&
    string DiagString;
    raw_string_ostream DiagStream(DiagString);
    DiagnosticPrinterRawOStream DiagPrinter(DiagStream);
  
    // Verify root signature.
    if (!VerifyRootSignature(pRootSignature, DiagStream,
                             bAllowReservedRegisterSpace)) {
      DiagStream.flush();
      DxcCreateBlobWithEncodingOnHeapCopy(DiagString.c_str(), DiagString.size(), CP_UTF8, ppErrorBlob);
      return;
    }
  
    try {
      switch (pRootSignature->Version)
      {
      case DxilRootSignatureVersion::Version_1_0:
        SerializeRootSignatureTemplate<
          DxilRootSignatureDesc,
          DxilRootParameter,
          DxilRootDescriptor,
          DxilContainerDescriptorRange>(&pRootSignature->Desc_1_0,
            DxilRootSignatureVersion::Version_1_0,
            ppBlob, DiagPrinter,
            bAllowReservedRegisterSpace);
        break;
  
      case DxilRootSignatureVersion::Version_1_1:
      default:
        DXASSERT(pRootSignature->Version == DxilRootSignatureVersion::Version_1_1, "else VerifyRootSignature didn't validate");
        SerializeRootSignatureTemplate<
          DxilRootSignatureDesc1,
          DxilRootParameter1,
          DxilContainerRootDescriptor1,
          DxilContainerDescriptorRange1>(&pRootSignature->Desc_1_1,
            DxilRootSignatureVersion::Version_1_1,
            ppBlob, DiagPrinter,
            bAllowReservedRegisterSpace);
        break;
      }
    } catch (...) {
      DiagStream.flush();
      DxcCreateBlobWithEncodingOnHeapCopy(DiagString.c_str(), DiagString.size(), CP_UTF8, ppErrorBlob);
    }
  }
  
  //=============================================================================
  //
  // 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,
           typename T_ROOT_PARAMETER,
           typename T_ROOT_DESCRIPTOR,
           typename T_ROOT_DESCRIPTOR_INTERNAL,
           typename T_DESCRIPTOR_RANGE,
           typename T_DESCRIPTOR_RANGE_INTERNAL>
  void DeserializeRootSignatureTemplate(_In_reads_bytes_(SrcDataSizeInBytes) const void *pSrcData,
                                        _In_ uint32_t SrcDataSizeInBytes,
                                        DxilRootSignatureVersion DescVersion,
                                        T_ROOT_SIGNATURE_DESC &RootSignatureDesc) {
    // Note that in case of failure, outside code must deallocate memory.
    T_ROOT_SIGNATURE_DESC *pRootSignature = &RootSignatureDesc;
    const char *pData = (const char *)pSrcData;
    const char *pMaxPtr = pData + SrcDataSizeInBytes;
    UNREFERENCED_PARAMETER(DescVersion);
    DXASSERT_NOMSG(((const uint32_t*)pData)[0] == (uint32_t)DescVersion);
  
    // Root signature.
    IFTBOOL(pData + sizeof(DxilContainerRootSignatureDesc) <= pMaxPtr, E_FAIL);
    const DxilContainerRootSignatureDesc *pRS = (const DxilContainerRootSignatureDesc *)pData;
    pRootSignature->Flags = (DxilRootSignatureFlags)pRS->Flags;
    pRootSignature->NumParameters = pRS->NumParameters;
    pRootSignature->NumStaticSamplers = pRS->NumStaticSamplers;
    // Intialize all pointers early so that clean up works properly.
    pRootSignature->pParameters = nullptr;
    pRootSignature->pStaticSamplers = nullptr;
  
    size_t s = sizeof(DxilContainerRootParameter)*pRS->NumParameters;
    const DxilContainerRootParameter *pInRTS = (const DxilContainerRootParameter *)(pData + pRS->RootParametersOffset);
    IFTBOOL(((const char*)pInRTS) + s <= pMaxPtr, E_FAIL);
    if (pRootSignature->NumParameters) {
      pRootSignature->pParameters = new T_ROOT_PARAMETER[pRootSignature->NumParameters];
    }
    memset((void *)pRootSignature->pParameters, 0, s);
  
    for(unsigned iRP = 0; iRP < pRootSignature->NumParameters; iRP++) {
      DxilRootParameterType ParameterType = (DxilRootParameterType)pInRTS[iRP].ParameterType;
      T_ROOT_PARAMETER *pOutRTS = (T_ROOT_PARAMETER *)&pRootSignature->pParameters[iRP];
      pOutRTS->ParameterType = ParameterType;
      pOutRTS->ShaderVisibility = (DxilShaderVisibility)pInRTS[iRP].ShaderVisibility;
      switch(ParameterType) {
      case DxilRootParameterType::DescriptorTable: {
        const DxilContainerRootDescriptorTable *p1 = (const DxilContainerRootDescriptorTable*)(pData + pInRTS[iRP].PayloadOffset);
        IFTBOOL((const char*)p1 + sizeof(DxilContainerRootDescriptorTable) <= pMaxPtr, E_FAIL);
        pOutRTS->DescriptorTable.NumDescriptorRanges = p1->NumDescriptorRanges;
        pOutRTS->DescriptorTable.pDescriptorRanges = nullptr;
        const T_DESCRIPTOR_RANGE_INTERNAL *p2 = (const T_DESCRIPTOR_RANGE_INTERNAL*)(pData + p1->DescriptorRangesOffset);
        IFTBOOL((const char*)p2 + sizeof(T_DESCRIPTOR_RANGE_INTERNAL) <= pMaxPtr, E_FAIL);
        if (p1->NumDescriptorRanges) {
          pOutRTS->DescriptorTable.pDescriptorRanges = new T_DESCRIPTOR_RANGE[p1->NumDescriptorRanges];
        }
        for (unsigned i = 0; i < p1->NumDescriptorRanges; i++) {
          T_DESCRIPTOR_RANGE *p3 = (T_DESCRIPTOR_RANGE *)&pOutRTS->DescriptorTable.pDescriptorRanges[i];
          p3->RangeType                         = (DxilDescriptorRangeType)p2[i].RangeType;
          p3->NumDescriptors                    = p2[i].NumDescriptors;
          p3->BaseShaderRegister                = p2[i].BaseShaderRegister;
          p3->RegisterSpace                     = p2[i].RegisterSpace;
          p3->OffsetInDescriptorsFromTableStart = p2[i].OffsetInDescriptorsFromTableStart;
          DxilDescriptorRangeFlags Flags = GetFlags(p2[i]);
          SetFlags(*p3, Flags);
        }
        break;
      }
      case DxilRootParameterType::Constants32Bit: {
        const DxilRootConstants *p = (const DxilRootConstants*)(pData + pInRTS[iRP].PayloadOffset);
        IFTBOOL((const char*)p + sizeof(DxilRootConstants) <= pMaxPtr, E_FAIL);
        pOutRTS->Constants.Num32BitValues = p->Num32BitValues;
        pOutRTS->Constants.ShaderRegister = p->ShaderRegister;
        pOutRTS->Constants.RegisterSpace  = p->RegisterSpace;
        break;
      }
      case DxilRootParameterType::CBV:
      case DxilRootParameterType::SRV:
      case DxilRootParameterType::UAV: {
        const T_ROOT_DESCRIPTOR *p = (const T_ROOT_DESCRIPTOR *)(pData + pInRTS[iRP].PayloadOffset);
        IFTBOOL((const char*)p + sizeof(T_ROOT_DESCRIPTOR) <= pMaxPtr, E_FAIL);
        pOutRTS->Descriptor.ShaderRegister = p->ShaderRegister;
        pOutRTS->Descriptor.RegisterSpace  = p->RegisterSpace;
        DxilRootDescriptorFlags Flags = GetFlags(*p);
        SetFlags(pOutRTS->Descriptor, Flags);
        break;
      }
      default:
        IFT(E_FAIL);
      }
    }
  
    s = sizeof(DxilStaticSamplerDesc)*pRS->NumStaticSamplers;
    const DxilStaticSamplerDesc *pInSS = (const DxilStaticSamplerDesc *)(pData + pRS->StaticSamplersOffset);
    IFTBOOL(((const char*)pInSS) + s <= pMaxPtr, E_FAIL);
    if (pRootSignature->NumStaticSamplers) {
      pRootSignature->pStaticSamplers = new DxilStaticSamplerDesc[pRootSignature->NumStaticSamplers];
    }
    memcpy((void*)pRootSignature->pStaticSamplers, pInSS, s);
  }
  
  _Use_decl_annotations_
  void DeserializeRootSignature(const void *pSrcData,
                                uint32_t SrcDataSizeInBytes,
                                const DxilVersionedRootSignatureDesc **ppRootSignature) {
    DxilVersionedRootSignatureDesc *pRootSignature = nullptr;
    IFTBOOL(pSrcData != nullptr && SrcDataSizeInBytes != 0 && ppRootSignature != nullptr, E_INVALIDARG);
    IFTBOOL(*ppRootSignature == nullptr, E_INVALIDARG);
    const char *pData = (const char *)pSrcData;
    IFTBOOL(pData + sizeof(uint32_t) < pData + SrcDataSizeInBytes, E_FAIL);
  
    DxilRootSignatureVersion Version = (const DxilRootSignatureVersion)((const uint32_t*)pData)[0];
  
    pRootSignature = new DxilVersionedRootSignatureDesc();
  
    try {
      switch (Version) {
      case DxilRootSignatureVersion::Version_1_0:
        pRootSignature->Version = DxilRootSignatureVersion::Version_1_0;
        DeserializeRootSignatureTemplate<
           DxilRootSignatureDesc,
           DxilRootParameter,
           DxilRootDescriptor,
           DxilRootDescriptor,
           DxilDescriptorRange,
           DxilContainerDescriptorRange>(pSrcData,
                                         SrcDataSizeInBytes,
                                         DxilRootSignatureVersion::Version_1_0,
                                         pRootSignature->Desc_1_0);
        break;
  
      case DxilRootSignatureVersion::Version_1_1:
        pRootSignature->Version = DxilRootSignatureVersion::Version_1_1;
        DeserializeRootSignatureTemplate<
           DxilRootSignatureDesc1,
           DxilRootParameter1,
           DxilRootDescriptor1,
           DxilContainerRootDescriptor1,
           DxilDescriptorRange1,
           DxilContainerDescriptorRange1>(pSrcData,
                                          SrcDataSizeInBytes,
                                          DxilRootSignatureVersion::Version_1_1,
                                          pRootSignature->Desc_1_1);
        break;
  
      default:
        IFT(E_FAIL);
        break;
      }
    } catch(...) {
      DeleteRootSignature(pRootSignature);
      throw;
    }
  
    *ppRootSignature = pRootSignature;
  }
  
  } // namespace hlsl
  