Skip to content
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

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions include/dxc/HLSL/DxcValidatorBase.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
///////////////////////////////////////////////////////////////////////////////
// //
// DxcValidatorBase.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. //
// //
// Implements the DirectX Validator base validation functionality //
// //
///////////////////////////////////////////////////////////////////////////////

#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 DxcValidatorBase : 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:
DxcValidatorBase(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;
};
1 change: 1 addition & 0 deletions lib/HLSL/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ add_llvm_library(LLVMHLSL
ComputeViewIdState.cpp
ComputeViewIdStateBuilder.cpp
ControlDependence.cpp
DxcValidatorBase.cpp
DxilCondenseResources.cpp
DxilContainerReflection.cpp
DxilConvergent.cpp
Expand Down
276 changes: 276 additions & 0 deletions lib/HLSL/DxcValidatorBase.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
///////////////////////////////////////////////////////////////////////////////
// //
// DxcValidatorBase.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 base validation functionality //
// //
///////////////////////////////////////////////////////////////////////////////

#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"

#include "dxc/DxilContainer/DxilContainer.h"
#include "dxc/HLSL/DxcValidatorBase.h"
#include "dxc/HLSL/DxilValidation.h"
#include "dxc/Support/WinIncludes.h"

#include "dxc/DxilRootSignature/DxilRootSignature.h"
#include "dxc/Support/FileIOHelper.h"
#include "dxc/Support/Global.h"
#include "dxc/Support/dxcapi.impl.h"
#include "dxc/dxcapi.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 DxcValidatorBase::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 DxcValidatorBase::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 DxcValidatorBase::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 DxcValidatorBase::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) {
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
DxcValidatorBase::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);

DxcValidatorBase *pInternalValidator = (DxcValidatorBase *)pValidator;
return pInternalValidator->ValidateWithOptModules(pShader, Flags, pModule,
pDebugModule, ppResult);
}
2 changes: 1 addition & 1 deletion lib/HLSL/LLVMBuild.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
type = Library
name = HLSL
parent = Libraries
required_libraries = BitReader Core DxcSupport DxilContainer IPA Support DXIL DxcBindingTable
required_libraries = BitReader Core DxcSupport DxilContainer DxilRootSignature IPA Support DXIL DxcBindingTable
1 change: 1 addition & 0 deletions tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ if (WIN32)
# This target can currently only be built on Windows.
add_llvm_tool_subdirectory(dxexp)
endif (WIN32)
add_llvm_tool_subdirectory(no-sig-dxillib)
# HLSL Change ends

# add_llvm_tool_subdirectory(llc) # HLSL Change
Expand Down
12 changes: 4 additions & 8 deletions tools/clang/tools/dxclib/dxc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,13 @@
// /Gpp - Force partial precision.
// /Lx - Output hexadecimal literals
// /Op - Disable preshaders
//
// Unimplemented but on roadmap:
//
// /matchUAVs - Match template shader UAV slot allocations in the current
// shader /mergeUAVs - Merge UAV slot allocations of template shader and the
// current shader /Ni - Output instruction numbers in assembly listings
// shader
// /mergeUAVs - Merge UAV slot allocations of template shader and the
// current shader
// /Ni - Output instruction numbers in assembly listings
// /No - Output instruction byte offset in assembly listings
// /Qstrip_reflect
// /res_may_alias
// /shtemplate
// /verifyrootsignature
//

#include "dxc.h"
Expand Down
2 changes: 1 addition & 1 deletion tools/clang/tools/dxcompiler/dxcapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ HRESULT CreateDxcContainerReflection(REFIID riid, _Out_ LPVOID *ppv) {
HRESULT CreateDxcContainerBuilder(REFIID riid, _Out_ LPVOID *ppv) {
// Call dxil.dll's containerbuilder
*ppv = nullptr;
const char *warning;
const char *warning = nullptr;
HRESULT hr = DxilLibCreateInstance(CLSID_DxcContainerBuilder,
(IDxcContainerBuilder **)ppv);
if (FAILED(hr)) {
Expand Down
Loading