Add Subobjects: classes, metadata, serialization, reflection, disasm

This commit is contained in:
Tex Riddell 2018-10-17 20:22:33 -07:00
Родитель 527bfc4176
Коммит 9678588269
15 изменённых файлов: 1404 добавлений и 57 удалений

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

@ -1131,6 +1131,31 @@ namespace DXIL {
const unsigned ShaderFeatureInfoCount = 19;
// DxilSubobjectType must match D3D12_STATE_SUBOBJECT_TYPE, with
// certain values reserved, since they cannot be used from Dxil.
enum class SubobjectKind : uint32_t {
StateObjectConfig = 0,
GlobalRootSignature = 1,
LocalRootSignature = 2,
// 3-7 are reserved (not supported in Dxil)
SubobjectToExportsAssociation = 8,
RaytracingShaderConfig = 9,
RaytracingPipelineConfig = 10,
HitGroup = 11,
NumKinds // aka D3D12_STATE_SUBOBJECT_TYPE_MAX_VALID
};
inline bool IsValidSubobjectKind(SubobjectKind kind) {
return (kind < SubobjectKind::NumKinds &&
( kind <= SubobjectKind::LocalRootSignature ||
kind >= SubobjectKind::SubobjectToExportsAssociation));
}
enum class StateObjectFlags : uint32_t {
AllowLocalDependenciesOnExternalDefinitions = 0x1,
AllowExternalDependenciesOnLocalDefinitions = 0x2,
ValidMask = 0x3,
};
extern const char* kLegacyLayoutString;
extern const char* kNewLayoutString;
extern const char* kFP32DenormKindString;

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

@ -29,6 +29,7 @@ class MDTuple;
class MDNode;
class NamedMDNode;
class GlobalVariable;
class StringRef;
}
namespace hlsl {
@ -49,6 +50,8 @@ class DxilFunctionAnnotation;
class DxilParameterAnnotation;
class RootSignatureHandle;
struct DxilFunctionProps;
class DxilSubobjects;
class DxilSubobject;
/// Use this class to manipulate DXIL-spcific metadata.
// In our code, only DxilModule and HLModule should use this class.
@ -80,6 +83,9 @@ public:
// ViewId state.
static const char kDxilViewIdStateMDName[];
// Subobjects
static const char kDxilSubobjectsMDName[];
// Source info.
static const char kDxilSourceContentsMDName[];
static const char kDxilSourceDefinesMDName[];
@ -357,6 +363,11 @@ public:
// Control flow hints.
static llvm::MDNode *EmitControlFlowHints(llvm::LLVMContext &Ctx, std::vector<DXIL::ControlFlowHint> &hints);
// Subobjects
void EmitSubobjects(const DxilSubobjects &Subobjects);
void LoadSubobjects(DxilSubobjects &Subobjects);
llvm::Metadata *EmitSubobject(const DxilSubobject &obj);
void LoadSubobject(const llvm::MDNode &MDO, DxilSubobjects &Subobjects);
// Shader specific.
private:
@ -408,6 +419,7 @@ public:
static bool ConstMDToBool(const llvm::MDOperand &MDO);
static float ConstMDToFloat(const llvm::MDOperand &MDO);
static std::string StringMDToString(const llvm::MDOperand &MDO);
static llvm::StringRef StringMDToStringRef(const llvm::MDOperand &MDO);
static llvm::Value *ValueMDToValue(const llvm::MDOperand &MDO);
llvm::MDTuple *Uint32VectorToConstMDTuple(const std::vector<unsigned> &Vec);
void ConstMDTupleToUint32Vector(llvm::MDTuple *pTupleMD, std::vector<unsigned> &Vec);

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

@ -11,13 +11,14 @@
#pragma once
#include "dxc/DXIL/DxilConstants.h"
#include "dxc/DXIL/DxilMetadataHelper.h"
#include "dxc/DXIL/DxilCBuffer.h"
#include "dxc/DXIL/DxilResource.h"
#include "dxc/DXIL/DxilSampler.h"
#include "dxc/DXIL/DxilShaderFlags.h"
#include "dxc/DXIL/DxilSignature.h"
#include "dxc/DXIL/DxilConstants.h"
#include "dxc/DXIL/DxilSubobject.h"
#include "dxc/DXIL/DxilTypeSystem.h"
#include <memory>
@ -147,6 +148,8 @@ public:
// Remove Root Signature from module metadata
void StripRootSignatureFromMetadata();
// Remove Subobjects from module metadata
void StripSubobjectsFromMetadata();
// Update validator version metadata to current setting
void UpdateValidatorVersionMetadata();
@ -268,6 +271,11 @@ public:
void SetShaderProperties(DxilFunctionProps *props);
DxilSubobjects *GetSubobjects();
const DxilSubobjects *GetSubobjects() const;
DxilSubobjects *ReleaseSubobjects();
void ResetSubobjects(DxilSubobjects *subobjects);
private:
// Signatures.
std::vector<uint8_t> m_SerializedRootSignature;
@ -326,6 +334,8 @@ private:
bool m_bUseMinPrecision;
bool m_bAllResourcesBound;
uint32_t m_AutoBindingSpace;
std::unique_ptr<DxilSubobjects> m_pSubobjects;
};
} // namespace hlsl

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

@ -0,0 +1,154 @@
///////////////////////////////////////////////////////////////////////////////
// //
// DxilSubobject.h //
// Copyright (C) Microsoft Corporation. All rights reserved. //
// This file is distributed under the University of Illinois Open Source //
// License. See LICENSE.TXT for details. //
// //
// Defines Subobject types for DxilModule. //
// //
///////////////////////////////////////////////////////////////////////////////
#pragma once
#include <vector>
#include <memory>
#include <unordered_map>
#include <map>
#include "DxilConstants.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringRef.h"
using namespace llvm;
namespace hlsl {
class DxilSubobjects;
class DxilSubobject {
public:
using Kind = DXIL::SubobjectKind;
DxilSubobject() = delete;
DxilSubobject(const DxilSubobject &other) = delete;
DxilSubobject(DxilSubobject &&other);
~DxilSubobject();
DxilSubobject &operator=(const DxilSubobject &other) = delete;
Kind GetKind() const { return m_Kind; }
llvm::StringRef GetName() const { return m_Name; }
// Note: strings and root signature data is owned by DxilModule
// When creating subobjects, use canonical strings from module
bool GetStateObjectConfig(uint32_t &Flags) const;
bool GetRootSignature(bool local, const void * &Data, uint32_t &Size) const;
bool GetSubobjectToExportsAssociation(llvm::StringRef &Subobject,
const char * const * &Exports,
uint32_t &NumExports) const;
bool GetRaytracingShaderConfig(uint32_t &MaxPayloadSizeInBytes,
uint32_t &MaxAttributeSizeInBytes) const;
bool GetRaytracingPipelineConfig(uint32_t &MaxTraceRecursionDepth) const;
bool GetHitGroup(llvm::StringRef &Intersection,
llvm::StringRef &AnyHit,
llvm::StringRef &ClosestHit) const;
private:
DxilSubobject(DxilSubobjects &owner, Kind kind, llvm::StringRef name);
DxilSubobject(DxilSubobjects &owner, const DxilSubobject &other, llvm::StringRef name);
void CopyUnionedContents(const DxilSubobject &other);
void InternStrings();
DxilSubobjects &m_Owner;
Kind m_Kind;
llvm::StringRef m_Name;
std::vector<const char*> m_Exports;
union {
struct {
uint32_t Flags; // DXIL::StateObjectFlags
} StateObjectConfig;
struct {
uint32_t Size;
const void *Data;
} RootSignature;
struct {
const char *Subobject;
// see m_Exports for export list
} SubobjectToExportsAssociation;
struct {
uint32_t MaxPayloadSizeInBytes;
uint32_t MaxAttributeSizeInBytes;
} RaytracingShaderConfig;
struct {
uint32_t MaxTraceRecursionDepth;
} RaytracingPipelineConfig;
struct {
const char *Intersection;
const char *AnyHit;
const char *ClosestHit;
} HitGroup;
};
friend class DxilSubobjects;
};
class DxilSubobjects {
public:
typedef llvm::MapVector< llvm::StringRef, std::string > StringStorage;
typedef llvm::MapVector< const void*, std::vector<char> > RawBytesStorage;
typedef llvm::MapVector< llvm::StringRef, std::unique_ptr<DxilSubobject> > SubobjectStorage;
using Kind = DXIL::SubobjectKind;
DxilSubobjects();
DxilSubobjects(const DxilSubobjects &other) = delete;
DxilSubobjects(DxilSubobjects &&other);
~DxilSubobjects();
DxilSubobjects &operator=(const DxilSubobjects &other) = delete;
// Add/find string in owned subobject strings, returning canonical ptr
llvm::StringRef GetSubobjectString(StringRef value);
// Add/find raw bytes, returning canonical ptr
const void *GetRawBytes(const void *ptr, size_t size);
DxilSubobject *FindSubobject(StringRef name);
void RemoveSubobject(StringRef name);
DxilSubobject &CloneSubobject(const DxilSubobject &Subobject, llvm::StringRef Name);
const SubobjectStorage &GetSubobjects() const { return m_Subobjects; }
// Create DxilSubobjects
DxilSubobject &CreateStateObjectConfig(llvm::StringRef Name,
uint32_t Flags);
// Local/Global RootSignature
DxilSubobject &CreateRootSignature(llvm::StringRef Name,
bool local,
const void *Data,
uint32_t Size);
DxilSubobject &CreateSubobjectToExportsAssociation(
llvm::StringRef Name,
llvm::StringRef Subobject, const char * const *Exports, uint32_t NumExports);
DxilSubobject &CreateRaytracingShaderConfig(
llvm::StringRef Name,
uint32_t MaxPayloadSizeInBytes,
uint32_t MaxAttributeSizeInBytes);
DxilSubobject &CreateRaytracingPipelineConfig(
llvm::StringRef Name,
uint32_t MaxTraceRecursionDepth);
DxilSubobject &CreateHitGroup(llvm::StringRef Name,
llvm::StringRef Intersection,
llvm::StringRef AnyHit,
llvm::StringRef ClosestHit);
private:
DxilSubobject &CreateSubobject(Kind kind, llvm::StringRef Name);
StringStorage m_StringStorage;
RawBytesStorage m_RawBytesStorage;
SubobjectStorage m_Subobjects;
};
} // namespace hlsl

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

