diff --git a/code/def_files/data/effects/main-f.sdr b/code/def_files/data/effects/main-f.sdr index 1a46b848d9e..f8390b496fc 100644 --- a/code/def_files/data/effects/main-f.sdr +++ b/code/def_files/data/effects/main-f.sdr @@ -229,10 +229,13 @@ vec3 CalculateLighting(vec3 normal, vec3 diffuseMaterial, vec3 specularMaterial, vec3 lightSpecular = vec3(0.0, 0.0, 0.0); #ifdef MODEL_SDR_FLAG_RT_SHADOWS - // Whenever this compile-time flag is present we're always in Vulkan/large-shader - // mode, so `flags`/MODEL_SDR_FLAG_SHADOWS (the runtime shadow-receiving gate that - // IF_FLAG expands to elsewhere in this file) are guaranteed to exist here too. - bool rtShadowsActive = (flags & MODEL_SDR_FLAG_SHADOWS) != 0; + // Whether this material actually receives shadows. This has to go through IF_FLAG + // rather than testing `flags` directly: in small-shader mode MODEL_SDR_FLAG_SHADOWS + // is only a (valueless) preprocessor define, so it can't be used in an expression. + bool rtShadowsActive = false; + #prereplace IF_FLAG MODEL_SDR_FLAG_SHADOWS + rtShadowsActive = true; + #prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SHADOWS mat4 invView = inverse(viewMatrix); vec3 worldPos = (invView * vertIn.position).xyz; vec3 worldNormal = normalize((invView * vec4(normal, 0.0)).xyz); diff --git a/code/def_files/data/effects/main-v.sdr b/code/def_files/data/effects/main-v.sdr index 39426766ab1..7933ecf3578 100644 --- a/code/def_files/data/effects/main-v.sdr +++ b/code/def_files/data/effects/main-v.sdr @@ -128,15 +128,19 @@ layout(set = 1, binding = 3, std430) readonly buffer TransformBuffer { mat4 transforms[]; } transformBuf; -// Outputs to fragment shader +// Outputs to fragment shader. The shadow members are gated exactly like the matching +// block in main-f.sdr so the stage interfaces stay identical in small-shader mode. layout(location = 0) out VertexOutput { vec4 position; vec3 normal; vec4 texCoord; mat3 tangentMatrix; float fogDist; + +#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS vec4 shadowUV[NUM_SHADOW_CASCADES]; vec4 shadowPos; +#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS } vertOut; #else #prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_TRANSFORM diff --git a/code/def_files/data/effects/model_shader_flags.h b/code/def_files/data/effects/model_shader_flags.h index 5fa94ca4b91..ed9919148f3 100644 --- a/code/def_files/data/effects/model_shader_flags.h +++ b/code/def_files/data/effects/model_shader_flags.h @@ -29,12 +29,12 @@ SDR_FLAG(MODEL_SDR_FLAG_ALPHA_MULT , (1 << 14), false) //But since these are checked with ifdefs even for the large shader, they must never be available in GLSL mode SDR_FLAG(MODEL_SDR_FLAG_THICK_OUTLINES, (1 << 16), true) -// Like MODEL_SDR_FLAG_SHADOW_MAP/THICK_OUTLINES above, this must stay a genuine -// compile-time ifdef check (not the runtime flag-branch macros used for ordinary -// MODEL_SDR_FLAG_* bits) since Vulkan always runs in "large shader" mode, where -// those bits are only checked via a runtime `flags` uniform -- ray query usage -// can't be gated that way, since the GL_EXT_ray_query extension and its types -// must not appear at all in a shader compiled for hardware that doesn't support it. +// Like MODEL_SDR_FLAG_THICK_OUTLINES above, this must stay a genuine compile-time +// ifdef check (not the runtime flag-branch macros used for ordinary MODEL_SDR_FLAG_* +// bits): the GL_EXT_ray_query extension and its types must not appear at all in a +// shader compiled for hardware that doesn't support it, so the usage can't be left +// in the code and skipped via a runtime `flags` branch the way large-shader mode +// handles the ordinary bits. SDR_FLAG(MODEL_SDR_FLAG_RT_SHADOWS , (1 << 17), true) #endif \ No newline at end of file diff --git a/code/graphics/vulkan/gr_vulkan.cpp b/code/graphics/vulkan/gr_vulkan.cpp index 4d5d5768ff8..8fb01daa2a0 100644 --- a/code/graphics/vulkan/gr_vulkan.cpp +++ b/code/graphics/vulkan/gr_vulkan.cpp @@ -142,7 +142,10 @@ bool vulkan_is_capable(gr_capability capability) // Vulkan always supports BC1/BC2/BC3 (S3TC equivalent) as core features return true; case gr_capability::CAPABILITY_LARGE_SHADER: - return true; + // Same troubleshooting switch as OpenGL: -no_large_shaders splits the model + // ubershader into per-flag-combination variants for drivers that choke on the + // single large program (see main_large.sdr / main_small.sdr). + return !Cmdline_no_large_shaders; case gr_capability::CAPABILITY_INSTANCED_RENDERING: return true; case gr_capability::CAPABILITY_FAST_SHADOWS: