Add GLSPIRV profile, to allow for both GL- and VK-friendly SPIR-V output
authorEthan Lee <flibitijibibo@flibitijibibo.com>
Tue, 31 Dec 2019 12:58:06 -0500
changeset 1225 50b8dd7e0b1a
parent 1224 21cd84f1aa0a
child 1226 773dafd11a6e
Add GLSPIRV profile, to allow for both GL- and VK-friendly SPIR-V output
CMakeLists.txt
mojoshader.c
mojoshader.h
mojoshader_internal.h
mojoshader_opengl.c
profiles/mojoshader_profile.h
profiles/mojoshader_profile_spirv.c
profiles/mojoshader_profile_spirv.h
--- a/CMakeLists.txt	Tue Dec 31 12:22:44 2019 -0500
+++ b/CMakeLists.txt	Tue Dec 31 12:58:06 2019 -0500
@@ -11,6 +11,7 @@
 OPTION(PROFILE_ARB1_NV "Build MojoShader with support for the ARB1_NV profile" ON)
 OPTION(PROFILE_METAL "Build MojoShader with support for the Metal profile" ON)
 OPTION(PROFILE_SPIRV "Build MojoShader with support for the SPIR-V profile" ON)
+OPTION(PROFILE_GLSPIRV "Build MojoShader with support for the ARB_gl_spirv profile" ON)
 OPTION(EFFECT_SUPPORT "Build MojoShader with support for Effect framework files" ON)
 OPTION(COMPILER_SUPPORT "Build MojoShader with support for HLSL source files" OFF)
 OPTION(FLIP_VIEWPORT "Build MojoShader with the ability to flip the GL viewport" OFF)
@@ -128,6 +129,9 @@
 IF(NOT PROFILE_SPIRV)
     ADD_DEFINITIONS(-DSUPPORT_PROFILE_SPIRV=0)
 ENDIF(NOT PROFILE_SPIRV)
+IF(NOT PROFILE_GLSPIRV)
+    ADD_DEFINITIONS(-DSUPPORT_PROFILE_GLSPIRV=0)
+ENDIF(NOT PROFILE_GLSPIRV)
 
 IF(EFFECT_SUPPORT)
     IF(UNIX)
--- a/mojoshader.c	Tue Dec 31 12:22:44 2019 -0500
+++ b/mojoshader.c	Tue Dec 31 12:58:06 2019 -0500
@@ -319,6 +319,7 @@
 // This is for profiles that extend other profiles...
 static const struct { const char *from; const char *to; } profileMap[] =
 {
+    { MOJOSHADER_PROFILE_GLSPIRV, MOJOSHADER_PROFILE_SPIRV },
     { MOJOSHADER_PROFILE_GLSLES, MOJOSHADER_PROFILE_GLSL },
     { MOJOSHADER_PROFILE_GLSL120, MOJOSHADER_PROFILE_GLSL },
     { MOJOSHADER_PROFILE_NV2, MOJOSHADER_PROFILE_ARB1 },
@@ -3459,7 +3460,8 @@
         retval->mainfn = ctx->mainfn;
 
 #if SUPPORT_PROFILE_SPIRV
-        if (strcmp(retval->profile, "spirv") == 0)
+        if (strcmp(retval->profile, MOJOSHADER_PROFILE_SPIRV) == 0
+         || strcmp(retval->profile, MOJOSHADER_PROFILE_GLSPIRV) == 0)
         {
             size_t i, max;
             int binary_size = retval->output_len - sizeof(SpirvPatchTable);
@@ -3478,7 +3480,7 @@
                     binary[entry.offset] = entry.location;
             } // for
         } // if
-#endif
+#endif // SUPPORT_PROFILE_SPIRV
 
         // we don't own these now, retval does.
         ctx->ctab.symbols = NULL;
@@ -3864,6 +3866,7 @@
     PROFILE_SHADER_MODEL(MOJOSHADER_PROFILE_NV4, 3);
     PROFILE_SHADER_MODEL(MOJOSHADER_PROFILE_METAL, 3);
     PROFILE_SHADER_MODEL(MOJOSHADER_PROFILE_SPIRV, 3);
