From 5ed0fd067dba54fe07870e5c0303ee1f1cf253a1 Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Thu, 11 Mar 2021 12:57:52 +0000 Subject: [PATCH] Batching - use FINAL_MODULATE_ALIAS in shaders As part of the improvements to batch more cases, batching can store final_modulate as an attribute in the vertex format rather than sending as a uniform. This allows draw calls with different final_modulate to be batched together. However custom shader code was reading from only the final_modulate uniform, and not the attribute when it was in use. This was leading to visual errors. This is tricky to solve, because we cannot use the same name for the attribute in the vertex and fragment shaders, because one is an attribute and one a varying, whereas a uniform is accessible anywhere. To get around this, a macro is used which can translate to the most appropriate variable depending on whether uniform or attribute or varying is required. --- drivers/gles2/shader_compiler_gles2.cpp | 2 +- drivers/gles2/shaders/canvas.glsl | 29 ++++++++++++++++++++----- drivers/gles3/shader_compiler_gles3.cpp | 2 +- drivers/gles3/shaders/canvas.glsl | 29 ++++++++++++++++++++----- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 7db08c37ebf..60bbecfecd0 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -911,7 +911,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { actions[VS::SHADER_CANVAS_ITEM].renames["INSTANCE_CUSTOM"] = "instance_custom"; actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"] = "color"; - actions[VS::SHADER_CANVAS_ITEM].renames["MODULATE"] = "final_modulate"; + actions[VS::SHADER_CANVAS_ITEM].renames["MODULATE"] = "final_modulate_alias"; actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL"] = "normal"; actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP"] = "normal_map"; actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP_DEPTH"] = "normal_depth"; diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index 3cf5ca841f9..2420e62021c 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -31,6 +31,17 @@ attribute vec2 uv_attrib; // attrib:4 attribute highp vec4 modulate_attrib; // attrib:5 #endif +// Usually, final_modulate is passed as a uniform. However during batching +// If larger fvfs are used, final_modulate is passed as an attribute. +// we need to read from the attribute in custom vertex shader +// rather than the uniform. We do this by specifying final_modulate_alias +// in shaders rather than final_modulate directly. +#ifdef USE_ATTRIB_MODULATE +#define final_modulate_alias modulate_attrib +#else +#define final_modulate_alias final_modulate +#endif + #ifdef USE_ATTRIB_LARGE_VERTEX // shared with skeleton attributes, not used in batched shader attribute highp vec2 translate_attrib; // attrib:6 @@ -469,6 +480,18 @@ void main() { normal_used = true; #endif + // If larger fvfs are used, final_modulate is passed as an attribute. + // we need to read from this in custom fragment shaders or applying in the post step, + // rather than using final_modulate directly. +#if defined(final_modulate_alias) +#undef final_modulate_alias +#endif +#ifdef USE_ATTRIB_MODULATE +#define final_modulate_alias modulate_interp +#else +#define final_modulate_alias final_modulate +#endif + /* clang-format off */ FRAGMENT_SHADER_CODE @@ -481,11 +504,7 @@ FRAGMENT_SHADER_CODE } #if !defined(MODULATE_USED) -#ifdef USE_ATTRIB_MODULATE - color *= modulate_interp; -#else - color *= final_modulate; -#endif + color *= final_modulate_alias; #endif #ifdef USE_LIGHTING diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index a994096a334..b6e4e4c8c28 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -891,7 +891,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_CANVAS_ITEM].renames["INSTANCE_CUSTOM"] = "instance_custom"; actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"] = "color"; - actions[VS::SHADER_CANVAS_ITEM].renames["MODULATE"] = "final_modulate"; + actions[VS::SHADER_CANVAS_ITEM].renames["MODULATE"] = "final_modulate_alias"; actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL"] = "normal"; actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP"] = "normal_map"; actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP_DEPTH"] = "normal_depth"; diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 620968cd143..b4e65dfb0a4 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -14,6 +14,17 @@ layout(location = 3) in vec4 color_attrib; layout(location = 5) in vec4 modulate_attrib; // attrib:5 #endif +// Usually, final_modulate is passed as a uniform. However during batching +// If larger fvfs are used, final_modulate is passed as an attribute. +// we need to read from the attribute in custom vertex shader +// rather than the uniform. We do this by specifying final_modulate_alias +// in shaders rather than final_modulate directly. +#ifdef USE_ATTRIB_MODULATE +#define final_modulate_alias modulate_attrib +#else +#define final_modulate_alias final_modulate +#endif + #ifdef USE_ATTRIB_LARGE_VERTEX // shared with skeleton attributes, not used in batched shader layout(location = 6) in vec2 translate_attrib; // attrib:6 @@ -567,6 +578,18 @@ void main() { normal_used = true; #endif + // If larger fvfs are used, final_modulate is passed as an attribute. + // we need to read from this in custom fragment shaders or applying in the post step, + // rather than using final_modulate directly. +#if defined(final_modulate_alias) +#undef final_modulate_alias +#endif +#ifdef USE_ATTRIB_MODULATE +#define final_modulate_alias modulate_interp +#else +#define final_modulate_alias final_modulate +#endif + /* clang-format off */ FRAGMENT_SHADER_CODE @@ -582,12 +605,8 @@ FRAGMENT_SHADER_CODE color = vec4(vec3(enc32), 1.0); #endif -#ifdef USE_ATTRIB_MODULATE - color *= modulate_interp; -#else #if !defined(MODULATE_USED) - color *= final_modulate; -#endif + color *= final_modulate_alias; #endif #ifdef USE_LIGHTING