From 3d22cbad766e1f3f4d39df637e650d703a5fe937 Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Tue, 31 Dec 2019 12:58:06 -0500 Subject: [PATCH] Add GLSPIRV profile, to allow for both GL- and VK-friendly SPIR-V output --- CMakeLists.txt | 4 ++++ mojoshader.c | 7 ++++-- mojoshader.h | 5 +++++ mojoshader_internal.h | 8 +++++++ mojoshader_opengl.c | 28 +++++++++++------------ profiles/mojoshader_profile.h | 3 +++ profiles/mojoshader_profile_spirv.c | 35 ++++++++++++++++++++--------- profiles/mojoshader_profile_spirv.h | 2 ++ 8 files changed, 66 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 466da148..0026036e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ OPTION(PROFILE_ARB1 "Build MojoShader with support for the ARB1 profile" ON) 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 @@ ENDIF(NOT PROFILE_METAL) 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) diff --git a/mojoshader.c b/mojoshader.c index 9491a82e..1203dc16 100644 --- a/mojoshader.c +++ b/mojoshader.c @@ -319,6 +319,7 @@ static const Profile profiles[] = // 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 @@ static MOJOSHADER_parseData *build_parsedata(Context *ctx) 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 @@ static MOJOSHADER_parseData *build_parsedata(Context *ctx) 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 @@ int MOJOSHADER_maxShaderModel(const char *profile) 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 diff --git a/mojoshader.h b/mojoshader.h index d1e487ee..548138ca 100644 --- a/mojoshader.h +++ b/mojoshader.h @@ -724,6 +724,11 @@ typedef struct MOJOSHADER_parseData */ #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. */ diff --git a/mojoshader_internal.h b/mojoshader_internal.h index 07dc9e5d..6d2296e5 100644 --- a/mojoshader_internal.h +++ b/mojoshader_internal.h @@ -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 diff --git a/mojoshader_opengl.c b/mojoshader_opengl.c index a74604e3..fbf888f3 100644 --- a/mojoshader_opengl.c +++ b/mojoshader_opengl.c @@ -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 @@ static inline void toggle_gl_state(GLenum state, int val) // 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 @@ static int impl_GLSL_MaxUniforms(MOJOSHADER_shaderType shader_type) 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 @@ static void impl_SPIRV_FinalInitProgram(MOJOSHADER_glProgram *program) 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 @@ static void impl_GLSL_PushSampler(GLint loc, GLuint sampler) 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 @@ static int valid_profile(const char *profile) } // 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 int valid_profile(const char *profile) 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 @@ MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile, // !!! 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; diff --git a/profiles/mojoshader_profile.h b/profiles/mojoshader_profile.h index f9db8a1b..39007327 100644 --- a/profiles/mojoshader_profile.h +++ b/profiles/mojoshader_profile.h @@ -210,6 +210,9 @@ typedef struct Context 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. diff --git a/profiles/mojoshader_profile_spirv.c b/profiles/mojoshader_profile_spirv.c index d5f30a0c..f3ef3113 100644 --- a/profiles/mojoshader_profile_spirv.c +++ b/profiles/mojoshader_profile_spirv.c @@ -1270,8 +1270,9 @@ static void spv_assign_destarg(Context *ctx, SpirvResult value) 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 @@ static void spv_emit_vs_main_end(Context* ctx) 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 @@ static void spv_emit_vs_main_end(Context* ctx) 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 @@ static void spv_emit_vs_main_end(Context* ctx) 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 @@ static void spv_emit_func_end(Context *ctx) { 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 @@ static void spv_emit_func_end(Context *ctx) 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 @@ static void spv_link_ps_attributes(Context *ctx, uint32 id, RegisterType regtype { 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 @@ void emit_SPIRV_start(Context *ctx, const char *profilestr) 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)); diff --git a/profiles/mojoshader_profile_spirv.h b/profiles/mojoshader_profile_spirv.h index ceea039f..e840db15 100644 --- a/profiles/mojoshader_profile_spirv.h +++ b/profiles/mojoshader_profile_spirv.h @@ -147,7 +147,9 @@ typedef struct SpirvResult 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;