[Validator] Check size of PSV. (#6924)

Check size of PSV part matches the PSVVersion.
Updated DxilPipelineStateValidation::ReadOrWrite to read based on
initInfo.PSVVersion.
And return fail when size mismatch in RWMode::Read.

Fixes #6817
This commit is contained in:
Xiang Li 2024-10-02 20:48:32 -07:00 коммит произвёл GitHub
Родитель b05313c384
Коммит 9221570027
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
7 изменённых файлов: 815 добавлений и 54 удалений

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

@ -23,6 +23,7 @@ Place release notes for the upcoming release below this line and remove this lin
- The incomplete WaveMatrix implementation has been removed.
- DXIL Validator Hash is open sourced.
- DXIL container validation for PSV0 part allows any content ordering inside string and semantic index tables.
### Version 1.8.2407

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

@ -226,7 +226,8 @@ struct PSVStringTable {
PSVStringTable() : Table(nullptr), Size(0) {}
PSVStringTable(const char *table, uint32_t size) : Table(table), Size(size) {}
const char *Get(uint32_t offset) const {
assert(offset < Size && Table && Table[Size - 1] == '\0');
if (!(offset < Size && Table && Table[Size - 1] == '\0'))
return nullptr;
return Table + offset;
}
};
@ -344,7 +345,8 @@ struct PSVSemanticIndexTable {
PSVSemanticIndexTable(const uint32_t *table, uint32_t entries)
: Table(table), Entries(entries) {}
const uint32_t *Get(uint32_t offset) const {
assert(offset < Entries && Table);
if (!(offset < Entries && Table))
return nullptr;
return Table + offset;
}
};
@ -638,7 +640,8 @@ public:
_T *GetRecord(void *pRecords, uint32_t recordSize, uint32_t numRecords,
uint32_t index) const {
if (pRecords && index < numRecords && sizeof(_T) <= recordSize) {
assert((size_t)index * (size_t)recordSize <= UINT_MAX);
if (!((size_t)index * (size_t)recordSize <= UINT_MAX))
return nullptr;
return reinterpret_cast<_T *>(reinterpret_cast<uint8_t *>(pRecords) +
(index * recordSize));
}
@ -1126,6 +1129,10 @@ void InitPSVSignatureElement(PSVSignatureElement0 &E,
const DxilSignatureElement &SE,
bool i1ToUnknownCompat);
// Setup PSVInitInfo with DxilModule.
// Note that the StringTable and PSVSemanticIndexTable are not done.
void SetupPSVInitInfo(PSVInitInfo &InitInfo, const DxilModule &DM);
// Setup shader properties for PSVRuntimeInfo* with DxilModule.
void SetShaderProps(PSVRuntimeInfo0 *pInfo, const DxilModule &DM);
void SetShaderProps(PSVRuntimeInfo1 *pInfo1, const DxilModule &DM);

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

@ -738,30 +738,14 @@ public:
DxilPSVWriter(const DxilModule &mod, uint32_t PSVVersion = UINT_MAX)
: m_Module(mod), m_PSVInitInfo(PSVVersion) {
m_Module.GetValidatorVersion(m_ValMajor, m_ValMinor);
// Constraint PSVVersion based on validator version
uint32_t PSVVersionConstraint = hlsl::GetPSVVersion(m_ValMajor, m_ValMinor);
if (PSVVersion > PSVVersionConstraint)
m_PSVInitInfo.PSVVersion = PSVVersionConstraint;
hlsl::SetupPSVInitInfo(m_PSVInitInfo, m_Module);
const ShaderModel *SM = m_Module.GetShaderModel();
UINT uCBuffers = m_Module.GetCBuffers().size();
UINT uSamplers = m_Module.GetSamplers().size();
UINT uSRVs = m_Module.GetSRVs().size();
UINT uUAVs = m_Module.GetUAVs().size();
m_PSVInitInfo.ResourceCount = uCBuffers + uSamplers + uSRVs + uUAVs;
// TODO: for >= 6.2 version, create more efficient structure
if (m_PSVInitInfo.PSVVersion > 0) {
m_PSVInitInfo.ShaderStage = (PSVShaderKind)SM->GetKind();
// Copy Dxil Signatures
m_StringBuffer.push_back('\0'); // For empty semantic name (system value)
m_PSVInitInfo.SigInputElements =
m_Module.GetInputSignature().GetElements().size();
m_SigInputElements.resize(m_PSVInitInfo.SigInputElements);
m_PSVInitInfo.SigOutputElements =
m_Module.GetOutputSignature().GetElements().size();
m_SigOutputElements.resize(m_PSVInitInfo.SigOutputElements);
m_PSVInitInfo.SigPatchConstOrPrimElements =
m_Module.GetPatchConstOrPrimSignature().GetElements().size();
m_SigPatchConstOrPrimElements.resize(
m_PSVInitInfo.SigPatchConstOrPrimElements);
uint32_t i = 0;
@ -791,20 +775,6 @@ public:
m_PSVInitInfo.StringTable.Size = m_StringBuffer.size();
m_PSVInitInfo.SemanticIndexTable.Table = m_SemanticIndexBuffer.data();
m_PSVInitInfo.SemanticIndexTable.Entries = m_SemanticIndexBuffer.size();
// Set up ViewID and signature dependency info
m_PSVInitInfo.UsesViewID =
m_Module.m_ShaderFlags.GetViewID() ? true : false;
m_PSVInitInfo.SigInputVectors =
m_Module.GetInputSignature().NumVectorsUsed(0);
for (unsigned streamIndex = 0; streamIndex < 4; streamIndex++) {
m_PSVInitInfo.SigOutputVectors[streamIndex] =
m_Module.GetOutputSignature().NumVectorsUsed(streamIndex);
}
m_PSVInitInfo.SigPatchConstOrPrimVectors = 0;
if (SM->IsHS() || SM->IsDS() || SM->IsMS()) {
m_PSVInitInfo.SigPatchConstOrPrimVectors =
m_Module.GetPatchConstOrPrimSignature().NumVectorsUsed(0);
}
}
if (!m_PSV.InitNew(m_PSVInitInfo, nullptr, &m_PSVBufferSize)) {
DXASSERT(false, "PSV InitNew failed computing size!");

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

@ -110,6 +110,43 @@ void hlsl::InitPSVSignatureElement(PSVSignatureElement0 &E,
E.DynamicMaskAndStream |= (SE.GetDynIdxCompMask()) & 0xF;
}
void hlsl::SetupPSVInitInfo(PSVInitInfo &InitInfo, const DxilModule &DM) {
// Constraint PSVVersion based on validator version
unsigned ValMajor, ValMinor;
DM.GetValidatorVersion(ValMajor, ValMinor);
unsigned PSVVersionConstraint = hlsl::GetPSVVersion(ValMajor, ValMinor);
if (InitInfo.PSVVersion > PSVVersionConstraint)
InitInfo.PSVVersion = PSVVersionConstraint;
const ShaderModel *SM = DM.GetShaderModel();
uint32_t uCBuffers = DM.GetCBuffers().size();
uint32_t uSamplers = DM.GetSamplers().size();
uint32_t uSRVs = DM.GetSRVs().size();
uint32_t uUAVs = DM.GetUAVs().size();
InitInfo.ResourceCount = uCBuffers + uSamplers + uSRVs + uUAVs;
if (InitInfo.PSVVersion > 0) {
InitInfo.ShaderStage = (PSVShaderKind)SM->GetKind();
InitInfo.SigInputElements = DM.GetInputSignature().GetElements().size();
InitInfo.SigPatchConstOrPrimElements =
DM.GetPatchConstOrPrimSignature().GetElements().size();
InitInfo.SigOutputElements = DM.GetOutputSignature().GetElements().size();
// Set up ViewID and signature dependency info
InitInfo.UsesViewID = DM.m_ShaderFlags.GetViewID() ? true : false;
InitInfo.SigInputVectors = DM.GetInputSignature().NumVectorsUsed(0);
for (unsigned streamIndex = 0; streamIndex < 4; streamIndex++) {
InitInfo.SigOutputVectors[streamIndex] =
DM.GetOutputSignature().NumVectorsUsed(streamIndex);
}
InitInfo.SigPatchConstOrPrimVectors = 0;
if (SM->IsHS() || SM->IsDS() || SM->IsMS()) {
InitInfo.SigPatchConstOrPrimVectors =
DM.GetPatchConstOrPrimSignature().NumVectorsUsed(0);
}
}
}
void hlsl::SetShaderProps(PSVRuntimeInfo0 *pInfo, const DxilModule &DM) {
const ShaderModel *SM = DM.GetShaderModel();
pInfo->MinimumExpectedWaveLaneCount = 0;

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

@ -24,6 +24,7 @@
#include "dxc/DXIL/DxilUtil.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/Module.h"
@ -33,6 +34,7 @@
#include "DxilValidationUtils.h"
#include <memory>
#include <unordered_map>
#include <unordered_set>
using namespace llvm;
@ -79,17 +81,95 @@ static void emitDxilDiag(LLVMContext &Ctx, const char *str) {
hlsl::dxilutil::EmitErrorOnContext(Ctx, str);
}
class StringTableVerifier {
std::unordered_map<unsigned, unsigned> OffsetToUseCountMap;
const PSVStringTable &Table;
public:
StringTableVerifier(const PSVStringTable &Table) : Table(Table) {
unsigned Start = 0;
for (unsigned i = 0; i < Table.Size; ++i) {
char ch = Table.Table[i];
if (ch == '\0') {
OffsetToUseCountMap[Start] = 0;
Start = i + 1;
}
}
if (Table.Size >= 4) {
// Remove the '\0's at the end of the table added for padding.
for (unsigned i = Table.Size - 1; i > Table.Size - 4; --i) {
if (Table.Table[i] != '\0')
break;
OffsetToUseCountMap.erase(i);
}
}
}
bool MarkUse(unsigned Offset) {
auto it = OffsetToUseCountMap.find(Offset);
if (it != OffsetToUseCountMap.end())
it->second++;
return Offset < Table.Size;
}
void Verify(ValidationContext &ValCtx) {
for (auto [Offset, UseCount] : OffsetToUseCountMap) {
if (UseCount != 0)
continue;
// DXC will always add a null-terminated string at the beginning of the
// StringTable. It is OK if it is not used.
if (Offset == 0 && Table.Table[0] == '\0')
continue;
ValCtx.EmitFormatError(ValidationRule::ContainerUnusedItemInTable,
{"StringTable", Table.Get(Offset)});
}
}
};
class SemanticIndexTableVerifier {
const PSVSemanticIndexTable &Table;
llvm::BitVector UseMask;
public:
SemanticIndexTableVerifier(const PSVSemanticIndexTable &Table)
: Table(Table), UseMask(Table.Entries, false) {}
bool MarkUse(unsigned Offset, unsigned Size) {
if (Table.Table == nullptr)
return false;
if (Offset > Table.Entries)
return false;
if ((Offset + Size) > Table.Entries)
return false;
for (unsigned i = Offset; i < (Offset + Size); ++i) {
UseMask[i] = true;
}
return true;
}
void Verify(ValidationContext &ValCtx) {
for (unsigned i = 0; i < Table.Entries; i++) {
if (UseMask[i])
continue;
ValCtx.EmitFormatError(ValidationRule::ContainerUnusedItemInTable,
{"SemanticIndexTable", std::to_string(i)});
}
}
};
class PSVContentVerifier {
DxilModule &DM;
DxilPipelineStateValidation &PSV;
ValidationContext &ValCtx;
bool PSVContentValid = true;
StringTableVerifier StrTableVerifier;
SemanticIndexTableVerifier IndexTableVerifier;
public:
PSVContentVerifier(DxilPipelineStateValidation &PSV, DxilModule &DM,
ValidationContext &ValCtx)
: DM(DM), PSV(PSV), ValCtx(ValCtx) {}
void Verify();
: DM(DM), PSV(PSV), ValCtx(ValCtx),
StrTableVerifier(PSV.GetStringTable()),
IndexTableVerifier(PSV.GetSemanticIndexTable()) {}
void Verify(unsigned ValMajor, unsigned ValMinor, unsigned PSVVersion);
private:
void VerifySignatures(unsigned ValMajor, unsigned ValMinor);
@ -113,7 +193,8 @@ private:
PSVContentValid = false;
}
void EmitInvalidError(StringRef Name) {
ValCtx.EmitFormatError(ValidationRule::ContainerContentInvalid, {Name});
ValCtx.EmitFormatError(ValidationRule::ContainerContentInvalid,
{"PSV0 part", Name});
PSVContentValid = false;
}
template <typename Ty> static std::string GetDump(const Ty &T) {
@ -226,6 +307,17 @@ void PSVContentVerifier::VerifySignatureElement(
const DxilSignatureElement &SE, PSVSignatureElement0 *PSVSE0,
const PSVStringTable &StrTab, const PSVSemanticIndexTable &IndexTab,
std::string Name, bool i1ToUnknownCompat) {
bool InvalidTableAccess = false;
if (!StrTableVerifier.MarkUse(PSVSE0->SemanticName)) {
EmitInvalidError("SemanticName");
InvalidTableAccess = true;
}
if (!IndexTableVerifier.MarkUse(PSVSE0->SemanticIndexes, PSVSE0->Rows)) {
EmitInvalidError("SemanticIndex");
InvalidTableAccess = true;
}
if (InvalidTableAccess)
return;
// Find the signature element in the set.
PSVSignatureElement0 ModulePSVSE0;
InitPSVSignatureElement(ModulePSVSE0, SE, i1ToUnknownCompat);
@ -368,18 +460,9 @@ void PSVContentVerifier::VerifyEntryProperties(const ShaderModel *SM,
}
}
void PSVContentVerifier::Verify() {
unsigned ValMajor, ValMinor;
DM.GetValidatorVersion(ValMajor, ValMinor);
unsigned PSVVersion = hlsl::GetPSVVersion(ValMajor, ValMinor);
void PSVContentVerifier::Verify(unsigned ValMajor, unsigned ValMinor,
unsigned PSVVersion) {
PSVInitInfo PSVInfo(PSVVersion);
if (PSV.GetRuntimeInfoSize() != PSVInfo.RuntimeInfoSize()) {
EmitMismatchError("PSVRuntimeInfoSize",
std::to_string(PSV.GetRuntimeInfoSize()),
std::to_string(PSVInfo.RuntimeInfoSize()));
return;
}
if (PSV.GetBindCount() > 0 &&
PSV.GetResourceBindInfoSize() != PSVInfo.ResourceBindInfoSize()) {
@ -421,11 +504,19 @@ void PSVContentVerifier::Verify() {
}
// PSV2 only added NumThreadsX/Y/Z which verified in VerifyEntryProperties.
if (PSVVersion > 2) {
if (DM.GetEntryFunctionName() != PSV.GetEntryFunctionName())
EmitMismatchError("EntryFunctionName", PSV.GetEntryFunctionName(),
DM.GetEntryFunctionName());
PSVRuntimeInfo3 *PSV3 = PSV.GetPSVRuntimeInfo3();
if (!StrTableVerifier.MarkUse(PSV3->EntryFunctionName)) {
EmitInvalidError("EntryFunctionName");
} else {
if (DM.GetEntryFunctionName() != PSV.GetEntryFunctionName())
EmitMismatchError("EntryFunctionName", PSV.GetEntryFunctionName(),
DM.GetEntryFunctionName());
}
}
StrTableVerifier.Verify(ValCtx);
IndexTableVerifier.Verify(ValCtx);
if (!PSVContentValid)
ValCtx.EmitFormatError(ValidationRule::ContainerPartMatches,
{"Pipeline State Validation"});
@ -507,16 +598,204 @@ bool VerifySignatureMatches(llvm::Module *pModule, DXIL::SignatureKind SigKind,
return !ValCtx.Failed;
}
struct SimplePSV {
uint32_t PSVRuntimeInfoSize = 0;
uint32_t PSVNumResources = 0;
uint32_t PSVResourceBindInfoSize = 0;
uint32_t StringTableSize = 0;
const char *StringTable = nullptr;
uint32_t SemanticIndexTableEntries = 0;
const uint32_t *SemanticIndexTable = nullptr;
uint32_t PSVSignatureElementSize = 0;
const PSVRuntimeInfo1 *RuntimeInfo1 = nullptr;
bool IsValid = true;
SimplePSV(const void *pPSVData, uint32_t PSVSize) {
#define INCREMENT_POS(Size) \
Offset += Size; \
if (Offset > PSVSize) { \
IsValid = false; \
return; \
}
uint32_t Offset = 0;
PSVRuntimeInfoSize = GetUint32AtOffset(pPSVData, 0);
INCREMENT_POS(4);
if (PSVRuntimeInfoSize >= sizeof(PSVRuntimeInfo1))
RuntimeInfo1 =
(const PSVRuntimeInfo1 *)(GetPtrAtOffset(pPSVData, Offset));
INCREMENT_POS(PSVRuntimeInfoSize);
PSVNumResources = GetUint32AtOffset(pPSVData, Offset);
INCREMENT_POS(4);
if (PSVNumResources > 0) {
PSVResourceBindInfoSize = GetUint32AtOffset(pPSVData, Offset);
// Increase the offset for the resource bind info size.
INCREMENT_POS(4);
// Increase the offset for the resource bind info.
INCREMENT_POS(PSVNumResources * PSVResourceBindInfoSize);
}
if (RuntimeInfo1) {
StringTableSize = GetUint32AtOffset(pPSVData, Offset);
INCREMENT_POS(4);
// Make sure StringTableSize is aligned to 4 bytes.
if ((StringTableSize & 3) != 0) {
IsValid = false;
return;
}
if (StringTableSize) {
StringTable = GetPtrAtOffset(pPSVData, Offset);
INCREMENT_POS(StringTableSize);
}
SemanticIndexTableEntries = GetUint32AtOffset(pPSVData, Offset);
INCREMENT_POS(4);
if (SemanticIndexTableEntries) {
SemanticIndexTable =
(const uint32_t *)(GetPtrAtOffset(pPSVData, Offset));
INCREMENT_POS(SemanticIndexTableEntries * 4);
}
if (RuntimeInfo1->SigInputElements || RuntimeInfo1->SigOutputElements ||
RuntimeInfo1->SigPatchConstOrPrimElements) {
PSVSignatureElementSize = GetUint32AtOffset(pPSVData, Offset);
INCREMENT_POS(4);
uint32_t PSVNumSignatures = RuntimeInfo1->SigInputElements +
RuntimeInfo1->SigOutputElements +
RuntimeInfo1->SigPatchConstOrPrimElements;
INCREMENT_POS(PSVNumSignatures * PSVSignatureElementSize);
}
if (RuntimeInfo1->UsesViewID) {
for (unsigned i = 0; i < DXIL::kNumOutputStreams; i++) {
uint32_t SigOutputVectors = RuntimeInfo1->SigOutputVectors[i];
if (SigOutputVectors == 0)
continue;
uint32_t MaskSizeInBytes =
sizeof(uint32_t) *
PSVComputeMaskDwordsFromVectors(SigOutputVectors);
INCREMENT_POS(MaskSizeInBytes);
}
if ((RuntimeInfo1->ShaderStage == (unsigned)DXIL::ShaderKind::Hull ||
RuntimeInfo1->ShaderStage == (unsigned)DXIL::ShaderKind::Mesh) &&
RuntimeInfo1->SigPatchConstOrPrimVectors) {
uint32_t MaskSizeInBytes =
sizeof(uint32_t) * PSVComputeMaskDwordsFromVectors(
RuntimeInfo1->SigPatchConstOrPrimVectors);
INCREMENT_POS(MaskSizeInBytes);
}
}
for (unsigned i = 0; i < DXIL::kNumOutputStreams; i++) {
uint32_t SigOutputVectors = RuntimeInfo1->SigOutputVectors[i];
if (SigOutputVectors == 0)
continue;
uint32_t TableSizeInBytes =
sizeof(uint32_t) *
PSVComputeInputOutputTableDwords(RuntimeInfo1->SigInputVectors,
SigOutputVectors);
INCREMENT_POS(TableSizeInBytes);
}
if ((RuntimeInfo1->ShaderStage == (unsigned)DXIL::ShaderKind::Hull ||
RuntimeInfo1->ShaderStage == (unsigned)DXIL::ShaderKind::Mesh) &&
RuntimeInfo1->SigPatchConstOrPrimVectors &&
RuntimeInfo1->SigInputVectors) {
uint32_t TableSizeInBytes =
sizeof(uint32_t) * PSVComputeInputOutputTableDwords(
RuntimeInfo1->SigInputVectors,
RuntimeInfo1->SigPatchConstOrPrimVectors);
INCREMENT_POS(TableSizeInBytes);
}
if (RuntimeInfo1->ShaderStage == (unsigned)DXIL::ShaderKind::Domain &&
RuntimeInfo1->SigOutputVectors[0] &&
RuntimeInfo1->SigPatchConstOrPrimVectors) {
uint32_t TableSizeInBytes =
sizeof(uint32_t) * PSVComputeInputOutputTableDwords(
RuntimeInfo1->SigPatchConstOrPrimVectors,
RuntimeInfo1->SigOutputVectors[0]);
INCREMENT_POS(TableSizeInBytes);
}
}
IsValid = PSVSize == Offset;
#undef INCREMENT_POS
}
bool ValidatePSVInit(PSVInitInfo PSVInfo, ValidationContext &ValCtx) {
if (PSVRuntimeInfoSize != PSVInfo.RuntimeInfoSize()) {
ValCtx.EmitFormatError(ValidationRule::ContainerContentMatches,
{"PSVRuntimeInfoSize", "PSV0",
std::to_string(PSVRuntimeInfoSize),
std::to_string(PSVInfo.RuntimeInfoSize())});
return false;
}
if (PSVNumResources &&
PSVResourceBindInfoSize != PSVInfo.ResourceBindInfoSize()) {
ValCtx.EmitFormatError(ValidationRule::ContainerContentMatches,
{"PSVResourceBindInfoSize", "PSV0",
std::to_string(PSVResourceBindInfoSize),
std::to_string(PSVInfo.ResourceBindInfoSize())});
return false;
}
if (RuntimeInfo1 &&
(RuntimeInfo1->SigInputElements || RuntimeInfo1->SigOutputElements ||
RuntimeInfo1->SigPatchConstOrPrimElements) &&
PSVSignatureElementSize != PSVInfo.SignatureElementSize()) {
ValCtx.EmitFormatError(ValidationRule::ContainerContentMatches,
{"PSVSignatureElementSize", "PSV0",
std::to_string(PSVSignatureElementSize),
std::to_string(PSVInfo.SignatureElementSize())});
return false;
}
return true;
}
private:
const char *GetPtrAtOffset(const void *BasePtr, uint32_t Offset) const {
return (const char *)BasePtr + Offset;
}
uint32_t GetUint32AtOffset(const void *BasePtr, uint32_t Offset) const {
return *(const uint32_t *)GetPtrAtOffset(BasePtr, Offset);
}
};
static void VerifyPSVMatches(ValidationContext &ValCtx, const void *pPSVData,
uint32_t PSVSize) {
// SimplePSV.IsValid indicates whether the part is well-formed so that we may
// proceed with more detailed validation.
SimplePSV SimplePSV(pPSVData, PSVSize);
if (!SimplePSV.IsValid) {
ValCtx.EmitFormatError(ValidationRule::ContainerContentInvalid,
{"DxilContainer", "PSV0 part"});
return;
}
// The PSVVersion determines the size of record structures that should be
// used when writing PSV0 data, and is based on the validator version in the
// module.
unsigned ValMajor, ValMinor;
ValCtx.DxilMod.GetValidatorVersion(ValMajor, ValMinor);
unsigned PSVVersion = hlsl::GetPSVVersion(ValMajor, ValMinor);
// PSVInfo is used to compute the expected record size of the PSV0 part of the
// container. It uses facts from the module.
PSVInitInfo PSVInfo(PSVVersion);
hlsl::SetupPSVInitInfo(PSVInfo, ValCtx.DxilMod);
// ValidatePSVInit checks that record sizes match expected for PSVVersion.
if (!SimplePSV.ValidatePSVInit(PSVInfo, ValCtx))
return;
// Ensure that the string table data is null-terminated.
if (SimplePSV.StringTable &&
SimplePSV.StringTable[SimplePSV.StringTableSize - 1] != '\0') {
ValCtx.EmitFormatError(ValidationRule::ContainerContentInvalid,
{"PSV part StringTable"});
return;
}
DxilPipelineStateValidation PSV;
if (!PSV.InitFromPSV0(pPSVData, PSVSize)) {
ValCtx.EmitFormatError(ValidationRule::ContainerPartMatches,
{"Pipeline State Validation"});
return;
}
PSVContentVerifier Verifier(PSV, ValCtx.DxilMod, ValCtx);
Verifier.Verify();
Verifier.Verify(ValMajor, ValMinor, PSVVersion);
}
static void VerifyFeatureInfoMatches(ValidationContext &ValCtx,

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

@ -321,6 +321,9 @@ public:
TEST_METHOD(PSVContentValidationCS)
TEST_METHOD(PSVContentValidationMS)
TEST_METHOD(PSVContentValidationAS)
TEST_METHOD(WrongPSVSize)
TEST_METHOD(WrongPSVSizeOnZeros)
TEST_METHOD(WrongPSVVersion)
dxc::DxcDllSupport m_dllSupport;
VersionSupportInfo m_ver;
@ -427,6 +430,18 @@ public:
pResultBlob);
}
bool CompileFile(LPCWSTR fileName, LPCSTR pShaderModel, LPCWSTR *pArguments,
UINT32 argCount, IDxcBlob **pResultBlob) {
std::wstring fullPath = hlsl_test::GetPathToHlslDataFile(fileName);
CComPtr<IDxcLibrary> pLibrary;
CComPtr<IDxcBlobEncoding> pSource;
VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary));
VERIFY_SUCCEEDED(
pLibrary->CreateBlobFromFile(fullPath.c_str(), nullptr, &pSource));
return CompileSource(pSource, pShaderModel, pArguments, argCount, nullptr,
0, pResultBlob);
}
bool CompileSource(IDxcBlobEncoding *pSource, LPCSTR pShaderModel,
IDxcBlob **pResultBlob) {
return CompileSource(pSource, pShaderModel, nullptr, 0, nullptr, 0,
@ -4636,7 +4651,7 @@ TEST_F(ValidationTest, PSVStringTableReorder) {
" ComponentType: 3",
" DynamicIndexMask: 0",
"') and DXIL module:('PSVSignatureElement:",
" SemanticName: ",
" SemanticName: A",
" SemanticIndex: 0 ",
" IsAllocated: 1",
" StartRow: 0",
@ -4664,7 +4679,7 @@ TEST_F(ValidationTest, PSVStringTableReorder) {
" ComponentType: 3",
" DynamicIndexMask: 0",
"') and DXIL module:('PSVSignatureElement:",
" SemanticName: ",
" SemanticName: B",
" SemanticIndex: 0 ",
" IsAllocated: 1",
" StartRow: 0",
@ -4679,6 +4694,8 @@ TEST_F(ValidationTest, PSVStringTableReorder) {
"')",
"error: DXIL container mismatch for 'EntryFunctionName' between 'PSV0' "
"part:('ain') and DXIL module:('main')",
"error: In 'StringTable', 'A' is not used",
"error: In 'StringTable', 'main' is not used",
"error: Container part 'Pipeline State Validation' does not match "
"expected for module.",
"Validation failed."},
@ -4697,6 +4714,25 @@ TEST_F(ValidationTest, PSVStringTableReorder) {
VERIFY_IS_NOT_NULL(pUpdatedResult);
VERIFY_SUCCEEDED(pUpdatedResult->GetStatus(&status));
VERIFY_SUCCEEDED(status);
// Create unused name in String table.
PSVInfo->EntryFunctionName = UINT32_MAX;
// Run validation again.
CComPtr<IDxcOperationResult> pUpdatedTableResult2;
VERIFY_SUCCEEDED(
pValidator->Validate(pProgram, Flags, &pUpdatedTableResult2));
// Make sure the validation was fail.
VERIFY_IS_NOT_NULL(pUpdatedTableResult2);
VERIFY_SUCCEEDED(pUpdatedTableResult2->GetStatus(&status));
VERIFY_FAILED(status);
CheckOperationResultMsgs(
pUpdatedTableResult2,
{
"In 'PSV0 part', 'EntryFunctionName' is not well-formed",
"error: In 'StringTable', 'main' is not used",
},
/*maySucceedAnyway*/ false, /*bRegex*/ false);
}
class SemanticIndexRotator {
@ -4715,6 +4751,10 @@ public:
SignatureElements[i].SemanticIndexes =
SignatureElements[i].SemanticIndexes - 1;
}
void Clear(unsigned Index) {
for (unsigned i = 0; i < SignatureElements.size(); ++i)
SignatureElements[i].SemanticIndexes = Index;
}
};
TEST_F(ValidationTest, PSVSemanticIndexTableReorder) {
@ -5043,6 +5083,31 @@ TEST_F(ValidationTest, PSVSemanticIndexTableReorder) {
VERIFY_IS_NOT_NULL(pUpdatedResult);
VERIFY_SUCCEEDED(pUpdatedResult->GetStatus(&status));
VERIFY_SUCCEEDED(status);
// Clear SemanticIndexes.
InputRotator.Clear(UINT32_MAX);
OutputRotator.Clear(UINT32_MAX);
PatchConstOrPrimRotator.Clear(UINT32_MAX);
// Run validation again.
CComPtr<IDxcOperationResult> pUpdatedResult2;
VERIFY_SUCCEEDED(pValidator->Validate(pProgram, Flags, &pUpdatedResult2));
// Make sure the validation was successful.
VERIFY_IS_NOT_NULL(pUpdatedResult2);
VERIFY_SUCCEEDED(pUpdatedResult2->GetStatus(&status));
VERIFY_FAILED(status);
CheckOperationResultMsgs(
pUpdatedResult2,
{"error: In 'PSV0 part', 'SemanticIndex' is not well-formed",
"error: In 'SemanticIndexTable', '0' is not used",
"error: In 'SemanticIndexTable', '2' is not used",
"error: In 'SemanticIndexTable', '3' is not used",
"error: In 'SemanticIndexTable', '4' is not used",
"error: Container part 'Pipeline State Validation' "
"does not match expected for module.",
"Validation failed."},
/*maySucceedAnyway*/ false, /*bRegex*/ false);
}
struct SimplePSV {
@ -6034,3 +6099,400 @@ TEST_F(ValidationTest, PSVContentValidationAS) {
"Validation failed."},
/*maySucceedAnyway*/ false, /*bRegex*/ false);
}
struct SimpleContainer {
hlsl::DxilContainerHeader *Header;
std::vector<uint32_t> PartOffsets;
std::vector<const DxilPartHeader *> PartHeaders;
SimpleContainer(void *Ptr) {
Header = (hlsl::DxilContainerHeader *)Ptr;
hlsl::DxilPartIterator pPartIter(nullptr, 0);
pPartIter = hlsl::begin(Header);
for (unsigned i = 0; i < Header->PartCount; ++i) {
VERIFY_IS_TRUE(pPartIter != hlsl::end(Header));
PartOffsets.push_back(
(uint32_t)((const char *)(*pPartIter) - (const char *)Header));
PartHeaders.push_back((const DxilPartHeader *)(*pPartIter));
++pPartIter;
}
VERIFY_ARE_EQUAL(pPartIter, hlsl::end(Header));
}
};
TEST_F(ValidationTest, WrongPSVSize) {
if (!m_ver.m_InternalValidator)
if (m_ver.SkipDxilVersion(1, 8))
return;
CComPtr<IDxcBlob> pProgram;
CompileFile(L"..\\DXC\\dumpPSV_AS.hlsl", "as_6_8", &pProgram);
CComPtr<IDxcValidator> pValidator;
CComPtr<IDxcOperationResult> pResult;
unsigned Flags = 0;
VERIFY_SUCCEEDED(
m_dllSupport.CreateInstance(CLSID_DxcValidator, &pValidator));
VERIFY_SUCCEEDED(pValidator->Validate(pProgram, Flags, &pResult));
// Make sure the validation was successful.
HRESULT status;
VERIFY_IS_NOT_NULL(pResult);
VERIFY_SUCCEEDED(pResult->GetStatus(&status));
VERIFY_SUCCEEDED(status);
hlsl::DxilContainerHeader *pHeader;
hlsl::DxilPartIterator pPartIter(nullptr, 0);
pHeader = (hlsl::DxilContainerHeader *)pProgram->GetBufferPointer();
// Make sure the PSV part exists.
pPartIter =
std::find_if(hlsl::begin(pHeader), hlsl::end(pHeader),
hlsl::DxilPartIsType(hlsl::DFCC_PipelineStateValidation));
VERIFY_ARE_NOT_EQUAL(hlsl::end(pHeader), pPartIter);
// Create a new Blob which is 16 bytes larger than the original one.
std::vector<char> pProgram2Data(pProgram->GetBufferSize() + 16, 0);
// Copy data from the original blob part by part.
// Copy all parts to program2.
SimpleContainer Container(pProgram->GetBufferPointer());
uint32_t PartOffsetsSize = pHeader->PartCount * sizeof(uint32_t);
uint32_t Offset = sizeof(hlsl::DxilContainerHeader) + PartOffsetsSize;
std::vector<uint32_t> PartOffsets;
const uint32_t ExtraSize = 16;
// copy all parts to program2.
for (unsigned i = 0; i < pHeader->PartCount; ++i) {
PartOffsets.emplace_back(Offset);
const DxilPartHeader *pPartHeader = Container.PartHeaders[i];
// Copy part header.
memcpy(pProgram2Data.data() + Offset, pPartHeader, sizeof(DxilPartHeader));
Offset += sizeof(DxilPartHeader);
// Copy part content.
uint32_t *PartPtr =
const_cast<uint32_t *>((const uint32_t *)GetDxilPartData(pPartHeader));
memcpy(pProgram2Data.data() + Offset, PartPtr, pPartHeader->PartSize);
Offset += pPartHeader->PartSize;
if (pPartHeader->PartFourCC == hlsl::DFCC_PipelineStateValidation) {
// Update the size of PSV part.
DxilPartHeader *pPSVPartHeader =
(DxilPartHeader *)(pProgram2Data.data() + PartOffsets.back());
pPSVPartHeader->PartSize += ExtraSize;
Offset += ExtraSize;
}
}
// Copy header.
pHeader->ContainerSizeInBytes += ExtraSize;
memcpy(pProgram2Data.data(), pHeader, sizeof(hlsl::DxilContainerHeader));
// Copy partOffsets.
memcpy(pProgram2Data.data() + sizeof(hlsl::DxilContainerHeader),
PartOffsets.data(), PartOffsetsSize);
// Create a new Blob from pProgram2Data.
CComPtr<IDxcBlobEncoding> pProgram2;
CComPtr<IDxcLibrary> pLibrary;
VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary));
VERIFY_SUCCEEDED(pLibrary->CreateBlobWithEncodingFromPinned(
pProgram2Data.data(), pProgram2Data.size(), CP_UTF8, &pProgram2));
// Run validation on updated container.
CComPtr<IDxcOperationResult> pUpdatedResult;
VERIFY_SUCCEEDED(pValidator->Validate(pProgram2, Flags, &pUpdatedResult));
// Make sure the validation was fail.
VERIFY_IS_NOT_NULL(pUpdatedResult);
VERIFY_SUCCEEDED(pUpdatedResult->GetStatus(&status));
VERIFY_FAILED(status);
CheckOperationResultMsgs(
pUpdatedResult, {"In 'DxilContainer', 'PSV0 part' is not well-formed"},
/*maySucceedAnyway*/ false, /*bRegex*/ false);
}
TEST_F(ValidationTest, WrongPSVSizeOnZeros) {
if (!m_ver.m_InternalValidator)
if (m_ver.SkipDxilVersion(1, 8))
return;
CComPtr<IDxcBlob> pProgram;
CompileFile(L"..\\DXC\\dumpPSV_PS.hlsl", "ps_6_8", &pProgram);
CComPtr<IDxcValidator> pValidator;
CComPtr<IDxcOperationResult> pResult;
unsigned Flags = 0;
VERIFY_SUCCEEDED(
m_dllSupport.CreateInstance(CLSID_DxcValidator, &pValidator));
VERIFY_SUCCEEDED(pValidator->Validate(pProgram, Flags, &pResult));
// Make sure the validation was successful.
HRESULT status;
VERIFY_IS_NOT_NULL(pResult);
VERIFY_SUCCEEDED(pResult->GetStatus(&status));
VERIFY_SUCCEEDED(status);
hlsl::DxilContainerHeader *pHeader;
hlsl::DxilPartIterator pPartIter(nullptr, 0);
pHeader = (hlsl::DxilContainerHeader *)pProgram->GetBufferPointer();
// Make sure the PSV part exists.
pPartIter =
std::find_if(hlsl::begin(pHeader), hlsl::end(pHeader),
hlsl::DxilPartIsType(hlsl::DFCC_PipelineStateValidation));
VERIFY_ARE_NOT_EQUAL(hlsl::end(pHeader), pPartIter);
const DxilPartHeader *pPSVPart = (const DxilPartHeader *)(*pPartIter);
const uint32_t *PSVPtr = (const uint32_t *)GetDxilPartData(pPSVPart);
uint32_t PSVRuntimeInfo_size = *(PSVPtr++);
VERIFY_ARE_EQUAL(sizeof(PSVRuntimeInfo3), PSVRuntimeInfo_size);
PSVRuntimeInfo3 *PSVInfo =
const_cast<PSVRuntimeInfo3 *>((const PSVRuntimeInfo3 *)PSVPtr);
VERIFY_ARE_EQUAL(2u, PSVInfo->SigInputElements);
PSVPtr += PSVRuntimeInfo_size / 4;
uint32_t *ResourceCountPtr = const_cast<uint32_t *>(PSVPtr++);
uint32_t ResourceCount = *ResourceCountPtr;
VERIFY_ARE_NOT_EQUAL(0u, ResourceCount);
uint32_t ResourceBindingsSize = *(PSVPtr++);
PSVPtr += (ResourceCount * ResourceBindingsSize) / 4;
uint32_t *StringTableSizePtr = const_cast<uint32_t *>(PSVPtr++);
uint32_t StringTableSize = *StringTableSizePtr;
// Skip string table.
PSVPtr += StringTableSize / 4;
uint32_t *SemanticIndexTableEntriesPtr = const_cast<uint32_t *>(PSVPtr++);
uint32_t SemanticIndexTableEntries = *SemanticIndexTableEntriesPtr;
*SemanticIndexTableEntriesPtr = 0;
// Run validation on updated container.
CComPtr<IDxcOperationResult> pUpdatedResult1;
VERIFY_SUCCEEDED(pValidator->Validate(pProgram, Flags, &pUpdatedResult1));
// Make sure the validation was fail.
VERIFY_IS_NOT_NULL(pUpdatedResult1);
VERIFY_SUCCEEDED(pUpdatedResult1->GetStatus(&status));
VERIFY_FAILED(status);
CheckOperationResultMsgs(
pUpdatedResult1, {"In 'DxilContainer', 'PSV0 part' is not well-formed"},
/*maySucceedAnyway*/ false, /*bRegex*/ false);
*SemanticIndexTableEntriesPtr = SemanticIndexTableEntries;
*StringTableSizePtr = 0;
// Run validation on updated container.
CComPtr<IDxcOperationResult> pUpdatedResult2;
VERIFY_SUCCEEDED(pValidator->Validate(pProgram, Flags, &pUpdatedResult2));
// Make sure the validation was fail.
VERIFY_IS_NOT_NULL(pUpdatedResult2);
VERIFY_SUCCEEDED(pUpdatedResult2->GetStatus(&status));
VERIFY_FAILED(status);
CheckOperationResultMsgs(
pUpdatedResult2, {"In 'DxilContainer', 'PSV0 part' is not well-formed"},
/*maySucceedAnyway*/ false, /*bRegex*/ false);
*StringTableSizePtr = StringTableSize;
*ResourceCountPtr = 0;
// Run validation on updated container.
CComPtr<IDxcOperationResult> pUpdatedResult3;
VERIFY_SUCCEEDED(pValidator->Validate(pProgram, Flags, &pUpdatedResult3));
// Make sure the validation was fail.
VERIFY_IS_NOT_NULL(pUpdatedResult3);
VERIFY_SUCCEEDED(pUpdatedResult3->GetStatus(&status));
VERIFY_FAILED(status);
CheckOperationResultMsgs(
pUpdatedResult3, {"In 'DxilContainer', 'PSV0 part' is not well-formed"},
/*maySucceedAnyway*/ false, /*bRegex*/ false);
*ResourceCountPtr = ResourceCount;
}
TEST_F(ValidationTest, WrongPSVVersion) {
if (!m_ver.m_InternalValidator)
if (m_ver.SkipDxilVersion(1, 8))
return;
CComPtr<IDxcBlob> pProgram60;
std::vector<LPCWSTR> args;
args.emplace_back(L"-validator-version");
args.emplace_back(L"1.0");
CompileFile(L"..\\DXC\\dumpPSV_CS.hlsl", "cs_6_0", args.data(), args.size(),
&pProgram60);
CComPtr<IDxcValidator> pValidator;
CComPtr<IDxcOperationResult> pResult;
unsigned Flags = DxcValidatorFlags_InPlaceEdit;
VERIFY_SUCCEEDED(
m_dllSupport.CreateInstance(CLSID_DxcValidator, &pValidator));
VERIFY_SUCCEEDED(pValidator->Validate(pProgram60, Flags, &pResult));
// Make sure the validation was successful.
HRESULT status;
VERIFY_IS_NOT_NULL(pResult);
VERIFY_SUCCEEDED(pResult->GetStatus(&status));
VERIFY_SUCCEEDED(status);
hlsl::DxilContainerHeader *pHeader60;
hlsl::DxilPartIterator pPartIter(nullptr, 0);
pHeader60 = (hlsl::DxilContainerHeader *)pProgram60->GetBufferPointer();
// Make sure the PSV part exists.
pPartIter =
std::find_if(hlsl::begin(pHeader60), hlsl::end(pHeader60),
hlsl::DxilPartIsType(hlsl::DFCC_PipelineStateValidation));
VERIFY_ARE_NOT_EQUAL(hlsl::end(pHeader60), pPartIter);
CComPtr<IDxcBlob> pProgram68;
CompileFile(L"..\\DXC\\dumpPSV_CS.hlsl", "cs_6_8", &pProgram68);
CComPtr<IDxcOperationResult> pResult2;
VERIFY_SUCCEEDED(pValidator->Validate(pProgram68, Flags, &pResult2));
// Make sure the validation was successful.
VERIFY_IS_NOT_NULL(pResult);
VERIFY_SUCCEEDED(pResult->GetStatus(&status));
VERIFY_SUCCEEDED(status);
hlsl::DxilContainerHeader *pHeader68;
pHeader68 = (hlsl::DxilContainerHeader *)pProgram68->GetBufferPointer();
// Make sure the PSV part exists.
pPartIter =
std::find_if(hlsl::begin(pHeader68), hlsl::end(pHeader68),
hlsl::DxilPartIsType(hlsl::DFCC_PipelineStateValidation));
VERIFY_ARE_NOT_EQUAL(hlsl::end(pHeader68), pPartIter);
// Switch the PSV part between 6.0 to 6.8.
SimpleContainer Container60(pProgram60->GetBufferPointer());
SimpleContainer Container68(pProgram68->GetBufferPointer());
uint32_t Container60WithPSV68Size = sizeof(hlsl::DxilContainerHeader) +
pHeader60->PartCount * sizeof(uint32_t);
uint32_t Container68WithPSV60Size = sizeof(hlsl::DxilContainerHeader) +
pHeader60->PartCount * sizeof(uint32_t);
unsigned Container68PartSkipped = 0;
for (unsigned i = 0; i < pHeader60->PartCount; ++i) {
const DxilPartHeader *pPartHeader60 = Container60.PartHeaders[i];
const DxilPartHeader *pPartHeader68 =
Container68.PartHeaders[i + Container68PartSkipped];
if (pPartHeader68->PartFourCC == hlsl::DFCC_ShaderHash) {
Container68PartSkipped++;
pPartHeader68 = Container68.PartHeaders[i + Container68PartSkipped];
}
VERIFY_ARE_EQUAL(pPartHeader60->PartFourCC, pPartHeader68->PartFourCC);
Container60WithPSV68Size += sizeof(DxilPartHeader);
Container68WithPSV60Size += sizeof(DxilPartHeader);
if (pPartHeader60->PartFourCC == hlsl::DFCC_PipelineStateValidation) {
Container60WithPSV68Size += pPartHeader68->PartSize;
Container68WithPSV60Size += pPartHeader60->PartSize;
} else {
Container60WithPSV68Size += pPartHeader60->PartSize;
Container68WithPSV60Size += pPartHeader68->PartSize;
}
}
// Create mixed container.
std::vector<char> pProgram60WithPSV68Data(Container60WithPSV68Size, 0);
std::vector<char> pProgram68WithPSV60Data(Container68WithPSV60Size, 0);
uint32_t PartOffsetsSize = pHeader60->PartCount * sizeof(uint32_t);
uint32_t Offset60 = sizeof(hlsl::DxilContainerHeader) + PartOffsetsSize;
std::vector<uint32_t> PartOffsets60;
uint32_t Offset68 = sizeof(hlsl::DxilContainerHeader) + PartOffsetsSize;
std::vector<uint32_t> PartOffsets68;
Container68PartSkipped = 0;
for (unsigned i = 0; i < pHeader60->PartCount; ++i) {
PartOffsets60.emplace_back(Offset60);
PartOffsets68.emplace_back(Offset68);
const DxilPartHeader *pPartHeader60 = Container60.PartHeaders[i];
const DxilPartHeader *pPartHeader68 =
Container68.PartHeaders[i + Container68PartSkipped];
if (pPartHeader68->PartFourCC == hlsl::DFCC_ShaderHash) {
Container68PartSkipped++;
pPartHeader68 = Container68.PartHeaders[i + Container68PartSkipped];
}
if (pPartHeader60->PartFourCC == hlsl::DFCC_PipelineStateValidation) {
// Copy PSV part from 6.8 to 6.0.
memcpy(pProgram60WithPSV68Data.data() + Offset60, pPartHeader68,
sizeof(DxilPartHeader));
Offset60 += sizeof(DxilPartHeader);
memcpy(pProgram60WithPSV68Data.data() + Offset60,
GetDxilPartData(pPartHeader68), pPartHeader68->PartSize);
Offset60 += pPartHeader68->PartSize;
// Copy PSV part from 6.0 to 6.8.
memcpy(pProgram68WithPSV60Data.data() + Offset68, pPartHeader60,
sizeof(DxilPartHeader));
Offset68 += sizeof(DxilPartHeader);
memcpy(pProgram68WithPSV60Data.data() + Offset68,
GetDxilPartData(pPartHeader60), pPartHeader60->PartSize);
Offset68 += pPartHeader60->PartSize;
} else {
// Copy PSV part from 6.0 to 6.0.
memcpy(pProgram60WithPSV68Data.data() + Offset60, pPartHeader60,
sizeof(DxilPartHeader));
Offset60 += sizeof(DxilPartHeader);
memcpy(pProgram60WithPSV68Data.data() + Offset60,
GetDxilPartData(pPartHeader60), pPartHeader60->PartSize);
Offset60 += pPartHeader60->PartSize;
// Copy PSV part from 6.8 to 6.8.
memcpy(pProgram68WithPSV60Data.data() + Offset68, pPartHeader68,
sizeof(DxilPartHeader));
Offset68 += sizeof(DxilPartHeader);
memcpy(pProgram68WithPSV60Data.data() + Offset68,
GetDxilPartData(pPartHeader68), pPartHeader68->PartSize);
Offset68 += pPartHeader68->PartSize;
}
}
// Copy header.
VERIFY_ARE_EQUAL(Container60WithPSV68Size, Offset60);
pHeader60->ContainerSizeInBytes = Container60WithPSV68Size;
memcpy(pProgram60WithPSV68Data.data(), pHeader60,
sizeof(hlsl::DxilContainerHeader));
VERIFY_ARE_EQUAL(Container68WithPSV60Size, Offset68);
pHeader68->ContainerSizeInBytes = Container68WithPSV60Size;
pHeader68->PartCount -= Container68PartSkipped;
memcpy(pProgram68WithPSV60Data.data(), pHeader68,
sizeof(hlsl::DxilContainerHeader));
// Copy partOffsets.
memcpy(pProgram60WithPSV68Data.data() + sizeof(hlsl::DxilContainerHeader),
PartOffsets60.data(), PartOffsetsSize);
memcpy(pProgram68WithPSV60Data.data() + sizeof(hlsl::DxilContainerHeader),
PartOffsets68.data(), PartOffsetsSize);
// Create a new Blob.
CComPtr<IDxcBlobEncoding> pProgram60WithPSV68;
CComPtr<IDxcLibrary> pLibrary;
VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary));
VERIFY_SUCCEEDED(pLibrary->CreateBlobWithEncodingFromPinned(
pProgram60WithPSV68Data.data(), pProgram60WithPSV68Data.size(), CP_UTF8,
&pProgram60WithPSV68));
// Run validation on new containers.
CComPtr<IDxcOperationResult> p60WithPSV68Result;
VERIFY_SUCCEEDED(
pValidator->Validate(pProgram60WithPSV68, Flags, &p60WithPSV68Result));
// Make sure the validation was fail.
VERIFY_IS_NOT_NULL(p60WithPSV68Result);
VERIFY_SUCCEEDED(p60WithPSV68Result->GetStatus(&status));
VERIFY_FAILED(status);
CheckOperationResultMsgs(
p60WithPSV68Result,
{"DXIL container mismatch for 'PSVRuntimeInfoSize' between 'PSV0' "
"part:('52') and DXIL module:('24')"},
/*maySucceedAnyway*/ false, /*bRegex*/ false);
// Create a new Blob.
CComPtr<IDxcBlobEncoding> pProgram68WithPSV60;
VERIFY_SUCCEEDED(pLibrary->CreateBlobWithEncodingFromPinned(
pProgram68WithPSV60Data.data(), pProgram68WithPSV60Data.size(), CP_UTF8,
&pProgram68WithPSV60));
CComPtr<IDxcOperationResult> p68WithPSV60Result;
VERIFY_SUCCEEDED(
pValidator->Validate(pProgram68WithPSV60, Flags, &p68WithPSV60Result));
// Make sure the validation was fail.
VERIFY_IS_NOT_NULL(p68WithPSV60Result);
VERIFY_SUCCEEDED(p68WithPSV60Result->GetStatus(&status));
VERIFY_FAILED(status);
CheckOperationResultMsgs(
p68WithPSV60Result,
{"DXIL container mismatch for 'PSVRuntimeInfoSize' between 'PSV0' "
"part:('24') and DXIL module:('52')"},
/*maySucceedAnyway*/ false, /*bRegex*/ false);
}

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

@ -6933,6 +6933,11 @@ class db_dxil(object):
"DXIL Container Content is well-formed",
"In '%0', '%1' is not well-formed",
)
self.add_valrule_msg(
"Container.UnusedItemInTable",
"Items in Table must be used",
"In '%0', '%1' is not used",
)
self.add_valrule("Meta.Required", "Required metadata missing.")
self.add_valrule_msg(
"Meta.ComputeWithNode",