summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-07-19 10:10:17 -0700
committerTim Foley <tfoley@nvidia.com>2017-07-19 10:12:58 -0700
commit55a29042a2826f26272c9e1b65cd3745bad3ee31 (patch)
treef8016cf92678a6dfaa1903a161ebcad78f0f42d0
parenta727017340165d02977387e1e1a2a7e328308295 (diff)
Fix up translation of `GetDimensions()`
Fixes #122 - In cases with an explicit mip level being specified, there was a mistake in how the argument for setting the mip level in the GLSL code was constructed that led to a parse error in GLSL - Also, that argument is a `uint` in HLSL and an `int` in GLSL, so an explicit cast was needed - The GLSL functions here seem to require a newer GLSL (at least higher than `420`), so I had to add in a capability for builtins to specify a required GLSL version. For now I made these ones require `450`. - Added a test case to confirm that our lowering works (for some definition of "works")
-rw-r--r--.gitignore14
-rw-r--r--source/slang/emit.cpp112
-rw-r--r--source/slang/lower.cpp22
-rw-r--r--source/slang/modifier-defs.h6
-rw-r--r--source/slang/parser.cpp13
-rw-r--r--source/slang/slang-stdlib.cpp4
-rw-r--r--tests/bugs/gh-122.slang15
-rw-r--r--tests/bugs/gh-122.slang.glsl32
8 files changed, 158 insertions, 60 deletions
diff --git a/.gitignore b/.gitignore
index 9267cfca3..26a5f0506 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,15 +8,17 @@
bin/
intermediate/
-# files generated by test runner
+# Files generated by test runner.
+#
+# Note: in some cases a `.expected` file needs to be checked in, but
+# trying to exhaustively enumerate those cases is hard with the
+# way the tests are currently sorted.
+
*.actual
*.expected
-!*.slang.expected
-!*.slang.*.expected
*.expected.png
*.actual.png
-tests/render/*.expected
-tests/cross-compile/*.expected
-# files generated by other shader compilers
+# Files generated by other shader compilers
+
*.spv
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 8660b5f93..2f009bb81 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -74,6 +74,31 @@ struct EmitContext
//
+void requireGLSLVersion(
+ EntryPointRequest* entryPoint,
+ ProfileVersion version)
+{
+ auto profile = entryPoint->profile;
+ auto currentVersion = profile.GetVersion();
+ if (profile.getFamily() == ProfileFamily::GLSL)
+ {
+ // Check if this profile is newer
+ if ((UInt)version > (UInt)profile.GetVersion())
+ {
+ profile.setVersion(version);
+ entryPoint->profile = profile;
+ }
+ }
+ else
+ {
+ // Non-GLSL target? Set it to a GLSL one.
+ profile.setVersion(version);
+ entryPoint->profile = profile;
+ }
+}
+
+//
+
static String getStringOrIdentifierTokenValue(
Token const& token)
{
@@ -1647,6 +1672,39 @@ struct EmitVisitor
context->shared->glslExtensionsRequired.Add(name);
}
+ void requireGLSLVersion(ProfileVersion version)
+ {
+ if (context->shared->target != CodeGenTarget::GLSL)
+ return;
+
+ auto entryPoint = context->shared->entryPoint;
+ Slang::requireGLSLVersion(entryPoint, version);
+ }
+
+ void requireGLSLVersion(int version)
+ {
+ switch (version)
+ {
+ #define CASE(NUMBER) \
+ case NUMBER: requireGLSLVersion(ProfileVersion::GLSL_##NUMBER); break
+
+ CASE(110);
+ CASE(120);
+ CASE(130);
+ CASE(140);
+ CASE(150);
+ CASE(330);
+ CASE(400);
+ CASE(410);
+ CASE(420);
+ CASE(430);
+ CASE(440);
+ CASE(450);
+
+ #undef CASE
+ }
+ }
+
void visitInvokeExpressionSyntaxNode(
RefPtr<InvokeExpressionSyntaxNode> callExpr,
ExprEmitArg const& arg)
@@ -1768,6 +1826,13 @@ struct EmitVisitor
// If so, we had better request the extension.
requireGLSLExtension(requiredGLSLExtensionModifier->extensionNameToken.Content);
}
+
+ // Does this intrinsic requie a particular GLSL extension that wouldn't be available by default?
+ if (auto requiredGLSLVersionModifier = funcDecl->FindModifier<RequiredGLSLVersionModifier>())
+ {
+ // If so, we had better request the extension.
+ requireGLSLVersion((int) getIntegerLiteralValue(requiredGLSLVersionModifier->versionNumberToken));
+ }
}
@@ -3705,47 +3770,22 @@ String emitEntryPoint(
auto lowered = lowerEntryPoint(entryPoint, programLayout, target);
sharedContext.program = lowered.program;
+ // Note that we emit the main body code of the program *before*
+ // we emit any leading preprocessor directives for GLSL.
+ // This is to give the emit logic a change to make last-minute
+ // adjustments like changing the required GLSL version.
+ //
+ // TODO: All such adjustments would be better handled during
+ // lowering, but that requires having a semantic rather than
+ // textual format for the HLSL->GLSL mapping.
+ visitor.EmitDeclsInContainer(lowered.program.Ptr());
+ String code = sharedContext.sb.ProduceString();
+ sharedContext.sb.Clear();
// There may be global-scope modifiers that we should emit now
visitor.emitGLSLPreprocessorDirectives(translationUnitSyntax);
-
String prefix = sharedContext.sb.ProduceString();
- sharedContext.sb.Clear();
- switch(target)
- {
- case CodeGenTarget::GLSL:
- {
- // TODO(tfoley): Need a plan for how to enable/disable these as needed...
-// Emit(context, "#extension GL_GOOGLE_cpp_style_line_directive : require\n");
- }
- break;
-
- default:
- break;
- }
-
-
- visitor.EmitDeclsInContainer(lowered.program.Ptr());
-
-#if 0
- if( isRewrite )
- {
- // In rewrite mode, we will just emit the text of the translation unit as given,
- // and not pay attention to the specific entry point that was requested.
- //
- // It is a user error to request GLSL output and have an entry point name
- // other than `main`.
- EmitDeclsInContainerUsingLayout(&context, translationUnitSyntax, globalStructLayout);
- }
- else
- {
- // We are being asked to emit a single entry point in "full" mode.
- emitEntryPoint(&context, entryPoint);
- }
-#endif
-
- String code = sharedContext.sb.ProduceString();
StringBuilder finalResultBuilder;
finalResultBuilder << prefix;
diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp
index 127ef75ca..c61003bc6 100644
--- a/source/slang/lower.cpp
+++ b/source/slang/lower.cpp
@@ -291,6 +291,10 @@ static void attachLayout(
addModifier(syntax, modifier);
}
+void requireGLSLVersion(
+ EntryPointRequest* entryPoint,
+ ProfileVersion version);
+
struct LoweringVisitor
: ExprVisitor<LoweringVisitor, RefPtr<ExpressionSyntaxNode>>
, StmtVisitor<LoweringVisitor, void>
@@ -2958,23 +2962,7 @@ struct LoweringVisitor
return;
auto entryPoint = shared->entryPointRequest;
- auto profile = entryPoint->profile;
- auto currentVersion = profile.GetVersion();
- if (profile.getFamily() == ProfileFamily::GLSL)
- {
- // Check if this profile is newer
- if ((UInt)version > (UInt)profile.GetVersion())
- {
- profile.setVersion(version);
- entryPoint->profile = profile;
- }
- }
- else
- {
- // Non-GLSL target? Set it to a GLSL one.
- profile.setVersion(version);
- entryPoint->profile = profile;
- }
+ Slang::requireGLSLVersion(entryPoint, version);
}
RefPtr<ExpressionSyntaxNode> lowerSimpleShaderParameterToGLSLGlobal(
diff --git a/source/slang/modifier-defs.h b/source/slang/modifier-defs.h
index fadc68695..89f2096e4 100644
--- a/source/slang/modifier-defs.h
+++ b/source/slang/modifier-defs.h
@@ -59,6 +59,12 @@ SYNTAX_CLASS(RequiredGLSLExtensionModifier, Modifier)
FIELD(Token, extensionNameToken)
END_SYNTAX_CLASS()
+// A modifier to tag something as an intrinsic that requires
+// a certain GLSL version to be enabled when used
+SYNTAX_CLASS(RequiredGLSLVersionModifier, Modifier)
+ FIELD(Token, versionNumberToken)
+END_SYNTAX_CLASS()
+
SIMPLE_SYNTAX_CLASS(InOutModifier, OutModifier)
// This is a special sentinel modifier that gets added
diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp
index 50205ff29..a624c58c5 100644
--- a/source/slang/parser.cpp
+++ b/source/slang/parser.cpp
@@ -729,6 +729,19 @@ namespace Slang
AddModifier(&modifierLink, modifier);
}
+ else if (AdvanceIf(parser, "__glsl_version"))
+ {
+ auto modifier = new RequiredGLSLVersionModifier();
+ modifier->Position = loc;
+
+ parser->ReadToken(TokenType::LParent);
+ modifier->versionNumberToken = parser->ReadToken(TokenType::IntegerLiteral);
+ parser->ReadToken(TokenType::RParent);
+
+ AddModifier(&modifierLink, modifier);
+ }
+
+
else if (AdvanceIf(parser, "layout"))
{
parser->ReadToken(TokenType::LParent);
diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp
index a62db693c..7850b0ce0 100644
--- a/source/slang/slang-stdlib.cpp
+++ b/source/slang/slang-stdlib.cpp
@@ -1417,6 +1417,7 @@ namespace Slang
for(int includeMipInfo = 0; includeMipInfo < 2; ++includeMipInfo)
{
{
+ sb << "__glsl_version(450)\n";
sb << "__intrinsic(glsl, \"(";
int aa = 0;
@@ -1424,8 +1425,9 @@ namespace Slang
if (includeMipInfo)
{
int mipLevelArg = aa++;
- lodStr.append("$");
+ lodStr = "int($";
lodStr.append(mipLevelArg);
+ lodStr.append(")");
}
int cc = 0;
diff --git a/tests/bugs/gh-122.slang b/tests/bugs/gh-122.slang
new file mode 100644
index 000000000..1a011df37
--- /dev/null
+++ b/tests/bugs/gh-122.slang
@@ -0,0 +1,15 @@
+//TEST:CROSS_COMPILE: -profile ps_5_0 -entry main -target spirv-assembly
+
+// Ensure that `GetDimensions` with `mipCount` output works
+// on a `Texture2D`
+
+layout(binding = 1)
+Texture2D t;
+
+float4 main() : SV_Target
+{
+ uint x, y, mipCount;
+ t.GetDimensions(0, x, y, mipCount);
+
+ return float4(x, y, mipCount, 0);
+}
diff --git a/tests/bugs/gh-122.slang.glsl b/tests/bugs/gh-122.slang.glsl
new file mode 100644
index 000000000..a6f43256e
--- /dev/null
+++ b/tests/bugs/gh-122.slang.glsl
@@ -0,0 +1,32 @@
+#version 450
+//TEST_IGNORE_FILE:
+
+layout(binding = 0)
+uniform sampler SLANG_hack_samplerForTexelFetch;
+
+layout(binding = 1)
+uniform texture2D t;
+
+vec4 main_()
+{
+ uint x, y, mipCount;
+
+ x = textureSize(sampler2D(t,SLANG_hack_samplerForTexelFetch), 0).x;
+ y = textureSize(sampler2D(t,SLANG_hack_samplerForTexelFetch), 0).y;
+ mipCount = textureQueryLevels(sampler2D(t,SLANG_hack_samplerForTexelFetch));
+
+ return vec4(
+ float(x),
+ float(y),
+ float(mipCount),
+ 0.0);
+}
+
+layout(location = 0)
+out vec4 SLANG_out_main_result;
+
+void main()
+{
+ vec4 main_result = main_();
+ SLANG_out_main_result = main_result;
+}