You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-04 12:00:25 +00:00
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.
This commit is contained in:
@@ -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,148 +1533,10 @@ 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;
|
||||
|
||||
} 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;
|
||||
|
||||
} 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;
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
RD::PipelineColorBlendState blend_state;
|
||||
blend_state.attachments.push_back(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);
|
||||
|
||||
//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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
valid = true;
|
||||
}
|
||||
|
||||
bool RendererCanvasRenderRD::CanvasShaderData::is_animated() const {
|
||||
@@ -1576,14 +1549,54 @@ bool RendererCanvasRenderRD::CanvasShaderData::casts_shadows() const {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return input_mask;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
RendererCanvasRenderRD::CanvasShaderData::CanvasShaderData() {
|
||||
RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
|
||||
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() {
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user