From 7f3a19789cada66135413341bdad184331344722 Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Wed, 17 Mar 2021 15:09:50 +0000 Subject: [PATCH] Batching - separate single item from large fvf logic Trying to use the old `hardware_transform` flag to combine the new large_fvf has lead to several bugs. So here the logic is broken out into 2 separate components, single item and large_fvf. The old `hardware_transform` name also no longer makes sense, as there are now 3 transform paths: Software (CPU) Hardware (uniform) Hardware (attribute) --- drivers/gles2/rasterizer_canvas_gles2.cpp | 4 +-- drivers/gles3/rasterizer_canvas_gles3.cpp | 2 +- drivers/gles_common/batch_diagnose.inc | 6 ++--- .../gles_common/rasterizer_canvas_batcher.h | 26 ++++++++++++------- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index dc3a425ebaa..652d466302a 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -2171,7 +2171,7 @@ void RasterizerCanvasGLES2::render_joined_item(const BItemJoined &p_bij, RenderI // using software transform? // (i.e. don't send the transform matrix, send identity, and either use baked verts, // or large fvf where the transform is done in the shader from transform stored in the fvf.) - if (!p_bij.use_hardware_transform()) { + if (!p_bij.is_single_item()) { state.uniforms.modelview_matrix = Transform2D(); // final_modulate will be baked per item ref so the final_modulate can be an identity color state.uniforms.final_modulate = Color(1, 1, 1, 1); @@ -2196,7 +2196,7 @@ void RasterizerCanvasGLES2::render_joined_item(const BItemJoined &p_bij, RenderI VS::CanvasLightMode mode = VS::CANVAS_LIGHT_MODE_ADD; // we leave this set to 1, 1, 1, 1 if using software because the colors are baked into the vertices - if (p_bij.use_hardware_transform()) { + if (p_bij.is_single_item()) { state.uniforms.final_modulate = ci->final_modulate; // remove the canvas modulate } diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 4eff07d01f7..2e7aab2ad8b 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -1456,7 +1456,7 @@ void RasterizerCanvasGLES3::render_joined_item(const BItemJoined &p_bij, RenderI // using software transform? // (i.e. don't send the transform matrix, send identity, and either use baked verts, // or large fvf where the transform is done in the shader from transform stored in the fvf.) - if (!p_bij.use_hardware_transform()) { + if (!p_bij.is_single_item()) { state.final_transform = Transform2D(); // final_modulate will be baked per item ref so the final_modulate can be an identity color state.canvas_item_modulate = Color(1, 1, 1, 1); diff --git a/drivers/gles_common/batch_diagnose.inc b/drivers/gles_common/batch_diagnose.inc index 1eb0052dc34..9c5d5ae0f50 100644 --- a/drivers/gles_common/batch_diagnose.inc +++ b/drivers/gles_common/batch_diagnose.inc @@ -43,10 +43,8 @@ void _debug_write_garbage() { String _diagnose_make_item_joined_string(const BItemJoined &p_bij) const { String sz; - if (p_bij.use_hardware_transform()) { - sz = "hxform"; - } else { - sz = "sxform"; + if (p_bij.use_attrib_transform()) { + sz = "attrib_xform"; } sz += _diagnose_batch_flags_to_string(p_bij.flags); diff --git a/drivers/gles_common/rasterizer_canvas_batcher.h b/drivers/gles_common/rasterizer_canvas_batcher.h index fce51a72895..9e205ce2c2e 100644 --- a/drivers/gles_common/rasterizer_canvas_batcher.h +++ b/drivers/gles_common/rasterizer_canvas_batcher.h @@ -227,7 +227,8 @@ public: // we are always splitting items with lots of commands, // and items with unhandled primitives (default) - bool use_hardware_transform() const { return (num_item_refs == 1) && !(flags & RasterizerStorageCommon::USE_LARGE_FVF); } + bool is_single_item() const { return (num_item_refs == 1); } + bool use_attrib_transform() const { return flags & RasterizerStorageCommon::USE_LARGE_FVF; } }; struct BItemRef { @@ -441,9 +442,12 @@ public: sequence_batch_type_flags = 0; } - void reset_joined_item(bool p_use_hardware_transform) { + void reset_joined_item(bool p_is_single_item, bool p_use_attrib_transform) { reset_flush(); - use_hardware_transform = p_use_hardware_transform; + is_single_item = p_is_single_item; + use_attrib_transform = p_use_attrib_transform; + use_software_transform = !is_single_item && !use_attrib_transform; + extra_matrix_sent = false; } @@ -453,7 +457,11 @@ public: Batch *curr_batch; int batch_tex_id; - bool use_hardware_transform; + + bool is_single_item; + bool use_attrib_transform; + bool use_software_transform; + bool contract_uvs; Vector2 texpixel_size; Color final_modulate; @@ -1849,7 +1857,7 @@ bool C_PREAMBLE::_prefill_rect(RasterizerCanvas::Item::CommandRect *rect, FillSt // because joined items with more than 1, the command * will be incorrect // NOTE - this is assuming that use_hardware_transform means that it is a non-joined item!! // If that assumption is incorrect this will go horribly wrong. - if (bdata.settings_use_single_rect_fallback && r_fill_state.use_hardware_transform) { + if (bdata.settings_use_single_rect_fallback && r_fill_state.is_single_item) { bool is_single_rect = false; int command_num_next = command_num + 1; if (command_num_next < command_count) { @@ -2156,7 +2164,7 @@ PREAMBLE(bool)::prefill_joined_item(FillState &r_fill_state, int &r_command_star // checking the color for not being white makes it 92/90 times faster in the case where it is white bool multiply_final_modulate = false; - if (!r_fill_state.use_hardware_transform && (r_fill_state.final_modulate != Color(1, 1, 1, 1))) { + if (!r_fill_state.is_single_item && (r_fill_state.final_modulate != Color(1, 1, 1, 1))) { multiply_final_modulate = true; } @@ -2210,7 +2218,7 @@ PREAMBLE(bool)::prefill_joined_item(FillState &r_fill_state, int &r_command_star RasterizerCanvas::Item::CommandTransform *transform = static_cast(command); const Transform2D &extra_matrix = transform->xform; - if (r_fill_state.use_hardware_transform) { + if (r_fill_state.is_single_item && !r_fill_state.use_attrib_transform) { // if we are using hardware transform mode, we have already sent the final transform, // so we only want to software transform the extra matrix r_fill_state.transform_combined = extra_matrix; @@ -2447,7 +2455,7 @@ PREAMBLE(void)::render_joined_item_commands(const BItemJoined &p_bij, Rasterizer // fill_state and bdata have once off setup per joined item, and a smaller reset on flush FillState fill_state; - fill_state.reset_joined_item(p_bij.use_hardware_transform()); + fill_state.reset_joined_item(p_bij.is_single_item(), p_bij.use_attrib_transform()); bdata.reset_joined_item(); @@ -2489,7 +2497,7 @@ PREAMBLE(void)::render_joined_item_commands(const BItemJoined &p_bij, Rasterizer // decide the initial transform mode, and make a backup // in orig_transform_mode in case we need to switch back - if (!fill_state.use_hardware_transform) { + if (fill_state.use_software_transform) { fill_state.transform_mode = _find_transform_mode(fill_state.transform_combined); } else { fill_state.transform_mode = TM_NONE;