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.
This commit is contained in:
Jeff Noyle 2022-12-15 16:36:09 -08:00 коммит произвёл GitHub
Родитель ee0994e58e
Коммит 20bb3d0228
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 384 добавлений и 159 удалений

Просмотреть файл

@ -385,6 +385,43 @@ bool VerifyRootSignature(_In_ const DxilVersionedRootSignatureDesc *pDesc,
_In_ llvm::raw_ostream &DiagStream,
_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
#endif // __DXC_ROOTSIGNATURE__

Просмотреть файл

@ -9,10 +9,12 @@
#include "dxc/DXIL/DxilOperations.h"
#include "dxc/DXIL/DxilInstructions.h"
#include "dxc/DXIL/DxilFunctionProps.h"
#include "dxc/DXIL/DxilModule.h"
#include "dxc/DXIL/DxilResourceBinding.h"
#include "dxc/DXIL/DxilResourceProperties.h"
#include "dxc/HLSL/DxilSpanAllocator.h"
#include "dxc/DxilRootSignature/DxilRootSignature.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
@ -21,6 +23,10 @@
#include "PixPassHelpers.h"
#include "dxc/Support/Global.h"
#include "dxc/Support/WinIncludes.h"
#include "dxc/dxcapi.h"
#ifdef PIX_DEBUG_DUMP_HELPER
#include <iostream>
#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,
unsigned int registerId, const char *name) {
LLVMContext &Ctx = DM.GetModule()->getContext();
@ -170,6 +262,11 @@ llvm::CallInst *CreateUAV(DxilModule &DM, IRBuilder<> &Builder,
if (UAVStructTy == nullptr) {
SmallVector<llvm::Type *, 1> Elements{Type::getInt32Ty(Ctx)};
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>();

Просмотреть файл

@ -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,
typename T_ROOT_PARAMETER,
typename T_ROOT_DESCRIPTOR,

Просмотреть файл

@ -5850,13 +5850,14 @@ HRESULT ValidateDxilBitcode(
IFT(CreateMemoryStream(DxcGetThreadMallocNoRef(), &pOutputStream));
pOutputStream->Reserve(pWriter->size());
pWriter->write(pOutputStream);
DxilVersionedRootSignature desc;
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;
}
IFTBOOL(VerifyRootSignatureWithShaderPSV(pDesc,
IFTBOOL(VerifyRootSignatureWithShaderPSV(desc.get(),
dxilModule.GetShaderModel()->GetKind(),
pOutputStream->GetPtr(), pWriter->size(),
DiagStream), DXC_E_INCORRECT_ROOT_SIGNATURE);

Просмотреть файл

@ -25,7 +25,12 @@
#include <sstream>
#include <algorithm>
#include <cfloat>
#include "dxc/Support/WinIncludes.h"
#include "dxc/DxilContainer/DxilContainer.h"
#include "dxc/DxilContainer/DxilRuntimeReflection.h"
#include "dxc/DxilRootSignature/DxilRootSignature.h"
#include "dxc/Support/WinIncludes.h"
#include "dxc/dxcapi.h"
#include "dxc/dxcpix.h"
@ -195,10 +200,6 @@ public:
TEST_METHOD(DiaCompileArgs)
TEST_METHOD(PixDebugCompileInfo)
TEST_METHOD(CheckSATPassFor66_NoDynamicAccess)
TEST_METHOD(CheckSATPassFor66_DynamicFromRootSig)
TEST_METHOD(CheckSATPassFor66_DynamicFromHeap)
TEST_METHOD(AddToASPayload)
TEST_METHOD(PixStructAnnotation_Lib_DualRaygen)
@ -223,6 +224,9 @@ public:
TEST_METHOD(VirtualRegisters_InstructionCounts)
TEST_METHOD(RootSignatureUpgrade_SubObjects)
TEST_METHOD(RootSignatureUpgrade_Annotation)
dxc::DxcDllSupport m_dllSupport;
VersionSupportInfo m_ver;
@ -1003,8 +1007,9 @@ public:
bool validateCoverage = true,
const wchar_t *profile = L"as_6_5");
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);
};
@ -1665,81 +1670,35 @@ TEST_F(PixTest, PixDebugCompileInfo) {
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;
VERIFY_SUCCEEDED(
m_dllSupport.CreateInstance(CLSID_DxcOptimizer, &pOptimizer));
std::vector<LPCWSTR> Options;
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<IDxcBlobEncoding> pText;
VERIFY_SUCCEEDED(pOptimizer->RunOptimizer(
dxil, Options.data(), Options.size(), &pOptimizedModule, &pText));
blob, Options.data(), Options.size(), &pOptimizedModule, &pText));
std::string outputText;
if (pText->GetBufferSize() != 0) {
outputText = reinterpret_cast<const char *>(pText->GetBufferPointer());
}
CComPtr<IDxcAssembler> pAssembler;
VERIFY_SUCCEEDED(
m_dllSupport.CreateInstance(CLSID_DxcAssembler, &pAssembler));
return outputText;
}
CComPtr<IDxcOperationResult> pAssembleResult;
VERIFY_SUCCEEDED(
pAssembler->AssembleToContainer(pOptimizedModule, &pAssembleResult));
TEST_F(PixTest, CheckSATPassFor66_NoDynamicAccess) {
HRESULT hr;
VERIFY_SUCCEEDED(pAssembleResult->GetStatus(&hr));
VERIFY_SUCCEEDED(hr);
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;
}
)";
CComPtr<IDxcBlob> pNewContainer;
VERIFY_SUCCEEDED(pAssembleResult->GetResult(&pNewContainer));
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";
auto compiled = Compile(dynamicTextureAccess, L"ps_6_6");
auto satResults = RunShaderAccessTrackingPassAndReturnOutputMessages(compiled);
VERIFY_IS_TRUE(satResults.find("FoundDynamicIndexing") != string::npos);
}
TEST_F(PixTest, CheckSATPassFor66_DynamicFromHeap) {
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));
}
)";
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) {
@ -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