Texture Handler:

- Finish refactoring and cleaning up TexCache (now renamed to “TextureCache”) and TexCacheItem (now renamed to “TextureStore”).
- TextureCache items are now evicted based on age and usage instead of arbitrarily.
This commit is contained in:
rogerman 2016-11-23 20:41:07 +00:00
parent c75b9ed62b
commit 02645310b4
7 changed files with 921 additions and 640 deletions

View File

@ -636,10 +636,42 @@ static void OGLGetDriverVersion(const char *oglVersionString,
}
}
void OGLTextureDeleteCallback(TexCacheItem *texItem, void *param1, void *param2)
OpenGLTexture::OpenGLTexture()
{
OpenGLRenderer *oglRenderer = (OpenGLRenderer *)param1;
oglRenderer->DeleteTexture(texItem);
_cacheSize = GetUnpackSizeUsingFormat(TexFormat_32bpp);
_invSizeS = 0.0f;
_invSizeT = 0.0f;
glGenTextures(1, &_texID);
}
OpenGLTexture::OpenGLTexture(u32 texAttributes, u32 palAttributes) : TextureStore(texAttributes, palAttributes)
{
_cacheSize = GetUnpackSizeUsingFormat(TexFormat_32bpp);
_invSizeS = 1.0f / (float)_sizeS;
_invSizeT = 1.0f / (float)_sizeT;
glGenTextures(1, &_texID);
}
OpenGLTexture::~OpenGLTexture()
{
glDeleteTextures(1, &this->_texID);
}
GLuint OpenGLTexture::GetID() const
{
return this->_texID;
}
GLfloat OpenGLTexture::GetInvWidth() const
{
return this->_invSizeS;
}
GLfloat OpenGLTexture::GetInvHeight() const
{
return this->_invSizeT;
}
template<bool require_profile, bool enable_3_2>
@ -1199,13 +1231,6 @@ OpenGLRenderer_1_2::~OpenGLRenderer_1_2()
// Kill the texture cache now before all of our texture IDs disappear.
texCache.Reset();
while(!ref->freeTextureIDs.empty())
{
GLuint temp = ref->freeTextureIDs.front();
ref->freeTextureIDs.pop();
glDeleteTextures(1, &temp);
}
glFinish();
}
@ -1352,7 +1377,6 @@ Render3DError OpenGLRenderer_1_2::InitExtensions()
INFO("OpenGL: Multisampled FBOs are unsupported. Multisample antialiasing will be disabled.\n");
}
this->InitTextures();
this->InitFinalRenderStates(&oglExtensionSet); // This must be done last
return OGLERROR_NOERR;
@ -2063,13 +2087,6 @@ Render3DError OpenGLRenderer_1_2::InitFinalRenderStates(const std::set<std::stri
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::InitTextures()
{
this->ExpandFreeTextures();
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::InitTables()
{
static bool needTableInit = true;
@ -2228,20 +2245,6 @@ void OpenGLRenderer_1_2::GetExtensionSet(std::set<std::string> *oglExtensionSet)
}
}
Render3DError OpenGLRenderer_1_2::ExpandFreeTextures()
{
static const GLsizei kInitTextures = 128;
GLuint oglTempTextureID[kInitTextures];
glGenTextures(kInitTextures, oglTempTextureID);
for(GLsizei i = 0; i < kInitTextures; i++)
{
this->ref->freeTextureIDs.push(oglTempTextureID[i]);
}
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::EnableVertexAttributes()
{
OGLRenderRef &OGLRef = *this->ref;
@ -2416,14 +2419,6 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels()
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::DeleteTexture(const TexCacheItem *item)
{
this->ref->freeTextureIDs.push((GLuint)item->texid);
texCache.cache_size -= item->unpackSize;
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
{
OGLRenderRef &OGLRef = *this->ref;
@ -2692,7 +2687,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.Evict(TEXCACHE_MAX_SIZE);
texCache.Evict();
this->ReadBackPixels();
@ -2953,54 +2948,44 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, bool enableT
return OGLERROR_NOERR;
}
OpenGLTexture *theTexture = (OpenGLTexture *)texCache.GetTexture(thePoly.texParam, thePoly.texPalette);
const bool isNewTexture = (theTexture == NULL);
TexCacheItem *theTexture = texCache.GetTexture(thePoly.texParam, thePoly.texPalette);
if (isNewTexture)
{
theTexture = new OpenGLTexture(thePoly.texParam, thePoly.texPalette);
texCache.Add(theTexture);
}
const NDSTextureFormat packFormat = theTexture->GetPackFormat();
// Enable textures if they weren't already enabled
if (this->isShaderSupported)
{
glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE);
glUniform1i(OGLRef.uniformTexSingleBitAlpha, (theTexture->packFormat != TEXMODE_A3I5 && theTexture->packFormat != TEXMODE_A5I3) ? GL_TRUE : GL_FALSE);
glUniform2f(OGLRef.uniformPolyTexScale, theTexture->invSizeX, theTexture->invSizeY);
glUniform1i(OGLRef.uniformTexSingleBitAlpha, (packFormat != TEXMODE_A3I5 && packFormat != TEXMODE_A5I3) ? GL_TRUE : GL_FALSE);
glUniform2f(OGLRef.uniformPolyTexScale, theTexture->GetInvWidth(), theTexture->GetInvHeight());
}
else
{
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(theTexture->invSizeX, theTexture->invSizeY, 1.0f);
glScalef(theTexture->GetInvWidth(), theTexture->GetInvHeight(), 1.0f);
}
if (theTexture->unpackFormat != TexFormat_32bpp)
glBindTexture(GL_TEXTURE_2D, theTexture->GetID());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
if (theTexture->IsLoadNeeded())
{
//has the ogl renderer initialized the texture?
const bool isNewTexture = (theTexture->GetDeleteCallback() == NULL);
if (isNewTexture)
{
theTexture->SetDeleteCallback(&OGLTextureDeleteCallback, this, NULL);
if (OGLRef.freeTextureIDs.empty())
{
this->ExpandFreeTextures();
}
theTexture->texid = (u32)OGLRef.freeTextureIDs.front();
OGLRef.freeTextureIDs.pop();
theTexture->unpackSize = theTexture->GetUnpackSizeUsingFormat(TexFormat_32bpp);
texCache.cache_size += theTexture->unpackSize;
}
theTexture->Unpack<TexFormat_32bpp>((u32 *)this->_workingTextureUnpackBuffer);
glBindTexture(GL_TEXTURE_2D, (GLuint)theTexture->texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
const NDSTextureFormat texFormat = theTexture->GetTextureFormat();
const u32 *textureSrc = (u32 *)this->_workingTextureUnpackBuffer;
size_t texWidth = theTexture->sizeX;
size_t texHeight = theTexture->sizeY;
size_t texWidth = theTexture->GetWidth();
size_t texHeight = theTexture->GetHeight();
if (this->_textureDeposterizeDstSurface.Surface != NULL)
{
@ -3031,17 +3016,17 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, bool enableT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
this->TextureUpscale<2>(texFormat, textureSrc, texWidth, texHeight);
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
if (isNewTexture)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, theTexture->sizeX, theTexture->sizeY, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, theTexture->GetWidth(), theTexture->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, theTexture->sizeX, theTexture->sizeY, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, theTexture->GetWidth(), theTexture->GetHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
break;
}
@ -3051,29 +3036,29 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, bool enableT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
this->TextureUpscale<4>(texFormat, textureSrc, texWidth, texHeight);
this->TextureUpscale<4>(packFormat, textureSrc, texWidth, texHeight);
if (isNewTexture)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
texWidth = theTexture->sizeX;
texHeight = theTexture->sizeY;
this->TextureUpscale<2>(texFormat, textureSrc, texWidth, texHeight);
texWidth = theTexture->GetWidth();
texHeight = theTexture->GetHeight();
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, theTexture->sizeX, theTexture->sizeY, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, theTexture->GetWidth(), theTexture->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
texWidth = theTexture->sizeX;
texHeight = theTexture->sizeY;
this->TextureUpscale<2>(texFormat, textureSrc, texWidth, texHeight);
texWidth = theTexture->GetWidth();
texHeight = theTexture->GetHeight();
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, theTexture->sizeX, theTexture->sizeY, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, theTexture->GetWidth(), theTexture->GetHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
break;
}
@ -3095,11 +3080,9 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, bool enableT
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
}
}
else
{
//otherwise, just bind it
glBindTexture(GL_TEXTURE_2D, (GLuint)theTexture->texid);
}
theTexture->ResetCacheAge();
theTexture->IncreaseCacheUsageCount(1);
return OGLERROR_NOERR;
}
@ -3867,7 +3850,6 @@ Render3DError OpenGLRenderer_2_0::InitExtensions()
INFO("OpenGL: Multisampled FBOs are unsupported. Multisample antialiasing will be disabled.\n");
}
this->InitTextures();
this->InitFinalRenderStates(&oglExtensionSet); // This must be done last
return OGLERROR_NOERR;
@ -4644,42 +4626,32 @@ Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY &thePoly, bool enableT
return OGLERROR_NOERR;
}
TexCacheItem *theTexture = texCache.GetTexture(thePoly.texParam, thePoly.texPalette);
OpenGLTexture *theTexture = (OpenGLTexture *)texCache.GetTexture(thePoly.texParam, thePoly.texPalette);
const bool isNewTexture = (theTexture == NULL);
if (isNewTexture)
{
theTexture = new OpenGLTexture(thePoly.texParam, thePoly.texPalette);
texCache.Add(theTexture);
}
const NDSTextureFormat packFormat = theTexture->GetPackFormat();
glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE);
glUniform1i(OGLRef.uniformTexSingleBitAlpha, (theTexture->packFormat != TEXMODE_A3I5 && theTexture->packFormat != TEXMODE_A5I3) ? GL_TRUE : GL_FALSE);
glUniform2f(OGLRef.uniformPolyTexScale, theTexture->invSizeX, theTexture->invSizeY);
glUniform1i(OGLRef.uniformTexSingleBitAlpha, (packFormat != TEXMODE_A3I5 && packFormat != TEXMODE_A5I3) ? GL_TRUE : GL_FALSE);
glUniform2f(OGLRef.uniformPolyTexScale, theTexture->GetInvWidth(), theTexture->GetInvHeight());
if (theTexture->unpackFormat != TexFormat_32bpp)
glBindTexture(GL_TEXTURE_2D, theTexture->GetID());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
if (theTexture->IsLoadNeeded())
{
//has the ogl renderer initialized the texture?
const bool isNewTexture = (theTexture->GetDeleteCallback() == NULL);
if (isNewTexture)
{
theTexture->SetDeleteCallback(&OGLTextureDeleteCallback, this, NULL);
if (OGLRef.freeTextureIDs.empty())
{
this->ExpandFreeTextures();
}
theTexture->texid = (u32)OGLRef.freeTextureIDs.front();
OGLRef.freeTextureIDs.pop();
theTexture->unpackSize = theTexture->GetUnpackSizeUsingFormat(TexFormat_32bpp);
texCache.cache_size += theTexture->unpackSize;
}
theTexture->Unpack<TexFormat_32bpp>((u32 *)this->_workingTextureUnpackBuffer);
glBindTexture(GL_TEXTURE_2D, (GLuint)theTexture->texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
const NDSTextureFormat texFormat = theTexture->GetTextureFormat();
const u32 *textureSrc = (u32 *)this->_workingTextureUnpackBuffer;
size_t texWidth = theTexture->sizeX;
size_t texHeight = theTexture->sizeY;
size_t texWidth = theTexture->GetWidth();
size_t texHeight = theTexture->GetHeight();
if (this->_textureDeposterizeDstSurface.Surface != NULL)
{
@ -4710,15 +4682,17 @@ Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY &thePoly, bool enableT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
if (isNewTexture)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, theTexture->sizeX, theTexture->sizeY, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, theTexture->GetWidth(), theTexture->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, theTexture->sizeX, theTexture->sizeY, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, theTexture->GetWidth(), theTexture->GetHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
break;
}
@ -4728,29 +4702,29 @@ Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY &thePoly, bool enableT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
this->TextureUpscale<4>(texFormat, textureSrc, texWidth, texHeight);
this->TextureUpscale<4>(packFormat, textureSrc, texWidth, texHeight);
if (isNewTexture)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
texWidth = theTexture->sizeX;
texHeight = theTexture->sizeY;
this->TextureUpscale<2>(texFormat, textureSrc, texWidth, texHeight);
texWidth = theTexture->GetWidth();
texHeight = theTexture->GetHeight();
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, theTexture->sizeX, theTexture->sizeY, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, theTexture->GetWidth(), theTexture->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
texWidth = theTexture->sizeX;
texHeight = theTexture->sizeY;
this->TextureUpscale<2>(texFormat, textureSrc, texWidth, texHeight);
texWidth = theTexture->GetWidth();
texHeight = theTexture->GetHeight();
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, theTexture->sizeX, theTexture->sizeY, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, theTexture->GetWidth(), theTexture->GetHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
break;
}
@ -4772,11 +4746,9 @@ Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY &thePoly, bool enableT
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
}
}
else
{
//otherwise, just bind it
glBindTexture(GL_TEXTURE_2D, (GLuint)theTexture->texid);
}
theTexture->ResetCacheAge();
theTexture->IncreaseCacheUsageCount(1);
return OGLERROR_NOERR;
}

