Prevent item joining with custom shaders using selected BUILTINs

Large FVF allows batching of many custom shaders, but should not join items which have shaders that utilize BUILTINs which would change for each item, because these will not be sent individually, and all joined items would wrongly use the values from the first joined item.
This commit is contained in:
lawnjelly 2020-11-19 15:09:33 +00:00
parent 3a8e1f324f
commit 1394df3188
7 changed files with 106 additions and 45 deletions

View file

@ -1372,33 +1372,42 @@ bool RasterizerCanvasGLES2::try_join_item(Item *p_ci, RenderItemState &r_ris, bo
bdata.joined_item_batch_flags = 0;
if (r_ris.shader_cache) {
unsigned int and_flags = r_ris.shader_cache->canvas_item.batch_flags & (RasterizerStorageCommon::PREVENT_COLOR_BAKING | RasterizerStorageCommon::PREVENT_VERTEX_BAKING);
unsigned int and_flags = r_ris.shader_cache->canvas_item.batch_flags & (RasterizerStorageCommon::PREVENT_COLOR_BAKING | RasterizerStorageCommon::PREVENT_VERTEX_BAKING | RasterizerStorageCommon::PREVENT_ITEM_JOINING);
if (and_flags) {
bool use_larger_fvfs = true;
if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) {
// in some circumstances, if the modulate is identity, we still allow baking because reading modulate / color
// will still be okay to do in the shader with no ill effects
if (r_ris.final_modulate == Color(1, 1, 1, 1)) {
use_larger_fvfs = false;
}
}
// new .. always use large FVF
if (use_larger_fvfs) {
if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) {
bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_MODULATE_FVF;
} else {
// we need to save on the joined item that it should use large fvf.
// This info will then be used in filling and rendering
bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_LARGE_FVF;
}
// special case for preventing item joining altogether
if (and_flags & RasterizerStorageCommon::PREVENT_ITEM_JOINING) {
join = false;
//r_batch_break = true; // don't think we need a batch break
// save the flags so that they don't need to be recalculated in the 2nd pass
bdata.joined_item_batch_flags |= r_ris.shader_cache->canvas_item.batch_flags;
}
} else {
/*
bool use_larger_fvfs = true;
if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) {
// in some circumstances, if the modulate is identity, we still allow baking because reading modulate / color
// will still be okay to do in the shader with no ill effects
if (r_ris.final_modulate == Color(1, 1, 1, 1)) {
use_larger_fvfs = false;
}
}
// new .. always use large FVF
if (use_larger_fvfs) {
if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) {
bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_MODULATE_FVF;
} else {
// we need to save on the joined item that it should use large fvf.
// This info will then be used in filling and rendering
bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_LARGE_FVF;
}
bdata.joined_item_batch_flags |= r_ris.shader_cache->canvas_item.batch_flags;
}
/*
if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) {
// in some circumstances, if the modulate is identity, we still allow baking because reading modulate / color
// will still be okay to do in the shader with no ill effects
@ -1424,6 +1433,7 @@ bool RasterizerCanvasGLES2::try_join_item(Item *p_ci, RenderItemState &r_ris, bo
bdata.joined_item_batch_flags |= r_ris.shader_cache->canvas_item.batch_flags;
}
*/
} // if not prevent item joining
}
}

View file

@ -1437,6 +1437,11 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
p_shader->canvas_item.uses_vertex = false;
p_shader->canvas_item.batch_flags = 0;
p_shader->canvas_item.uses_world_matrix = false;
p_shader->canvas_item.uses_extra_matrix = false;
p_shader->canvas_item.uses_projection_matrix = false;
p_shader->canvas_item.uses_instance_custom = false;
shaders.actions_canvas.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_ADD);
shaders.actions_canvas.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MIX);
shaders.actions_canvas.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_SUB);
@ -1455,6 +1460,11 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
shaders.actions_canvas.usage_flag_pointers["VERTEX"] = &p_shader->canvas_item.uses_vertex;
shaders.actions_canvas.usage_flag_pointers["WORLD_MATRIX"] = &p_shader->canvas_item.uses_world_matrix;
shaders.actions_canvas.usage_flag_pointers["EXTRA_MATRIX"] = &p_shader->canvas_item.uses_extra_matrix;
shaders.actions_canvas.usage_flag_pointers["PROJECTION_MATRIX"] = &p_shader->canvas_item.uses_projection_matrix;
shaders.actions_canvas.usage_flag_pointers["INSTANCE_CUSTOM"] = &p_shader->canvas_item.uses_instance_custom;
actions = &shaders.actions_canvas;
actions->uniforms = &p_shader->uniforms;
} break;
@ -1558,6 +1568,9 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
if (p_shader->canvas_item.uses_vertex) {
p_shader->canvas_item.batch_flags |= RasterizerStorageCommon::PREVENT_VERTEX_BAKING;
}
if (p_shader->canvas_item.uses_world_matrix | p_shader->canvas_item.uses_extra_matrix | p_shader->canvas_item.uses_projection_matrix | p_shader->canvas_item.uses_instance_custom) {
p_shader->canvas_item.batch_flags |= RasterizerStorageCommon::PREVENT_ITEM_JOINING;
}
}
p_shader->shader->set_custom_shader(p_shader->custom_code_id);

View file

