Browse Source

Merge pull request #23386 from eska014/buffersubdata

Use BufferSubData instead of MapBufferRange in non-ES platforms
Rémi Verschelde 6 years ago
parent
commit
187507d4ba

+ 20 - 1
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -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]) {
 			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
 				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;
 				SortArray<RasterizerGLES3Particle, RasterizerGLES3ParticleSort> sorter;
 
 
@@ -1440,7 +1449,17 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo
 
 
 				sorter.sort(particle_array, particles->amount);
 				sorter.sort(particle_array, particles->amount);
 
 
+#ifndef __EMSCRIPTEN__
 				glUnmapBuffer(GL_ARRAY_BUFFER);
 				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
 #ifdef DEBUG_ENABLED
 				if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->instancing_array_wireframe_id) {
 				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
 					glBindVertexArray(s->instancing_array_wireframe_id); // use the wireframe instancing array ID

+ 74 - 22
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -101,6 +101,28 @@
 #define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
 #define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
 #define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
 #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) {
 void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type) {
 
 
 #ifdef GLES_OVER_GL
 #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];
 	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;
 	PoolVector<uint8_t> ret;
 	ret.resize(surface->array_byte_size);
 	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();
 		PoolVector<uint8_t>::Write w = ret.write();
 		copymem(w.ptr(), data, surface->array_byte_size);
 		copymem(w.ptr(), data, surface->array_byte_size);
 	}
 	}
 	glUnmapBuffer(GL_ARRAY_BUFFER);
 	glUnmapBuffer(GL_ARRAY_BUFFER);
+#endif
 
 
+	glBindBuffer(GL_ARRAY_BUFFER, 0);
 	return ret;
 	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>());
 	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;
 	PoolVector<uint8_t> ret;
 	ret.resize(surface->index_array_byte_size);
 	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();
 		PoolVector<uint8_t>::Write w = ret.write();
 		copymem(w.ptr(), data, surface->index_array_byte_size);
 		copymem(w.ptr(), data, surface->index_array_byte_size);
 	}
 	}
-
 	glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
 	glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
+#endif
 
 
+	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 	return ret;
 	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++) {
 	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;
 		PoolVector<uint8_t> ret;
 		ret.resize(mesh->surfaces[p_surface]->array_byte_size);
 		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();
 			PoolVector<uint8_t>::Write w = ret.write();
 			copymem(w.ptr(), data, mesh->surfaces[p_surface]->array_byte_size);
 			copymem(w.ptr(), data, mesh->surfaces[p_surface]->array_byte_size);
 		}
 		}
+		glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
+#endif
 
 
 		bsarr.push_back(ret);
 		bsarr.push_back(ret);
-
-		glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
 	}
 	}
 
 
 	return bsarr;
 	return bsarr;
@@ -6001,9 +6035,21 @@ AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) {
 	const Particles *particles = particles_owner.getornull(p_particles);
 	const Particles *particles = particles_owner.getornull(p_particles);
 	ERR_FAIL_COND_V(!particles, AABB());
 	ERR_FAIL_COND_V(!particles, AABB());
 
 
+	const float *data;
 	glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]);
 	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;
 	AABB aabb;
 
 
 	Transform inv = particles->emission_transform.affine_inverse();
 	Transform inv = particles->emission_transform.affine_inverse();
@@ -6020,7 +6066,13 @@ AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) {
 			aabb.expand_to(pos);
 			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);
 	glUnmapBuffer(GL_ARRAY_BUFFER);
+#endif
+
 	glBindBuffer(GL_ARRAY_BUFFER, 0);
 	glBindBuffer(GL_ARRAY_BUFFER, 0);
 
 
 	float longest_axis = 0;
 	float longest_axis = 0;

+ 6 - 0
drivers/gles3/rasterizer_storage_gles3.h

@@ -43,6 +43,12 @@
 #include "shaders/cubemap_filter.glsl.gen.h"
 #include "shaders/cubemap_filter.glsl.gen.h"
 #include "shaders/particles.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 RasterizerCanvasGLES3;
 class RasterizerSceneGLES3;
 class RasterizerSceneGLES3;