View File

@ -24,6 +24,7 @@
#include <set>
#include <string>
#include "render3D.h"
#include "texcache.h"
#include "types.h"
#ifndef OGLRENDER_3_2_H
@ -491,9 +492,6 @@ struct OGLRenderRef
GLuint vaoGeometryStatesID;
GLuint vaoPostprocessStatesID;
// Textures
std::queue<GLuint> freeTextureIDs;
// Client-side Buffers
GLfloat *color4fBuffer;
GLushort *vertIndexBuffer;
@ -526,8 +524,6 @@ extern CACHE_ALIGN const GLfloat divide6bitBy63_LUT[64];
extern const GLfloat PostprocessVtxBuffer[16];
extern const GLubyte PostprocessElementBuffer[6];
extern void OGLTextureDeleteCallback(TexCacheItem *texItem, void *param1, void *param2);
//This is called by OGLRender whenever it initializes.
//Platforms, please be sure to set this up.
//return true if you successfully init.
@ -559,6 +555,23 @@ extern void (*OGLCreateRenderer_3_2_Func)(OpenGLRenderer **rendererPtr);
bool IsVersionSupported(unsigned int checkVersionMajor, unsigned int checkVersionMinor, unsigned int checkVersionRevision);
class OpenGLTexture : public TextureStore
{
private:
GLuint _texID;
GLfloat _invSizeS;
GLfloat _invSizeT;
public:
OpenGLTexture();
OpenGLTexture(u32 texAttributes, u32 palAttributes);
virtual ~OpenGLTexture();
GLuint GetID() const;
GLfloat GetInvWidth() const;
GLfloat GetInvHeight() const;
};
#if defined(ENABLE_SSE2)
class OpenGLRenderer : public Render3D_SSE2
#else
@ -609,7 +622,6 @@ protected:
virtual void DestroyGeometryProgram() = 0;
virtual Render3DError CreateVAOs() = 0;
virtual void DestroyVAOs() = 0;
virtual Render3DError InitTextures() = 0;
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet) = 0;
virtual Render3DError InitTables() = 0;
virtual Render3DError InitPostprocessingPrograms(const std::string &edgeMarkVtxShader,
@ -635,7 +647,6 @@ protected:
virtual Render3DError UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer) = 0;
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet) = 0;
virtual Render3DError ExpandFreeTextures() = 0;
virtual Render3DError EnableVertexAttributes() = 0;
virtual Render3DError DisableVertexAttributes() = 0;
virtual Render3DError DownsampleFBO() = 0;
@ -648,7 +659,6 @@ public:
virtual ~OpenGLRenderer();
virtual Render3DError InitExtensions() = 0;
virtual Render3DError DeleteTexture(const TexCacheItem *item) = 0;
bool IsExtensionPresent(const std::set<std::string> *oglExtensionSet, const std::string extensionName) const;
bool ValidateShaderCompile(GLuint theShader) const;
@ -673,7 +683,6 @@ protected:
virtual void DestroyMultisampledFBO();
virtual Render3DError CreateVAOs();
virtual void DestroyVAOs();
virtual Render3DError InitTextures();
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet);
virtual Render3DError InitTables();
@ -702,7 +711,6 @@ protected:
virtual Render3DError UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer);
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
virtual Render3DError ExpandFreeTextures();
virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes();
virtual Render3DError DownsampleFBO();
@ -729,8 +737,6 @@ public:
virtual Render3DError Reset();
virtual Render3DError RenderFinish();
virtual Render3DError SetFramebufferSize(size_t w, size_t h);
virtual Render3DError DeleteTexture(const TexCacheItem *item);
};
class OpenGLRenderer_1_3 : public OpenGLRenderer_1_2

