diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index f7b1546d5e..22ca8f8568 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -1372,33 +1372,42 @@ bool RasterizerCanvasGLES2::try_join_item(Item *p_ci, RenderItemState &r_ris, bo bdata.joined_item_batch_flags = 0; if (r_ris.shader_cache) { - unsigned int and_flags = r_ris.shader_cache->canvas_item.batch_flags & (RasterizerStorageCommon::PREVENT_COLOR_BAKING | RasterizerStorageCommon::PREVENT_VERTEX_BAKING); + unsigned int and_flags = r_ris.shader_cache->canvas_item.batch_flags & (RasterizerStorageCommon::PREVENT_COLOR_BAKING | RasterizerStorageCommon::PREVENT_VERTEX_BAKING | RasterizerStorageCommon::PREVENT_ITEM_JOINING); if (and_flags) { - bool use_larger_fvfs = true; - - if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) { - // in some circumstances, if the modulate is identity, we still allow baking because reading modulate / color - // will still be okay to do in the shader with no ill effects - if (r_ris.final_modulate == Color(1, 1, 1, 1)) { - use_larger_fvfs = false; - } - } - - // new .. always use large FVF - if (use_larger_fvfs) { - if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) { - bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_MODULATE_FVF; - } else { - // we need to save on the joined item that it should use large fvf. - // This info will then be used in filling and rendering - bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_LARGE_FVF; - } + // special case for preventing item joining altogether + if (and_flags & RasterizerStorageCommon::PREVENT_ITEM_JOINING) { + join = false; + //r_batch_break = true; // don't think we need a batch break + // save the flags so that they don't need to be recalculated in the 2nd pass bdata.joined_item_batch_flags |= r_ris.shader_cache->canvas_item.batch_flags; - } + } else { - /* + bool use_larger_fvfs = true; + + if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) { + // in some circumstances, if the modulate is identity, we still allow baking because reading modulate / color + // will still be okay to do in the shader with no ill effects + if (r_ris.final_modulate == Color(1, 1, 1, 1)) { + use_larger_fvfs = false; + } + } + + // new .. always use large FVF + if (use_larger_fvfs) { + if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) { + bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_MODULATE_FVF; + } else { + // we need to save on the joined item that it should use large fvf. + // This info will then be used in filling and rendering + bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_LARGE_FVF; + } + + bdata.joined_item_batch_flags |= r_ris.shader_cache->canvas_item.batch_flags; + } + + /* if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) { // in some circumstances, if the modulate is identity, we still allow baking because reading modulate / color // will still be okay to do in the shader with no ill effects @@ -1424,6 +1433,7 @@ bool RasterizerCanvasGLES2::try_join_item(Item *p_ci, RenderItemState &r_ris, bo bdata.joined_item_batch_flags |= r_ris.shader_cache->canvas_item.batch_flags; } */ + } // if not prevent item joining } } diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index d155d37217..322f63488c 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -1437,6 +1437,11 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const { p_shader->canvas_item.uses_vertex = false; p_shader->canvas_item.batch_flags = 0; + p_shader->canvas_item.uses_world_matrix = false; + p_shader->canvas_item.uses_extra_matrix = false; + p_shader->canvas_item.uses_projection_matrix = false; + p_shader->canvas_item.uses_instance_custom = false; + 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); shaders.actions_canvas.render_mode_values["blend_sub"] = Pair(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_SUB); @@ -1455,6 +1460,11 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const { shaders.actions_canvas.usage_flag_pointers["VERTEX"] = &p_shader->canvas_item.uses_vertex; + shaders.actions_canvas.usage_flag_pointers["WORLD_MATRIX"] = &p_shader->canvas_item.uses_world_matrix; + shaders.actions_canvas.usage_flag_pointers["EXTRA_MATRIX"] = &p_shader->canvas_item.uses_extra_matrix; + shaders.actions_canvas.usage_flag_pointers["PROJECTION_MATRIX"] = &p_shader->canvas_item.uses_projection_matrix; + shaders.actions_canvas.usage_flag_pointers["INSTANCE_CUSTOM"] = &p_shader->canvas_item.uses_instance_custom; + actions = &shaders.actions_canvas; actions->uniforms = &p_shader->uniforms; } break; @@ -1558,6 +1568,9 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const { if (p_shader->canvas_item.uses_vertex) { p_shader->canvas_item.batch_flags |= RasterizerStorageCommon::PREVENT_VERTEX_BAKING; } + if (p_shader->canvas_item.uses_world_matrix | p_shader->canvas_item.uses_extra_matrix | p_shader->canvas_item.uses_projection_matrix | p_shader->canvas_item.uses_instance_custom) { + p_shader->canvas_item.batch_flags |= RasterizerStorageCommon::PREVENT_ITEM_JOINING; + } } 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 f2024de128..28be646dbb 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -458,6 +458,12 @@ public: bool uses_color; bool uses_vertex; + // all these should disable item joining if used in a custom shader + bool uses_world_matrix; + bool uses_extra_matrix; + bool uses_projection_matrix; + bool uses_instance_custom; + } canvas_item; struct Spatial { diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 66ba398291..42480a8b2f 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -1770,31 +1770,41 @@ bool RasterizerCanvasGLES3::try_join_item(Item *p_ci, RenderItemState &r_ris, bo bdata.joined_item_batch_flags = 0; if (r_ris.shader_cache) { - unsigned int and_flags = r_ris.shader_cache->canvas_item.batch_flags & (RasterizerStorageCommon::PREVENT_COLOR_BAKING | RasterizerStorageCommon::PREVENT_VERTEX_BAKING); + unsigned int and_flags = r_ris.shader_cache->canvas_item.batch_flags & (RasterizerStorageCommon::PREVENT_COLOR_BAKING | RasterizerStorageCommon::PREVENT_VERTEX_BAKING | RasterizerStorageCommon::PREVENT_ITEM_JOINING); if (and_flags) { - bool use_larger_fvfs = true; - - if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) { - // in some circumstances, if the modulate is identity, we still allow baking because reading modulate / color - // will still be okay to do in the shader with no ill effects - if (r_ris.final_modulate == Color(1, 1, 1, 1)) { - use_larger_fvfs = false; - } - } - - // new .. always use large FVF - if (use_larger_fvfs) { - if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) { - bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_MODULATE_FVF; - } else { - // we need to save on the joined item that it should use large fvf. - // This info will then be used in filling and rendering - bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_LARGE_FVF; - } + // special case for preventing item joining altogether + if (and_flags & RasterizerStorageCommon::PREVENT_ITEM_JOINING) { + join = false; + //r_batch_break = true; // don't think we need a batch break + // save the flags so that they don't need to be recalculated in the 2nd pass bdata.joined_item_batch_flags |= r_ris.shader_cache->canvas_item.batch_flags; - } + } else { + + bool use_larger_fvfs = true; + + if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) { + // in some circumstances, if the modulate is identity, we still allow baking because reading modulate / color + // will still be okay to do in the shader with no ill effects + if (r_ris.final_modulate == Color(1, 1, 1, 1)) { + use_larger_fvfs = false; + } + } + + // new .. always use large FVF + if (use_larger_fvfs) { + if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) { + bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_MODULATE_FVF; + } else { + // we need to save on the joined item that it should use large fvf. + // This info will then be used in filling and rendering + bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_LARGE_FVF; + } + + bdata.joined_item_batch_flags |= r_ris.shader_cache->canvas_item.batch_flags; + } + } // if not prevent item joining } } diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index bba60d1029..c22f12816c 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -2313,6 +2313,11 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { p_shader->canvas_item.uses_vertex = false; p_shader->canvas_item.batch_flags = 0; + p_shader->canvas_item.uses_world_matrix = false; + p_shader->canvas_item.uses_extra_matrix = false; + p_shader->canvas_item.uses_projection_matrix = false; + p_shader->canvas_item.uses_instance_custom = false; + 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); shaders.actions_canvas.render_mode_values["blend_sub"] = Pair(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_SUB); @@ -2332,6 +2337,11 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { shaders.actions_canvas.usage_flag_pointers["COLOR"] = &p_shader->canvas_item.uses_color; shaders.actions_canvas.usage_flag_pointers["VERTEX"] = &p_shader->canvas_item.uses_vertex; + shaders.actions_canvas.usage_flag_pointers["WORLD_MATRIX"] = &p_shader->canvas_item.uses_world_matrix; + shaders.actions_canvas.usage_flag_pointers["EXTRA_MATRIX"] = &p_shader->canvas_item.uses_extra_matrix; + shaders.actions_canvas.usage_flag_pointers["PROJECTION_MATRIX"] = &p_shader->canvas_item.uses_projection_matrix; + shaders.actions_canvas.usage_flag_pointers["INSTANCE_CUSTOM"] = &p_shader->canvas_item.uses_instance_custom; + actions = &shaders.actions_canvas; actions->uniforms = &p_shader->uniforms; @@ -2436,6 +2446,9 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { if (p_shader->canvas_item.uses_vertex) { p_shader->canvas_item.batch_flags |= RasterizerStorageCommon::PREVENT_VERTEX_BAKING; } + if (p_shader->canvas_item.uses_world_matrix | p_shader->canvas_item.uses_extra_matrix | p_shader->canvas_item.uses_projection_matrix | p_shader->canvas_item.uses_instance_custom) { + p_shader->canvas_item.batch_flags |= RasterizerStorageCommon::PREVENT_ITEM_JOINING; + } } //all materials using this shader will have to be invalidated, unfortunately diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index a8800ba49b..f1fed7085e 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -473,6 +473,12 @@ public: bool uses_color; bool uses_vertex; + // all these should disable item joining if used in a custom shader + bool uses_world_matrix; + bool uses_extra_matrix; + bool uses_projection_matrix; + bool uses_instance_custom; + } canvas_item; struct Spatial { diff --git a/drivers/gles_common/rasterizer_storage_common.h b/drivers/gles_common/rasterizer_storage_common.h index e5750de9b9..aa81f2c260 100644 --- a/drivers/gles_common/rasterizer_storage_common.h +++ b/drivers/gles_common/rasterizer_storage_common.h @@ -48,8 +48,11 @@ public: PREVENT_COLOR_BAKING = 1 << 0, PREVENT_VERTEX_BAKING = 1 << 1, - USE_MODULATE_FVF = 1 << 2, - USE_LARGE_FVF = 1 << 3, + // custom vertex shaders using BUILTINS that vary per item + PREVENT_ITEM_JOINING = 1 << 2, + + USE_MODULATE_FVF = 1 << 3, + USE_LARGE_FVF = 1 << 4, }; enum BatchType : uint16_t {