@ -30,17 +30,20 @@ namespace RDAT {
// - else if part.Type is Index:
// uint32_t IndexData[part.Size / 4];
enum class RuntimeDataPartType : uint32_t { // TODO: Rename: PartType
Invalid = 0,
StringBuffer = 1,
IndexArrays = 2,
ResourceTable = 3,
FunctionTable = 4,
enum class RuntimeDataPartType : uint32_t {
Invalid = 0,
StringBuffer = 1,
IndexArrays = 2,
ResourceTable = 3,
FunctionTable = 4,
RawBytes = 5,
SubobjectTable = 6,
};
enum RuntimeDataVersion {
// Cannot be mistaken for part count from prerelease version
RDAT_Version_0 = 0x10,
RDAT_Version_10 = 0x10,
RDAT_Version_11 = 0x11,
};
struct RuntimeDataHeader {
@ -165,7 +168,7 @@ struct RuntimeDataFunctionInfo {
uint32_t FunctionDependencies; // index to a list of functions that function
// depends on
uint32_t ShaderKind;
uint32_t PayloadSizeInBytes; // 1) hit, miss, or closest shader: payload count
uint32_t PayloadSizeInBytes; // 1) any/closest hit or miss shader: payload size
// 2) call shader: parameter size
uint32_t AttributeSizeInBytes; // attribute size for closest hit and any hit
uint32_t FeatureInfo1; // first 32 bits of feature flag
@ -174,14 +177,62 @@ struct RuntimeDataFunctionInfo {
uint32_t MinShaderTarget; // minimum shader target.
};
class RawBytesReader {
const void *m_table;
uint32_t m_size;
public:
RawBytesReader() : m_table(nullptr), m_size(0) {}
RawBytesReader(const void *table, uint32_t size)
: m_table(table), m_size(size) {}
const void *Get(uint32_t offset) const {
_Analysis_assume_(offset < m_size && m_table);
return (const void*)(((const char*)m_table) + offset);
}
};
struct RuntimeDataSobobjectInfo {
uint32_t Kind;
uint32_t Name;
union {
struct {
uint32_t Flags;
} StateObjectConfig;
struct {
uint32_t RawBytesOffset;
uint32_t SizeInBytes;
} RootSignature;
struct {
uint32_t Sobobject; // string table offset for name of subobject
uint32_t Exports; // index table offset for array of string table offsets for export names
} SubobjectToExportsAssociation;
struct {
uint32_t MaxPayloadSizeInBytes;
uint32_t MaxAttributeSizeInBytes;
} RaytracingShaderConfig;
struct {
uint32_t MaxTraceRecursionDepth;
} RaytracingPipelineConfig;
struct {
// each is a string table offset for the shader name
// 0 points to empty name, indicating no shader.
uint32_t Intersection;
uint32_t AnyHit;
uint32_t ClosestHit;
} HitGroup;
};
};
class ResourceTableReader;
class FunctionTableReader;
class SubobjectTableReader;
struct RuntimeDataContext {
StringTableReader *pStringTableReader;
IndexTableReader *pIndexTableReader;
RawBytesReader *pRawBytesReader;
ResourceTableReader *pResourceTableReader;
FunctionTableReader *pFunctionTableReader;
SubobjectTableReader *pSubobjectTableReader;
};
class ResourceReader {
@ -379,20 +430,132 @@ public:
class FunctionTableReader {
private:
TableReader m_Table;
RuntimeDataContext *m_context;
RuntimeDataContext *m_Context;
public:
FunctionTableReader() : m_context(nullptr) {}
FunctionTableReader() : m_Context(nullptr) {}
FunctionReader GetItem(uint32_t i) const {
return FunctionReader(m_Table.Row<RuntimeDataFunctionInfo>(i), m_context);
return FunctionReader(m_Table.Row<RuntimeDataFunctionInfo>(i), m_Context);
}
uint32_t GetNumFunctions() const { return m_Table.Count(); }
void SetFunctionInfo(const char *ptr, uint32_t count, uint32_t recordStride) {
m_Table.Init(ptr, count, recordStride);
}
void SetContext(RuntimeDataContext *context) { m_context = context; }
void SetContext(RuntimeDataContext *context) { m_Context = context; }
};
class SubobjectReader {
private:
const RuntimeDataSobobjectInfo *m_SubobjectInfo;
RuntimeDataContext *m_Context;
public:
SubobjectReader(const RuntimeDataSobobjectInfo *info, RuntimeDataContext *context)
: m_SubobjectInfo(info), m_Context(context) {}
DXIL::SubobjectKind GetKind() const {
return m_SubobjectInfo ? (DXIL::SubobjectKind)(m_SubobjectInfo->Kind) :
(DXIL::SubobjectKind)(-1);
}
const char *GetName() const {
return m_SubobjectInfo && m_SubobjectInfo->Name ?
m_Context->pStringTableReader->Get(m_SubobjectInfo->Name) : "";
}
// StateObjectConfig
uint32_t GetStateObjectConfig_Flags() const {
return (GetKind() == DXIL::SubobjectKind::StateObjectConfig) ?
m_SubobjectInfo->StateObjectConfig.Flags : (uint32_t)0;
}
// [Global|Local]RootSignature
// returns true if valid non-zero-length buffer found and set to output params
bool GetRootSignature(const void **ppOutBytes, uint32_t *pOutSizeInBytes) const {
if (!ppOutBytes || !pOutSizeInBytes)
return false;
if (m_SubobjectInfo &&
( GetKind() == DXIL::SubobjectKind::GlobalRootSignature ||
GetKind() == DXIL::SubobjectKind::LocalRootSignature ) &&
m_SubobjectInfo->RootSignature.SizeInBytes > 0) {
*ppOutBytes = m_Context->pRawBytesReader->Get(m_SubobjectInfo->RootSignature.RawBytesOffset);
*pOutSizeInBytes = m_SubobjectInfo->RootSignature.SizeInBytes;
return true;
} else {
*ppOutBytes = nullptr;
*pOutSizeInBytes = 0;
}
return false;
}
// SubobjectToExportsAssociation
const char *GetSubobjectToExportsAssociation_Subobject() const {
return (GetKind() == DXIL::SubobjectKind::SubobjectToExportsAssociation) ?
m_Context->pStringTableReader->Get(m_SubobjectInfo->SubobjectToExportsAssociation.Sobobject) : "";
}
uint32_t GetSubobjectToExportsAssociation_NumExports() const {
return (GetKind() == DXIL::SubobjectKind::SubobjectToExportsAssociation) ?
m_Context->pIndexTableReader->getRow(m_SubobjectInfo->SubobjectToExportsAssociation.Exports).Count() : 0;
}
const char *GetSubobjectToExportsAssociation_Export(uint32_t index) const {
if (!(GetKind() == DXIL::SubobjectKind::SubobjectToExportsAssociation))
return "";
auto row = m_Context->pIndexTableReader->getRow(
m_SubobjectInfo->SubobjectToExportsAssociation.Exports);
if (index >= row.Count())
return "";
return m_Context->pStringTableReader->Get(row.At(index));
}
// RaytracingShaderConfig
uint32_t GetRaytracingShaderConfig_MaxPayloadSizeInBytes() const {
return (GetKind() == DXIL::SubobjectKind::RaytracingShaderConfig) ?
m_SubobjectInfo->RaytracingShaderConfig.MaxPayloadSizeInBytes : 0;
}
uint32_t GetRaytracingShaderConfig_MaxAttributeSizeInBytes() const {
return (GetKind() == DXIL::SubobjectKind::RaytracingShaderConfig) ?
m_SubobjectInfo->RaytracingShaderConfig.MaxAttributeSizeInBytes : 0;
}
// RaytracingPipelineConfig
uint32_t GetRaytracingPipelineConfig_MaxTraceRecursionDepth() const {
return (GetKind() == DXIL::SubobjectKind::RaytracingPipelineConfig) ?
m_SubobjectInfo->RaytracingPipelineConfig.MaxTraceRecursionDepth : 0;
}
// HitGroup
const char *GetHitGroup_Intersection() const {
return (GetKind() == DXIL::SubobjectKind::HitGroup) ?
m_Context->pStringTableReader->Get(m_SubobjectInfo->HitGroup.Intersection) : "";
}
const char *GetHitGroup_AnyHit() const {
return (GetKind() == DXIL::SubobjectKind::HitGroup) ?
m_Context->pStringTableReader->Get(m_SubobjectInfo->HitGroup.AnyHit) : "";
}
const char *GetHitGroup_ClosestHit() const {
return (GetKind() == DXIL::SubobjectKind::HitGroup) ?
m_Context->pStringTableReader->Get(m_SubobjectInfo->HitGroup.ClosestHit) : "";
}
};
class SubobjectTableReader {
private:
TableReader m_Table;
RuntimeDataContext *m_Context;
public:
SubobjectTableReader() : m_Context(nullptr) {}
void SetContext(RuntimeDataContext *context) { m_Context = context; }
void SetSubobjectInfo(const char *ptr, uint32_t count, uint32_t recordStride) {
m_Table.Init(ptr, count, recordStride);
}
uint32_t GetCount() const { return m_Table.Count(); }
SubobjectReader GetItem(uint32_t i) const {
return SubobjectReader(m_Table.Row<RuntimeDataSobobjectInfo>(i), m_Context);
}
};
class DxilRuntimeData {
@ -400,8 +563,10 @@ private:
uint32_t m_TableCount;
StringTableReader m_StringReader;
IndexTableReader m_IndexTableReader;
RawBytesReader m_RawBytesReader;
ResourceTableReader m_ResourceTableReader;
FunctionTableReader m_FunctionTableReader;
SubobjectTableReader m_SubobjectTableReader;
RuntimeDataContext m_Context;
public:
@ -413,6 +578,7 @@ public:
bool InitFromRDAT_Prerelease(const void *pRDAT, size_t size);
FunctionTableReader *GetFunctionTableReader();
ResourceTableReader *GetResourceTableReader();
SubobjectTableReader *GetSubobjectTableReader();
};
//////////////////////////////////
@ -447,6 +613,34 @@ typedef struct DxilFunctionDesc {
} DxilFunctionDesc;
typedef struct DxilSubobjectDesc {
uint32_t Kind; // DXIL::SubobjectKind / D3D12_STATE_SUBOBJECT_TYPE
LPCWSTR Name;
union {
struct {
uint32_t Flags; // DXIL::StateObjectFlags / D3D12_STATE_OBJECT_FLAGS
} StateObjectConfig;
struct {
LPCVOID pSerializedSignature;
uint32_t SizeInBytes;
} RootSignature; // GlobalRootSignature or LocalRootSignature
struct {
LPCWSTR Subobject;
uint32_t NumExports;
const LPCWSTR* Exports;
} SubobjectToExportsAssociation;
struct {
uint32_t MaxPayloadSizeInBytes;
uint32_t MaxAttributeSizeInBytes;
} RaytracingShaderConfig;
struct {
uint32_t MaxTraceRecursionDepth;
} RaytracingPipelineConfig;
struct {
LPCWSTR Intersection;
LPCWSTR AnyHit;
LPCWSTR ClosestHit;
} HitGroup;
};
} DxilSubobjectDesc;
typedef struct DxilLibraryDesc {

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

@ -93,12 +93,15 @@ public:
DxilRuntimeData::DxilRuntimeData() : DxilRuntimeData(nullptr, 0) {}
DxilRuntimeData::DxilRuntimeData(const char *ptr, size_t size)
: m_TableCount(0), m_StringReader(), m_ResourceTableReader(),
m_FunctionTableReader(), m_IndexTableReader(), m_Context() {
m_Context = {&m_StringReader, &m_IndexTableReader, &m_ResourceTableReader,
&m_FunctionTableReader};
: m_TableCount(0), m_StringReader(), m_IndexTableReader(), m_RawBytesReader(),
m_ResourceTableReader(), m_FunctionTableReader(),
m_SubobjectTableReader(), m_Context() {
m_Context = {&m_StringReader, &m_IndexTableReader, &m_RawBytesReader,
&m_ResourceTableReader, &m_FunctionTableReader,
&m_SubobjectTableReader};
m_ResourceTableReader.SetContext(&m_Context);
m_FunctionTableReader.SetContext(&m_Context);
m_SubobjectTableReader.SetContext(&m_Context);
InitFromRDAT(ptr, size);
}
@ -108,7 +111,7 @@ bool DxilRuntimeData::InitFromRDAT(const void *pRDAT, size_t size) {
try {
CheckedReader Reader(pRDAT, size);
RuntimeDataHeader RDATHeader = Reader.Read<RuntimeDataHeader>();
if (RDATHeader.Version < RDAT_Version_0) {
if (RDATHeader.Version < RDAT_Version_10) {
// Prerelease version, fallback to that Init
return InitFromRDAT_Prerelease(pRDAT, size);
}
@ -129,6 +132,11 @@ bool DxilRuntimeData::InitFromRDAT(const void *pRDAT, size_t size) {
PR.ReadArray<uint32_t>(count), count);
break;
}
case RuntimeDataPartType::RawBytes: {
m_RawBytesReader = RawBytesReader(
PR.ReadArray<char>(part.Size), part.Size);
break;
}
case RuntimeDataPartType::ResourceTable: {
RuntimeDataTableHeader table = PR.Read<RuntimeDataTableHeader>();
size_t tableSize = table.RecordCount * table.RecordStride;
@ -143,6 +151,13 @@ bool DxilRuntimeData::InitFromRDAT(const void *pRDAT, size_t size) {
table.RecordCount, table.RecordStride);
break;
}
case RuntimeDataPartType::SubobjectTable: {
RuntimeDataTableHeader table = PR.Read<RuntimeDataTableHeader>();
size_t tableSize = table.RecordCount * table.RecordStride;
m_SubobjectTableReader.SetSubobjectInfo(PR.ReadArray<char>(tableSize),
table.RecordCount, table.RecordStride);
break;
}
default:
continue; // Skip unrecognized parts
}
@ -226,6 +241,10 @@ ResourceTableReader *DxilRuntimeData::GetResourceTableReader() {
return &m_ResourceTableReader;
}
SubobjectTableReader *DxilRuntimeData::GetSubobjectTableReader() {
return &m_SubobjectTableReader;
}
}} // hlsl::RDAT
using namespace hlsl;
@ -245,18 +264,21 @@ namespace {
class DxilRuntimeReflection_impl : public DxilRuntimeReflection {
private:
typedef std::unordered_map<const char *, std::unique_ptr<wchar_t[]>> StringMap;
typedef std::vector<const wchar_t *> WStringList;
typedef std::vector<DxilResourceDesc> ResourceList;
typedef std::vector<DxilResourceDesc *> ResourceRefList;
typedef std::vector<DxilFunctionDesc> FunctionList;
typedef std::vector<const wchar_t *> WStringList;
typedef std::vector<DxilSubobjectDesc> SubobjectList;
DxilRuntimeData m_RuntimeData;
StringMap m_StringMap;
ResourceList m_Resources;
FunctionList m_Functions;
SubobjectList m_Subobjects;
std::unordered_map<ResourceKey, DxilResourceDesc *> m_ResourceMap;
std::unordered_map<DxilFunctionDesc *, ResourceRefList> m_FuncToResMap;
std::unordered_map<DxilFunctionDesc *, WStringList> m_FuncToStringMap;
std::unordered_map<DxilSubobjectDesc *, WStringList> m_SubobjectToStringMap;
bool m_initialized;
const wchar_t *GetWideString(const char *ptr);
@ -266,15 +288,19 @@ private:
const FunctionReader &functionReader);
const wchar_t **GetDependenciesForFunction(DxilFunctionDesc &function,
const FunctionReader &functionReader);
const wchar_t **GetExportsForAssociation(DxilSubobjectDesc &subobject,
const SubobjectReader &subobjectReader);
DxilResourceDesc *AddResource(const ResourceReader &resourceReader);
DxilFunctionDesc *AddFunction(const FunctionReader &functionReader);
DxilSubobjectDesc *AddSubobject(const SubobjectReader &subobjectReader);
public:
// TODO: Implement pipeline state validation with runtime data
// TODO: Update BlobContainer.h to recognize 'RDAT' blob
DxilRuntimeReflection_impl()
: m_RuntimeData(), m_StringMap(), m_Resources(), m_Functions(),
m_FuncToResMap(), m_FuncToStringMap(), m_initialized(false) {}
m_FuncToResMap(), m_FuncToStringMap(), m_SubobjectToStringMap(),
m_initialized(false) {}
virtual ~DxilRuntimeReflection_impl() {}
// This call will allocate memory for GetLibraryReflection call
bool InitFromRDAT(const void *pRDAT, size_t size) override;
@ -342,6 +368,13 @@ void DxilRuntimeReflection_impl::InitializeReflection() {
AddString(functionReader.GetName());
AddFunction(functionReader);
}
const SubobjectTableReader *subobjectTableReader = m_RuntimeData.GetSubobjectTableReader();
m_Subobjects.reserve(subobjectTableReader->GetCount());
for (uint32_t i = 0; i < subobjectTableReader->GetCount(); ++i) {
SubobjectReader subobjectReader = subobjectTableReader->GetItem(i);
AddString(subobjectReader.GetName());
AddSubobject(subobjectReader);
}
}
DxilResourceDesc *
@ -418,6 +451,60 @@ DxilRuntimeReflection_impl::AddFunction(const FunctionReader &functionReader) {
return &function;
}
const wchar_t **DxilRuntimeReflection_impl::GetExportsForAssociation(
DxilSubobjectDesc &subobject, const SubobjectReader &subobjectReader) {
if (m_SubobjectToStringMap.find(&subobject) == m_SubobjectToStringMap.end())
m_SubobjectToStringMap.insert(
std::pair<DxilSubobjectDesc *, WStringList>(&subobject, WStringList()));
WStringList &wStringList = m_SubobjectToStringMap.at(&subobject);
for (uint32_t i = 0; i < subobjectReader.GetSubobjectToExportsAssociation_NumExports(); ++i) {
wStringList.emplace_back(GetWideString(subobjectReader.GetSubobjectToExportsAssociation_Export(i)));
}
return wStringList.empty() ? nullptr : wStringList.data();
}
DxilSubobjectDesc *DxilRuntimeReflection_impl::AddSubobject(const SubobjectReader &subobjectReader) {
assert(m_Subobjects.size() < m_Subobjects.capacity() && "Otherwise, number of subobjects was incorrect");
if (!(m_Subobjects.size() < m_Subobjects.capacity()))
return nullptr;
m_Subobjects.emplace_back(DxilSubobjectDesc({0}));
DxilSubobjectDesc &subobject = m_Subobjects.back();
subobject.Name = GetWideString(subobjectReader.GetName());
subobject.Kind = (uint32_t)subobjectReader.GetKind();
switch (subobjectReader.GetKind()) {
case DXIL::SubobjectKind::StateObjectConfig:
subobject.StateObjectConfig.Flags = subobjectReader.GetStateObjectConfig_Flags();
break;
case DXIL::SubobjectKind::GlobalRootSignature:
case DXIL::SubobjectKind::LocalRootSignature:
if (!subobjectReader.GetRootSignature(&subobject.RootSignature.pSerializedSignature, &subobject.RootSignature.SizeInBytes))
return nullptr;
break;
case DXIL::SubobjectKind::SubobjectToExportsAssociation:
subobject.SubobjectToExportsAssociation.Subobject =
GetWideString(subobjectReader.GetSubobjectToExportsAssociation_Subobject());
subobject.SubobjectToExportsAssociation.NumExports = subobjectReader.GetSubobjectToExportsAssociation_NumExports();
subobject.SubobjectToExportsAssociation.Exports = GetExportsForAssociation(subobject, subobjectReader);
break;
case DXIL::SubobjectKind::RaytracingShaderConfig:
subobject.RaytracingShaderConfig.MaxPayloadSizeInBytes = subobjectReader.GetRaytracingShaderConfig_MaxPayloadSizeInBytes();
subobject.RaytracingShaderConfig.MaxAttributeSizeInBytes = subobjectReader.GetRaytracingShaderConfig_MaxAttributeSizeInBytes();
break;
case DXIL::SubobjectKind::RaytracingPipelineConfig:
subobject.RaytracingPipelineConfig.MaxTraceRecursionDepth = subobjectReader.GetRaytracingPipelineConfig_MaxTraceRecursionDepth();
break;
case DXIL::SubobjectKind::HitGroup:
subobject.HitGroup.Intersection = GetWideString(subobjectReader.GetHitGroup_Intersection());
subobject.HitGroup.AnyHit = GetWideString(subobjectReader.GetHitGroup_AnyHit());
subobject.HitGroup.ClosestHit = GetWideString(subobjectReader.GetHitGroup_ClosestHit());
break;
default:
// Ignore contents of unrecognized subobject type (forward-compat)
break;
}
return &subobject;
}
} // namespace anon
DxilRuntimeReflection *hlsl::RDAT::CreateDxilRuntimeReflection() {

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

@ -20,6 +20,7 @@
#include "dxc/DXIL/DxilShaderModel.h"
#include "dxc/DXIL/DxilSignature.h"
#include "dxc/DXIL/DxilFunctionProps.h"
#include "dxc/DXIL/DxilSubobject.h"
#include <memory>
#include <string>
#include <vector>
@ -242,6 +243,11 @@ public:
llvm::DebugInfoFinder &DbgInfoFinder,
llvm::GlobalVariable *NewGV);
DxilSubobjects *GetSubobjects();
const DxilSubobjects *GetSubobjects() const;
DxilSubobjects *ReleaseSubobjects();
void ResetSubobjects(DxilSubobjects *subobjects);
private:
// Signatures.
std::vector<uint8_t> m_SerializedRootSignature;
@ -280,6 +286,7 @@ private:
size_t m_pUnused;
uint32_t m_AutoBindingSpace;
DXIL::DefaultLinkage m_DefaultLinkage;
std::unique_ptr<DxilSubobjects> m_pSubobjects;
// DXIL metadata serialization/deserialization.
llvm::MDTuple *EmitHLResources();

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

@ -15,6 +15,7 @@ add_llvm_library(LLVMDXIL
DxilShaderModel.cpp
DxilSignature.cpp
DxilSignatureElement.cpp
DxilSubobject.cpp
DxilTypeSystem.cpp
DxilUtil.cpp

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

@ -18,6 +18,7 @@
#include "dxc/DXIL/DxilTypeSystem.h"
#include "dxc/DXIL/DxilFunctionProps.h"
#include "dxc/DXIL/DxilShaderFlags.h"
#include "dxc/DXIL/DxilSubobject.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
@ -54,6 +55,7 @@ const char DxilMDHelper::kDxilValidatorVersionMDName[] = "dx.valv
// This named metadata is not valid in final module (should be moved to DxilContainer)
const char DxilMDHelper::kDxilRootSignatureMDName[] = "dx.rootSignature";
const char DxilMDHelper::kDxilViewIdStateMDName[] = "dx.viewIdState";
const char DxilMDHelper::kDxilSubobjectsMDName[] = "dx.subobjects";
const char DxilMDHelper::kDxilSourceContentsMDName[] = "dx.source.contents";
const char DxilMDHelper::kDxilSourceDefinesMDName[] = "dx.source.defines";
@ -1329,6 +1331,160 @@ MDNode *DxilMDHelper::EmitControlFlowHints(llvm::LLVMContext &Ctx, std::vector<D
return hintsNode;
}
void DxilMDHelper::EmitSubobjects(const DxilSubobjects &Subobjects) {
NamedMDNode *pSubobjectsNamedMD = m_pModule->getNamedMetadata(kDxilSubobjectsMDName);
IFTBOOL(pSubobjectsNamedMD == nullptr, DXC_E_INCORRECT_DXIL_METADATA);
pSubobjectsNamedMD = m_pModule->getOrInsertNamedMetadata(kDxilSubobjectsMDName);
const auto &objMap = Subobjects.GetSubobjects();
for (auto &it : objMap)
pSubobjectsNamedMD->addOperand(cast<MDNode>(EmitSubobject(*it.second)));
}
void DxilMDHelper::LoadSubobjects(DxilSubobjects &Subobjects) {
NamedMDNode *pSubobjectsNamedMD = m_pModule->getNamedMetadata(kDxilSubobjectsMDName);
if (!pSubobjectsNamedMD)
return;
for (unsigned i = 0; i < pSubobjectsNamedMD->getNumOperands(); ++i)
LoadSubobject(*pSubobjectsNamedMD->getOperand(i), Subobjects);
}
Metadata *DxilMDHelper::EmitSubobject(const DxilSubobject &obj) {
SmallVector<Metadata *, 6> Args;
Args.emplace_back(MDString::get(m_Ctx, obj.GetName()));
Args.emplace_back(Uint32ToConstMD((unsigned)obj.GetKind()));
bool bLocalRS = false;
IFTBOOL(DXIL::IsValidSubobjectKind(obj.GetKind()), DXC_E_INCORRECT_DXIL_METADATA);
switch (obj.GetKind()) {
case DXIL::SubobjectKind::StateObjectConfig: {
uint32_t Flags;
IFTBOOL(!obj.GetStateObjectConfig(Flags),
DXC_E_INCORRECT_DXIL_METADATA);
Args.emplace_back(Uint32ToConstMD((unsigned)Flags));
break;
}
case DXIL::SubobjectKind::LocalRootSignature:
bLocalRS = true;
case DXIL::SubobjectKind::GlobalRootSignature: {
const void * Data;
uint32_t Size;
IFTBOOL(!obj.GetRootSignature(bLocalRS, Data, Size),
DXC_E_INCORRECT_DXIL_METADATA);
Constant *V = ConstantDataArray::get(m_Ctx,
ArrayRef<uint8_t>((const uint8_t *)Data, Size));
Args.emplace_back(MDNode::get(m_Ctx, { ConstantAsMetadata::get(V) }));
break;
}
case DXIL::SubobjectKind::SubobjectToExportsAssociation: {
StringRef Subobj;
const char * const * Exports;
uint32_t NumExports;
IFTBOOL(!obj.GetSubobjectToExportsAssociation(Subobj, Exports, NumExports),
DXC_E_INCORRECT_DXIL_METADATA);
SmallVector<Metadata *, 4> strArgs;
for (unsigned i = 0; i < NumExports; ++i) {
strArgs.emplace_back(MDString::get(m_Ctx, Exports[i]));
}
Args.emplace_back(MDNode::get(m_Ctx, strArgs));
break;
}
case DXIL::SubobjectKind::RaytracingShaderConfig: {
uint32_t MaxPayloadSizeInBytes;
uint32_t MaxAttributeSizeInBytes;
IFTBOOL(!obj.GetRaytracingShaderConfig(MaxPayloadSizeInBytes,
MaxAttributeSizeInBytes),
DXC_E_INCORRECT_DXIL_METADATA);
Args.emplace_back(Uint32ToConstMD(MaxPayloadSizeInBytes));
Args.emplace_back(Uint32ToConstMD(MaxAttributeSizeInBytes));
break;
}
case DXIL::SubobjectKind::RaytracingPipelineConfig: {
uint32_t MaxTraceRecursionDepth;
IFTBOOL(!obj.GetRaytracingPipelineConfig(MaxTraceRecursionDepth),
DXC_E_INCORRECT_DXIL_METADATA);
Args.emplace_back(Uint32ToConstMD(MaxTraceRecursionDepth));
break;
}
case DXIL::SubobjectKind::HitGroup: {
llvm::StringRef Intersection, AnyHit, ClosestHit;
IFTBOOL(!obj.GetHitGroup(Intersection, AnyHit, ClosestHit),
DXC_E_INCORRECT_DXIL_METADATA);
Args.emplace_back(MDString::get(m_Ctx, Intersection));
Args.emplace_back(MDString::get(m_Ctx, AnyHit));
Args.emplace_back(MDString::get(m_Ctx, ClosestHit));
break;
}
default:
DXASSERT(false, "otherwise, we didn't handle a valid subobject kind");
break;
}
return MDNode::get(m_Ctx, Args);
}
void DxilMDHelper::LoadSubobject(const llvm::MDNode &MD, DxilSubobjects &Subobjects) {
IFTBOOL(MD.getNumOperands() >= 2, DXC_E_INCORRECT_DXIL_METADATA);
unsigned i = 0;
StringRef name(StringMDToStringRef(MD.getOperand(i++)));
DXIL::SubobjectKind kind = (DXIL::SubobjectKind)ConstMDToUint32(MD.getOperand(i++));
IFTBOOL(DXIL::IsValidSubobjectKind(kind), DXC_E_INCORRECT_DXIL_METADATA);
bool bLocalRS = false;
switch (kind) {
case DXIL::SubobjectKind::StateObjectConfig: {
uint32_t Flags = ConstMDToUint32(MD.getOperand(i++));
IFTBOOL(0 == ((~(uint32_t)DXIL::StateObjectFlags::ValidMask) & Flags),
DXC_E_INCORRECT_DXIL_METADATA);
Subobjects.CreateStateObjectConfig(name, Flags);
break;
}
case DXIL::SubobjectKind::LocalRootSignature:
bLocalRS = true;
case DXIL::SubobjectKind::GlobalRootSignature: {
const ConstantAsMetadata *pMetaData = dyn_cast<ConstantAsMetadata>(MD.getOperand(i++));
IFTBOOL(pMetaData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
const ConstantDataArray *pData = dyn_cast<ConstantDataArray>(pMetaData->getValue());
IFTBOOL(pData != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
IFTBOOL(pData->getElementType() == Type::getInt8Ty(m_Ctx), DXC_E_INCORRECT_DXIL_METADATA);
IFTBOOL(pData->getRawDataValues().size() < UINT_MAX &&
(pData->getRawDataValues().size() & 3) == 0, DXC_E_INCORRECT_DXIL_METADATA);
const void *Data = pData->getRawDataValues().begin();
uint32_t Size = pData->getRawDataValues().size();
Subobjects.CreateRootSignature(name, bLocalRS, Data, Size);
break;
}
case DXIL::SubobjectKind::SubobjectToExportsAssociation: {
StringRef Subobj(StringMDToStringRef(MD.getOperand(i++)));
const MDNode *exportMD = dyn_cast<MDNode>(MD.getOperand(i++));
SmallVector<const char *, 4> Exports;
for (unsigned iExport = 0; iExport < exportMD->getNumOperands(); iExport++) {
Exports.push_back(StringMDToStringRef(exportMD->getOperand(iExport)).data());
}
Subobjects.CreateSubobjectToExportsAssociation(name, Subobj, Exports.data(), Exports.size());
break;
}
case DXIL::SubobjectKind::RaytracingShaderConfig: {
uint32_t MaxPayloadSizeInBytes = ConstMDToUint32(MD.getOperand(i++));;
uint32_t MaxAttributeSizeInBytes = ConstMDToUint32(MD.getOperand(i++));;
Subobjects.CreateRaytracingShaderConfig(name, MaxPayloadSizeInBytes, MaxAttributeSizeInBytes);
break;
}
case DXIL::SubobjectKind::RaytracingPipelineConfig: {
uint32_t MaxTraceRecursionDepth = ConstMDToUint32(MD.getOperand(i++));;
Subobjects.CreateRaytracingPipelineConfig(name, MaxTraceRecursionDepth);
break;
}
case DXIL::SubobjectKind::HitGroup: {
StringRef Intersection(StringMDToStringRef(MD.getOperand(i++)));
StringRef AnyHit(StringMDToStringRef(MD.getOperand(i++)));
StringRef ClosestHit(StringMDToStringRef(MD.getOperand(i++)));
Subobjects.CreateHitGroup(name, Intersection, AnyHit, ClosestHit);
break;
}
default:
DXASSERT(false, "otherwise, we didn't handle a valid subobject kind");
break;
}
}
MDTuple *DxilMDHelper::EmitDxilSampler(const DxilSampler &S) {
Metadata *MDVals[kDxilSamplerNumFields];
@ -1828,6 +1984,12 @@ string DxilMDHelper::StringMDToString(const MDOperand &MDO) {
return pMDString->getString();
}
StringRef DxilMDHelper::StringMDToStringRef(const MDOperand &MDO) {
MDString *pMDString = dyn_cast<MDString>(MDO.get());
IFTBOOL(pMDString != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
return pMDString->getString();
}
Value *DxilMDHelper::ValueMDToValue(const MDOperand &MDO) {
IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
ValueAsMetadata *pValAsMD = dyn_cast<ValueAsMetadata>(MDO.get());

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

@ -16,6 +16,7 @@
#include "dxc/DXIL/DxilFunctionProps.h"
#include "dxc/Support/WinAdapter.h"
#include "dxc/DXIL/DxilEntryProps.h"
#include "dxc/DXIL/DxilSubobject.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
@ -97,7 +98,9 @@ DxilModule::DxilModule(Module *pModule)
, m_bDisableOptimizations(false)
, m_bUseMinPrecision(true) // use min precision by default
, m_bAllResourcesBound(false)
, m_AutoBindingSpace(UINT_MAX) {
, m_AutoBindingSpace(UINT_MAX)
, m_pSubobjects(nullptr)
{
DXASSERT_NOMSG(m_pModule != nullptr);
@ -1041,6 +1044,26 @@ void DxilModule::StripRootSignatureFromMetadata() {
}
}
DxilSubobjects *DxilModule::GetSubobjects() {
return m_pSubobjects.get();
}
const DxilSubobjects *DxilModule::GetSubobjects() const {
return m_pSubobjects.get();
}
DxilSubobjects *DxilModule::ReleaseSubobjects() {
return m_pSubobjects.release();
}
void DxilModule::ResetSubobjects(DxilSubobjects *subobjects) {
m_pSubobjects.reset(subobjects);
}
void DxilModule::StripSubobjectsFromMetadata() {
NamedMDNode *pSubobjectsNamedMD = GetModule()->getNamedMetadata(DxilMDHelper::kDxilSubobjectsMDName);
if (pSubobjectsNamedMD) {
GetModule()->eraseNamedMetadata(pSubobjectsNamedMD);
}
}
void DxilModule::UpdateValidatorVersionMetadata() {
m_pMDHelper->EmitValidatorVersion(m_ValMajor, m_ValMinor);
}
@ -1145,6 +1168,7 @@ void DxilModule::ClearDxilMetadata(Module &M) {
name == DxilMDHelper::kDxilResourcesMDName ||
name == DxilMDHelper::kDxilTypeSystemMDName ||
name == DxilMDHelper::kDxilViewIdStateMDName ||
name == DxilMDHelper::kDxilSubobjectsMDName ||
name.startswith(DxilMDHelper::kDxilTypeSystemHelperVariablePrefix)) {
nodes.push_back(&b);
}
@ -1215,6 +1239,11 @@ void DxilModule::EmitDxilMetadata() {
Entries.emplace_back(pSubEntry);
}
funcOrder.clear();
// Save Subobjects
if (GetSubobjects()) {
m_pMDHelper->EmitSubobjects(*GetSubobjects());
}
}
m_pMDHelper->EmitDxilEntryPoints(Entries);
@ -1301,6 +1330,13 @@ void DxilModule::LoadDxilMetadata() {
m_DxilEntryPropsMap[pFunc] = std::move(pEntryProps);
}
// Load Subobjects
std::unique_ptr<DxilSubobjects> pSubobjects(new DxilSubobjects());
m_pMDHelper->LoadSubobjects(*pSubobjects);
if (pSubobjects->GetSubobjects().size()) {
ResetSubobjects(pSubobjects.release());
}
} else {
std::unique_ptr<DxilEntryProps> pEntryProps =
llvm::make_unique<DxilEntryProps>(entryFuncProps, m_bUseMinPrecision);

312
lib/DXIL/DxilSubobject.cpp Normal file
Просмотреть файл

@ -0,0 +1,312 @@
///////////////////////////////////////////////////////////////////////////////
// //
// DxilSubobject.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. //
// //
///////////////////////////////////////////////////////////////////////////////
#include "dxc/Support/Global.h"
#include "dxc/DXIL/DxilSubobject.h"
#include "llvm/ADT/STLExtras.h"
namespace hlsl {
//------------------------------------------------------------------------------
//
// Subobject methods.
//
DxilSubobject::DxilSubobject(DxilSubobject &&other)
: m_Owner(other.m_Owner),
m_Kind(other.m_Kind),
m_Name(m_Owner.GetSubobjectString(other.m_Name)),
m_Exports(std::move(other.m_Exports))
{
DXASSERT_NOMSG(DXIL::IsValidSubobjectKind(m_Kind));
CopyUnionedContents(other);
}
DxilSubobject::DxilSubobject(DxilSubobjects &owner, Kind kind, llvm::StringRef name)
: m_Owner(owner),
m_Kind(kind),
m_Name(m_Owner.GetSubobjectString(name)),
m_Exports()
{
DXASSERT_NOMSG(DXIL::IsValidSubobjectKind(m_Kind));
}
DxilSubobject::DxilSubobject(DxilSubobjects &owner, const DxilSubobject &other, llvm::StringRef name)
: m_Owner(owner),
m_Kind(other.m_Kind),
m_Name(name),
m_Exports(other.m_Exports.begin(), other.m_Exports.end())
{
DXASSERT_NOMSG(DXIL::IsValidSubobjectKind(m_Kind));
CopyUnionedContents(other);
if (&m_Owner != &other.m_Owner)
InternStrings();
}
void DxilSubobject::CopyUnionedContents(const DxilSubobject &other) {
switch (m_Kind) {
case Kind::StateObjectConfig:
StateObjectConfig.Flags = other.StateObjectConfig.Flags;
break;
case Kind::GlobalRootSignature:
case Kind::LocalRootSignature:
RootSignature.Size = other.RootSignature.Size;
RootSignature.Data = other.RootSignature.Data;
break;
case Kind::SubobjectToExportsAssociation:
SubobjectToExportsAssociation.Subobject = other.SubobjectToExportsAssociation.Subobject;
break;
case Kind::RaytracingShaderConfig:
RaytracingShaderConfig.MaxPayloadSizeInBytes = other.RaytracingShaderConfig.MaxPayloadSizeInBytes;
RaytracingShaderConfig.MaxAttributeSizeInBytes = other.RaytracingShaderConfig.MaxAttributeSizeInBytes;
break;
case Kind::RaytracingPipelineConfig:
RaytracingPipelineConfig.MaxTraceRecursionDepth = other.RaytracingPipelineConfig.MaxTraceRecursionDepth;
break;
case Kind::HitGroup:
HitGroup.Intersection = other.HitGroup.Intersection;
HitGroup.AnyHit = other.HitGroup.AnyHit;
HitGroup.ClosestHit = other.HitGroup.ClosestHit;
break;
}
}
void DxilSubobject::InternStrings() {
// Transfer strings if necessary
m_Name = m_Owner.GetSubobjectString(m_Name).data();
switch (m_Kind) {
case Kind::SubobjectToExportsAssociation:
SubobjectToExportsAssociation.Subobject = m_Owner.GetSubobjectString(SubobjectToExportsAssociation.Subobject).data();
for (auto &ptr : m_Exports)
ptr = m_Owner.GetSubobjectString(ptr).data();
break;
case Kind::HitGroup:
HitGroup.Intersection = m_Owner.GetSubobjectString(HitGroup.Intersection).data();
HitGroup.AnyHit = m_Owner.GetSubobjectString(HitGroup.AnyHit).data();
HitGroup.ClosestHit = m_Owner.GetSubobjectString(HitGroup.ClosestHit).data();
break;
default:
break;
}
}
DxilSubobject::~DxilSubobject() {
}
// StateObjectConfig
bool DxilSubobject::GetStateObjectConfig(uint32_t &Flags) const {
if (m_Kind == Kind::StateObjectConfig) {
Flags = StateObjectConfig.Flags;
return true;
}
return false;
}
// Local/Global RootSignature
bool DxilSubobject::GetRootSignature(
bool local, const void * &Data, uint32_t &Size) const {
Kind expected = local ? Kind::LocalRootSignature : Kind::GlobalRootSignature;
if (m_Kind == expected) {
Data = RootSignature.Data;
Size = RootSignature.Size;
return true;
}
return false;
}
// SubobjectToExportsAssociation
bool DxilSubobject::GetSubobjectToExportsAssociation(
llvm::StringRef &Subobject,
const char * const * &Exports,
uint32_t &NumExports) const {
if (m_Kind == Kind::SubobjectToExportsAssociation) {
Subobject = SubobjectToExportsAssociation.Subobject;
Exports = m_Exports.data();
NumExports = (uint32_t)m_Exports.size();
return true;
}
return false;
}
// RaytracingShaderConfig
bool DxilSubobject::GetRaytracingShaderConfig(uint32_t &MaxPayloadSizeInBytes,
uint32_t &MaxAttributeSizeInBytes) const {
if (m_Kind == Kind::RaytracingShaderConfig) {
MaxPayloadSizeInBytes = RaytracingShaderConfig.MaxPayloadSizeInBytes;
MaxAttributeSizeInBytes = RaytracingShaderConfig.MaxAttributeSizeInBytes;
return true;
}
return false;
}
// RaytracingPipelineConfig
bool DxilSubobject::GetRaytracingPipelineConfig(
uint32_t &MaxTraceRecursionDepth) const {
if (m_Kind == Kind::RaytracingPipelineConfig) {
MaxTraceRecursionDepth = RaytracingPipelineConfig.MaxTraceRecursionDepth;
return true;
}
return false;
}
// HitGroup
bool DxilSubobject::GetHitGroup(llvm::StringRef &Intersection,
llvm::StringRef &AnyHit,
llvm::StringRef &ClosestHit) const {
if (m_Kind == Kind::HitGroup) {
Intersection = HitGroup.Intersection;
AnyHit = HitGroup.AnyHit;
ClosestHit = HitGroup.ClosestHit;
return true;
}
return false;
}
DxilSubobjects::DxilSubobjects()
: m_StringStorage()
, m_RawBytesStorage()
, m_Subobjects()
{}
DxilSubobjects::DxilSubobjects(DxilSubobjects &&other)
: m_StringStorage(std::move(other.m_StringStorage))
, m_RawBytesStorage(std::move(other.m_RawBytesStorage))
, m_Subobjects(std::move(other.m_Subobjects))
{}
DxilSubobjects::~DxilSubobjects() {}
StringRef DxilSubobjects::GetSubobjectString(StringRef value) {
auto it = m_StringStorage.find(value);
if (it != m_StringStorage.end())
return it->first;
std::string stored(value.begin(), value.size());
const char *ptr = stored.c_str();
m_StringStorage[ptr] = std::move(stored);
return ptr;
}
const void *DxilSubobjects::GetRawBytes(const void *ptr, size_t size) {
auto it = m_RawBytesStorage.find(ptr);
if (it != m_RawBytesStorage.end())
return ptr;
DXASSERT_NOMSG(size < UINT_MAX);
if (size >= UINT_MAX)
return nullptr;
std::vector<char> stored;
stored.reserve(size);
stored.assign((const char*)ptr, (const char*)ptr + size);
ptr = stored.data();
m_RawBytesStorage[ptr] = std::move(stored);
return ptr;
}
DxilSubobject *DxilSubobjects::FindSubobject(StringRef name) {
auto it = m_Subobjects.find(name);
if (it != m_Subobjects.end())
return it->second.get();
return nullptr;
}
void DxilSubobjects::RemoveSubobject(StringRef name) {
auto it = m_Subobjects.find(name);
if (it != m_Subobjects.end())
m_Subobjects.erase(it);
}
DxilSubobject &DxilSubobjects::CloneSubobject(
const DxilSubobject &Subobject, llvm::StringRef Name) {
Name = GetSubobjectString(Name);
DXASSERT(FindSubobject(Name) == nullptr,
"otherwise, name collision between subobjects");
std::unique_ptr<DxilSubobject> ptr(new DxilSubobject(*this, Subobject, Name));
DxilSubobject &ref = *ptr;
m_Subobjects[Name] = std::move(ptr);
return ref;
}
// Create DxilSubobjects
DxilSubobject &DxilSubobjects::CreateStateObjectConfig(
llvm::StringRef Name, uint32_t Flags) {
DXASSERT_NOMSG(0 == ((~(uint32_t)DXIL::StateObjectFlags::ValidMask) & Flags));
auto &obj = CreateSubobject(Kind::StateObjectConfig, Name);
obj.StateObjectConfig.Flags = Flags;
return obj;
}
DxilSubobject &DxilSubobjects::CreateRootSignature(
llvm::StringRef Name, bool local, const void *Data, uint32_t Size) {
auto &obj = CreateSubobject(local ? Kind::LocalRootSignature : Kind::GlobalRootSignature, Name);
obj.RootSignature.Data = Data;
obj.RootSignature.Size = Size;
return obj;
}
DxilSubobject &DxilSubobjects::CreateSubobjectToExportsAssociation(
llvm::StringRef Name,
llvm::StringRef Subobject,
const char * const *Exports,
uint32_t NumExports) {
auto &obj = CreateSubobject(Kind::SubobjectToExportsAssociation, Name);
Subobject = GetSubobjectString(Subobject);
obj.SubobjectToExportsAssociation.Subobject = Subobject.data();
obj.m_Exports.assign(Exports, Exports + NumExports);
return obj;
}
DxilSubobject &DxilSubobjects::CreateRaytracingShaderConfig(
llvm::StringRef Name,
uint32_t MaxPayloadSizeInBytes,
uint32_t MaxAttributeSizeInBytes) {
auto &obj = CreateSubobject(Kind::RaytracingShaderConfig, Name);
obj.RaytracingShaderConfig.MaxPayloadSizeInBytes = MaxPayloadSizeInBytes;
obj.RaytracingShaderConfig.MaxAttributeSizeInBytes = MaxAttributeSizeInBytes;
return obj;
}
DxilSubobject &DxilSubobjects::CreateRaytracingPipelineConfig(
llvm::StringRef Name,
uint32_t MaxTraceRecursionDepth) {
auto &obj = CreateSubobject(Kind::RaytracingPipelineConfig, Name);
obj.RaytracingPipelineConfig.MaxTraceRecursionDepth = MaxTraceRecursionDepth;
return obj;
}
DxilSubobject &DxilSubobjects::CreateHitGroup(llvm::StringRef Name,
llvm::StringRef Intersection,
llvm::StringRef AnyHit,
llvm::StringRef ClosestHit) {
auto &obj = CreateSubobject(Kind::HitGroup, Name);
Intersection = GetSubobjectString(Intersection);
AnyHit = GetSubobjectString(AnyHit);
ClosestHit = GetSubobjectString(ClosestHit);
obj.HitGroup.Intersection = Intersection.data();
obj.HitGroup.AnyHit = AnyHit.data();
obj.HitGroup.ClosestHit = ClosestHit.data();
return obj;
}
DxilSubobject &DxilSubobjects::CreateSubobject(Kind kind, llvm::StringRef Name) {
Name = GetSubobjectString(Name);
DXASSERT(FindSubobject(Name) == nullptr,
"otherwise, name collision between subobjects");
std::unique_ptr<DxilSubobject> ptr(new DxilSubobject(*this, kind, Name));
DxilSubobject &ref = *ptr;
m_Subobjects[Name] = std::move(ptr);
return ref;
}
} // namespace hlsl

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

@ -938,6 +938,35 @@ public:
}
};
class RawBytesPart : public RDATPart {
private:
std::unordered_map<const void *, uint32_t> m_PtrMap;
std::vector<char> m_DataBuffer;
public:
RawBytesPart() : m_DataBuffer() {}
uint32_t Insert(const void *pData, size_t dataSize) {
auto it = m_PtrMap.find(pData);
if (it != m_PtrMap.end())
return it->second;
if (dataSize + m_DataBuffer.size() > UINT_MAX)
return UINT_MAX;
uint32_t offset = (uint32_t)m_DataBuffer.size();
m_DataBuffer.reserve(m_DataBuffer.size() + dataSize);
m_DataBuffer.insert(m_DataBuffer.end(),
(const char*)pData, (const char*)pData + dataSize);
return offset;
}
RuntimeDataPartType GetType() const { return RuntimeDataPartType::RawBytes; }
uint32_t GetPartSize() const { return m_DataBuffer.size(); }
void Write(void *ptr) { memcpy(ptr, m_DataBuffer.data(), m_DataBuffer.size()); }
};
class SubobjectTable : public RDATTable<RuntimeDataSobobjectInfo> {
public:
RuntimeDataPartType GetType() const { return RuntimeDataPartType::SubobjectTable; }
};
using namespace DXIL;
class DxilRDATWriter : public DxilPartWriter {
@ -1016,10 +1045,8 @@ private:
void InsertToResourceTable(DxilResourceBase &resource,
ResourceClass resourceClass,
ResourceTable &resourceTable,
StringBufferPart &stringBufferPart,
uint32_t &resourceIndex) {
uint32_t stringIndex = stringBufferPart.Insert(resource.GetGlobalName());
uint32_t stringIndex = m_pStringBufferPart->Insert(resource.GetGlobalName());
UpdateFunctionToResourceInfo(&resource, resourceIndex++);
RuntimeDataResourceInfo info = {};
info.ID = resource.GetID();
@ -1040,38 +1067,32 @@ private:
info.Flags |= static_cast<uint32_t>(DxilResourceFlag::UAVRasterizerOrderedView);
// TODO: add dynamic index flag
}
resourceTable.Insert(info);
m_pResourceTable->Insert(info);
}
void UpdateResourceInfo(StringBufferPart &stringBufferPart) {
void UpdateResourceInfo() {
// Try to allocate string table for resources. String table is a sequence
// of strings delimited by \0
m_Parts.emplace_back(llvm::make_unique<ResourceTable>());
ResourceTable &resourceTable = *reinterpret_cast<ResourceTable*>(m_Parts.back().get());
uint32_t resourceIndex = 0;
for (auto &resource : m_Module.GetCBuffers()) {
InsertToResourceTable(*resource.get(), ResourceClass::CBuffer, resourceTable, stringBufferPart,
resourceIndex);
InsertToResourceTable(*resource.get(), ResourceClass::CBuffer, resourceIndex);
}
for (auto &resource : m_Module.GetSamplers()) {
InsertToResourceTable(*resource.get(), ResourceClass::Sampler, resourceTable, stringBufferPart,
resourceIndex);
InsertToResourceTable(*resource.get(), ResourceClass::Sampler, resourceIndex);
}
for (auto &resource : m_Module.GetSRVs()) {
InsertToResourceTable(*resource.get(), ResourceClass::SRV, resourceTable, stringBufferPart,
resourceIndex);
InsertToResourceTable(*resource.get(), ResourceClass::SRV, resourceIndex);
}
for (auto &resource : m_Module.GetUAVs()) {
InsertToResourceTable(*resource.get(), ResourceClass::UAV, resourceTable, stringBufferPart,
resourceIndex);
InsertToResourceTable(*resource.get(), ResourceClass::UAV, resourceIndex);
}
}
void UpdateFunctionDependency(llvm::Function *F, StringBufferPart &stringBufferPart) {
void UpdateFunctionDependency(llvm::Function *F) {
for (const auto &user : F->users()) {
const llvm::Function *userFunction = FindUsingFunction(user);
uint32_t index = stringBufferPart.Insert(F->getName());
uint32_t index = m_pStringBufferPart->Insert(F->getName());
if (m_FuncToDependencies.find(userFunction) ==
m_FuncToDependencies.end()) {
m_FuncToDependencies[userFunction] =
@ -1081,11 +1102,7 @@ private:
}
}
void UpdateFunctionInfo(StringBufferPart &stringBufferPart) {
m_Parts.emplace_back(llvm::make_unique<FunctionTable>());
FunctionTable &functionTable = *reinterpret_cast<FunctionTable*>(m_Parts.back().get());
m_Parts.emplace_back(llvm::make_unique<IndexArraysPart>());
IndexArraysPart &indexArraysPart = *reinterpret_cast<IndexArraysPart*>(m_Parts.back().get());
void UpdateFunctionInfo() {
for (auto &function : m_Module.GetModule()->getFunctionList()) {
if (function.isDeclaration() && !function.isIntrinsic()) {
if (OP::IsDxilOpFunc(&function)) {
@ -1093,7 +1110,7 @@ private:
UpdateFunctionToShaderCompat(&function);
} else {
// collect unresolved dependencies per function
UpdateFunctionDependency(&function, stringBufferPart);
UpdateFunctionDependency(&function);
}
}
}
@ -1101,8 +1118,8 @@ private:
if (!function.isDeclaration()) {
StringRef mangled = function.getName();
StringRef unmangled = hlsl::dxilutil::DemangleFunctionName(function.getName());
uint32_t mangledIndex = stringBufferPart.Insert(mangled);
uint32_t unmangledIndex = stringBufferPart.Insert(unmangled);
uint32_t mangledIndex = m_pStringBufferPart->Insert(mangled);
uint32_t unmangledIndex = m_pStringBufferPart->Insert(unmangled);
// Update resource Index
uint32_t resourceIndex = UINT_MAX;
uint32_t functionDependencies = UINT_MAX;
@ -1112,11 +1129,11 @@ private:
if (m_FuncToResNameOffset.find(&function) != m_FuncToResNameOffset.end())
resourceIndex =
indexArraysPart.AddIndex(m_FuncToResNameOffset[&function].begin(),
m_pIndexArraysPart->AddIndex(m_FuncToResNameOffset[&function].begin(),
m_FuncToResNameOffset[&function].end());
if (m_FuncToDependencies.find(&function) != m_FuncToDependencies.end())
functionDependencies =
indexArraysPart.AddIndex(m_FuncToDependencies[&function].begin(),
m_pIndexArraysPart->AddIndex(m_FuncToDependencies[&function].begin(),
m_FuncToDependencies[&function].end());
if (m_Module.HasDxilFunctionProps(&function)) {
auto props = m_Module.GetDxilFunctionProps(&function);
@ -1171,19 +1188,99 @@ private:
info.ShaderStageFlag &= compatInfo.mask;
}
info.MinShaderTarget = EncodeVersion((DXIL::ShaderKind)shaderKind, minMajor, minMinor);
functionTable.Insert(info);
m_pFunctionTable->Insert(info);
}
}
}
void UpdateSubobjectInfo() {
if (!m_Module.GetSubobjects())
return;
for (auto &it : m_Module.GetSubobjects()->GetSubobjects()) {
auto &obj = *it.second;
RuntimeDataSobobjectInfo info = {};
info.Name = m_pStringBufferPart->Insert(obj.GetName());
info.Kind = (uint32_t)obj.GetKind();
bool bLocalRS = false;
switch (obj.GetKind()) {
case DXIL::SubobjectKind::StateObjectConfig:
obj.GetStateObjectConfig(info.StateObjectConfig.Flags);
break;
case DXIL::SubobjectKind::LocalRootSignature:
bLocalRS = true;
case DXIL::SubobjectKind::GlobalRootSignature: {
const void *Data;
obj.GetRootSignature(bLocalRS, Data, info.RootSignature.SizeInBytes);
info.RootSignature.RawBytesOffset =
m_pRawBytesPart->Insert(Data, info.RootSignature.SizeInBytes);
break;
}
case DXIL::SubobjectKind::SubobjectToExportsAssociation: {
llvm::StringRef Subobject;
const char * const * Exports;
uint32_t NumExports;
std::vector<uint32_t> ExportIndices;
obj.GetSubobjectToExportsAssociation(Subobject, Exports, NumExports);
info.SubobjectToExportsAssociation.Sobobject =
m_pStringBufferPart->Insert(Subobject);
ExportIndices.resize(NumExports);
for (unsigned i = 0; i < NumExports; ++i) {
ExportIndices[i] = m_pStringBufferPart->Insert(Exports[i]);
}
m_pIndexArraysPart->AddIndex(
ExportIndices.begin(), ExportIndices.end());
break;
}
case DXIL::SubobjectKind::RaytracingShaderConfig:
obj.GetRaytracingShaderConfig(
info.RaytracingShaderConfig.MaxPayloadSizeInBytes,
info.RaytracingShaderConfig.MaxAttributeSizeInBytes);
break;
case DXIL::SubobjectKind::RaytracingPipelineConfig:
obj.GetRaytracingPipelineConfig(
info.RaytracingPipelineConfig.MaxTraceRecursionDepth);
break;
case DXIL::SubobjectKind::HitGroup:
StringRef Intersection;
StringRef AnyHit;
StringRef ClosestHit;
obj.GetHitGroup(Intersection, AnyHit, ClosestHit);
info.HitGroup.Intersection = m_pStringBufferPart->Insert(Intersection);
info.HitGroup.AnyHit = m_pStringBufferPart->Insert(AnyHit);
info.HitGroup.ClosestHit = m_pStringBufferPart->Insert(ClosestHit);
break;
}
m_pSubobjectTable->Insert(info);
}
}
void CreateParts() {
#define ADD_PART(type) \
m_Parts.emplace_back(llvm::make_unique<type>()); \
m_p##type = reinterpret_cast<type*>(m_Parts.back().get());
ADD_PART(StringBufferPart);
ADD_PART(IndexArraysPart);
ADD_PART(RawBytesPart);
ADD_PART(FunctionTable);
ADD_PART(ResourceTable);
ADD_PART(SubobjectTable);
#undef ADD_PART
}
StringBufferPart *m_pStringBufferPart;
IndexArraysPart *m_pIndexArraysPart;
RawBytesPart *m_pRawBytesPart;
FunctionTable *m_pFunctionTable;
ResourceTable *m_pResourceTable;
SubobjectTable *m_pSubobjectTable;
public:
DxilRDATWriter(const DxilModule &module, uint32_t InfoVersion = 0)
: m_Module(module), m_RDATBuffer(), m_Parts(), m_FuncToResNameOffset() {
// It's important to keep the order of this update
m_Parts.emplace_back(llvm::make_unique<StringBufferPart>());
StringBufferPart &stringBufferPart = *reinterpret_cast<StringBufferPart*>(m_Parts.back().get());
UpdateResourceInfo(stringBufferPart);
UpdateFunctionInfo(stringBufferPart);
CreateParts();
UpdateResourceInfo();
UpdateFunctionInfo();
UpdateSubobjectInfo();
// Delete any empty parts:
std::vector<std::unique_ptr<RDATPart>>::iterator it = m_Parts.begin();
@ -1211,7 +1308,7 @@ public:
CheckedWriter W(m_RDATBuffer.data(), m_RDATBuffer.size());
// write RDAT header
RuntimeDataHeader &header = W.Map<RuntimeDataHeader>();
header.Version = RDAT_Version_0;
header.Version = RDAT_Version_10;
header.PartCount = m_Parts.size();
// map offsets
uint32_t *offsets = W.MapArray<uint32_t>(header.PartCount);
@ -1421,17 +1518,19 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
});
}
}
// Write the DxilPipelineStateValidation (PSV0) part.
std::unique_ptr<DxilRDATWriter> pRDATWriter = nullptr;
std::unique_ptr<DxilPSVWriter> pPSVWriter = nullptr;
unsigned int major, minor;
pModule->GetDxilVersion(major, minor);
if (pModule->GetShaderModel()->IsLib()) {
// Write the DxilRuntimeData (RDAT) part.
pRDATWriter = llvm::make_unique<DxilRDATWriter>(*pModule);
writer.AddPart(
DFCC_RuntimeData, pRDATWriter->size(),
[&](AbstractMemoryStream *pStream) { pRDATWriter->write(pStream); });
} else if (!pModule->GetShaderModel()->IsLib()) {
pModule->StripSubobjectsFromMetadata();
} else {
// Write the DxilPipelineStateValidation (PSV0) part.
pPSVWriter = llvm::make_unique<DxilPSVWriter>(*pModule);
writer.AddPart(
DFCC_PipelineStateValidation, pPSVWriter->size(),

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

@ -186,6 +186,9 @@ void InitDxilModuleFromHLModule(HLModule &H, DxilModule &M, bool HasDebugInfo) {
// Signatures.
M.ResetSerializedRootSignature(H.GetSerializedRootSignature());
// Subobjects.
M.ResetSubobjects(H.ReleaseSubobjects());
// Shader properties.
//bool m_bDisableOptimizations;
M.SetDisableOptimization(H.GetHLOptions().bDisableOptimizations);

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

@ -50,7 +50,12 @@ HLModule::HLModule(Module *pModule)
, m_pSM(nullptr)
, m_DxilMajor(DXIL::kDxilMajor)
, m_DxilMinor(DXIL::kDxilMinor)
, m_ValMajor(0)
, m_ValMinor(0)
, m_Float32DenormMode(DXIL::Float32DenormMode::Any)
, m_pOP(llvm::make_unique<OP>(pModule->getContext(), pModule))
, m_AutoBindingSpace(UINT_MAX)
, m_DefaultLinkage(DXIL::DefaultLinkage::Default)
, m_pTypeSystem(llvm::make_unique<DxilTypeSystem>(pModule)) {
DXASSERT_NOMSG(m_pModule != nullptr);
@ -479,6 +484,11 @@ void HLModule::EmitHLMetadata() {
if (!m_SerializedRootSignature.empty()) {
m_pMDHelper->EmitRootSignature(m_SerializedRootSignature);
}
// Save Subobjects
if (GetSubobjects()) {
m_pMDHelper->EmitSubobjects(*GetSubobjects());
}
}
void HLModule::LoadHLMetadata() {
@ -533,6 +543,13 @@ void HLModule::LoadHLMetadata() {
}
m_pMDHelper->LoadRootSignature(m_SerializedRootSignature);
// Load Subobjects
std::unique_ptr<DxilSubobjects> pSubobjects(new DxilSubobjects());
m_pMDHelper->LoadSubobjects(*pSubobjects);
if (pSubobjects->GetSubobjects().size()) {
ResetSubobjects(pSubobjects.release());
}
}
void HLModule::ClearHLMetadata(llvm::Module &M) {
@ -1235,6 +1252,24 @@ DebugInfoFinder &HLModule::GetOrCreateDebugInfoFinder() {
}
return *m_pDebugInfoFinder;
}
//------------------------------------------------------------------------------
//
// Subobject methods.
//
DxilSubobjects *HLModule::GetSubobjects() {
return m_pSubobjects.get();
}
const DxilSubobjects *HLModule::GetSubobjects() const {
return m_pSubobjects.get();
}
DxilSubobjects *HLModule::ReleaseSubobjects() {
return m_pSubobjects.release();
}
void HLModule::ResetSubobjects(DxilSubobjects *subobjects) {
m_pSubobjects.reset(subobjects);
}
//------------------------------------------------------------------------------
//
// Signature methods.

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

@ -26,6 +26,7 @@
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Format.h"
#include "dxc/HLSL/DxilPipelineStateValidation.h"
#include "dxc/HLSL/DxilRuntimeReflection.h"
#include "dxc/HLSL/ComputeViewIdState.h"
#include "dxc/DxilContainer/DxilContainer.h"
#include "dxc/DXIL/DxilUtil.h"
@ -575,6 +576,143 @@ void PrintViewIdState(DxilModule &M, raw_string_ostream &OS,
OS << comment << "\n";
}
static const char *SubobjectKindToString(DXIL::SubobjectKind kind) {
switch (kind) {
case DXIL::SubobjectKind::StateObjectConfig: return "StateObjectConfig";
case DXIL::SubobjectKind::GlobalRootSignature: return "GlobalRootSignature";
case DXIL::SubobjectKind::LocalRootSignature: return "LocalRootSignature";
case DXIL::SubobjectKind::SubobjectToExportsAssociation: return "SubobjectToExportsAssociation";
case DXIL::SubobjectKind::RaytracingShaderConfig: return "RaytracingShaderConfig";
case DXIL::SubobjectKind::RaytracingPipelineConfig: return "RaytracingPipelineConfig";
case DXIL::SubobjectKind::HitGroup: return "HitGroup";
}
return "<invalid kind>";
}
static const char *FlagToString(DXIL::StateObjectFlags Flag) {
switch (Flag) {
case DXIL::StateObjectFlags::AllowLocalDependenciesOnExternalDefinitions:
return "AllowLocalDependenciesOnExternalDefinitions";
case DXIL::StateObjectFlags::AllowExternalDependenciesOnLocalDefinitions:
return "AllowExternalDependenciesOnLocalDefinitions";
}
return "<invalid StateObjectFlag>";
}
template <typename _T>
void PrintFlags(raw_string_ostream &OS, uint32_t Flags) {
if (!Flags) {
OS << "0";
return;
}
uint32_t flag = 0;
while (Flags) {
if (flag)
OS << " | ";
flag = (Flags & ~(Flags - 1));
Flags ^= flag;
OS << FlagToString((_T)flag);
}
}
void PrintSubobjects(const DxilSubobjects &subobjects,
raw_string_ostream &OS,
StringRef comment) {
if (subobjects.GetSubobjects().empty())
return;
OS << comment << "\n";
OS << comment << " Subobjects:\n";
OS << comment << "\n";
for (auto &it : subobjects.GetSubobjects()) {
StringRef name = it.first;
if (!it.second) {
OS << comment << " " << name << " = <null>" << "\n";
continue;
}
const DxilSubobject &obj = *it.second.get();
OS << comment << " " << SubobjectKindToString(obj.GetKind()) << " " << name << " = " << "{ ";
bool bLocalRS = false;
switch (obj.GetKind()) {
case DXIL::SubobjectKind::StateObjectConfig: {
uint32_t Flags = 0;
if (!obj.GetStateObjectConfig(Flags)) {
OS << "<error getting subobject>";
break;
}
PrintFlags<DXIL::StateObjectFlags>(OS, Flags);
break;
}
case DXIL::SubobjectKind::LocalRootSignature:
bLocalRS = true;
case DXIL::SubobjectKind::GlobalRootSignature: {
const void *Data = nullptr;
uint32_t Size = 0;
if (!obj.GetRootSignature(bLocalRS, Data, Size)) {
OS << "<error getting subobject>";
break;
}
// TODO: Deserialize root signature?
OS << "<" << Size << " bytes>";
break;
}
case DXIL::SubobjectKind::SubobjectToExportsAssociation: {
llvm::StringRef Subobject;
const char * const * Exports = nullptr;
uint32_t NumExports;
if (!obj.GetSubobjectToExportsAssociation(Subobject, Exports, NumExports)) {
OS << "<error getting subobject>";
break;
}
OS << "\"" << Subobject << "\", { ";
if (Exports) {
for (unsigned i = 0; i < NumExports; ++i) {
OS << "\"" << Exports[i] << "\"" << (i ? ", " : "");
}
}
OS << " } ";
break;
}
case DXIL::SubobjectKind::RaytracingShaderConfig: {
uint32_t MaxPayloadSizeInBytes;
uint32_t MaxAttributeSizeInBytes;
if (!obj.GetRaytracingShaderConfig(MaxPayloadSizeInBytes,
MaxAttributeSizeInBytes)) {
OS << "<error getting subobject>";
break;
}
OS << "MaxPayloadSizeInBytes = " << MaxPayloadSizeInBytes
<< "MaxAttributeSizeInBytes = " << MaxAttributeSizeInBytes;
break;
}
case DXIL::SubobjectKind::RaytracingPipelineConfig: {
uint32_t MaxTraceRecursionDepth;
if (!obj.GetRaytracingPipelineConfig(MaxTraceRecursionDepth)) {
OS << "<error getting subobject>";
break;
}
OS << "MaxTraceRecursionDepth = " << MaxTraceRecursionDepth;
break;
}
case DXIL::SubobjectKind::HitGroup: {
StringRef Intersection;
StringRef AnyHit;
StringRef ClosestHit;
if (!obj.GetHitGroup(Intersection, AnyHit, ClosestHit)) {
OS << "<error getting subobject>";
break;
}
OS << "intersection = \"" << Intersection
<< "\", anyhit = \"" << AnyHit
<< "\", closesthit = \"" << ClosestHit << "\"";
break;
}
}
OS << " };\n";
}
}
void PrintStructLayout(StructType *ST, DxilTypeSystem &typeSys,
raw_string_ostream &OS, StringRef comment,
StringRef varName, unsigned offset,
@ -1289,6 +1427,61 @@ void PrintPipelineStateValidationRuntimeInfo(const char *pBuffer,
namespace dxcutil {
// TODO: Move DeserializeSubobjectsFromRuntimeData to more appropriate place
void DeserializeSubobjectsFromRuntimeData(DxilSubobjects &subobjects, RDAT::DxilRuntimeData &runtimeData) {
RDAT::SubobjectTableReader *pSubobjectTableReader = runtimeData.GetSubobjectTableReader();
if (!pSubobjectTableReader)
return;
for (unsigned i = 0; i < pSubobjectTableReader->GetCount(); ++i) {
auto reader = pSubobjectTableReader->GetItem(i);
DXIL::SubobjectKind kind = reader.GetKind();
bool bLocalRS = false;
switch (kind) {
case DXIL::SubobjectKind::StateObjectConfig:
subobjects.CreateStateObjectConfig(reader.GetName(),
reader.GetStateObjectConfig_Flags());
break;
case DXIL::SubobjectKind::LocalRootSignature:
bLocalRS = true;
case DXIL::SubobjectKind::GlobalRootSignature: {
const void *pOutBytes;
uint32_t OutSizeInBytes;
reader.GetRootSignature(&pOutBytes, &OutSizeInBytes);
subobjects.CreateRootSignature(reader.GetName(), bLocalRS, pOutBytes, OutSizeInBytes);
break;
}
case DXIL::SubobjectKind::SubobjectToExportsAssociation: {
uint32_t NumExports = reader.GetSubobjectToExportsAssociation_NumExports();
std::vector<const char*> Exports;
Exports.resize(NumExports);
for (unsigned i = 0; i < NumExports; ++i) {
Exports[i] = reader.GetSubobjectToExportsAssociation_Export(i);
}
subobjects.CreateSubobjectToExportsAssociation(reader.GetName(),
reader.GetSubobjectToExportsAssociation_Subobject(),
Exports.data(), NumExports);
break;
}
case DXIL::SubobjectKind::RaytracingShaderConfig:
subobjects.CreateRaytracingShaderConfig(reader.GetName(),
reader.GetRaytracingShaderConfig_MaxPayloadSizeInBytes(),
reader.GetRaytracingShaderConfig_MaxAttributeSizeInBytes());
break;
case DXIL::SubobjectKind::RaytracingPipelineConfig:
subobjects.CreateRaytracingPipelineConfig(reader.GetName(),
reader.GetRaytracingPipelineConfig_MaxTraceRecursionDepth());
break;
case DXIL::SubobjectKind::HitGroup:
subobjects.CreateHitGroup(reader.GetName(),
reader.GetHitGroup_Intersection(),
reader.GetHitGroup_AnyHit(),
reader.GetHitGroup_ClosestHit());
break;
}
}
}
HRESULT Disassemble(IDxcBlob *pProgram, raw_string_ostream &Stream) {
const char *pIL = (const char *)pProgram->GetBufferPointer();
uint32_t pILLength = pProgram->GetBufferSize();
@ -1369,6 +1562,20 @@ HRESULT Disassemble(IDxcBlob *pProgram, raw_string_ostream &Stream) {
GetVersionShaderType(pProgramHeader->ProgramVersion), Stream,
/*comment*/ ";");
}
// RDAT
it = std::find_if(begin(pContainer), end(pContainer),
DxilPartIsType(DFCC_RuntimeData));
if (it != end(pContainer)) {
RDAT::DxilRuntimeData runtimeData(GetDxilPartData(*it), (*it)->PartSize);
Stream << ";" << " [RDAT] Begin\n";
// TODO: Print the rest of the RDAT info
DxilSubobjects subobjects;
DeserializeSubobjectsFromRuntimeData(subobjects, runtimeData);
PrintSubobjects(subobjects, Stream, /*comment*/ ";");
Stream << ";" << " [RDAT] End\n";
}
GetDxilProgramBitcode(pProgramHeader, &pIL, &pILLength);
} else {
const DxilProgramHeader *pProgramHeader =
@ -1400,6 +1607,9 @@ HRESULT Disassemble(IDxcBlob *pProgram, raw_string_ostream &Stream) {
PrintBufferDefinitions(dxilModule, Stream, /*comment*/ ";");
PrintResourceBindings(dxilModule, Stream, /*comment*/ ";");
PrintViewIdState(dxilModule, Stream, /*comment*/ ";");
if (dxilModule.GetSubobjects()) {
PrintSubobjects(*dxilModule.GetSubobjects(), Stream, /*comment*/ ";");
}
}
DxcAssemblyAnnotationWriter w;
pModule->print(Stream, &w);