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:
Родитель
ee0994e58e
Коммит
20bb3d0228
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче