GLES2 Batching - Fix custom shaders reading VERTEX

In situations where custom canvas shaders read VERTEX values, they could read incorrect global positions rather than local positions where batching had baked item transforms. This PR prevents joining items that read VERTEX built in in shaders, and thus prevents this situation arising (as unjoined items will not bake transforms).
This commit is contained in:
lawnjelly 2020-05-11 15:46:31 +01:00
parent a9bcd8ba26
commit d096ce1644
3 changed files with 22 additions and 9 deletions

View File

@ -2267,7 +2267,8 @@ bool RasterizerCanvasGLES2::try_join_item(Item *p_ci, RenderItemState &r_ris, bo
// does the shader contain BUILTINs which should break the batching?
if (r_ris.shader_cache && !unshaded) {
if (r_ris.shader_cache->canvas_item.prevent_color_baking) {
const unsigned int test_flags = RasterizerStorageGLES2::Shader::CanvasItem::PREVENT_COLOR_BAKING | RasterizerStorageGLES2::Shader::CanvasItem::PREVENT_VERTEX_BAKING;
if (r_ris.shader_cache->canvas_item.batch_flags & test_flags) {
// we will do this same test on the shader during the rendering pass in order to set a bool not to bake vertex colors
// instead of saving this info as it is cheap to calculate
join = false;
@ -3000,7 +3001,7 @@ void RasterizerCanvasGLES2::render_joined_item(const BItemJoined &p_bij, RenderI
// does the shader contain BUILTINs which break the batching and should prevent color baking?
bdata.prevent_color_baking = false;
if (r_ris.shader_cache && !unshaded) {
if (r_ris.shader_cache->canvas_item.prevent_color_baking) {
if (r_ris.shader_cache->canvas_item.batch_flags & RasterizerStorageGLES2::Shader::CanvasItem::PREVENT_COLOR_BAKING) {
bdata.prevent_color_baking = true;
}
}

View File

@ -1426,7 +1426,8 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
p_shader->canvas_item.uses_time = false;
p_shader->canvas_item.uses_modulate = false;
p_shader->canvas_item.reads_color = false;
p_shader->canvas_item.prevent_color_baking = false;
p_shader->canvas_item.reads_vertex = false;
p_shader->canvas_item.batch_flags = 0;
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);
@ -1444,6 +1445,7 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
shaders.actions_canvas.usage_flag_pointers["MODULATE"] = &p_shader->canvas_item.uses_modulate;
shaders.actions_canvas.read_flag_pointers["COLOR"] = &p_shader->canvas_item.reads_color;
shaders.actions_canvas.read_flag_pointers["VERTEX"] = &p_shader->canvas_item.reads_vertex;
actions = &shaders.actions_canvas;
actions->uniforms = &p_shader->uniforms;
@ -1533,7 +1535,12 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
// some logic for batching
if (p_shader->mode == VS::SHADER_CANVAS_ITEM) {
p_shader->canvas_item.prevent_color_baking = p_shader->canvas_item.uses_modulate | p_shader->canvas_item.reads_color;
if (p_shader->canvas_item.uses_modulate | p_shader->canvas_item.reads_color) {
p_shader->canvas_item.batch_flags |= Shader::CanvasItem::PREVENT_COLOR_BAKING;
}
if (p_shader->canvas_item.reads_vertex) {
p_shader->canvas_item.batch_flags |= Shader::CanvasItem::PREVENT_VERTEX_BAKING;
}
}
p_shader->shader->set_custom_shader(p_shader->custom_code_id);

View File

@ -447,16 +447,21 @@ public:
int light_mode;
enum BatchFlags {
PREVENT_COLOR_BAKING = 1 << 0,
PREVENT_VERTEX_BAKING = 1 << 1,
};
// these flags are specifically for batching
// some of the logic is thus in rasterizer_storage.cpp
// we could alternatively set bitflags for each 'uses' and test on the fly
unsigned int batch_flags;
bool uses_screen_texture;
bool uses_screen_uv;
bool uses_time;
bool uses_modulate;
bool reads_color;
// this flag is specifically for batching
// some of the logic is thus in rasterizer_storage.cpp
// we could alternatively set some bitflags here and test on the fly
bool prevent_color_baking;
bool reads_vertex;
} canvas_item;