Texture Handler:

- Do some heavy cleanup and code refactoring.
- Add SSE2-enabled unpacking function for direct 16-bit color textures.
This commit is contained in:
rogerman 2016-10-30 23:16:49 +00:00
parent 318613e783
commit 95db2317b9
6 changed files with 1543 additions and 886 deletions

View File

@ -1196,7 +1196,8 @@ OpenGLRenderer_1_2::~OpenGLRenderer_1_2()
DestroyMultisampledFBO();
// Kill the texture cache now before all of our texture IDs disappear.
TexCache_Reset();
texCache.Reset();
texCache.Reset();
while(!ref->freeTextureIDs.empty())
{
@ -2694,7 +2695,7 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState,
Render3DError OpenGLRenderer_1_2::EndRender(const u64 frameCount)
{
//needs to happen before endgl because it could free some textureids for expired cache items
TexCache_EvictFrame();
texCache.Evict(TEXCACHE_MAX_SIZE);
this->ReadBackPixels();
@ -2967,21 +2968,21 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, bool enableT
glEnable(GL_TEXTURE_2D);
}
TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette);
if(newTexture != this->currTexture)
TexCacheItem *newTexture = texCache.GetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette);
if (newTexture != this->currTexture)
{
this->currTexture = newTexture;
//has the ogl renderer initialized the texture?
if(this->currTexture->GetDeleteCallback() == NULL)
if (this->currTexture->GetDeleteCallback() == NULL)
{
this->currTexture->SetDeleteCallback(&texDeleteCallback, this, NULL);
if(OGLRef.freeTextureIDs.empty())
if (OGLRef.freeTextureIDs.empty())
{
this->ExpandFreeTextures();
}
this->currTexture->texid = (u64)OGLRef.freeTextureIDs.front();
this->currTexture->texid = (u32)OGLRef.freeTextureIDs.front();
OGLRef.freeTextureIDs.pop();
glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid);
@ -2989,7 +2990,7 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, bool enableT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
const NDSTextureFormat texFormat = this->currTexture->GetTextureFormat();
const u32 *textureSrc = (u32 *)this->currTexture->decoded;
const u32 *textureSrc = this->currTexture->unpackData;
size_t texWidth = this->currTexture->sizeX;
size_t texHeight = this->currTexture->sizeY;
@ -3133,7 +3134,7 @@ Render3DError OpenGLRenderer_1_2::Reset()
memset(this->clearImagePolyIDBuffer, 0, sizeof(this->clearImagePolyIDBuffer));
memset(this->clearImageFogBuffer, 0, sizeof(this->clearImageFogBuffer));
TexCache_Reset();
texCache.Reset();
return OGLERROR_NOERR;
}
@ -4618,21 +4619,21 @@ Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY &thePoly, bool enableT
glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE);
glUniform1i(OGLRef.uniformTexSingleBitAlpha, (params.texFormat != TEXMODE_A3I5 && params.texFormat != TEXMODE_A5I3) ? GL_TRUE : GL_FALSE);
TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette);
if(newTexture != this->currTexture)
TexCacheItem *newTexture = texCache.GetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette);
if (newTexture != this->currTexture)
{
this->currTexture = newTexture;
//has the ogl renderer initialized the texture?
if(this->currTexture->GetDeleteCallback() == NULL)
if (this->currTexture->GetDeleteCallback() == NULL)
{
this->currTexture->SetDeleteCallback(&texDeleteCallback, this, NULL);
if(OGLRef.freeTextureIDs.empty())
if (OGLRef.freeTextureIDs.empty())
{
this->ExpandFreeTextures();
}
this->currTexture->texid = (u64)OGLRef.freeTextureIDs.front();
this->currTexture->texid = (u32)OGLRef.freeTextureIDs.front();
OGLRef.freeTextureIDs.pop();
glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid);
@ -4640,7 +4641,7 @@ Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY &thePoly, bool enableT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
const NDSTextureFormat texFormat = this->currTexture->GetTextureFormat();
const u32 *textureSrc = (u32 *)this->currTexture->decoded;
const u32 *textureSrc = this->currTexture->unpackData;
size_t texWidth = this->currTexture->sizeX;
size_t texHeight = this->currTexture->sizeY;

View File

@ -1695,21 +1695,21 @@ Render3DError OpenGLRenderer_3_2::SetupTexture(const POLY &thePoly, bool enableT
return OGLERROR_NOERR;
}
TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette);
if(newTexture != this->currTexture)
TexCacheItem *newTexture = texCache.GetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette);
if (newTexture != this->currTexture)
{
this->currTexture = newTexture;
//has the ogl renderer initialized the texture?
if(this->currTexture->GetDeleteCallback() == NULL)
if (this->currTexture->GetDeleteCallback() == NULL)
{
this->currTexture->SetDeleteCallback(&texDeleteCallback, this, NULL);
if(OGLRef.freeTextureIDs.empty())
if (OGLRef.freeTextureIDs.empty())
{
this->ExpandFreeTextures();
}
this->currTexture->texid = (u64)OGLRef.freeTextureIDs.front();
this->currTexture->texid = (u32)OGLRef.freeTextureIDs.front();
OGLRef.freeTextureIDs.pop();
glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid);
@ -1717,7 +1717,7 @@ Render3DError OpenGLRenderer_3_2::SetupTexture(const POLY &thePoly, bool enableT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
const NDSTextureFormat texFormat = this->currTexture->GetTextureFormat();
const u32 *textureSrc = (u32 *)this->currTexture->decoded;
const u32 *textureSrc = this->currTexture->unpackData;
size_t texWidth = this->currTexture->sizeX;
size_t texHeight = this->currTexture->sizeY;

View File

@ -461,7 +461,7 @@ public:
sampler.dowrap(iu, iv);
FragmentColor color;
color.color = ((u32*)lastTexKey->decoded)[(iv<<sampler.wshift)+iu];
color.color = lastTexKey->unpackData[(iv<<sampler.wshift)+iu];
return color;
}
@ -1373,7 +1373,7 @@ void SoftRasterizerRenderer::setupTextures()
const POLY &firstPoly = *firstClippedPoly.poly;
u32 lastTexParams = firstPoly.texParam;
u32 lastTexPalette = firstPoly.texPalette;
TexCacheItem *lastTexKey = TexCache_SetTexture(TexFormat_15bpp, firstPoly.texParam, firstPoly.texPalette);
TexCacheItem *lastTexKey = texCache.GetTexture(TexFormat_15bpp, firstPoly.texParam, firstPoly.texPalette);
for (size_t i = 0; i < this->_clippedPolyCount; i++)
{
@ -1386,7 +1386,7 @@ void SoftRasterizerRenderer::setupTextures()
//and then it won't be safe.
if (lastTexParams != thePoly.texParam || lastTexPalette != thePoly.texPalette)
{
lastTexKey = TexCache_SetTexture(TexFormat_15bpp, thePoly.texParam, thePoly.texPalette);
lastTexKey = texCache.GetTexture(TexFormat_15bpp, thePoly.texParam, thePoly.texPalette);
lastTexParams = thePoly.texParam;
lastTexPalette = thePoly.texPalette;
}
@ -1537,7 +1537,7 @@ Render3DError SoftRasterizerRenderer::RenderGeometry(const GFX3D_State &renderSt
{
rasterizerUnit[0].mainLoop<false>();
this->_renderGeometryNeedsFinish = false;
TexCache_EvictFrame(); // Since we're finishing geometry rendering here and now, also check the texture cache now.
texCache.Evict(TEXCACHE_MAX_SIZE); // Since we're finishing geometry rendering here and now, also check the texture cache now.
}
// printf("rendered %d of %d polys after backface culling\n",gfx3d.polylist->count-culled,gfx3d.polylist->count);
@ -1888,7 +1888,7 @@ Render3DError SoftRasterizerRenderer::Reset()
memset(this->clearImagePolyIDBuffer, 0, sizeof(this->clearImagePolyIDBuffer));
memset(this->clearImageFogBuffer, 0, sizeof(this->clearImageFogBuffer));
TexCache_Reset();
texCache.Reset();
return RENDER3DERROR_NOERR;
}
@ -1947,7 +1947,7 @@ Render3DError SoftRasterizerRenderer::RenderFinish()
}
// Now that geometry rendering is finished on all threads, check the texture cache.
TexCache_EvictFrame();
texCache.Evict(TEXCACHE_MAX_SIZE);
// Do multithreaded post-processing.
if (this->currentRenderState->enableEdgeMarking || this->currentRenderState->enableFog)

View File

@ -389,7 +389,7 @@ void Render3D::SetTextureProcessingProperties(size_t scalingFactor, bool willDep
if (needTexCacheReset)
{
TexCache_Reset();
texCache.Reset();
}
}
@ -616,7 +616,7 @@ Render3DError Render3D::Reset()
this->_willFlushFramebufferRGBA6665 = true;
this->_willFlushFramebufferRGBA5551 = true;
TexCache_Reset();
texCache.Reset();
return RENDER3DERROR_NOERR;
}
@ -658,7 +658,7 @@ Render3DError Render3D::RenderFinish()
Render3DError Render3D::VramReconfigureSignal()
{
TexCache_Invalidate();
texCache.Invalidate();
return RENDER3DERROR_NOERR;
}

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,14 @@
#include "common.h"
#include "gfx3d.h"
//this ought to be enough for anyone
//#define TEXCACHE_MAX_SIZE (64*1024*1024);
//changed by zeromus on 15-dec. I couldnt find any games that were getting anywhere NEAR 64
//metal slug burns through sprites so fast, it can test it pretty quickly though
#define TEXCACHE_MAX_SIZE (16*1024*1024)
#define PALETTE_DUMP_SIZE ((64+16+16)*1024)
enum TexCache_TexFormat
{
TexFormat_None, //used when nothing yet is cached
@ -33,11 +41,31 @@ enum TexCache_TexFormat
TexFormat_15bpp //used by rasterizer
};
class MemSpan;
class TexCacheItem;
typedef std::multimap<u32,TexCacheItem*> TTexCacheItemMultimap;
typedef void (*TexCacheItemDeleteCallback)(TexCacheItem *texItem, void *param1, void *param2);
class TexCache
{
public:
TexCache();
TTexCacheItemMultimap index;
u32 cache_size; //this is not really precise, it is off by a constant factor
u8 paletteDump[PALETTE_DUMP_SIZE];
void list_remove(TexCacheItem *item);
void list_push_front(TexCacheItem *item);
void Invalidate();
void Evict(u32 target);
void Reset();
TexCacheItem* GetTexture(TexCache_TexFormat texCacheFormat, u32 texAttributes, u32 palAttributes);
};
class TexCacheItem
{
private:
@ -46,65 +74,68 @@ private:
void *_deleteCallbackParam2;
public:
TexCacheItem()
: decode_len(0)
, decoded(NULL)
, suspectedInvalid(false)
, assumedInvalid(false)
, _deleteCallback(NULL)
, _deleteCallbackParam1(NULL)
, _deleteCallbackParam2(NULL)
, cacheFormat(TexFormat_None)
{}
TexCacheItem();
~TexCacheItem();
NDSTextureFormat packFormat;
u32 packSize;
u8 *packData;
u16 *paletteColorTable;
TexCache_TexFormat unpackFormat;
u32 unpackSize;
u32 *unpackData;
~TexCacheItem()
{
free_aligned(this->decoded);
if (this->_deleteCallback != NULL) this->_deleteCallback(this, this->_deleteCallbackParam1, this->_deleteCallbackParam2);
}
u32 decode_len;
NDSTextureFormat format;
u8* decoded; //decoded texture data
bool suspectedInvalid;
bool assumedInvalid;
TTexCacheItemMultimap::iterator iterator;
NDSTextureFormat GetTextureFormat() const { return this->format; }
u32 texformat, texpal;
u32 sizeX, sizeY;
float invSizeX, invSizeY;
u32 texid; //used by ogl renderer for the texid
TexCache_TexFormat cacheFormat;
struct Dump {
~Dump() {
delete[] texture;
}
int textureSize, indexSize;
static const int maxTextureSize=128*1024;
u8* texture;
u8 palette[256*2];
} dump;
u32 textureAttributes;
u32 paletteAttributes;
u32 paletteAddress;
u32 paletteSize;
u32 sizeX;
u32 sizeY;
float invSizeX;
float invSizeY;
TexCacheItemDeleteCallback GetDeleteCallback()
{
return this->_deleteCallback;
}
// Only used by 4x4 formatted textures
u8 *packIndexData;
u32 packSizeFirstSlot;
u32 packIndexSize;
void SetDeleteCallback(TexCacheItemDeleteCallback callbackFunc, void *inParam1, void *inParam2)
{
this->_deleteCallback = callbackFunc;
this->_deleteCallbackParam1 = inParam1;
this->_deleteCallbackParam2 = inParam2;
}
// Only used by the OpenGL renderer for the texture ID
u32 texid;
TexCacheItemDeleteCallback GetDeleteCallback() const;
void SetDeleteCallback(TexCacheItemDeleteCallback callbackFunc, void *inParam1, void *inParam2);
NDSTextureFormat GetTextureFormat() const;
void SetTextureData(const u32 attr, const MemSpan &packedData, const MemSpan &packedIndexData);
void SetTexturePalette(const u32 attr, const u16 *paletteBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void Unpack(const MemSpan &packedData);
void DebugDump();
};
void TexCache_Invalidate();
void TexCache_Reset();
void TexCache_EvictFrame();
// TODO: Delete these MemSpan based functions after testing confirms that using the dumped texture data works properly.
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackI2(const MemSpan &ms, const u16 *pal, const bool isPalZeroTransparent, u32 *dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackI4(const MemSpan &ms, const u16 *pal, const bool isPalZeroTransparent, u32 *dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackI8(const MemSpan &ms, const u16 *pal, const bool isPalZeroTransparent, u32 *dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackA3I5(const MemSpan &ms, const u16 *pal, u32 *dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackA5I3(const MemSpan &ms, const u16 *pal, u32 *dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpack4x4(const MemSpan &ms, const u32 palAddress, const u32 texAttributes, const u32 sizeX, const u32 sizeY, u32 *dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackDirect16Bit(const MemSpan &ms, u32 *dstBuffer);
TexCacheItem* TexCache_SetTexture(TexCache_TexFormat TEXFORMAT, u32 format, u32 texpal);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackI2(const size_t srcSize, const u8 *srcData, const u16 *srcPal, const bool isPalZeroTransparent, u32 *dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackI4(const size_t srcSize, const u8 *srcData, const u16 *srcPal, const bool isPalZeroTransparent, u32 *dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackI8(const size_t srcSize, const u8 *srcData, const u16 *srcPal, const bool isPalZeroTransparent, u32 *dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackA3I5(const size_t srcSize, const u8 *srcData, const u16 *srcPal, u32 *dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackA5I3(const size_t srcSize, const u8 *srcData, const u16 *srcPal, u32 *dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpack4x4(const size_t srcSize, const u8 *srcData, const u8 *srcIndex, const u32 palAddress, const u32 texAttributes, const u32 sizeX, const u32 sizeY, u32 *dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackDirect16Bit(const size_t srcSize, const u8 *srcData, u32 *dstBuffer);
extern TexCache texCache;
#endif