summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--source/slang/emit.cpp5
-rw-r--r--source/slang/lower.cpp99
-rw-r--r--tests/cross-compile/integer-input.slang11
-rw-r--r--tests/cross-compile/integer-input.slang.glsl26
-rw-r--r--tests/cross-compile/nointerpolation-input.slang11
-rw-r--r--tests/cross-compile/nointerpolation-input.slang.glsl26
-rw-r--r--tools/slang-test/main.cpp78
8 files changed, 255 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index 2e654c7bb..9267cfca3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,6 +16,7 @@ intermediate/
*.expected.png
*.actual.png
tests/render/*.expected
+tests/cross-compile/*.expected
# files generated by other shader compilers
*.spv
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 88b80589a..7ffce2acd 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -2667,11 +2667,12 @@ struct EmitVisitor
else if(auto mod_##TYPE = mod.As<TYPE>()) Emit(#KEYWORD " ")
#define CASE2(TYPE, HLSL_NAME, GLSL_NAME) \
- else if(auto mod_##TYPE = mod.As<TYPE>()) Emit((context->shared->target == CodeGenTarget::GLSL) ? GLSL_NAME : HLSL_NAME)
+ else if(auto mod_##TYPE = mod.As<TYPE>()) Emit((context->shared->target == CodeGenTarget::GLSL) ? (#GLSL_NAME " ") : (#HLSL_NAME " "))
CASE(RowMajorLayoutModifier, row_major);
CASE(ColumnMajorLayoutModifier, column_major);
- CASE(HLSLNoInterpolationModifier, nointerpolation);
+
+ CASE2(HLSLNoInterpolationModifier, nointerpolation, flat);
CASE(HLSLPreciseModifier, precise);
CASE(HLSLEffectSharedModifier, shared);
CASE(HLSLGroupSharedModifier, groupshared);
diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp
index caa1ab075..856da9b6c 100644
--- a/source/slang/lower.cpp
+++ b/source/slang/lower.cpp
@@ -7,6 +7,19 @@
namespace Slang
{
+struct CloneVisitor
+ : ModifierVisitor<CloneVisitor, RefPtr<Modifier>>
+{
+#define ABSTRACT_SYNTAX_CLASS(NAME, BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE, ...) \
+ RefPtr<NAME> visit ## NAME(NAME* obj) { return new NAME(*obj); }
+
+#include "object-meta-begin.h"
+#include "modifier-defs.h"
+#include "object-meta-end.h"
+
+};
+
//
template<typename V>
@@ -2244,11 +2257,40 @@ struct LoweringVisitor
IntVal* elementCount;
};
+ struct VaryingParameterVarChain
+ {
+ VaryingParameterVarChain* next = nullptr;
+ VarDeclBase* varDecl;
+ };
+
+ template<typename T>
+ T* findModifier(VaryingParameterVarChain* chain)
+ {
+ for (auto c = chain; c; c = c->next)
+ {
+ auto v = c->varDecl;
+ if (auto mod = v->FindModifier<T>())
+ return mod;
+ }
+ return nullptr;
+ }
+
+ RefPtr<Modifier> cloneModifier(Modifier* modifier)
+ {
+ if (!modifier) return nullptr;
+
+ // For now we just do a shallow copy of the modifier
+
+ CloneVisitor visitor;
+ return visitor.dispatch(modifier);
+ }
+
struct VaryingParameterInfo
{
String name;
VaryingParameterDirection direction;
VaryingParameterArraySpec* arraySpecs = nullptr;
+ VaryingParameterVarChain* varChain = nullptr;
};
RefPtr<ExpressionSyntaxNode> createGLSLBuiltinRef(
@@ -2259,6 +2301,33 @@ struct LoweringVisitor
return globalVarRef;
}
+ bool isIntegralType(
+ ExpressionType* type)
+ {
+ if (auto baseType = type->As<BasicExpressionType>())
+ {
+ switch (baseType->BaseType)
+ {
+ default:
+ return false;
+
+ case BaseType::Int:
+ case BaseType::UInt:
+ case BaseType::UInt64:
+ return true;
+ }
+ }
+ else if (auto vecType = type->As<VectorExpressionType>())
+ {
+ return isIntegralType(vecType->elementType);
+ }
+ else if (auto matType = type->As<MatrixExpressionType>())
+ {
+ return isIntegralType(matType->getElementType());
+ }
+
+ return false;
+ }
void lowerSimpleShaderParameterToGLSLGlobal(
VaryingParameterInfo const& info,
@@ -2449,6 +2518,26 @@ struct LoweringVisitor
break;
}
+ // We want to copy certain modifiers from the declaration as given,
+ // over to the newly created global variable. The most important
+ // of these is any interpolation-mode modifier.
+ //
+ // Note that a shader parameter could have been nested inside
+ // a `struct` type, so we will look for interpolation modifiers
+ // starting on the "deepest" field, and working out way out.
+
+ // Look for interpolation mode modifier
+ if (auto interpolationModeModifier = findModifier<InterpolationModeModifier>(info.varChain))
+ {
+ addModifier(globalVarDecl, cloneModifier(interpolationModeModifier));
+ }
+ // Otherwise, check if we need to add one:
+ else if (isIntegralType(varType))
+ {
+ auto mod = new HLSLNoInterpolationModifier();
+ addModifier(globalVarDecl, mod);
+ }
+
RefPtr<VarExpressionSyntaxNode> globalVarRef = new VarExpressionSyntaxNode();
globalVarRef->Position = globalVarDecl->Position;
@@ -2554,8 +2643,13 @@ struct LoweringVisitor
fieldExpr->declRef = fieldDeclRef;
fieldExpr->BaseExpression = varExpr;
+ VaryingParameterVarChain fieldVarChain;
+ fieldVarChain.next = info.varChain;
+ fieldVarChain.varDecl = fieldDeclRef.getDecl();
+
VaryingParameterInfo fieldInfo = info;
fieldInfo.name = info.name + "_" + fieldDeclRef.GetName();
+ fieldInfo.varChain = &fieldVarChain;
// Need to find the layout for the given field...
Decl* originalFieldDecl = nullptr;
@@ -2598,9 +2692,14 @@ struct LoweringVisitor
expr->declRef = declRef;
expr->Type.type = GetType(declRef);
+ VaryingParameterVarChain varChain;
+ varChain.next = nullptr;
+ varChain.varDecl = localVarDecl;
+
VaryingParameterInfo info;
info.name = name;
info.direction = direction;
+ info.varChain = &varChain;
// Ensure that we don't get name collisions on `inout` variables
switch (direction)
diff --git a/tests/cross-compile/integer-input.slang b/tests/cross-compile/integer-input.slang
new file mode 100644
index 000000000..2069091c6
--- /dev/null
+++ b/tests/cross-compile/integer-input.slang
@@ -0,0 +1,11 @@
+//TEST:CROSS_COMPILE: -profile ps_5_0 -entry main -target spirv-assembly
+
+struct VS_OUT
+{
+ uint drawID : DRAW_ID;
+};
+
+float4 main(VS_OUT vsOut) : SV_Target
+{
+ return float4(float(vsOut.drawID));
+}
diff --git a/tests/cross-compile/integer-input.slang.glsl b/tests/cross-compile/integer-input.slang.glsl
new file mode 100644
index 000000000..ce6998a9a
--- /dev/null
+++ b/tests/cross-compile/integer-input.slang.glsl
@@ -0,0 +1,26 @@
+//TEST_IGNORE_FILE:
+
+struct VS_OUT
+{
+ uint drawID;
+};
+
+in flat uint SLANG_in_vsOut_drawID;
+
+out vec4 SLANG_out_main_result;
+
+vec4 main_(VS_OUT vsOut)
+{
+ return vec4(float(vsOut.drawID));
+}
+
+void main()
+{
+ VS_OUT vsOut;
+ vsOut.drawID = SLANG_in_vsOut_drawID;
+
+ vec4 main_result;
+ main_result = main_(vsOut);
+
+ SLANG_out_main_result = main_result;
+}
diff --git a/tests/cross-compile/nointerpolation-input.slang b/tests/cross-compile/nointerpolation-input.slang
new file mode 100644
index 000000000..c215f380a
--- /dev/null
+++ b/tests/cross-compile/nointerpolation-input.slang
@@ -0,0 +1,11 @@
+//TEST:CROSS_COMPILE: -profile ps_5_0 -entry main -target spirv-assembly
+
+struct VS_OUT
+{
+ nointerpolation float drawID : DRAW_ID;
+};
+
+float4 main(VS_OUT vsOut) : SV_Target
+{
+ return float4(vsOut.drawID);
+}
diff --git a/tests/cross-compile/nointerpolation-input.slang.glsl b/tests/cross-compile/nointerpolation-input.slang.glsl
new file mode 100644
index 000000000..279590fa5
--- /dev/null
+++ b/tests/cross-compile/nointerpolation-input.slang.glsl
@@ -0,0 +1,26 @@
+//TEST_IGNORE_FILE:
+
+struct VS_OUT
+{
+ float drawID;
+};
+
+in flat float SLANG_in_vsOut_drawID;
+
+out vec4 SLANG_out_main_result;
+
+vec4 main_(VS_OUT vsOut)
+{
+ return vec4(vsOut.drawID);
+}
+
+void main()
+{
+ VS_OUT vsOut;
+ vsOut.drawID = SLANG_in_vsOut_drawID;
+
+ vec4 main_result;
+ main_result = main_(vsOut);
+
+ SLANG_out_main_result = main_result;
+}
diff --git a/tools/slang-test/main.cpp b/tools/slang-test/main.cpp
index 2bca2f78d..6b7da5844 100644
--- a/tools/slang-test/main.cpp
+++ b/tools/slang-test/main.cpp
@@ -671,6 +671,83 @@ TestResult runSimpleTest(TestInput& input)
return result;
}
+TestResult runCrossCompilerTest(TestInput& input)
+{
+ // need to execute the stand-alone Slang compiler on the file
+ // then on the same file + `.glsl` and compare output
+
+ auto filePath = input.filePath;
+ auto outputStem = input.outputStem;
+
+ OSProcessSpawner actualSpawner;
+ OSProcessSpawner expectedSpawner;
+
+ actualSpawner.pushExecutablePath(String(options.binDir) + "slangc.exe");
+ expectedSpawner.pushExecutablePath(String(options.binDir) + "slangc.exe");
+
+ actualSpawner.pushArgument(filePath);
+ expectedSpawner.pushArgument(filePath + ".glsl");
+
+ for( auto arg : input.testOptions->args )
+ {
+ actualSpawner.pushArgument(arg);
+ expectedSpawner.pushArgument(arg);
+ }
+ expectedSpawner.pushArgument("-no-checking");
+
+ if (spawnAndWait(outputStem, expectedSpawner) != kOSError_None)
+ {
+ return kTestResult_Fail;
+ }
+
+ String expectedOutput = getOutput(expectedSpawner);
+ String expectedOutputPath = outputStem + ".expected";
+ try
+ {
+ Slang::File::WriteAllText(expectedOutputPath, expectedOutput);
+ }
+ catch (Slang::IOException)
+ {
+ return kTestResult_Fail;
+ }
+
+ if (spawnAndWait(outputStem, actualSpawner) != kOSError_None)
+ {
+ return kTestResult_Fail;
+ }
+ String actualOutput = getOutput(actualSpawner);
+
+ TestResult result = kTestResult_Pass;
+
+ // Otherwise we compare to the expected output
+ if (actualOutput != expectedOutput)
+ {
+ result = kTestResult_Fail;
+ }
+
+ // If the test failed, then we write the actual output to a file
+ // so that we can easily diff it from the command line and
+ // diagnose the problem.
+ if (result == kTestResult_Fail)
+ {
+ String actualOutputPath = outputStem + ".actual";
+ Slang::File::WriteAllText(actualOutputPath, actualOutput);
+
+ if (options.outputMode == kOutputMode_AppVeyor)
+ {
+ fprintf(stderr, "ERROR:\n"
+ "EXPECTED{{{\n%s}}}\n"
+ "ACTUAL{{{\n%s}}}\n",
+ expectedOutput.Buffer(),
+ actualOutput.Buffer());
+ fflush(stderr);
+ }
+ }
+
+ return result;
+}
+
+
#ifdef SLANG_TEST_SUPPORT_HLSL
TestResult generateHLSLBaseline(TestInput& input)
{
@@ -1076,6 +1153,7 @@ TestResult runTest(
{ "COMPARE_HLSL_CROSS_COMPILE_RENDER", &runHLSLCrossCompileRenderComparisonTest},
{ "COMPARE_HLSL_GLSL_RENDER", &runHLSLAndGLSLComparisonTest },
{ "COMPARE_GLSL", &runGLSLComparisonTest },
+ { "CROSS_COMPILE", &runCrossCompilerTest },
{ nullptr, nullptr },
};