Skip to content

Commit 5621ace

Browse files
authored
Use disassemble API from SPIRV-Tools (shader-slang#6001)
* Use disassemble API from SPIRV-Tools This commit uses C API version of SPIRV disassemble function rather than calling spirv-dis.exe. This allows us to use a correct version of SPIRV disassble function that Slangc.exe is using. The implementation is mostly copied from external/spirv-tools/tools/dis/dis.cpp, which is a source file for building spirv-dis.exe. This commit also includes a fix for a bug in RPC communication to `test-server`. When an RPC connection to `test-server.exe` is reused and the second test abruptly fails due to a compile error or SPIRV validation error, the output from the first test run was incorrectly reused as the output for the second test. This commit resets the RPC result before waiting for the response so that even when the RPC connection is erratically disconnected, the result from the previous run will not be reused incorrectly. Some of the tests appear to be relying on this type of behavior. By using an option, `-skip-spirv-validation`, the RPC connection will continue without an interruption.
1 parent a448b7e commit 5621ace

15 files changed

+87
-78
lines changed

source/compiler-core/slang-downstream-compiler.h

+10
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,9 @@ class IDownstreamCompiler : public ICastable
337337
/// Validate and return the result
338338
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
339339
validate(const uint32_t* contents, int contentsSize) = 0;
340+
/// Disassemble and print to stdout
341+
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
342+
disassemble(const uint32_t* contents, int contentsSize) = 0;
340343

341344
/// True if underlying compiler uses file system to communicate source
342345
virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() = 0;
@@ -374,6 +377,13 @@ class DownstreamCompilerBase : public ComBaseObject, public IDownstreamCompiler
374377
SLANG_UNUSED(contentsSize);
375378
return SLANG_FAIL;
376379
}
380+
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
381+
disassemble(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE
382+
{
383+
SLANG_UNUSED(contents);
384+
SLANG_UNUSED(contentsSize);
385+
return SLANG_FAIL;
386+
}
377387

378388
DownstreamCompilerBase(const Desc& desc)
379389
: m_desc(desc)

source/compiler-core/slang-glslang-compiler.cpp

+19-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class GlslangDownstreamCompiler : public DownstreamCompilerBase
4747
SLANG_OVERRIDE;
4848
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
4949
validate(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE;
50+
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
51+
disassemble(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE;
5052

5153
/// Must be called before use
5254
SlangResult init(ISlangSharedLibrary* library);
@@ -63,6 +65,7 @@ class GlslangDownstreamCompiler : public DownstreamCompilerBase
6365
glslang_CompileFunc_1_1 m_compile_1_1 = nullptr;
6466
glslang_CompileFunc_1_2 m_compile_1_2 = nullptr;
6567
glslang_ValidateSPIRVFunc m_validate = nullptr;
68+
glslang_DisassembleSPIRVFunc m_disassemble = nullptr;
6669

6770
ComPtr<ISlangSharedLibrary> m_sharedLibrary;
6871

@@ -75,7 +78,8 @@ SlangResult GlslangDownstreamCompiler::init(ISlangSharedLibrary* library)
7578
m_compile_1_1 = (glslang_CompileFunc_1_1)library->findFuncByName("glslang_compile_1_1");
7679
m_compile_1_2 = (glslang_CompileFunc_1_2)library->findFuncByName("glslang_compile_1_2");
7780
m_validate = (glslang_ValidateSPIRVFunc)library->findFuncByName("glslang_validateSPIRV");
78-
81+
m_disassemble =
82+
(glslang_DisassembleSPIRVFunc)library->findFuncByName("glslang_disassembleSPIRV");
7983

8084
if (m_compile_1_0 == nullptr && m_compile_1_1 == nullptr && m_compile_1_2 == nullptr)
8185
{
@@ -305,6 +309,20 @@ SlangResult GlslangDownstreamCompiler::validate(const uint32_t* contents, int co
305309
return SLANG_FAIL;
306310
}
307311

312+
SlangResult GlslangDownstreamCompiler::disassemble(const uint32_t* contents, int contentsSize)
313+
{
314+
if (m_disassemble == nullptr)
315+
{
316+
return SLANG_FAIL;
317+
}
318+
319+
if (m_disassemble(contents, contentsSize))
320+
{
321+
return SLANG_OK;
322+
}
323+
return SLANG_FAIL;
324+
}
325+
308326
bool GlslangDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactDesc& to)
309327
{
310328
// Can only disassemble blobs that are SPIR-V

source/compiler-core/slang-json-rpc-connection.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ SlangResult JSONRPCConnection::sendCall(
273273

274274
SlangResult JSONRPCConnection::waitForResult(Int timeOutInMs)
275275
{
276+
// Invalidate m_jsonRoot before waitForResult, because when waitForResult fail,
277+
// we don't want to use the result from the previous read.
278+
m_jsonRoot.reset();
279+
276280
SLANG_RETURN_ON_FAIL(m_connection->waitForResult(timeOutInMs));
277281
return tryReadMessage();
278282
}

source/slang-glslang/slang-glslang.cpp

+31
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,37 @@ extern "C"
182182
return tools.Validate(contents, contentsSize, options);
183183
}
184184

185+
// Disassemble the given SPIRV-ASM instructions.
186+
extern "C"
187+
#ifdef _MSC_VER
188+
_declspec(dllexport)
189+
#else
190+
__attribute__((__visibility__("default")))
191+
#endif
192+
bool glslang_disassembleSPIRV(const uint32_t* contents, int contentsSize)
193+
{
194+
static const auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_5;
195+
196+
uint32_t options = SPV_BINARY_TO_TEXT_OPTION_NONE;
197+
options |= SPV_BINARY_TO_TEXT_OPTION_COMMENT;
198+
options |= SPV_BINARY_TO_TEXT_OPTION_PRINT;
199+
options |= SPV_BINARY_TO_TEXT_OPTION_COLOR;
200+
201+
spv_diagnostic diagnostic = nullptr;
202+
spv_context context = spvContextCreate(kDefaultEnvironment);
203+
spv_result_t error =
204+
spvBinaryToText(context, contents, contentsSize, options, nullptr, &diagnostic);
205+
spvContextDestroy(context);
206+
if (error)
207+
{
208+
spvDiagnosticPrint(diagnostic);
209+
spvDiagnosticDestroy(diagnostic);
210+
return false;
211+
}
212+
213+
return true;
214+
}
215+
185216
// Apply the SPIRV-Tools optimizer to generated SPIR-V based on the desired optimization level
186217
// TODO: add flag for optimizing SPIR-V size as well
187218
static void glslang_optimizeSPIRV(

source/slang-glslang/slang-glslang.h

+1
Original file line numberDiff line numberDiff line change
@@ -156,5 +156,6 @@ typedef int (*glslang_CompileFunc_1_0)(glslang_CompileRequest_1_0* request);
156156
typedef int (*glslang_CompileFunc_1_1)(glslang_CompileRequest_1_1* request);
157157
typedef int (*glslang_CompileFunc_1_2)(glslang_CompileRequest_1_2* request);
158158
typedef bool (*glslang_ValidateSPIRVFunc)(const uint32_t* contents, int contentsSize);
159+
typedef bool (*glslang_DisassembleSPIRVFunc)(const uint32_t* contents, int contentsSize);
159160

160161
#endif

source/slang-llvm/slang-llvm.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@ class LLVMDownstreamCompiler : public ComBaseObject, public IDownstreamCompiler
140140
SLANG_UNUSED(contentsSize);
141141
return SLANG_FAIL;
142142
}
143+
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
144+
disassemble(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE
145+
{
146+
SLANG_UNUSED(contents);
147+
SLANG_UNUSED(contentsSize);
148+
return SLANG_FAIL;
149+
}
143150

144151
LLVMDownstreamCompiler()
145152
: m_desc(

source/slang/slang-diagnostic-defs.h

+1-5
Original file line numberDiff line numberDiff line change
@@ -2562,11 +2562,7 @@ DIAGNOSTIC(
25622562
Internal,
25632563
serialDebugVerificationFailed,
25642564
"Verification of serial debug information failed.")
2565-
DIAGNOSTIC(
2566-
99999,
2567-
Internal,
2568-
spirvValidationFailed,
2569-
"Validation of generated SPIR-V failed. SPIRV generated: \n$0")
2565+
DIAGNOSTIC(99999, Internal, spirvValidationFailed, "Validation of generated SPIR-V failed.")
25702566

25712567
DIAGNOSTIC(
25722568
99999,

source/slang/slang-emit-spirv.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include "slang-ir-util.h"
1313
#include "slang-ir.h"
1414
#include "slang-lookup-spirv.h"
15-
#include "slang-spirv-val.h"
1615
#include "spirv/unified1/spirv.h"
1716

1817
#include <type_traits>

source/slang/slang-emit.cpp

+7-13
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@
104104
#include "slang-legalize-types.h"
105105
#include "slang-lower-to-ir.h"
106106
#include "slang-mangle.h"
107-
#include "slang-spirv-val.h"
108107
#include "slang-syntax.h"
109108
#include "slang-type-layout.h"
110109
#include "slang-visitor.h"
@@ -1942,18 +1941,16 @@ SlangResult emitSPIRVForEntryPointsDirectly(
19421941
ArtifactUtil::createArtifactForCompileTarget(asExternal(codeGenContext->getTargetFormat()));
19431942
artifact->addRepresentationUnknown(ListBlob::moveCreate(spirv));
19441943

1945-
#if 0
1946-
// Dump the unoptimized SPIRV after lowering from slang IR -> SPIRV
1947-
String err; String dis;
1948-
disassembleSPIRV(spirv, err, dis);
1949-
printf("%s", dis.begin());
1950-
#endif
1951-
19521944
IDownstreamCompiler* compiler = codeGenContext->getSession()->getOrLoadDownstreamCompiler(
19531945
PassThroughMode::SpirvOpt,
19541946
codeGenContext->getSink());
19551947
if (compiler)
19561948
{
1949+
#if 0
1950+
// Dump the unoptimized SPIRV after lowering from slang IR -> SPIRV
1951+
compiler->disassemble((uint32_t*)spirv.getBuffer(), int(spirv.getCount() / 4));
1952+
#endif
1953+
19571954
if (!codeGenContext->shouldSkipSPIRVValidation())
19581955
{
19591956
StringBuilder runSpirvValEnvVar;
@@ -1966,13 +1963,10 @@ SlangResult emitSPIRVForEntryPointsDirectly(
19661963
(uint32_t*)spirv.getBuffer(),
19671964
int(spirv.getCount() / 4))))
19681965
{
1969-
String err;
1970-
String dis;
1971-
disassembleSPIRV(spirv, err, dis);
1966+
compiler->disassemble((uint32_t*)spirv.getBuffer(), int(spirv.getCount() / 4));
19721967
codeGenContext->getSink()->diagnoseWithoutSourceView(
19731968
SourceLoc{},
1974-
Diagnostics::spirvValidationFailed,
1975-
dis);
1969+
Diagnostics::spirvValidationFailed);
19761970
}
19771971
}
19781972
}

source/slang/slang-spirv-val.cpp

-41
This file was deleted.

source/slang/slang-spirv-val.h

-10
This file was deleted.

tests/diagnostics/illegal-func-decl.slang

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
//TEST:COMPILE: tests/diagnostics/illegal-func-decl-module.slang -o tests/diagnostics/illegal-func-decl-module.slang-module
77

88
//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK1): -r tests/diagnostics/illegal-func-decl-module.slang-module -DTEST1 -target spirv -o illegal-func-decl.spv
9-
//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK2): -r tests/diagnostics/illegal-func-decl-module.slang-module -DTEST2 -target spirv -o illegal-func-decl.spv
9+
//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
1010
//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK3): -r tests/diagnostics/illegal-func-decl-module.slang-module -DTEST3 -target spirv -o illegal-func-decl.spv
11-
//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK4): -r tests/diagnostics/illegal-func-decl-module.slang-module -DTEST4 -target spirv -o illegal-func-decl.spv
11+
//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
1212

1313
#ifdef TEST1
1414
// CHECK1: ([[# @LINE+1]]): error 45001: unresolved external symbol 'libraryFunction'.

tests/language-feature/capability/capability3.slang

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//TEST:SIMPLE(filecheck=CHECK): -target spirv -emit-spirv-directly -entry main -stage compute
2-
//TEST:SIMPLE(filecheck=CHECK_IGNORE_CAPS): -target spirv -emit-spirv-directly -entry main -stage compute -ignore-capabilities
2+
//TEST:SIMPLE(filecheck=CHECK_IGNORE_CAPS): -target spirv -emit-spirv-directly -entry main -stage compute -ignore-capabilities -skip-spirv-validation
33
// CHECK_IGNORE_CAPS-NOT: error 36108
44

55
// Test that capabilities can be declared on module.
@@ -39,4 +39,4 @@ void main()
3939
{
4040
use1();
4141
use2();
42-
}
42+
}

tests/language-feature/capability/capability7.slang

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//TEST:SIMPLE(filecheck=CHECK): -target glsl -entry computeMain -stage compute -profile sm_5_0
2-
//TEST:SIMPLE(filecheck=CHECK_IGNORE_CAPS): -target glsl -emit-spirv-directly -entry computeMain -stage compute -profile sm_5_0 -ignore-capabilities
2+
//TEST:SIMPLE(filecheck=CHECK_IGNORE_CAPS): -target glsl -emit-spirv-directly -entry computeMain -stage compute -profile sm_5_0 -ignore-capabilities -skip-spirv-validation
33

44
// Test that we diagnose simplified capabilities
55
// CHECK_IGNORE_CAPS-NOT: error 36104

tests/language-feature/capability/conflicting-profile-stage-for-entry-point.slang

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
//TEST:SIMPLE(filecheck=CHECK): -target spirv -entry vsmain -profile vs_6_0
55
//TEST:SIMPLE(filecheck=CHECK): -target spirv -entry psmain -profile vs_6_0 -ignore-capabilities
6-
//TEST:SIMPLE(filecheck=CHECK): -target spirv -entry vsmain -profile ps_6_0 -ignore-capabilities
6+
//TEST:SIMPLE(filecheck=CHECK): -target spirv -entry vsmain -profile ps_6_0 -ignore-capabilities -skip-spirv-validation
77

88
// CHECK_ERROR: warning 36112
99
// CHECK-NOT: warning 36112
@@ -33,4 +33,4 @@ VSOutput vsmain(float3 PositionOS : POSITION, float3 Color : COLOR0)
3333
float4 psmain(VSOutput input) : SV_TARGET
3434
{
3535
return float4(input.Color, 1);
36-
}
36+
}

0 commit comments

Comments
 (0)