Add project settings to manually specify API usage

As a result of the GLES specifications being vague about best practice for how buffers should be used dynamically, different GPUs / platforms appear to have different preferences.

Mac in particular seems to have a number of problems in this area, and none of the rendering team uses Macs. So far we have relied on guesswork to choose the best usage, but in an attempt to pin this down, this PR begins to introduce manual selection of options for users to test their configurations.
This commit is contained in:
lawnjelly 2020-10-25 15:38:54 +00:00
parent 4f908fb671
commit 5c8f497a24
12 changed files with 107 additions and 36 deletions

View File

@ -447,7 +447,7 @@ void RasterizerCanvasBaseGLES2::_draw_polygon(const int *p_indices, int p_index_
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
uint32_t buffer_ofs = 0;
storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, sizeof(Vector2) * p_vertex_count, p_vertices);
storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, sizeof(Vector2) * p_vertex_count, p_vertices, GL_ARRAY_BUFFER, _buffer_upload_usage_flag, true);
glEnableVertexAttribArray(VS::ARRAY_VERTEX);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL);
@ -495,7 +495,7 @@ void RasterizerCanvasBaseGLES2::_draw_polygon(const int *p_indices, int p_index_
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
if (storage->config.support_32_bits_indices) { //should check for
storage->buffer_orphan_and_upload(data.polygon_index_buffer_size, 0, sizeof(int) * p_index_count, p_indices, GL_ELEMENT_ARRAY_BUFFER);
storage->buffer_orphan_and_upload(data.polygon_index_buffer_size, 0, sizeof(int) * p_index_count, p_indices, GL_ELEMENT_ARRAY_BUFFER, _buffer_upload_usage_flag, true);
glDrawElements(GL_TRIANGLES, p_index_count, GL_UNSIGNED_INT, 0);
storage->info.render._2d_draw_call_count++;
} else {
@ -503,7 +503,7 @@ void RasterizerCanvasBaseGLES2::_draw_polygon(const int *p_indices, int p_index_
for (int i = 0; i < p_index_count; i++) {
index16[i] = uint16_t(p_indices[i]);
}
storage->buffer_orphan_and_upload(data.polygon_index_buffer_size, 0, sizeof(uint16_t) * p_index_count, index16, GL_ELEMENT_ARRAY_BUFFER);
storage->buffer_orphan_and_upload(data.polygon_index_buffer_size, 0, sizeof(uint16_t) * p_index_count, index16, GL_ELEMENT_ARRAY_BUFFER, _buffer_upload_usage_flag, true);
glDrawElements(GL_TRIANGLES, p_index_count, GL_UNSIGNED_SHORT, 0);
storage->info.render._2d_draw_call_count++;
}
@ -517,7 +517,7 @@ void RasterizerCanvasBaseGLES2::_draw_generic(GLuint p_primitive, int p_vertex_c
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
uint32_t buffer_ofs = 0;
storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, sizeof(Vector2) * p_vertex_count, p_vertices);
storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, sizeof(Vector2) * p_vertex_count, p_vertices, GL_ARRAY_BUFFER, _buffer_upload_usage_flag, true);
glEnableVertexAttribArray(VS::ARRAY_VERTEX);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL);
@ -556,7 +556,7 @@ void RasterizerCanvasBaseGLES2::_draw_generic_indices(GLuint p_primitive, const
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
uint32_t buffer_ofs = 0;
storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, sizeof(Vector2) * p_vertex_count, p_vertices);
storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, sizeof(Vector2) * p_vertex_count, p_vertices, GL_ARRAY_BUFFER, _buffer_upload_usage_flag, true);
glEnableVertexAttribArray(VS::ARRAY_VERTEX);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL);
@ -588,7 +588,7 @@ void RasterizerCanvasBaseGLES2::_draw_generic_indices(GLuint p_primitive, const
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
if (storage->config.support_32_bits_indices) { //should check for
storage->buffer_orphan_and_upload(data.polygon_index_buffer_size, 0, sizeof(int) * p_index_count, p_indices, GL_ELEMENT_ARRAY_BUFFER);
storage->buffer_orphan_and_upload(data.polygon_index_buffer_size, 0, sizeof(int) * p_index_count, p_indices, GL_ELEMENT_ARRAY_BUFFER, _buffer_upload_usage_flag, true);
glDrawElements(p_primitive, p_index_count, GL_UNSIGNED_INT, 0);
storage->info.render._2d_draw_call_count++;
} else {
@ -596,7 +596,7 @@ void RasterizerCanvasBaseGLES2::_draw_generic_indices(GLuint p_primitive, const
for (int i = 0; i < p_index_count; i++) {
index16[i] = uint16_t(p_indices[i]);
}
storage->buffer_orphan_and_upload(data.polygon_index_buffer_size, 0, sizeof(uint16_t) * p_index_count, index16, GL_ELEMENT_ARRAY_BUFFER);
storage->buffer_orphan_and_upload(data.polygon_index_buffer_size, 0, sizeof(uint16_t) * p_index_count, index16, GL_ELEMENT_ARRAY_BUFFER, _buffer_upload_usage_flag, true);
glDrawElements(p_primitive, p_index_count, GL_UNSIGNED_SHORT, 0);
storage->info.render._2d_draw_call_count++;
}
@ -659,7 +659,7 @@ void RasterizerCanvasBaseGLES2::_draw_gui_primitive(int p_points, const Vector2
}
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, p_points * stride * 4 * sizeof(float), buffer_data);
storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, p_points * stride * 4 * sizeof(float), buffer_data, GL_ARRAY_BUFFER, _buffer_upload_usage_flag, true);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, stride * sizeof(float), NULL);
@ -912,6 +912,12 @@ void RasterizerCanvasBaseGLES2::draw_lens_distortion_rect(const Rect2 &p_rect, f
void RasterizerCanvasBaseGLES2::initialize() {
bool flag_stream = GLOBAL_GET("rendering/options/api_usage_legacy/flag_stream");
if (flag_stream)
_buffer_upload_usage_flag = GL_STREAM_DRAW;
else
_buffer_upload_usage_flag = GL_DYNAMIC_DRAW;
// quad buffer
{
glGenBuffers(1, &data.canvas_quad_vertices);

View File

@ -107,6 +107,9 @@ public:
RasterizerStorageGLES2 *storage;
// allow user to choose api usage
GLenum _buffer_upload_usage_flag;
void _set_uniforms();
virtual RID light_internal_create();

View File

@ -53,26 +53,34 @@ void RasterizerCanvasGLES2::_batch_upload_buffers() {
glBindBuffer(GL_ARRAY_BUFFER, bdata.gl_vertex_buffer);
// usage flag is a project setting
GLenum buffer_usage_flag = GL_DYNAMIC_DRAW;
if (bdata.buffer_mode_batch_upload_flag_stream) {
buffer_usage_flag = GL_STREAM_DRAW;
}
// orphan the old (for now)
//glBufferData(GL_ARRAY_BUFFER, 0, 0, GL_DYNAMIC_DRAW);
if (bdata.buffer_mode_batch_upload_send_null) {
glBufferData(GL_ARRAY_BUFFER, 0, 0, buffer_usage_flag); // GL_DYNAMIC_DRAW);
}
switch (bdata.fvf) {
case RasterizerStorageCommon::FVF_UNBATCHED: // should not happen
break;
case RasterizerStorageCommon::FVF_REGULAR: // no change
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertex) * bdata.vertices.size(), bdata.vertices.get_data(), GL_DYNAMIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertex) * bdata.vertices.size(), bdata.vertices.get_data(), buffer_usage_flag);
break;
case RasterizerStorageCommon::FVF_COLOR:
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexColored) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), GL_DYNAMIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexColored) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), buffer_usage_flag);
break;
case RasterizerStorageCommon::FVF_LIGHT_ANGLE:
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexLightAngled) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), GL_DYNAMIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexLightAngled) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), buffer_usage_flag);
break;
case RasterizerStorageCommon::FVF_MODULATED:
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexModulated) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), GL_DYNAMIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexModulated) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), buffer_usage_flag);
break;
case RasterizerStorageCommon::FVF_LARGE:
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexLarge) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), GL_DYNAMIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexLarge) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), buffer_usage_flag);
break;
}
@ -810,7 +818,7 @@ void RasterizerCanvasGLES2::render_batches(Item::Command *const *p_commands, Ite
}
glBindBuffer(GL_ARRAY_BUFFER, data.ninepatch_vertices);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * (16 + 16) * 2, buffer, GL_DYNAMIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * (16 + 16) * 2, buffer, _buffer_upload_usage_flag);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ninepatch_elements);

