summaryrefslogtreecommitdiffstats
path: root/source/slang
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2017-07-13 09:54:47 -0700
committerGitHub <noreply@github.com>2017-07-13 09:54:47 -0700
commitc963b44aa48a4349e20a0afcd423b55b1996d2fa (patch)
tree88f7f0b51d679cc308437461b8c210e828efeda0 /source/slang
parent9058358792fa393e0e92af80f24a54a037aa9691 (diff)
parentc51fd4ee8f478aa3d3b7e6208a3a4e9c00e2413a (diff)
Merge pull request #85 from tfoleyNV/working
Various bug fixes
Diffstat (limited to 'source/slang')
-rw-r--r--source/slang/compiler.cpp2
-rw-r--r--source/slang/emit.cpp102
-rw-r--r--source/slang/profile-defs.h100
-rw-r--r--source/slang/profile.h1
-rw-r--r--source/slang/slang-stdlib.cpp41
-rw-r--r--source/slang/slang.cpp25
6 files changed, 230 insertions, 41 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 6905a8a76..21c91a5c0 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -18,9 +18,17 @@ 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;
+ // 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 +464,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)
{
@@ -3387,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...
@@ -3412,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
- Emit("#version 420\n");
+ 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;
+
+ 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.
@@ -3479,6 +3531,8 @@ 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"
};
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;
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