Skip to content

Commit a312157

Browse files
committed
Apply targeted MapBufferRange optimization for NoOverwrite
- Only applies to NoOverwrite operations (not Discard) - Uses ARB_map_buffer_range extension check for better portability - More conservative approach to avoid driver-specific issues
1 parent aab8181 commit a312157

File tree

3 files changed

+21
-73
lines changed

3 files changed

+21
-73
lines changed

src/FNA3D_Driver_OpenGL.c

Lines changed: 16 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -4640,44 +4640,23 @@ static void OPENGL_SetVertexBufferData(
46404640

46414641
/* FIXME: Staging buffer for elementSizeInBytes < vertexStride! */
46424642

4643-
const GLsizeiptr updateSize = (GLsizeiptr) (elementCount * vertexStride);
4644-
4645-
#ifdef USE_ES3
4646-
/* GLES3 optimization: Use glMapBufferRange to avoid CPU-GPU sync overhead.
4647-
* GL_MAP_UNSYNCHRONIZED_BIT is critical for NoOverwrite (ring buffer) performance.
4648-
* Desktop OpenGL doesn't benefit from this, so keep GLES3-only.
4649-
*/
4650-
if (renderer->supports_ARB_map_buffer_range && renderer->glMapBufferRange != NULL)
4643+
if ( options == FNA3D_SETDATAOPTIONS_NOOVERWRITE &&
4644+
renderer->supports_ARB_map_buffer_range )
46514645
{
4652-
GLbitfield mapFlags = GL_MAP_WRITE_BIT;
4653-
4654-
if (options == FNA3D_SETDATAOPTIONS_NOOVERWRITE)
4655-
{
4656-
mapFlags |= GL_MAP_UNSYNCHRONIZED_BIT; /* No sync - huge speedup! */
4657-
}
4658-
else if (options == FNA3D_SETDATAOPTIONS_DISCARD)
4659-
{
4660-
mapFlags |= GL_MAP_INVALIDATE_RANGE_BIT; /* Invalidate old data */
4661-
}
4662-
4663-
void* ptr = renderer->glMapBufferRange(
4646+
void *ptr = renderer->glMapBufferRange(
46644647
GL_ARRAY_BUFFER,
46654648
(GLintptr) offsetInBytes,
4666-
updateSize,
4667-
mapFlags
4649+
(GLsizeiptr) (elementCount * vertexStride),
4650+
GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT
46684651
);
4669-
46704652
if (ptr != NULL)
46714653
{
4672-
SDL_memcpy(ptr, data, updateSize);
4654+
SDL_memcpy(ptr, data, (elementCount * vertexStride));
46734655
renderer->glUnmapBuffer(GL_ARRAY_BUFFER);
4674-
return;
46754656
}
4676-
/* Fall through to glBufferSubData if map failed */
4657+
return;
46774658
}
4678-
#endif
4679-
4680-
/* Fallback: standard glBufferData/glBufferSubData path */
4659+
46814660
if (options == FNA3D_SETDATAOPTIONS_DISCARD)
46824661
{
46834662
renderer->glBufferData(
@@ -4691,7 +4670,7 @@ static void OPENGL_SetVertexBufferData(
46914670
renderer->glBufferSubData(
46924671
GL_ARRAY_BUFFER,
46934672
(GLintptr) offsetInBytes,
4694-
updateSize,
4673+
(GLsizeiptr) (elementCount * vertexStride),
46954674
data
46964675
);
46974676
}
@@ -4862,39 +4841,23 @@ static void OPENGL_SetIndexBufferData(
48624841

48634842
BindIndexBuffer(renderer, glBuffer->handle);
48644843

4865-
#ifdef USE_ES3
4866-
/* GLES3 optimization: Use glMapBufferRange for index buffers too */
4867-
if (renderer->supports_ARB_map_buffer_range && renderer->glMapBufferRange != NULL)
4844+
if ( options == FNA3D_SETDATAOPTIONS_NOOVERWRITE &&
4845+
renderer->supports_ARB_map_buffer_range )
48684846
{
4869-
GLbitfield mapFlags = GL_MAP_WRITE_BIT;
4870-
4871-
if (options == FNA3D_SETDATAOPTIONS_NOOVERWRITE)
4872-
{
4873-
mapFlags |= GL_MAP_UNSYNCHRONIZED_BIT;
4874-
}
4875-
else if (options == FNA3D_SETDATAOPTIONS_DISCARD)
4876-
{
4877-
mapFlags |= GL_MAP_INVALIDATE_RANGE_BIT;
4878-
}
4879-
4880-
void* ptr = renderer->glMapBufferRange(
4847+
void *ptr = renderer->glMapBufferRange(
48814848
GL_ELEMENT_ARRAY_BUFFER,
48824849
(GLintptr) offsetInBytes,
48834850
(GLsizeiptr) dataLength,
4884-
mapFlags
4851+
GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT
48854852
);
4886-
48874853
if (ptr != NULL)
48884854
{
48894855
SDL_memcpy(ptr, data, dataLength);
48904856
renderer->glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
4891-
return;
48924857
}
4893-
/* Fall through if map failed */
4858+
return;
48944859
}
4895-
#endif
48964860

4897-
/* Fallback: standard path */
48984861
if (options == FNA3D_SETDATAOPTIONS_DISCARD)
48994862
{
49004863
renderer->glBufferData(
@@ -5377,16 +5340,8 @@ static uint8_t OPENGL_SupportsHardwareInstancing(FNA3D_Renderer *driverData)
53775340

53785341
static uint8_t OPENGL_SupportsNoOverwrite(FNA3D_Renderer *driverData)
53795342
{
5380-
/* NoOverwrite (ring buffer optimization) is critical for GLES3 SpriteBatch performance.
5381-
* On desktop OpenGL, keep disabled as drivers handle buffer updates differently.
5382-
* GLES3 benefits greatly from avoiding frequent glBufferData orphaning.
5383-
*/
5384-
#ifdef USE_ES3
5385-
return 1; /* Enable for GLES3 only */
5386-
#else
5387-
(void) driverData; /* Unused in desktop OpenGL */
5388-
return 0; /* Keep disabled for desktop OpenGL */
5389-
#endif
5343+
OpenGLRenderer *renderer = (OpenGLRenderer*) driverData;
5344+
return renderer->supports_ARB_map_buffer_range;
53905345
}
53915346

53925347
static uint8_t OPENGL_SupportsSRGBRenderTargets(FNA3D_Renderer *driverData)

src/FNA3D_Driver_OpenGL.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,9 @@ typedef unsigned char GLboolean;
232232
#define GL_STATIC_DRAW 0x88E4
233233
#define GL_MAX_VERTEX_ATTRIBS 0x8869
234234

235-
/* Buffer map flags (GLES3 optimization) */
236-
#ifdef USE_ES3
235+
/* NoOverwrite Uploads */
237236
#define GL_MAP_WRITE_BIT 0x0002
238-
#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
239237
#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
240-
#endif
241238

242239
/* Render targets */
243240
#define GL_FRAMEBUFFER 0x8D40

src/FNA3D_Driver_OpenGL_glfuncs.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,12 @@ GL_EXT(EXT_framebuffer_blit)
3838
GL_EXT(EXT_framebuffer_multisample)
3939
GL_EXT(ARB_internalformat_query)
4040
GL_EXT(ARB_invalidate_subdata)
41-
#ifdef USE_ES3
42-
GL_EXT(ARB_map_buffer_range)
43-
#endif
4441
GL_EXT(ARB_draw_instanced)
4542
GL_EXT(ARB_instanced_arrays)
4643
GL_EXT(ARB_draw_elements_base_vertex)
4744
GL_EXT(EXT_draw_buffers2)
4845
GL_EXT(ARB_texture_multisample)
46+
GL_EXT(ARB_map_buffer_range)
4947
GL_EXT(KHR_debug)
5048
GL_EXT(GREMEDY_string_marker)
5149

@@ -155,11 +153,6 @@ GL_PROC(ARB_internalformat_query, void, glGetInternalformativ, (GLenum a, GLenum
155153
/* This is mostly needed by ES3, where loads/stores are a huge slowdown */
156154
GL_PROC(ARB_invalidate_subdata, void, glInvalidateFramebuffer, (GLenum a, GLsizei b, const GLenum *c))
157155

158-
/* Buffer mapping for GLES3 optimization */
159-
#ifdef USE_ES3
160-
GL_PROC_EXT(ARB_map_buffer_range, EXT, GLvoid*, glMapBufferRange, (GLenum a, GLintptr b, GLsizeiptr c, GLbitfield d))
161-
#endif
162-
163156
/* Hardware instancing is nice to have, but isn't used all the time */
164157
GL_PROC(ARB_draw_instanced, void, glDrawElementsInstanced, (GLenum a, GLsizei b, GLenum c, const GLvoid *d, GLsizei e))
165158
GL_PROC(ARB_instanced_arrays, void, glVertexAttribDivisor, (GLuint a, GLuint b))
@@ -178,6 +171,9 @@ GL_PROC(EXT_draw_buffers2, void, glColorMaski, (GLuint a, GLboolean b, GLboolean
178171
/* Probably used by nobody, honestly */
179172
GL_PROC(ARB_texture_multisample, void, glSampleMaski, (GLuint a, GLuint b))
180173

174+
/* Technically UnmapBuffer is core, but useless without MapBufferRange */
175+
GL_PROC_EXT(ARB_map_buffer_range, EXT, GLvoid*, glMapBufferRange, (GLenum a, GLintptr b, GLsizeiptr c, GLbitfield d))
176+
181177
/* "NOTE: when implemented in an OpenGL ES context, all entry points defined
182178
* by this extension must have a "KHR" suffix. When implemented in an
183179
* OpenGL context, all entry points must have NO suffix, as shown below."

0 commit comments

Comments
 (0)