View File

@ -3798,7 +3798,7 @@ void RasterizerStorageGLES2::_update_skeleton_transform_buffer(const PoolVector<
glBufferData(GL_ARRAY_BUFFER, buffer_size, p_data.read().ptr(), GL_DYNAMIC_DRAW);
} else {
// this may not be best, it could be better to use glBufferData in both cases.
buffer_orphan_and_upload(resources.skeleton_transform_buffer_size, 0, buffer_size, p_data.read().ptr());
buffer_orphan_and_upload(resources.skeleton_transform_buffer_size, 0, buffer_size, p_data.read().ptr(), GL_ARRAY_BUFFER, true);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
@ -6289,6 +6289,7 @@ void RasterizerStorageGLES2::initialize() {
config.force_vertex_shading = GLOBAL_GET("rendering/quality/shading/force_vertex_shading");
config.use_fast_texture_filter = GLOBAL_GET("rendering/quality/filters/use_nearest_mipmap_filter");
config.should_orphan = GLOBAL_GET("rendering/options/api_usage_legacy/orphan_buffers");
}
void RasterizerStorageGLES2::finalize() {
@ -6308,4 +6309,5 @@ void RasterizerStorageGLES2::update_dirty_resources() {
RasterizerStorageGLES2::RasterizerStorageGLES2() {
RasterizerStorageGLES2::system_fbo = 0;
config.should_orphan = true;
}

View File

@ -96,6 +96,9 @@ public:
GLuint depth_type;
GLuint depth_buffer_internalformat;
// in some cases the legacy render didn't orphan. We will mark these
// so the user can switch orphaning off for them.
bool should_orphan;
} config;
struct Resources {
@ -1334,17 +1337,19 @@ public:
virtual String get_video_adapter_name() const;
virtual String get_video_adapter_vendor() const;
void buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target = GL_ARRAY_BUFFER);
void buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target = GL_ARRAY_BUFFER, GLenum p_usage = GL_DYNAMIC_DRAW, bool p_optional_orphan = false);
RasterizerStorageGLES2();
};
// standardize the orphan / upload in one place so it can be changed per platform as necessary, and avoid future
// bugs causing pipeline stalls
inline void RasterizerStorageGLES2::buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target) {
inline void RasterizerStorageGLES2::buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target, GLenum p_usage, bool p_optional_orphan) {
// Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
// Was previously #ifndef GLES_OVER_GL however this causes stalls on desktop mac also (and possibly other)
glBufferData(p_target, p_buffer_size, NULL, GL_DYNAMIC_DRAW);
if (!p_optional_orphan || (config.should_orphan)) {
glBufferData(p_target, p_buffer_size, NULL, p_usage);
}
glBufferSubData(p_target, p_offset, p_data_size, p_data);
}