+    PROFILE_SHADER_MODEL(MOJOSHADER_PROFILE_GLSPIRV, 3);
     #undef PROFILE_SHADER_MODEL
     return -1;  // unknown profile?
 } // MOJOSHADER_maxShaderModel
--- a/mojoshader.h	Tue Dec 31 12:22:44 2019 -0500
+++ b/mojoshader.h	Tue Dec 31 12:58:06 2019 -0500
@@ -725,6 +725,11 @@
 #define MOJOSHADER_PROFILE_SPIRV "spirv"
 
 /*
+ * Profile string for ARB_gl_spirv-friendly SPIR-V binary output
+ */
+#define MOJOSHADER_PROFILE_GLSPIRV "glspirv"
+
+/*
  * Determine the highest supported Shader Model for a profile.
  */
 DECLSPEC int MOJOSHADER_maxShaderModel(const char *profile);
--- a/mojoshader_internal.h	Tue Dec 31 12:22:44 2019 -0500
+++ b/mojoshader_internal.h	Tue Dec 31 12:58:06 2019 -0500
@@ -68,6 +68,10 @@
 #define SUPPORT_PROFILE_SPIRV 1
 #endif
 
+#ifndef SUPPORT_PROFILE_GLSPIRV
+#define SUPPORT_PROFILE_GLSPIRV 1
+#endif
+
 #if SUPPORT_PROFILE_ARB1_NV && !SUPPORT_PROFILE_ARB1
 #error nv profiles require arb1 profile. Fix your build.
 #endif
@@ -80,6 +84,10 @@
 #error glsles profile requires glsl profile. Fix your build.
 #endif
 
+#if SUPPORT_PROFILE_GLSPIRV && !SUPPORT_PROFILE_SPIRV
+#error glspirv profile requires spirv profile. Fix your build.
+#endif
+
 // Microsoft's preprocessor has some quirks. In some ways, it doesn't work
 //  like you'd expect a C preprocessor to function.
 #ifndef MATCH_MICROSOFT_PREPROCESSOR
--- a/mojoshader_opengl.c	Tue Dec 31 12:22:44 2019 -0500
+++ b/mojoshader_opengl.c	Tue Dec 31 12:58:06 2019 -0500
@@ -36,7 +36,7 @@
 #include "GL/gl.h"
 #include "GL/glext.h"
 
-#if SUPPORT_PROFILE_SPIRV
+#if SUPPORT_PROFILE_GLSPIRV
 #include "spirv/spirv.h"
 #endif
 
@@ -402,7 +402,7 @@
 
 // profile-specific implementations...
 
-#if SUPPORT_PROFILE_GLSL || SUPPORT_PROFILE_SPIRV
+#if SUPPORT_PROFILE_GLSL || SUPPORT_PROFILE_GLSPIRV
 static inline GLenum glsl_shader_type(const MOJOSHADER_shaderType t)
 {
     // these enums match between core 2.0 and the ARB extensions.
@@ -436,7 +436,7 @@
     return (int) val;
 } // impl_GLSL_MaxUniforms
 
-#if SUPPORT_PROFILE_SPIRV
+#if SUPPORT_PROFILE_GLSPIRV
 static const SpirvPatchTable* spv_getPatchTable(MOJOSHADER_glShader *shader)
 {
     const MOJOSHADER_parseData *pd = shader->parseData;
@@ -657,7 +657,7 @@
         if (program->ps_vpos_flip_loc != -1) program->ps_vpos_flip_loc += ps_base_location;
     } // if
 } // impl_SPIRV_FinalInitProgram
-#endif // SUPPORT_PROFILE_SPIRV
+#endif // SUPPORT_PROFILE_GLSPIRV
 
 #if SUPPORT_PROFILE_GLSL
 static int impl_GLSL_CompileShader(const MOJOSHADER_parseData *pd, GLuint *s)
@@ -909,7 +909,7 @@
     ctx->glUniform1i(loc, sampler);
 } // impl_GLSL_PushSampler
 
-#endif // SUPPORT_PROFILE_GLSL || SUPPORT_PROFILE_SPIRV
+#endif // SUPPORT_PROFILE_GLSL || SUPPORT_PROFILE_GLSPIRV
 
 
 #if SUPPORT_PROFILE_ARB1
