Compare commits

3 Commits

2 changed files with 60 additions and 0 deletions
+27
View File
@@ -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,
+33
View File
@@ -319,9 +319,15 @@ allocateDXT(Raster *raster, int32 dxt, int32 numLevels, bool32 hasAlpha)
glGenTextures(1, &natras->texid);
uint32 prev = bindTexture(natras->texid);
#ifndef __SWITCH__
glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat,
raster->width, raster->height,
0, natras->format, natras->type, nil);
#else
// __SWITCH__: skip this level-0 allocation. rasterUnlock's
// glCompressedTexImage2D allocates+uploads level 0 anyway, so pre-allocating
// here just wastes a driver call per texture (~0.5ms each on nouveau).
#endif
// TODO: allocate other levels...probably
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, natras->numLevels-1);
natras->filterMode = 0;
@@ -946,14 +952,41 @@ readNativeTexture(Stream *stream)
natras = GETGL3RASTEREXT(raster);
tex->raster = raster;
int32 uploadLevels = numLevels;
#ifdef __SWITCH__
// switch-mesa/nouveau charges a fixed ~0.7ms per texture-upload driver call
// regardless of data size. A txd's long tail of tiny mip levels (each an
// 8-16 byte block) then dominates load time and causes streaming hitches.
// Upload only the largest RW_SWITCH_TEX_MAXLEVELS level(s); bump this if
// distant-texture aliasing becomes noticeable.
#ifndef RW_SWITCH_TEX_MAXLEVELS
#define RW_SWITCH_TEX_MAXLEVELS 1
#endif
if(uploadLevels > RW_SWITCH_TEX_MAXLEVELS)
uploadLevels = RW_SWITCH_TEX_MAXLEVELS;
#endif
uint32 size;
uint8 *data;
for(int32 i = 0; i < numLevels; i++){
size = stream->readU32();
if(i >= uploadLevels){
// skipped level: consume its bytes, don't upload
stream->seek(size);
continue;
}
data = raster->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
stream->read8(data, size);
raster->unlock(i);
}
#ifdef __SWITCH__
if(uploadLevels < numLevels){
// cap the sampled mip level so undefined higher levels aren't read
uint32 prev = bindTexture(natras->texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, uploadLevels-1);
bindTexture(prev);
}
#endif
return tex;
}