View File

@ -349,7 +349,7 @@ void RasterizerCanvasBaseGLES3::_draw_polygon(const int *p_indices, int p_index_
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
uint32_t buffer_ofs = 0;
storage->buffer_orphan_and_upload(data.polygon_buffer_size, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices);
storage->buffer_orphan_and_upload(data.polygon_buffer_size, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices, GL_ARRAY_BUFFER, _buffer_upload_usage_flag);
glEnableVertexAttribArray(VS::ARRAY_VERTEX);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
@ -417,7 +417,7 @@ void RasterizerCanvasBaseGLES3::_draw_polygon(const int *p_indices, int p_index_
//bind the indices buffer.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
storage->buffer_orphan_and_upload(data.polygon_index_buffer_size, 0, sizeof(int) * p_index_count, p_indices, GL_ELEMENT_ARRAY_BUFFER);
storage->buffer_orphan_and_upload(data.polygon_index_buffer_size, 0, sizeof(int) * p_index_count, p_indices, GL_ELEMENT_ARRAY_BUFFER, _buffer_upload_usage_flag);
//draw the triangles.
glDrawElements(GL_TRIANGLES, p_index_count, GL_UNSIGNED_INT, 0);
@ -441,7 +441,7 @@ void RasterizerCanvasBaseGLES3::_draw_generic(GLuint p_primitive, int p_vertex_c
//vertex
uint32_t buffer_ofs = 0;
storage->buffer_orphan_and_upload(data.polygon_buffer_size, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices);
storage->buffer_orphan_and_upload(data.polygon_buffer_size, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices, GL_ARRAY_BUFFER, _buffer_upload_usage_flag);
glEnableVertexAttribArray(VS::ARRAY_VERTEX);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
@ -489,7 +489,7 @@ void RasterizerCanvasBaseGLES3::_draw_generic_indices(GLuint p_primitive, const
//vertex
uint32_t buffer_ofs = 0;
storage->buffer_orphan_and_upload(data.polygon_buffer_size, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices);
storage->buffer_orphan_and_upload(data.polygon_buffer_size, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices, GL_ARRAY_BUFFER, _buffer_upload_usage_flag);
glEnableVertexAttribArray(VS::ARRAY_VERTEX);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
@ -535,7 +535,7 @@ void RasterizerCanvasBaseGLES3::_draw_generic_indices(GLuint p_primitive, const
//bind the indices buffer.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
storage->buffer_orphan_and_upload(data.polygon_index_buffer_size, 0, sizeof(int) * p_index_count, p_indices, GL_ELEMENT_ARRAY_BUFFER);
storage->buffer_orphan_and_upload(data.polygon_index_buffer_size, 0, sizeof(int) * p_index_count, p_indices, GL_ELEMENT_ARRAY_BUFFER, _buffer_upload_usage_flag);
//draw the triangles.
glDrawElements(p_primitive, p_index_count, GL_UNSIGNED_INT, 0);
@ -610,7 +610,7 @@ void RasterizerCanvasBaseGLES3::_draw_gui_primitive(int p_points, const Vector2
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
//TODO the below call may need to be replaced with: p_points * stride * 4 * sizeof(float), &b[0]);
storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, p_points * stride * 4, &b[0]);
storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, p_points * stride * 4, &b[0], GL_ARRAY_BUFFER, _buffer_upload_usage_flag);
glBindVertexArray(data.polygon_buffer_quad_arrays[version]);
glDrawArrays(prim[p_points], 0, p_points);
@ -1140,6 +1140,13 @@ void RasterizerCanvasBaseGLES3::draw_window_margins(int *black_margin, RID *blac
void RasterizerCanvasBaseGLES3::initialize() {
bool flag_stream = GLOBAL_GET("rendering/options/api_usage_legacy/flag_stream");
if (flag_stream) {
_buffer_upload_usage_flag = GL_STREAM_DRAW;
} else {
_buffer_upload_usage_flag = GL_DYNAMIC_DRAW;
}
{
//quad buffers

View File

@ -102,6 +102,9 @@ public:
RasterizerStorageGLES3 *storage;
// allow user to choose api usage
GLenum _buffer_upload_usage_flag;
struct LightInternal : public RID_Data {
struct UBOData {

View File

@ -1924,7 +1924,7 @@ void RasterizerCanvasGLES3::canvas_render_items_implementation(Item *p_item_list
ris.prev_distance_field = false;
glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data, GL_DYNAMIC_DRAW);
glBufferData(GL_UNIFORM_BUFFER, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data, _buffer_upload_usage_flag);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
state.current_tex = RID();
@ -1969,26 +1969,34 @@ void RasterizerCanvasGLES3::_batch_upload_buffers() {
glBindBuffer(GL_ARRAY_BUFFER, bdata.gl_vertex_buffer);
// usage flag is a project setting
GLenum buffer_usage_flag = GL_DYNAMIC_DRAW;
if (bdata.buffer_mode_batch_upload_flag_stream) {
buffer_usage_flag = GL_STREAM_DRAW;
}
// orphan the old (for now)
//glBufferData(GL_ARRAY_BUFFER, 0, 0, GL_DYNAMIC_DRAW);
if (bdata.buffer_mode_batch_upload_send_null) {
glBufferData(GL_ARRAY_BUFFER, 0, 0, buffer_usage_flag); // GL_DYNAMIC_DRAW);
}
switch (bdata.fvf) {
case RasterizerStorageCommon::FVF_UNBATCHED: // should not happen
break;
case RasterizerStorageCommon::FVF_REGULAR: // no change
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertex) * bdata.vertices.size(), bdata.vertices.get_data(), GL_DYNAMIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertex) * bdata.vertices.size(), bdata.vertices.get_data(), buffer_usage_flag);
break;
case RasterizerStorageCommon::FVF_COLOR:
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexColored) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), GL_DYNAMIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexColored) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), buffer_usage_flag);
break;
case RasterizerStorageCommon::FVF_LIGHT_ANGLE:
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexLightAngled) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), GL_DYNAMIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexLightAngled) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), buffer_usage_flag);
break;
case RasterizerStorageCommon::FVF_MODULATED:
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexModulated) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), GL_DYNAMIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexModulated) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), buffer_usage_flag);
break;
case RasterizerStorageCommon::FVF_LARGE:
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexLarge) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), GL_DYNAMIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(BatchVertexLarge) * bdata.unit_vertices.size(), bdata.unit_vertices.get_unit(0), buffer_usage_flag);
break;
}

