From f48035ff26381d8bc22a7e484eda53fc087ae7b7 Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Thu, 13 Jul 2017 08:31:18 -0700 Subject: Don't emit C-style `#line` directives when directly generating GLSL - This fixes the render tests, which aren't tested by the continuous integration setup - This was broken in the commit that decided to use C-style directives all the time. - This works for stuff that eventually passes through glslang (or at least our build of it) - It *doensn't* work if we take the GLSL and pass it off to an OpenGL driver (which is what I do for testing) - A longer-term fix is still required to deal with line directives properly --- source/slang/emit.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'source') diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 6905a8a76..68c84a277 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -21,6 +21,11 @@ struct SharedEmitContext // The target language we want to generate code for CodeGenTarget target; + // The final code generation target + // + // For example, `target` might be `GLSL`, while `finalTarget` might be `SPIRV` + CodeGenTarget finalTarget; + // The string of code we've built so far StringBuilder sb; @@ -456,13 +461,17 @@ struct EmitVisitor bool shouldUseGLSLStyleLineDirective = false; - // Let's not do this -#if 0 - if (context->shared->target == CodeGenTarget::GLSL) + // TODO: Eventually we should give he user a proper API + // and command-line mechanism to control what kind of line + // directives we output (and to turn the feature off + // completely), but for now we always emit C-style line + // directives *unless* the final target language is raw + // GLSL code (all other targets will eventually pass + // through glslang, which supports C-style line directives). + if (context->shared->finalTarget == CodeGenTarget::GLSL) { shouldUseGLSLStyleLineDirective = true; } -#endif if(shouldUseGLSLStyleLineDirective) { @@ -3479,6 +3488,7 @@ String emitEntryPoint( SharedEmitContext sharedContext; sharedContext.target = target; + sharedContext.finalTarget = entryPoint->compileRequest->Target; sharedContext.programLayout = programLayout; -- cgit v1.2.3 From 72a3e97fe6bfdffee253ad008cab7cdd3b9e796f Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Thu, 13 Jul 2017 08:36:47 -0700 Subject: Allow `spGetEntryPointCode` to return text results too Fixes #77 - The `spGetEntryPointSource` function is now no longer needed, but I'm not going to "deprecate" it just yet --- source/slang/slang.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'source') diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 0561f30a9..bfc499c1b 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -880,8 +880,29 @@ SLANG_API void const* spGetEntryPointCode( { auto req = REQ(request); Slang::CompileResult& result = req->entryPoints[entryPointIndex]->result; - if(outSize) *outSize = result.outputBinary.Count(); - return result.outputBinary.Buffer(); + + void const* data = nullptr; + size_t size = 0; + + switch (result.format) + { + case Slang::ResultFormat::None: + default: + break; + + case Slang::ResultFormat::Binary: + data = result.outputBinary.Buffer(); + size = result.outputBinary.Count(); + break; + + case Slang::ResultFormat::Text: + data = result.outputString.Buffer(); + size = result.outputString.Length(); + break; + } + + if(outSize) *outSize = size; + return data; } // Reflection API -- cgit v1.2.3 From 6da80f58ba8f51fc768f177f28a7d818b03c434e Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Thu, 13 Jul 2017 09:12:50 -0700 Subject: Allow GLSL `#version` to be selected based on profile Fixes #83 - The basic idea is that I added a bunch of more specific profile names line `glsl_vertex_430` which indicate the desired GLSL version the user wants. - An explicit `#version` line in the code always overrides one specified by profile, though --- slang.h | 1 + source/slang/compiler.cpp | 2 +- source/slang/emit.cpp | 84 ++++++++++++++++++++++++++++--------- source/slang/profile-defs.h | 100 +++++++++++++++++++++++++++++++++++++++----- source/slang/profile.h | 1 + 5 files changed, 157 insertions(+), 31 deletions(-) (limited to 'source') diff --git a/slang.h b/slang.h index 14efc26c7..26a8a406f 100644 --- a/slang.h +++ b/slang.h @@ -947,6 +947,7 @@ namespace slang #include "source/slang/parameter-binding.cpp" #include "source/slang/parser.cpp" #include "source/slang/preprocessor.cpp" +#include "source/slang/profile.cpp" #include "source/slang/lookup.cpp" #include "source/slang/lower.cpp" #include "source/slang/check.cpp" diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp index 284bb200a..4c3885ebf 100644 --- a/source/slang/compiler.cpp +++ b/source/slang/compiler.cpp @@ -72,7 +72,7 @@ namespace Slang Profile Profile::LookUp(char const* name) { #define PROFILE(TAG, NAME, STAGE, VERSION) if(strcmp(name, #NAME) == 0) return Profile::TAG; - #define PROFILE_ALIAS(TAG, NAME) if(strcmp(name, #NAME) == 0) return Profile::TAG; + #define PROFILE_ALIAS(TAG, DEF, NAME) if(strcmp(name, #NAME) == 0) return Profile::TAG; #include "profile-defs.h" return Profile::Unknown; diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 68c84a277..21c91a5c0 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -18,6 +18,9 @@ namespace Slang { // Shared state for an entire emit session struct SharedEmitContext { + // The entry point we are being asked to compile + EntryPointRequest* entryPoint; + // The target language we want to generate code for CodeGenTarget target; @@ -3396,19 +3399,10 @@ struct EmitVisitor } } - void emitGLSLPreprocessorDirectives( - RefPtr program) + void emitGLSLVersionDirective( + ProgramSyntaxNode* program) { - switch(context->shared->target) - { - // Don't emit this stuff unless we are targetting GLSL - default: - return; - - case CodeGenTarget::GLSL: - break; - } - + // Did the user provide an explicit `#version` directive in their code? if( auto versionDirective = program->FindModifier() ) { // TODO(tfoley): Emit an appropriate `#line` directive... @@ -3421,19 +3415,68 @@ struct EmitVisitor emit(versionDirective->glslProfileToken.Content); } Emit("\n"); + return; } - else + + // No explicit version was given. This could be because we are cross-compiling, + // but it also might just be that they user wrote GLSL without thinking about + // versions. + + // First, look and see if the target profile gives us a version to use: + auto profile = context->shared->entryPoint->profile; + if (profile.getFamily() == ProfileFamily::GLSL) { - // No explicit version was given (probably because we are cross-compiling). - // - // We need to pick an appropriate version, ideally based on the features - // that the shader ends up using. - // - // For now we just fall back to a reasonably recent version. + switch (profile.GetVersion()) + { +#define CASE(TAG, VALUE) \ + case ProfileVersion::TAG: Emit("#version " #VALUE "\n"); return + + CASE(GLSL_110, 110); + CASE(GLSL_120, 120); + CASE(GLSL_130, 130); + CASE(GLSL_140, 140); + CASE(GLSL_150, 150); + CASE(GLSL_330, 330); + CASE(GLSL_400, 400); + CASE(GLSL_410, 410); + CASE(GLSL_420, 420); + CASE(GLSL_430, 430); + CASE(GLSL_440, 440); + CASE(GLSL_450, 450); +#undef CASE + + default: + break; + } + } + + // No information is available for us to guess a profile, + // so it seems like we need to pick one out of thin air. + // + // Ideally we should infer a minimum required version based + // on the constructs we have seen used in the user's code + // + // For now we just fall back to a reasonably recent version. + + Emit("#version 420\n"); + } + + void emitGLSLPreprocessorDirectives( + RefPtr program) + { + switch(context->shared->target) + { + // Don't emit this stuff unless we are targetting GLSL + default: + return; - Emit("#version 420\n"); + case CodeGenTarget::GLSL: + break; } + emitGLSLVersionDirective(program); + + // TODO: when cross-compiling we may need to output additional `#extension` directives // based on the features that we have used. @@ -3489,6 +3532,7 @@ String emitEntryPoint( SharedEmitContext sharedContext; sharedContext.target = target; sharedContext.finalTarget = entryPoint->compileRequest->Target; + sharedContext.entryPoint = entryPoint; sharedContext.programLayout = programLayout; diff --git a/source/slang/profile-defs.h b/source/slang/profile-defs.h index 76ba476bb..84153ee46 100644 --- a/source/slang/profile-defs.h +++ b/source/slang/profile-defs.h @@ -32,7 +32,7 @@ #endif #ifndef PROFILE_ALIAS -#define PROFILE_ALIAS(TAG, NAME) /* empty */ +#define PROFILE_ALIAS(TAG, DEF, NAME) /* empty */ #endif // Source and destination languages @@ -78,7 +78,18 @@ PROFILE_VERSION(DX_4_0_Level_9_3, DX) PROFILE_VERSION(DX_4_1, DX) PROFILE_VERSION(DX_5_0, DX) -PROFILE_VERSION(GLSL, GLSL) +PROFILE_VERSION(GLSL_110, GLSL) +PROFILE_VERSION(GLSL_120, GLSL) +PROFILE_VERSION(GLSL_130, GLSL) +PROFILE_VERSION(GLSL_140, GLSL) +PROFILE_VERSION(GLSL_150, GLSL) +PROFILE_VERSION(GLSL_330, GLSL) +PROFILE_VERSION(GLSL_400, GLSL) +PROFILE_VERSION(GLSL_410, GLSL) +PROFILE_VERSION(GLSL_420, GLSL) +PROFILE_VERSION(GLSL_430, GLSL) +PROFILE_VERSION(GLSL_440, GLSL) +PROFILE_VERSION(GLSL_450, GLSL) // Specific profiles @@ -104,14 +115,83 @@ PROFILE(DX_Vertex_4_0_Level_9_3, vs_4_0_level_9_3, Vertex, DX_4_0_Level_9_3) PROFILE(DX_Vertex_4_1, vs_4_1, Vertex, DX_4_1) PROFILE(DX_Vertex_5_0, vs_5_0, Vertex, DX_5_0) -// - -PROFILE(GLSL_Compute, glsl_compute, Compute, GLSL) -PROFILE(GLSL_Vertex, glsl_vertex, Vertex, GLSL) -PROFILE(GLSL_Fragment, glsl_fragment, Fragment, GLSL) -PROFILE(GLSL_Geometry, glsl_geometry, Geometry, GLSL) -PROFILE(GLSL_TessControl, glsl_tess_control, Hull, GLSL) -PROFILE(GLSL_TessEval, glsl_tess_eval, Domain, GLSL) +// Define all the GLSL profiles + +#define P(UPPER, LOWER, VERSION) \ +PROFILE(GLSL_##UPPER##_##VERSION, glsl_##LOWER##_##VERSION, UPPER, GLSL_##VERSION) + +P(Vertex, vertex, 110) +P(Vertex, vertex, 120) +P(Vertex, vertex, 130) +P(Vertex, vertex, 140) +P(Vertex, vertex, 150) +P(Vertex, vertex, 330) +P(Vertex, vertex, 400) +P(Vertex, vertex, 410) +P(Vertex, vertex, 420) +P(Vertex, vertex, 430) +P(Vertex, vertex, 440) +P(Vertex, vertex, 450) + +P(Fragment, fragment, 110) +P(Fragment, fragment, 120) +P(Fragment, fragment, 130) +P(Fragment, fragment, 140) +P(Fragment, fragment, 150) +P(Fragment, fragment, 330) +P(Fragment, fragment, 400) +P(Fragment, fragment, 410) +P(Fragment, fragment, 420) +P(Fragment, fragment, 430) +P(Fragment, fragment, 440) +P(Fragment, fragment, 450) + +P(Geometry, geometry, 150) +P(Geometry, geometry, 330) +P(Geometry, geometry, 400) +P(Geometry, geometry, 410) +P(Geometry, geometry, 420) +P(Geometry, geometry, 430) +P(Geometry, geometry, 440) +P(Geometry, geometry, 450) + +P(Compute, compute, 430) +P(Compute, compute, 440) +P(Compute, compute, 450) + +#undef P +#define P(UPPER, LOWER, STAGE, VERSION) \ +PROFILE(GLSL_##UPPER##_##VERSION, glsl_##LOWER##_##VERSION, STAGE, GLSL_##VERSION) + +P(TessControl, tess_control, Hull, 400) +P(TessControl, tess_control, Hull, 410) +P(TessControl, tess_control, Hull, 420) +P(TessControl, tess_control, Hull, 430) +P(TessControl, tess_control, Hull, 440) +P(TessControl, tess_control, Hull, 450) + +P(TessEval, tess_eval, Domain, 400) +P(TessEval, tess_eval, Domain, 410) +P(TessEval, tess_eval, Domain, 420) +P(TessEval, tess_eval, Domain, 430) +P(TessEval, tess_eval, Domain, 440) +P(TessEval, tess_eval, Domain, 450) + +#undef P + +// Define a default profile for each GLSL stage that just +// uses the latest language version we know of + +PROFILE_ALIAS(GLSL_Vertex, GLSL_Vertex_450, glsl_vertex) +PROFILE_ALIAS(GLSL_Fragment, GLSL_Fragment_450, glsl_fragment) +PROFILE_ALIAS(GLSL_Geometry, GLSL_Geometry_450, glsl_geometry) +PROFILE_ALIAS(GLSL_TessControl, GLSL_TessControl_450, glsl_tess_control) +PROFILE_ALIAS(GLSL_TessEval, GLSL_TessEval_450, glsl_tess_eval) +PROFILE_ALIAS(GLSL_Compute, GLSL_Compute_450, glsl_compute) + +// TODO: define a profile for each GLSL *version* that we can +// use as a catch-all when the stage can be inferred from +// something else #undef LANGUAGE #undef LANGUAGE_ALIAS diff --git a/source/slang/profile.h b/source/slang/profile.h index f8839be84..6d55d3195 100644 --- a/source/slang/profile.h +++ b/source/slang/profile.h @@ -54,6 +54,7 @@ namespace Slang Unknown, #define PROFILE(TAG, NAME, STAGE, VERSION) TAG = (uint32_t(Stage::STAGE) << 16) | uint32_t(ProfileVersion::VERSION), +#define PROFILE_ALIAS(TAG, DEF, NAME) TAG = DEF, #include "profile-defs.h" }; -- cgit v1.2.3 From c51fd4ee8f478aa3d3b7e6208a3a4e9c00e2413a Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Thu, 13 Jul 2017 09:33:07 -0700 Subject: Add several missing GLSL qualifiers Fixes #81 - This is based on a san over the GLSL spec (but is probably not exhaustive) - There are some qualifiers that are currently being handled by general-case code for all languages, and some of these happen to cover GLSL qualifiers too - Some of the qualifiers being handled by the general-case mechanism are *accidentally* working for GLSL (e.g., the HLSL `shared` qualifier doesn't mean the same thing as GLSL `shared`, but as long as we spit it back out nobody seems to care). - This should be fixed sooner or later. --- source/slang/slang-stdlib.cpp | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) (limited to 'source') diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp index 563f5a015..3450e72d7 100644 --- a/source/slang/slang-stdlib.cpp +++ b/source/slang/slang-stdlib.cpp @@ -2073,13 +2073,46 @@ namespace Slang sb << "__magic_type(GLSLInputAttachmentType) struct subpassInput {};"; // Define additional keywords + sb << "__modifier(GLSLBufferModifier) buffer;\n"; - sb << "__modifier(GLSLWriteOnlyModifier) writeonly;\n"; - sb << "__modifier(GLSLReadOnlyModifier) readonly;\n"; + + // [GLSL 4.3] Storage Qualifiers + + // TODO: need to support `shared` here with its GLSL meaning + sb << "__modifier(GLSLPatchModifier) patch;\n"; + // `centroid` and `sample` handled centrally + + // [GLSL 4.5] Interpolation Qualifiers + sb << "__modifier(SimpleModifier) smooth;\n"; + sb << "__modifier(SimpleModifier) flat;\n"; + sb << "__modifier(SimpleModifier) noperspective;\n"; + + + // [GLSL 4.3.2] Constant Qualifier + + // We need to handle GLSL `const` separately from HLSL `const`, + // since they mean such different things. + + // [GLSL 4.7.2] Precision Qualifiers + sb << "__modifier(SimpleModifier) highp;\n"; + sb << "__modifier(SimpleModifier) mediump;\n"; + sb << "__modifier(SimpleModifier) lowp;\n"; + + // [GLSL 4.8.1] The Invariant Qualifier + + sb << "__modifier(GLSLWriteOnlyModifier) invariant;\n"; + + // [GLSL 4.10] Memory Qualifiers + + sb << "__modifier(SimpleModifier) coherent;\n"; + sb << "__modifier(SimpleModifier) volatile;\n"; + sb << "__modifier(SimpleModifier) restrict;\n"; + sb << "__modifier(GLSLReadOnlyModifier) readonly;\n"; + sb << "__modifier(GLSLWriteOnlyModifier) writeonly;\n"; - sb << "__modifier(SimpleModifier) flat;\n"; - sb << "__modifier(SimpleModifier) highp;\n"; + // We will treat `subroutine` as a qualifier + sb << "__modifier(SimpleModifier) subroutine;\n"; glslLibraryCode = sb.ProduceString(); return glslLibraryCode; -- cgit v1.2.3