@@ -1553,11 +1553,11 @@
     } // else if
     #endif
 
-    #if SUPPORT_PROFILE_SPIRV
-    else if (strcmp(profile, MOJOSHADER_PROFILE_SPIRV) == 0)
+    #if SUPPORT_PROFILE_GLSPIRV
+    else if (strcmp(profile, MOJOSHADER_PROFILE_GLSPIRV) == 0)
     {
-        MUST_HAVE(MOJOSHADER_PROFILE_SPIRV, GL_ARB_ES2_compatibility);
-        MUST_HAVE(MOJOSHADER_PROFILE_SPIRV, GL_ARB_gl_spirv);
+        MUST_HAVE(MOJOSHADER_PROFILE_GLSPIRV, GL_ARB_ES2_compatibility);
+        MUST_HAVE(MOJOSHADER_PROFILE_GLSPIRV, GL_ARB_gl_spirv);
     } // else if
     #endif
 
@@ -1595,8 +1595,8 @@
 
 
 static const char *profile_priorities[] = {
-#if SUPPORT_PROFILE_SPIRV
-    MOJOSHADER_PROFILE_SPIRV,
+#if SUPPORT_PROFILE_GLSPIRV
+    MOJOSHADER_PROFILE_GLSPIRV,
 #endif
 #if SUPPORT_PROFILE_GLSL120
     MOJOSHADER_PROFILE_GLSL120,
@@ -1726,9 +1726,9 @@
     // !!! FIXME: generalize this part.
     if (profile == NULL) {}
 
-    // We don't check SUPPORT_PROFILE_SPIRV here, since valid_profile() does.
-#if SUPPORT_PROFILE_SPIRV
-    else if (strcmp(profile, MOJOSHADER_PROFILE_SPIRV) == 0)
+    // We don't check SUPPORT_PROFILE_GLSPIRV here, since valid_profile() does.
+#if SUPPORT_PROFILE_GLSPIRV
+    else if (strcmp(profile, MOJOSHADER_PROFILE_GLSPIRV) == 0)
     {
         ctx->profileMaxUniforms = impl_GLSL_MaxUniforms;
         ctx->profileCompileShader = impl_SPIRV_CompileShader;
--- a/profiles/mojoshader_profile.h	Tue Dec 31 12:22:44 2019 -0500
+++ b/profiles/mojoshader_profile.h	Tue Dec 31 12:58:06 2019 -0500
@@ -210,6 +210,9 @@
     int branch_labels_patch_stack[32];
     SpirvContext spirv;
 #endif
+#if SUPPORT_PROFILE_GLSPIRV
+    int profile_supports_glspirv;
+#endif
 } Context;
 
 // Use these macros so we can remove all bits of these profiles from the build.
--- a/profiles/mojoshader_profile_spirv.c	Tue Dec 31 12:22:44 2019 -0500
+++ b/profiles/mojoshader_profile_spirv.c	Tue Dec 31 12:58:06 2019 -0500
@@ -1270,8 +1270,9 @@
 
 static void spv_emit_vs_main_end(Context* ctx)
 {
+#if SUPPORT_PROFILE_GLSPIRV
 #if defined(MOJOSHADER_DEPTH_CLIPPING) || defined(MOJOSHADER_FLIP_RENDERTARGET)
-    if (!shader_is_vertex(ctx))
+    if (!ctx->profile_supports_glspirv || !shader_is_vertex(ctx))
         return;
 
     uint32 tid_void = spv_get_type(ctx, STI_VOID);
@@ -1317,7 +1318,7 @@
 
     spv_output_name(ctx, id_pvpflip, "vpFlip");
     ctx->spirv.patch_table.vpflip.offset = spv_output_location(ctx, id_pvpflip, ~0u);
-#endif
+#endif // MOJOSHADER_FLIP_RENDERTARGET
 
 #ifdef MOJOSHADER_DEPTH_CLIPPING
     // gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;
@@ -1334,7 +1335,7 @@
     spv_emit(ctx, 5, SpvOpFSub, tid_float, id_new_z, id_2z, id_old_w);
     spv_emit(ctx, 6, SpvOpCompositeInsert, output.tid, id_new_output, id_new_z, output.id, 2);
     output.id = id_new_output;
-#endif
+#endif // MOJOSHADER_DEPTH_CLIPPING
 
     spv_emit(ctx, 3, SpvOpStore, reg->spirv.iddecl, output.id);
     spv_emit(ctx, 1, SpvOpReturn);
@@ -1342,7 +1343,8 @@
     pop_output(ctx);
 
     spv_output_name(ctx, id_func, "vs_epilogue");
-#endif
+#endif // defined(MOJOSHADER_DEPTH_CLIPPING) || defined(MOJOSHADER_FLIP_RENDERTARGET)
+#endif // SUPPORT_PROFILE_GLSPIRV
 } // spv_emit_vs_main_end
 
 static void spv_emit_func_lit(Context *ctx)
@@ -1458,8 +1460,11 @@
 {
     push_output(ctx, &ctx->mainline);
 
+#if SUPPORT_PROFILE_GLSPIRV
 #if defined(MOJOSHADER_DEPTH_CLIPPING) || defined(MOJOSHADER_FLIP_RENDERTARGET)
-    if (shader_is_vertex(ctx) && ctx->spirv.id_vs_main_end == 0)
+    if (ctx->profile_supports_glspirv
+     && shader_is_vertex(ctx)
+     && ctx->spirv.id_vs_main_end == 0)
     {
         ctx->spirv.id_vs_main_end = spv_bumpid(ctx);
         uint32 tid_void = spv_get_type(ctx, STI_VOID);
@@ -1469,7 +1474,8 @@
         spv_emit(ctx, 4, SpvOpFunctionCall, tid_void, id_res, ctx->spirv.id_vs_main_end);
         pop_output(ctx);
     } // if
-#endif
+#endif // defined(MOJOSHADER_DEPTH_CLIPPING) || defined(MOJOSHADER_FLIP_RENDERTARGET)
+#endif // SUPPORT_PROFILE_GLSPIRV
 
     spv_emit(ctx, 1, SpvOpReturn);
     spv_emit(ctx, 1, SpvOpFunctionEnd);
@@ -1564,8 +1570,10 @@
             {
                 case MISCTYPE_TYPE_POSITION: // vPos
                 {
-                    // In SM3.0 vPos only has x and y defined, but we should be fine to leave the z and w attributes in
-                    // that SpvBuiltInFragCoord gives
+                    // In SM3.0 vPos only has x and y defined, but we should be
+                    // fine to leave the z and w attributes in that
+                    // SpvBuiltInFragCoord gives.
+                    // FIXME: Is the flip needed for Vulkan?
 
                     uint32 tid_float = spv_get_type(ctx, STI_FLOAT);
                     uint32 tid_vec2 = spv_get_type(ctx, STI_VEC2);
@@ -1792,8 +1800,15 @@
         return;
     } // if
 
-    if (strcmp(profilestr, MOJOSHADER_PROFILE_SPIRV) != 0)
-        failf(ctx, "Profile '%s' unsupported or unknown.", profilestr);
+#if SUPPORT_PROFILE_GLSPIRV
+    if (strcmp(profilestr, MOJOSHADER_PROFILE_GLSPIRV) == 0)
+        ctx->profile_supports_glspirv = 1;
+    else
+#endif // SUPPORT_PROFILE_GLSPIRV
+    {
+        if (strcmp(profilestr, MOJOSHADER_PROFILE_SPIRV) != 0)
+            failf(ctx, "Profile '%s' unsupported or unknown.", profilestr);
+    } // else
 
     memset(&(ctx->spirv), '\0', sizeof(ctx->spirv));
 
--- a/profiles/mojoshader_profile_spirv.h	Tue Dec 31 12:22:44 2019 -0500
+++ b/profiles/mojoshader_profile_spirv.h	Tue Dec 31 12:58:06 2019 -0500
@@ -147,7 +147,9 @@
 
 typedef struct SpirvContext
 {
+#if SUPPORT_PROFILE_GLSPIRV
     uint32 id_vs_main_end;
+#endif // SUPPORT_PROFILE_GLSPIRV
     // ext. glsl instructions have been imported
     uint32 idext;
     uint32 idmax;