View File

@ -5086,7 +5086,11 @@ void RasterizerStorageGLES3::update_dirty_multimeshes() {
glBindBuffer(GL_ARRAY_BUFFER, multimesh->buffer);
uint32_t buffer_size = multimesh->data.size() * sizeof(float);
glBufferData(GL_ARRAY_BUFFER, buffer_size, multimesh->data.ptr(), GL_DYNAMIC_DRAW);
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);
}
@ -8550,6 +8554,8 @@ void RasterizerStorageGLES3::initialize() {
}
}
}
config.should_orphan = GLOBAL_GET("rendering/options/api_usage_legacy/orphan_buffers");
}
void RasterizerStorageGLES3::finalize() {
@ -8569,4 +8575,5 @@ void RasterizerStorageGLES3::update_dirty_resources() {
}
RasterizerStorageGLES3::RasterizerStorageGLES3() {
config.should_orphan = true;
}

View File

@ -106,6 +106,10 @@ public:
bool use_depth_prepass;
bool force_vertex_shading;
// in some cases the legacy render didn't orphan. We will mark these
// so the user can switch orphaning off for them.
bool should_orphan;
} config;
mutable struct Shaders {
@ -1499,17 +1503,19 @@ public:
virtual String get_video_adapter_name() const;
virtual String get_video_adapter_vendor() const;
void buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target = GL_ARRAY_BUFFER);
void buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target = GL_ARRAY_BUFFER, GLenum p_usage = GL_DYNAMIC_DRAW, bool p_optional_orphan = false);
RasterizerStorageGLES3();
};
// standardize the orphan / upload in one place so it can be changed per platform as necessary, and avoid future
// bugs causing pipeline stalls
inline void RasterizerStorageGLES3::buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target) {
inline void RasterizerStorageGLES3::buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target, GLenum p_usage, bool p_optional_orphan) {
// Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
// Was previously #ifndef GLES_OVER_GL however this causes stalls on desktop mac also (and possibly other)
glBufferData(p_target, p_buffer_size, NULL, GL_DYNAMIC_DRAW);
if (!p_optional_orphan || (config.should_orphan)) {
glBufferData(p_target, p_buffer_size, NULL, p_usage);
}
glBufferSubData(p_target, p_offset, p_data_size, p_data);
}

