Use BufferSubData instead of MapBufferRange in HTML5 platform

WebGL does not support MapBufferRange or UnmapBuffer.
Also used in non-ES platforms where an extra-copy is avoided.
This commit is contained in:
Leon Krause 2018-10-29 20:39:18 +01:00
parent 0a80ceaf02
commit 92e7c8daf0
3 changed files with 100 additions and 23 deletions

View File

@ -1428,7 +1428,16 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo
if (particles->draw_order == VS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->particle_valid_histories[1]) {
glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[1]); //modify the buffer, this was used 2 frames ago so it should be good enough for flushing
RasterizerGLES3Particle *particle_array = (RasterizerGLES3Particle *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 24 * sizeof(float), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
RasterizerGLES3Particle *particle_array;
#ifndef __EMSCRIPTEN__
particle_array = static_cast<RasterizerGLES3Particle *>(glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 24 * sizeof(float), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
#else
PoolVector<RasterizerGLES3Particle> particle_vector;
particle_vector.resize(particles->amount);
PoolVector<RasterizerGLES3Particle>::Write w = particle_vector.write();
particle_array = w.ptr();
glGetBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(RasterizerGLES3Particle), particle_array);
#endif
SortArray<RasterizerGLES3Particle, RasterizerGLES3ParticleSort> sorter;
@ -1440,7 +1449,17 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo
sorter.sort(particle_array, particles->amount);
#ifndef __EMSCRIPTEN__
glUnmapBuffer(GL_ARRAY_BUFFER);
#else
w = PoolVector<RasterizerGLES3Particle>::Write();
particle_array = NULL;
{
PoolVector<RasterizerGLES3Particle>::Read r = particle_vector.read();
glBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(RasterizerGLES3Particle), r.ptr());
}
particle_vector = PoolVector<RasterizerGLES3Particle>();
#endif
#ifdef DEBUG_ENABLED
if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->instancing_array_wireframe_id) {
glBindVertexArray(s->instancing_array_wireframe_id); // use the wireframe instancing array ID

View File

@ -101,6 +101,28 @@
#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data) {
/* clang-format off */
EM_ASM({
GLctx.getBufferSubData($0, $1, HEAPU8, $2, $3);
}, target, offset, data, size);
/* clang-format on */
}
void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) {
/* clang-format off */
EM_ASM({
GLctx.bufferSubData($0, $1, HEAPU8, $2, $3);
}, target, offset, data, size);
/* clang-format on */
}
#endif
void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type) {
#ifdef GLES_OVER_GL
@ -3494,21 +3516,26 @@ PoolVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_array(RID p_mesh, i
Surface *surface = mesh->surfaces[p_surface];
glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id);
void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, surface->array_byte_size, GL_MAP_READ_BIT);
ERR_FAIL_COND_V(!data, PoolVector<uint8_t>());
PoolVector<uint8_t> ret;
ret.resize(surface->array_byte_size);
glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id);
#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
{
PoolVector<uint8_t>::Write w = ret.write();
glGetBufferSubData(GL_ARRAY_BUFFER, 0, surface->array_byte_size, w.ptr());
}
#else
void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, surface->array_byte_size, GL_MAP_READ_BIT);
ERR_FAIL_NULL_V(data, PoolVector<uint8_t>());
{
PoolVector<uint8_t>::Write w = ret.write();
copymem(w.ptr(), data, surface->array_byte_size);
}
glUnmapBuffer(GL_ARRAY_BUFFER);
#endif
glBindBuffer(GL_ARRAY_BUFFER, 0);
return ret;
}
@ -3521,22 +3548,26 @@ PoolVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_index_array(RID p_m
ERR_FAIL_COND_V(surface->index_array_len == 0, PoolVector<uint8_t>());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id);
void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, GL_MAP_READ_BIT);
ERR_FAIL_COND_V(!data, PoolVector<uint8_t>());
PoolVector<uint8_t> ret;
ret.resize(surface->index_array_byte_size);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id);
#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
{
PoolVector<uint8_t>::Write w = ret.write();
glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, w.ptr());
}
#else
void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, GL_MAP_READ_BIT);
ERR_FAIL_NULL_V(data, PoolVector<uint8_t>());
{
PoolVector<uint8_t>::Write w = ret.write();
copymem(w.ptr(), data, surface->index_array_byte_size);
}
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
#endif
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
return ret;
}
@ -3577,23 +3608,26 @@ Vector<PoolVector<uint8_t> > RasterizerStorageGLES3::mesh_surface_get_blend_shap
for (int i = 0; i < mesh->surfaces[p_surface]->blend_shapes.size(); i++) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->surfaces[p_surface]->blend_shapes[i].vertex_id);
void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->surfaces[p_surface]->array_byte_size, GL_MAP_READ_BIT);
ERR_FAIL_COND_V(!data, Vector<PoolVector<uint8_t> >());
PoolVector<uint8_t> ret;
ret.resize(mesh->surfaces[p_surface]->array_byte_size);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->surfaces[p_surface]->blend_shapes[i].vertex_id);
#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
{
PoolVector<uint8_t>::Write w = ret.write();
glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->surfaces[p_surface]->array_byte_size, w.ptr());
}
#else
void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->surfaces[p_surface]->array_byte_size, GL_MAP_READ_BIT);
ERR_FAIL_COND_V(!data, Vector<PoolVector<uint8_t> >());
{
PoolVector<uint8_t>::Write w = ret.write();
copymem(w.ptr(), data, mesh->surfaces[p_surface]->array_byte_size);
}
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
#endif
bsarr.push_back(ret);
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
}
return bsarr;
@ -6001,9 +6035,21 @@ AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) {
const Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND_V(!particles, AABB());
const float *data;
glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]);
float *data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, GL_MAP_READ_BIT);
#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
PoolVector<uint8_t> vector;
vector.resize(particles->amount * 16 * 6);
{
PoolVector<uint8_t>::Write w = vector.write();
glGetBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, w.ptr());
}
PoolVector<uint8_t>::Read r = vector.read();
data = reinterpret_cast<const float *>(r.ptr());
#else
data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, GL_MAP_READ_BIT);
#endif
AABB aabb;
Transform inv = particles->emission_transform.affine_inverse();
@ -6020,7 +6066,13 @@ AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) {
aabb.expand_to(pos);
}
#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
r = PoolVector<uint8_t>::Read();
vector = PoolVector<uint8_t>();
#else
glUnmapBuffer(GL_ARRAY_BUFFER);
#endif
glBindBuffer(GL_ARRAY_BUFFER, 0);
float longest_axis = 0;

View File

@ -43,6 +43,12 @@
#include "shaders/cubemap_filter.glsl.gen.h"
#include "shaders/particles.glsl.gen.h"
// WebGL 2.0 has no MapBufferRange/UnmapBuffer, but offers a non-ES style BufferSubData API instead.
#ifdef __EMSCRIPTEN__
void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);
void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
#endif
class RasterizerCanvasGLES3;
class RasterizerSceneGLES3;