Skip to content

Commit 20bb3d0

Browse files
authored
PIX: Modify root sigs in place (plus fix root sig memory leak) (microsoft#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 (microsoft#4845) as it eveolved, since I needed that change and this to test PIX.
1 parent ee0994e commit 20bb3d0

File tree

5 files changed

+384
-159
lines changed

5 files changed

+384
-159
lines changed

include/dxc/DxilRootSignature/DxilRootSignature.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,43 @@ bool VerifyRootSignature(_In_ const DxilVersionedRootSignatureDesc *pDesc,
385385
_In_ llvm::raw_ostream &DiagStream,
386386
_In_ bool bAllowReservedRegisterSpace);
387387

388+
class DxilVersionedRootSignature {
389+
DxilVersionedRootSignatureDesc *m_pRootSignature;
390+
391+
public:
392+
// Non-copyable:
393+
DxilVersionedRootSignature(DxilVersionedRootSignature const &) = delete;
394+
DxilVersionedRootSignature const &
395+
operator=(DxilVersionedRootSignature const &) = delete;
396+
397+
// but movable:
398+
DxilVersionedRootSignature(DxilVersionedRootSignature &&) = default;
399+
DxilVersionedRootSignature &
400+
operator=(DxilVersionedRootSignature &&) = default;
401+
402+
DxilVersionedRootSignature() : m_pRootSignature(nullptr) {}
403+
explicit DxilVersionedRootSignature(
404+
const DxilVersionedRootSignatureDesc *pRootSignature)
405+
: m_pRootSignature(
406+
const_cast<DxilVersionedRootSignatureDesc *> (pRootSignature)) {}
407+
~DxilVersionedRootSignature() {
408+
DeleteRootSignature(m_pRootSignature);
409+
}
410+
const DxilVersionedRootSignatureDesc* operator -> () const {
411+
return m_pRootSignature;
412+
}
413+
const DxilVersionedRootSignatureDesc ** get_address_of() {
414+
if (m_pRootSignature != nullptr)
415+
return nullptr; // You're probably about to leak...
416+
return const_cast<const DxilVersionedRootSignatureDesc **> (&m_pRootSignature);
417+
}
418+
const DxilVersionedRootSignatureDesc* get() const {
419+
return m_pRootSignature;
420+
}
421+
DxilVersionedRootSignatureDesc* get_mutable() const {
422+
return m_pRootSignature;
423+
}
424+
};
388425
} // namespace hlsl
389426

390427
#endif // __DXC_ROOTSIGNATURE__

lib/DxilPIXPasses/PixPassHelpers.cpp

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99

1010
#include "dxc/DXIL/DxilOperations.h"
1111
#include "dxc/DXIL/DxilInstructions.h"
12+
#include "dxc/DXIL/DxilFunctionProps.h"
1213
#include "dxc/DXIL/DxilModule.h"
1314
#include "dxc/DXIL/DxilResourceBinding.h"
1415
#include "dxc/DXIL/DxilResourceProperties.h"
1516
#include "dxc/HLSL/DxilSpanAllocator.h"
17+
#include "dxc/DxilRootSignature/DxilRootSignature.h"
1618

1719
#include "llvm/IR/IRBuilder.h"
1820
#include "llvm/IR/Module.h"
@@ -21,6 +23,10 @@
2123

2224
#include "PixPassHelpers.h"
2325

26+
#include "dxc/Support/Global.h"
27+
#include "dxc/Support/WinIncludes.h"
28+
#include "dxc/dxcapi.h"
29+
2430
#ifdef PIX_DEBUG_DUMP_HELPER
2531
#include <iostream>
2632
#include "llvm/IR/DebugInfo.h"
@@ -159,7 +165,93 @@ llvm::CallInst *CreateHandleForResource(hlsl::DxilModule &DM,
159165
}
160166
}
161167

