Add Subobjects: classes, metadata, serialization, reflection, disasm
This commit is contained in:
Родитель
527bfc4176
Коммит
9678588269
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче