summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorEllie Hermaszewska <ellieh@nvidia.com>2023-08-08 06:02:53 +0800
committerGitHub <noreply@github.com>2023-08-07 15:02:53 -0700
commit3a9624040d3a3395d855caaa4358a9ff1fbcca3b (patch)
tree97a7f9de5b7c7718714f566a28c147d93cadd086 /source
parent0e28cd02710e6a8e989e89fd1f9b4ebf85892f99 (diff)
Validate generated SPIR-V on output (#3061)
* Validate generated SPIR-V * regenerate vs projects * Do not fail compiles if spirv-val is not available --------- Co-authored-by: Yong He <yonghe@outlook.com>
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-diagnostic-defs.h1
-rw-r--r--source/slang/slang-emit-spirv.cpp13
-rw-r--r--source/slang/slang-spirv-val.cpp40
-rw-r--r--source/slang/slang-spirv-val.h10
4 files changed, 64 insertions, 0 deletions
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index 14a03884b..e2c00ec38 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -726,6 +726,7 @@ DIAGNOSTIC(99999, Internal, internalCompilerError, "Slang internal compiler erro
DIAGNOSTIC(99999, Error, compilationAborted, "Slang compilation aborted due to internal error")
DIAGNOSTIC(99999, Error, compilationAbortedDueToException, "Slang compilation aborted due to an exception of $0: $1")
DIAGNOSTIC(99999, Internal, serialDebugVerificationFailed, "Verification of serial debug information failed.")
+DIAGNOSTIC(99999, Internal, spirvValidationFailed, "Validation of generated SPIR-V failed.")
DIAGNOSTIC(99999, Internal, noBlocksOrIntrinsic, "no blocks found for function definition, is there a '$0' intrinsic missing?")
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index 1386de4eb..c16ee6a90 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -9,6 +9,7 @@
#include "slang-ir-layout.h"
#include "slang-ir-spirv-snippet.h"
#include "slang-ir-spirv-legalize.h"
+#include "slang-spirv-val.h"
#include "spirv/unified1/spirv.h"
#include "../core/slang-memory-arena.h"
@@ -3078,6 +3079,18 @@ SlangResult emitSPIRVFromIR(
(uint8_t const*) context.m_words.getBuffer(),
context.m_words.getCount() * sizeof(context.m_words[0]));
+ const auto validationResult = debugValidateSPIRV(spirvOut);
+ // If validation isn't available, don't say it failed, it's just a debug
+ // feature so we can skip
+ if(SLANG_FAILED(validationResult) && validationResult != SLANG_E_NOT_AVAILABLE)
+ {
+ codeGenContext->getSink()->diagnoseWithoutSourceView(
+ SourceLoc{},
+ Diagnostics::spirvValidationFailed
+ );
+ return validationResult;
+ }
+
return SLANG_OK;
}
diff --git a/source/slang/slang-spirv-val.cpp b/source/slang/slang-spirv-val.cpp
new file mode 100644
index 000000000..990ccd909
--- /dev/null
+++ b/source/slang/slang-spirv-val.cpp
@@ -0,0 +1,40 @@
+#include "slang-spirv-val.h"
+
+namespace Slang
+{
+
+SlangResult debugValidateSPIRV(const List<uint8_t>& spirv)
+{
+ // Set up our process
+ CommandLine commandLine;
+ commandLine.m_executableLocation.setName("spirv-val");
+ RefPtr<Process> p;
+ const auto createResult = Process::create(commandLine, 0, p);
+ // If we failed to even start the process, then validation isn't available
+ if(SLANG_FAILED(createResult))
+ return SLANG_E_NOT_AVAILABLE;
+ const auto in = p->getStream(StdStreamType::In);
+ const auto out = p->getStream(StdStreamType::Out);
+ const auto err = p->getStream(StdStreamType::ErrorOut);
+
+ // Write the assembly
+ SLANG_RETURN_ON_FAIL(in->write(spirv.getBuffer(), spirv.getCount()));
+ in->close();
+
+ // Wait for it to finish
+ if(!p->waitForTermination(1000))
+ return SLANG_FAIL;
+
+ // TODO: allow inheriting stderr in Process
+ List<Byte> outData;
+ SLANG_RETURN_ON_FAIL(StreamUtil::readAll(out, 0, outData));
+ fwrite(outData.getBuffer(), outData.getCount(), 1, stderr);
+ outData.clear();
+ SLANG_RETURN_ON_FAIL(StreamUtil::readAll(err, 0, outData));
+ fwrite(outData.getBuffer(), outData.getCount(), 1, stderr);
+
+ const auto ret = p->getReturnValue();
+ return ret == 0 ? SLANG_OK : SLANG_FAIL;
+}
+
+}
diff --git a/source/slang/slang-spirv-val.h b/source/slang/slang-spirv-val.h
new file mode 100644
index 000000000..08e08b373
--- /dev/null
+++ b/source/slang/slang-spirv-val.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <cstdint>
+#include "slang-compiler.h"
+
+namespace Slang
+{
+SlangResult debugValidateSPIRV(const List<uint8_t>& spirv);
+}
+