diff --git a/source/compiler-core/slang-downstream-compiler.h b/source/compiler-core/slang-downstream-compiler.h index c0cc868d10..82aaef1076 100644 --- a/source/compiler-core/slang-downstream-compiler.h +++ b/source/compiler-core/slang-downstream-compiler.h @@ -337,6 +337,9 @@ class IDownstreamCompiler : public ICastable /// Validate and return the result virtual SLANG_NO_THROW SlangResult SLANG_MCALL validate(const uint32_t* contents, int contentsSize) = 0; + /// Disassemble and print to stdout + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + disassemble(const uint32_t* contents, int contentsSize) = 0; /// True if underlying compiler uses file system to communicate source virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() = 0; @@ -374,6 +377,13 @@ class DownstreamCompilerBase : public ComBaseObject, public IDownstreamCompiler SLANG_UNUSED(contentsSize); return SLANG_FAIL; } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + disassemble(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE + { + SLANG_UNUSED(contents); + SLANG_UNUSED(contentsSize); + return SLANG_FAIL; + } DownstreamCompilerBase(const Desc& desc) : m_desc(desc) diff --git a/source/compiler-core/slang-glslang-compiler.cpp b/source/compiler-core/slang-glslang-compiler.cpp index 5550ac8ade..b619f468f3 100644 --- a/source/compiler-core/slang-glslang-compiler.cpp +++ b/source/compiler-core/slang-glslang-compiler.cpp @@ -47,6 +47,8 @@ class GlslangDownstreamCompiler : public DownstreamCompilerBase SLANG_OVERRIDE; virtual SLANG_NO_THROW SlangResult SLANG_MCALL validate(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + disassemble(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE; /// Must be called before use SlangResult init(ISlangSharedLibrary* library); @@ -63,6 +65,7 @@ class GlslangDownstreamCompiler : public DownstreamCompilerBase glslang_CompileFunc_1_1 m_compile_1_1 = nullptr; glslang_CompileFunc_1_2 m_compile_1_2 = nullptr; glslang_ValidateSPIRVFunc m_validate = nullptr; + glslang_DisassembleSPIRVFunc m_disassemble = nullptr; ComPtr m_sharedLibrary; @@ -75,7 +78,8 @@ SlangResult GlslangDownstreamCompiler::init(ISlangSharedLibrary* library) m_compile_1_1 = (glslang_CompileFunc_1_1)library->findFuncByName("glslang_compile_1_1"); m_compile_1_2 = (glslang_CompileFunc_1_2)library->findFuncByName("glslang_compile_1_2"); m_validate = (glslang_ValidateSPIRVFunc)library->findFuncByName("glslang_validateSPIRV"); - + m_disassemble = + (glslang_DisassembleSPIRVFunc)library->findFuncByName("glslang_disassembleSPIRV"); if (m_compile_1_0 == nullptr && m_compile_1_1 == nullptr && m_compile_1_2 == nullptr) { @@ -305,6 +309,20 @@ SlangResult GlslangDownstreamCompiler::validate(const uint32_t* contents, int co return SLANG_FAIL; } +SlangResult GlslangDownstreamCompiler::disassemble(const uint32_t* contents, int contentsSize) +{ + if (m_disassemble == nullptr) + { + return SLANG_FAIL; + } + + if (m_disassemble(contents, contentsSize)) + { + return SLANG_OK; + } + return SLANG_FAIL; +} + bool GlslangDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactDesc& to) { // Can only disassemble blobs that are SPIR-V diff --git a/source/compiler-core/slang-json-rpc-connection.cpp b/source/compiler-core/slang-json-rpc-connection.cpp index 79ffc95831..fbbd23d75a 100644 --- a/source/compiler-core/slang-json-rpc-connection.cpp +++ b/source/compiler-core/slang-json-rpc-connection.cpp @@ -273,6 +273,10 @@ SlangResult JSONRPCConnection::sendCall( SlangResult JSONRPCConnection::waitForResult(Int timeOutInMs) { + // Invalidate m_jsonRoot before waitForResult, because when waitForResult fail, + // we don't want to use the result from the previous read. + m_jsonRoot.reset(); + SLANG_RETURN_ON_FAIL(m_connection->waitForResult(timeOutInMs)); return tryReadMessage(); } diff --git a/source/slang-glslang/slang-glslang.cpp b/source/slang-glslang/slang-glslang.cpp index 4abcada624..ca45be05b0 100644 --- a/source/slang-glslang/slang-glslang.cpp +++ b/source/slang-glslang/slang-glslang.cpp @@ -182,6 +182,37 @@ extern "C" return tools.Validate(contents, contentsSize, options); } +// Disassemble the given SPIRV-ASM instructions. +extern "C" +#ifdef _MSC_VER + _declspec(dllexport) +#else + __attribute__((__visibility__("default"))) +#endif + bool glslang_disassembleSPIRV(const uint32_t* contents, int contentsSize) +{ + static const auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_5; + + uint32_t options = SPV_BINARY_TO_TEXT_OPTION_NONE; + options |= SPV_BINARY_TO_TEXT_OPTION_COMMENT; + options |= SPV_BINARY_TO_TEXT_OPTION_PRINT; + options |= SPV_BINARY_TO_TEXT_OPTION_COLOR; + + spv_diagnostic diagnostic = nullptr; + spv_context context = spvContextCreate(kDefaultEnvironment); + spv_result_t error = + spvBinaryToText(context, contents, contentsSize, options, nullptr, &diagnostic); + spvContextDestroy(context); + if (error) + { + spvDiagnosticPrint(diagnostic); + spvDiagnosticDestroy(diagnostic); + return false; + } + + return true; +} + // Apply the SPIRV-Tools optimizer to generated SPIR-V based on the desired optimization level // TODO: add flag for optimizing SPIR-V size as well static void glslang_optimizeSPIRV( diff --git a/source/slang-glslang/slang-glslang.h b/source/slang-glslang/slang-glslang.h index cfeed975ae..7b955c5af7 100644 --- a/source/slang-glslang/slang-glslang.h +++ b/source/slang-glslang/slang-glslang.h @@ -156,5 +156,6 @@ typedef int (*glslang_CompileFunc_1_0)(glslang_CompileRequest_1_0* request); typedef int (*glslang_CompileFunc_1_1)(glslang_CompileRequest_1_1* request); typedef int (*glslang_CompileFunc_1_2)(glslang_CompileRequest_1_2* request); typedef bool (*glslang_ValidateSPIRVFunc)(const uint32_t* contents, int contentsSize); +typedef bool (*glslang_DisassembleSPIRVFunc)(const uint32_t* contents, int contentsSize); #endif diff --git a/source/slang-llvm/slang-llvm.cpp b/source/slang-llvm/slang-llvm.cpp index 990f99f747..86565a4852 100644 --- a/source/slang-llvm/slang-llvm.cpp +++ b/source/slang-llvm/slang-llvm.cpp @@ -140,6 +140,13 @@ class LLVMDownstreamCompiler : public ComBaseObject, public IDownstreamCompiler SLANG_UNUSED(contentsSize); return SLANG_FAIL; } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + disassemble(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE + { + SLANG_UNUSED(contents); + SLANG_UNUSED(contentsSize); + return SLANG_FAIL; + } LLVMDownstreamCompiler() : m_desc( diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 9d08d5b73c..821a895bc7 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -2562,11 +2562,7 @@ DIAGNOSTIC( Internal, serialDebugVerificationFailed, "Verification of serial debug information failed.") -DIAGNOSTIC( - 99999, - Internal, - spirvValidationFailed, - "Validation of generated SPIR-V failed. SPIRV generated: \n$0") +DIAGNOSTIC(99999, Internal, spirvValidationFailed, "Validation of generated SPIR-V failed.") DIAGNOSTIC( 99999, diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 676a16228c..d8c479cd12 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -12,7 +12,6 @@ #include "slang-ir-util.h" #include "slang-ir.h" #include "slang-lookup-spirv.h" -#include "slang-spirv-val.h" #include "spirv/unified1/spirv.h" #include diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index f9118bb452..7ea2fef882 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -104,7 +104,6 @@ #include "slang-legalize-types.h" #include "slang-lower-to-ir.h" #include "slang-mangle.h" -#include "slang-spirv-val.h" #include "slang-syntax.h" #include "slang-type-layout.h" #include "slang-visitor.h" @@ -1942,18 +1941,16 @@ SlangResult emitSPIRVForEntryPointsDirectly( ArtifactUtil::createArtifactForCompileTarget(asExternal(codeGenContext->getTargetFormat())); artifact->addRepresentationUnknown(ListBlob::moveCreate(spirv)); -#if 0 - // Dump the unoptimized SPIRV after lowering from slang IR -> SPIRV - String err; String dis; - disassembleSPIRV(spirv, err, dis); - printf("%s", dis.begin()); -#endif - IDownstreamCompiler* compiler = codeGenContext->getSession()->getOrLoadDownstreamCompiler( PassThroughMode::SpirvOpt, codeGenContext->getSink()); if (compiler) { +#if 0 + // Dump the unoptimized SPIRV after lowering from slang IR -> SPIRV + compiler->disassemble((uint32_t*)spirv.getBuffer(), int(spirv.getCount() / 4)); +#endif + if (!codeGenContext->shouldSkipSPIRVValidation()) { StringBuilder runSpirvValEnvVar; @@ -1966,13 +1963,10 @@ SlangResult emitSPIRVForEntryPointsDirectly( (uint32_t*)spirv.getBuffer(), int(spirv.getCount() / 4)))) { - String err; - String dis; - disassembleSPIRV(spirv, err, dis); + compiler->disassemble((uint32_t*)spirv.getBuffer(), int(spirv.getCount() / 4)); codeGenContext->getSink()->diagnoseWithoutSourceView( SourceLoc{}, - Diagnostics::spirvValidationFailed, - dis); + Diagnostics::spirvValidationFailed); } } } diff --git a/source/slang/slang-spirv-val.cpp b/source/slang/slang-spirv-val.cpp deleted file mode 100644 index e2b4da46c8..0000000000 --- a/source/slang/slang-spirv-val.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "slang-spirv-val.h" - -namespace Slang -{ - -SlangResult disassembleSPIRV(const List& spirv, String& outErr, String& outDis) -{ - // Set up our process - CommandLine commandLine; - commandLine.m_executableLocation.setName("spirv-dis"); - commandLine.addArg("--comment"); - commandLine.addArg("--color"); - RefPtr p; - - // If we failed to even start the process, then validation isn't available - SLANG_RETURN_ON_FAIL(Process::create(commandLine, 0, p)); - const auto in = p->getStream(StdStreamType::In); - const auto out = p->getStream(StdStreamType::Out); - const auto err = p->getStream(StdStreamType::ErrorOut); - - List outData; - List outErrData; - SLANG_RETURN_ON_FAIL( - StreamUtil::readAndWrite(in, spirv.getArrayView(), out, outData, err, outErrData)); - - SLANG_RETURN_ON_FAIL(p->waitForTermination(10)); - - outDis = String( - reinterpret_cast(outData.begin()), - reinterpret_cast(outData.end())); - - outErr = String( - reinterpret_cast(outErrData.begin()), - reinterpret_cast(outErrData.end())); - - const auto ret = p->getReturnValue(); - return ret == 0 ? SLANG_OK : SLANG_FAIL; -} - - -} // namespace Slang diff --git a/source/slang/slang-spirv-val.h b/source/slang/slang-spirv-val.h deleted file mode 100644 index 01e111f91a..0000000000 --- a/source/slang/slang-spirv-val.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "slang-compiler.h" - -#include - -namespace Slang -{ -SlangResult disassembleSPIRV(const List& spirv, String& outErr, String& outDis); -} diff --git a/tests/diagnostics/illegal-func-decl.slang b/tests/diagnostics/illegal-func-decl.slang index 0ec73dc277..64199a7913 100644 --- a/tests/diagnostics/illegal-func-decl.slang +++ b/tests/diagnostics/illegal-func-decl.slang @@ -6,9 +6,9 @@ //TEST:COMPILE: tests/diagnostics/illegal-func-decl-module.slang -o tests/diagnostics/illegal-func-decl-module.slang-module //DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK1): -r tests/diagnostics/illegal-func-decl-module.slang-module -DTEST1 -target spirv -o illegal-func-decl.spv -//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK2): -r tests/diagnostics/illegal-func-decl-module.slang-module -DTEST2 -target spirv -o illegal-func-decl.spv +//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK2): -r tests/diagnostics/illegal-func-decl-module.slang-module -DTEST2 -target spirv -o illegal-func-decl.spv -skip-spirv-validation //DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK3): -r tests/diagnostics/illegal-func-decl-module.slang-module -DTEST3 -target spirv -o illegal-func-decl.spv -//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK4): -r tests/diagnostics/illegal-func-decl-module.slang-module -DTEST4 -target spirv -o illegal-func-decl.spv +//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK4): -r tests/diagnostics/illegal-func-decl-module.slang-module -DTEST4 -target spirv -o illegal-func-decl.spv -skip-spirv-validation #ifdef TEST1 // CHECK1: ([[# @LINE+1]]): error 45001: unresolved external symbol 'libraryFunction'. diff --git a/tests/language-feature/capability/capability3.slang b/tests/language-feature/capability/capability3.slang index 67099a1dad..4091b9c936 100644 --- a/tests/language-feature/capability/capability3.slang +++ b/tests/language-feature/capability/capability3.slang @@ -1,5 +1,5 @@ //TEST:SIMPLE(filecheck=CHECK): -target spirv -emit-spirv-directly -entry main -stage compute -//TEST:SIMPLE(filecheck=CHECK_IGNORE_CAPS): -target spirv -emit-spirv-directly -entry main -stage compute -ignore-capabilities +//TEST:SIMPLE(filecheck=CHECK_IGNORE_CAPS): -target spirv -emit-spirv-directly -entry main -stage compute -ignore-capabilities -skip-spirv-validation // CHECK_IGNORE_CAPS-NOT: error 36108 // Test that capabilities can be declared on module. @@ -39,4 +39,4 @@ void main() { use1(); use2(); -} \ No newline at end of file +} diff --git a/tests/language-feature/capability/capability7.slang b/tests/language-feature/capability/capability7.slang index 21f3d68e41..011112a34a 100644 --- a/tests/language-feature/capability/capability7.slang +++ b/tests/language-feature/capability/capability7.slang @@ -1,5 +1,5 @@ //TEST:SIMPLE(filecheck=CHECK): -target glsl -entry computeMain -stage compute -profile sm_5_0 -//TEST:SIMPLE(filecheck=CHECK_IGNORE_CAPS): -target glsl -emit-spirv-directly -entry computeMain -stage compute -profile sm_5_0 -ignore-capabilities +//TEST:SIMPLE(filecheck=CHECK_IGNORE_CAPS): -target glsl -emit-spirv-directly -entry computeMain -stage compute -profile sm_5_0 -ignore-capabilities -skip-spirv-validation // Test that we diagnose simplified capabilities // CHECK_IGNORE_CAPS-NOT: error 36104 diff --git a/tests/language-feature/capability/conflicting-profile-stage-for-entry-point.slang b/tests/language-feature/capability/conflicting-profile-stage-for-entry-point.slang index 9cc06347f7..a888e7cf96 100644 --- a/tests/language-feature/capability/conflicting-profile-stage-for-entry-point.slang +++ b/tests/language-feature/capability/conflicting-profile-stage-for-entry-point.slang @@ -3,7 +3,7 @@ //TEST:SIMPLE(filecheck=CHECK): -target spirv -entry vsmain -profile vs_6_0 //TEST:SIMPLE(filecheck=CHECK): -target spirv -entry psmain -profile vs_6_0 -ignore-capabilities -//TEST:SIMPLE(filecheck=CHECK): -target spirv -entry vsmain -profile ps_6_0 -ignore-capabilities +//TEST:SIMPLE(filecheck=CHECK): -target spirv -entry vsmain -profile ps_6_0 -ignore-capabilities -skip-spirv-validation // CHECK_ERROR: warning 36112 // CHECK-NOT: warning 36112 @@ -33,4 +33,4 @@ VSOutput vsmain(float3 PositionOS : POSITION, float3 Color : COLOR0) float4 psmain(VSOutput input) : SV_TARGET { return float4(input.Color, 1); -} \ No newline at end of file +}