View File

@ -279,6 +279,9 @@ public:
settings_uv_contract = false;
settings_uv_contract_amount = 0.0f;
buffer_mode_batch_upload_send_null = true;
buffer_mode_batch_upload_flag_stream = false;
stats_items_sorted = 0;
stats_light_items_joined = 0;
}
@ -399,6 +402,10 @@ public:
int settings_light_max_join_items;
int settings_ninepatch_mode;
// buffer orphaning modes
bool buffer_mode_batch_upload_send_null;
bool buffer_mode_batch_upload_flag_stream;
// uv contraction
bool settings_uv_contract;
float settings_uv_contract_amount;
@ -1028,6 +1035,10 @@ PREAMBLE(void)::batch_initialize() {
bdata.settings_light_max_join_items = CLAMP(bdata.settings_light_max_join_items, 0, 65535);
bdata.settings_item_reordering_lookahead = CLAMP(bdata.settings_item_reordering_lookahead, 0, 65535);
// allow user to override the api usage techniques using project settings
bdata.buffer_mode_batch_upload_send_null = GLOBAL_GET("rendering/options/api_usage_batching/send_null");
bdata.buffer_mode_batch_upload_flag_stream = GLOBAL_GET("rendering/options/api_usage_batching/flag_stream");
// for debug purposes, output a string with the batching options
String batching_options_string = "OpenGL ES Batching: ";
if (bdata.settings_use_batching) {

View File

@ -2450,6 +2450,11 @@ VisualServer::VisualServer() {
GLOBAL_DEF("rendering/quality/2d/ninepatch_mode", 0);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/2d/ninepatch_mode", PropertyInfo(Variant::INT, "rendering/quality/2d/ninepatch_mode", PROPERTY_HINT_ENUM, "Default,Scaling"));
GLOBAL_DEF_RST("rendering/options/api_usage_batching/send_null", true);
GLOBAL_DEF_RST("rendering/options/api_usage_batching/flag_stream", false);
GLOBAL_DEF_RST("rendering/options/api_usage_legacy/flag_stream", false);
GLOBAL_DEF_RST("rendering/options/api_usage_legacy/orphan_buffers", true);
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);