-
Notifications
You must be signed in to change notification settings - Fork 721
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a test dxil lib for testing loadability #5952
Changes from 11 commits
3ae2a52
496b071
df3fdf7
ea7d6fc
740fb27
cab6842
d00cb4d
bda8263
297c41e
b080b8e
63d46cd
bd3e013
f0e0cb2
b93e5aa
eac1e7d
d67697a
ba0d7c4
1c95008
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#include "dxc/Support/Global.h" | ||
#include "dxc/Support/WinIncludes.h" | ||
#include "dxc/Support/microcom.h" | ||
#include "dxc/dxcapi.h" | ||
|
||
namespace llvm { | ||
class Module; | ||
} | ||
|
||
namespace hlsl { | ||
class AbstractMemoryStream; | ||
} | ||
|
||
class DxilValidator : public IDxcValidator2 { | ||
private: | ||
CComPtr<IMalloc> m_pMalloc; | ||
HRESULT RunValidation( | ||
IDxcBlob *pShader, // Shader to validate. | ||
UINT32 Flags, // Validation flags. | ||
llvm::Module *pModule, // Module to validate, if available. | ||
llvm::Module *pDebugModule, // Debug module to validate, if available | ||
hlsl::AbstractMemoryStream *pDiagStream); | ||
|
||
HRESULT RunRootSignatureValidation(IDxcBlob *pShader, // Shader to validate. | ||
hlsl::AbstractMemoryStream *pDiagStream); | ||
|
||
public: | ||
DxilValidator(IMalloc *pMalloc) : m_pMalloc(pMalloc) {} | ||
|
||
// For internal use only. | ||
HRESULT ValidateWithOptModules( | ||
IDxcBlob *pShader, // Shader to validate. | ||
UINT32 Flags, // Validation flags. | ||
llvm::Module *pModule, // Module to validate, if available. | ||
llvm::Module *pDebugModule, // Debug module to validate, if available | ||
IDxcOperationResult * | ||
*ppResult // Validation output status, buffer, and errors | ||
); | ||
|
||
// IDxcValidator | ||
HRESULT STDMETHODCALLTYPE Validate( | ||
IDxcBlob *pShader, // Shader to validate. | ||
UINT32 Flags, // Validation flags. | ||
IDxcOperationResult * | ||
*ppResult // Validation output status, buffer, and errors | ||
) override; | ||
|
||
// IDxcValidator2 | ||
HRESULT STDMETHODCALLTYPE ValidateWithDebug( | ||
IDxcBlob *pShader, // Shader to validate. | ||
UINT32 Flags, // Validation flags. | ||
DxcBuffer *pOptDebugBitcode, // Optional debug module bitcode to provide | ||
// line numbers | ||
IDxcOperationResult * | ||
*ppResult // Validation output status, buffer, and errors | ||
) override; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,278 @@ | ||
/////////////////////////////////////////////////////////////////////////////// | ||
// // | ||
// DxilValidator.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. // | ||
// // | ||
// Implements the DirectX Validator object. // | ||
// // | ||
/////////////////////////////////////////////////////////////////////////////// | ||
|
||
#include "llvm/IR/DiagnosticPrinter.h" | ||
#include "llvm/IR/LLVMContext.h" | ||
#include "llvm/IR/Module.h" | ||
|
||
#include "dxc/DxilContainer/DxilContainer.h" | ||
#include "dxc/HLSL/DxilValidation.h" | ||
#include "dxc/HLSL/DxilValidator.h" | ||
#include "dxc/Support/WinIncludes.h" | ||
|
||
#include "dxc/DxilRootSignature/DxilRootSignature.h" | ||
#include "dxc/Support/FileIOHelper.h" | ||
#include "dxc/Support/Global.h" | ||
#include "dxc/dxcapi.h" | ||
#include "dxc/Support/dxcapi.impl.h" | ||
#include "llvm/Support/MemoryBuffer.h" | ||
|
||
#ifdef _WIN32 | ||
#include "dxcetw.h" | ||
#endif | ||
|
||
using namespace llvm; | ||
using namespace hlsl; | ||
|
||
// Utility class for setting and restoring the diagnostic context so we may | ||
// capture errors/warnings | ||
struct DiagRestore { | ||
LLVMContext &Ctx; | ||
void *OrigDiagContext; | ||
LLVMContext::DiagnosticHandlerTy OrigHandler; | ||
|
||
DiagRestore(llvm::LLVMContext &Ctx, void *DiagContext) : Ctx(Ctx) { | ||
OrigHandler = Ctx.getDiagnosticHandler(); | ||
OrigDiagContext = Ctx.getDiagnosticContext(); | ||
Ctx.setDiagnosticHandler(PrintDiagnosticContext::PrintDiagnosticHandler, | ||
DiagContext); | ||
} | ||
~DiagRestore() { Ctx.setDiagnosticHandler(OrigHandler, OrigDiagContext); } | ||
}; | ||
|
||
// Compile a single entry point to the target shader model | ||
HRESULT STDMETHODCALLTYPE DxilValidator::Validate( | ||
IDxcBlob *pShader, // Shader to validate. | ||
UINT32 Flags, // Validation flags. | ||
IDxcOperationResult * | ||
*ppResult // Validation output status, buffer, and errors | ||
) { | ||
DxcThreadMalloc TM(m_pMalloc); | ||
if (ppResult == nullptr) | ||
return E_INVALIDARG; | ||
*ppResult = nullptr; | ||
if (pShader == nullptr || Flags & ~DxcValidatorFlags_ValidMask) | ||
return E_INVALIDARG; | ||
if ((Flags & DxcValidatorFlags_ModuleOnly) && | ||
(Flags & | ||
(DxcValidatorFlags_InPlaceEdit | DxcValidatorFlags_RootSignatureOnly))) | ||
return E_INVALIDARG; | ||
return ValidateWithOptModules(pShader, Flags, nullptr, nullptr, ppResult); | ||
} | ||
|
||
HRESULT STDMETHODCALLTYPE DxilValidator::ValidateWithDebug( | ||
IDxcBlob *pShader, // Shader to validate. | ||
UINT32 Flags, // Validation flags. | ||
DxcBuffer *pOptDebugBitcode, // Optional debug module bitcode to provide | ||
// line numbers | ||
IDxcOperationResult * | ||
*ppResult // Validation output status, buffer, and errors | ||
) { | ||
if (ppResult == nullptr) | ||
return E_INVALIDARG; | ||
*ppResult = nullptr; | ||
if (pShader == nullptr || Flags & ~DxcValidatorFlags_ValidMask) | ||
return E_INVALIDARG; | ||
if ((Flags & DxcValidatorFlags_ModuleOnly) && | ||
(Flags & | ||
(DxcValidatorFlags_InPlaceEdit | DxcValidatorFlags_RootSignatureOnly))) | ||
return E_INVALIDARG; | ||
if (pOptDebugBitcode && | ||
(pOptDebugBitcode->Ptr == nullptr || pOptDebugBitcode->Size == 0 || | ||
pOptDebugBitcode->Size >= UINT32_MAX)) | ||
return E_INVALIDARG; | ||
|
||
HRESULT hr = S_OK; | ||
DxcThreadMalloc TM(m_pMalloc); | ||
try { | ||
LLVMContext Ctx; | ||
CComPtr<AbstractMemoryStream> pDiagStream; | ||
IFT(CreateMemoryStream(m_pMalloc, &pDiagStream)); | ||
raw_stream_ostream DiagStream(pDiagStream); | ||
llvm::DiagnosticPrinterRawOStream DiagPrinter(DiagStream); | ||
PrintDiagnosticContext DiagContext(DiagPrinter); | ||
Ctx.setDiagnosticHandler(PrintDiagnosticContext::PrintDiagnosticHandler, | ||
&DiagContext, true); | ||
std::unique_ptr<llvm::Module> pDebugModule; | ||
if (pOptDebugBitcode) { | ||
IFT(ValidateLoadModule((const char *)pOptDebugBitcode->Ptr, | ||
(uint32_t)pOptDebugBitcode->Size, pDebugModule, | ||
Ctx, DiagStream, /*bLazyLoad*/ false)); | ||
} | ||
return ValidateWithOptModules(pShader, Flags, nullptr, pDebugModule.get(), | ||
ppResult); | ||
} | ||
CATCH_CPP_ASSIGN_HRESULT(); | ||
return hr; | ||
} | ||
|
||
HRESULT DxilValidator::ValidateWithOptModules( | ||
IDxcBlob *pShader, // Shader to validate. | ||
UINT32 Flags, // Validation flags. | ||
llvm::Module *pModule, // Module to validate, if available. | ||
llvm::Module *pDebugModule, // Debug module to validate, if available | ||
IDxcOperationResult * | ||
*ppResult // Validation output status, buffer, and errors | ||
) { | ||
*ppResult = nullptr; | ||
HRESULT hr = S_OK; | ||
HRESULT validationStatus = S_OK; | ||
DxcEtw_DxcValidation_Start(); | ||
DxcThreadMalloc TM(m_pMalloc); | ||
try { | ||
CComPtr<AbstractMemoryStream> pDiagStream; | ||
IFT(CreateMemoryStream(m_pMalloc, &pDiagStream)); | ||
|
||
// Run validation may throw, but that indicates an inability to validate, | ||
// not that the validation failed (eg out of memory). | ||
if (Flags & DxcValidatorFlags_RootSignatureOnly) { | ||
validationStatus = RunRootSignatureValidation(pShader, pDiagStream); | ||
} else { | ||
validationStatus = | ||
RunValidation(pShader, Flags, pModule, pDebugModule, pDiagStream); | ||
} | ||
if (FAILED(validationStatus)) { | ||
std::string msg("Validation failed.\n"); | ||
ULONG cbWritten; | ||
pDiagStream->Write(msg.c_str(), msg.size(), &cbWritten); | ||
} | ||
// Assemble the result object. | ||
CComPtr<IDxcBlob> pDiagBlob; | ||
hr = pDiagStream.QueryInterface(&pDiagBlob); | ||
DXASSERT_NOMSG(SUCCEEDED(hr)); | ||
IFT(DxcResult::Create( | ||
validationStatus, DXC_OUT_NONE, | ||
{DxcOutputObject::ErrorOutput( | ||
CP_UTF8, // TODO Support DefaultTextCodePage | ||
(LPCSTR)pDiagBlob->GetBufferPointer(), pDiagBlob->GetBufferSize())}, | ||
ppResult)); | ||
} | ||
CATCH_CPP_ASSIGN_HRESULT(); | ||
|
||
DxcEtw_DxcValidation_Stop(SUCCEEDED(hr) ? validationStatus : hr); | ||
return hr; | ||
} | ||
|
||
HRESULT DxilValidator::RunValidation( | ||
IDxcBlob *pShader, | ||
UINT32 Flags, // Validation flags. | ||
llvm::Module *pModule, // Module to validate, if available. | ||
llvm::Module *pDebugModule, // Debug module to validate, if available | ||
AbstractMemoryStream *pDiagStream) { | ||
|
||
// Run validation may throw, but that indicates an inability to validate, | ||
// not that the validation failed (eg out of memory). That is indicated | ||
// by a failing HRESULT, and possibly error messages in the diagnostics | ||
// stream. | ||
|
||
raw_stream_ostream DiagStream(pDiagStream); | ||
|
||
if (Flags & DxcValidatorFlags_ModuleOnly) { | ||
IFRBOOL(!IsDxilContainerLike(pShader->GetBufferPointer(), | ||
pShader->GetBufferSize()), | ||
E_INVALIDARG); | ||
} else { | ||
IFRBOOL(IsDxilContainerLike(pShader->GetBufferPointer(), | ||
pShader->GetBufferSize()), | ||
DXC_E_CONTAINER_INVALID); | ||
} | ||
|
||
if (!pModule) { | ||
DXASSERT_NOMSG(pDebugModule == nullptr); | ||
if (Flags & DxcValidatorFlags_ModuleOnly) { | ||
return ValidateDxilBitcode((const char *)pShader->GetBufferPointer(), | ||
(uint32_t)pShader->GetBufferSize(), | ||
DiagStream); | ||
} else { | ||
return ValidateDxilContainer(pShader->GetBufferPointer(), | ||
pShader->GetBufferSize(), DiagStream); | ||
} | ||
} | ||
|
||
llvm::DiagnosticPrinterRawOStream DiagPrinter(DiagStream); | ||
PrintDiagnosticContext DiagContext(DiagPrinter); | ||
DiagRestore DR(pModule->getContext(), &DiagContext); | ||
|
||
IFR(hlsl::ValidateDxilModule(pModule, pDebugModule)); | ||
if (!(Flags & DxcValidatorFlags_ModuleOnly)) { | ||
IFR(ValidateDxilContainerParts( | ||
pModule, pDebugModule, | ||
IsDxilContainerLike(pShader->GetBufferPointer(), | ||
pShader->GetBufferSize()), | ||
(uint32_t)pShader->GetBufferSize())); | ||
} | ||
|
||
if (DiagContext.HasErrors() || DiagContext.HasWarnings()) { | ||
return DXC_E_IR_VERIFICATION_FAILED; | ||
} | ||
|
||
return S_OK; | ||
} | ||
|
||
HRESULT | ||
DxilValidator::RunRootSignatureValidation(IDxcBlob *pShader, | ||
AbstractMemoryStream *pDiagStream) { | ||
|
||
const DxilContainerHeader *pDxilContainer = IsDxilContainerLike( | ||
pShader->GetBufferPointer(), pShader->GetBufferSize()); | ||
if (!pDxilContainer) { | ||
return DXC_E_IR_VERIFICATION_FAILED; | ||
} | ||
|
||
const DxilProgramHeader *pProgramHeader = | ||
GetDxilProgramHeader(pDxilContainer, DFCC_DXIL); | ||
const DxilPartHeader *pPSVPart = | ||
GetDxilPartByType(pDxilContainer, DFCC_PipelineStateValidation); | ||
const DxilPartHeader *pRSPart = | ||
GetDxilPartByType(pDxilContainer, DFCC_RootSignature); | ||
IFRBOOL(pRSPart, DXC_E_MISSING_PART); | ||
if (pProgramHeader) { | ||
// Container has shader part, make sure we have PSV. | ||
IFRBOOL(pPSVPart, DXC_E_MISSING_PART); | ||
} | ||
try { | ||
RootSignatureHandle RSH; | ||
RSH.LoadSerialized((const uint8_t *)GetDxilPartData(pRSPart), | ||
pRSPart->PartSize); | ||
RSH.Deserialize(); | ||
raw_stream_ostream DiagStream(pDiagStream); | ||
if (pProgramHeader) { | ||
IFRBOOL(VerifyRootSignatureWithShaderPSV( | ||
RSH.GetDesc(), | ||
GetVersionShaderType(pProgramHeader->ProgramVersion), | ||
GetDxilPartData(pPSVPart), pPSVPart->PartSize, DiagStream), | ||
DXC_E_INCORRECT_ROOT_SIGNATURE); | ||
} else { | ||
IFRBOOL(VerifyRootSignature(RSH.GetDesc(), DiagStream, false), | ||
DXC_E_INCORRECT_ROOT_SIGNATURE); | ||
} | ||
} catch (...) { | ||
return DXC_E_IR_VERIFICATION_FAILED; | ||
} | ||
|
||
return S_OK; | ||
} | ||
|
||
/////////////////////////////////////////////////////////////////////////////// | ||
|
||
HRESULT RunInternalValidator(IDxcValidator *pValidator, llvm::Module *pModule, | ||
llvm::Module *pDebugModule, IDxcBlob *pShader, | ||
UINT32 Flags, IDxcOperationResult **ppResult) { | ||
DXASSERT_NOMSG(pValidator != nullptr); | ||
DXASSERT_NOMSG(pModule != nullptr); | ||
DXASSERT_NOMSG(pShader != nullptr); | ||
DXASSERT_NOMSG(ppResult != nullptr); | ||
|
||
DxilValidator *pInternalValidator = (DxilValidator *)pValidator; | ||
return pInternalValidator->ValidateWithOptModules(pShader, Flags, pModule, | ||
pDebugModule, ppResult); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
// RUN: %dxilver 1.6 | %dxc -E main -T as_6_5 %s | FileCheck %s -check-prefix=CHK_NODB | ||
|
||
// CHK_DB: 23:5: error: For amplification shader with entry 'main', payload size 16400 is greater than maximum size of 16384 bytes. | ||
// CHK_NODB: 23:5: error: For amplification shader with entry 'main', payload size 16400 is greater than maximum size of 16384 bytes. | ||
// CHK_NODB: error: For amplification shader with entry 'main', payload size 16400 is greater than maximum size of 16384 bytes. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change shouldn't have been necessary. IDxcValidator2::ValidateWithDebug allows you to provide the serialized debug module, which is normally provided to the external validator when present. This must work with the normal DXIL.dll because these don't normally fail when testing against that. So perhaps there's something wrong with the new test validator? |
||
|
||
#define NUM_THREADS 32 | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we rename
DxilValidator
toDxcValidatorBase
?It's already a little confusing to have
DxilValidation
andDxcValidator
, but it's a pattern that is used elsewhere, with core implementation inDxil*
andDxc*
being the implementation of theIDxc*
interface.Adding
DxilValidator
confuses things more, while I thinkDxcValidatorBase
makes the purpose of being a base class for theIDxcValidator
implementation clearer.