diff options
| author | Tim Foley <tfoley@nvidia.com> | 2017-07-13 09:12:50 -0700 |
|---|---|---|
| committer | Tim Foley <tfoley@nvidia.com> | 2017-07-13 09:17:27 -0700 |
| commit | 6da80f58ba8f51fc768f177f28a7d818b03c434e (patch) | |
| tree | 7bc2a09c412856951e036622f2b9d3a2742bcd4c /source | |
| parent | 72a3e97fe6bfdffee253ad008cab7cdd3b9e796f (diff) | |
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
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/compiler.cpp | 2 | ||||
| -rw-r--r-- | source/slang/emit.cpp | 84 | ||||
| -rw-r--r-- | source/slang/profile-defs.h | 100 | ||||
| -rw-r--r-- | source/slang/profile.h | 1 |
4 files changed, 156 insertions, 31 deletions
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<ProgramSyntaxNode> 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<GLSLVersionDirective>() ) { // 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<ProgramSyntaxNode> 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" }; |
