summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-04-02 09:22:13 -0400
committerGitHub <noreply@github.com>2019-04-02 09:22:13 -0400
commit2896aa39a529a00673a30ef4a9c3ebe76f401fea (patch)
tree3db2c41af598b3285c5313055d90dbf1a5cc06b6
parentc21bffecd9da150576f62ecf8a73a1660717abe9 (diff)
Feature/test improvements (#934)
* First pass extract the test information by 'running tests'. * * Checking renderer availablilty * Using TestInfo to determine which tests are run and synthesized * Display if test is synthesized and what render api it's targetting * * Improved comments * Removed some dead code * Display ignored tests. * TestInfo -> TestRequirements * * Added DIAGNOSTIC_TEST type - test always runs (ie has no requirements). * Made diagnostic tests use DIAGNOSTIC_TEST * TestInfo -> TestRequirements * TestDetails holds TestRequirements and TestOptions * Fix debug typo.
-rw-r--r--tests/diagnostics/attribute-error.slang2
-rw-r--r--tests/diagnostics/break-outside-loop.slang4
-rw-r--r--tests/diagnostics/call-argument-type.slang2
-rw-r--r--tests/diagnostics/command-line/duplicate-output.slang2
-rw-r--r--tests/diagnostics/command-line/duplicate-target.slang2
-rw-r--r--tests/diagnostics/command-line/entry-point-conflicting-stage.slang4
-rw-r--r--tests/diagnostics/command-line/entry-point-redundant-stage.slang4
-rw-r--r--tests/diagnostics/command-line/explicit-implicit-stage-mismatch.vert2
-rw-r--r--tests/diagnostics/command-line/option-missing-argument.slang4
-rw-r--r--tests/diagnostics/command-line/output-no-entry-point.slang2
-rw-r--r--tests/diagnostics/command-line/output-no-target.slang2
-rw-r--r--tests/diagnostics/command-line/pass-through-no-stage.hlsl2
-rw-r--r--tests/diagnostics/command-line/profile-ignored.slang4
-rw-r--r--tests/diagnostics/command-line/stage-ignored.slang2
-rw-r--r--tests/diagnostics/command-line/unknown-codegen-target.slang2
-rw-r--r--tests/diagnostics/command-line/unknown-line-directive-mode.slang2
-rw-r--r--tests/diagnostics/command-line/unknown-option.slang2
-rw-r--r--tests/diagnostics/command-line/unknown-output-format.slang2
-rw-r--r--tests/diagnostics/command-line/unknown-pass-through-target.slang2
-rw-r--r--tests/diagnostics/command-line/unknown-profile.slang2
-rw-r--r--tests/diagnostics/command-line/unknown-source-language.slang2
-rw-r--r--tests/diagnostics/command-line/unknown-stage.slang2
-rw-r--r--tests/diagnostics/constexpr-error.slang2
-rw-r--r--tests/diagnostics/continue-outside-loop.slang2
-rw-r--r--tests/diagnostics/entry-point-no-stage.slang2
-rw-r--r--tests/diagnostics/entry-point-stage-mismatch.slang2
-rw-r--r--tests/diagnostics/enum-implicit-conversion.slang2
-rw-r--r--tests/diagnostics/expected-token-eof.slang2
-rw-r--r--tests/diagnostics/expected-token.slang2
-rw-r--r--tests/diagnostics/gh-38-vs.hlsl2
-rw-r--r--tests/diagnostics/global-uniform.slang4
-rw-r--r--tests/diagnostics/illegal-character.slang2
-rw-r--r--tests/diagnostics/implicit-cast-lvalue.slang2
-rw-r--r--tests/diagnostics/local-used-before-declared.slang2
-rw-r--r--tests/diagnostics/local-used-in-own-declaration.slang2
-rw-r--r--tests/diagnostics/missing-include-file.slang2
-rw-r--r--tests/diagnostics/missing-return.slang2
-rw-r--r--tests/diagnostics/missing-semicolon-after-semantic.slang2
-rw-r--r--tests/diagnostics/packoffset.slang2
-rw-r--r--tests/diagnostics/parameter-already-defined.slang2
-rw-r--r--tests/diagnostics/recursive-import.slang2
-rw-r--r--tests/diagnostics/register-bindings.slang2
-rw-r--r--tests/diagnostics/setter-method.slang2
-rw-r--r--tests/diagnostics/single-shader-record.slang2
-rw-r--r--tests/diagnostics/static-ref-to-nonstatic-member.slang2
-rw-r--r--tests/diagnostics/undefined-identifier.slang2
-rw-r--r--tests/diagnostics/undefined-in-preprocessor-conditional.slang2
-rw-r--r--tests/diagnostics/unreachable-code.slang2
-rw-r--r--tests/diagnostics/variable-void-type.slang2
-rw-r--r--tests/diagnostics/vk-bindings.slang2
-rw-r--r--tests/diagnostics/while-predicate-type.slang2
-rw-r--r--tools/render-test/options.cpp4
-rw-r--r--tools/render-test/options.h1
-rw-r--r--tools/render-test/render-test-main.cpp17
-rw-r--r--tools/slang-test/slang-test-main.cpp943
-rw-r--r--tools/slang-test/test-context.h76
56 files changed, 806 insertions, 349 deletions
diff --git a/tests/diagnostics/attribute-error.slang b/tests/diagnostics/attribute-error.slang
index b913d3d4a..9cc24437a 100644
--- a/tests/diagnostics/attribute-error.slang
+++ b/tests/diagnostics/attribute-error.slang
@@ -2,7 +2,7 @@
// Tests reflection of user defined attributes.
-//TEST:REFLECTION:-stage compute -entry main -target hlsl
+//DIAGNOSTIC_TEST:REFLECTION:-stage compute -entry main -target hlsl
[__AttributeUsage(_AttributeTargets.Struct)]
struct MyStructAttribute
diff --git a/tests/diagnostics/break-outside-loop.slang b/tests/diagnostics/break-outside-loop.slang
index 0de64e2c5..28db144e8 100644
--- a/tests/diagnostics/break-outside-loop.slang
+++ b/tests/diagnostics/break-outside-loop.slang
@@ -1,5 +1,5 @@
-//TEST:SIMPLE:
-//TEST:COMMAND_LINE_SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
+//DIAGNOSTIC_TEST:COMMAND_LINE_SIMPLE:
// `break` where it isn't allowed
diff --git a/tests/diagnostics/call-argument-type.slang b/tests/diagnostics/call-argument-type.slang
index b4f7e7477..93446265d 100644
--- a/tests/diagnostics/call-argument-type.slang
+++ b/tests/diagnostics/call-argument-type.slang
@@ -1,4 +1,4 @@
-//TEST(smoke):SIMPLE:
+//DIAGNOSTIC_TEST(smoke):SIMPLE:
// call function with wrong argument type
struct A {};
diff --git a/tests/diagnostics/command-line/duplicate-output.slang b/tests/diagnostics/command-line/duplicate-output.slang
index 794a8717b..bb6a63070 100644
--- a/tests/diagnostics/command-line/duplicate-output.slang
+++ b/tests/diagnostics/command-line/duplicate-output.slang
@@ -1,3 +1,3 @@
// duplicate-output.slang
-//TEST:SIMPLE:-entry main -stage compute -o myKernel.dxbc -o myKernel.dxbc
+//DIAGNOSTIC_TEST:SIMPLE:-entry main -stage compute -o myKernel.dxbc -o myKernel.dxbc
diff --git a/tests/diagnostics/command-line/duplicate-target.slang b/tests/diagnostics/command-line/duplicate-target.slang
index 44bbc62c7..a9ec96d0f 100644
--- a/tests/diagnostics/command-line/duplicate-target.slang
+++ b/tests/diagnostics/command-line/duplicate-target.slang
@@ -1,3 +1,3 @@
// duplicate-target.slang
-//TEST:SIMPLE:-target hlsl -target hlsl
+//DIAGNOSTIC_TEST:SIMPLE:-target hlsl -target hlsl
diff --git a/tests/diagnostics/command-line/entry-point-conflicting-stage.slang b/tests/diagnostics/command-line/entry-point-conflicting-stage.slang
index 89cf5cba0..c6c517258 100644
--- a/tests/diagnostics/command-line/entry-point-conflicting-stage.slang
+++ b/tests/diagnostics/command-line/entry-point-conflicting-stage.slang
@@ -1,5 +1,5 @@
// entry-point-conflicting-stage.slang
-//TEST:SIMPLE:-stage vertex -stage fragment
+//DIAGNOSTIC_TEST:SIMPLE:-stage vertex -stage fragment
-//TEST:SIMPLE:-entry vsMain -stage compute -stage vertex
+//DIAGNOSTIC_TEST:SIMPLE:-entry vsMain -stage compute -stage vertex
diff --git a/tests/diagnostics/command-line/entry-point-redundant-stage.slang b/tests/diagnostics/command-line/entry-point-redundant-stage.slang
index 903d696c7..9507b1ea0 100644
--- a/tests/diagnostics/command-line/entry-point-redundant-stage.slang
+++ b/tests/diagnostics/command-line/entry-point-redundant-stage.slang
@@ -1,5 +1,5 @@
// entry-point-redundant-stage.slang
-//TEST:SIMPLE:-stage vertex -stage vertex
+//DIAGNOSTIC_TEST:SIMPLE:-stage vertex -stage vertex
-//TEST:SIMPLE:-entry vsMain -stage vertex -stage vertex
+//DIAGNOSTIC_TEST:SIMPLE:-entry vsMain -stage vertex -stage vertex
diff --git a/tests/diagnostics/command-line/explicit-implicit-stage-mismatch.vert b/tests/diagnostics/command-line/explicit-implicit-stage-mismatch.vert
index 0ea731470..ec1f17887 100644
--- a/tests/diagnostics/command-line/explicit-implicit-stage-mismatch.vert
+++ b/tests/diagnostics/command-line/explicit-implicit-stage-mismatch.vert
@@ -1,3 +1,3 @@
// explicit-implicit-stage-mismatch.vert
-//TEST:SIMPLE:-stage fragment
+//DIAGNOSTIC_TEST:SIMPLE:-stage fragment
diff --git a/tests/diagnostics/command-line/option-missing-argument.slang b/tests/diagnostics/command-line/option-missing-argument.slang
index e62b37ba6..9af53301a 100644
--- a/tests/diagnostics/command-line/option-missing-argument.slang
+++ b/tests/diagnostics/command-line/option-missing-argument.slang
@@ -2,6 +2,6 @@
// Missing argument for an option:
-//TEST:SIMPLE:-target -profile ps_4_0
+//DIAGNOSTIC_TEST:SIMPLE:-target -profile ps_4_0
-//TEST:SIMPLE:-profile ps_4_0 -target
+//DIAGNOSTIC_TEST:SIMPLE:-profile ps_4_0 -target
diff --git a/tests/diagnostics/command-line/output-no-entry-point.slang b/tests/diagnostics/command-line/output-no-entry-point.slang
index 869dcabc4..891e4387a 100644
--- a/tests/diagnostics/command-line/output-no-entry-point.slang
+++ b/tests/diagnostics/command-line/output-no-entry-point.slang
@@ -1,3 +1,3 @@
// output-no-entry-point.slang
-//TEST:SIMPLE:-o something.dxbc -entry vsMain -stage vertex -entry fsMain -stage fragment
+//DIAGNOSTIC_TEST:SIMPLE:-o something.dxbc -entry vsMain -stage vertex -entry fsMain -stage fragment
diff --git a/tests/diagnostics/command-line/output-no-target.slang b/tests/diagnostics/command-line/output-no-target.slang
index 32921a8f0..a4c38f52d 100644
--- a/tests/diagnostics/command-line/output-no-target.slang
+++ b/tests/diagnostics/command-line/output-no-target.slang
@@ -1,3 +1,3 @@
// output-no-target.slang
-//TEST:SIMPLE:-target dxbc -target spirv -entry main -stage compute -o bad.hlsl
+//DIAGNOSTIC_TEST:SIMPLE:-target dxbc -target spirv -entry main -stage compute -o bad.hlsl
diff --git a/tests/diagnostics/command-line/pass-through-no-stage.hlsl b/tests/diagnostics/command-line/pass-through-no-stage.hlsl
index eabdadf10..e510d811c 100644
--- a/tests/diagnostics/command-line/pass-through-no-stage.hlsl
+++ b/tests/diagnostics/command-line/pass-through-no-stage.hlsl
@@ -5,4 +5,4 @@
// compilers don't support inferring the stage from
// an attribute.
-//TEST:SIMPLE:-pass-through fxc -entry main
+//DIAGNOSTIC_TEST:SIMPLE:-pass-through fxc -entry main
diff --git a/tests/diagnostics/command-line/profile-ignored.slang b/tests/diagnostics/command-line/profile-ignored.slang
index 8a6590690..8c5a3de11 100644
--- a/tests/diagnostics/command-line/profile-ignored.slang
+++ b/tests/diagnostics/command-line/profile-ignored.slang
@@ -5,10 +5,10 @@
// Case 1: multiple (conflicting) profiles, so we can't infer a single stage
//
-//TEST:SIMPLE:-profile sm_5_0 -profile glsl_450
+//DIAGNOSTIC_TEST:SIMPLE:-profile sm_5_0 -profile glsl_450
// Case 2: a `-profile` option before any `-target`, possibly because
// the user is specifying things in the wrong order.
//
-//TEST:SIMPLE:-profile sm_5_0 -target dxbc -profile glsl_450 -target spirv
+//DIAGNOSTIC_TEST:SIMPLE:-profile sm_5_0 -target dxbc -profile glsl_450 -target spirv
diff --git a/tests/diagnostics/command-line/stage-ignored.slang b/tests/diagnostics/command-line/stage-ignored.slang
index 6d28c52bc..56a822d6f 100644
--- a/tests/diagnostics/command-line/stage-ignored.slang
+++ b/tests/diagnostics/command-line/stage-ignored.slang
@@ -6,4 +6,4 @@
// A `-stage` option before any `-entry`, possibly because
// the user is specifying things in the wrong order.
//
-//TEST:SIMPLE:-stage vertex -entry vsMain -stage fragment -entry psMain
+//DIAGNOSTIC_TEST:SIMPLE:-stage vertex -entry vsMain -stage fragment -entry psMain
diff --git a/tests/diagnostics/command-line/unknown-codegen-target.slang b/tests/diagnostics/command-line/unknown-codegen-target.slang
index 57015601d..1a5485176 100644
--- a/tests/diagnostics/command-line/unknown-codegen-target.slang
+++ b/tests/diagnostics/command-line/unknown-codegen-target.slang
@@ -1,3 +1,3 @@
// unknown-codegen-target.slang
-//TEST:SIMPLE:-target z80
+//DIAGNOSTIC_TEST:SIMPLE:-target z80
diff --git a/tests/diagnostics/command-line/unknown-line-directive-mode.slang b/tests/diagnostics/command-line/unknown-line-directive-mode.slang
index 7e61df3f9..078adc1ee 100644
--- a/tests/diagnostics/command-line/unknown-line-directive-mode.slang
+++ b/tests/diagnostics/command-line/unknown-line-directive-mode.slang
@@ -1,3 +1,3 @@
// unknown-line-directive-mode.slang
-//TEST:SIMPLE:-line-directive-mode quizzical
+//DIAGNOSTIC_TEST:SIMPLE:-line-directive-mode quizzical
diff --git a/tests/diagnostics/command-line/unknown-option.slang b/tests/diagnostics/command-line/unknown-option.slang
index 52320d758..dd69aa2a5 100644
--- a/tests/diagnostics/command-line/unknown-option.slang
+++ b/tests/diagnostics/command-line/unknown-option.slang
@@ -1,3 +1,3 @@
// unknown-option.slang
-//TEST:SIMPLE:-destroy-all-humans
+//DIAGNOSTIC_TEST:SIMPLE:-destroy-all-humans
diff --git a/tests/diagnostics/command-line/unknown-output-format.slang b/tests/diagnostics/command-line/unknown-output-format.slang
index 05f59022b..63f026130 100644
--- a/tests/diagnostics/command-line/unknown-output-format.slang
+++ b/tests/diagnostics/command-line/unknown-output-format.slang
@@ -1,3 +1,3 @@
// unknown-output-format.slang
-//TEST:SIMPLE:-o cookies.jar
+//DIAGNOSTIC_TEST:SIMPLE:-o cookies.jar
diff --git a/tests/diagnostics/command-line/unknown-pass-through-target.slang b/tests/diagnostics/command-line/unknown-pass-through-target.slang
index 7b86f62d6..1e71e93b0 100644
--- a/tests/diagnostics/command-line/unknown-pass-through-target.slang
+++ b/tests/diagnostics/command-line/unknown-pass-through-target.slang
@@ -1,3 +1,3 @@
// unknown-pass-through-target.slang
-//TEST:SIMPLE:-pass-through subcon
+//DIAGNOSTIC_TEST:SIMPLE:-pass-through subcon
diff --git a/tests/diagnostics/command-line/unknown-profile.slang b/tests/diagnostics/command-line/unknown-profile.slang
index f96363058..9b58bc7af 100644
--- a/tests/diagnostics/command-line/unknown-profile.slang
+++ b/tests/diagnostics/command-line/unknown-profile.slang
@@ -1,3 +1,3 @@
// unknown-profile.slang
-//TEST:SIMPLE:-profile thunder_kiss_65
+//DIAGNOSTIC_TEST:SIMPLE:-profile thunder_kiss_65
diff --git a/tests/diagnostics/command-line/unknown-source-language.slang b/tests/diagnostics/command-line/unknown-source-language.slang
index c39a3ae4f..3ea80c606 100644
--- a/tests/diagnostics/command-line/unknown-source-language.slang
+++ b/tests/diagnostics/command-line/unknown-source-language.slang
@@ -2,4 +2,4 @@
// Unknown source file extension (can't deduce language)
-//TEST:SIMPLE:batmobile.car
+//DIAGNOSTIC_TEST:SIMPLE:batmobile.car
diff --git a/tests/diagnostics/command-line/unknown-stage.slang b/tests/diagnostics/command-line/unknown-stage.slang
index 1645e5998..5342936d4 100644
--- a/tests/diagnostics/command-line/unknown-stage.slang
+++ b/tests/diagnostics/command-line/unknown-stage.slang
@@ -1,3 +1,3 @@
// unknown-stage.slang
-//TEST:SIMPLE:-stage green_hills_zone
+//DIAGNOSTIC_TEST:SIMPLE:-stage green_hills_zone
diff --git a/tests/diagnostics/constexpr-error.slang b/tests/diagnostics/constexpr-error.slang
index 6006450a1..f0de9280d 100644
--- a/tests/diagnostics/constexpr-error.slang
+++ b/tests/diagnostics/constexpr-error.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// Failure to pass compile-time-constant data
// where it is expected.
diff --git a/tests/diagnostics/continue-outside-loop.slang b/tests/diagnostics/continue-outside-loop.slang
index cad9dce6e..ea8f36fea 100644
--- a/tests/diagnostics/continue-outside-loop.slang
+++ b/tests/diagnostics/continue-outside-loop.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// `continue` where it isn't allowed
void foo() { continue; }
diff --git a/tests/diagnostics/entry-point-no-stage.slang b/tests/diagnostics/entry-point-no-stage.slang
index 99ff8193c..042298e0f 100644
--- a/tests/diagnostics/entry-point-no-stage.slang
+++ b/tests/diagnostics/entry-point-no-stage.slang
@@ -4,7 +4,7 @@
// compiling an entry point without any
// stage specified.
-//TEST:SIMPLE:-entry main
+//DIAGNOSTIC_TEST:SIMPLE:-entry main
void main()
{}
diff --git a/tests/diagnostics/entry-point-stage-mismatch.slang b/tests/diagnostics/entry-point-stage-mismatch.slang
index 0f143c676..caa8d3e4b 100644
--- a/tests/diagnostics/entry-point-stage-mismatch.slang
+++ b/tests/diagnostics/entry-point-stage-mismatch.slang
@@ -3,7 +3,7 @@
// Confirm that we diagnose when stage specified via command
// line doesn't match what was specified via attribute.
-//TEST:SIMPLE:-entry main -stage vertex
+//DIAGNOSTIC_TEST:SIMPLE:-entry main -stage vertex
[shader("compute")]
void main()
diff --git a/tests/diagnostics/enum-implicit-conversion.slang b/tests/diagnostics/enum-implicit-conversion.slang
index d3f3d1d28..fc4757f7e 100644
--- a/tests/diagnostics/enum-implicit-conversion.slang
+++ b/tests/diagnostics/enum-implicit-conversion.slang
@@ -1,6 +1,6 @@
// enum-implicit-conversion.slang
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// Confirm that suitable error messages are
// generated for code that relies on implicit
diff --git a/tests/diagnostics/expected-token-eof.slang b/tests/diagnostics/expected-token-eof.slang
index 99ab161ec..45d234339 100644
--- a/tests/diagnostics/expected-token-eof.slang
+++ b/tests/diagnostics/expected-token-eof.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// expected one token, but got EOF
int foo()
diff --git a/tests/diagnostics/expected-token.slang b/tests/diagnostics/expected-token.slang
index db85e7b92..8978bc97c 100644
--- a/tests/diagnostics/expected-token.slang
+++ b/tests/diagnostics/expected-token.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// expected one token, but got another
int foo()
diff --git a/tests/diagnostics/gh-38-vs.hlsl b/tests/diagnostics/gh-38-vs.hlsl
index 92e0e957e..bb97482c4 100644
--- a/tests/diagnostics/gh-38-vs.hlsl
+++ b/tests/diagnostics/gh-38-vs.hlsl
@@ -1,4 +1,4 @@
-//TEST:SIMPLE: -profile sm_5_0 -entry main -stage vertex tests/diagnostics/gh-38-fs.hlsl -entry main -stage fragment
+//DIAGNOSTIC_TEST:SIMPLE: -profile sm_5_0 -entry main -stage vertex tests/diagnostics/gh-38-fs.hlsl -entry main -stage fragment
// Ensure that we catch errors with overlapping or conflicting parameter bindings.
diff --git a/tests/diagnostics/global-uniform.slang b/tests/diagnostics/global-uniform.slang
index 6d3189cbc..6b17016f2 100644
--- a/tests/diagnostics/global-uniform.slang
+++ b/tests/diagnostics/global-uniform.slang
@@ -1,6 +1,6 @@
// global-uniform.slang
-//TEST:SIMPLE:-target hlsl
-//TEST:COMMAND_LINE_SIMPLE:-target hlsl
+//DIAGNOSTIC_TEST:SIMPLE:-target hlsl
+//DIAGNOSTIC_TEST:COMMAND_LINE_SIMPLE:-target hlsl
// Any attempt to declare a global variable that actually declares a
// global uniform should be diagnosed as unsupported.
diff --git a/tests/diagnostics/illegal-character.slang b/tests/diagnostics/illegal-character.slang
index 5915e861f..9831bb93e 100644
--- a/tests/diagnostics/illegal-character.slang
+++ b/tests/diagnostics/illegal-character.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// illegal character
`
diff --git a/tests/diagnostics/implicit-cast-lvalue.slang b/tests/diagnostics/implicit-cast-lvalue.slang
index 4bf3c13b0..79b619443 100644
--- a/tests/diagnostics/implicit-cast-lvalue.slang
+++ b/tests/diagnostics/implicit-cast-lvalue.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// Passing an argument for an `out` parameter such
// that implicit conversion would be required in
diff --git a/tests/diagnostics/local-used-before-declared.slang b/tests/diagnostics/local-used-before-declared.slang
index 96d68b9eb..bd17666b6 100644
--- a/tests/diagnostics/local-used-before-declared.slang
+++ b/tests/diagnostics/local-used-before-declared.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:-target dxbc -profile ps_5_0 -entry main
+//DIAGNOSTIC_TEST:SIMPLE:-target dxbc -profile ps_5_0 -entry main
// Early versions of the front-end had bugs when local
// variables were used before their definition, or
diff --git a/tests/diagnostics/local-used-in-own-declaration.slang b/tests/diagnostics/local-used-in-own-declaration.slang
index 9802acbb9..d95ef12e0 100644
--- a/tests/diagnostics/local-used-in-own-declaration.slang
+++ b/tests/diagnostics/local-used-in-own-declaration.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:-target dxbc -profile ps_5_0
+//DIAGNOSTIC_TEST:SIMPLE:-target dxbc -profile ps_5_0
// Early versions of the front-end had bugs when local
// variables were used before their definition, or
diff --git a/tests/diagnostics/missing-include-file.slang b/tests/diagnostics/missing-include-file.slang
index 9e0f99b9c..ee49e2cbe 100644
--- a/tests/diagnostics/missing-include-file.slang
+++ b/tests/diagnostics/missing-include-file.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// trying to include a non-existant file
#include "does-not-exist.h"
diff --git a/tests/diagnostics/missing-return.slang b/tests/diagnostics/missing-return.slang
index 83f5f9dc1..988d706d5 100644
--- a/tests/diagnostics/missing-return.slang
+++ b/tests/diagnostics/missing-return.slang
@@ -1,6 +1,6 @@
// missing-return.slang
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// Non-`void` function that fails to return
diff --git a/tests/diagnostics/missing-semicolon-after-semantic.slang b/tests/diagnostics/missing-semicolon-after-semantic.slang
index 00fc3aa6c..d2eb12825 100644
--- a/tests/diagnostics/missing-semicolon-after-semantic.slang
+++ b/tests/diagnostics/missing-semicolon-after-semantic.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// Forgetting to put in the `;` after declaraing a variable/field
// with a semantic used to put the compiler into an infinite loop.
diff --git a/tests/diagnostics/packoffset.slang b/tests/diagnostics/packoffset.slang
index 31ee63bbd..b5669c410 100644
--- a/tests/diagnostics/packoffset.slang
+++ b/tests/diagnostics/packoffset.slang
@@ -1,5 +1,5 @@
// packoffset.slang
-//TEST:SIMPLE:-target hlsl
+//DIAGNOSTIC_TEST:SIMPLE:-target hlsl
// use of `packoffset` (not supported):
cbuffer B
diff --git a/tests/diagnostics/parameter-already-defined.slang b/tests/diagnostics/parameter-already-defined.slang
index 860b17e65..312b3d8b0 100644
--- a/tests/diagnostics/parameter-already-defined.slang
+++ b/tests/diagnostics/parameter-already-defined.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// re-use parameter name
int foo( int a, float a ) { return 0; }
diff --git a/tests/diagnostics/recursive-import.slang b/tests/diagnostics/recursive-import.slang
index ff74025f8..b74e55be4 100644
--- a/tests/diagnostics/recursive-import.slang
+++ b/tests/diagnostics/recursive-import.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// A file that recursively imports itself
// (including transitive cases) should be diagnosed.
diff --git a/tests/diagnostics/register-bindings.slang b/tests/diagnostics/register-bindings.slang
index 188d22bf5..263329bf6 100644
--- a/tests/diagnostics/register-bindings.slang
+++ b/tests/diagnostics/register-bindings.slang
@@ -1,5 +1,5 @@
// register-bindings.slang
-//TEST:SIMPLE:-target hlsl
+//DIAGNOSTIC_TEST:SIMPLE:-target hlsl
// Various bad forms for register bindings
diff --git a/tests/diagnostics/setter-method.slang b/tests/diagnostics/setter-method.slang
index 58e7c3417..c1e6019d0 100644
--- a/tests/diagnostics/setter-method.slang
+++ b/tests/diagnostics/setter-method.slang
@@ -1,6 +1,6 @@
// setter-method.slang
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// Make sure we provide a user a diagnostic if they
// try to declare a setter method without `mutating`
diff --git a/tests/diagnostics/single-shader-record.slang b/tests/diagnostics/single-shader-record.slang
index 4dbf65daa..0c6657f2f 100644
--- a/tests/diagnostics/single-shader-record.slang
+++ b/tests/diagnostics/single-shader-record.slang
@@ -1,5 +1,5 @@
// single-shader-record.slang
-//TEST:SIMPLE: -profile sm_6_3 -stage closesthit -entry main -target spirv-assembly
+//DIAGNOSTIC_TEST:SIMPLE: -profile sm_6_3 -stage closesthit -entry main -target spirv-assembly
struct ReflectionRay
{
diff --git a/tests/diagnostics/static-ref-to-nonstatic-member.slang b/tests/diagnostics/static-ref-to-nonstatic-member.slang
index 485a0ed67..828cf46b1 100644
--- a/tests/diagnostics/static-ref-to-nonstatic-member.slang
+++ b/tests/diagnostics/static-ref-to-nonstatic-member.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
struct Color
diff --git a/tests/diagnostics/undefined-identifier.slang b/tests/diagnostics/undefined-identifier.slang
index 6c5a59f75..88633bf07 100644
--- a/tests/diagnostics/undefined-identifier.slang
+++ b/tests/diagnostics/undefined-identifier.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// use of undefined identifier
void foo()
diff --git a/tests/diagnostics/undefined-in-preprocessor-conditional.slang b/tests/diagnostics/undefined-in-preprocessor-conditional.slang
index d46c68d33..100468703 100644
--- a/tests/diagnostics/undefined-in-preprocessor-conditional.slang
+++ b/tests/diagnostics/undefined-in-preprocessor-conditional.slang
@@ -1,4 +1,4 @@
-//TEST(smoke):SIMPLE:
+//DIAGNOSTIC_TEST(smoke):SIMPLE:
// Use an undefined identifier in a preprocessor conditional
diff --git a/tests/diagnostics/unreachable-code.slang b/tests/diagnostics/unreachable-code.slang
index 493ccc81f..6c54fcec3 100644
--- a/tests/diagnostics/unreachable-code.slang
+++ b/tests/diagnostics/unreachable-code.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// "Obviously" unreachable code.
diff --git a/tests/diagnostics/variable-void-type.slang b/tests/diagnostics/variable-void-type.slang
index 926e6401d..57f16cc22 100644
--- a/tests/diagnostics/variable-void-type.slang
+++ b/tests/diagnostics/variable-void-type.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// variable with `void` type
void foo()
diff --git a/tests/diagnostics/vk-bindings.slang b/tests/diagnostics/vk-bindings.slang
index a329fcdde..c0a3ca7f8 100644
--- a/tests/diagnostics/vk-bindings.slang
+++ b/tests/diagnostics/vk-bindings.slang
@@ -1,6 +1,6 @@
// vk-bindings.slang
-//TEST:SIMPLE:-target spirv
+//DIAGNOSTIC_TEST:SIMPLE:-target spirv
// D3D `register` without VK binding
Texture2D t : register(t0);
diff --git a/tests/diagnostics/while-predicate-type.slang b/tests/diagnostics/while-predicate-type.slang
index 14ce45533..ec1d55b47 100644
--- a/tests/diagnostics/while-predicate-type.slang
+++ b/tests/diagnostics/while-predicate-type.slang
@@ -1,4 +1,4 @@
-//TEST:SIMPLE:
+//DIAGNOSTIC_TEST:SIMPLE:
// bad type for `while` predicate
struct S {};
diff --git a/tools/render-test/options.cpp b/tools/render-test/options.cpp
index 9d5ff35c8..2277a6ad7 100644
--- a/tools/render-test/options.cpp
+++ b/tools/render-test/options.cpp
@@ -151,6 +151,10 @@ SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper s
{
gOptions.useDXIL = true;
}
+ else if (strcmp(arg, "-only-startup") == 0)
+ {
+ gOptions.onlyStartup = true;
+ }
else if (strcmp(arg, "-adapter") == 0)
{
if (argCursor == argEnd)
diff --git a/tools/render-test/options.h b/tools/render-test/options.h
index 104906f42..0214c66e7 100644
--- a/tools/render-test/options.h
+++ b/tools/render-test/options.h
@@ -55,6 +55,7 @@ struct Options
int slangArgCount = 0;
bool useDXIL = false;
+ bool onlyStartup = false;
Slang::List<Slang::String> renderFeatures; /// Required render features for this test to run
diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp
index 2bc6cd8f8..34e041473 100644
--- a/tools/render-test/render-test-main.cpp
+++ b/tools/render-test/render-test-main.cpp
@@ -555,6 +555,7 @@ SLANG_TEST_TOOL_API SlangResult innerMain(Slang::StdWriters* stdWriters, SlangSe
return SLANG_FAIL;
}
+
StringBuilder rendererName;
rendererName << "[" << RendererUtil::toText(gOptions.rendererType) << "] ";
if (gOptions.adapter.Length())
@@ -565,7 +566,10 @@ SLANG_TEST_TOOL_API SlangResult innerMain(Slang::StdWriters* stdWriters, SlangSe
if (!renderer)
{
- fprintf(stderr, "Unable to create renderer %s\n", rendererName.Buffer());
+ if (!gOptions.onlyStartup)
+ {
+ fprintf(stderr, "Unable to create renderer %s\n", rendererName.Buffer());
+ }
return SLANG_FAIL;
}
@@ -578,11 +582,20 @@ SLANG_TEST_TOOL_API SlangResult innerMain(Slang::StdWriters* stdWriters, SlangSe
SlangResult res = renderer->initialize(desc, (HWND)window->getHandle());
if (SLANG_FAILED(res))
{
- fprintf(stderr, "Unable to initialize renderer %s\n", rendererName.Buffer());
+ if (!gOptions.onlyStartup)
+ {
+ fprintf(stderr, "Unable to initialize renderer %s\n", rendererName.Buffer());
+ }
return res;
}
}
+ // If the only test is we can startup, then we are done
+ if (gOptions.onlyStartup)
+ {
+ return SLANG_OK;
+ }
+
{
for (const auto& feature : gOptions.renderFeatures)
{
diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp
index 9119c3224..e475d4b5a 100644
--- a/tools/slang-test/slang-test-main.cpp
+++ b/tools/slang-test/slang-test-main.cpp
@@ -21,31 +21,48 @@ using namespace Slang;
#define STB_IMAGE_IMPLEMENTATION
#include "external/stb/stb_image.h"
-#ifdef _WIN32
-#define SLANG_TEST_SUPPORT_HLSL 1
-#include <d3dcompiler.h>
-#endif
-
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
+
// Options for a particular test
struct TestOptions
{
+ enum Type
+ {
+ Normal, ///< A regular test
+ Diagnostic, ///< Diagnostic tests will always run (as form of failure is being tested)
+ };
+
+ Type type = Type::Normal;
+
String command;
List<String> args;
// The categories that this test was assigned to
List<TestCategory*> categories;
+
+ bool isSynthesized = false;
+};
+
+struct TestDetails
+{
+ TestDetails() {}
+ explicit TestDetails(const TestOptions& inOptions):
+ options(inOptions)
+ {}
+
+ TestOptions options; ///< The options for the test
+ TestRequirements requirements; ///< The requirements for the test to work
};
// Information on tests to run for a particular file
struct FileTestList
{
- List<TestOptions> tests;
+ List<TestDetails> tests;
};
enum class SpawnType
@@ -68,9 +85,6 @@ struct TestInput
// as command line args)
TestOptions const* testOptions;
- // The list of tests that will be run on this file
- FileTestList const* testList;
-
// Determines how the test will be spawned
SpawnType spawnType;
};
@@ -79,6 +93,9 @@ typedef TestResult(*TestCallback)(TestContext* context, TestInput& input);
// Globals
+// Pre declare
+static void _addRenderTestOptions(const Options& options, OSProcessSpawner& spawner);
+
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! Functions !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
bool match(char const** ioCursor, char const* expected)
@@ -165,16 +182,13 @@ String collectRestOfLine(char const** ioCursor)
}
-
-TestResult gatherTestOptions(
+static TestResult _gatherTestOptions(
TestCategorySet* categorySet,
char const** ioCursor,
- FileTestList* testList)
+ TestOptions& outOptions)
{
char const* cursor = *ioCursor;
- TestOptions testOptions;
-
// Right after the `TEST` keyword, the user may specify
// one or more categories for the test.
if(*cursor == '(')
@@ -206,7 +220,7 @@ TestResult gatherTestOptions(
}
- testOptions.categories.Add(category);
+ outOptions.categories.Add(category);
if( *categoryEnd == ',' )
{
@@ -226,9 +240,9 @@ TestResult gatherTestOptions(
}
// If no categories were specified, then add the default category
- if(testOptions.categories.Count() == 0)
+ if(outOptions.categories.Count() == 0)
{
- testOptions.categories.Add(categorySet->defaultCategory);
+ outOptions.categories.Add(categorySet->defaultCategory);
}
if(*cursor == ':')
@@ -259,7 +273,7 @@ TestResult gatherTestOptions(
}
char const* commandEnd = cursor;
- testOptions.command = getString(commandStart, commandEnd);
+ outOptions.command = getString(commandStart, commandEnd);
if(*cursor == ':')
cursor++;
@@ -280,7 +294,6 @@ TestResult gatherTestOptions(
{
case 0: case '\r': case '\n':
skipToEndOfLine(&cursor);
- testList->tests.Add(testOptions);
return TestResult::Pass;
default:
@@ -306,7 +319,7 @@ TestResult gatherTestOptions(
char const* argEnd = cursor;
assert(argBegin != argEnd);
- testOptions.args.Add(getString(argBegin, argEnd));
+ outOptions.args.Add(getString(argBegin, argEnd));
}
}
@@ -343,8 +356,23 @@ TestResult gatherTestsForFile(
}
else if(match(&cursor, "//TEST"))
{
- if(gatherTestOptions(categorySet, &cursor, testList) != TestResult::Pass)
+ TestDetails testDetails;
+
+ if(_gatherTestOptions(categorySet, &cursor, testDetails.options) != TestResult::Pass)
+ return TestResult::Fail;
+
+ testList->tests.Add(testDetails);
+ }
+ else if (match(&cursor, "//DIAGNOSTIC_TEST"))
+ {
+ TestDetails testDetails;
+
+ if (_gatherTestOptions(categorySet, &cursor, testDetails.options) != TestResult::Pass)
return TestResult::Fail;
+
+ // Mark that it is a diagnostic test
+ testDetails.options.type = TestOptions::Type::Diagnostic;
+ testList->tests.Add(testDetails);
}
else
{
@@ -445,6 +473,324 @@ OSError spawnAndWaitSharedLibrary(TestContext* context, const String& testPath,
return kOSError_OperationFailed;
}
+
+static SlangResult _extractArg(const List<String>& args, const String& argName, String& outValue)
+{
+ SLANG_ASSERT(argName.Length() > 0 && argName[0] == '-');
+
+ const UInt count = args.Count();
+ for (UInt i = 0; i < count - 1; ++i)
+ {
+ if (args[i] == argName)
+ {
+ outValue = args[i + 1];
+ return SLANG_OK;
+ }
+ }
+ return SLANG_FAIL;
+}
+
+static bool _hasOption(const List<String>& args, const String& argName)
+{
+ return args.IndexOf(argName) != UInt(-1);
+}
+
+static BackendType _toBackendType(const UnownedStringSlice& slice)
+{
+ if (slice == "dxc")
+ {
+ return BackendType::Dxc;
+ }
+ else if (slice == "fxc")
+ {
+ return BackendType::Fxc;
+ }
+ else if (slice == "glslang")
+ {
+ return BackendType::Glslang;
+ }
+ return BackendType::Unknown;
+}
+
+static BackendFlags _getBackendFlagsForTarget(SlangCompileTarget target)
+{
+ switch (target)
+ {
+ case SLANG_TARGET_UNKNOWN:
+ case SLANG_HLSL:
+ case SLANG_GLSL:
+ {
+ return 0;
+ }
+ case SLANG_DXBC:
+ case SLANG_DXBC_ASM:
+ {
+ return BackendFlag::Fxc;
+ }
+ case SLANG_SPIRV:
+ case SLANG_SPIRV_ASM:
+ {
+ return BackendFlag::Glslang;
+ }
+ case SLANG_DXIL:
+ case SLANG_DXIL_ASM:
+ {
+ return BackendFlag::Dxc;
+ }
+ default:
+ {
+ SLANG_ASSERT(!"Unknown type");
+ return 0;
+ }
+ }
+}
+
+static BackendType _toBackendTypeFromPassThroughType(SlangPassThrough passThru)
+{
+ switch (passThru)
+ {
+ case SLANG_PASS_THROUGH_DXC: return BackendType::Dxc;
+ case SLANG_PASS_THROUGH_FXC: return BackendType::Fxc;
+ case SLANG_PASS_THROUGH_GLSLANG: return BackendType::Glslang;
+ default: return BackendType::Unknown;
+ }
+}
+
+static SlangCompileTarget _getCompileTarget(const UnownedStringSlice& name)
+{
+#define CASE(NAME, TARGET) if(name == NAME) return SLANG_##TARGET;
+
+ CASE("hlsl", HLSL)
+ CASE("glsl", GLSL)
+ CASE("dxbc", DXBC)
+ CASE("dxbc-assembly", DXBC_ASM)
+ CASE("dxbc-asm", DXBC_ASM)
+ CASE("spirv", SPIRV)
+ CASE("spirv-assembly", SPIRV_ASM)
+ CASE("spirv-asm", SPIRV_ASM)
+ CASE("dxil", DXIL)
+ CASE("dxil-assembly", DXIL_ASM)
+ CASE("dxil-asm", DXIL_ASM)
+#undef CASE
+
+ return SLANG_TARGET_UNKNOWN;
+}
+
+static SlangResult _extractRenderTestRequirements(OSProcessSpawner& spawner, TestRequirements* ioRequirements)
+{
+ const auto& args = spawner.argumentList_;
+
+ // TODO(JS):
+ // This is rather convoluted in that it has to work out from the command line parameters passed
+ // to render-test what renderer will be used.
+ // That a similar logic has to be kept inside the implementation of render-test and both this
+ // and render-test will have to be kept in sync.
+
+ bool useDxil = _hasOption(args, "-use-dxil");
+
+ bool usePassthru = false;
+
+ // Work out what kind of render will be used
+ RenderApiType renderApiType;
+ {
+ RenderApiType foundRenderApiType = RenderApiType::Unknown;
+ RenderApiType foundLanguageRenderType = RenderApiType::Unknown;
+
+ for (const auto& arg: args)
+ {
+ Slang::UnownedStringSlice argSlice = arg.getUnownedSlice();
+ if (argSlice.size() && argSlice[0] == '-')
+ {
+ // Look up the rendering API if set
+ UnownedStringSlice argName = UnownedStringSlice(argSlice.begin() + 1, argSlice.end());
+ RenderApiType renderApiType = RenderApiUtil::findApiTypeByName(argName);
+
+ if (renderApiType != RenderApiType::Unknown)
+ {
+ foundRenderApiType = renderApiType;
+
+ // There should be only one explicit api
+ SLANG_ASSERT(ioRequirements->explicitRenderApi == RenderApiType::Unknown || ioRequirements->explicitRenderApi == renderApiType);
+
+ // Set the explicitly set render api
+ ioRequirements->explicitRenderApi = renderApiType;
+ continue;
+ }
+
+ // Lookup the target language type
+ RenderApiType languageRenderType = RenderApiUtil::findImplicitLanguageRenderApiType(argName);
+ if (languageRenderType != RenderApiType::Unknown)
+ {
+ foundLanguageRenderType = languageRenderType;
+
+ // Use the pass thru compiler if these are the sources
+ usePassthru |= (argName == "hlsl" || argName == "glsl");
+
+ continue;
+ }
+ }
+ }
+
+ // If a render option isn't set use defaultRenderType
+ renderApiType = (foundRenderApiType == RenderApiType::Unknown) ? foundLanguageRenderType : foundRenderApiType;
+ }
+
+ // The native language for the API
+ SlangSourceLanguage nativeLanguage = SLANG_SOURCE_LANGUAGE_UNKNOWN;
+ SlangCompileTarget target = SLANG_TARGET_NONE;
+ SlangPassThrough passThru = SLANG_PASS_THROUGH_NONE;
+
+ switch (renderApiType)
+ {
+ case RenderApiType::D3D11:
+ target = SLANG_DXBC;
+ nativeLanguage = SLANG_SOURCE_LANGUAGE_HLSL;
+ passThru = SLANG_PASS_THROUGH_FXC;
+ break;
+ case RenderApiType::D3D12:
+ target = SLANG_DXBC;
+ nativeLanguage = SLANG_SOURCE_LANGUAGE_HLSL;
+ passThru = SLANG_PASS_THROUGH_FXC;
+ if (useDxil)
+ {
+ target = SLANG_DXIL;
+ passThru = SLANG_PASS_THROUGH_DXC;
+ }
+ break;
+
+ case RenderApiType::OpenGl:
+ target = SLANG_GLSL;
+ nativeLanguage = SLANG_SOURCE_LANGUAGE_GLSL;
+ passThru = SLANG_PASS_THROUGH_GLSLANG;
+ break;
+ case RenderApiType::Vulkan:
+ target = SLANG_SPIRV;
+ nativeLanguage = SLANG_SOURCE_LANGUAGE_GLSL;
+ passThru = SLANG_PASS_THROUGH_GLSLANG;
+ break;
+ }
+
+ SlangSourceLanguage sourceLanguage = nativeLanguage;
+ if (!usePassthru)
+ {
+ sourceLanguage = SLANG_SOURCE_LANGUAGE_SLANG;
+ passThru = SLANG_PASS_THROUGH_NONE;
+ }
+
+ if (passThru == SLANG_PASS_THROUGH_NONE)
+ {
+ // Work out backends needed based on the target
+ ioRequirements->addUsedBackends(_getBackendFlagsForTarget(target));
+ }
+ else
+ {
+ ioRequirements->addUsed(_toBackendTypeFromPassThroughType(passThru));
+ }
+
+ // Add the render api used
+ ioRequirements->addUsed(renderApiType);
+
+ return SLANG_OK;
+}
+
+static SlangResult _extractSlangCTestRequirements(OSProcessSpawner& spawner, TestRequirements* ioRequirements)
+{
+ // This determines what the requirements are for a slangc like command line
+ const auto& args = spawner.argumentList_;
+
+ // First check pass through
+ {
+ String passThrough;
+ if (SLANG_SUCCEEDED(_extractArg(args, "-pass-through", passThrough)))
+ {
+ ioRequirements->addUsed(_toBackendType(passThrough.getUnownedSlice()));
+ }
+ }
+
+ // The target if set will also imply a backend
+ {
+ String targetName;
+ if (SLANG_SUCCEEDED(_extractArg(args, "-target", targetName)))
+ {
+ const SlangCompileTarget target = _getCompileTarget(targetName.getUnownedSlice());
+ ioRequirements->addUsedBackends(_getBackendFlagsForTarget(target));
+ }
+ }
+ return SLANG_OK;
+
+}
+
+static SlangResult _extractReflectionTestRequirements(OSProcessSpawner& spawner, TestRequirements* ioRequirements)
+{
+ // There are no specialized constraints for a reflection test
+ return SLANG_OK;
+}
+
+static SlangResult _extractTestRequirements(OSProcessSpawner& spawner, TestRequirements* ioInfo)
+{
+ String exeName = Path::GetFileNameWithoutEXT(spawner.executableName_);
+
+ if (exeName == "render-test")
+ {
+ return _extractRenderTestRequirements(spawner, ioInfo);
+ }
+ else if (exeName == "slangc")
+ {
+ return _extractSlangCTestRequirements(spawner, ioInfo);
+ }
+ else if (exeName == "slang-reflection-test")
+ {
+ return _extractReflectionTestRequirements(spawner, ioInfo);
+ }
+
+ SLANG_ASSERT(!"Unknown tool type");
+ return SLANG_FAIL;
+}
+
+static RenderApiFlags _getAvailableRenderApiFlags(TestContext* context)
+{
+ // Only evaluate if it hasn't already been evaluated (the actual evaluation is slow...)
+ if (!context->isAvailableRenderApiFlagsValid)
+ {
+ // Call the render-test tool asking it only to startup a specified render api
+ // (taking into account adapter options)
+
+ RenderApiFlags availableRenderApiFlags = 0;
+ for (int i = 0; i < int(RenderApiType::CountOf); ++i)
+ {
+ const RenderApiType apiType = RenderApiType(i);
+
+ // See if it's possible the api is available
+ if (RenderApiUtil::calcHasApi(apiType))
+ {
+ // Try starting up the device
+ OSProcessSpawner spawner;
+ spawner.pushExecutablePath(String(context->options.binDir) + "render-test" + osGetExecutableSuffix());
+ _addRenderTestOptions(context->options, spawner);
+ // We just want to see if the device can be started up
+ spawner.pushArgument("-only-startup");
+
+ // Select what api to use
+ StringBuilder builder;
+ builder << "-" << RenderApiUtil::getApiName(apiType);
+ spawner.pushArgument(builder);
+
+ // Run the render-test tool and see if the device could startup
+ if (spawnAndWaitSharedLibrary(context, "device-startup", spawner) == OSError::kOSError_None
+ && TestToolUtil::getReturnCodeFromInt(spawner.resultCode_) == ToolReturnCode::Success)
+ {
+ availableRenderApiFlags |= RenderApiFlags(1) << int(apiType);
+ }
+ }
+ }
+
+ context->availableRenderApiFlags = availableRenderApiFlags;
+ context->isAvailableRenderApiFlagsValid = true;
+ }
+
+ return context->availableRenderApiFlags;
+}
+
ToolReturnCode getReturnCode(OSProcessSpawner& spawner)
{
return TestToolUtil::getReturnCodeFromInt(spawner.getResultCode());
@@ -452,6 +798,17 @@ ToolReturnCode getReturnCode(OSProcessSpawner& spawner)
ToolReturnCode spawnAndWait(TestContext* context, const String& testPath, SpawnType spawnType, OSProcessSpawner& spawner)
{
+ if (context->isCollectingRequirements())
+ {
+ // If we just want info... don't bother running anything
+ const SlangResult res = _extractTestRequirements(spawner, context->testRequirements);
+ // Keep compiler happy on release
+ SLANG_UNUSED(res);
+ SLANG_ASSERT(SLANG_SUCCEEDED(res));
+
+ return ToolReturnCode::Success;
+ }
+
const auto& options = context->options;
OSError spawnResult = kOSError_OperationFailed;
@@ -581,9 +938,14 @@ TestResult runSimpleTest(TestContext* context, TestInput& input)
{
spawner.pushArgument(arg);
}
-
+
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, spawner));
+ if (context->isCollectingRequirements())
+ {
+ return TestResult::Pass;
+ }
+
String actualOutput = getOutput(spawner);
String expectedOutputPath = outputStem + ".expected";
@@ -655,6 +1017,11 @@ TestResult runReflectionTest(TestContext* context, TestInput& input)
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, spawner));
+ if (context->isCollectingRequirements())
+ {
+ return TestResult::Pass;
+ }
+
String actualOutput = getOutput(spawner);
String expectedOutputPath = outputStem + ".expected";
@@ -718,28 +1085,6 @@ String getExpectedOutput(String const& outputStem)
return expectedOutput;
}
-static SlangCompileTarget _getCompileTarget(const UnownedStringSlice& name)
-{
-#define CASE(NAME, TARGET) if(name == NAME) return SLANG_##TARGET;
-
- CASE("hlsl", HLSL)
- CASE("glsl", GLSL)
- CASE("dxbc", DXBC)
- CASE("dxbc-assembly", DXBC_ASM)
- CASE("dxbc-asm", DXBC_ASM)
- CASE("spirv", SPIRV)
- CASE("spirv-assembly", SPIRV_ASM)
- CASE("spirv-asm", SPIRV_ASM)
- CASE("dxil", DXIL)
- CASE("dxil-assembly", DXIL_ASM)
- CASE("dxil-asm", DXIL_ASM)
-#undef CASE
-
- return SLANG_TARGET_UNKNOWN;
-}
-
-
-
TestResult runCrossCompilerTest(TestContext* context, TestInput& input)
{
// need to execute the stand-alone Slang compiler on the file
@@ -755,7 +1100,9 @@ TestResult runCrossCompilerTest(TestContext* context, TestInput& input)
_initSlangCompiler(context, expectedSpawner);
actualSpawner.pushArgument(filePath);
-
+
+ // TODO(JS): This should no longer be needed with TestInfo accumulated for a test
+
const auto& args = input.testOptions->args;
const UInt targetIndex = args.IndexOf("-target");
@@ -802,20 +1149,29 @@ TestResult runCrossCompilerTest(TestContext* context, TestInput& input)
}
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, expectedSpawner));
-
- String expectedOutput = getOutput(expectedSpawner);
- String expectedOutputPath = outputStem + ".expected";
- try
- {
- Slang::File::WriteAllText(expectedOutputPath, expectedOutput);
- }
- catch (Slang::IOException)
+
+ String expectedOutput;
+ if (context->isExecuting())
{
- return TestResult::Fail;
+ expectedOutput = getOutput(expectedSpawner);
+ String expectedOutputPath = outputStem + ".expected";
+ try
+ {
+ Slang::File::WriteAllText(expectedOutputPath, expectedOutput);
+ }
+ catch (Slang::IOException)
+ {
+ return TestResult::Fail;
+ }
}
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, actualSpawner));
+ if (context->isCollectingRequirements())
+ {
+ return TestResult::Pass;
+ }
+
String actualOutput = getOutput(actualSpawner);
TestResult result = TestResult::Pass;
@@ -849,8 +1205,6 @@ TestResult runCrossCompilerTest(TestContext* context, TestInput& input)
return result;
}
-
-#ifdef SLANG_TEST_SUPPORT_HLSL
TestResult generateHLSLBaseline(TestContext* context, TestInput& input)
{
auto filePath999 = input.filePath;
@@ -873,6 +1227,11 @@ TestResult generateHLSLBaseline(TestContext* context, TestInput& input)
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, spawner));
+ if (context->isCollectingRequirements())
+ {
+ return TestResult::Pass;
+ }
+
String expectedOutput = getOutput(spawner);
String expectedOutputPath = outputStem + ".expected";
try
@@ -918,6 +1277,11 @@ TestResult runHLSLComparisonTest(TestContext* context, TestInput& input)
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, spawner));
+ if (context->isCollectingRequirements())
+ {
+ return TestResult::Pass;
+ }
+
// We ignore output to stdout, and only worry about what the compiler
// wrote to stderr.
@@ -985,7 +1349,6 @@ TestResult runHLSLComparisonTest(TestContext* context, TestInput& input)
return result;
}
-#endif
TestResult doGLSLComparisonTestRun(TestContext* context,
TestInput& input,
@@ -1024,6 +1387,11 @@ TestResult doGLSLComparisonTestRun(TestContext* context,
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, spawner));
+ if (context->isCollectingRequirements())
+ {
+ return TestResult::Pass;
+ }
+
OSProcessSpawner::ResultCode resultCode = spawner.getResultCode();
String standardOuptut = spawner.getStandardOutput();
@@ -1058,6 +1426,11 @@ TestResult runGLSLComparisonTest(TestContext* context, TestInput& input)
TestResult hlslResult = doGLSLComparisonTestRun(context, input, "__GLSL__", "glslang", ".expected", &expectedOutput);
TestResult slangResult = doGLSLComparisonTestRun(context, input, "__SLANG__", nullptr, ".actual", &actualOutput);
+ if (context->isCollectingRequirements())
+ {
+ return TestResult::Pass;
+ }
+
// If either is ignored, the whole test is
if (hlslResult == TestResult::Ignored ||
slangResult == TestResult::Ignored)
@@ -1096,12 +1469,6 @@ TestResult runComputeComparisonImpl(TestContext* context, TestInput& input, cons
auto filePath999 = input.filePath;
auto outputStem = input.outputStem;
- const String referenceOutput = findExpectedPath(input, ".expected.txt");
- if (referenceOutput.Length() <= 0)
- {
- return TestResult::Fail;
- }
-
OSProcessSpawner spawner;
spawner.pushExecutablePath(String(context->options.binDir) + "render-test" + osGetExecutableSuffix());
@@ -1122,11 +1489,25 @@ TestResult runComputeComparisonImpl(TestContext* context, TestInput& input, cons
auto actualOutputFile = outputStem + ".actual.txt";
spawner.pushArgument(actualOutputFile);
- // clear the stale actual output file first. This will allow us to detect error if render-test fails and outputs nothing.
- File::WriteAllText(actualOutputFile, "");
+ if (context->isExecuting())
+ {
+ // clear the stale actual output file first. This will allow us to detect error if render-test fails and outputs nothing.
+ File::WriteAllText(actualOutputFile, "");
+ }
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, spawner));
+ if (context->isCollectingRequirements())
+ {
+ return TestResult::Pass;
+ }
+
+ const String referenceOutput = findExpectedPath(input, ".expected.txt");
+ if (referenceOutput.Length() <= 0)
+ {
+ return TestResult::Fail;
+ }
+
auto actualOutput = getOutput(spawner);
auto expectedOutput = getExpectedOutput(outputStem);
if (actualOutput != expectedOutput)
@@ -1224,6 +1605,11 @@ TestResult doRenderComparisonTestRun(TestContext* context, TestInput& input, cha
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, spawner));
+ if (context->isCollectingRequirements())
+ {
+ return TestResult::Pass;
+ }
+
OSProcessSpawner::ResultCode resultCode = spawner.getResultCode();
String standardOutput = spawner.getStandardOutput();
@@ -1429,6 +1815,11 @@ TestResult runHLSLRenderComparisonTestImpl(
return slangResult;
}
+ if (context->isCollectingRequirements())
+ {
+ return TestResult::Pass;
+ }
+
Slang::File::WriteAllText(outputStem + ".expected", expectedOutput);
Slang::File::WriteAllText(outputStem + ".actual", actualOutput);
@@ -1471,168 +1862,61 @@ TestResult skipTest(TestContext* /* context */, TestInput& /*input*/)
return TestResult::Ignored;
}
-static bool hasRenderOption(RenderApiType apiType, const List<String>& options)
+// based on command name, dispatch to an appropriate callback
+struct TestCommandInfo
{
- SLANG_ASSERT(apiType != RenderApiType::Unknown);
- if (apiType == RenderApiType::Unknown)
- {
- return false;
- }
-
- const RenderApiUtil::Info& info = RenderApiUtil::getInfo(apiType);
-
- List<UnownedStringSlice> namesList;
-
- for (UInt i = 0; i < options.Count(); ++i)
- {
- const String& option = options[i];
-
- if (option.StartsWith("-"))
- {
- const UnownedStringSlice parameter(option.Buffer() + 1, option.Buffer() + option.Length());
- const RenderApiType paramType = RenderApiUtil::findApiTypeByName(parameter);
-
- // Found it
- if (apiType == paramType)
- {
- return true;
- }
- }
- }
-
- return false;
-}
-
-bool hasRenderOption(RenderApiType apiType, const TestOptions& options)
-{
- return hasRenderOption(apiType, options.args);
-}
-
-bool hasRenderOption(RenderApiType apiType, const FileTestList& testList)
-{
- const int numTests = int(testList.tests.Count());
- for (int i = 0; i < numTests; i++)
- {
- if (hasRenderOption(apiType, testList.tests[i].args))
- {
- return true;
- }
- }
- return false;
-}
-
-bool isHLSLTest(const String& command)
-{
- return command == "COMPARE_HLSL" ||
- command == "COMPARE_HLSL_RENDER" ||
- command == "COMPARE_HLSL_CROSS_COMPILE_RENDER" ||
- command == "COMPARE_HLSL_GLSL_RENDER";
-}
-
-bool isRenderTest(const String& command)
-{
- return command == "COMPARE_COMPUTE" ||
- command == "COMPARE_COMPUTE_EX" ||
- command == "HLSL_COMPUTE" ||
- command == "COMPARE_RENDER_COMPUTE" ||
- command == "COMPARE_HLSL_RENDER" ||
- command == "COMPARE_HLSL_CROSS_COMPILE_RENDER" ||
- command == "COMPARE_HLSL_GLSL_RENDER";
-}
-
-static bool canIgnoreTestWithDisabledRenderer(const TestOptions& testOptions, const Options& appOptions)
-{
- for (int i = 0; i < int(RenderApiType::CountOf); ++i)
- {
- RenderApiType apiType = RenderApiType(i);
- RenderApiFlag::Enum apiFlag = RenderApiFlag::Enum(1 << i);
-
- if (hasRenderOption(apiType, testOptions) && (appOptions.enabledApis & apiFlag) == 0)
- {
- return true;
- }
- }
+ char const* name;
+ TestCallback callback;
+};
- return false;
-}
+static const TestCommandInfo s_testCommandInfos[] =
+{
+ { "SIMPLE", &runSimpleTest},
+ { "REFLECTION", &runReflectionTest},
+ { "COMMAND_LINE_SIMPLE", &runSimpleCompareCommandLineTest},
+ { "COMPARE_HLSL", &runHLSLComparisonTest},
+ { "COMPARE_HLSL_RENDER", &runHLSLRenderComparisonTest},
+ { "COMPARE_HLSL_CROSS_COMPILE_RENDER", &runHLSLCrossCompileRenderComparisonTest},
+ { "COMPARE_HLSL_GLSL_RENDER", &runHLSLAndGLSLRenderComparisonTest},
+ { "COMPARE_COMPUTE", &runSlangComputeComparisonTest},
+ { "COMPARE_COMPUTE_EX", &runSlangComputeComparisonTestEx},
+ { "HLSL_COMPUTE", &runHLSLComputeTest},
+ { "COMPARE_RENDER_COMPUTE", &runSlangRenderComputeComparisonTest},
+ { "COMPARE_GLSL", &runGLSLComparisonTest},
+ { "CROSS_COMPILE", &runCrossCompilerTest},
+};
TestResult runTest(
TestContext* context,
String const& filePath,
String const& outputStem,
- TestOptions const& testOptions,
- FileTestList const& testList)
+ String const& testName,
+ TestOptions const& testOptions)
{
- // If this test can be ignored
- if (canIgnoreTestWithDisabledRenderer(testOptions, context->options))
+ // If we are collecting requirements and it's diagnostic test, we always run
+ // (ie no requirements need to be captured - effectively it has 'no requirements')
+ if (context->isCollectingRequirements() && testOptions.type == TestOptions::Diagnostic)
{
- return TestResult::Ignored;
+ return TestResult::Pass;
}
-
- // based on command name, dispatch to an appropriate callback
- struct TestCommands
- {
- char const* name;
- TestCallback callback;
- };
-
- static const TestCommands kTestCommands[] =
- {
- { "SIMPLE", &runSimpleTest},
- { "REFLECTION", &runReflectionTest},
- { "COMMAND_LINE_SIMPLE", &runSimpleCompareCommandLineTest},
-#if SLANG_TEST_SUPPORT_HLSL
- { "COMPARE_HLSL", &runHLSLComparisonTest},
- { "COMPARE_HLSL_RENDER", &runHLSLRenderComparisonTest},
- { "COMPARE_HLSL_CROSS_COMPILE_RENDER", &runHLSLCrossCompileRenderComparisonTest},
- { "COMPARE_HLSL_GLSL_RENDER", &runHLSLAndGLSLRenderComparisonTest },
- { "COMPARE_COMPUTE", runSlangComputeComparisonTest},
- { "COMPARE_COMPUTE_EX", runSlangComputeComparisonTestEx},
- { "HLSL_COMPUTE", runHLSLComputeTest},
- { "COMPARE_RENDER_COMPUTE", &runSlangRenderComputeComparisonTest },
-
-#else
- { "COMPARE_HLSL", &skipTest },
- { "COMPARE_HLSL_RENDER", &skipTest },
- { "COMPARE_HLSL_CROSS_COMPILE_RENDER", &skipTest},
- { "COMPARE_HLSL_GLSL_RENDER", &skipTest },
- { "COMPARE_COMPUTE", &skipTest},
- { "COMPARE_COMPUTE_EX", &skipTest},
- { "HLSL_COMPUTE", &skipTest},
- { "COMPARE_RENDER_COMPUTE", &skipTest },
-#endif
- { "COMPARE_GLSL", &runGLSLComparisonTest },
- { "CROSS_COMPILE", &runCrossCompilerTest },
- { nullptr, nullptr },
- };
const SpawnType defaultSpawnType = context->options.useExes ? SpawnType::UseExe : SpawnType::UseSharedLibrary;
- for( auto ii = kTestCommands; ii->name; ++ii )
+ for( const auto& command : s_testCommandInfos)
{
- if(testOptions.command != ii->name)
+ if(testOptions.command != command.name)
continue;
TestInput testInput;
testInput.filePath = filePath;
testInput.outputStem = outputStem;
testInput.testOptions = &testOptions;
- testInput.testList = &testList;
testInput.spawnType = defaultSpawnType;
- {
- TestReporter* reporter = context->reporter;
- TestReporter::TestScope scope(reporter, outputStem);
-
- TestResult testResult = ii->callback(context, testInput);
- reporter->addResult(testResult);
-
- return testResult;
- }
+ return command.callback(context, testInput);
}
// No actual test runner found!
-
return TestResult::Fail;
}
@@ -1674,7 +1958,7 @@ bool testPassesCategoryMask(
return false;
}
- // Otherwise inclue any test the user asked for
+ // Otherwise include any test the user asked for
for( auto testCategory : test.categories )
{
if(testCategoryMatches(testCategory, context->options.includeCategories))
@@ -1685,74 +1969,79 @@ bool testPassesCategoryMask(
return false;
}
-static RenderApiType _findRenderApi(const List<String>& args, bool onlyExplicit)
+static void _calcSynthesizedTests(TestContext* context, RenderApiType synthRenderApiType, const List<TestDetails>& srcTests, List<TestDetails>& ioSynthTests)
{
- RenderApiType targetLanguageRenderer = RenderApiType::Unknown;
-
- for (const auto& arg: args)
+ // Add the explicit parameter
+ for (const auto& testDetails: srcTests)
{
- const UnownedStringSlice argSlice = arg.getUnownedSlice();
- if (argSlice.size() && argSlice[0] == '-' && !argSlice.startsWith(UnownedStringSlice::fromLiteral("--")))
- {
- UnownedStringSlice argName(argSlice.begin() + 1, argSlice.end());
+ const auto& requirements = testDetails.requirements;
- RenderApiType renderType = RenderApiUtil::findRenderApiType(argName);
- if (renderType != RenderApiType::Unknown)
- {
- return renderType;
- }
+ // Render tests use renderApis...
+ // If it's an explicit test, we don't synth from it now
- if (!onlyExplicit)
- {
- RenderApiType implicitRenderType = RenderApiUtil::findImplicitLanguageRenderApiType(argName);
- if (implicitRenderType != RenderApiType::Unknown)
- {
- targetLanguageRenderer = implicitRenderType;
- }
- }
+ // TODO(JS): Arguably we should synthesize from explicit tests. In principal we can remove the explicit api apply another
+ // although that may not always work.
+ if (requirements.usedRenderApiFlags == 0 ||
+ requirements.explicitRenderApi != RenderApiType::Unknown)
+ {
+ continue;
}
- }
-
- return targetLanguageRenderer;
-}
-static void _addSynthesizedTest(RenderApiType rendererType, const List<TestOptions>& renderTests, List<TestOptions>& outSynthesizedTests)
-{
- for (const auto& test : renderTests)
- {
- // If doesn't have an explicit render api, add one and add to the synthesized tests
- RenderApiType explicitRenderer = _findRenderApi(test.args, true);
-
- if (explicitRenderer == RenderApiType::Unknown)
- {
- // Add the explicit parameter
+ TestDetails synthTestDetails(testDetails.options);
+ TestOptions& synthOptions = synthTestDetails.options;
- TestOptions options(test);
+ // Mark as synthesized
+ synthOptions.isSynthesized = true;
- StringBuilder builder;
- builder << "-";
- builder << RenderApiUtil::getApiName(rendererType);
+ StringBuilder builder;
+ builder << "-";
+ builder << RenderApiUtil::getApiName(synthRenderApiType);
- options.args.Add(builder);
+ synthOptions.args.Add(builder);
- // If the target is vulkan remove the -hlsl option
- if (rendererType == RenderApiType::Vulkan)
+ // If the target is vulkan remove the -hlsl option
+ if (synthRenderApiType == RenderApiType::Vulkan)
+ {
+ UInt index = synthOptions.args.IndexOf("-hlsl");
+ if (index != UInt(-1))
{
- UInt index = options.args.IndexOf("-hlsl");
- if (index != UInt(-1))
- {
- options.args.RemoveAt(index);
- }
+ synthOptions.args.RemoveAt(index);
}
+ }
- // Add to the tests
- outSynthesizedTests.Add(options);
+ // Work out the info about this tests
+ context->testRequirements = &synthTestDetails.requirements;
+ runTest(context, "", "", "", synthOptions);
+ context->testRequirements = nullptr;
- return;
- }
+ // It does set the explicit render target
+ SLANG_ASSERT(synthTestDetails.requirements.explicitRenderApi == synthRenderApiType);
+ // Add to the tests
+ ioSynthTests.Add(synthTestDetails);
}
}
+static bool _canIgnore(TestContext* context,
+ const TestRequirements& requirements)
+{
+ // Work out what render api flags are available
+ const RenderApiFlags availableRenderApiFlags = requirements.usedRenderApiFlags ? _getAvailableRenderApiFlags(context) : 0;
+
+ // Are all the required backends available?
+ if (((requirements.usedBackendFlags & context->availableBackendFlags) != requirements.usedBackendFlags))
+ {
+ return true;
+ }
+
+ // Are all the required rendering apis available?
+ if ((requirements.usedRenderApiFlags & availableRenderApiFlags) != requirements.usedRenderApiFlags)
+ {
+ return true;
+ }
+
+ return false;
+}
+
void runTestsOnFile(
TestContext* context,
String filePath)
@@ -1773,73 +2062,132 @@ void runTestsOnFile(
return;
}
- // If synthesized tests are wanted look into adding them
- if (context->options.synthesizedTestApis)
+ RenderApiFlags apiUsedFlags = 0;
+ RenderApiFlags explictUsedApiFlags = 0;
+
{
- List<TestOptions> synthesizedTests;
+ // We can get the test info for each of them
+ for (auto& testDetails : testList.tests)
+ {
+ auto& requirements = testDetails.requirements;
- // Lets find all tests which are render tests
- RenderApiFlags apisUsed = 0;
- List<TestOptions> renderTests;
+ // Collect what the test needs (by setting restRequirements the test isn't actually run)
+ context->testRequirements = &requirements;
+ runTest(context, filePath, filePath, filePath, testDetails.options);
- const int numTests = int(testList.tests.Count());
- for (int i = 0; i < numTests; i++)
- {
- const TestOptions& testOptions = testList.tests[i];
- if (isRenderTest(testOptions.command))
- {
- RenderApiType renderType = _findRenderApi(testOptions.args, false);
- if (renderType != RenderApiType::Unknown)
- {
- apisUsed |= (1 << int(renderType));
- }
- renderTests.Add(testOptions);
- }
+ //
+ apiUsedFlags |= requirements.usedRenderApiFlags;
+ explictUsedApiFlags |= (requirements.explicitRenderApi != RenderApiType::Unknown) ? (RenderApiFlags(1) << int(requirements.explicitRenderApi)) : 0;
}
+ context->testRequirements = nullptr;
+ }
+
+ SLANG_ASSERT((apiUsedFlags & explictUsedApiFlags) == explictUsedApiFlags);
+
+ const RenderApiFlags availableRenderApiFlags = apiUsedFlags ? _getAvailableRenderApiFlags(context) : 0;
+
+ // If synthesized tests are wanted look into adding them
+ if (context->options.synthesizedTestApis && availableRenderApiFlags)
+ {
+ List<TestDetails> synthesizedTests;
+
// What render options do we want to synthesize
- RenderApiFlags missingApis = (~apisUsed) & context->options.synthesizedTestApis;
-
- // We can only synthesize if if there isn't an explicit render option
+ RenderApiFlags missingApis = (~apiUsedFlags) & (context->options.synthesizedTestApis & availableRenderApiFlags);
+
+ const UInt numInitialTests = testList.tests.Count();
while (missingApis)
{
const int index = ByteEncodeUtil::calcMsb8(missingApis);
SLANG_ASSERT(index >= 0 && index <= int(RenderApiType::CountOf));
- _addSynthesizedTest(RenderApiType(index), renderTests, synthesizedTests);
+ const RenderApiType synthRenderApiType = RenderApiType(index);
+ _calcSynthesizedTests(context, synthRenderApiType, testList.tests, synthesizedTests);
+
// Disable the bit
missingApis &= ~(RenderApiFlags(1) << index);
}
- // Add any tests that were synthesized
- for (UInt i = 0; i < synthesizedTests.Count(); ++i)
- {
- testList.tests.Add(synthesizedTests[i]);
- }
+ // Add all the synthesized tests
+ testList.tests.AddRange(synthesizedTests);
}
// We have found a test to run!
int subTestCount = 0;
- for( auto& tt : testList.tests )
+ for( auto& testDetails : testList.tests )
{
int subTestIndex = subTestCount++;
// Check that the test passes our current category mask
- if(!testPassesCategoryMask(context, tt))
+ if(!testPassesCategoryMask(context, testDetails.options))
{
continue;
}
- String outputStem = filePath;
- if(subTestIndex != 0)
+ // Work out the test stem
+
+ StringBuilder outputStem;
+ outputStem << filePath;
+ if (subTestIndex != 0)
+ {
+ outputStem << "." << subTestIndex;
+ }
+
+ // Work out the test name - taking into account render api / if synthesized
+ StringBuilder testName(outputStem);
+
+ if (testDetails.options.isSynthesized)
{
- outputStem = outputStem + "." + String(subTestIndex);
+ testName << " syn";
}
- /* TestResult result = */ runTest(context, filePath, outputStem, tt, testList);
+ const auto& requirements = testDetails.requirements;
- // Could determine if to continue or not here... based on result
+ // Display list of used apis on render test
+ if (requirements.usedRenderApiFlags)
+ {
+ RenderApiFlags usedFlags = requirements.usedRenderApiFlags;
+ testName << " (";
+ bool isPrev = false;
+ while (usedFlags)
+ {
+ const int index = ByteEncodeUtil::calcMsb8(usedFlags);
+ const RenderApiType renderApiType = RenderApiType(index);
+ if (isPrev)
+ {
+ testName << ",";
+ }
+ testName << RenderApiUtil::getApiName(renderApiType);
+
+ // Disable bit
+ usedFlags &= ~(RenderApiFlags(1) << index);
+ isPrev = true;
+ }
+ testName << ")";
+ }
+
+ // Report the test and run/ignore
+ {
+ auto reporter = context->reporter;
+ TestReporter::TestScope scope(reporter, testName);
+
+ TestResult testResult = TestResult::Fail;
+
+ // If this test can be ignored
+ if (_canIgnore(context, testDetails.requirements))
+ {
+ testResult = TestResult::Ignored;
+ }
+ else
+ {
+ testResult = runTest(context, filePath, outputStem, testName, testDetails.options);
+ }
+
+ reporter->addResult(testResult);
+
+ // Could determine if to continue or not here... based on result
+ }
}
}
@@ -1911,6 +2259,7 @@ void runTestsInDirectory(
}
}
+
SlangResult innerMain(int argc, char** argv)
{
auto stdWriters = StdWriters::initDefaultSingleton();
@@ -1964,6 +2313,22 @@ SlangResult innerMain(int argc, char** argv)
// An un-categorized test will always belong to the `full` category
categorySet.defaultCategory = fullTestCategory;
+ // Work out what backends are available
+ {
+ SlangSession* session = context.getSession();
+ const SlangPassThrough passThrus[] = { SLANG_PASS_THROUGH_DXC, SLANG_PASS_THROUGH_FXC, SLANG_PASS_THROUGH_GLSLANG };
+ for (auto passThru: passThrus)
+ {
+ if (SLANG_SUCCEEDED(spSessionCheckPassThroughSupport(session, passThru)))
+ {
+ context.availableBackendFlags |= BackendFlags(1) << int(_toBackendTypeFromPassThroughType(passThru));
+ }
+ }
+ }
+
+ // Working out what renderApis is worked on on demand through
+ // _getAvailableRenderApiFlags()
+
{
// We can set the slangc command line tool, to just use the function defined here
context.setInnerMainFunc("slangc", &SlangCTool::innerMain);
diff --git a/tools/slang-test/test-context.h b/tools/slang-test/test-context.h
index b07ca94e6..95b46fe6e 100644
--- a/tools/slang-test/test-context.h
+++ b/tools/slang-test/test-context.h
@@ -8,16 +8,78 @@
#include "../../source/core/slang-std-writers.h"
#include "../../source/core/dictionary.h"
#include "../../source/core/slang-test-tool-util.h"
+#include "../../source/core/slang-render-api-util.h"
#include "options.h"
+enum class BackendType
+{
+ Unknown = -1,
+ Dxc,
+ Fxc,
+ Glslang,
+ CountOf,
+};
+
+typedef uint32_t BackendFlags;
+struct BackendFlag
+{
+ enum Enum : uint32_t
+ {
+ Dxc = 1 << int(BackendType::Dxc),
+ Fxc = 1 << int(BackendType::Fxc),
+ Glslang = 1 << int(BackendType::Glslang),
+ };
+};
+
+/// Structure that describes requirements needs to run - such as rendering APIs or
+/// back-end availability
+struct TestRequirements
+{
+ TestRequirements& addUsed(BackendType type)
+ {
+ if (type != BackendType::Unknown)
+ {
+ usedBackendFlags |= BackendFlags(1) << int(type);
+ }
+ return *this;
+ }
+ TestRequirements& addUsed(Slang::RenderApiType type)
+ {
+ using namespace Slang;
+ if (type != RenderApiType::Unknown)
+ {
+ usedRenderApiFlags |=RenderApiFlags(1) << int(type);
+ }
+ return *this;
+ }
+ TestRequirements& addUsedBackends(BackendFlags flags)
+ {
+ usedBackendFlags |= flags;
+ return *this;
+ }
+ TestRequirements& addUsedRenderApis(Slang::RenderApiFlags flags)
+ {
+ usedRenderApiFlags |= flags;
+ return *this;
+ }
+ /// True if has this render api as used
+ bool isUsed(Slang::RenderApiType apiType) const
+ {
+ return (apiType != Slang::RenderApiType::Unknown) && ((usedRenderApiFlags & (Slang::RenderApiFlags(1) << int(apiType))) != 0);
+ }
+
+ Slang::RenderApiType explicitRenderApi = Slang::RenderApiType::Unknown; ///< The render api explicitly specified
+ BackendFlags usedBackendFlags = 0; ///< Used backends
+ Slang::RenderApiFlags usedRenderApiFlags = 0; ///< Used render api flags (some might be implied)
+};
+
class TestContext
{
public:
typedef Slang::TestToolUtil::InnerMainFunc InnerMainFunc;
-
/// Get the slang session
SlangSession* getSession() const { return m_session; }
@@ -28,6 +90,11 @@ class TestContext
/// Set the function for the shared library
void setInnerMainFunc(const Slang::String& name, InnerMainFunc func);
+ /// If true tests aren't being run just the information on testing is being accumulated
+ bool isCollectingRequirements() const { return testRequirements != nullptr; }
+ /// If set, then tests are executed
+ bool isExecuting() const { return testRequirements == nullptr; }
+
/// Ctor
TestContext();
/// Dtor
@@ -37,6 +104,13 @@ class TestContext
TestReporter* reporter = nullptr;
TestCategorySet categorySet;
+ /// If set then tests are not run, but their requirements are set
+ TestRequirements* testRequirements = nullptr;
+
+ BackendFlags availableBackendFlags = 0;
+ Slang::RenderApiFlags availableRenderApiFlags = 0;
+ bool isAvailableRenderApiFlagsValid = false;
+
protected:
struct SharedLibraryTool
{