summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-07-13 09:12:50 -0700
committerTim Foley <tfoley@nvidia.com>2017-07-13 09:17:27 -0700
commit6da80f58ba8f51fc768f177f28a7d818b03c434e (patch)
tree7bc2a09c412856951e036622f2b9d3a2742bcd4c /source
parent72a3e97fe6bfdffee253ad008cab7cdd3b9e796f (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.cpp2
-rw-r--r--source/slang/emit.cpp84
-rw-r--r--source/slang/profile-defs.h100
-rw-r--r--source/slang/profile.h1
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"
};