Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/dxc/DXIL/DxilConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const unsigned kDxilMajor = 1;
/* <py::lines('VALRULE-TEXT')>hctdb_instrhelp.get_dxil_version_minor()</py>*/
// VALRULE-TEXT:BEGIN
const unsigned kDxilMinor = 10;
const unsigned kDxilReleasedMinor = 9;
// VALRULE-TEXT:END

inline unsigned MakeDxilVersion(unsigned DxilMajor, unsigned DxilMinor) {
Expand Down Expand Up @@ -60,6 +61,11 @@ inline int CompareVersions(unsigned Major1, unsigned Minor1, unsigned Major2,
return 0;
}

// Use this instead of fixed version checks to enable experimental features.
inline bool IsVersionExperimental(unsigned Major, unsigned Minor) {
return CompareVersions(Major, Minor, kDxilMajor, kDxilReleasedMinor) > 0;
}

// Utility for updating major,minor to max of current and new.
inline bool UpdateToMaxOfVersions(unsigned &major, unsigned &minor,
unsigned newMajor, unsigned newMinor) {
Expand Down
66 changes: 47 additions & 19 deletions include/dxc/DxilContainer/DxilRDATBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,57 @@ class DxilRDATBuilder {
public:
DxilRDATBuilder(bool allowRecordDuplication);

template <typename T> RDATTable *GetOrAddTable() {
RDATTable **tablePtr =
// Add all supported parts first to control table ordering and prevent use of
// unsupported parts.

StringBufferPart *AddStringBufferPart() {
assert(nullptr == m_pStringBufferPart &&
"otherwise, string buffer part already exists");
return GetOrAddPart(&m_pStringBufferPart);
}
IndexArraysPart *AddIndexArraysPart() {
assert(nullptr == m_pIndexArraysPart &&
"otherwise, index arrays part already exists");
return GetOrAddPart(&m_pIndexArraysPart);
}
RawBytesPart *AddRawBytesPart() {
assert(nullptr == m_pRawBytesPart &&
"otherwise, raw bytes part already exists");
return GetOrAddPart(&m_pRawBytesPart);
}

template <typename T> RDATTable *AddTable() {
RDATTable **TablePtr =
&m_pTables[(size_t)RDAT::RecordTraits<T>::TableIndex()];
if (!*tablePtr) {
m_Parts.emplace_back(llvm::make_unique<RDATTable>());
*tablePtr = reinterpret_cast<RDATTable *>(m_Parts.back().get());
(*tablePtr)->SetRecordStride(sizeof(T));
(*tablePtr)->SetType(RDAT::RecordTraits<T>::PartType());
(*tablePtr)->SetDeduplication(m_bRecordDeduplicationEnabled);
}
return *tablePtr;
assert(nullptr == *TablePtr && "otherwise, table already exists");
RDATTable *Table = GetOrAddPart(TablePtr);
Table->SetRecordStride(sizeof(T));
Table->SetType(RDAT::RecordTraits<T>::PartType());
Table->SetDeduplication(m_bRecordDeduplicationEnabled);
return Table;
}

StringBufferPart &GetStringBufferPart() {
assert(m_pStringBufferPart);
return *m_pStringBufferPart;
}
IndexArraysPart &GetIndexArraysPart() {
assert(m_pIndexArraysPart);
return *m_pIndexArraysPart;
}
RawBytesPart &GetRawBytesPart() {
assert(m_pRawBytesPart);
return *m_pRawBytesPart;
}

template <typename T> RDATTable *GetTable() {
return m_pTables[(size_t)RDAT::RecordTraits<T>::TableIndex()];
}

template <typename T> uint32_t InsertRecord(const T &record) {
return GetOrAddTable<T>()->Insert(record);
RDATTable *Table = GetTable<T>();
assert(Table && "otherwise, missing version check");
return Table->Insert(record);
}
uint32_t InsertString(llvm::StringRef str) {
return GetStringBufferPart().Insert(str);
Expand All @@ -73,14 +109,6 @@ class DxilRDATBuilder {
return InsertArray(arr.begin(), arr.end());
}

StringBufferPart &GetStringBufferPart() {
return *GetOrAddPart(&m_pStringBufferPart);
}
IndexArraysPart &GetIndexArraysPart() {
return *GetOrAddPart(&m_pIndexArraysPart);
}
RawBytesPart &GetRawBytesPart() { return *GetOrAddPart(&m_pRawBytesPart); }

struct SizeInfo {
uint32_t sizeInBytes;
uint32_t numParts;
Expand Down
15 changes: 10 additions & 5 deletions include/dxc/DxilContainer/DxilRuntimeReflection.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ enum class RuntimeDataPartType : uint32_t {

LastPlus1,
LastExperimental = LastPlus1 - 1,
LastRelease = Last_1_8,

DxilPdbInfoTable = RDAT_PART_ID_WITH_GROUP(RuntimeDataGroup::PdbInfo, 1),
DxilPdbInfoSourceTable =
Expand All @@ -91,17 +92,21 @@ enum class RuntimeDataPartType : uint32_t {
RDAT_PART_ID_WITH_GROUP(RuntimeDataGroup::PdbInfo, 3),
};

inline RuntimeDataPartType MaxPartTypeForValVer(unsigned Major,
unsigned Minor) {
inline RuntimeDataPartType
MaxPartTypeForValVer(unsigned Major, unsigned Minor,
bool IsPrereleaseShaderModel = false) {
return DXIL::CompareVersions(Major, Minor, 1, 3) < 0
? RuntimeDataPartType::Invalid // No RDAT before 1.3
: DXIL::CompareVersions(Major, Minor, 1, 4) < 0
? RuntimeDataPartType::Last_1_3
: DXIL::CompareVersions(Major, Minor, 1, 8) < 0
? RuntimeDataPartType::Last_1_4
: DXIL::CompareVersions(Major, Minor, 1, 8) == 0
? RuntimeDataPartType::Last_1_8
: RuntimeDataPartType::LastExperimental;
: DXIL::IsVersionExperimental(Major, Minor) &&
(IsPrereleaseShaderModel || Major == 0)
? RuntimeDataPartType::LastExperimental
: RuntimeDataPartType::LastRelease;
// If validator version > released version, and it's a prerelease shader model
// or unbound validator, allow experimental parts.
}

enum class RecordTableIndex : unsigned {
Expand Down
2 changes: 1 addition & 1 deletion include/dxc/DxilContainer/RDAT_LibraryTypes.inl
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ RDAT_STRUCT_END()

#define RECORD_TYPE RuntimeDataFunctionInfo2
RDAT_STRUCT_TABLE_DERIVED(RuntimeDataFunctionInfo2, RuntimeDataFunctionInfo,
FunctionTable)
FunctionTable, 1, 8)

// 128 lanes is maximum that could be supported by HLSL
RDAT_VALUE(uint8_t, MinimumExpectedWaveLaneCount) // 0 = none specified
Expand Down
8 changes: 4 additions & 4 deletions include/dxc/DxilContainer/RDAT_Macros.inl
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
#define RDAT_FLAGS(sTy, eTy, name) sTy name;
#define RDAT_BYTES(name) hlsl::RDAT::BytesRef name;
#define RDAT_ARRAY_VALUE(type, count, type_name, name) type_name name;
#define RDAT_STRUCT_TABLE_DERIVED(type, base, table) \
#define RDAT_STRUCT_TABLE_DERIVED(type, base, table, MajorVer, MinorVer) \
template <> constexpr const char *RecordTraits<type>::TypeName(); \
template <> constexpr RecordTableIndex RecordTraits<type>::TableIndex(); \
template <> constexpr RuntimeDataPartType RecordTraits<type>::PartType(); \
Expand Down Expand Up @@ -169,7 +169,7 @@
return BaseRecordReader::asRecord<type>(); \
}
#define RDAT_STRUCT_TABLE(type, table) RDAT_STRUCT(type)
#define RDAT_STRUCT_TABLE_DERIVED(type, base, table) \
#define RDAT_STRUCT_TABLE_DERIVED(type, base, table, MajorVer, MinorVer) \
RDAT_STRUCT_DERIVED(type, base)
#define RDAT_UNION_IF(name, expr) \
bool GLUE(RECORD_TYPE, _Reader)::has##name() const { \
Expand Down Expand Up @@ -336,7 +336,7 @@
template <> constexpr RuntimeDataPartType RecordTraits<type>::PartType() { \
return RuntimeDataPartType::table; \
}
#define RDAT_STRUCT_TABLE_DERIVED(type, base, table) \
#define RDAT_STRUCT_TABLE_DERIVED(type, base, table, MajorVer, MinorVer) \
RDAT_STRUCT_DERIVED(type, base) \
template <> constexpr RecordTableIndex RecordTraits<type>::TableIndex() { \
return RecordTableIndex::table; \
Expand All @@ -360,7 +360,7 @@
#define RDAT_STRUCT_TABLE(type, table) RDAT_STRUCT(type)
#endif
#ifndef RDAT_STRUCT_TABLE_DERIVED
#define RDAT_STRUCT_TABLE_DERIVED(type, base, table) \
#define RDAT_STRUCT_TABLE_DERIVED(type, base, table, MajorVer, MinorVer) \
RDAT_STRUCT_DERIVED(type, base)
#endif
#ifndef RDAT_STRUCT_END
Expand Down
39 changes: 21 additions & 18 deletions lib/DxilContainer/DxilContainerAssembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1547,8 +1547,7 @@ class DxilRDATWriter : public DxilPartWriter {
if (entryProps.props.IsNode()) {
shaderInfo = AddShaderNodeInfo(DM, function, entryProps, *pInfo2,
TGSMInFunc[&function]);
} else if (DXIL::CompareVersions(m_ValMajor, m_ValMinor, 1, 8) >
0) {
} else if (Builder.GetTable<RDAT::SignatureElement>()) {
shaderInfo =
AddShaderInfo(function, entryProps, *pInfo2,
compatInfo.shaderFlags, TGSMInFunc[&function]);
Expand Down Expand Up @@ -1656,30 +1655,34 @@ class DxilRDATWriter : public DxilPartWriter {
DxilRDATWriter(DxilModule &mod) : Builder(GetRecordDuplicationAllowed(mod)) {
// Keep track of validator version so we can make a compatible RDAT
mod.GetValidatorVersion(m_ValMajor, m_ValMinor);
RDAT::RuntimeDataPartType maxAllowedType =
RDAT::MaxPartTypeForValVer(m_ValMajor, m_ValMinor);
RDAT::RuntimeDataPartType maxAllowedType = RDAT::MaxPartTypeForValVer(
m_ValMajor, m_ValMinor,
mod.GetShaderModel()->IsPreReleaseShaderModel());

mod.ComputeShaderCompatInfo();

// Instantiate the parts in the order that validator expects.
Builder.GetStringBufferPart();
m_pResourceTable = Builder.GetOrAddTable<RDAT::RuntimeDataResourceInfo>();
m_pFunctionTable = Builder.GetOrAddTable<RuntimeDataFunctionInfo>();
if (DXIL::CompareVersions(m_ValMajor, m_ValMinor, 1, 8) >= 0) {
m_pFunctionTable->SetRecordStride(sizeof(RuntimeDataFunctionInfo2));
} else {
m_pFunctionTable->SetRecordStride(sizeof(RuntimeDataFunctionInfo));
}
Builder.GetIndexArraysPart();
Builder.GetRawBytesPart();
Builder.AddStringBufferPart();
m_pResourceTable = Builder.AddTable<RDAT::RuntimeDataResourceInfo>();
m_pFunctionTable = Builder.AddTable<RuntimeDataFunctionInfo>();
Builder.AddIndexArraysPart();
Builder.AddRawBytesPart();
if (RDAT::RecordTraits<RuntimeDataSubobjectInfo>::PartType() <=
maxAllowedType)
m_pSubobjectTable = Builder.GetOrAddTable<RuntimeDataSubobjectInfo>();
m_pSubobjectTable = Builder.AddTable<RuntimeDataSubobjectInfo>();

// Once per table.
// Once per table, if not already added.
#define RDAT_STRUCT_TABLE(type, table) \
if (RDAT::RecordTraits<RDAT::type>::PartType() <= maxAllowedType) \
(void)Builder.GetOrAddTable<RDAT::type>();
if (RDAT::RecordTraits<RDAT::type>::PartType() <= maxAllowedType && \
!Builder.GetTable<RDAT::type>()) \
(void)Builder.AddTable<RDAT::type>();
// Update the record stride for supported derived types.
#define RDAT_STRUCT_TABLE_DERIVED(type, base, table, MajorVer, MinorVer) \
if (DXIL::CompareVersions(m_ValMajor, m_ValMinor, MajorVer, MinorVer) >= \
0 && \
Builder.GetTable<RDAT::type>()) { \
Builder.GetTable<RDAT::type>()->SetRecordStride(sizeof(RDAT::type)); \
}

#define DEF_RDAT_TYPES DEF_RDAT_DEFAULTS
#include "dxc/DxilContainer/RDAT_Macros.inl"
Expand Down
28 changes: 28 additions & 0 deletions tools/clang/test/CodeGenDXIL/reflection/experimental_rdat.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Note: Base this on highest the experimental version, or released+1.
// REQUIRES: dxil-1-10
// RUN: %dxc %s -Tlib_6_10 -Vd -validator-version 0.0 -Fo %t
// RUN: %dxa %t -dumprdat | FileCheck %s -check-prefixes=CHECK,EXP
// RUN: %dxc %s -Tlib_6_10 -Fo %t
// RUN: %dxa %t -dumprdat | FileCheck %s -check-prefixes=CHECK,EXP
// RUN: %dxc %s -Tlib_6_10 -validator-version 1.10 -Fo %t
// RUN: %dxa %t -dumprdat | FileCheck %s -check-prefixes=CHECK,EXP

// No experimental RDAT for released shader models even with default or latest
// validator versions.
// RUN: %dxc %s -Tlib_6_9 -Fo %t
// RUN: %dxa %t -dumprdat | FileCheck %s -check-prefixes=CHECK,NOEXP
// RUN: %dxc %s -Tlib_6_9 -validator-version 1.10 -Fo %t
// RUN: %dxa %t -dumprdat | FileCheck %s -check-prefixes=CHECK,NOEXP

// Make sure experimental RDAT is not emitted for released shader models,
// unless the validator version is 0.0 (no validation supported). Validator
// version 0.0 is implied for the offline linking target lib_6_x.

// CHECK: DxilRuntimeData
// EXP: PSInfoTable
// NOEXP-NOT: PSInfoTable

[shader("pixel")]
float4 main() : SV_Target {
return float4(1.0, 0.0, 0.0, 1.0);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Note: Add RUN lines for newer released shader models to this test when available.
// REQUIRES: dxil-1-9
// RUN: %dxc %s -Tlib_6_x -Fo %t
// RUN: %dxa %t -dumprdat | FileCheck %s -check-prefixes=CHECK,EXP
// RUN: %dxc %s -Tlib_6_9 -Vd -validator-version 0.0 -Fo %t
// RUN: %dxa %t -dumprdat | FileCheck %s -check-prefixes=CHECK,EXP
// RUN: %dxc %s -Tlib_6_9 -Fo %t
// RUN: %dxa %t -dumprdat | FileCheck %s -check-prefixes=CHECK,NOEXP
// RUN: %dxc %s -Tlib_6_9 -validator-version 1.9 -Fo %t
// RUN: %dxa %t -dumprdat | FileCheck %s -check-prefixes=CHECK,NOEXP

// Make sure experimental RDAT is not emitted for released shader models,
// unless the validator version is 0.0 (no validation supported). Validator
// version 0.0 is implied for the offline linking target lib_6_x.

// CHECK: DxilRuntimeData
// EXP: PSInfoTable
// NOEXP-NOT: PSInfoTable

[shader("pixel")]
float4 main() : SV_Target {
return float4(1.0, 0.0, 0.0, 1.0);
}
3 changes: 2 additions & 1 deletion utils/hct/hctdb_instrhelp.py
Original file line number Diff line number Diff line change
Expand Up @@ -1748,7 +1748,8 @@ def get_highest_shader_model():


def get_dxil_version_minor():
return "const unsigned kDxilMinor = %d;" % highest_minor
return (f"const unsigned kDxilMinor = {highest_minor};\n" +
f"const unsigned kDxilReleasedMinor = {highest_released_minor};")


def get_dxil_version_minor_int():
Expand Down
Loading