162-
// Set up a UAV with structure of a single int
168+
static std::vector<uint8_t> SerializeRootSignatureToVector(DxilVersionedRootSignatureDesc const *rootSignature) {
169+
CComPtr<IDxcBlob> serializedRootSignature;
170+
CComPtr<IDxcBlobEncoding> errorBlob;
171+
constexpr bool allowReservedRegisterSpace = true;
172+
SerializeRootSignature(rootSignature, &serializedRootSignature, &errorBlob,
173+
allowReservedRegisterSpace);
174+
std::vector<uint8_t> ret;
175+
auto const *serializedData = reinterpret_cast<const uint8_t *>(
176+
serializedRootSignature->GetBufferPointer());
177+
ret.assign(serializedData,
178+
serializedData + serializedRootSignature->GetBufferSize());
179+
180+
return ret;
181+
}
182+
183+
constexpr uint32_t toolsRegisterSpace = static_cast<uint32_t>(-2);
184+
constexpr uint32_t toolsUAVRegister = 0;
185+
186+
template<typename RootSigDesc, typename RootParameterDesc>
187+
void ExtendRootSig(RootSigDesc &rootSigDesc) {
188+
auto *existingParams = rootSigDesc.pParameters;
189+
auto *newParams = new RootParameterDesc[rootSigDesc.NumParameters + 1];
190+
if (existingParams != nullptr) {
191+
memcpy(newParams, existingParams,
192+
rootSigDesc.NumParameters * sizeof(RootParameterDesc));
193+
delete[] existingParams;
194+
}
195+
rootSigDesc.pParameters = newParams;
196+
rootSigDesc.pParameters[rootSigDesc.NumParameters].ParameterType = DxilRootParameterType::UAV;
197+
rootSigDesc.pParameters[rootSigDesc.NumParameters].Descriptor.RegisterSpace = toolsRegisterSpace;
198+
rootSigDesc.pParameters[rootSigDesc.NumParameters].Descriptor.ShaderRegister = toolsUAVRegister;
199+
rootSigDesc.pParameters[rootSigDesc.NumParameters].ShaderVisibility = DxilShaderVisibility::All;
200+
rootSigDesc.NumParameters++;
201+
}
202+
203+
static std::vector<uint8_t> AddUAVParamterToRootSignature(const void *Data,
204+
uint32_t Size) {
205+
DxilVersionedRootSignature rootSignature;
206+
DeserializeRootSignature(Data, Size, rootSignature.get_address_of());
207+
auto *rs = rootSignature.get_mutable();
208+
switch (rootSignature->Version) {
209+
case DxilRootSignatureVersion::Version_1_0:
210+
ExtendRootSig<DxilRootSignatureDesc, DxilRootParameter>(rs->Desc_1_0);
211+
break;
212+
case DxilRootSignatureVersion::Version_1_1:
213+
ExtendRootSig<DxilRootSignatureDesc1, DxilRootParameter1>(rs->Desc_1_1);
214+
rs->Desc_1_1.pParameters[rs->Desc_1_1.NumParameters - 1].Descriptor.Flags =
215+
hlsl::DxilRootDescriptorFlags::None;
216+
break;
217+
}
218+
return SerializeRootSignatureToVector(rs);
219+
}
220+
221+
static void AddUAVToShaderAttributeRootSignature(DxilModule &DM) {
222+
auto rs = DM.GetSerializedRootSignature();
223+
if(!rs.empty()) {
224+
std::vector<uint8_t> asVector = AddUAVParamterToRootSignature(rs.data(), static_cast<uint32_t>(rs.size()));
225+
DM.ResetSerializedRootSignature(asVector);
226+
}
227+
}
228+
229+
static void AddUAVToDxilDefinedGlobalRootSignatures(DxilModule& DM) {
230+
auto *subObjects = DM.GetSubobjects();
231+
if (subObjects != nullptr) {
232+
for (auto const &subObject : subObjects->GetSubobjects()) {
233+
if (subObject.second->GetKind() ==
234+
DXIL::SubobjectKind::GlobalRootSignature) {
235+
const void *Data = nullptr;
236+
uint32_t Size = 0;
237+
constexpr bool notALocalRS = false;
238+
if (subObject.second->GetRootSignature(notALocalRS, Data, Size,
239+
nullptr)) {
240+
auto extendedRootSig = AddUAVParamterToRootSignature(Data, Size);
241+
auto rootSignatureSubObjectName = subObject.first;
242+
subObjects->RemoveSubobject(rootSignatureSubObjectName);
243+
subObjects->CreateRootSignature(rootSignatureSubObjectName,
244+
notALocalRS,
245+
extendedRootSig.data(),
246+
static_cast<uint32_t>(extendedRootSig.size()));
247+
break;
248+
}
249+
}
250+
}
251+
}
252+
}
253+
254+
// Set up a UAV with structure of a single int
163255
llvm::CallInst *CreateUAV(DxilModule &DM, IRBuilder<> &Builder,
164256
unsigned int registerId, const char *name) {
165257
LLVMContext &Ctx = DM.GetModule()->getContext();
@@ -170,6 +262,11 @@ llvm::CallInst *CreateUAV(DxilModule &DM, IRBuilder<> &Builder,
170262
if (UAVStructTy == nullptr) {
171263
SmallVector<llvm::Type *, 1> Elements{Type::getInt32Ty(Ctx)};
172264
UAVStructTy = llvm::StructType::create(Elements, PIXStructTypeName);
265+
266+
// Since we only have to do this once per module, we can do it now when
267+
// we're adding the singular UAV structure type to the module:
268+
AddUAVToDxilDefinedGlobalRootSignatures(DM);
269+
AddUAVToShaderAttributeRootSignature(DM);
173270
}
174271

175272
std::unique_ptr<DxilResource> pUAV = llvm::make_unique<DxilResource>();

lib/DxilRootSignature/DxilRootSignatureSerializer.cpp

Lines changed: 0 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -332,93 +332,6 @@ void SerializeRootSignature(const DxilVersionedRootSignatureDesc *pRootSignature
332332
}
333333
}
334334

335-
//=============================================================================
336-
//
337-
// CVersionedRootSignatureDeserializer.
338-
//
339-
//=============================================================================
340-
class CVersionedRootSignatureDeserializer {
341-
protected:
342-
const DxilVersionedRootSignatureDesc *m_pRootSignature;
343-
const DxilVersionedRootSignatureDesc *m_pRootSignature10;
344-
const DxilVersionedRootSignatureDesc *m_pRootSignature11;
345-
346-
public:
347-
CVersionedRootSignatureDeserializer();
348-
~CVersionedRootSignatureDeserializer();
349-
350-
void Initialize(_In_reads_bytes_(SrcDataSizeInBytes) const void *pSrcData,
351-
_In_ uint32_t SrcDataSizeInBytes);
352-
353-
const DxilVersionedRootSignatureDesc *GetRootSignatureDescAtVersion(DxilRootSignatureVersion convertToVersion);
354-
355-
const DxilVersionedRootSignatureDesc *GetUnconvertedRootSignatureDesc();
356-
};
357-
358-
CVersionedRootSignatureDeserializer::CVersionedRootSignatureDeserializer()
359-
: m_pRootSignature(nullptr)
360-
, m_pRootSignature10(nullptr)
361-
, m_pRootSignature11(nullptr) {
362-
}
363-
364-
CVersionedRootSignatureDeserializer::~CVersionedRootSignatureDeserializer() {
365-
DeleteRootSignature(m_pRootSignature10);
366-
DeleteRootSignature(m_pRootSignature11);
367-
}
368-
369-
void CVersionedRootSignatureDeserializer::Initialize(_In_reads_bytes_(SrcDataSizeInBytes) const void *pSrcData,
370-
_In_ uint32_t SrcDataSizeInBytes) {
371-
const DxilVersionedRootSignatureDesc *pRootSignature = nullptr;
372-
DeserializeRootSignature(pSrcData, SrcDataSizeInBytes, &pRootSignature);
373-
374-
switch (pRootSignature->Version) {
375-
case DxilRootSignatureVersion::Version_1_0:
376-
m_pRootSignature10 = pRootSignature;
377-
break;
378-
379-
case DxilRootSignatureVersion::Version_1_1:
380-
m_pRootSignature11 = pRootSignature;
381-
break;
382-
383-
default:
384-
DeleteRootSignature(pRootSignature);
385-
return;
386-
}
387-
388-
m_pRootSignature = pRootSignature;
389-
}
390-
391-
const DxilVersionedRootSignatureDesc *
392-
CVersionedRootSignatureDeserializer::GetUnconvertedRootSignatureDesc() {
393-
return m_pRootSignature;
394-
}
395-
396-
const DxilVersionedRootSignatureDesc *
397-
CVersionedRootSignatureDeserializer::GetRootSignatureDescAtVersion(DxilRootSignatureVersion ConvertToVersion) {
398-
switch (ConvertToVersion) {
399-
case DxilRootSignatureVersion::Version_1_0:
400-
if (m_pRootSignature10 == nullptr) {
401-
ConvertRootSignature(m_pRootSignature,
402-
ConvertToVersion,
403-
(const DxilVersionedRootSignatureDesc **)&m_pRootSignature10);
404-
}
405-
return m_pRootSignature10;
406-
407-
case DxilRootSignatureVersion::Version_1_1:
408-
if (m_pRootSignature11 == nullptr) {
409-
ConvertRootSignature(m_pRootSignature,
410-
ConvertToVersion,
411-
(const DxilVersionedRootSignatureDesc **)&m_pRootSignature11);
412-
}
413-
return m_pRootSignature11;
414-
415-
default:
416-
IFTBOOL(false, E_FAIL);
417-
}
418-
419-
return nullptr;
420-
}
421-
422335
template<typename T_ROOT_SIGNATURE_DESC,
423336
typename T_ROOT_PARAMETER,
424337
typename T_ROOT_DESCRIPTOR,

lib/HLSL/DxilValidation.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5850,13 +5850,14 @@ HRESULT ValidateDxilBitcode(
58505850
IFT(CreateMemoryStream(DxcGetThreadMallocNoRef(), &pOutputStream));
58515851
pOutputStream->Reserve(pWriter->size());
58525852
pWriter->write(pOutputStream);
5853+
DxilVersionedRootSignature desc;
58535854
try {
5854-
const DxilVersionedRootSignatureDesc* pDesc = nullptr;
5855-
DeserializeRootSignature(SerializedRootSig.data(), SerializedRootSig.size(), &pDesc);
5856-
if (!pDesc) {
5855+
DeserializeRootSignature(SerializedRootSig.data(),
5856+
SerializedRootSig.size(), desc.get_address_of());
5857+
if (!desc.get()) {
58575858
return DXC_E_INCORRECT_ROOT_SIGNATURE;
58585859
}
5859-
IFTBOOL(VerifyRootSignatureWithShaderPSV(pDesc,
5860+
IFTBOOL(VerifyRootSignatureWithShaderPSV(desc.get(),
58605861
dxilModule.GetShaderModel()->GetKind(),
58615862
pOutputStream->GetPtr(), pWriter->size(),
58625863
DiagStream), DXC_E_INCORRECT_ROOT_SIGNATURE);

0 commit comments

Comments
 (0)