summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Kwak <82421531+jkwak-work@users.noreply.github.com>2025-08-28 10:45:07 -0700
committerGitHub <noreply@github.com>2025-08-28 17:45:07 +0000
commitc19e2e92ae8e713225262a17f39a438cd511d416 (patch)
tree7c78e65d3c826c52b527c71500a72ecb18754254
parent3dc466487d489f09c835bdd872eb130cdc5784ea (diff)
Remove the embedded source to avoid self-matching in slang-test (#8305)
When `SIMPLE` type test is used with `-g[1-3]` option, the filecheck pattern will most likely to match to the string itself on the embedded source code rather than match to the emitted spirv-asm code. This commit avoids the problem by removing the embedded source code. This commit also provides an option to keep the embedded source code, `-preserve-embedded-source`. The source code removal is happening in two steps: 1. iterate all output lines and find SPIRV-ASM in the following pattern: `%N = OpExtInst %void %M DebugSource %fileId %sourceId`. And then, store the "%sourceId" value to identify which SPIRV instructions are for the embedded source code. 2. iterate all output lines again to find the `%sourceId = OpString "...."` and replace the whole string with the following string, ``` %1 = OpString "// slang-test removed the embedded source // Use `-preserve-embedded-source` to keep it explicitly " ``` This change revealed problems in the existing tests: - tests/bugs/spirv-debug-info.slang : The expected text was missing and it had to be added. The file also had Carrage-Return character on all lines and the pre-commit git hook removed them. - tests/spirv/debug-info.slang : the expected keyword DebugValue had to change to DebugDeclare, because that's what we get with ToT. - tests/spirv/debug-value-dynamic-index.slang : This test is currently failing, and it will pass once DebugLocalVariable instruction missing for parameter of the entry point function #7693 is resolved. --------- Co-authored-by: slangbot <ellieh+slangbot@nvidia.com>
-rw-r--r--tests/bugs/spirv-debug-info.slang24
-rw-r--r--tests/spirv/debug-info.slang2
-rw-r--r--tests/spirv/debug-value-dynamic-index.slang5
-rw-r--r--tools/slang-test/slang-test-main.cpp107
4 files changed, 121 insertions, 17 deletions
diff --git a/tests/bugs/spirv-debug-info.slang b/tests/bugs/spirv-debug-info.slang
index 500299057..fe1c4fb05 100644
--- a/tests/bugs/spirv-debug-info.slang
+++ b/tests/bugs/spirv-debug-info.slang
@@ -1,5 +1,5 @@
-//TEST:SIMPLE(filecheck=CHECK):-target spirv -entry MainPs -stage fragment -profile glsl_450 -g3 -line-directive-mode none
-//TEST:SIMPLE(filecheck=CHECK-SPIRV):-target spirv -entry MainPs -stage fragment -profile glsl_450 -g3 -emit-spirv-directly
+//TEST:SIMPLE(filecheck=CHECK):-target spirv -entry MainPs -stage fragment -profile glsl_450 -g3 -line-directive-mode none -preserve-embedded-source
+//TEST:SIMPLE(filecheck=CHECK-SPIRV):-target spirv -entry MainPs -stage fragment -profile glsl_450 -g3 -emit-spirv-directly -preserve-embedded-source
// make sure that the generated spirv has glsl source in it.
// CHECK: #version 450
@@ -10,14 +10,14 @@
// CHECK-SPIRV: {{.*}} OpFunction
// CHECK-SPIRV: {{.*}} = OpExtInst %void {{.*}} DebugLine
-struct PS_OUTPUT
-{
- float4 vColor : SV_Target0 ;
-} ;
+struct PS_OUTPUT
+{
+ float4 vColor : SV_Target0 ;
+} ;
-PS_OUTPUT MainPs ( )
-{
- PS_OUTPUT o ;
- o . vColor = float4 ( 0 , 0 , 0 , 0 ) ;
- return o ;
-} \ No newline at end of file
+PS_OUTPUT MainPs ( )
+{
+ PS_OUTPUT o ;
+ o . vColor = float4 ( 0 , 0 , 0 , 0 ) ;
+ return o ;
+}
diff --git a/tests/spirv/debug-info.slang b/tests/spirv/debug-info.slang
index dc225f8cc..d1107b774 100644
--- a/tests/spirv/debug-info.slang
+++ b/tests/spirv/debug-info.slang
@@ -27,4 +27,4 @@ void main()
// CHECK: DebugFunctionDefinition
// CHECK: DebugScope
// CHECK: DebugLine
-// CHECK: DebugValue
+// CHECK: DebugDeclare
diff --git a/tests/spirv/debug-value-dynamic-index.slang b/tests/spirv/debug-value-dynamic-index.slang
index 591b1f6da..8b4f6b43e 100644
--- a/tests/spirv/debug-value-dynamic-index.slang
+++ b/tests/spirv/debug-value-dynamic-index.slang
@@ -1,4 +1,5 @@
-//TEST:SIMPLE(filecheck=CHECK):-target spirv -entry main -stage compute -g2 -emit-spirv-directly
+// This will be re-enabled when github #7693 is resolved
+//DISABLE_TEST:SIMPLE(filecheck=CHECK):-target spirv -entry main -stage compute -g2 -emit-spirv-directly
struct TestType
{
@@ -25,5 +26,5 @@ void main(int id : SV_DispatchThreadID)
// CHECK: DebugTypeComposite
// CHECK: DebugFunctionDefinition
// CHECK: DebugScope
+// CHECK: DebugDeclare
// CHECK: DebugLine
-// CHECK: DebugValue
diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp
index 3f707b5e5..6c0de13ec 100644
--- a/tools/slang-test/slang-test-main.cpp
+++ b/tools/slang-test/slang-test-main.cpp
@@ -54,6 +54,9 @@ SLANG_RHI_EXPORT_AGILITY_SDK
using namespace Slang;
+// Constants for slang-test specific options
+static const char* kPreserveEmbeddedSourceOption = "-preserve-embedded-source";
+
// Options for a particular test
struct TestOptions
{
@@ -1531,7 +1534,94 @@ ToolReturnCode spawnAndWait(
return getReturnCode(outExeRes);
}
-String getOutput(const ExecuteResult& exeRes)
+// Remove embedded source code from SPIR-V assembly output to prevent filecheck from matching
+// against embedded source instead of actual SPIR-V instructions
+String removeEmbeddedSourceFromSPIRV(const String& spirvOutput)
+{
+ StringBuilder filteredOutput;
+ List<UnownedStringSlice> lines;
+ StringUtil::calcLines(spirvOutput.getUnownedSlice(), lines);
+
+ if (spirvOutput.endsWith("\n"))
+ {
+ // The last empty line should be removed,
+ // because `StringUtil::calcLines()` turns "A\nB\n" into three lines; not two.
+ SLANG_ASSERT(lines[lines.getCount() - 1] == "");
+ lines.setCount(lines.getCount() - 1);
+ }
+
+ // First pass: Find OpString IDs that are referenced by DebugSource
+ List<String> sourceStringIds;
+ for (const auto& line : lines)
+ {
+ UnownedStringSlice trimmedLine = line.trim();
+
+ if (trimmedLine.indexOf(UnownedStringSlice(" DebugSource ")) == Index(-1))
+ continue;
+
+ // Extract the last parameter which is the source string ID
+ // Pattern: %4 = OpExtInst %void %2 DebugSource %5 %1
+ List<UnownedStringSlice> tokens;
+ StringUtil::split(trimmedLine, ' ', tokens);
+
+ // The last token should be the source string ID
+ UnownedStringSlice lastToken = tokens.getLast();
+ if (lastToken.startsWith(UnownedStringSlice("%")))
+ {
+ sourceStringIds.add(String(lastToken));
+ }
+ }
+
+ // Second pass: Process embedded source strings to replace content with informative message
+ bool insideSourceString = false;
+ for (const auto& line : lines)
+ {
+ UnownedStringSlice trimmedLine = line.trim();
+
+ if (!insideSourceString)
+ {
+ Index equalPos = trimmedLine.indexOf(UnownedStringSlice(" = OpString"));
+ if (equalPos != Index(-1) && trimmedLine.startsWith(UnownedStringSlice("%")))
+ {
+ String currentStringId = String(trimmedLine.head(equalPos));
+ if (sourceStringIds.contains(currentStringId))
+ {
+ insideSourceString = true;
+ Index quotePos = line.indexOf('\"');
+ if (quotePos != Index(-1))
+ {
+ filteredOutput.append(String(line.head(quotePos + 1)));
+ filteredOutput.append("// slang-test removed the embedded source\n");
+ filteredOutput.append("// Use `");
+ filteredOutput.append(kPreserveEmbeddedSourceOption);
+ filteredOutput.append("` to keep it explicitly\n\"\n");
+ }
+ continue;
+ }
+ }
+ }
+
+ if (insideSourceString)
+ {
+ if (trimmedLine.endsWith("\"") &&
+ (trimmedLine.getLength() < 2 || trimmedLine[trimmedLine.getLength() - 2] != '\\'))
+ {
+ insideSourceString = false;
+ }
+
+ // skip the embedded source lines
+ continue;
+ }
+
+ // Add this line to the filtered output
+ filteredOutput.append(line);
+ filteredOutput.append("\n");
+ }
+
+ return filteredOutput.produceString();
+}
+
+String getOutput(const ExecuteResult& exeRes, bool removeEmbeddedSource = false)
{
ExecuteResult::ResultCode resultCode = exeRes.resultCode;
@@ -1539,6 +1629,12 @@ String getOutput(const ExecuteResult& exeRes)
String standardError = exeRes.standardError;
String debugLayer = exeRes.debugLayer;
+ // Apply embedded source removal to standard output if requested
+ if (removeEmbeddedSource)
+ {
+ standardOuptut = removeEmbeddedSourceFromSPIRV(standardOuptut);
+ }
+
// We construct a single output string that captures the results
StringBuilder actualOutputBuilder;
actualOutputBuilder.append("result code = ");
@@ -2325,6 +2421,9 @@ TestResult runSimpleTest(TestContext* context, TestInput& input)
for (auto arg : input.testOptions->args)
{
+ // Filter out slang-test specific options that shouldn't be passed to slangc
+ if (arg == kPreserveEmbeddedSourceOption)
+ continue;
cmdLine.addArg(arg);
}
@@ -2366,7 +2465,11 @@ TestResult runSimpleTest(TestContext* context, TestInput& input)
exeRes = runExeRes;
}
- String actualOutput = getOutput(exeRes);
+ bool needToRemoveEmbeddedSource =
+ ((target == SLANG_SPIRV || target == SLANG_SPIRV_ASM) &&
+ input.testOptions->args.indexOf(kPreserveEmbeddedSourceOption) == Index(-1));
+
+ String actualOutput = getOutput(exeRes, needToRemoveEmbeddedSource);
return _validateOutput(
context,