From d096ce16440c958956c9866d457dfd83c76f057e Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Mon, 11 May 2020 15:46:31 +0100 Subject: [PATCH] GLES2 Batching - Fix custom shaders reading VERTEX In situations where custom canvas shaders read VERTEX values, they could read incorrect global positions rather than local positions where batching had baked item transforms. This PR prevents joining items that read VERTEX built in in shaders, and thus prevents this situation arising (as unjoined items will not bake transforms). --- drivers/gles2/rasterizer_canvas_gles2.cpp | 5 +++-- drivers/gles2/rasterizer_storage_gles2.cpp | 11 +++++++++-- drivers/gles2/rasterizer_storage_gles2.h | 15 ++++++++++----- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index 5baafaff037..eacb0b5579a 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -2267,7 +2267,8 @@ bool RasterizerCanvasGLES2::try_join_item(Item *p_ci, RenderItemState &r_ris, bo // does the shader contain BUILTINs which should break the batching? if (r_ris.shader_cache && !unshaded) { - if (r_ris.shader_cache->canvas_item.prevent_color_baking) { + const unsigned int test_flags = RasterizerStorageGLES2::Shader::CanvasItem::PREVENT_COLOR_BAKING | RasterizerStorageGLES2::Shader::CanvasItem::PREVENT_VERTEX_BAKING; + if (r_ris.shader_cache->canvas_item.batch_flags & test_flags) { // we will do this same test on the shader during the rendering pass in order to set a bool not to bake vertex colors // instead of saving this info as it is cheap to calculate join = false; @@ -3000,7 +3001,7 @@ void RasterizerCanvasGLES2::render_joined_item(const BItemJoined &p_bij, RenderI // does the shader contain BUILTINs which break the batching and should prevent color baking? bdata.prevent_color_baking = false; if (r_ris.shader_cache && !unshaded) { - if (r_ris.shader_cache->canvas_item.prevent_color_baking) { + if (r_ris.shader_cache->canvas_item.batch_flags & RasterizerStorageGLES2::Shader::CanvasItem::PREVENT_COLOR_BAKING) { bdata.prevent_color_baking = true; } } diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 1ca7cc30281..6a2a2b7113b 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -1426,7 +1426,8 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const { p_shader->canvas_item.uses_time = false; p_shader->canvas_item.uses_modulate = false; p_shader->canvas_item.reads_color = false; - p_shader->canvas_item.prevent_color_baking = false; + p_shader->canvas_item.reads_vertex = false; + p_shader->canvas_item.batch_flags = 0; shaders.actions_canvas.render_mode_values["blend_add"] = Pair(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_ADD); shaders.actions_canvas.render_mode_values["blend_mix"] = Pair(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MIX); @@ -1444,6 +1445,7 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const { shaders.actions_canvas.usage_flag_pointers["MODULATE"] = &p_shader->canvas_item.uses_modulate; shaders.actions_canvas.read_flag_pointers["COLOR"] = &p_shader->canvas_item.reads_color; + shaders.actions_canvas.read_flag_pointers["VERTEX"] = &p_shader->canvas_item.reads_vertex; actions = &shaders.actions_canvas; actions->uniforms = &p_shader->uniforms; @@ -1533,7 +1535,12 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const { // some logic for batching if (p_shader->mode == VS::SHADER_CANVAS_ITEM) { - p_shader->canvas_item.prevent_color_baking = p_shader->canvas_item.uses_modulate | p_shader->canvas_item.reads_color; + if (p_shader->canvas_item.uses_modulate | p_shader->canvas_item.reads_color) { + p_shader->canvas_item.batch_flags |= Shader::CanvasItem::PREVENT_COLOR_BAKING; + } + if (p_shader->canvas_item.reads_vertex) { + p_shader->canvas_item.batch_flags |= Shader::CanvasItem::PREVENT_VERTEX_BAKING; + } } p_shader->shader->set_custom_shader(p_shader->custom_code_id); diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index 32e1d9bbdaa..f85461593d6 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -447,16 +447,21 @@ public: int light_mode; + enum BatchFlags { + PREVENT_COLOR_BAKING = 1 << 0, + PREVENT_VERTEX_BAKING = 1 << 1, + }; + // these flags are specifically for batching + // some of the logic is thus in rasterizer_storage.cpp + // we could alternatively set bitflags for each 'uses' and test on the fly + unsigned int batch_flags; + bool uses_screen_texture; bool uses_screen_uv; bool uses_time; bool uses_modulate; bool reads_color; - - // this flag is specifically for batching - // some of the logic is thus in rasterizer_storage.cpp - // we could alternatively set some bitflags here and test on the fly - bool prevent_color_baking; + bool reads_vertex; } canvas_item;