Reduce glBufferSubData calls in legacy renderer

This is part of effort to make more efficient use of the API for devices with poor drivers. This eliminates multiple calls to glBufferSubData per update.
This commit is contained in:
lawnjelly 2020-10-18 10:41:42 +01:00
parent c2290dbedd
commit 74c460fb67
4 changed files with 55 additions and 19 deletions

View File

@ -446,8 +446,21 @@ void RasterizerCanvasBaseGLES2::_draw_polygon(const int *p_indices, int p_index_
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
// precalculate the buffer size ahead of time instead of making multiple glBufferSubData calls
uint32_t total_buffer_size = sizeof(Vector2) * p_vertex_count;
if (!p_singlecolor && p_colors) {
total_buffer_size += sizeof(Color) * p_vertex_count;
}
if (p_uvs) {
total_buffer_size += sizeof(Vector2) * p_vertex_count;
}
if (p_weights && p_bones) {
total_buffer_size += sizeof(float) * 4 * p_vertex_count; // weights
total_buffer_size += sizeof(int) * 4 * p_vertex_count; // bones
}
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, total_buffer_size, p_vertices);
glEnableVertexAttribArray(VS::ARRAY_VERTEX);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL);
@ -461,14 +474,12 @@ void RasterizerCanvasBaseGLES2::_draw_polygon(const int *p_indices, int p_index_
glDisableVertexAttribArray(VS::ARRAY_COLOR);
glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
} else {
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors);
glEnableVertexAttribArray(VS::ARRAY_COLOR);
glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
buffer_ofs += sizeof(Color) * p_vertex_count;
}
if (p_uvs) {
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs);
glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
buffer_ofs += sizeof(Vector2) * p_vertex_count;
@ -477,12 +488,10 @@ void RasterizerCanvasBaseGLES2::_draw_polygon(const int *p_indices, int p_index_
}
if (p_weights && p_bones) {
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(float) * 4 * p_vertex_count, p_weights);
glEnableVertexAttribArray(VS::ARRAY_WEIGHTS);
glVertexAttribPointer(VS::ARRAY_WEIGHTS, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs));
buffer_ofs += sizeof(float) * 4 * p_vertex_count;
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(int) * 4 * p_vertex_count, p_bones);
glEnableVertexAttribArray(VS::ARRAY_BONES);
glVertexAttribPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, GL_FALSE, sizeof(int) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs));
buffer_ofs += sizeof(int) * 4 * p_vertex_count;
@ -516,8 +525,17 @@ void RasterizerCanvasBaseGLES2::_draw_generic(GLuint p_primitive, int p_vertex_c
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
// precalculate the buffer size ahead of time instead of making multiple glBufferSubData calls
uint32_t total_buffer_size = sizeof(Vector2) * p_vertex_count;
if (!p_singlecolor && p_colors) {
total_buffer_size += sizeof(Color) * p_vertex_count;
}
if (p_uvs) {
total_buffer_size += sizeof(Vector2) * p_vertex_count;
}
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, total_buffer_size, p_vertices);
glEnableVertexAttribArray(VS::ARRAY_VERTEX);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL);
@ -531,14 +549,12 @@ void RasterizerCanvasBaseGLES2::_draw_generic(GLuint p_primitive, int p_vertex_c
glDisableVertexAttribArray(VS::ARRAY_COLOR);
glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
} else {
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors);
glEnableVertexAttribArray(VS::ARRAY_COLOR);
glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
buffer_ofs += sizeof(Color) * p_vertex_count;
}
if (p_uvs) {
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs);
glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
} else {

View File

@ -3788,14 +3788,17 @@ void RasterizerStorageGLES2::_update_skeleton_transform_buffer(const PoolVector<
glBindBuffer(GL_ARRAY_BUFFER, resources.skeleton_transform_buffer);
uint32_t buffer_size = p_size * sizeof(float);
if (p_size > resources.skeleton_transform_buffer_size) {
// new requested buffer is bigger, so resizing the GPU buffer
resources.skeleton_transform_buffer_size = p_size;
glBufferData(GL_ARRAY_BUFFER, p_size * sizeof(float), p_data.read().ptr(), GL_DYNAMIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, buffer_size, p_data.read().ptr(), GL_DYNAMIC_DRAW);
} else {
glBufferSubData(GL_ARRAY_BUFFER, 0, p_size * sizeof(float), p_data.read().ptr());
// 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());
}
glBindBuffer(GL_ARRAY_BUFFER, 0);

View File

@ -348,8 +348,21 @@ void RasterizerCanvasBaseGLES3::_draw_polygon(const int *p_indices, int p_index_
glBindVertexArray(data.polygon_buffer_pointer_array);
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
// precalculate the buffer size ahead of time instead of making multiple glBufferSubData calls
uint32_t total_buffer_size = sizeof(Vector2) * p_vertex_count;
if (!p_singlecolor && p_colors) {
total_buffer_size += sizeof(Color) * p_vertex_count;
}
if (p_uvs) {
total_buffer_size += sizeof(Vector2) * p_vertex_count;
}
if (p_weights && p_bones) {
total_buffer_size += sizeof(int) * 4 * p_vertex_count; // bones
total_buffer_size += sizeof(float) * 4 * p_vertex_count; // weights
}
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, total_buffer_size, p_vertices);
glEnableVertexAttribArray(VS::ARRAY_VERTEX);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
@ -368,7 +381,6 @@ void RasterizerCanvasBaseGLES3::_draw_polygon(const int *p_indices, int p_index_
glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
} else {
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors);
glEnableVertexAttribArray(VS::ARRAY_COLOR);
glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
buffer_ofs += sizeof(Color) * p_vertex_count;
@ -380,7 +392,6 @@ void RasterizerCanvasBaseGLES3::_draw_polygon(const int *p_indices, int p_index_
if (p_uvs) {
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs);
glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
buffer_ofs += sizeof(Vector2) * p_vertex_count;
@ -395,13 +406,11 @@ void RasterizerCanvasBaseGLES3::_draw_polygon(const int *p_indices, int p_index_
if (p_bones && p_weights) {
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(int) * 4 * p_vertex_count, p_bones);
glEnableVertexAttribArray(VS::ARRAY_BONES);
//glVertexAttribPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, false, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs);
glVertexAttribIPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, sizeof(int) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs));
buffer_ofs += sizeof(int) * 4 * p_vertex_count;
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(float) * 4 * p_vertex_count, p_weights);
glEnableVertexAttribArray(VS::ARRAY_WEIGHTS);
glVertexAttribPointer(VS::ARRAY_WEIGHTS, 4, GL_FLOAT, false, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs));
buffer_ofs += sizeof(float) * 4 * p_vertex_count;
@ -439,9 +448,18 @@ void RasterizerCanvasBaseGLES3::_draw_generic(GLuint p_primitive, int p_vertex_c
glBindVertexArray(data.polygon_buffer_pointer_array);
glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
// precalculate the buffer size ahead of time instead of making multiple glBufferSubData calls
uint32_t total_buffer_size = sizeof(Vector2) * p_vertex_count;
if (!p_singlecolor && p_colors) {
total_buffer_size += sizeof(Color) * p_vertex_count;
}
if (p_uvs) {
total_buffer_size += sizeof(Vector2) * p_vertex_count;
}
//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, total_buffer_size, p_vertices);
glEnableVertexAttribArray(VS::ARRAY_VERTEX);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
@ -457,7 +475,6 @@ void RasterizerCanvasBaseGLES3::_draw_generic(GLuint p_primitive, int p_vertex_c
glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
} else {
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors);
glEnableVertexAttribArray(VS::ARRAY_COLOR);
glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
buffer_ofs += sizeof(Color) * p_vertex_count;
@ -465,7 +482,6 @@ void RasterizerCanvasBaseGLES3::_draw_generic(GLuint p_primitive, int p_vertex_c
if (p_uvs) {
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs);
glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
buffer_ofs += sizeof(Vector2) * p_vertex_count;

View File

@ -5085,7 +5085,8 @@ void RasterizerStorageGLES3::update_dirty_multimeshes() {
if (multimesh->size && multimesh->dirty_data) {
glBindBuffer(GL_ARRAY_BUFFER, multimesh->buffer);
glBufferSubData(GL_ARRAY_BUFFER, 0, multimesh->data.size() * sizeof(float), multimesh->data.ptr());
uint32_t buffer_size = multimesh->data.size() * sizeof(float);
glBufferData(GL_ARRAY_BUFFER, buffer_size, multimesh->data.ptr(), GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}