View File

@ -609,7 +609,6 @@ Render3DError OpenGLRenderer_3_2::InitExtensions()
}
}
this->InitTextures();
this->InitFinalRenderStates(&oglExtensionSet); // This must be done last
return OGLERROR_NOERR;
@ -1686,7 +1685,6 @@ Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly)
Render3DError OpenGLRenderer_3_2::SetupTexture(const POLY &thePoly, bool enableTexturing)
{
OGLRenderRef &OGLRef = *this->ref;
const PolygonTexParams params = thePoly.getTexParams();
// Check if we need to use textures
@ -1695,37 +1693,27 @@ Render3DError OpenGLRenderer_3_2::SetupTexture(const POLY &thePoly, bool enableT
return OGLERROR_NOERR;
}
TexCacheItem *theTexture = texCache.GetTexture(thePoly.texParam, thePoly.texPalette);
if (theTexture->unpackFormat != TexFormat_32bpp)
OpenGLTexture *theTexture = (OpenGLTexture *)texCache.GetTexture(thePoly.texParam, thePoly.texPalette);
const bool isNewTexture = (theTexture == NULL);
if (isNewTexture)
{
theTexture = new OpenGLTexture(thePoly.texParam, thePoly.texPalette);
texCache.Add(theTexture);
}
glBindTexture(GL_TEXTURE_2D, theTexture->GetID());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
if (theTexture->IsLoadNeeded())
{
//has the ogl renderer initialized the texture?
const bool isNewTexture = (theTexture->GetDeleteCallback() == NULL);
if (isNewTexture)
{
theTexture->SetDeleteCallback(&OGLTextureDeleteCallback, this, NULL);
if (OGLRef.freeTextureIDs.empty())
{
this->ExpandFreeTextures();
}
theTexture->texid = (u32)OGLRef.freeTextureIDs.front();
OGLRef.freeTextureIDs.pop();
theTexture->unpackSize = theTexture->GetUnpackSizeUsingFormat(TexFormat_32bpp);
texCache.cache_size += theTexture->unpackSize;
}
theTexture->Unpack<TexFormat_32bpp>((u32 *)this->_workingTextureUnpackBuffer);
glBindTexture(GL_TEXTURE_2D, (GLuint)theTexture->texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
const NDSTextureFormat texFormat = theTexture->GetTextureFormat();
const u32 *textureSrc = (u32 *)this->_workingTextureUnpackBuffer;
size_t texWidth = theTexture->sizeX;
size_t texHeight = theTexture->sizeY;
const NDSTextureFormat packFormat = theTexture->GetPackFormat();
size_t texWidth = theTexture->GetWidth();
size_t texHeight = theTexture->GetHeight();
if (this->_textureDeposterizeDstSurface.Surface != NULL)
{
@ -1756,17 +1744,17 @@ Render3DError OpenGLRenderer_3_2::SetupTexture(const POLY &thePoly, bool enableT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
this->TextureUpscale<2>(texFormat, textureSrc, texWidth, texHeight);
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
if (isNewTexture)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, theTexture->sizeX, theTexture->sizeY, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, theTexture->GetWidth(), theTexture->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, theTexture->sizeX, theTexture->sizeY, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, theTexture->GetWidth(), theTexture->GetHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
break;
}
@ -1776,29 +1764,29 @@ Render3DError OpenGLRenderer_3_2::SetupTexture(const POLY &thePoly, bool enableT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
this->TextureUpscale<4>(texFormat, textureSrc, texWidth, texHeight);
this->TextureUpscale<4>(packFormat, textureSrc, texWidth, texHeight);
if (isNewTexture)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
texWidth = theTexture->sizeX;
texHeight = theTexture->sizeY;
this->TextureUpscale<2>(texFormat, textureSrc, texWidth, texHeight);
texWidth = theTexture->GetWidth();
texHeight = theTexture->GetHeight();
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, theTexture->sizeX, theTexture->sizeY, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, theTexture->GetWidth(), theTexture->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
texWidth = theTexture->sizeX;
texHeight = theTexture->sizeY;
this->TextureUpscale<2>(texFormat, textureSrc, texWidth, texHeight);
texWidth = theTexture->GetWidth();
texHeight = theTexture->GetHeight();
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, theTexture->sizeX, theTexture->sizeY, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, theTexture->GetWidth(), theTexture->GetHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
break;
}
@ -1820,11 +1808,9 @@ Render3DError OpenGLRenderer_3_2::SetupTexture(const POLY &thePoly, bool enableT
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
}
}
else
{
//otherwise, just bind it
glBindTexture(GL_TEXTURE_2D, (GLuint)theTexture->texid);
}
theTexture->ResetCacheAge();
theTexture->IncreaseCacheUsageCount(1);
return OGLERROR_NOERR;
}

View File

@ -54,7 +54,6 @@
#include "matrix.h"
#include "render3D.h"
#include "gfx3d.h"
#include "texcache.h"
#include "MMU.h"
#include "NDSSystem.h"
#include "utils/task.h"
@ -331,7 +330,7 @@ class RasterizerUnit
{
protected:
SoftRasterizerRenderer *_softRender;
TexCacheItem *lastTexKey;
SoftRasterizerTexture *lastTexKey;
VERT* verts[MAX_CLIPPED_VERTS];
int polynum;
@ -351,19 +350,16 @@ public:
int width, height;
s32 wmask, hmask;
int wrap;
int wshift;
int texFormat;
void setup(u32 texParam)
void setup(SoftRasterizerTexture *theTexture, u32 texParam)
{
texFormat = (texParam>>26)&7;
wshift = ((texParam>>20)&0x07) + 3;
width=(1 << wshift);
height=(8 << ((texParam>>23)&0x07));
wmask = width-1;
hmask = height-1;
width = theTexture->GetRenderWidth();
height = theTexture->GetRenderHeight();
wmask = theTexture->GetRenderWidthMask();
hmask = theTexture->GetRenderHeightMask();
wrap = (texParam>>16)&0xF;
enabled = gfx3d.renderState.enableTexturing && (texFormat!=0);
enabled = gfx3d.renderState.enableTexturing && (theTexture->GetPackFormat() != TEXMODE_NONE);
}
FORCEINLINE void clamp(s32 &val, const int size, const s32 sizemask)
@ -461,7 +457,10 @@ public:
sampler.dowrap(iu, iv);
FragmentColor color;
color.color = lastTexKey->unpackData[(iv<<sampler.wshift)+iu];
const u32 *textureData = lastTexKey->GetUnpackData();
color.color = textureData[( iv << lastTexKey->GetRenderWidthShift() ) + iu];
return color;
}
@ -1006,15 +1005,15 @@ public:
const size_t dstWidth = this->_softRender->GetFramebufferWidth();
const size_t dstHeight = this->_softRender->GetFramebufferHeight();
lastTexKey = NULL;
const GFX3D_Clipper::TClippedPoly &firstClippedPoly = this->_softRender->clippedPolys[0];
const POLY &firstPoly = *firstClippedPoly.poly;
PolygonAttributes polyAttr = firstPoly.getAttributes();
u32 lastPolyAttr = firstPoly.polyAttr;
u32 lastTexParams = firstPoly.texParam;
u32 lastTexPalette = firstPoly.texPalette;
sampler.setup(firstPoly.texParam);
lastTexKey = this->_softRender->polyTexKeys[0];
sampler.setup(lastTexKey, firstPoly.texParam);
//iterate over polys
for (size_t i = 0; i < polyCount; i++)
@ -1035,13 +1034,15 @@ public:
if (lastTexParams != thePoly.texParam || lastTexPalette != thePoly.texPalette)
{
sampler.setup(thePoly.texParam);
lastTexParams = thePoly.texParam;
lastTexPalette = thePoly.texPalette;
lastTexKey = this->_softRender->polyTexKeys[i];
sampler.setup(lastTexKey, thePoly.texParam);
lastTexKey->ResetCacheAge();
lastTexKey->IncreaseCacheUsageCount(1);
}
lastTexKey = this->_softRender->polyTexKeys[i];
for (int j = 0; j < type; j++)
this->verts[j] = &clippedPoly.clipVerts[j];
for (int j = type; j < MAX_CLIPPED_VERTS; j++)
@ -1147,10 +1148,58 @@ static void SoftRasterizerRendererDestroy()
}
}
void SoftRasterizerTextureDeleteCallback(TexCacheItem *texItem, void *param1, void *param2)
SoftRasterizerTexture::SoftRasterizerTexture(u32 texAttributes, u32 palAttributes) : TextureStore(texAttributes, palAttributes)
{
free_aligned(texItem->unpackData);
texCache.cache_size -= texItem->unpackSize;
_cacheSize = GetUnpackSizeUsingFormat(TexFormat_15bpp);
_unpackData = (u32 *)malloc_alignedCacheLine(_cacheSize);
_renderWidth = _sizeS;
_renderHeight = _sizeT;
_renderWidthMask = _renderWidth - 1;
_renderHeightMask = _renderHeight - 1;
_renderWidthShift = 0;
u32 tempWidth = _renderWidth;
while ( (tempWidth & 1) == 0)
{
tempWidth >>= 1;
_renderWidthShift++;
}
}
SoftRasterizerTexture::~SoftRasterizerTexture()
{
free_aligned(this->_unpackData);
}
u32* SoftRasterizerTexture::GetUnpackData()
{
return this->_unpackData;
}
u32 SoftRasterizerTexture::GetRenderWidth() const
{
return this->_renderWidth;
}
u32 SoftRasterizerTexture::GetRenderHeight() const
{
return this->_renderHeight;
}
u32 SoftRasterizerTexture::GetRenderWidthMask() const
{
return this->_renderWidthMask;
}
u32 SoftRasterizerTexture::GetRenderHeightMask() const
{
return this->_renderHeightMask;
}
u32 SoftRasterizerTexture::GetRenderWidthShift() const
{
return this->_renderWidthShift;
}
GPU3DInterface gpu3DRasterize = {
@ -1380,19 +1429,16 @@ void SoftRasterizerRenderer::setupTextures()
u32 lastTexParams = firstPoly.texParam;
u32 lastTexPalette = firstPoly.texPalette;
TexCacheItem *lastTexItem = texCache.GetTexture(firstPoly.texParam, firstPoly.texPalette);
if (lastTexItem->unpackFormat != TexFormat_15bpp)
SoftRasterizerTexture *lastTexItem = (SoftRasterizerTexture *)texCache.GetTexture(firstPoly.texParam, firstPoly.texPalette);
if (lastTexItem == NULL)
{
const bool isNewTexture = (lastTexItem->GetDeleteCallback() == NULL);
if (isNewTexture)
{
lastTexItem->SetDeleteCallback(&SoftRasterizerTextureDeleteCallback, this, NULL);
lastTexItem->unpackSize = lastTexItem->GetUnpackSizeUsingFormat(TexFormat_15bpp);
lastTexItem->unpackData = (u32 *)malloc_alignedCacheLine(lastTexItem->unpackSize);
texCache.cache_size += lastTexItem->unpackSize;
}
lastTexItem->Unpack<TexFormat_15bpp>(lastTexItem->unpackData);
lastTexItem = new SoftRasterizerTexture(firstPoly.texParam, firstPoly.texPalette);
texCache.Add(lastTexItem);
}
if (lastTexItem->IsLoadNeeded())
{
lastTexItem->Unpack<TexFormat_15bpp>(lastTexItem->GetUnpackData());
}
for (size_t i = 0; i < this->_clippedPolyCount; i++)
@ -1406,19 +1452,16 @@ void SoftRasterizerRenderer::setupTextures()
//and then it won't be safe.
if (lastTexParams != thePoly.texParam || lastTexPalette != thePoly.texPalette)
{
lastTexItem = texCache.GetTexture(thePoly.texParam, thePoly.texPalette);
if (lastTexItem->unpackFormat != TexFormat_15bpp)
lastTexItem = (SoftRasterizerTexture *)texCache.GetTexture(thePoly.texParam, thePoly.texPalette);
if (lastTexItem == NULL)
{
const bool isNewTexture = (lastTexItem->GetDeleteCallback() == NULL);
if (isNewTexture)
{
lastTexItem->SetDeleteCallback(&SoftRasterizerTextureDeleteCallback, this, NULL);
lastTexItem->unpackSize = lastTexItem->GetUnpackSizeUsingFormat(TexFormat_15bpp);
lastTexItem->unpackData = (u32 *)malloc_alignedCacheLine(lastTexItem->unpackSize);
texCache.cache_size += lastTexItem->unpackSize;
}
lastTexItem->Unpack<TexFormat_15bpp>(lastTexItem->unpackData);
lastTexItem = new SoftRasterizerTexture(thePoly.texParam, thePoly.texPalette);
texCache.Add(lastTexItem);
}
if (lastTexItem->IsLoadNeeded())
{
lastTexItem->Unpack<TexFormat_15bpp>(lastTexItem->GetUnpackData());
}
lastTexParams = thePoly.texParam;
@ -1571,7 +1614,7 @@ Render3DError SoftRasterizerRenderer::RenderGeometry(const GFX3D_State &renderSt
{
rasterizerUnit[0].mainLoop<false>();
this->_renderGeometryNeedsFinish = false;
texCache.Evict(TEXCACHE_MAX_SIZE); // Since we're finishing geometry rendering here and now, also check the texture cache now.
texCache.Evict(); // 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);
@ -1981,7 +2024,7 @@ Render3DError SoftRasterizerRenderer::RenderFinish()
}
// Now that geometry rendering is finished on all threads, check the texture cache.
texCache.Evict(TEXCACHE_MAX_SIZE);
texCache.Evict();
// Do multithreaded post-processing.
if (this->currentRenderState->enableEdgeMarking || this->currentRenderState->enableFog)

View File

@ -20,6 +20,7 @@
#include "render3D.h"
#include "gfx3d.h"
#include "texcache.h"
#define SOFTRASTERIZER_DEPTH_EQUAL_TEST_TOLERANCE 0x200
@ -39,6 +40,28 @@ struct SoftRasterizerPostProcessParams
bool fogAlphaOnly;
};
class SoftRasterizerTexture : public TextureStore
{
protected:
u32 *_unpackData;
u32 _renderWidth;
u32 _renderHeight;
u32 _renderWidthMask;
u32 _renderHeightMask;
u32 _renderWidthShift;
public:
SoftRasterizerTexture(u32 texAttributes, u32 palAttributes);
virtual ~SoftRasterizerTexture();
u32* GetUnpackData();
u32 GetRenderWidth() const;
u32 GetRenderHeight() const;
u32 GetRenderWidthMask() const;
u32 GetRenderHeightMask() const;
u32 GetRenderWidthShift() const;
};
#if defined(ENABLE_SSE2)
class SoftRasterizerRenderer : public Render3D_SSE2
#else
@ -75,7 +98,7 @@ public:
FragmentColor toonColor32LUT[32];
GFX3D_Clipper::TClippedPoly *clippedPolys;
FragmentAttributesBuffer *_framebufferAttributes;
TexCacheItem *polyTexKeys[POLYLIST_SIZE];
SoftRasterizerTexture *polyTexKeys[POLYLIST_SIZE];
bool polyVisible[POLYLIST_SIZE];
bool polyBackfacing[POLYLIST_SIZE];
GFX3D_State *currentRenderState;

File diff suppressed because it is too large Load Diff

View File

@ -21,25 +21,26 @@
#define _TEXCACHE_H_
#include <map>
#include <vector>
#include "types.h"
#include "common.h"
#include "gfx3d.h"
//this ought to be enough for anyone
//#define TEXCACHE_MAX_SIZE (64*1024*1024)
//#define TEXCACHE_DEFAULT_THRESHOLD (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 TEXCACHE_DEFAULT_THRESHOLD (16*1024*1024)
// rogerman, 2016-11-02: Increase this to 32MB for games that use many large textures, such
// as Umihara Kawase Shun, which can cache over 20MB in the first level.
#define TEXCACHE_MAX_SIZE (32*1024*1024)
#define TEXCACHE_DEFAULT_THRESHOLD (32*1024*1024)
#define PALETTE_DUMP_SIZE ((64+16+16)*1024)
enum TexCache_TexFormat
enum TextureStoreUnpackFormat
{
TexFormat_None, //used when nothing yet is cached
TexFormat_32bpp, //used by ogl renderer
@ -47,97 +48,142 @@ enum TexCache_TexFormat
};
class MemSpan;
class TexCacheItem;
class TextureStore;
typedef u64 TexCacheKey;
typedef std::map<TexCacheKey, TexCacheItem *> TexCacheTable;
typedef void (*TexCacheItemDeleteCallback)(TexCacheItem *texItem, void *param1, void *param2);
typedef u64 TextureCacheKey;
typedef std::map<TextureCacheKey, TextureStore *> TextureCacheMap; // Key = A TextureCacheKey that includes a combination of the texture's NDS texture attributes and palette attributes; Value = Pointer to the texture item
typedef std::vector<TextureStore *> TextureCacheList;
//typedef u32 TextureFingerprint;
class TexCache
class TextureCache
{
public:
TexCache();
protected:
TextureCacheMap _texCacheMap; // Used to quickly find a texture item by using a key of type TextureCacheKey
TextureCacheList _texCacheList; // Used to sort existing texture items for various operations
size_t _actualCacheSize;
size_t _cacheSizeThreshold;
u8 _paletteDump[PALETTE_DUMP_SIZE];
public:
TextureCache();
size_t GetActualCacheSize() const;
size_t GetCacheSizeThreshold() const;
void SetCacheSizeThreshold(size_t newThreshold);
TexCacheTable cacheTable;
size_t cache_size; //this is not really precise, it is off by a constant factor
u8 paletteDump[PALETTE_DUMP_SIZE];
void Invalidate();
void Evict(size_t target);
void Evict();
void Reset();
TexCacheItem* GetTexture(u32 texAttributes, u32 palAttributes);
TextureStore* GetTexture(u32 texAttributes, u32 palAttributes);
static TexCacheKey GenerateKey(const u32 texAttributes, const u32 palAttributes);
void Add(TextureStore *texItem);
void Remove(TextureStore *texItem);
static TextureCacheKey GenerateKey(const u32 texAttributes, const u32 palAttributes);
};
class TexCacheItem
class TextureStore
{
private:
TexCacheItemDeleteCallback _deleteCallback;
void *_deleteCallbackParam1;
void *_deleteCallbackParam2;
protected:
u32 _textureAttributes;
u32 _paletteAttributes;
public:
TexCacheItem();
TexCacheItem(const u32 texAttributes, const u32 palAttributes);
~TexCacheItem();
u32 _sizeS;
u32 _sizeT;
bool _isPalZeroTransparent;
u32 textureAttributes;
u32 paletteAttributes;
NDSTextureFormat _packFormat;
u32 _packAddress;
u32 _packSize;
u8 *_packData;
u32 sizeX;
u32 sizeY;
float invSizeX;
float invSizeY;
bool isPalZeroTransparent;
bool suspectedInvalid;
bool assumedInvalid;
NDSTextureFormat packFormat;
u32 packAddress;
u32 packSize;
u8 *packData;
u32 paletteAddress;
u32 paletteSize;
u16 *paletteColorTable;
TexCache_TexFormat unpackFormat;
u32 unpackSize;
u32 *unpackData;
u32 _paletteAddress;
u32 _paletteSize;
u16 *_paletteColorTable;
// Only used by 4x4 formatted textures
u32 packIndexAddress;
u32 packIndexSize;
u8 *packIndexData;
u32 packSizeFirstSlot;
u32 _packIndexAddress;
u32 _packIndexSize;
u8 *_packIndexData;
u32 _packSizeFirstSlot;
// Only used by the OpenGL renderer for the texture ID
u32 texid;
bool _suspectedInvalid;
bool _assumedInvalid;
bool _isLoadNeeded;
TexCacheItemDeleteCallback GetDeleteCallback() const;
void SetDeleteCallback(TexCacheItemDeleteCallback callbackFunc, void *inParam1, void *inParam2);
TextureCacheKey _cacheKey;
size_t _cacheSize;
size_t _cacheAge; // A value of 0 means the texture was just used. The higher this value, the older the texture.
size_t _cacheUsageCount;
public:
TextureStore();
TextureStore(const u32 texAttributes, const u32 palAttributes);
virtual ~TextureStore();
u32 GetTextureAttributes() const;
u32 GetPaletteAttributes() const;
u32 GetWidth() const;
u32 GetHeight() const;
bool IsPalZeroTransparent() const;
NDSTextureFormat GetPackFormat() const;
u32 GetPackAddress() const;
u32 GetPackSize() const;
u8* GetPackData();
u32 GetPaletteAddress() const;
u32 GetPaletteSize() const;
u16* GetPaletteColorTable() const;
u32 GetPackIndexAddress() const;
u32 GetPackIndexSize() const;
u8* GetPackIndexData();
NDSTextureFormat GetTextureFormat() const;
void SetTextureData(const MemSpan &packedData, const MemSpan &packedIndexData);
void SetTexturePalette(const MemSpan &packedPalette);
void SetTexturePalette(const u16 *paletteBuffer);
size_t GetUnpackSizeUsingFormat(const TexCache_TexFormat texCacheFormat) const;
template<TexCache_TexFormat TEXCACHEFORMAT> void Unpack(u32 *unpackBuffer);
size_t GetUnpackSizeUsingFormat(const TextureStoreUnpackFormat texCacheFormat) const;
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void Unpack(u32 *unpackBuffer);
bool IsSuspectedInvalid() const;
void SetSuspectedInvalid();
bool IsAssumedInvalid() const;
void SetAssumedInvalid();
void SetLoadNeeded();
bool IsLoadNeeded() const;
TextureCacheKey GetCacheKey() const;
size_t GetCacheSize() const;
void SetCacheSize(size_t cacheSize);
size_t GetCacheAge() const;
void IncreaseCacheAge(const size_t ageAmount);
void ResetCacheAge();
size_t GetCacheUseCount() const;
void IncreaseCacheUsageCount(const size_t usageCount);
void ResetCacheUsageCount();
void Update();
void VRAMCompareAndUpdate();
void DebugDump();
};
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackI2(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, const bool isPalZeroTransparent, u32 *__restrict dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackI4(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, const bool isPalZeroTransparent, u32 *__restrict dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackI8(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, const bool isPalZeroTransparent, u32 *__restrict dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackA3I5(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, u32 *__restrict dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackA5I3(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, u32 *__restrict dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpack4x4(const size_t srcSize, const u32 *__restrict srcData, const u16 *__restrict srcIndex, const u32 palAddress, const u32 texAttributes, const u32 sizeX, const u32 sizeY, u32 *__restrict dstBuffer);
template<TexCache_TexFormat TEXCACHEFORMAT> void NDSTextureUnpackDirect16Bit(const size_t srcSize, const u16 *__restrict srcData, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackI2(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, const bool isPalZeroTransparent, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackI4(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, const bool isPalZeroTransparent, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackI8(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, const bool isPalZeroTransparent, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackA3I5(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackA5I3(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpack4x4(const size_t srcSize, const u32 *__restrict srcData, const u16 *__restrict srcIndex, const u32 palAddress, const u32 texAttributes, const u32 sizeX, const u32 sizeY, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackDirect16Bit(const size_t srcSize, const u16 *__restrict srcData, u32 *__restrict dstBuffer);
extern TexCache texCache;
extern TextureCache texCache;
#endif