Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a055d07fc5 | |||
| 9ac7075ec9 | |||
| 64e805c718 |
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user