From c810ea4c1b2e813fa4758f51ae2c074797ab5326 Mon Sep 17 00:00:00 2001 From: clayjohn Date: Wed, 24 Jan 2024 16:35:37 -0800 Subject: [PATCH] Reduce shader permutations in the compatibility backend --- drivers/gles3/rasterizer_canvas_gles3.cpp | 32 ++++++++++++++--------- drivers/gles3/rasterizer_canvas_gles3.h | 4 +-- drivers/gles3/shaders/canvas.glsl | 11 ++++---- drivers/gles3/shaders/sky.glsl | 6 ++--- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 0138f99d508..2fd3f7d7e27 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -687,6 +687,8 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou state.current_tex = RID(); + const uint64_t base_specialization = GLES3::Config::get_singleton()->float_texture_supported ? 0 : CanvasShaderGLES3::USE_RGBA_SHADOWS; + for (uint32_t i = 0; i <= state.current_batch_index; i++) { // Skipping when there is no instances. if (state.canvas_instance_batches[i].instance_count == 0) { @@ -705,10 +707,9 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou } GLES3::CanvasMaterialData *material_data = state.canvas_instance_batches[i].material_data; - CanvasShaderGLES3::ShaderVariant variant = state.canvas_instance_batches[i].shader_variant; - uint64_t specialization = 0; - specialization |= uint64_t(state.canvas_instance_batches[i].lights_disabled); - specialization |= uint64_t(!GLES3::Config::get_singleton()->float_texture_supported) << 1; + CanvasShaderGLES3::ShaderVariant variant = CanvasShaderGLES3::MODE_DEFAULT; + uint64_t specialization = state.canvas_instance_batches[i].specialization; + specialization |= base_specialization; RID shader_version = data.canvas_shader_default_version; if (material_data) { @@ -810,6 +811,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, const Point2 &p_repeat_offset) { RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? state.default_filter : p_item->texture_filter; + const uint64_t specialization_command_mask = ~(CanvasShaderGLES3::USE_NINEPATCH | CanvasShaderGLES3::USE_PRIMITIVE | CanvasShaderGLES3::USE_ATTRIBUTES | CanvasShaderGLES3::USE_INSTANCING); if (texture_filter != state.canvas_instance_batches[state.current_batch_index].filter) { _new_batch(r_batch_broken); @@ -868,9 +870,9 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend bool lights_disabled = light_count == 0 && !state.using_directional_lights; - if (lights_disabled != state.canvas_instance_batches[state.current_batch_index].lights_disabled) { + if (lights_disabled != bool(state.canvas_instance_batches[state.current_batch_index].specialization & CanvasShaderGLES3::DISABLE_LIGHTING)) { _new_batch(r_batch_broken); - state.canvas_instance_batches[state.current_batch_index].lights_disabled = lights_disabled; + state.canvas_instance_batches[state.current_batch_index].specialization ^= CanvasShaderGLES3::DISABLE_LIGHTING; } const Item::Command *c = p_item->commands; @@ -936,7 +938,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.canvas_instance_batches[state.current_batch_index].tex = rect->texture; state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_RECT; state.canvas_instance_batches[state.current_batch_index].command = c; - state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_QUAD; + state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask; } _prepare_canvas_texture(rect->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size); @@ -1026,7 +1028,8 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.canvas_instance_batches[state.current_batch_index].tex = np->texture; state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_NINEPATCH; state.canvas_instance_batches[state.current_batch_index].command = c; - state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_NINEPATCH; + state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask; + state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_NINEPATCH; } _prepare_canvas_texture(np->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size); @@ -1092,7 +1095,8 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.canvas_instance_batches[state.current_batch_index].tex = polygon->texture; state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_POLYGON; state.canvas_instance_batches[state.current_batch_index].command = c; - state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_ATTRIBUTES; + state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask; + state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_ATTRIBUTES; _prepare_canvas_texture(polygon->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size); @@ -1119,7 +1123,8 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.canvas_instance_batches[state.current_batch_index].primitive_points = primitive->point_count; state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_PRIMITIVE; state.canvas_instance_batches[state.current_batch_index].command = c; - state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_PRIMITIVE; + state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask; + state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_PRIMITIVE; } _prepare_canvas_texture(state.canvas_instance_batches[state.current_batch_index].tex, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size); @@ -1164,7 +1169,8 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend _new_batch(r_batch_broken); Color modulate(1, 1, 1, 1); - state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_ATTRIBUTES; + state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask; + state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_ATTRIBUTES; if (c->type == Item::Command::TYPE_MESH) { const Item::CommandMesh *m = static_cast(c); state.canvas_instance_batches[state.current_batch_index].tex = m->texture; @@ -1174,7 +1180,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend } else if (c->type == Item::Command::TYPE_MULTIMESH) { const Item::CommandMultiMesh *mm = static_cast(c); state.canvas_instance_batches[state.current_batch_index].tex = mm->texture; - state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED; + state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_INSTANCING; if (GLES3::MeshStorage::get_singleton()->multimesh_uses_colors(mm->multimesh)) { state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_COLORS; @@ -1189,7 +1195,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend const Item::CommandParticles *pt = static_cast(c); RID particles = pt->particles; state.canvas_instance_batches[state.current_batch_index].tex = pt->texture; - state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED; + state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_INSTANCING; state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_COLORS; state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index a82e2713e02..b9d9a44e2aa 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -273,14 +273,12 @@ public: RID material; GLES3::CanvasMaterialData *material_data = nullptr; - CanvasShaderGLES3::ShaderVariant shader_variant = CanvasShaderGLES3::MODE_QUAD; uint64_t vertex_input_mask = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_COLOR | RS::ARRAY_FORMAT_TEX_UV; + uint64_t specialization = 0; const Item::Command *command = nullptr; Item::Command::Type command_type = Item::Command::TYPE_ANIMATION_SLICE; // Can default to any type that doesn't form a batch. uint32_t primitive_points = 0; - - bool lights_disabled = false; }; // DataBuffer contains our per-frame data. I.e. the resources that are updated each frame. diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 5e7fb3b3389..1ac289d5a24 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -1,17 +1,16 @@ /* clang-format off */ #[modes] -mode_quad = -mode_ninepatch = #define USE_NINEPATCH -mode_primitive = #define USE_PRIMITIVE -mode_attributes = #define USE_ATTRIBUTES -mode_instanced = #define USE_ATTRIBUTES \n#define USE_INSTANCING +mode_default = #[specializations] DISABLE_LIGHTING = true USE_RGBA_SHADOWS = false -SINGLE_INSTANCE = false +USE_NINEPATCH = false +USE_PRIMITIVE = false +USE_ATTRIBUTES = false +USE_INSTANCING = false #[vertex] diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl index 186b630bc85..043023aee0d 100644 --- a/drivers/gles3/shaders/sky.glsl +++ b/drivers/gles3/shaders/sky.glsl @@ -2,17 +2,15 @@ #[modes] mode_background = -mode_half_res = #define USE_HALF_RES_PASS -mode_quarter_res = #define USE_QUARTER_RES_PASS mode_cubemap = #define USE_CUBEMAP_PASS -mode_cubemap_half_res = #define USE_CUBEMAP_PASS \n#define USE_HALF_RES_PASS -mode_cubemap_quarter_res = #define USE_CUBEMAP_PASS \n#define USE_QUARTER_RES_PASS #[specializations] USE_MULTIVIEW = false USE_INVERTED_Y = true APPLY_TONEMAPPING = true +USE_QUARTER_RES_PASS = false +USE_HALF_RES_PASS = false #[vertex]