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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions tools/clang/test/HLSL/val-wave-failures-ps.hlsl
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// RUN: %dxc -E main -T ps_6_0 %s /Zi | FileCheck %s

// CHECK: Gradient operations are not affected by wave-sensitive data or control flow.
// CHECK: Gradient operations are not affected by wave-sensitive data or control flow.
// CHECK: Gradient operations are not affected by wave-sensitive data or control flow.
// CHECK: val-wave-failures-ps.hlsl:10:9 Gradient operations are not affected by wave-sensitive data or control flow.
// CHECK: val-wave-failures-ps.hlsl:30:12 Gradient operations are not affected by wave-sensitive data or control flow.
// CHECK: val-wave-failures-ps.hlsl:40:12 Gradient operations are not affected by wave-sensitive data or control flow.

float4 main(float4 p: SV_Position) : SV_Target {
// cannot feed into ddx
Expand Down
81 changes: 48 additions & 33 deletions tools/clang/tools/dxcompiler/dxcompilerobj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1784,6 +1784,36 @@ static void PrintPipelineStateValidationRuntimeInfo(const char *pBuffer, DXIL::S
OS << comment << "\n";
}

// Class to manage lifetime of llvm module and provide some utility
// functions used for generating compiler output.
class DxilCompilerLLVMModuleOutput {
public:
DxilCompilerLLVMModuleOutput(std::unique_ptr<llvm::Module> module)
: m_llvmModule(std::move(module))
{ }

void CloneForDebugInfo() {
m_llvmModuleWithDebugInfo.reset(llvm::CloneModule(m_llvmModule.get()));
}

void WrapModuleInDxilContainer(IMalloc *pMalloc, AbstractMemoryStream *pModuleBitcode, CComPtr<IDxcBlob> &pDxilContainerBlob) {
CComPtr<AbstractMemoryStream> pContainerStream;
IFT(CreateMemoryStream(pMalloc, &pContainerStream));
SerializeDxilContainerForModule(m_llvmModule.get(), pModuleBitcode, pContainerStream);

pDxilContainerBlob.Release();
IFT(pContainerStream.QueryInterface(&pDxilContainerBlob));
}

llvm::Module *get() { return m_llvmModule.get(); }
llvm::Module *getWithDebugInfo() { return m_llvmModuleWithDebugInfo.get(); }

private:
std::unique_ptr<llvm::Module> m_llvmModule;
std::unique_ptr<llvm::Module> m_llvmModuleWithDebugInfo;
};


class DxcCompiler : public IDxcCompiler, public IDxcLangExtensions, public IDxcContainerEvent {
private:
DXC_MICROCOM_REF_FIELD(m_dwRef)
Expand Down Expand Up @@ -2002,53 +2032,38 @@ class DxcCompiler : public IDxcCompiler, public IDxcLangExtensions, public IDxcC
action.BeginSourceFile(compiler, file);
action.Execute();
action.EndSourceFile();
outStream.flush();

// Don't do work to put in a container if an error has occurred, or if
// there is only a a high-level representation in the module.

// Don't do work to put in a container if an error has occurred
bool compileOK = !compiler.getDiagnostics().hasErrorOccurred();
if (compileOK) {
HRESULT valHR = S_OK;
if (needsValidation) {
outStream.flush();

CComPtr<AbstractMemoryStream> pFinalStream;
IFT(CreateMemoryStream(pMalloc, &pFinalStream));

llvm::Module *pDebugModule, *pOrigModule;
std::unique_ptr<llvm::Module> llvmModule = action.takeModule();
std::unique_ptr<llvm::Module> llvmClonedModule;
if (internalValidator && opts.DebugInfo) {
// If using the internal validator, we'll use the modules directly.
// In this case, we'll want to make a clone to avoid SerializeDxilContainerForModule
// destroying this.
llvmClonedModule.reset(llvm::CloneModule(llvmModule.get()));
pDebugModule = llvmClonedModule.get();
SerializeDxilContainerForModule(llvmModule.get(), pOutputStream, pFinalStream);
pOrigModule = llvmModule.get();
}
else {
pOrigModule = llvmModule.get();
pDebugModule = nullptr;
SerializeDxilContainerForModule(llvmModule.get(), pOutputStream, pFinalStream);
}
pOutputBlob.Release();
IFT(pFinalStream.QueryInterface(&pOutputBlob));

CComPtr<IDxcBlob> pFinalStreamBlob;
CComPtr<IDxcOperationResult> pValResult;
IFT(pFinalStream.QueryInterface(&pFinalStreamBlob));
// Take ownership of the module from the action.
DxilCompilerLLVMModuleOutput llvmModule(action.takeModule());

// If using the internal validator, we'll use the modules directly.
// In this case, we'll want to make a clone to avoid SerializeDxilContainerForModule
// stripping all the debug info. The debug info will be stripped from the orginal
// module, but preserved in the cloned module.
if (internalValidator && opts.DebugInfo)
llvmModule.CloneForDebugInfo();

// Do not create a container when there is only a a high-level representation in the module.
if (!opts.CodeGenHighLevel)
llvmModule.WrapModuleInDxilContainer(pMalloc, pOutputStream, pOutputBlob);

if (needsValidation) {
// Important: in-place edit is required so the blob is reused and thus
// dxil.dll can be released.
if (internalValidator) {
IFT(RunInternalValidator(
pValidator, pOrigModule, pDebugModule, pFinalStreamBlob,
pValidator, llvmModule.get(), llvmModule.getWithDebugInfo(), pOutputBlob,
DxcValidatorFlags_InPlaceEdit, &pValResult));
}
else {
IFT(pValidator->Validate(
pFinalStreamBlob, DxcValidatorFlags_InPlaceEdit, &pValResult));
pOutputBlob, DxcValidatorFlags_InPlaceEdit, &pValResult));
}
IFT(pValResult->GetStatus(&valHR));
if (FAILED(valHR)) {
Expand Down
19 changes: 19 additions & 0 deletions tools/clang/unittests/HLSL/CompilerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ class CompilerTest {

TEST_METHOD(CompileWhenODumpThenPassConfig)
TEST_METHOD(CompileWhenODumpThenOptimizerMatch)
TEST_METHOD(CompileWhenVdThenProducesDxilContainer)

TEST_METHOD(CompileWhenShaderModelMismatchAttributeThenFail)
TEST_METHOD(CompileBadHlslThenFail)
Expand Down Expand Up @@ -1524,6 +1525,24 @@ TEST_F(CompilerTest, CompileWhenODumpThenPassConfig) {
VERIFY_ARE_NOT_EQUAL(string::npos, passes.find("inline"));
}

TEST_F(CompilerTest, CompileWhenVdThenProducesDxilContainer) {
CComPtr<IDxcCompiler> pCompiler;
CComPtr<IDxcOperationResult> pResult;
CComPtr<IDxcBlobEncoding> pSource;

VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
CreateBlobFromText(EmptyCompute, &pSource);

LPCWSTR Args[] = { L"/Vd" };

VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
L"cs_6_0", Args, _countof(Args), nullptr, 0, nullptr, &pResult));
VerifyOperationSucceeded(pResult);
CComPtr<IDxcBlob> pResultBlob;
VERIFY_SUCCEEDED(pResult->GetResult(&pResultBlob));
VERIFY_IS_TRUE(hlsl::IsValidDxilContainer(reinterpret_cast<hlsl::DxilContainerHeader *>(pResultBlob->GetBufferPointer()), pResultBlob->GetBufferSize()));
}

TEST_F(CompilerTest, CompileWhenODumpThenOptimizerMatch) {
LPCWSTR OptLevels[] = { L"/Od", L"/O1", L"/O2" };
CComPtr<IDxcCompiler> pCompiler;
Expand Down