Browse Source

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.
lawnjelly 4 years ago
parent
commit
1394df3188

+ 29 - 19
drivers/gles2/rasterizer_canvas_gles2.cpp

@@ -1372,33 +1372,42 @@ bool RasterizerCanvasGLES2::try_join_item(Item *p_ci, RenderItemState &r_ris, bo
 	bdata.joined_item_batch_flags = 0;
 	bdata.joined_item_batch_flags = 0;
 	if (r_ris.shader_cache) {
 	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) {
 		if (and_flags) {
 
 
-			bool use_larger_fvfs = true;
+			// 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
 
 
-			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;
-				}
-			}
+				// 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;
 
 
-			// new .. always use large FVF
-			if (use_larger_fvfs) {
 				if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) {
 				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;
+					// 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;
+					}
 				}
 				}
 
 
-				bdata.joined_item_batch_flags |= r_ris.shader_cache->canvas_item.batch_flags;
-			}
+				// 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) {
 			if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) {
 				// in some circumstances, if the modulate is identity, we still allow baking because reading modulate / color
 				// 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
 				// 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;
 				bdata.joined_item_batch_flags |= r_ris.shader_cache->canvas_item.batch_flags;
 			}
 			}
 			*/
 			*/
+			} // if not prevent item joining
 		}
 		}
 	}
 	}
 
 

+ 13 - 0
drivers/gles2/rasterizer_storage_gles2.cpp

@@ -1437,6 +1437,11 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
 			p_shader->canvas_item.uses_vertex = false;
 			p_shader->canvas_item.uses_vertex = false;
 			p_shader->canvas_item.batch_flags = 0;
 			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_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_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);
 			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["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 = &shaders.actions_canvas;
 			actions->uniforms = &p_shader->uniforms;
 			actions->uniforms = &p_shader->uniforms;
 		} break;
 		} break;
@@ -1558,6 +1568,9 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
 		if (p_shader->canvas_item.uses_vertex) {
 		if (p_shader->canvas_item.uses_vertex) {
 			p_shader->canvas_item.batch_flags |= RasterizerStorageCommon::PREVENT_VERTEX_BAKING;
 			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);
 	p_shader->shader->set_custom_shader(p_shader->custom_code_id);

+ 6 - 0
drivers/gles2/rasterizer_storage_gles2.h

@@ -458,6 +458,12 @@ public:
 			bool uses_color;
 			bool uses_color;
 			bool uses_vertex;
 			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;
 		} canvas_item;
 
 
 		struct Spatial {
 		struct Spatial {

+ 28 - 18
drivers/gles3/rasterizer_canvas_gles3.cpp

@@ -1770,31 +1770,41 @@ bool RasterizerCanvasGLES3::try_join_item(Item *p_ci, RenderItemState &r_ris, bo
 	bdata.joined_item_batch_flags = 0;
 	bdata.joined_item_batch_flags = 0;
 	if (r_ris.shader_cache) {
 	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) {
 		if (and_flags) {
 
 
-			bool use_larger_fvfs = true;
+			// 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
 
 
-			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;
-				}
-			}
+				// 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;
 
 
-			// new .. always use large FVF
-			if (use_larger_fvfs) {
 				if (and_flags == RasterizerStorageCommon::PREVENT_COLOR_BAKING) {
 				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;
+					// 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;
+					}
 				}
 				}
 
 
-				bdata.joined_item_batch_flags |= r_ris.shader_cache->canvas_item.batch_flags;
-			}
+				// 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
 		}
 		}
 	}
 	}
 
 

+ 13 - 0
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -2313,6 +2313,11 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
 			p_shader->canvas_item.uses_vertex = false;
 			p_shader->canvas_item.uses_vertex = false;
 			p_shader->canvas_item.batch_flags = 0;
 			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_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_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);
 			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["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["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 = &shaders.actions_canvas;
 			actions->uniforms = &p_shader->uniforms;
 			actions->uniforms = &p_shader->uniforms;
 
 
@@ -2436,6 +2446,9 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
 		if (p_shader->canvas_item.uses_vertex) {
 		if (p_shader->canvas_item.uses_vertex) {
 			p_shader->canvas_item.batch_flags |= RasterizerStorageCommon::PREVENT_VERTEX_BAKING;
 			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
 	//all materials using this shader will have to be invalidated, unfortunately

+ 6 - 0
drivers/gles3/rasterizer_storage_gles3.h

@@ -473,6 +473,12 @@ public:
 			bool uses_color;
 			bool uses_color;
 			bool uses_vertex;
 			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;
 		} canvas_item;
 
 
 		struct Spatial {
 		struct Spatial {

+ 5 - 2
drivers/gles_common/rasterizer_storage_common.h

@@ -48,8 +48,11 @@ public:
 		PREVENT_COLOR_BAKING = 1 << 0,
 		PREVENT_COLOR_BAKING = 1 << 0,
 		PREVENT_VERTEX_BAKING = 1 << 1,
 		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 {
 	enum BatchType : uint16_t {