summaryrefslogtreecommitdiffstats
path: root/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
diff options
context:
space:
mode:
authorDario <dariosamo@gmail.com>2024-03-15 14:13:31 -0300
committerDario <dariosamo@gmail.com>2024-10-02 15:11:58 -0300
commite2c6daf7eff6e0b7e2e8d967e95a9ad56e948231 (patch)
treed37262a01ec645c1e150f6f4612226303b0a9705 /servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
parent1917bc3454e58fc56750b00e04aa25cb94d8d266 (diff)
downloadredot-engine-e2c6daf7eff6e0b7e2e8d967e95a9ad56e948231.tar.gz
Implement asynchronous transfer queues, thread guards on RenderingDevice. Add ubershaders and rework pipeline caches for Forward+ and Mobile.
- Implements asynchronous transfer queues from PR #87590. - Adds ubershaders that can run with specialization constants specified as push constants. - Pipelines with specialization constants can compile in the background. - Added monitoring for pipeline compilations. - Materials and shaders can now be created asynchronously on background threads. - Meshes that are loaded on background threads can also compile pipelines as part of the loading process.
Diffstat (limited to 'servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp')
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp514
1 files changed, 237 insertions, 277 deletions
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 5441e28be0..713659b8dd 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -351,6 +351,23 @@ void RendererCanvasRenderRD::free_polygon(PolygonID p_polygon) {
////////////////////
+static RD::RenderPrimitive _primitive_type_to_render_primitive(RS::PrimitiveType p_primitive) {
+ switch (p_primitive) {
+ case RS::PRIMITIVE_POINTS:
+ return RD::RENDER_PRIMITIVE_POINTS;
+ case RS::PRIMITIVE_LINES:
+ return RD::RENDER_PRIMITIVE_LINES;
+ case RS::PRIMITIVE_LINE_STRIP:
+ return RD::RENDER_PRIMITIVE_LINESTRIPS;
+ case RS::PRIMITIVE_TRIANGLES:
+ return RD::RENDER_PRIMITIVE_TRIANGLES;
+ case RS::PRIMITIVE_TRIANGLE_STRIP:
+ return RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS;
+ default:
+ return RD::RENDER_PRIMITIVE_MAX;
+ }
+}
+
_FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primitive, uint32_t p_indices) {
static const uint32_t divisor[RS::PRIMITIVE_MAX] = { 1, 2, 1, 3, 1 };
static const uint32_t subtractor[RS::PRIMITIVE_MAX] = { 0, 0, 1, 0, 1 };
@@ -450,6 +467,42 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
return uniform_set;
}
+RID RendererCanvasRenderRD::_get_pipeline_specialization_or_ubershader(CanvasShaderData *p_shader_data, PipelineKey &r_pipeline_key, PushConstant &r_push_constant, RID p_mesh_instance, void *p_surface, uint32_t p_surface_index, RID *r_vertex_array) {
+ r_pipeline_key.ubershader = 0;
+
+ const uint32_t ubershader_iterations = 1;
+ while (r_pipeline_key.ubershader < ubershader_iterations) {
+ if (r_vertex_array != nullptr) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+ uint64_t input_mask = p_shader_data->get_vertex_input_mask(r_pipeline_key.variant, r_pipeline_key.ubershader);
+ if (p_mesh_instance.is_valid()) {
+ mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(p_mesh_instance, p_surface_index, input_mask, false, *r_vertex_array, r_pipeline_key.vertex_format_id);
+ } else {
+ mesh_storage->mesh_surface_get_vertex_arrays_and_format(p_surface, input_mask, false, *r_vertex_array, r_pipeline_key.vertex_format_id);
+ }
+ }
+
+ if (r_pipeline_key.ubershader) {
+ r_push_constant.shader_specialization = r_pipeline_key.shader_specialization;
+ r_pipeline_key.shader_specialization = {};
+ } else {
+ r_push_constant.shader_specialization = {};
+ }
+
+ bool wait_for_compilation = r_pipeline_key.ubershader || ubershader_iterations == 1;
+ RS::PipelineSource source = RS::PIPELINE_SOURCE_CANVAS;
+ RID pipeline = p_shader_data->pipeline_hash_map.get_pipeline(r_pipeline_key, r_pipeline_key.hash(), wait_for_compilation, source);
+ if (pipeline.is_valid()) {
+ return pipeline;
+ }
+
+ r_pipeline_key.ubershader++;
+ }
+
+ // This case should never be reached unless the shader wasn't available.
+ return RID();
+}
+
void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used, RenderingMethod::RenderInfo *r_render_info) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
@@ -717,7 +770,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (material.is_valid()) {
CanvasMaterialData *md = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::MaterialStorage::SHADER_TYPE_2D));
- if (md && md->shader_data->valid) {
+ if (md && md->shader_data->is_valid()) {
if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) {
if (!material_screen_texture_cached) {
backbuffer_copy = true;
@@ -1355,17 +1408,72 @@ void RendererCanvasRenderRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::
oc->cull_mode = p_mode;
}
+void RendererCanvasRenderRD::CanvasShaderData::_clear_vertex_input_mask_cache() {
+ for (uint32_t i = 0; i < VERTEX_INPUT_MASKS_SIZE; i++) {
+ vertex_input_masks[i].store(0);
+ }
+}
+
+void RendererCanvasRenderRD::CanvasShaderData::_create_pipeline(PipelineKey p_pipeline_key) {
+#if PRINT_PIPELINE_COMPILATION_KEYS
+ print_line(
+ "HASH:", p_pipeline_key.hash(),
+ "VERSION:", version,
+ "VARIANT:", p_pipeline_key.variant,
+ "FRAMEBUFFER:", p_pipeline_key.framebuffer_format_id,
+ "VERTEX:", p_pipeline_key.vertex_format_id,
+ "PRIMITIVE:", p_pipeline_key.render_primitive,
+ "SPEC PACKED #0:", p_pipeline_key.shader_specialization.packed_0,
+ "LCD:", p_pipeline_key.lcd_blend);
+#endif
+
+ RendererRD::MaterialStorage::ShaderData::BlendMode blend_mode_rd = RendererRD::MaterialStorage::ShaderData::BlendMode(blend_mode);
+ RD::PipelineColorBlendState blend_state;
+ RD::PipelineColorBlendState::Attachment attachment;
+ uint32_t dynamic_state_flags = 0;
+ if (p_pipeline_key.lcd_blend) {
+ attachment.enable_blend = true;
+ attachment.alpha_blend_op = RD::BLEND_OP_ADD;
+ attachment.color_blend_op = RD::BLEND_OP_ADD;
+ attachment.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR;
+ attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
+ attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ dynamic_state_flags = RD::DYNAMIC_STATE_BLEND_CONSTANTS;
+ } else {
+ attachment = RendererRD::MaterialStorage::ShaderData::blend_mode_to_blend_attachment(blend_mode_rd);
+ }
+
+ blend_state.attachments.push_back(attachment);
+
+ // Convert the specialization from the key to pipeline specialization constants.
+ Vector<RD::PipelineSpecializationConstant> specialization_constants;
+ RD::PipelineSpecializationConstant sc;
+ sc.constant_id = 0;
+ sc.int_value = p_pipeline_key.shader_specialization.packed_0;
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
+ specialization_constants.push_back(sc);
+
+ RID shader_rid = get_shader(p_pipeline_key.variant, p_pipeline_key.ubershader);
+ ERR_FAIL_COND(shader_rid.is_null());
+
+ RID pipeline = RD::get_singleton()->render_pipeline_create(shader_rid, p_pipeline_key.framebuffer_format_id, p_pipeline_key.vertex_format_id, p_pipeline_key.render_primitive, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, dynamic_state_flags, 0, specialization_constants);
+ ERR_FAIL_COND(pipeline.is_null());
+
+ pipeline_hash_map.add_compiled_pipeline(p_pipeline_key.hash(), pipeline);
+}
+
void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
//compile
code = p_code;
- valid = false;
ubo_size = 0;
uniforms.clear();
uses_screen_texture = false;
uses_screen_texture_mipmaps = false;
uses_sdf = false;
uses_time = false;
+ _clear_vertex_input_mask_cache();
if (code.is_empty()) {
return; //just invalid, but no error
@@ -1373,7 +1481,7 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
ShaderCompiler::GeneratedCode gen_code;
- int blend_mode = BLEND_MODE_MIX;
+ blend_mode = BLEND_MODE_MIX;
ShaderCompiler::IdentifierActions actions;
actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
@@ -1384,7 +1492,7 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX);
actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_mode, BLEND_MODE_SUB);
actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MUL);
- actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PMALPHA);
+ actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PREMULTIPLIED_ALPHA);
actions.render_mode_values["blend_disabled"] = Pair<int *, int>(&blend_mode, BLEND_MODE_DISABLED);
actions.usage_flag_pointers["texture_sdf"] = &uses_sdf;
@@ -1393,6 +1501,7 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
actions.uniforms = &uniforms;
RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
+ MutexLock lock(canvas_singleton->shader.mutex);
Error err = canvas_singleton->shader.compiler.compile(RS::SHADER_CANVAS_ITEM, code, &actions, path, gen_code);
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
@@ -1400,6 +1509,8 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
uses_screen_texture = gen_code.uses_screen_texture;
+ pipeline_hash_map.clear_pipelines();
+
if (version.is_null()) {
version = canvas_singleton->shader.canvas_shader.version_create();
}
@@ -1422,168 +1533,70 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
canvas_singleton->shader.canvas_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
- ERR_FAIL_COND(!canvas_singleton->shader.canvas_shader.version_is_valid(version));
ubo_size = gen_code.uniform_total_size;
ubo_offsets = gen_code.uniform_offsets;
texture_uniforms = gen_code.texture_uniforms;
+}
- //update them pipelines
-
- RD::PipelineColorBlendState::Attachment attachment;
-
- switch (blend_mode) {
- case BLEND_MODE_DISABLED: {
- // nothing to do here, disabled by default
-
- } break;
- case BLEND_MODE_MIX: {
- attachment.enable_blend = true;
- attachment.color_blend_op = RD::BLEND_OP_ADD;
- attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
- attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
-
- attachment.alpha_blend_op = RD::BLEND_OP_ADD;
- attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
- attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
-
- } break;
- case BLEND_MODE_ADD: {
- attachment.enable_blend = true;
- attachment.alpha_blend_op = RD::BLEND_OP_ADD;
- attachment.color_blend_op = RD::BLEND_OP_ADD;
- attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
- attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
- attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
- attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
-
- } break;
- case BLEND_MODE_SUB: {
- attachment.enable_blend = true;
- attachment.alpha_blend_op = RD::BLEND_OP_REVERSE_SUBTRACT;
- attachment.color_blend_op = RD::BLEND_OP_REVERSE_SUBTRACT;
- attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
- attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
- attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
- attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+bool RendererCanvasRenderRD::CanvasShaderData::is_animated() const {
+ return false;
+}
- } break;
- case BLEND_MODE_MUL: {
- attachment.enable_blend = true;
- attachment.alpha_blend_op = RD::BLEND_OP_ADD;
- attachment.color_blend_op = RD::BLEND_OP_ADD;
- attachment.src_color_blend_factor = RD::BLEND_FACTOR_DST_COLOR;
- attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ZERO;
- attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_DST_ALPHA;
- attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;
+bool RendererCanvasRenderRD::CanvasShaderData::casts_shadows() const {
+ return false;
+}
- } break;
- case BLEND_MODE_PMALPHA: {
- attachment.enable_blend = true;
- attachment.alpha_blend_op = RD::BLEND_OP_ADD;
- attachment.color_blend_op = RD::BLEND_OP_ADD;
- attachment.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
- attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
- attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
- attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+RS::ShaderNativeSourceCode RendererCanvasRenderRD::CanvasShaderData::get_native_source_code() const {
+ RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
+ MutexLock lock(canvas_singleton->shader.mutex);
+ return canvas_singleton->shader.canvas_shader.version_get_native_source_code(version);
+}
- } break;
+RID RendererCanvasRenderRD::CanvasShaderData::get_shader(ShaderVariant p_shader_variant, bool p_ubershader) const {
+ if (version.is_valid()) {
+ uint32_t variant_index = p_shader_variant + (p_ubershader ? SHADER_VARIANT_MAX : 0);
+ RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
+ MutexLock lock(canvas_singleton->shader.mutex);
+ return canvas_singleton->shader.canvas_shader.version_get_shader(version, variant_index);
+ } else {
+ return RID();
}
+}
- RD::PipelineColorBlendState blend_state;
- blend_state.attachments.push_back(attachment);
+uint64_t RendererCanvasRenderRD::CanvasShaderData::get_vertex_input_mask(ShaderVariant p_shader_variant, bool p_ubershader) {
+ // Vertex input masks require knowledge of the shader. Since querying the shader can be expensive due to high contention and the necessary mutex, we cache the result instead.
+ uint32_t input_mask_index = p_shader_variant + (p_ubershader ? SHADER_VARIANT_MAX : 0);
+ uint64_t input_mask = vertex_input_masks[input_mask_index].load(std::memory_order_relaxed);
+ if (input_mask == 0) {
+ RID shader_rid = get_shader(p_shader_variant, p_ubershader);
+ ERR_FAIL_COND_V(shader_rid.is_null(), 0);
- RD::PipelineColorBlendState::Attachment attachment_lcd;
- attachment_lcd.enable_blend = true;
- attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD;
- attachment_lcd.color_blend_op = RD::BLEND_OP_ADD;
- attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR;
- attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
- attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
- attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
-
- RD::PipelineColorBlendState blend_state_lcd;
- blend_state_lcd.attachments.push_back(attachment_lcd);
-
- //update pipelines
-
- for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) {
- for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) {
- RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = {
- RD::RENDER_PRIMITIVE_TRIANGLES,
- RD::RENDER_PRIMITIVE_TRIANGLES,
- RD::RENDER_PRIMITIVE_TRIANGLES,
- RD::RENDER_PRIMITIVE_LINES,
- RD::RENDER_PRIMITIVE_POINTS,
- RD::RENDER_PRIMITIVE_TRIANGLES,
- RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS,
- RD::RENDER_PRIMITIVE_LINES,
- RD::RENDER_PRIMITIVE_LINESTRIPS,
- RD::RENDER_PRIMITIVE_POINTS,
- RD::RENDER_PRIMITIVE_TRIANGLES,
- };
-
- ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = {
- {
- //non lit
- SHADER_VARIANT_QUAD,
- SHADER_VARIANT_NINEPATCH,
- SHADER_VARIANT_PRIMITIVE,
- SHADER_VARIANT_PRIMITIVE,
- SHADER_VARIANT_PRIMITIVE_POINTS,
- SHADER_VARIANT_ATTRIBUTES,
- SHADER_VARIANT_ATTRIBUTES,
- SHADER_VARIANT_ATTRIBUTES,
- SHADER_VARIANT_ATTRIBUTES,
- SHADER_VARIANT_ATTRIBUTES_POINTS,
- SHADER_VARIANT_QUAD,
- },
- {
- //lit
- SHADER_VARIANT_QUAD_LIGHT,
- SHADER_VARIANT_NINEPATCH_LIGHT,
- SHADER_VARIANT_PRIMITIVE_LIGHT,
- SHADER_VARIANT_PRIMITIVE_LIGHT,
- SHADER_VARIANT_PRIMITIVE_POINTS_LIGHT,
- SHADER_VARIANT_ATTRIBUTES_LIGHT,
- SHADER_VARIANT_ATTRIBUTES_LIGHT,
- SHADER_VARIANT_ATTRIBUTES_LIGHT,
- SHADER_VARIANT_ATTRIBUTES_LIGHT,
- SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT,
- SHADER_VARIANT_QUAD_LIGHT,
- },
- };
-
- RID shader_variant = canvas_singleton->shader.canvas_shader.version_get_shader(version, shader_variants[i][j]);
- if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) {
- pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS);
- } else {
- pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
- }
- }
+ input_mask = RD::get_singleton()->shader_get_vertex_input_attribute_mask(shader_rid);
+ vertex_input_masks[input_mask_index].store(input_mask, std::memory_order_relaxed);
}
- valid = true;
-}
-
-bool RendererCanvasRenderRD::CanvasShaderData::is_animated() const {
- return false;
+ return input_mask;
}
-bool RendererCanvasRenderRD::CanvasShaderData::casts_shadows() const {
- return false;
+bool RendererCanvasRenderRD::CanvasShaderData::is_valid() const {
+ RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
+ MutexLock lock(canvas_singleton->shader.mutex);
+ return canvas_singleton->shader.canvas_shader.version_is_valid(version);
}
-RS::ShaderNativeSourceCode RendererCanvasRenderRD::CanvasShaderData::get_native_source_code() const {
+RendererCanvasRenderRD::CanvasShaderData::CanvasShaderData() {
RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
- return canvas_singleton->shader.canvas_shader.version_get_native_source_code(version);
+ pipeline_hash_map.set_creation_object_and_function(this, &CanvasShaderData::_create_pipeline);
+ pipeline_hash_map.set_compilations(&canvas_singleton->shader.pipeline_compilations[0], &canvas_singleton->shader.mutex);
}
RendererCanvasRenderRD::CanvasShaderData::~CanvasShaderData() {
- RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
- ERR_FAIL_NULL(canvas_singleton);
- //pipeline variants will clear themselves if shader is gone
+ pipeline_hash_map.clear_pipelines();
+
if (version.is_valid()) {
+ RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
+ MutexLock lock(canvas_singleton->shader.mutex);
canvas_singleton->shader.canvas_shader.version_free(version);
}
}
@@ -1595,8 +1608,10 @@ RendererRD::MaterialStorage::ShaderData *RendererCanvasRenderRD::_create_shader_
bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
- bool uniform_set_changed = update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET, true, false);
- bool uniform_set_srgb_changed = update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set_srgb, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET, false, false);
+ MutexLock lock(canvas_singleton->shader.mutex);
+ RID shader_to_update = canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0);
+ bool uniform_set_changed = update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_to_update, MATERIAL_UNIFORM_SET, true, false);
+ bool uniform_set_srgb_changed = update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set_srgb, shader_to_update, MATERIAL_UNIFORM_SET, false, false);
return uniform_set_changed || uniform_set_srgb_changed;
}
@@ -1647,107 +1662,23 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
state.light_uniforms = memnew_arr(LightUniform, state.max_lights_per_render);
Vector<String> variants;
- //non light variants
- variants.push_back(""); //none by default is first variant
- variants.push_back("#define USE_NINEPATCH\n"); //ninepatch is the second variant
- variants.push_back("#define USE_PRIMITIVE\n"); //primitive is the third
- variants.push_back("#define USE_PRIMITIVE\n#define USE_POINT_SIZE\n"); //points need point size
- variants.push_back("#define USE_ATTRIBUTES\n"); // attributes for vertex arrays
- variants.push_back("#define USE_ATTRIBUTES\n#define USE_POINT_SIZE\n"); //attributes with point size
- //light variants
- variants.push_back("#define USE_LIGHTING\n"); //none by default is first variant
- variants.push_back("#define USE_LIGHTING\n#define USE_NINEPATCH\n"); //ninepatch is the second variant
- variants.push_back("#define USE_LIGHTING\n#define USE_PRIMITIVE\n"); //primitive is the third
- variants.push_back("#define USE_LIGHTING\n#define USE_PRIMITIVE\n#define USE_POINT_SIZE\n"); //points need point size
- variants.push_back("#define USE_LIGHTING\n#define USE_ATTRIBUTES\n"); // attributes for vertex arrays
- variants.push_back("#define USE_LIGHTING\n#define USE_ATTRIBUTES\n#define USE_POINT_SIZE\n"); //attributes with point size
+ const uint32_t ubershader_iterations = 1;
+ for (uint32_t ubershader = 0; ubershader < ubershader_iterations; ubershader++) {
+ const String base_define = ubershader ? "\n#define UBERSHADER\n" : "";
+ variants.push_back(base_define + ""); // SHADER_VARIANT_QUAD
+ variants.push_back(base_define + "#define USE_NINEPATCH\n"); // SHADER_VARIANT_NINEPATCH
+ variants.push_back(base_define + "#define USE_PRIMITIVE\n"); // SHADER_VARIANT_PRIMITIVE
+ variants.push_back(base_define + "#define USE_PRIMITIVE\n#define USE_POINT_SIZE\n"); // SHADER_VARIANT_PRIMITIVE_POINTS
+ variants.push_back(base_define + "#define USE_ATTRIBUTES\n"); // SHADER_VARIANT_ATTRIBUTES
+ variants.push_back(base_define + "#define USE_ATTRIBUTES\n#define USE_POINT_SIZE\n"); // SHADER_VARIANT_ATTRIBUTES_POINTS
+ }
shader.canvas_shader.initialize(variants, global_defines);
- shader.default_version = shader.canvas_shader.version_create();
- shader.default_version_rd_shader = shader.canvas_shader.version_get_shader(shader.default_version, SHADER_VARIANT_QUAD);
-
- RD::PipelineColorBlendState blend_state;
- RD::PipelineColorBlendState::Attachment blend_attachment;
-
- blend_attachment.enable_blend = true;
- blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
- blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
- blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
-
- blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
- blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
- blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
-
- blend_state.attachments.push_back(blend_attachment);
-
- RD::PipelineColorBlendState::Attachment attachment_lcd;
- attachment_lcd.enable_blend = true;
- attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD;
- attachment_lcd.color_blend_op = RD::BLEND_OP_ADD;
- attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR;
- attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
- attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
- attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
-
- RD::PipelineColorBlendState blend_state_lcd;
- blend_state_lcd.attachments.push_back(attachment_lcd);
-
- for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) {
- for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) {
- RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = {
- RD::RENDER_PRIMITIVE_TRIANGLES,
- RD::RENDER_PRIMITIVE_TRIANGLES,
- RD::RENDER_PRIMITIVE_TRIANGLES,
- RD::RENDER_PRIMITIVE_LINES,
- RD::RENDER_PRIMITIVE_POINTS,
- RD::RENDER_PRIMITIVE_TRIANGLES,
- RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS,
- RD::RENDER_PRIMITIVE_LINES,
- RD::RENDER_PRIMITIVE_LINESTRIPS,
- RD::RENDER_PRIMITIVE_POINTS,
- RD::RENDER_PRIMITIVE_TRIANGLES,
- };
-
- ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = {
- {
- //non lit
- SHADER_VARIANT_QUAD,
- SHADER_VARIANT_NINEPATCH,
- SHADER_VARIANT_PRIMITIVE,
- SHADER_VARIANT_PRIMITIVE,
- SHADER_VARIANT_PRIMITIVE_POINTS,
- SHADER_VARIANT_ATTRIBUTES,
- SHADER_VARIANT_ATTRIBUTES,
- SHADER_VARIANT_ATTRIBUTES,
- SHADER_VARIANT_ATTRIBUTES,
- SHADER_VARIANT_ATTRIBUTES_POINTS,
- SHADER_VARIANT_QUAD,
- },
- {
- //lit
- SHADER_VARIANT_QUAD_LIGHT,
- SHADER_VARIANT_NINEPATCH_LIGHT,
- SHADER_VARIANT_PRIMITIVE_LIGHT,
- SHADER_VARIANT_PRIMITIVE_LIGHT,
- SHADER_VARIANT_PRIMITIVE_POINTS_LIGHT,
- SHADER_VARIANT_ATTRIBUTES_LIGHT,
- SHADER_VARIANT_ATTRIBUTES_LIGHT,
- SHADER_VARIANT_ATTRIBUTES_LIGHT,
- SHADER_VARIANT_ATTRIBUTES_LIGHT,
- SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT,
- SHADER_VARIANT_QUAD_LIGHT,
- },
- };
-
- RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[i][j]);
- if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) {
- shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS);
- } else {
- shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
- }
- }
- }
+ shader.default_version_data = memnew(CanvasShaderData);
+ shader.default_version_data->version = shader.canvas_shader.version_create();
+ shader.default_version_data->blend_mode = RendererRD::MaterialStorage::ShaderData::BLEND_MODE_MIX;
+ shader.default_version_rd_shader = shader.default_version_data->get_shader(SHADER_VARIANT_QUAD, false);
}
{
@@ -2101,6 +2032,12 @@ void RendererCanvasRenderRD::set_debug_redraw(bool p_enabled, double p_time, con
debug_redraw_color = p_color;
}
+uint32_t RendererCanvasRenderRD::get_pipeline_compilations(RS::PipelineSource p_source) {
+ RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
+ MutexLock lock(canvas_singleton->shader.mutex);
+ return shader.pipeline_compilations[p_source];
+}
+
void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer, RenderingMethod::RenderInfo *r_render_info) {
// Record batches
uint32_t instance_index = 0;
@@ -2244,12 +2181,11 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target
}
}
- PipelineVariants *pipeline_variants = &shader.pipeline_variants;
-
+ CanvasShaderData *shader_data = shader.default_version_data;
CanvasMaterialData *material_data = current_batch->material_data;
if (material_data) {
- if (material_data->shader_data->version.is_valid() && material_data->shader_data->valid) {
- pipeline_variants = &material_data->shader_data->pipeline_variants;
+ if (material_data->shader_data->version.is_valid() && material_data->shader_data->is_valid()) {
+ shader_data = material_data->shader_data;
// Update uniform set.
RID uniform_set = texture_storage->render_target_is_using_hdr(p_to_render_target.render_target) ? material_data->uniform_set : material_data->uniform_set_srgb;
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { // Material may not have a uniform set.
@@ -2259,7 +2195,7 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target
}
}
- _render_batch(draw_list, pipeline_variants, fb_format, p_lights, current_batch, r_render_info);
+ _render_batch(draw_list, shader_data, fb_format, p_lights, current_batch, r_render_info);
}
RD::get_singleton()->draw_list_end();
@@ -2291,7 +2227,6 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
uint32_t lights[4] = { 0, 0, 0, 0 };
uint16_t light_count = 0;
- PipelineLightMode light_mode;
{
Light *light = p_lights;
@@ -2313,11 +2248,11 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
base_flags |= light_count << FLAGS_LIGHT_COUNT_SHIFT;
}
- light_mode = (light_count > 0 || using_directional_lights) ? PIPELINE_LIGHT_MODE_ENABLED : PIPELINE_LIGHT_MODE_DISABLED;
+ bool use_lighting = (light_count > 0 || using_directional_lights);
- if (light_mode != r_current_batch->light_mode) {
+ if (use_lighting != r_current_batch->use_lighting) {
r_current_batch = _new_batch(r_batch_broken);
- r_current_batch->light_mode = light_mode;
+ r_current_batch->use_lighting = use_lighting;
}
// new_instance_data should be called after the current_batch is set.
@@ -2369,7 +2304,8 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
r_current_batch->command_type = Item::Command::TYPE_RECT;
r_current_batch->command = c;
// default variant
- r_current_batch->pipeline_variant = PIPELINE_VARIANT_QUAD;
+ r_current_batch->shader_variant = SHADER_VARIANT_QUAD;
+ r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES;
}
if (bool(rect->flags & CANVAS_RECT_TILE)) {
@@ -2397,7 +2333,8 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
r_current_batch = _new_batch(r_batch_broken);
r_current_batch->has_blend = has_blend;
r_current_batch->modulate = modulated;
- r_current_batch->pipeline_variant = has_blend ? PIPELINE_VARIANT_QUAD_LCD_BLEND : PIPELINE_VARIANT_QUAD;
+ r_current_batch->shader_variant = SHADER_VARIANT_QUAD;
+ r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES;
}
InstanceData *instance_data = new_instance_data();
@@ -2486,7 +2423,8 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
r_current_batch->command_type = Item::Command::TYPE_NINEPATCH;
r_current_batch->command = c;
r_current_batch->has_blend = false;
- r_current_batch->pipeline_variant = PipelineVariant::PIPELINE_VARIANT_NINEPATCH;
+ r_current_batch->shader_variant = SHADER_VARIANT_NINEPATCH;
+ r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES;
}
TextureState tex_state(np->texture, texture_filter, texture_repeat, false, use_linear_colors);
@@ -2567,9 +2505,9 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
// pipeline variant
{
- static const PipelineVariant variant[RS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP };
ERR_CONTINUE(polygon->primitive < 0 || polygon->primitive >= RS::PRIMITIVE_MAX);
- r_current_batch->pipeline_variant = variant[polygon->primitive];
+ r_current_batch->shader_variant = polygon->primitive == RS::PRIMITIVE_POINTS ? SHADER_VARIANT_ATTRIBUTES_POINTS : SHADER_VARIANT_ATTRIBUTES;
+ r_current_batch->render_primitive = _primitive_type_to_render_primitive(polygon->primitive);
}
InstanceData *instance_data = new_instance_data();
@@ -2597,9 +2535,26 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
r_current_batch->command = c;
r_current_batch->primitive_points = primitive->point_count;
- static const PipelineVariant variant[4] = { PIPELINE_VARIANT_PRIMITIVE_POINTS, PIPELINE_VARIANT_PRIMITIVE_LINES, PIPELINE_VARIANT_PRIMITIVE_TRIANGLES, PIPELINE_VARIANT_PRIMITIVE_TRIANGLES };
ERR_CONTINUE(primitive->point_count == 0 || primitive->point_count > 4);
- r_current_batch->pipeline_variant = variant[primitive->point_count - 1];
+
+ switch (primitive->point_count) {
+ case 1:
+ r_current_batch->shader_variant = SHADER_VARIANT_PRIMITIVE_POINTS;
+ r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_POINTS;
+ break;
+ case 2:
+ r_current_batch->shader_variant = SHADER_VARIANT_PRIMITIVE;
+ r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_LINES;
+ break;
+ case 3:
+ case 4:
+ r_current_batch->shader_variant = SHADER_VARIANT_PRIMITIVE;
+ r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES;
+ break;
+ default:
+ // Unknown point count.
+ break;
+ };
TextureState tex_state(primitive->texture, texture_filter, texture_repeat, false, use_linear_colors);
if (tex_state != r_current_batch->tex_info.state) {
@@ -2795,7 +2750,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
}
}
-void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineVariants *p_pipeline_variants, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info) {
+void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasShaderData *p_shader_data, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
@@ -2816,17 +2771,24 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV
}
}
+ RID pipeline;
+ PipelineKey pipeline_key;
+ PushConstant push_constant;
+ pipeline_key.framebuffer_format_id = p_framebuffer_format;
+ pipeline_key.variant = p_batch->shader_variant;
+ pipeline_key.render_primitive = p_batch->render_primitive;
+ pipeline_key.shader_specialization.use_lighting = p_batch->use_lighting;
+ pipeline_key.lcd_blend = p_batch->has_blend;
+
switch (p_batch->command_type) {
case Item::Command::TYPE_RECT:
case Item::Command::TYPE_NINEPATCH: {
- RID pipeline = p_pipeline_variants->variants[p_batch->light_mode][p_batch->pipeline_variant].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format);
+ pipeline = _get_pipeline_specialization_or_ubershader(p_shader_data, pipeline_key, push_constant);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
if (p_batch->has_blend) {
- DEV_ASSERT(p_batch->pipeline_variant == PIPELINE_VARIANT_QUAD_LCD_BLEND);
RD::get_singleton()->draw_list_set_blend_constants(p_draw_list, p_batch->modulate);
}
- PushConstant push_constant;
push_constant.base_instance_index = p_batch->start;
RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant));
RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array);
@@ -2845,10 +2807,10 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV
PolygonBuffers *pb = polygon_buffers.polygons.getptr(polygon->polygon.polygon_id);
ERR_FAIL_NULL(pb);
- RID pipeline = p_pipeline_variants->variants[p_batch->light_mode][p_batch->pipeline_variant].get_render_pipeline(pb->vertex_format_id, p_framebuffer_format);
+ pipeline_key.vertex_format_id = pb->vertex_format_id;
+ pipeline = _get_pipeline_specialization_or_ubershader(p_shader_data, pipeline_key, push_constant);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
- PushConstant push_constant;
push_constant.base_instance_index = p_batch->start;
RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant));
RD::get_singleton()->draw_list_bind_vertex_array(p_draw_list, pb->vertex_array);
@@ -2867,10 +2829,9 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV
case Item::Command::TYPE_PRIMITIVE: {
const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(p_batch->command);
- RID pipeline = p_pipeline_variants->variants[p_batch->light_mode][p_batch->pipeline_variant].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format);
+ pipeline = _get_pipeline_specialization_or_ubershader(p_shader_data, pipeline_key, push_constant);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
- PushConstant push_constant;
push_constant.base_instance_index = p_batch->start;
RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant));
RD::get_singleton()->draw_list_bind_index_array(p_draw_list, primitive_arrays.index_array[MIN(3u, primitive->point_count) - 1]);
@@ -2933,7 +2894,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV
}
uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh);
- static const PipelineVariant variant[RS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP };
for (uint32_t j = 0; j < surf_count; j++) {
void *surface = mesh_storage->mesh_get_surface(mesh, j);
@@ -2941,7 +2901,7 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV
RS::PrimitiveType primitive = mesh_storage->mesh_surface_get_primitive(surface);
ERR_CONTINUE(primitive < 0 || primitive >= RS::PRIMITIVE_MAX);
- uint64_t input_mask = p_pipeline_variants->variants[p_batch->light_mode][variant[primitive]].get_vertex_input_mask();
+ uint64_t input_mask = p_shader_data->get_vertex_input_mask(pipeline_key.variant, pipeline_key.ubershader);
RID vertex_array;
RD::VertexFormatID vertex_format = RD::INVALID_FORMAT_ID;
@@ -2952,10 +2912,13 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV
mesh_storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, false, vertex_array, vertex_format);
}
- RID pipeline = p_pipeline_variants->variants[p_batch->light_mode][variant[primitive]].get_render_pipeline(vertex_format, p_framebuffer_format);
+ pipeline_key.variant = primitive == RS::PRIMITIVE_POINTS ? SHADER_VARIANT_ATTRIBUTES_POINTS : SHADER_VARIANT_ATTRIBUTES;
+ pipeline_key.render_primitive = _primitive_type_to_render_primitive(primitive);
+ pipeline_key.vertex_format_id = vertex_format;
+
+ pipeline = _get_pipeline_specialization_or_ubershader(p_shader_data, pipeline_key, push_constant);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
- PushConstant push_constant;
push_constant.base_instance_index = p_batch->start;
RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant));
@@ -3105,11 +3068,6 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() {
//this will also automatically clear all pipelines
RD::get_singleton()->free(state.shadow_sampler);
}
- //bindings
-
- //shaders
-
- shader.canvas_shader.version_free(shader.default_version);
//buffers
{
@@ -3132,4 +3090,6 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() {
RendererRD::TextureStorage::get_singleton()->canvas_texture_free(default_canvas_texture);
//pipelines don't need freeing, they are all gone after shaders are gone
+
+ memdelete(shader.default_version_data);
}