From a055d07fc558c88d13fbcaa29a63ba08410a57f6 Mon Sep 17 00:00:00 2001 From: Dima353 <75039669+Dima353@users.noreply.github.com> Date: Tue, 21 Jul 2026 22:38:51 +0300 Subject: [PATCH] gl3: orphan im2D/im3D buffers at actual size on Switch --- src/gl/gl3immed.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/gl/gl3immed.cpp b/src/gl/gl3immed.cpp index 3b4aae4..c8631d2 100644 --- a/src/gl/gl3immed.cpp +++ b/src/gl/gl3immed.cpp @@ -133,8 +133,19 @@ im2DRenderPrimitive(PrimitiveType primType, void *vertices, int32 numVertices) #endif glBindBuffer(GL_ARRAY_BUFFER, im2DVbo); +#ifdef __SWITCH__ + // Orphan with exactly the size we need, in one call that also uploads. + // The stock path orphans the whole STARTVERTICES buffer (~240KB) on every + // single 2D draw - even a 4-vertex sprite - and hundreds of those per frame + // exhaust nouveau's buffer allocator. It then hands back a buffer with no + // backing store and glBufferSubData memcpy's into null (Data Abort at 0). + // Orphaning itself must stay: without it the GPU may still be reading the + // buffer we overwrite, which mixes geometry between draws. + glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(Im2DVertex), vertices, GL_STREAM_DRAW); +#else glBufferData(GL_ARRAY_BUFFER, STARTVERTICES*sizeof(Im2DVertex), nil, GL_STREAM_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices*sizeof(Im2DVertex), vertices); +#endif if(im2dOverrideShader) im2dOverrideShader->use(); @@ -163,12 +174,20 @@ im2DRenderIndexedPrimitive(PrimitiveType primType, #endif glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2DIbo); +#ifdef __SWITCH__ + glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices*2, indices, GL_STREAM_DRAW); +#else glBufferData(GL_ELEMENT_ARRAY_BUFFER, STARTINDICES*2, nil, GL_STREAM_DRAW); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, numIndices*2, indices); +#endif glBindBuffer(GL_ARRAY_BUFFER, im2DVbo); +#ifdef __SWITCH__ + glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(Im2DVertex), vertices, GL_STREAM_DRAW); +#else glBufferData(GL_ARRAY_BUFFER, STARTVERTICES*sizeof(Im2DVertex), nil, GL_STREAM_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices*sizeof(Im2DVertex), vertices); +#endif if(im2dOverrideShader) im2dOverrideShader->use(); @@ -263,8 +282,12 @@ im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags) #endif glBindBuffer(GL_ARRAY_BUFFER, im3DVbo); +#ifdef __SWITCH__ + glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(Im3DVertex), vertices, GL_STREAM_DRAW); +#else glBufferData(GL_ARRAY_BUFFER, STARTVERTICES*sizeof(Im3DVertex), nil, GL_STREAM_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices*sizeof(Im3DVertex), vertices); +#endif #ifndef RW_GL_USE_VAOS setAttribPointers(im3dattribDesc, 3); #endif @@ -284,8 +307,12 @@ void im3DRenderIndexedPrimitive(PrimitiveType primType, void *indices, int32 numIndices) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im3DIbo); +#ifdef __SWITCH__ + glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices*2, indices, GL_STREAM_DRAW); +#else glBufferData(GL_ELEMENT_ARRAY_BUFFER, STARTINDICES*2, nil, GL_STREAM_DRAW); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, numIndices*2, indices); +#endif flushCache(); glDrawElements(primTypeMap[primType], numIndices,