[NFC] Move DxilValidation to a dedicated folder. (#6849)
Move DxilValidation out of HLSL. Also move code to validate dxil container into DxilContainerValidation.cpp from DxilValidation.cpp. This is a preparatory step for #6817. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Родитель
f810e92e72
Коммит
0e7591a6ee
|
@ -17,7 +17,6 @@ configure_file(
|
|||
|
||||
add_subdirectory(DXIL)
|
||||
add_subdirectory(DxilContainer)
|
||||
add_subdirectory(HLSL)
|
||||
add_subdirectory(Support)
|
||||
add_subdirectory(Tracing)
|
||||
|
||||
|
|
|
@ -26,29 +26,7 @@ class DiagnosticInfo;
|
|||
|
||||
namespace hlsl {
|
||||
|
||||
#include "dxc/HLSL/DxilValidation.inc"
|
||||
|
||||
const char *GetValidationRuleText(ValidationRule value);
|
||||
void GetValidationVersion(unsigned *pMajor, unsigned *pMinor);
|
||||
HRESULT ValidateDxilModule(llvm::Module *pModule, llvm::Module *pDebugModule);
|
||||
|
||||
// DXIL Container Verification Functions (return false on failure)
|
||||
|
||||
bool VerifySignatureMatches(llvm::Module *pModule,
|
||||
hlsl::DXIL::SignatureKind SigKind,
|
||||
const void *pSigData, uint32_t SigSize);
|
||||
|
||||
// PSV = data for Pipeline State Validation
|
||||
bool VerifyPSVMatches(llvm::Module *pModule, const void *pPSVData,
|
||||
uint32_t PSVSize);
|
||||
|
||||
// PSV = data for Pipeline State Validation
|
||||
bool VerifyRDATMatches(llvm::Module *pModule, const void *pRDATData,
|
||||
uint32_t RDATSize);
|
||||
|
||||
bool VerifyFeatureInfoMatches(llvm::Module *pModule,
|
||||
const void *pFeatureInfoData,
|
||||
uint32_t FeatureInfoSize);
|
||||
|
||||
// Validate the container parts, assuming supplied module is valid, loaded from
|
||||
// the container provided
|
||||
|
@ -106,4 +84,5 @@ public:
|
|||
static void PrintDiagnosticHandler(const llvm::DiagnosticInfo &DI,
|
||||
void *Context);
|
||||
};
|
||||
|
||||
} // namespace hlsl
|
|
@ -1 +0,0 @@
|
|||
add_hlsl_hctgen(DxilValidationInc OUTPUT DxilValidation.inc BUILD_DIR)
|
|
@ -30,6 +30,7 @@ add_subdirectory(DxilPdbInfo) # HLSL Change
|
|||
add_subdirectory(DxilPIXPasses) # HLSL Change
|
||||
add_subdirectory(DxilDia) # HLSL Change
|
||||
add_subdirectory(DxilRootSignature) # HLSL Change
|
||||
add_subdirectory(DxilValidation) # HLSL Change
|
||||
add_subdirectory(DxcBindingTable) # HLSL Change
|
||||
add_subdirectory(DxrFallback) # HLSL Change
|
||||
add_subdirectory(DxilCompression) # HLSL Change
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
# This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
add_hlsl_hctgen(DxilValidationInc OUTPUT DxilValidation.inc BUILD_DIR)
|
||||
add_hlsl_hctgen(DxilValidation OUTPUT DxilValidationImpl.inc BUILD_DIR)
|
||||
|
||||
add_llvm_library(LLVMDxilValidation
|
||||
DxilContainerValidation.cpp
|
||||
DxilValidation.cpp
|
||||
DxilValidationUtils.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${LLVM_MAIN_INCLUDE_DIR}/llvm/IR
|
||||
)
|
||||
|
||||
add_dependencies(LLVMDxilValidation intrinsics_gen)
|
|
@ -0,0 +1,705 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// DxilContainerValidation.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. //
|
||||
// //
|
||||
// This file provides support for validating DXIL container. //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "dxc/Support/FileIOHelper.h"
|
||||
#include "dxc/Support/Global.h"
|
||||
#include "dxc/Support/WinIncludes.h"
|
||||
|
||||
#include "dxc/DxilContainer/DxilContainer.h"
|
||||
#include "dxc/DxilContainer/DxilContainerAssembler.h"
|
||||
#include "dxc/DxilContainer/DxilPipelineStateValidation.h"
|
||||
#include "dxc/DxilContainer/DxilRuntimeReflection.h"
|
||||
#include "dxc/DxilRootSignature/DxilRootSignature.h"
|
||||
#include "dxc/DxilValidation/DxilValidation.h"
|
||||
|
||||
#include "dxc/DXIL/DxilModule.h"
|
||||
#include "dxc/DXIL/DxilUtil.h"
|
||||
|
||||
#include "llvm/Bitcode/ReaderWriter.h"
|
||||
#include "llvm/IR/DiagnosticPrinter.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include "DxilValidationUtils.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
using std::unique_ptr;
|
||||
using std::unordered_set;
|
||||
using std::vector;
|
||||
|
||||
namespace {
|
||||
|
||||
// Utility class for setting and restoring the diagnostic context so we may
|
||||
// capture errors/warnings
|
||||
struct DiagRestore {
|
||||
LLVMContext *Ctx = nullptr;
|
||||
void *OrigDiagContext;
|
||||
LLVMContext::DiagnosticHandlerTy OrigHandler;
|
||||
|
||||
DiagRestore(llvm::LLVMContext &InputCtx, void *DiagContext) : Ctx(&InputCtx) {
|
||||
init(DiagContext);
|
||||
}
|
||||
DiagRestore(Module *M, void *DiagContext) {
|
||||
if (!M)
|
||||
return;
|
||||
Ctx = &M->getContext();
|
||||
init(DiagContext);
|
||||
}
|
||||
~DiagRestore() {
|
||||
if (!Ctx)
|
||||
return;
|
||||
Ctx->setDiagnosticHandler(OrigHandler, OrigDiagContext);
|
||||
}
|
||||
|
||||
private:
|
||||
void init(void *DiagContext) {
|
||||
OrigHandler = Ctx->getDiagnosticHandler();
|
||||
OrigDiagContext = Ctx->getDiagnosticContext();
|
||||
Ctx->setDiagnosticHandler(
|
||||
hlsl::PrintDiagnosticContext::PrintDiagnosticHandler, DiagContext);
|
||||
}
|
||||
};
|
||||
|
||||
static void emitDxilDiag(LLVMContext &Ctx, const char *str) {
|
||||
hlsl::dxilutil::EmitErrorOnContext(Ctx, str);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace hlsl {
|
||||
|
||||
// DXIL Container Verification Functions
|
||||
|
||||
static void VerifyBlobPartMatches(ValidationContext &ValCtx, LPCSTR pName,
|
||||
DxilPartWriter *pWriter, const void *pData,
|
||||
uint32_t Size) {
|
||||
if (!pData && pWriter->size()) {
|
||||
// No blob part, but writer says non-zero size is expected.
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartMissing, {pName});
|
||||
return;
|
||||
}
|
||||
|
||||
// Compare sizes
|
||||
if (pWriter->size() != Size) {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartMatches, {pName});
|
||||
return;
|
||||
}
|
||||
|
||||
if (Size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
CComPtr<AbstractMemoryStream> pOutputStream;
|
||||
IFT(CreateMemoryStream(DxcGetThreadMallocNoRef(), &pOutputStream));
|
||||
pOutputStream->Reserve(Size);
|
||||
|
||||
pWriter->write(pOutputStream);
|
||||
DXASSERT(pOutputStream->GetPtrSize() == Size,
|
||||
"otherwise, DxilPartWriter misreported size");
|
||||
|
||||
if (memcmp(pData, pOutputStream->GetPtr(), Size)) {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartMatches, {pName});
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void VerifySignatureMatches(ValidationContext &ValCtx,
|
||||
DXIL::SignatureKind SigKind,
|
||||
const void *pSigData, uint32_t SigSize) {
|
||||
// Generate corresponding signature from module and memcmp
|
||||
|
||||
const char *pName = nullptr;
|
||||
switch (SigKind) {
|
||||
case hlsl::DXIL::SignatureKind::Input:
|
||||
pName = "Program Input Signature";
|
||||
break;
|
||||
case hlsl::DXIL::SignatureKind::Output:
|
||||
pName = "Program Output Signature";
|
||||
break;
|
||||
case hlsl::DXIL::SignatureKind::PatchConstOrPrim:
|
||||
if (ValCtx.DxilMod.GetShaderModel()->GetKind() == DXIL::ShaderKind::Mesh)
|
||||
pName = "Program Primitive Signature";
|
||||
else
|
||||
pName = "Program Patch Constant Signature";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
unique_ptr<DxilPartWriter> pWriter(
|
||||
NewProgramSignatureWriter(ValCtx.DxilMod, SigKind));
|
||||
VerifyBlobPartMatches(ValCtx, pName, pWriter.get(), pSigData, SigSize);
|
||||
}
|
||||
|
||||
bool VerifySignatureMatches(llvm::Module *pModule, DXIL::SignatureKind SigKind,
|
||||
const void *pSigData, uint32_t SigSize) {
|
||||
ValidationContext ValCtx(*pModule, nullptr, pModule->GetOrCreateDxilModule());
|
||||
VerifySignatureMatches(ValCtx, SigKind, pSigData, SigSize);
|
||||
return !ValCtx.Failed;
|
||||
}
|
||||
|
||||
static void VerifyPSVMatches(ValidationContext &ValCtx, const void *pPSVData,
|
||||
uint32_t PSVSize) {
|
||||
uint32_t PSVVersion =
|
||||
MAX_PSV_VERSION; // This should be set to the newest version
|
||||
unique_ptr<DxilPartWriter> pWriter(NewPSVWriter(ValCtx.DxilMod, PSVVersion));
|
||||
// Try each version in case an earlier version matches module
|
||||
while (PSVVersion && pWriter->size() != PSVSize) {
|
||||
PSVVersion--;
|
||||
pWriter.reset(NewPSVWriter(ValCtx.DxilMod, PSVVersion));
|
||||
}
|
||||
// generate PSV data from module and memcmp
|
||||
VerifyBlobPartMatches(ValCtx, "Pipeline State Validation", pWriter.get(),
|
||||
pPSVData, PSVSize);
|
||||
}
|
||||
|
||||
static void VerifyFeatureInfoMatches(ValidationContext &ValCtx,
|
||||
const void *pFeatureInfoData,
|
||||
uint32_t FeatureInfoSize) {
|
||||
// generate Feature Info data from module and memcmp
|
||||
unique_ptr<DxilPartWriter> pWriter(NewFeatureInfoWriter(ValCtx.DxilMod));
|
||||
VerifyBlobPartMatches(ValCtx, "Feature Info", pWriter.get(), pFeatureInfoData,
|
||||
FeatureInfoSize);
|
||||
}
|
||||
|
||||
// return true if the pBlob is a valid, well-formed CompilerVersion part, false
|
||||
// otherwise
|
||||
bool ValidateCompilerVersionPart(const void *pBlobPtr, UINT blobSize) {
|
||||
// The hlsl::DxilCompilerVersion struct is always 16 bytes. (2 2-byte
|
||||
// uint16's, 3 4-byte uint32's) The blob size should absolutely never be less
|
||||
// than 16 bytes.
|
||||
if (blobSize < sizeof(hlsl::DxilCompilerVersion)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const hlsl::DxilCompilerVersion *pDCV =
|
||||
(const hlsl::DxilCompilerVersion *)pBlobPtr;
|
||||
if (pDCV->VersionStringListSizeInBytes == 0) {
|
||||
// No version strings, just make sure there is no extra space.
|
||||
return blobSize == sizeof(hlsl::DxilCompilerVersion);
|
||||
}
|
||||
|
||||
// after this point, we know VersionStringListSizeInBytes >= 1, because it is
|
||||
// a UINT
|
||||
|
||||
UINT EndOfVersionStringIndex =
|
||||
sizeof(hlsl::DxilCompilerVersion) + pDCV->VersionStringListSizeInBytes;
|
||||
// Make sure that the buffer size is large enough to contain both the DCV
|
||||
// struct and the version string but not any larger than necessary
|
||||
if (PSVALIGN4(EndOfVersionStringIndex) != blobSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *VersionStringsListData =
|
||||
(const char *)pBlobPtr + sizeof(hlsl::DxilCompilerVersion);
|
||||
UINT VersionStringListSizeInBytes = pDCV->VersionStringListSizeInBytes;
|
||||
|
||||
// now make sure that any pad bytes that were added are null-terminators.
|
||||
for (UINT i = VersionStringListSizeInBytes;
|
||||
i < blobSize - sizeof(hlsl::DxilCompilerVersion); i++) {
|
||||
if (VersionStringsListData[i] != '\0') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Now, version string validation
|
||||
// first, the final byte of the string should always be null-terminator so
|
||||
// that the string ends
|
||||
if (VersionStringsListData[VersionStringListSizeInBytes - 1] != '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// construct the first string
|
||||
// data format for VersionString can be see in the definition for the
|
||||
// DxilCompilerVersion struct. summary: 2 strings that each end with the null
|
||||
// terminator, and [0-3] null terminators after the final null terminator
|
||||
StringRef firstStr(VersionStringsListData);
|
||||
|
||||
// if the second string exists, attempt to construct it.
|
||||
if (VersionStringListSizeInBytes > (firstStr.size() + 1)) {
|
||||
StringRef secondStr(VersionStringsListData + firstStr.size() + 1);
|
||||
|
||||
// the VersionStringListSizeInBytes member should be exactly equal to the
|
||||
// two string lengths, plus the 2 null terminator bytes.
|
||||
if (VersionStringListSizeInBytes !=
|
||||
firstStr.size() + secondStr.size() + 2) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// the VersionStringListSizeInBytes member should be exactly equal to the
|
||||
// first string length, plus the 1 null terminator byte.
|
||||
if (VersionStringListSizeInBytes != firstStr.size() + 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void VerifyRDATMatches(ValidationContext &ValCtx, const void *pRDATData,
|
||||
uint32_t RDATSize) {
|
||||
const char *PartName = "Runtime Data (RDAT)";
|
||||
RDAT::DxilRuntimeData rdat(pRDATData, RDATSize);
|
||||
if (!rdat.Validate()) {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartMatches, {PartName});
|
||||
return;
|
||||
}
|
||||
|
||||
// If DxilModule subobjects already loaded, validate these against the RDAT
|
||||
// blob, otherwise, load subobject into DxilModule to generate reference RDAT.
|
||||
if (!ValCtx.DxilMod.GetSubobjects()) {
|
||||
auto table = rdat.GetSubobjectTable();
|
||||
if (table && table.Count() > 0) {
|
||||
ValCtx.DxilMod.ResetSubobjects(new DxilSubobjects());
|
||||
if (!LoadSubobjectsFromRDAT(*ValCtx.DxilMod.GetSubobjects(), rdat)) {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartMatches,
|
||||
{PartName});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unique_ptr<DxilPartWriter> pWriter(NewRDATWriter(ValCtx.DxilMod));
|
||||
VerifyBlobPartMatches(ValCtx, PartName, pWriter.get(), pRDATData, RDATSize);
|
||||
}
|
||||
|
||||
bool VerifyRDATMatches(llvm::Module *pModule, const void *pRDATData,
|
||||
uint32_t RDATSize) {
|
||||
ValidationContext ValCtx(*pModule, nullptr, pModule->GetOrCreateDxilModule());
|
||||
VerifyRDATMatches(ValCtx, pRDATData, RDATSize);
|
||||
return !ValCtx.Failed;
|
||||
}
|
||||
|
||||
bool VerifyFeatureInfoMatches(llvm::Module *pModule,
|
||||
const void *pFeatureInfoData,
|
||||
uint32_t FeatureInfoSize) {
|
||||
ValidationContext ValCtx(*pModule, nullptr, pModule->GetOrCreateDxilModule());
|
||||
VerifyFeatureInfoMatches(ValCtx, pFeatureInfoData, FeatureInfoSize);
|
||||
return !ValCtx.Failed;
|
||||
}
|
||||
|
||||
HRESULT ValidateDxilContainerParts(llvm::Module *pModule,
|
||||
llvm::Module *pDebugModule,
|
||||
const DxilContainerHeader *pContainer,
|
||||
uint32_t ContainerSize) {
|
||||
|
||||
DXASSERT_NOMSG(pModule);
|
||||
if (!pContainer || !IsValidDxilContainer(pContainer, ContainerSize)) {
|
||||
return DXC_E_CONTAINER_INVALID;
|
||||
}
|
||||
|
||||
DxilModule *pDxilModule = DxilModule::TryGetDxilModule(pModule);
|
||||
if (!pDxilModule) {
|
||||
return DXC_E_IR_VERIFICATION_FAILED;
|
||||
}
|
||||
|
||||
ValidationContext ValCtx(*pModule, pDebugModule, *pDxilModule);
|
||||
|
||||
DXIL::ShaderKind ShaderKind = pDxilModule->GetShaderModel()->GetKind();
|
||||
bool bTessOrMesh = ShaderKind == DXIL::ShaderKind::Hull ||
|
||||
ShaderKind == DXIL::ShaderKind::Domain ||
|
||||
ShaderKind == DXIL::ShaderKind::Mesh;
|
||||
|
||||
std::unordered_set<uint32_t> FourCCFound;
|
||||
const DxilPartHeader *pRootSignaturePart = nullptr;
|
||||
const DxilPartHeader *pPSVPart = nullptr;
|
||||
|
||||
for (auto it = begin(pContainer), itEnd = end(pContainer); it != itEnd;
|
||||
++it) {
|
||||
const DxilPartHeader *pPart = *it;
|
||||
|
||||
char szFourCC[5];
|
||||
PartKindToCharArray(pPart->PartFourCC, szFourCC);
|
||||
if (FourCCFound.find(pPart->PartFourCC) != FourCCFound.end()) {
|
||||
// Two parts with same FourCC found
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartRepeated, {szFourCC});
|
||||
continue;
|
||||
}
|
||||
FourCCFound.insert(pPart->PartFourCC);
|
||||
|
||||
switch (pPart->PartFourCC) {
|
||||
case DFCC_InputSignature:
|
||||
if (ValCtx.isLibProfile) {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartInvalid,
|
||||
{szFourCC});
|
||||
} else {
|
||||
VerifySignatureMatches(ValCtx, DXIL::SignatureKind::Input,
|
||||
GetDxilPartData(pPart), pPart->PartSize);
|
||||
}
|
||||
break;
|
||||
case DFCC_OutputSignature:
|
||||
if (ValCtx.isLibProfile) {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartInvalid,
|
||||
{szFourCC});
|
||||
} else {
|
||||
VerifySignatureMatches(ValCtx, DXIL::SignatureKind::Output,
|
||||
GetDxilPartData(pPart), pPart->PartSize);
|
||||
}
|
||||
break;
|
||||
case DFCC_PatchConstantSignature:
|
||||
if (ValCtx.isLibProfile) {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartInvalid,
|
||||
{szFourCC});
|
||||
} else {
|
||||
if (bTessOrMesh) {
|
||||
VerifySignatureMatches(ValCtx, DXIL::SignatureKind::PatchConstOrPrim,
|
||||
GetDxilPartData(pPart), pPart->PartSize);
|
||||
} else {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartMatches,
|
||||
{"Program Patch Constant Signature"});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DFCC_FeatureInfo:
|
||||
VerifyFeatureInfoMatches(ValCtx, GetDxilPartData(pPart), pPart->PartSize);
|
||||
break;
|
||||
case DFCC_CompilerVersion:
|
||||
// This blob is either a PDB, or a library profile
|
||||
if (ValCtx.isLibProfile) {
|
||||
if (!ValidateCompilerVersionPart((void *)GetDxilPartData(pPart),
|
||||
pPart->PartSize)) {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartInvalid,
|
||||
{szFourCC});
|
||||
}
|
||||
} else {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartInvalid,
|
||||
{szFourCC});
|
||||
}
|
||||
break;
|
||||
|
||||
case DFCC_RootSignature:
|
||||
pRootSignaturePart = pPart;
|
||||
if (ValCtx.isLibProfile) {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartInvalid,
|
||||
{szFourCC});
|
||||
}
|
||||
break;
|
||||
case DFCC_PipelineStateValidation:
|
||||
pPSVPart = pPart;
|
||||
if (ValCtx.isLibProfile) {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartInvalid,
|
||||
{szFourCC});
|
||||
} else {
|
||||
VerifyPSVMatches(ValCtx, GetDxilPartData(pPart), pPart->PartSize);
|
||||
}
|
||||
break;
|
||||
|
||||
// Skip these
|
||||
case DFCC_ResourceDef:
|
||||
case DFCC_ShaderStatistics:
|
||||
case DFCC_PrivateData:
|
||||
case DFCC_DXIL:
|
||||
case DFCC_ShaderDebugInfoDXIL:
|
||||
case DFCC_ShaderDebugName:
|
||||
continue;
|
||||
|
||||
case DFCC_ShaderHash:
|
||||
if (pPart->PartSize != sizeof(DxilShaderHash)) {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartInvalid,
|
||||
{szFourCC});
|
||||
}
|
||||
break;
|
||||
|
||||
// Runtime Data (RDAT) for libraries
|
||||
case DFCC_RuntimeData:
|
||||
if (ValCtx.isLibProfile) {
|
||||
// TODO: validate without exact binary comparison of serialized data
|
||||
// - support earlier versions
|
||||
// - verify no newer record versions than known here (size no larger
|
||||
// than newest version)
|
||||
// - verify all data makes sense and matches expectations based on
|
||||
// module
|
||||
VerifyRDATMatches(ValCtx, GetDxilPartData(pPart), pPart->PartSize);
|
||||
} else {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartInvalid,
|
||||
{szFourCC});
|
||||
}
|
||||
break;
|
||||
|
||||
case DFCC_Container:
|
||||
default:
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartInvalid, {szFourCC});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify required parts found
|
||||
if (ValCtx.isLibProfile) {
|
||||
if (FourCCFound.find(DFCC_RuntimeData) == FourCCFound.end()) {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartMissing,
|
||||
{"Runtime Data (RDAT)"});
|
||||
}
|
||||
} else {
|
||||
if (FourCCFound.find(DFCC_InputSignature) == FourCCFound.end()) {
|
||||
VerifySignatureMatches(ValCtx, DXIL::SignatureKind::Input, nullptr, 0);
|
||||
}
|
||||
if (FourCCFound.find(DFCC_OutputSignature) == FourCCFound.end()) {
|
||||
VerifySignatureMatches(ValCtx, DXIL::SignatureKind::Output, nullptr, 0);
|
||||
}
|
||||
if (bTessOrMesh &&
|
||||
FourCCFound.find(DFCC_PatchConstantSignature) == FourCCFound.end() &&
|
||||
pDxilModule->GetPatchConstOrPrimSignature().GetElements().size()) {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartMissing,
|
||||
{"Program Patch Constant Signature"});
|
||||
}
|
||||
if (FourCCFound.find(DFCC_FeatureInfo) == FourCCFound.end()) {
|
||||
// Could be optional, but RS1 runtime doesn't handle this case properly.
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartMissing,
|
||||
{"Feature Info"});
|
||||
}
|
||||
|
||||
// Validate Root Signature
|
||||
if (pPSVPart) {
|
||||
if (pRootSignaturePart) {
|
||||
std::string diagStr;
|
||||
raw_string_ostream DiagStream(diagStr);
|
||||
try {
|
||||
RootSignatureHandle RS;
|
||||
RS.LoadSerialized(
|
||||
(const uint8_t *)GetDxilPartData(pRootSignaturePart),
|
||||
pRootSignaturePart->PartSize);
|
||||
RS.Deserialize();
|
||||
IFTBOOL(VerifyRootSignatureWithShaderPSV(
|
||||
RS.GetDesc(), pDxilModule->GetShaderModel()->GetKind(),
|
||||
GetDxilPartData(pPSVPart), pPSVPart->PartSize,
|
||||
DiagStream),
|
||||
DXC_E_INCORRECT_ROOT_SIGNATURE);
|
||||
} catch (...) {
|
||||
ValCtx.EmitError(ValidationRule::ContainerRootSignatureIncompatible);
|
||||
emitDxilDiag(pModule->getContext(), DiagStream.str().c_str());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ValCtx.EmitFormatError(ValidationRule::ContainerPartMissing,
|
||||
{"Pipeline State Validation"});
|
||||
}
|
||||
}
|
||||
|
||||
if (ValCtx.Failed) {
|
||||
return DXC_E_MALFORMED_CONTAINER;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT FindDxilPart(const void *pContainerBytes, uint32_t ContainerSize,
|
||||
DxilFourCC FourCC, const DxilPartHeader **ppPart) {
|
||||
|
||||
const DxilContainerHeader *pContainer =
|
||||
IsDxilContainerLike(pContainerBytes, ContainerSize);
|
||||
|
||||
if (!pContainer) {
|
||||
IFR(DXC_E_CONTAINER_INVALID);
|
||||
}
|
||||
if (!IsValidDxilContainer(pContainer, ContainerSize)) {
|
||||
IFR(DXC_E_CONTAINER_INVALID);
|
||||
}
|
||||
|
||||
DxilPartIterator it =
|
||||
std::find_if(begin(pContainer), end(pContainer), DxilPartIsType(FourCC));
|
||||
if (it == end(pContainer)) {
|
||||
IFR(DXC_E_CONTAINER_MISSING_DXIL);
|
||||
}
|
||||
|
||||
const DxilProgramHeader *pProgramHeader =
|
||||
reinterpret_cast<const DxilProgramHeader *>(GetDxilPartData(*it));
|
||||
if (!IsValidDxilProgramHeader(pProgramHeader, (*it)->PartSize)) {
|
||||
IFR(DXC_E_CONTAINER_INVALID);
|
||||
}
|
||||
|
||||
*ppPart = *it;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ValidateLoadModule(const char *pIL, uint32_t ILLength,
|
||||
unique_ptr<llvm::Module> &pModule, LLVMContext &Ctx,
|
||||
llvm::raw_ostream &DiagStream, unsigned bLazyLoad) {
|
||||
|
||||
llvm::DiagnosticPrinterRawOStream DiagPrinter(DiagStream);
|
||||
PrintDiagnosticContext DiagContext(DiagPrinter);
|
||||
DiagRestore DR(Ctx, &DiagContext);
|
||||
|
||||
std::unique_ptr<llvm::MemoryBuffer> pBitcodeBuf;
|
||||
pBitcodeBuf.reset(llvm::MemoryBuffer::getMemBuffer(
|
||||
llvm::StringRef(pIL, ILLength), "", false)
|
||||
.release());
|
||||
|
||||
ErrorOr<std::unique_ptr<Module>> loadedModuleResult =
|
||||
bLazyLoad == 0
|
||||
? llvm::parseBitcodeFile(pBitcodeBuf->getMemBufferRef(), Ctx, nullptr,
|
||||
true /*Track Bitstream*/)
|
||||
: llvm::getLazyBitcodeModule(std::move(pBitcodeBuf), Ctx, nullptr,
|
||||
false, true /*Track Bitstream*/);
|
||||
|
||||
// DXIL disallows some LLVM bitcode constructs, like unaccounted-for
|
||||
// sub-blocks. These appear as warnings, which the validator should reject.
|
||||
if (DiagContext.HasErrors() || DiagContext.HasWarnings() ||
|
||||
loadedModuleResult.getError())
|
||||
return DXC_E_IR_VERIFICATION_FAILED;
|
||||
|
||||
pModule = std::move(loadedModuleResult.get());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ValidateDxilBitcode(const char *pIL, uint32_t ILLength,
|
||||
llvm::raw_ostream &DiagStream) {
|
||||
|
||||
LLVMContext Ctx;
|
||||
std::unique_ptr<llvm::Module> pModule;
|
||||
|
||||
llvm::DiagnosticPrinterRawOStream DiagPrinter(DiagStream);
|
||||
PrintDiagnosticContext DiagContext(DiagPrinter);
|
||||
Ctx.setDiagnosticHandler(PrintDiagnosticContext::PrintDiagnosticHandler,
|
||||
&DiagContext, true);
|
||||
|
||||
HRESULT hr;
|
||||
if (FAILED(hr = ValidateLoadModule(pIL, ILLength, pModule, Ctx, DiagStream,
|
||||
/*bLazyLoad*/ false)))
|
||||
return hr;
|
||||
|
||||
if (FAILED(hr = ValidateDxilModule(pModule.get(), nullptr)))
|
||||
return hr;
|
||||
|
||||
DxilModule &dxilModule = pModule->GetDxilModule();
|
||||
auto &SerializedRootSig = dxilModule.GetSerializedRootSignature();
|
||||
if (!SerializedRootSig.empty()) {
|
||||
unique_ptr<DxilPartWriter> pWriter(NewPSVWriter(dxilModule));
|
||||
DXASSERT_NOMSG(pWriter->size());
|
||||
CComPtr<AbstractMemoryStream> pOutputStream;
|
||||
IFT(CreateMemoryStream(DxcGetThreadMallocNoRef(), &pOutputStream));
|
||||
pOutputStream->Reserve(pWriter->size());
|
||||
pWriter->write(pOutputStream);
|
||||
DxilVersionedRootSignature desc;
|
||||
try {
|
||||
DeserializeRootSignature(SerializedRootSig.data(),
|
||||
SerializedRootSig.size(), desc.get_address_of());
|
||||
if (!desc.get()) {
|
||||
return DXC_E_INCORRECT_ROOT_SIGNATURE;
|
||||
}
|
||||
IFTBOOL(VerifyRootSignatureWithShaderPSV(
|
||||
desc.get(), dxilModule.GetShaderModel()->GetKind(),
|
||||
pOutputStream->GetPtr(), pWriter->size(), DiagStream),
|
||||
DXC_E_INCORRECT_ROOT_SIGNATURE);
|
||||
} catch (...) {
|
||||
return DXC_E_INCORRECT_ROOT_SIGNATURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (DiagContext.HasErrors() || DiagContext.HasWarnings()) {
|
||||
return DXC_E_IR_VERIFICATION_FAILED;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT ValidateLoadModuleFromContainer(
|
||||
const void *pContainer, uint32_t ContainerSize,
|
||||
std::unique_ptr<llvm::Module> &pModule,
|
||||
std::unique_ptr<llvm::Module> &pDebugModule, llvm::LLVMContext &Ctx,
|
||||
LLVMContext &DbgCtx, llvm::raw_ostream &DiagStream, unsigned bLazyLoad) {
|
||||
llvm::DiagnosticPrinterRawOStream DiagPrinter(DiagStream);
|
||||
PrintDiagnosticContext DiagContext(DiagPrinter);
|
||||
DiagRestore DR(Ctx, &DiagContext);
|
||||
DiagRestore DR2(DbgCtx, &DiagContext);
|
||||
|
||||
const DxilPartHeader *pPart = nullptr;
|
||||
IFR(FindDxilPart(pContainer, ContainerSize, DFCC_DXIL, &pPart));
|
||||
|
||||
const char *pIL = nullptr;
|
||||
uint32_t ILLength = 0;
|
||||
GetDxilProgramBitcode(
|
||||
reinterpret_cast<const DxilProgramHeader *>(GetDxilPartData(pPart)), &pIL,
|
||||
&ILLength);
|
||||
|
||||
IFR(ValidateLoadModule(pIL, ILLength, pModule, Ctx, DiagStream, bLazyLoad));
|
||||
|
||||
HRESULT hr;
|
||||
const DxilPartHeader *pDbgPart = nullptr;
|
||||
if (FAILED(hr = FindDxilPart(pContainer, ContainerSize,
|
||||
DFCC_ShaderDebugInfoDXIL, &pDbgPart)) &&
|
||||
hr != DXC_E_CONTAINER_MISSING_DXIL) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (pDbgPart) {
|
||||
GetDxilProgramBitcode(
|
||||
reinterpret_cast<const DxilProgramHeader *>(GetDxilPartData(pDbgPart)),
|
||||
&pIL, &ILLength);
|
||||
if (FAILED(hr = ValidateLoadModule(pIL, ILLength, pDebugModule, DbgCtx,
|
||||
DiagStream, bLazyLoad))) {
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ValidateLoadModuleFromContainer(
|
||||
const void *pContainer, uint32_t ContainerSize,
|
||||
std::unique_ptr<llvm::Module> &pModule,
|
||||
std::unique_ptr<llvm::Module> &pDebugModule, llvm::LLVMContext &Ctx,
|
||||
llvm::LLVMContext &DbgCtx, llvm::raw_ostream &DiagStream) {
|
||||
return ValidateLoadModuleFromContainer(pContainer, ContainerSize, pModule,
|
||||
pDebugModule, Ctx, DbgCtx, DiagStream,
|
||||
/*bLazyLoad*/ false);
|
||||
}
|
||||
// Lazy loads module from container, validating load, but not module.
|
||||
HRESULT ValidateLoadModuleFromContainerLazy(
|
||||
const void *pContainer, uint32_t ContainerSize,
|
||||
std::unique_ptr<llvm::Module> &pModule,
|
||||
std::unique_ptr<llvm::Module> &pDebugModule, llvm::LLVMContext &Ctx,
|
||||
llvm::LLVMContext &DbgCtx, llvm::raw_ostream &DiagStream) {
|
||||
return ValidateLoadModuleFromContainer(pContainer, ContainerSize, pModule,
|
||||
pDebugModule, Ctx, DbgCtx, DiagStream,
|
||||
/*bLazyLoad*/ true);
|
||||
}
|
||||
|
||||
HRESULT ValidateDxilContainer(const void *pContainer, uint32_t ContainerSize,
|
||||
llvm::Module *pDebugModule,
|
||||
llvm::raw_ostream &DiagStream) {
|
||||
LLVMContext Ctx, DbgCtx;
|
||||
std::unique_ptr<llvm::Module> pModule, pDebugModuleInContainer;
|
||||
|
||||
llvm::DiagnosticPrinterRawOStream DiagPrinter(DiagStream);
|
||||
PrintDiagnosticContext DiagContext(DiagPrinter);
|
||||
Ctx.setDiagnosticHandler(PrintDiagnosticContext::PrintDiagnosticHandler,
|
||||
&DiagContext, true);
|
||||
DbgCtx.setDiagnosticHandler(PrintDiagnosticContext::PrintDiagnosticHandler,
|
||||
&DiagContext, true);
|
||||
|
||||
DiagRestore DR(pDebugModule, &DiagContext);
|
||||
|
||||
IFR(ValidateLoadModuleFromContainer(pContainer, ContainerSize, pModule,
|
||||
pDebugModuleInContainer, Ctx, DbgCtx,
|
||||
DiagStream));
|
||||
|
||||
if (pDebugModuleInContainer)
|
||||
pDebugModule = pDebugModuleInContainer.get();
|
||||
|
||||
// Validate DXIL Module
|
||||
IFR(ValidateDxilModule(pModule.get(), pDebugModule));
|
||||
|
||||
if (DiagContext.HasErrors() || DiagContext.HasWarnings()) {
|
||||
return DXC_E_IR_VERIFICATION_FAILED;
|
||||
}
|
||||
|
||||
return ValidateDxilContainerParts(
|
||||
pModule.get(), pDebugModule,
|
||||
IsDxilContainerLike(pContainer, ContainerSize), ContainerSize);
|
||||
}
|
||||
|
||||
HRESULT ValidateDxilContainer(const void *pContainer, uint32_t ContainerSize,
|
||||
llvm::raw_ostream &DiagStream) {
|
||||
return ValidateDxilContainer(pContainer, ContainerSize, nullptr, DiagStream);
|
||||
}
|
||||
} // namespace hlsl
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,526 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// DxilValidationUttils.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. //
|
||||
// //
|
||||
// This file provides utils for validating DXIL. //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "DxilValidationUtils.h"
|
||||
|
||||
#include "dxc/DXIL/DxilEntryProps.h"
|
||||
#include "dxc/DXIL/DxilInstructions.h"
|
||||
#include "dxc/DXIL/DxilModule.h"
|
||||
#include "dxc/DXIL/DxilOperations.h"
|
||||
#include "dxc/DXIL/DxilUtil.h"
|
||||
#include "dxc/Support/Global.h"
|
||||
|
||||
#include "llvm/IR/InstIterator.h"
|
||||
#include "llvm/IR/IntrinsicInst.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/Operator.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace hlsl {
|
||||
EntryStatus::EntryStatus(DxilEntryProps &entryProps)
|
||||
: m_bCoverageIn(false), m_bInnerCoverageIn(false), hasViewID(false) {
|
||||
for (unsigned i = 0; i < DXIL::kNumOutputStreams; i++) {
|
||||
hasOutputPosition[i] = false;
|
||||
OutputPositionMask[i] = 0;
|
||||
}
|
||||
|
||||
outputCols.resize(entryProps.sig.OutputSignature.GetElements().size(), 0);
|
||||
patchConstOrPrimCols.resize(
|
||||
entryProps.sig.PatchConstOrPrimSignature.GetElements().size(), 0);
|
||||
}
|
||||
|
||||
ValidationContext::ValidationContext(Module &llvmModule, Module *DebugModule,
|
||||
DxilModule &dxilModule)
|
||||
: M(llvmModule), pDebugModule(DebugModule), DxilMod(dxilModule),
|
||||
DL(llvmModule.getDataLayout()), LastRuleEmit((ValidationRule)-1),
|
||||
kDxilControlFlowHintMDKind(llvmModule.getContext().getMDKindID(
|
||||
DxilMDHelper::kDxilControlFlowHintMDName)),
|
||||
kDxilPreciseMDKind(llvmModule.getContext().getMDKindID(
|
||||
DxilMDHelper::kDxilPreciseAttributeMDName)),
|
||||
kDxilNonUniformMDKind(llvmModule.getContext().getMDKindID(
|
||||
DxilMDHelper::kDxilNonUniformAttributeMDName)),
|
||||
kLLVMLoopMDKind(llvmModule.getContext().getMDKindID("llvm.loop")),
|
||||
slotTracker(&llvmModule, true) {
|
||||
DxilMod.GetDxilVersion(m_DxilMajor, m_DxilMinor);
|
||||
HandleTy = DxilMod.GetOP()->GetHandleType();
|
||||
|
||||
for (Function &F : llvmModule.functions()) {
|
||||
if (DxilMod.HasDxilEntryProps(&F)) {
|
||||
DxilEntryProps &entryProps = DxilMod.GetDxilEntryProps(&F);
|
||||
entryStatusMap[&F] = llvm::make_unique<EntryStatus>(entryProps);
|
||||
}
|
||||
}
|
||||
|
||||
isLibProfile = dxilModule.GetShaderModel()->IsLib();
|
||||
BuildResMap();
|
||||
// Collect patch constant map.
|
||||
if (isLibProfile) {
|
||||
for (Function &F : dxilModule.GetModule()->functions()) {
|
||||
if (dxilModule.HasDxilEntryProps(&F)) {
|
||||
DxilEntryProps &entryProps = dxilModule.GetDxilEntryProps(&F);
|
||||
DxilFunctionProps &props = entryProps.props;
|
||||
if (props.IsHS()) {
|
||||
PatchConstantFuncMap[props.ShaderProps.HS.patchConstantFunc]
|
||||
.emplace_back(&F);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Function *Entry = dxilModule.GetEntryFunction();
|
||||
if (!dxilModule.HasDxilEntryProps(Entry)) {
|
||||
// must have props.
|
||||
EmitFnError(Entry, ValidationRule::MetaNoEntryPropsForEntry);
|
||||
return;
|
||||
}
|
||||
DxilEntryProps &entryProps = dxilModule.GetDxilEntryProps(Entry);
|
||||
DxilFunctionProps &props = entryProps.props;
|
||||
if (props.IsHS()) {
|
||||
PatchConstantFuncMap[props.ShaderProps.HS.patchConstantFunc].emplace_back(
|
||||
Entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ValidationContext::PropagateResMap(Value *V, DxilResourceBase *Res) {
|
||||
auto it = ResPropMap.find(V);
|
||||
if (it != ResPropMap.end()) {
|
||||
DxilResourceProperties RP = resource_helper::loadPropsFromResourceBase(Res);
|
||||
DxilResourceProperties itRP = it->second;
|
||||
if (itRP != RP) {
|
||||
EmitResourceError(Res, ValidationRule::InstrResourceMapToSingleEntry);
|
||||
}
|
||||
} else {
|
||||
DxilResourceProperties RP = resource_helper::loadPropsFromResourceBase(Res);
|
||||
ResPropMap[V] = RP;
|
||||
for (User *U : V->users()) {
|
||||
if (isa<GEPOperator>(U)) {
|
||||
PropagateResMap(U, Res);
|
||||
} else if (CallInst *CI = dyn_cast<CallInst>(U)) {
|
||||
// Stop propagate on function call.
|
||||
DxilInst_CreateHandleForLib hdl(CI);
|
||||
if (hdl) {
|
||||
DxilResourceProperties RP =
|
||||
resource_helper::loadPropsFromResourceBase(Res);
|
||||
ResPropMap[CI] = RP;
|
||||
}
|
||||
} else if (isa<LoadInst>(U)) {
|
||||
PropagateResMap(U, Res);
|
||||
} else if (isa<BitCastOperator>(U) && U->user_empty()) {
|
||||
// For hlsl type.
|
||||
continue;
|
||||
} else {
|
||||
EmitResourceError(Res, ValidationRule::InstrResourceUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ValidationContext::BuildResMap() {
|
||||
hlsl::OP *hlslOP = DxilMod.GetOP();
|
||||
|
||||
if (isLibProfile) {
|
||||
std::unordered_set<Value *> ResSet;
|
||||
// Start from all global variable in resTab.
|
||||
for (auto &Res : DxilMod.GetCBuffers())
|
||||
PropagateResMap(Res->GetGlobalSymbol(), Res.get());
|
||||
for (auto &Res : DxilMod.GetUAVs())
|
||||
PropagateResMap(Res->GetGlobalSymbol(), Res.get());
|
||||
for (auto &Res : DxilMod.GetSRVs())
|
||||
PropagateResMap(Res->GetGlobalSymbol(), Res.get());
|
||||
for (auto &Res : DxilMod.GetSamplers())
|
||||
PropagateResMap(Res->GetGlobalSymbol(), Res.get());
|
||||
} else {
|
||||
// Scan all createHandle.
|
||||
for (auto &it : hlslOP->GetOpFuncList(DXIL::OpCode::CreateHandle)) {
|
||||
Function *F = it.second;
|
||||
if (!F)
|
||||
continue;
|
||||
for (User *U : F->users()) {
|
||||
CallInst *CI = cast<CallInst>(U);
|
||||
DxilInst_CreateHandle hdl(CI);
|
||||
// Validate Class/RangeID/Index.
|
||||
Value *resClass = hdl.get_resourceClass();
|
||||
if (!isa<ConstantInt>(resClass)) {
|
||||
EmitInstrError(CI, ValidationRule::InstrOpConstRange);
|
||||
continue;
|
||||
}
|
||||
Value *rangeIndex = hdl.get_rangeId();
|
||||
if (!isa<ConstantInt>(rangeIndex)) {
|
||||
EmitInstrError(CI, ValidationRule::InstrOpConstRange);
|
||||
continue;
|
||||
}
|
||||
|
||||
DxilResourceBase *Res = nullptr;
|
||||
unsigned rangeId = hdl.get_rangeId_val();
|
||||
switch (static_cast<DXIL::ResourceClass>(hdl.get_resourceClass_val())) {
|
||||
default:
|
||||
EmitInstrError(CI, ValidationRule::InstrOpConstRange);
|
||||
continue;
|
||||
break;
|
||||
case DXIL::ResourceClass::CBuffer:
|
||||
if (DxilMod.GetCBuffers().size() > rangeId) {
|
||||
Res = &DxilMod.GetCBuffer(rangeId);
|
||||
} else {
|
||||
// Emit Error.
|
||||
EmitInstrError(CI, ValidationRule::InstrOpConstRange);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case DXIL::ResourceClass::Sampler:
|
||||
if (DxilMod.GetSamplers().size() > rangeId) {
|
||||
Res = &DxilMod.GetSampler(rangeId);
|
||||
} else {
|
||||
// Emit Error.
|
||||
EmitInstrError(CI, ValidationRule::InstrOpConstRange);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case DXIL::ResourceClass::SRV:
|
||||
if (DxilMod.GetSRVs().size() > rangeId) {
|
||||
Res = &DxilMod.GetSRV(rangeId);
|
||||
} else {
|
||||
// Emit Error.
|
||||
EmitInstrError(CI, ValidationRule::InstrOpConstRange);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case DXIL::ResourceClass::UAV:
|
||||
if (DxilMod.GetUAVs().size() > rangeId) {
|
||||
Res = &DxilMod.GetUAV(rangeId);
|
||||
} else {
|
||||
// Emit Error.
|
||||
EmitInstrError(CI, ValidationRule::InstrOpConstRange);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ConstantInt *cIndex = dyn_cast<ConstantInt>(hdl.get_index());
|
||||
if (!Res->GetHLSLType()->getPointerElementType()->isArrayTy()) {
|
||||
if (!cIndex) {
|
||||
// index must be 0 for none array resource.
|
||||
EmitInstrError(CI, ValidationRule::InstrOpConstRange);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (cIndex) {
|
||||
unsigned index = cIndex->getLimitedValue();
|
||||
if (index < Res->GetLowerBound() || index > Res->GetUpperBound()) {
|
||||
// index out of range.
|
||||
EmitInstrError(CI, ValidationRule::InstrOpConstRange);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
HandleResIndexMap[CI] = rangeId;
|
||||
DxilResourceProperties RP =
|
||||
resource_helper::loadPropsFromResourceBase(Res);
|
||||
ResPropMap[CI] = RP;
|
||||
}
|
||||
}
|
||||
}
|
||||
const ShaderModel &SM = *DxilMod.GetShaderModel();
|
||||
|
||||
for (auto &it : hlslOP->GetOpFuncList(DXIL::OpCode::AnnotateHandle)) {
|
||||
Function *F = it.second;
|
||||
if (!F)
|
||||
continue;
|
||||
|
||||
for (User *U : F->users()) {
|
||||
CallInst *CI = cast<CallInst>(U);
|
||||
DxilInst_AnnotateHandle hdl(CI);
|
||||
DxilResourceProperties RP =
|
||||
resource_helper::loadPropsFromAnnotateHandle(hdl, SM);
|
||||
if (RP.getResourceKind() == DXIL::ResourceKind::Invalid) {
|
||||
EmitInstrError(CI, ValidationRule::InstrOpConstRange);
|
||||
continue;
|
||||
}
|
||||
|
||||
ResPropMap[CI] = RP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ValidationContext::HasEntryStatus(Function *F) {
|
||||
return entryStatusMap.find(F) != entryStatusMap.end();
|
||||
}
|
||||
|
||||
EntryStatus &ValidationContext::GetEntryStatus(Function *F) {
|
||||
return *entryStatusMap[F];
|
||||
}
|
||||
|
||||
CallGraph &ValidationContext::GetCallGraph() {
|
||||
if (!pCallGraph)
|
||||
pCallGraph = llvm::make_unique<CallGraph>(M);
|
||||
return *pCallGraph.get();
|
||||
}
|
||||
|
||||
void ValidationContext::EmitGlobalVariableFormatError(
|
||||
GlobalVariable *GV, ValidationRule rule, ArrayRef<StringRef> args) {
|
||||
std::string ruleText = GetValidationRuleText(rule);
|
||||
FormatRuleText(ruleText, args);
|
||||
if (pDebugModule)
|
||||
GV = pDebugModule->getGlobalVariable(GV->getName());
|
||||
dxilutil::EmitErrorOnGlobalVariable(M.getContext(), GV, ruleText);
|
||||
Failed = true;
|
||||
}
|
||||
|
||||
// This is the least desirable mechanism, as it has no context.
|
||||
void ValidationContext::EmitError(ValidationRule rule) {
|
||||
dxilutil::EmitErrorOnContext(M.getContext(), GetValidationRuleText(rule));
|
||||
Failed = true;
|
||||
}
|
||||
|
||||
void ValidationContext::FormatRuleText(std::string &ruleText,
|
||||
ArrayRef<StringRef> args) {
|
||||
std::string escapedArg;
|
||||
// Consider changing const char * to StringRef
|
||||
for (unsigned i = 0; i < args.size(); i++) {
|
||||
std::string argIdx = "%" + std::to_string(i);
|
||||
StringRef pArg = args[i];
|
||||
if (pArg == "")
|
||||
pArg = "<null>";
|
||||
if (pArg[0] == 1) {
|
||||
escapedArg = "";
|
||||
raw_string_ostream os(escapedArg);
|
||||
dxilutil::PrintEscapedString(pArg, os);
|
||||
os.flush();
|
||||
pArg = escapedArg;
|
||||
}
|
||||
|
||||
std::string::size_type offset = ruleText.find(argIdx);
|
||||
if (offset == std::string::npos)
|
||||
continue;
|
||||
|
||||
unsigned size = argIdx.size();
|
||||
ruleText.replace(offset, size, pArg);
|
||||
}
|
||||
}
|
||||
|
||||
void ValidationContext::EmitFormatError(ValidationRule rule,
|
||||
ArrayRef<StringRef> args) {
|
||||
std::string ruleText = GetValidationRuleText(rule);
|
||||
FormatRuleText(ruleText, args);
|
||||
dxilutil::EmitErrorOnContext(M.getContext(), ruleText);
|
||||
Failed = true;
|
||||
}
|
||||
|
||||
void ValidationContext::EmitMetaError(Metadata *Meta, ValidationRule rule) {
|
||||
std::string O;
|
||||
raw_string_ostream OSS(O);
|
||||
Meta->print(OSS, &M);
|
||||
dxilutil::EmitErrorOnContext(M.getContext(), GetValidationRuleText(rule) + O);
|
||||
Failed = true;
|
||||
}
|
||||
|
||||
// Use this instead of DxilResourceBase::GetGlobalName
|
||||
std::string
|
||||
ValidationContext::GetResourceName(const hlsl::DxilResourceBase *Res) {
|
||||
if (!Res)
|
||||
return "nullptr";
|
||||
std::string resName = Res->GetGlobalName();
|
||||
if (!resName.empty())
|
||||
return resName;
|
||||
if (pDebugModule) {
|
||||
DxilModule &DM = pDebugModule->GetOrCreateDxilModule();
|
||||
switch (Res->GetClass()) {
|
||||
case DXIL::ResourceClass::CBuffer:
|
||||
return DM.GetCBuffer(Res->GetID()).GetGlobalName();
|
||||
case DXIL::ResourceClass::Sampler:
|
||||
return DM.GetSampler(Res->GetID()).GetGlobalName();
|
||||
case DXIL::ResourceClass::SRV:
|
||||
return DM.GetSRV(Res->GetID()).GetGlobalName();
|
||||
case DXIL::ResourceClass::UAV:
|
||||
return DM.GetUAV(Res->GetID()).GetGlobalName();
|
||||
default:
|
||||
return "Invalid Resource";
|
||||
}
|
||||
}
|
||||
// When names have been stripped, use class and binding location to
|
||||
// identify the resource. Format is roughly:
|
||||
// Allocated: (CB|T|U|S)<ID>: <ResourceKind> ((cb|t|u|s)<LB>[<RangeSize>]
|
||||
// space<SpaceID>) Unallocated: (CB|T|U|S)<ID>: <ResourceKind> (no bind
|
||||
// location) Example: U0: TypedBuffer (u5[2] space1)
|
||||
// [<RangeSize>] and space<SpaceID> skipped if 1 and 0 respectively.
|
||||
return (Twine(Res->GetResIDPrefix()) + Twine(Res->GetID()) + ": " +
|
||||
Twine(Res->GetResKindName()) +
|
||||
(Res->IsAllocated() ? (" (" + Twine(Res->GetResBindPrefix()) +
|
||||
Twine(Res->GetLowerBound()) +
|
||||
(Res->IsUnbounded() ? Twine("[unbounded]")
|
||||
: (Res->GetRangeSize() != 1)
|
||||
? "[" + Twine(Res->GetRangeSize()) + "]"
|
||||
: Twine()) +
|
||||
((Res->GetSpaceID() != 0)
|
||||
? " space" + Twine(Res->GetSpaceID())
|
||||
: Twine()) +
|
||||
")")
|
||||
: Twine(" (no bind location)")))
|
||||
.str();
|
||||
}
|
||||
|
||||
void ValidationContext::EmitResourceError(const hlsl::DxilResourceBase *Res,
|
||||
ValidationRule rule) {
|
||||
std::string QuotedRes = " '" + GetResourceName(Res) + "'";
|
||||
dxilutil::EmitErrorOnContext(M.getContext(),
|
||||
GetValidationRuleText(rule) + QuotedRes);
|
||||
Failed = true;
|
||||
}
|
||||
|
||||
void ValidationContext::EmitResourceFormatError(
|
||||
const hlsl::DxilResourceBase *Res, ValidationRule rule,
|
||||
ArrayRef<StringRef> args) {
|
||||
std::string QuotedRes = " '" + GetResourceName(Res) + "'";
|
||||
std::string ruleText = GetValidationRuleText(rule);
|
||||
FormatRuleText(ruleText, args);
|
||||
dxilutil::EmitErrorOnContext(M.getContext(), ruleText + QuotedRes);
|
||||
Failed = true;
|
||||
}
|
||||
|
||||
bool ValidationContext::IsDebugFunctionCall(Instruction *I) {
|
||||
return isa<DbgInfoIntrinsic>(I);
|
||||
}
|
||||
|
||||
Instruction *ValidationContext::GetDebugInstr(Instruction *I) {
|
||||
DXASSERT_NOMSG(I);
|
||||
if (pDebugModule) {
|
||||
// Look up the matching instruction in the debug module.
|
||||
llvm::Function *Fn = I->getParent()->getParent();
|
||||
llvm::Function *DbgFn = pDebugModule->getFunction(Fn->getName());
|
||||
if (DbgFn) {
|
||||
// Linear lookup, but then again, failing validation is rare.
|
||||
inst_iterator it = inst_begin(Fn);
|
||||
inst_iterator dbg_it = inst_begin(DbgFn);
|
||||
while (IsDebugFunctionCall(&*dbg_it))
|
||||
++dbg_it;
|
||||
while (&*it != I) {
|
||||
++it;
|
||||
++dbg_it;
|
||||
while (IsDebugFunctionCall(&*dbg_it))
|
||||
++dbg_it;
|
||||
}
|
||||
return &*dbg_it;
|
||||
}
|
||||
}
|
||||
return I;
|
||||
}
|
||||
|
||||
// Emit Error or note on instruction `I` with `Msg`.
|
||||
// If `isError` is true, `Rule` may omit repeated errors
|
||||
void ValidationContext::EmitInstrDiagMsg(Instruction *I, ValidationRule Rule,
|
||||
std::string Msg, bool isError) {
|
||||
BasicBlock *BB = I->getParent();
|
||||
Function *F = BB->getParent();
|
||||
|
||||
Instruction *DbgI = GetDebugInstr(I);
|
||||
if (isError) {
|
||||
if (const DebugLoc L = DbgI->getDebugLoc()) {
|
||||
// Instructions that get scalarized will likely hit
|
||||
// this case. Avoid redundant diagnostic messages.
|
||||
if (Rule == LastRuleEmit && L == LastDebugLocEmit) {
|
||||
return;
|
||||
}
|
||||
LastRuleEmit = Rule;
|
||||
LastDebugLocEmit = L;
|
||||
}
|
||||
dxilutil::EmitErrorOnInstruction(DbgI, Msg);
|
||||
} else {
|
||||
dxilutil::EmitNoteOnContext(DbgI->getContext(), Msg);
|
||||
}
|
||||
|
||||
// Add llvm information as a note to instruction string
|
||||
std::string InstrStr;
|
||||
raw_string_ostream InstrStream(InstrStr);
|
||||
I->print(InstrStream, slotTracker);
|
||||
InstrStream.flush();
|
||||
StringRef InstrStrRef = InstrStr;
|
||||
InstrStrRef = InstrStrRef.ltrim(); // Ignore indentation
|
||||
Msg = "at '" + InstrStrRef.str() + "'";
|
||||
|
||||
// Print the parent block name
|
||||
Msg += " in block '";
|
||||
if (!BB->getName().empty()) {
|
||||
Msg += BB->getName();
|
||||
} else {
|
||||
unsigned idx = 0;
|
||||
for (auto i = F->getBasicBlockList().begin(),
|
||||
e = F->getBasicBlockList().end();
|
||||
i != e; ++i) {
|
||||
if (BB == &(*i)) {
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
Msg += "#" + std::to_string(idx);
|
||||
}
|
||||
Msg += "'";
|
||||
|
||||
// Print the function name
|
||||
Msg += " of function '" + F->getName().str() + "'.";
|
||||
|
||||
dxilutil::EmitNoteOnContext(DbgI->getContext(), Msg);
|
||||
|
||||
Failed = true;
|
||||
}
|
||||
|
||||
void ValidationContext::EmitInstrError(Instruction *I, ValidationRule rule) {
|
||||
EmitInstrDiagMsg(I, rule, GetValidationRuleText(rule));
|
||||
}
|
||||
|
||||
void ValidationContext::EmitInstrNote(Instruction *I, std::string Msg) {
|
||||
EmitInstrDiagMsg(I, LastRuleEmit, Msg, false);
|
||||
}
|
||||
|
||||
void ValidationContext::EmitInstrFormatError(Instruction *I,
|
||||
ValidationRule rule,
|
||||
ArrayRef<StringRef> args) {
|
||||
std::string ruleText = GetValidationRuleText(rule);
|
||||
FormatRuleText(ruleText, args);
|
||||
EmitInstrDiagMsg(I, rule, ruleText);
|
||||
}
|
||||
|
||||
void ValidationContext::EmitSignatureError(DxilSignatureElement *SE,
|
||||
ValidationRule rule) {
|
||||
EmitFormatError(rule, {SE->GetName()});
|
||||
}
|
||||
|
||||
void ValidationContext::EmitTypeError(Type *Ty, ValidationRule rule) {
|
||||
std::string O;
|
||||
raw_string_ostream OSS(O);
|
||||
Ty->print(OSS);
|
||||
EmitFormatError(rule, {OSS.str()});
|
||||
}
|
||||
|
||||
void ValidationContext::EmitFnError(Function *F, ValidationRule rule) {
|
||||
if (pDebugModule)
|
||||
if (Function *dbgF = pDebugModule->getFunction(F->getName()))
|
||||
F = dbgF;
|
||||
dxilutil::EmitErrorOnFunction(M.getContext(), F, GetValidationRuleText(rule));
|
||||
Failed = true;
|
||||
}
|
||||
|
||||
void ValidationContext::EmitFnFormatError(Function *F, ValidationRule rule,
|
||||
ArrayRef<StringRef> args) {
|
||||
std::string ruleText = GetValidationRuleText(rule);
|
||||
FormatRuleText(ruleText, args);
|
||||
if (pDebugModule)
|
||||
if (Function *dbgF = pDebugModule->getFunction(F->getName()))
|
||||
F = dbgF;
|
||||
dxilutil::EmitErrorOnFunction(M.getContext(), F, ruleText);
|
||||
Failed = true;
|
||||
}
|
||||
|
||||
void ValidationContext::EmitFnAttributeError(Function *F, StringRef Kind,
|
||||
StringRef Value) {
|
||||
EmitFnFormatError(F, ValidationRule::DeclFnAttribute,
|
||||
{F->getName(), Kind, Value});
|
||||
}
|
||||
|
||||
} // namespace hlsl
|
|
@ -0,0 +1,149 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// DxilValidationUttils.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. //
|
||||
// //
|
||||
// This file provides utils for validating DXIL. //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "dxc/DXIL/DxilConstants.h"
|
||||
#include "dxc/DXIL/DxilResourceProperties.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Analysis/CallGraph.h"
|
||||
#include "llvm/IR/DebugLoc.h"
|
||||
#include "llvm/IR/ModuleSlotTracker.h"
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
class Module;
|
||||
class Function;
|
||||
class DataLayout;
|
||||
class Metadata;
|
||||
class Value;
|
||||
class GlobalVariable;
|
||||
class Instruction;
|
||||
class Type;
|
||||
} // namespace llvm
|
||||
|
||||
namespace hlsl {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Validation rules.
|
||||
#include "DxilValidation.inc"
|
||||
|
||||
const char *GetValidationRuleText(ValidationRule value);
|
||||
|
||||
class DxilEntryProps;
|
||||
class DxilModule;
|
||||
class DxilResourceBase;
|
||||
class DxilSignatureElement;
|
||||
|
||||
// Save status like output write for entries.
|
||||
struct EntryStatus {
|
||||
bool hasOutputPosition[DXIL::kNumOutputStreams];
|
||||
unsigned OutputPositionMask[DXIL::kNumOutputStreams];
|
||||
std::vector<unsigned> outputCols;
|
||||
std::vector<unsigned> patchConstOrPrimCols;
|
||||
bool m_bCoverageIn, m_bInnerCoverageIn;
|
||||
bool hasViewID;
|
||||
unsigned domainLocSize;
|
||||
EntryStatus(DxilEntryProps &entryProps);
|
||||
};
|
||||
|
||||
struct ValidationContext {
|
||||
bool Failed = false;
|
||||
Module &M;
|
||||
Module *pDebugModule;
|
||||
DxilModule &DxilMod;
|
||||
const Type *HandleTy;
|
||||
const DataLayout &DL;
|
||||
DebugLoc LastDebugLocEmit;
|
||||
ValidationRule LastRuleEmit;
|
||||
std::unordered_set<Function *> entryFuncCallSet;
|
||||
std::unordered_set<Function *> patchConstFuncCallSet;
|
||||
std::unordered_map<unsigned, bool> UavCounterIncMap;
|
||||
std::unordered_map<Value *, unsigned> HandleResIndexMap;
|
||||
// TODO: save resource map for each createHandle/createHandleForLib.
|
||||
std::unordered_map<Value *, DxilResourceProperties> ResPropMap;
|
||||
std::unordered_map<Function *, std::vector<Function *>> PatchConstantFuncMap;
|
||||
std::unordered_map<Function *, std::unique_ptr<EntryStatus>> entryStatusMap;
|
||||
bool isLibProfile;
|
||||
const unsigned kDxilControlFlowHintMDKind;
|
||||
const unsigned kDxilPreciseMDKind;
|
||||
const unsigned kDxilNonUniformMDKind;
|
||||
const unsigned kLLVMLoopMDKind;
|
||||
unsigned m_DxilMajor, m_DxilMinor;
|
||||
ModuleSlotTracker slotTracker;
|
||||
std::unique_ptr<CallGraph> pCallGraph;
|
||||
|
||||
ValidationContext(Module &llvmModule, Module *DebugModule,
|
||||
DxilModule &dxilModule);
|
||||
|
||||
void PropagateResMap(Value *V, DxilResourceBase *Res);
|
||||
void BuildResMap();
|
||||
bool HasEntryStatus(Function *F);
|
||||
EntryStatus &GetEntryStatus(Function *F);
|
||||
CallGraph &GetCallGraph();
|
||||
DxilResourceProperties GetResourceFromVal(Value *resVal);
|
||||
|
||||
void EmitGlobalVariableFormatError(GlobalVariable *GV, ValidationRule rule,
|
||||
ArrayRef<StringRef> args);
|
||||
// This is the least desirable mechanism, as it has no context.
|
||||
void EmitError(ValidationRule rule);
|
||||
|
||||
void FormatRuleText(std::string &ruleText, ArrayRef<StringRef> args);
|
||||
void EmitFormatError(ValidationRule rule, ArrayRef<StringRef> args);
|
||||
|
||||
void EmitMetaError(Metadata *Meta, ValidationRule rule);
|
||||
|
||||
// Use this instead of DxilResourceBase::GetGlobalName
|
||||
std::string GetResourceName(const hlsl::DxilResourceBase *Res);
|
||||
|
||||
void EmitResourceError(const hlsl::DxilResourceBase *Res,
|
||||
ValidationRule rule);
|
||||
|
||||
void EmitResourceFormatError(const hlsl::DxilResourceBase *Res,
|
||||
ValidationRule rule, ArrayRef<StringRef> args);
|
||||
|
||||
bool IsDebugFunctionCall(Instruction *I);
|
||||
|
||||
Instruction *GetDebugInstr(Instruction *I);
|
||||
|
||||
// Emit Error or note on instruction `I` with `Msg`.
|
||||
// If `isError` is true, `Rule` may omit repeated errors
|
||||
void EmitInstrDiagMsg(Instruction *I, ValidationRule Rule, std::string Msg,
|
||||
bool isError = true);
|
||||
void EmitInstrError(Instruction *I, ValidationRule rule);
|
||||
|
||||
void EmitInstrNote(Instruction *I, std::string Msg);
|
||||
|
||||
void EmitInstrFormatError(Instruction *I, ValidationRule rule,
|
||||
ArrayRef<StringRef> args);
|
||||
|
||||
void EmitSignatureError(DxilSignatureElement *SE, ValidationRule rule);
|
||||
|
||||
void EmitTypeError(Type *Ty, ValidationRule rule);
|
||||
|
||||
void EmitFnError(Function *F, ValidationRule rule);
|
||||
|
||||
void EmitFnFormatError(Function *F, ValidationRule rule,
|
||||
ArrayRef<StringRef> args);
|
||||
|
||||
void EmitFnAttributeError(Function *F, StringRef Kind, StringRef Value);
|
||||
};
|
||||
|
||||
uint32_t ValidateDxilModule(llvm::Module *pModule, llvm::Module *pDebugModule);
|
||||
} // namespace hlsl
|
|
@ -2,7 +2,6 @@
|
|||
# This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
|
||||
add_hlsl_hctgen(DxcOptimizer OUTPUT DxcOptimizer.inc BUILD_DIR)
|
||||
add_hlsl_hctgen(DxilValidation OUTPUT DxilValidationImpl.inc BUILD_DIR)
|
||||
|
||||
add_llvm_library(LLVMHLSL
|
||||
ComputeViewIdState.cpp
|
||||
|
@ -32,7 +31,6 @@ add_llvm_library(LLVMHLSL
|
|||
DxilTargetTransformInfo.cpp
|
||||
DxilTranslateRawBuffer.cpp
|
||||
DxilExportMap.cpp
|
||||
DxilValidation.cpp
|
||||
DxcOptimizer.cpp
|
||||
HLDeadFunctionElimination.cpp
|
||||
HLExpandStoreIntrinsics.cpp
|
||||
|
|
|
@ -11,33 +11,13 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "dxc/DXIL/DxilInstructions.h"
|
||||
#include "dxc/DXIL/DxilModule.h"
|
||||
#include "dxc/DXIL/DxilOperations.h"
|
||||
#include "dxc/DXIL/DxilShaderModel.h"
|
||||
#include "dxc/DxilContainer/DxilContainer.h"
|
||||
#include "dxc/HLSL/DxilGenerationPass.h"
|
||||
#include "dxc/HLSL/DxilValidation.h"
|
||||
#include "dxc/HLSL/HLModule.h"
|
||||
#include "dxc/HLSL/HLOperations.h"
|
||||
#include "dxc/Support/Global.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/Analysis/PostDominators.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/DiagnosticInfo.h"
|
||||
#include "llvm/IR/DiagnosticPrinter.h"
|
||||
#include "llvm/IR/InstIterator.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winerror.h>
|
||||
#endif
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <unordered_set>
|
||||
|
||||
using namespace llvm;
|
||||
using std::map;
|
||||
|
|
|
@ -13,7 +13,7 @@ target_link_libraries(dxilconv PRIVATE
|
|||
LLVMDXIL
|
||||
LLVMDxilContainer
|
||||
LLVMDxilRootSignature
|
||||
LLVMHLSL
|
||||
LLVMDxilValidation
|
||||
LLVMMSSupport
|
||||
LLVMScalarOpts
|
||||
)
|
||||
|
@ -23,4 +23,4 @@ set_target_properties(dxilconv
|
|||
OUTPUT_NAME "dxilconv"
|
||||
)
|
||||
|
||||
add_dependencies(dxilconv DxcEtw)
|
||||
add_dependencies(dxilconv DxcEtw)
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include "dxc/DxilValidation/DxilValidation.h"
|
||||
#include "dxc/HLSL/DxilLinker.h"
|
||||
#include "dxc/HLSL/DxilValidation.h"
|
||||
#include "dxc/Support/HLSLOptions.h"
|
||||
#include "dxc/Support/Unicode.h"
|
||||
#include "dxc/Support/microcom.h"
|
||||
|
|
|
@ -7,7 +7,7 @@ set( LLVM_LINK_COMPONENTS
|
|||
dxcsupport
|
||||
DXIL
|
||||
DxilContainer
|
||||
HLSL
|
||||
DxilValidation
|
||||
Option # option library
|
||||
Support # just for assert and raw streams
|
||||
)
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include "llvm/IR/LLVMContext.h"
|
||||
|
||||
#include "dxc/DxilContainer/DxilContainer.h"
|
||||
#include "dxc/HLSL/DxilValidation.h"
|
||||
#include "dxc/DxilValidation/DxilValidation.h"
|
||||
#include "dxc/Support/WinIncludes.h"
|
||||
#include "dxc/dxcapi.h"
|
||||
#include "dxcvalidator.h"
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "dxc/HLSL/DxilLinker.h"
|
||||
#include "dxc/DXIL/DxilModule.h"
|
||||
#include "dxc/DXIL/DxilUtil.h"
|
||||
#include "dxc/HLSL/DxilValidation.h"
|
||||
#include "dxc/DxilValidation/DxilValidation.h"
|
||||
#include "dxc/Support/FileIOHelper.h"
|
||||
#include "dxc/Support/dxcapi.impl.h"
|
||||
#include "dxcutil.h"
|
||||
|
|
|
@ -1941,7 +1941,6 @@ if __name__ == "__main__":
|
|||
"lib/DXIL/DxilShaderModel.cpp",
|
||||
"include/dxc/DXIL/DxilConstants.h",
|
||||
"include/dxc/DXIL/DxilShaderModel.h",
|
||||
"include/dxc/HLSL/DxilValidation.h",
|
||||
"include/dxc/Support/HLSLOptions.td",
|
||||
"include/dxc/DXIL/DxilInstructions.h",
|
||||
"lib/HLSL/DxcOptimizer.cpp",
|
||||
|
|
Загрузка…
Ссылка в новой задаче