diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 901a5788323..699429c7c71 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -1034,6 +1034,22 @@
Fix to improve physics jitter, specially on monitors where refresh rate is different than the physics FPS.
[b]Note:[/b] This property is only read when the project starts. To change the physics FPS at runtime, set [member Engine.physics_jitter_fix] instead.
+
+ [b]Experimental[/b] Calls [code]glBufferData[/code] with NULL data prior to uploading batching data. This may not be necessary but can be used for safety.
+ [b]Note:[/b] Use with care. You are advised to leave this as default for exports. A non-default setting that works better on your machine may adversely affect performance for end users.
+
+
+ [b]Experimental[/b] If set to on, uses the [code]GL_STREAM_DRAW[/code] flag for batching buffer uploads. If off, uses the [code]GL_DYNAMIC_DRAW[/code] flag.
+ [b]Note:[/b] Use with care. You are advised to leave this as default for exports. A non-default setting that works better on your machine may adversely affect performance for end users.
+
+
+ [b]Experimental[/b] If set to on, this applies buffer orphaning - [code]glBufferData[/code] is called with NULL data and the full buffer size prior to uploading new data. This can be important to avoid stalling on some hardware.
+ [b]Note:[/b] Use with care. You are advised to leave this as default for exports. A non-default setting that works better on your machine may adversely affect performance for end users.
+
+
+ [b]Experimental[/b] If set to on, uses the [code]GL_STREAM_DRAW[/code] flag for legacy buffer uploads. If off, uses the [code]GL_DYNAMIC_DRAW[/code] flag.
+ [b]Note:[/b] Use with care. You are advised to leave this as default for exports. A non-default setting that works better on your machine may adversely affect performance for end users.
+
Choose between fixed mode where corner scalings are preserved matching the artwork, and scaling mode.
Not available in GLES3 when [member rendering/batching/options/use_batching] is off.
diff --git a/drivers/gles2/rasterizer_canvas_base_gles2.cpp b/drivers/gles2/rasterizer_canvas_base_gles2.cpp
index 9cdbb5b4899..6fc9c8b5dac 100644
--- a/drivers/gles2/rasterizer_canvas_base_gles2.cpp
+++ b/drivers/gles2/rasterizer_canvas_base_gles2.cpp
@@ -947,11 +947,18 @@ void RasterizerCanvasBaseGLES2::draw_lens_distortion_rect(const Rect2 &p_rect, f
void RasterizerCanvasBaseGLES2::initialize() {
- bool flag_stream = false;
- if (flag_stream)
- _buffer_upload_usage_flag = GL_STREAM_DRAW;
- else
- _buffer_upload_usage_flag = GL_DYNAMIC_DRAW;
+ int flag_stream_mode = GLOBAL_GET("rendering/2d/opengl/legacy_stream");
+ switch (flag_stream_mode) {
+ default: {
+ _buffer_upload_usage_flag = GL_STREAM_DRAW;
+ } break;
+ case 1: {
+ _buffer_upload_usage_flag = GL_DYNAMIC_DRAW;
+ } break;
+ case 2: {
+ _buffer_upload_usage_flag = GL_STREAM_DRAW;
+ } break;
+ }
// quad buffer
{
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index 57ac5199ba6..1e7f27a2b8e 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -6420,6 +6420,19 @@ void RasterizerStorageGLES2::initialize() {
GLOBAL_DEF_RST("rendering/quality/lightmapping/use_bicubic_sampling", true);
GLOBAL_DEF_RST("rendering/quality/lightmapping/use_bicubic_sampling.mobile", false);
config.use_lightmap_filter_bicubic = GLOBAL_GET("rendering/quality/lightmapping/use_bicubic_sampling");
+
+ int orphan_mode = GLOBAL_GET("rendering/2d/opengl/legacy_orphan_buffers");
+ switch (orphan_mode) {
+ default: {
+ config.should_orphan = true;
+ } break;
+ case 1: {
+ config.should_orphan = false;
+ } break;
+ case 2: {
+ config.should_orphan = true;
+ } break;
+ }
}
void RasterizerStorageGLES2::finalize() {
diff --git a/drivers/gles3/rasterizer_canvas_base_gles3.cpp b/drivers/gles3/rasterizer_canvas_base_gles3.cpp
index d0a85e0e2f0..a1a48817d29 100644
--- a/drivers/gles3/rasterizer_canvas_base_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_base_gles3.cpp
@@ -1137,11 +1137,17 @@ void RasterizerCanvasBaseGLES3::draw_window_margins(int *black_margin, RID *blac
void RasterizerCanvasBaseGLES3::initialize() {
- bool flag_stream = false;
- if (flag_stream) {
- _buffer_upload_usage_flag = GL_STREAM_DRAW;
- } else {
- _buffer_upload_usage_flag = GL_DYNAMIC_DRAW;
+ int flag_stream_mode = GLOBAL_GET("rendering/2d/opengl/legacy_stream");
+ switch (flag_stream_mode) {
+ default: {
+ _buffer_upload_usage_flag = GL_STREAM_DRAW;
+ } break;
+ case 1: {
+ _buffer_upload_usage_flag = GL_DYNAMIC_DRAW;
+ } break;
+ case 2: {
+ _buffer_upload_usage_flag = GL_STREAM_DRAW;
+ } break;
}
{
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 65c712707a5..350aac8e6a9 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -5105,11 +5105,13 @@ void RasterizerStorageGLES3::update_dirty_multimeshes() {
glBindBuffer(GL_ARRAY_BUFFER, multimesh->buffer);
uint32_t buffer_size = multimesh->data.size() * sizeof(float);
- if (config.should_orphan) {
- glBufferData(GL_ARRAY_BUFFER, buffer_size, multimesh->data.ptr(), GL_DYNAMIC_DRAW);
- } else {
- glBufferSubData(GL_ARRAY_BUFFER, 0, buffer_size, multimesh->data.ptr());
- }
+
+ // this could potentially have a project setting for API options as with 2d
+ // if (config.should_orphan) {
+ glBufferData(GL_ARRAY_BUFFER, buffer_size, multimesh->data.ptr(), GL_DYNAMIC_DRAW);
+ // } else {
+ // glBufferSubData(GL_ARRAY_BUFFER, 0, buffer_size, multimesh->data.ptr());
+ // }
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
@@ -8652,6 +8654,19 @@ void RasterizerStorageGLES3::initialize() {
}
}
}
+
+ int orphan_mode = GLOBAL_GET("rendering/2d/opengl/legacy_orphan_buffers");
+ switch (orphan_mode) {
+ default: {
+ config.should_orphan = true;
+ } break;
+ case 1: {
+ config.should_orphan = false;
+ } break;
+ case 2: {
+ config.should_orphan = true;
+ } break;
+ }
}
void RasterizerStorageGLES3::finalize() {
diff --git a/drivers/gles_common/rasterizer_canvas_batcher.h b/drivers/gles_common/rasterizer_canvas_batcher.h
index d3209880a87..9ee7fc76176 100644
--- a/drivers/gles_common/rasterizer_canvas_batcher.h
+++ b/drivers/gles_common/rasterizer_canvas_batcher.h
@@ -1007,6 +1007,33 @@ PREAMBLE(void)::batch_initialize() {
bdata.settings_use_software_skinning = GLOBAL_GET("rendering/2d/options/use_software_skinning");
bdata.settings_ninepatch_mode = GLOBAL_GET("rendering/2d/options/ninepatch_mode");
+ // allow user to override the api usage techniques using project settings
+ int send_null_mode = GLOBAL_GET("rendering/2d/opengl/batching_send_null");
+ switch (send_null_mode) {
+ default: {
+ bdata.buffer_mode_batch_upload_send_null = true;
+ } break;
+ case 1: {
+ bdata.buffer_mode_batch_upload_send_null = false;
+ } break;
+ case 2: {
+ bdata.buffer_mode_batch_upload_send_null = true;
+ } break;
+ }
+
+ int stream_mode = GLOBAL_GET("rendering/2d/opengl/batching_stream");
+ switch (stream_mode) {
+ default: {
+ bdata.buffer_mode_batch_upload_flag_stream = false;
+ } break;
+ case 1: {
+ bdata.buffer_mode_batch_upload_flag_stream = false;
+ } break;
+ case 2: {
+ bdata.buffer_mode_batch_upload_flag_stream = true;
+ } break;
+ }
+
// alternatively only enable uv contract if pixel snap in use,
// but with this enable bool, it should not be necessary
bdata.settings_uv_contract = GLOBAL_GET("rendering/batching/precision/uv_contract");
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 99392fdcc63..0f99d3c278c 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -2454,6 +2454,15 @@ VisualServer::VisualServer() {
GLOBAL_DEF_RST("rendering/2d/options/ninepatch_mode", 1);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/options/ninepatch_mode", PropertyInfo(Variant::INT, "rendering/2d/options/ninepatch_mode", PROPERTY_HINT_ENUM, "Fixed,Scaling"));
+ GLOBAL_DEF_RST("rendering/2d/opengl/batching_send_null", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/batching_send_null", PropertyInfo(Variant::INT, "rendering/2d/opengl/batching_send_null", PROPERTY_HINT_ENUM, "Default (On),Off,On"));
+ GLOBAL_DEF_RST("rendering/2d/opengl/batching_stream", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/batching_stream", PropertyInfo(Variant::INT, "rendering/2d/opengl/batching_stream", PROPERTY_HINT_ENUM, "Default (Off),Off,On"));
+ GLOBAL_DEF_RST("rendering/2d/opengl/legacy_orphan_buffers", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/legacy_orphan_buffers", PropertyInfo(Variant::INT, "rendering/2d/opengl/legacy_orphan_buffers", PROPERTY_HINT_ENUM, "Default (On),Off,On"));
+ GLOBAL_DEF_RST("rendering/2d/opengl/legacy_stream", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/legacy_stream", PropertyInfo(Variant::INT, "rendering/2d/opengl/legacy_stream", PROPERTY_HINT_ENUM, "Default (On),Off,On"));
+
GLOBAL_DEF("rendering/batching/options/use_batching", true);
GLOBAL_DEF_RST("rendering/batching/options/use_batching_in_editor", true);
GLOBAL_DEF("rendering/batching/options/single_rect_fallback", false);