diff options
| author | Tim Foley <tfoley@nvidia.com> | 2017-07-19 10:10:17 -0700 |
|---|---|---|
| committer | Tim Foley <tfoley@nvidia.com> | 2017-07-19 10:12:58 -0700 |
| commit | 55a29042a2826f26272c9e1b65cd3745bad3ee31 (patch) | |
| tree | f8016cf92678a6dfaa1903a161ebcad78f0f42d0 | |
| parent | a727017340165d02977387e1e1a2a7e328308295 (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-- | .gitignore | 14 | ||||
| -rw-r--r-- | source/slang/emit.cpp | 112 | ||||
| -rw-r--r-- | source/slang/lower.cpp | 22 | ||||
| -rw-r--r-- | source/slang/modifier-defs.h | 6 | ||||
| -rw-r--r-- | source/slang/parser.cpp | 13 | ||||
| -rw-r--r-- | source/slang/slang-stdlib.cpp | 4 | ||||
| -rw-r--r-- | tests/bugs/gh-122.slang | 15 | ||||
| -rw-r--r-- | tests/bugs/gh-122.slang.glsl | 32 |
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; +} |