@ -458,6 +458,12 @@ public:
bool uses_color;
bool uses_vertex;
// all these should disable item joining if used in a custom shader
bool uses_world_matrix;
bool uses_extra_matrix;
bool uses_projection_matrix;
bool uses_instance_custom;
} canvas_item;
struct Spatial {

View file

@ -1770,31 +1770,41 @@ bool RasterizerCanvasGLES3::try_join_item(Item *p_ci, RenderItemState &r_ris, bo
bdata.joined_item_batch_flags = 0;
if (r_ris.shader_cache) {
unsigned int and_flags = r_ris.shader_cache->canvas_item.batch_flags & (RasterizerStorageCommon::PREVENT_COLOR_BAKING | RasterizerStorageCommon::PREVENT_VERTEX_BAKING);
unsigned int and_flags = r_ris.shader_cache->canvas_item.batch_flags & (RasterizerStorageCommon::PREVENT_COLOR_BAKING | RasterizerStorageCommon::PREVENT_VERTEX_BAKING | RasterizerStorageCommon::PREVENT_ITEM_JOINING);
if (and_flags) {
bool use_larger_fvfs = true;
if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) {
// in some circumstances, if the modulate is identity, we still allow baking because reading modulate / color
// will still be okay to do in the shader with no ill effects
if (r_ris.final_modulate == Color(1, 1, 1, 1)) {
use_larger_fvfs = false;
}
}
// new .. always use large FVF
if (use_larger_fvfs) {
if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) {
bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_MODULATE_FVF;
} else {
// we need to save on the joined item that it should use large fvf.
// This info will then be used in filling and rendering
bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_LARGE_FVF;
}
// special case for preventing item joining altogether
if (and_flags & RasterizerStorageCommon::PREVENT_ITEM_JOINING) {
join = false;
//r_batch_break = true; // don't think we need a batch break
// save the flags so that they don't need to be recalculated in the 2nd pass
bdata.joined_item_batch_flags |= r_ris.shader_cache->canvas_item.batch_flags;
}
} else {
bool use_larger_fvfs = true;
if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) {
// in some circumstances, if the modulate is identity, we still allow baking because reading modulate / color
// will still be okay to do in the shader with no ill effects
if (r_ris.final_modulate == Color(1, 1, 1, 1)) {
use_larger_fvfs = false;
}
}
// new .. always use large FVF
if (use_larger_fvfs) {
if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) {
bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_MODULATE_FVF;
} else {
// we need to save on the joined item that it should use large fvf.
// This info will then be used in filling and rendering
bdata.joined_item_batch_flags |= RasterizerStorageCommon::USE_LARGE_FVF;
}
bdata.joined_item_batch_flags |= r_ris.shader_cache->canvas_item.batch_flags;
}
} // if not prevent item joining
}
}

View file

@ -2313,6 +2313,11 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
p_shader->canvas_item.uses_vertex = false;
p_shader->canvas_item.batch_flags = 0;
p_shader->canvas_item.uses_world_matrix = false;
p_shader->canvas_item.uses_extra_matrix = false;
p_shader->canvas_item.uses_projection_matrix = false;
p_shader->canvas_item.uses_instance_custom = false;
shaders.actions_canvas.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_ADD);
shaders.actions_canvas.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MIX);
shaders.actions_canvas.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_SUB);
@ -2332,6 +2337,11 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
shaders.actions_canvas.usage_flag_pointers["COLOR"] = &p_shader->canvas_item.uses_color;
shaders.actions_canvas.usage_flag_pointers["VERTEX"] = &p_shader->canvas_item.uses_vertex;
shaders.actions_canvas.usage_flag_pointers["WORLD_MATRIX"] = &p_shader->canvas_item.uses_world_matrix;
shaders.actions_canvas.usage_flag_pointers["EXTRA_MATRIX"] = &p_shader->canvas_item.uses_extra_matrix;
shaders.actions_canvas.usage_flag_pointers["PROJECTION_MATRIX"] = &p_shader->canvas_item.uses_projection_matrix;
shaders.actions_canvas.usage_flag_pointers["INSTANCE_CUSTOM"] = &p_shader->canvas_item.uses_instance_custom;
actions = &shaders.actions_canvas;
actions->uniforms = &p_shader->uniforms;
@ -2436,6 +2446,9 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
if (p_shader->canvas_item.uses_vertex) {
p_shader->canvas_item.batch_flags |= RasterizerStorageCommon::PREVENT_VERTEX_BAKING;
}
if (p_shader->canvas_item.uses_world_matrix | p_shader->canvas_item.uses_extra_matrix | p_shader->canvas_item.uses_projection_matrix | p_shader->canvas_item.uses_instance_custom) {
p_shader->canvas_item.batch_flags |= RasterizerStorageCommon::PREVENT_ITEM_JOINING;
}
}
//all materials using this shader will have to be invalidated, unfortunately

View file

@ -473,6 +473,12 @@ public:
bool uses_color;
bool uses_vertex;
// all these should disable item joining if used in a custom shader
bool uses_world_matrix;
bool uses_extra_matrix;
bool uses_projection_matrix;
bool uses_instance_custom;
} canvas_item;
struct Spatial {

View file

@ -48,8 +48,11 @@ public:
PREVENT_COLOR_BAKING = 1 << 0,
PREVENT_VERTEX_BAKING = 1 << 1,
USE_MODULATE_FVF = 1 << 2,
USE_LARGE_FVF = 1 << 3,
// custom vertex shaders using BUILTINS that vary per item
PREVENT_ITEM_JOINING = 1 << 2,
USE_MODULATE_FVF = 1 << 3,
USE_LARGE_FVF = 1 << 4,
};
enum BatchType : uint16_t {