Implemented global dynamic texture LOD selection to constrain texture memory usage within bounds

--HG--
extra : convert_revision : svn%3A7752d6cf-9f14-4ad2-affc-04f1e67b81a5/trunk%40108
This commit is contained in:
kearwood
2012-09-26 20:07:48 +00:00
parent a39610a292
commit 63fb848da5
15 changed files with 167 additions and 79 deletions

View File

@@ -132,7 +132,7 @@ void KRCamera::setPosition(const KRVector3 &position) {
void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix)
{
m_pContext->rotateBuffers();
m_pContext->rotateBuffers(true);
KRMat4 invViewMatrix = viewMatrix;
invViewMatrix.invert();
@@ -234,7 +234,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD
backToFrontOrder[i] = frontToBackOrder[7-i];
}
fprintf(stderr, "Draw Order: %i%i%i%i%i%i%i%i ", frontToBackOrder[0], frontToBackOrder[1], frontToBackOrder[2], frontToBackOrder[3], frontToBackOrder[4], frontToBackOrder[5], frontToBackOrder[6], frontToBackOrder[7]);
//fprintf(stderr, "Draw Order: %i%i%i%i%i%i%i%i ", frontToBackOrder[0], frontToBackOrder[1], frontToBackOrder[2], frontToBackOrder[3], frontToBackOrder[4], frontToBackOrder[5], frontToBackOrder[6], frontToBackOrder[7]);
KRBoundingVolume frustrumVolume = KRBoundingVolume(viewMatrix, perspective_fov, getViewportSize().x / getViewportSize().y, perspective_nearz, perspective_farz);
@@ -281,10 +281,10 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD
GLDEBUG(glDepthMask(GL_FALSE));
// Set source to buffers from pass 1
m_pContext->getTextureManager()->selectTexture(6, NULL);
m_pContext->getTextureManager()->selectTexture(6, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE6));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeColorTexture));
m_pContext->getTextureManager()->selectTexture(7, NULL);
m_pContext->getTextureManager()->selectTexture(7, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE7));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeDepthTexture));
@@ -304,7 +304,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD
GLDEBUG(glClear(GL_COLOR_BUFFER_BIT));
// Set source to buffers from pass 2
m_pContext->getTextureManager()->selectTexture(6, NULL);
m_pContext->getTextureManager()->selectTexture(6, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE6));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, lightAccumulationTexture));
@@ -325,10 +325,10 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD
scene.render(this, frontToBackOrder, emptyBoundsSet, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_DEFERRED_OPAQUE, newVisibleBounds);
// Deactivate source buffer texture units
m_pContext->getTextureManager()->selectTexture(6, NULL);
m_pContext->getTextureManager()->selectTexture(6, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE6));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
m_pContext->getTextureManager()->selectTexture(7, NULL);
m_pContext->getTextureManager()->selectTexture(7, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE7));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
} else {
@@ -446,7 +446,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD
GLDEBUG(glDepthMask(GL_TRUE));
fprintf(stderr, "VBO Mem: %i Kbyte Texture Mem: %i Kbyte Shader Handles: %i Visible Bounds: %i\n", (int)m_pContext->getModelManager()->getMemUsed() / 1024, (int)m_pContext->getTextureManager()->getMemUsed() / 1024, (int)m_pContext->getShaderManager()->getShaderHandlesUsed(), (int)m_visibleBounds.size());
fprintf(stderr, "VBO Mem: %i Kbyte Texture Mem: %i/%i Kbyte (active/total) Shader Handles: %i Visible Bounds: %i Max Texture LOD: %i\n", (int)m_pContext->getModelManager()->getMemUsed() / 1024, (int)m_pContext->getTextureManager()->getActiveMemUsed() / 1024, (int)m_pContext->getTextureManager()->getMemUsed() / 1024, (int)m_pContext->getShaderManager()->getShaderHandlesUsed(), (int)m_visibleBounds.size(), m_pContext->getTextureManager()->getLODDimCap());
}
@@ -666,11 +666,11 @@ void KRCamera::renderPost()
KRVector3 vec4Temp; // Value not used by postshader
postShader->bind(this, matIdentity, matIdentity, m_position, vec4Temp, NULL, NULL, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
m_pContext->getTextureManager()->selectTexture(0, NULL);
m_pContext->getTextureManager()->selectTexture(0, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE0));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeDepthTexture));
m_pContext->getTextureManager()->selectTexture(1, NULL);
m_pContext->getTextureManager()->selectTexture(1, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE1));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeColorTexture));
@@ -679,11 +679,11 @@ void KRCamera::renderPost()
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
m_pContext->getTextureManager()->selectTexture(0, NULL);
m_pContext->getTextureManager()->selectTexture(0, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE0));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
m_pContext->getTextureManager()->selectTexture(1, NULL);
m_pContext->getTextureManager()->selectTexture(1, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE1));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
@@ -691,7 +691,7 @@ void KRCamera::renderPost()
if(bShowShadowBuffer) {
GLDEBUG(glDisable(GL_DEPTH_TEST));
m_pContext->getTextureManager()->selectTexture(0, NULL);
m_pContext->getTextureManager()->selectTexture(0, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE0));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeDepthTexture));
@@ -701,7 +701,7 @@ void KRCamera::renderPost()
GLDEBUG(glVertexAttribPointer(KRShader::KRENGINE_ATTRIB_TEXUVA, 2, GL_FLOAT, 0, 0, KRENGINE_VERTICES_2D_SQUARE_UV));
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
m_pContext->getTextureManager()->selectTexture(1, NULL);
m_pContext->getTextureManager()->selectTexture(1, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE1));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow]));
GLDEBUG(glVertexAttribPointer(KRShader::KRENGINE_ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVerticesShadow[iShadow]));
@@ -709,11 +709,11 @@ void KRCamera::renderPost()
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}
m_pContext->getTextureManager()->selectTexture(0, NULL);
m_pContext->getTextureManager()->selectTexture(0, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE0));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
m_pContext->getTextureManager()->selectTexture(1, NULL);
m_pContext->getTextureManager()->selectTexture(1, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE1));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
}
@@ -726,11 +726,11 @@ void KRCamera::renderPost()
GLDEBUG(glDisable(GL_DEPTH_TEST));
m_pContext->getTextureManager()->selectTexture(0, NULL);
m_pContext->getTextureManager()->selectTexture(0, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE0));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeDepthTexture));
m_pContext->getTextureManager()->selectTexture(1, pFontTexture);
m_pContext->getTextureManager()->selectTexture(1, pFontTexture, 2048);
const char *pChar = szText;
int iPos=0;
@@ -766,7 +766,7 @@ void KRCamera::renderPost()
GLDEBUG(glActiveTexture(GL_TEXTURE0));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
m_pContext->getTextureManager()->selectTexture(1, NULL);
m_pContext->getTextureManager()->selectTexture(1, NULL, 0);
}
}

View File

@@ -112,10 +112,10 @@ void KRContext::loadResource(std::string path) {
}
}
void KRContext::rotateBuffers() {
void KRContext::rotateBuffers(bool new_frame) {
//fprintf(stderr, "Rotating Buffers...\n");
GLDEBUG(glFinish());
m_pModelManager->rotateBuffers();
m_pTextureManager->rotateBuffers();
m_pModelManager->rotateBuffers(new_frame);
m_pTextureManager->rotateBuffers(new_frame);
}

View File

@@ -34,7 +34,7 @@ public:
KRCamera *createCamera(int width, int height);
void rotateBuffers();
void rotateBuffers(bool new_frame);
private:
KRBundleManager *m_pBundleManager;

View File

@@ -99,7 +99,7 @@ void KRInstance::render(KRCamera *pCamera, KRContext *pContext, KRBoundingVolume
}
if(cShadowBuffers == 0 && m_pLightMap && pCamera->bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP) {
m_pContext->getTextureManager()->selectTexture(3, m_pLightMap);
m_pContext->getTextureManager()->selectTexture(3, m_pLightMap, 0);
}
KRMat4 mvpmatrix = m_modelMatrix * viewMatrix * projectionMatrix;

View File

@@ -151,7 +151,7 @@ void KRLight::render(KRCamera *pCamera, KRContext *pContext, KRBoundingVolume &f
pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_FLARE_SIZE],
m_flareSize
));
m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture);
m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture, 2048);
m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_2D_SQUARE, KRENGINE_VBO_2D_SQUARE_SIZE, true, false, false, true, false);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}

View File

@@ -397,20 +397,20 @@ bool KRMaterial::bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, KRC
GLDEBUG(glUniform1f(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_MATERIAL_REFLECTIVITY], m_reflectionFactor));
if(bDiffuseMap) {
m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap);
m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap, 2048);
}
if(bSpecMap) {
m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap);
m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap, 2048);
}
if(bNormalMap) {
m_pContext->getTextureManager()->selectTexture(2, m_pNormalMap);
m_pContext->getTextureManager()->selectTexture(2, m_pNormalMap, 2048);
}
if(bReflectionMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) {
// GL_TEXTURE7 is used for reading the depth buffer in gBuffer pass 2 and re-used for the reflection map in gBuffer Pass 3 and in forward rendering
m_pContext->getTextureManager()->selectTexture(7, m_pReflectionMap);
m_pContext->getTextureManager()->selectTexture(7, m_pReflectionMap, 2048);
}
*prevBoundMaterial = this;

View File

@@ -104,14 +104,14 @@ void KRModelManager::bindVBO(GLvoid *data, GLsizeiptr size, bool enable_vertex,
while(m_vbosPool.size() + m_vbosActive.size() >= KRENGINE_MAX_VBO_HANDLES || m_vboMemUsed >= KRENGINE_MAX_VBO_MEM) {
if(m_vbosPool.empty()) {
fprintf(stderr, "flushBuffers due to VBO exhaustion...\n");
m_pContext->rotateBuffers();
m_pContext->rotateBuffers(false);
}
std::map<GLvoid *, vbo_info_type>::iterator first_itr = m_vbosPool.begin();
vbo_info_type firstVBO = first_itr->second;
GLDEBUG(glDeleteBuffers(1, &firstVBO.handle));
m_vboMemUsed -= firstVBO.size;
m_vbosPool.erase(first_itr);
//fprintf(stderr, "VBO Swapping...\n");
fprintf(stderr, "VBO Swapping...\n");
}
m_currentVBO.handle = -1;
@@ -231,7 +231,7 @@ long KRModelManager::getMemUsed()
return m_vboMemUsed;
}
void KRModelManager::rotateBuffers()
void KRModelManager::rotateBuffers(bool new_frame)
{
m_vbosPool.insert(m_vbosActive.begin(), m_vbosActive.end());
m_vbosActive.clear();

View File

@@ -33,7 +33,7 @@
#define KRMODELMANAGER_H
#define KRENGINE_MAX_VBO_HANDLES 10000
#define KRENGINE_MAX_VBO_MEM 50000000
#define KRENGINE_MAX_VBO_MEM 128000000
#import "KREngine-common.h"
#import "KRContextObject.h"
@@ -51,7 +51,7 @@ public:
KRModelManager(KRContext &context);
virtual ~KRModelManager();
void rotateBuffers();
void rotateBuffers(bool new_frame);
KRModel *loadModel(const char *szName, KRDataBlock *pData);
KRModel *getModel(const char *szName);

View File

@@ -63,7 +63,7 @@ void KRScene::render(KRCamera *pCamera, int childOrder[], std::set<KRAABB> &visi
if(renderPass != KRNode::RENDER_PASS_SHADOWMAP) {
if(cShadowBuffers > 0) {
m_pContext->getTextureManager()->selectTexture(3, NULL);
m_pContext->getTextureManager()->selectTexture(3, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE3));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTextures[0]));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
@@ -73,7 +73,7 @@ void KRScene::render(KRCamera *pCamera, int childOrder[], std::set<KRAABB> &visi
}
if(cShadowBuffers > 1) {
m_pContext->getTextureManager()->selectTexture(4, NULL);
m_pContext->getTextureManager()->selectTexture(4, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE4));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTextures[1]));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
@@ -83,7 +83,7 @@ void KRScene::render(KRCamera *pCamera, int childOrder[], std::set<KRAABB> &visi
}
if(cShadowBuffers > 2) {
m_pContext->getTextureManager()->selectTexture(5, NULL);
m_pContext->getTextureManager()->selectTexture(5, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE5));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTextures[2]));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));

View File

@@ -140,12 +140,12 @@ void KRSkyBox::render(KRCamera *pCamera, KRContext *pContext, KRBoundingVolume &
// KRShader *pShader = pContext->getShaderManager()->getShader("sky_box", pCamera, false, false, false, 0, false, false, false, false, false, false, false, false, renderPass);
// pShader->bind(pCamera, matModelToView, mvpmatrix, cameraPosition, NULL, NULL, NULL, 0, renderPass);
m_pContext->getTextureManager()->selectTexture(0, m_pFrontTexture);
m_pContext->getTextureManager()->selectTexture(1, m_pBackTexture);
m_pContext->getTextureManager()->selectTexture(2, m_pTopTexture);
m_pContext->getTextureManager()->selectTexture(3, m_pBottomTexture);
m_pContext->getTextureManager()->selectTexture(4, m_pLeftTexture);
m_pContext->getTextureManager()->selectTexture(5, m_pRightTexture);
m_pContext->getTextureManager()->selectTexture(0, m_pFrontTexture, 2048);
m_pContext->getTextureManager()->selectTexture(1, m_pBackTexture, 2048);
m_pContext->getTextureManager()->selectTexture(2, m_pTopTexture, 2048);
m_pContext->getTextureManager()->selectTexture(3, m_pBottomTexture, 2048);
m_pContext->getTextureManager()->selectTexture(4, m_pLeftTexture, 2048);
m_pContext->getTextureManager()->selectTexture(5, m_pRightTexture, 2048);
// Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE));

View File

@@ -71,8 +71,10 @@ typedef struct _PVRTexHeader
KRTexture::KRTexture(KRDataBlock *data, KRTextureManager *manager) {
m_pData = data;
m_iName = 0;
m_iHandle = 0;
m_pManager = manager;
m_current_lod_max_dim = 0;
m_textureMemUsed = 0;
load();
}
@@ -154,6 +156,9 @@ bool KRTexture::load() {
height = 1;
}
}
m_max_lod_max_dim = m_iWidth > m_iHeight ? m_iWidth : m_iHeight;
m_min_lod_max_dim = width >> height ? width : height;
#endif
return true;
@@ -161,7 +166,8 @@ bool KRTexture::load() {
bool KRTexture::createGLTexture() {
bool KRTexture::createGLTexture(int lod_max_dim) {
m_current_lod_max_dim = 0;
int width = m_iWidth;
int height = m_iHeight;
GLenum err;
@@ -170,11 +176,11 @@ bool KRTexture::createGLTexture() {
return false;
}
GLDEBUG(glGenTextures(1, &m_iName));
if(m_iName == 0) {
GLDEBUG(glGenTextures(1, &m_iHandle));
if(m_iHandle == 0) {
return false;
}
GLDEBUG(glBindTexture(GL_TEXTURE_2D, m_iName));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, m_iHandle));
if (m_blocks.size() > 1) {
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
@@ -184,14 +190,26 @@ bool KRTexture::createGLTexture() {
int i=0;
for(std::list<dataBlockStruct>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
dataBlockStruct block = *itr;
GLDEBUG(glCompressedTexImage2D(GL_TEXTURE_2D, i, m_internalFormat, width, height, 0, block.length, block.start));
err = glGetError();
if (err != GL_NO_ERROR) {
GLDEBUG(glDeleteTextures(1, &m_iName));
m_iName = 0;
return false;
}
if(width <= lod_max_dim && height <= lod_max_dim) {
if(width > m_current_lod_max_dim) {
m_current_lod_max_dim = width;
}
if(height > m_current_lod_max_dim) {
m_current_lod_max_dim = height;
}
GLDEBUG(glCompressedTexImage2D(GL_TEXTURE_2D, i, m_internalFormat, width, height, 0, block.length, block.start));
err = glGetError();
if (err != GL_NO_ERROR) {
GLDEBUG(glDeleteTextures(1, &m_iHandle));
m_textureMemUsed = 0;
m_iHandle = 0;
lod_max_dim = 0;
return false;
}
m_textureMemUsed += block.length;
i++;
}
width = width >> 1;
if(width < 1) {
@@ -201,16 +219,22 @@ bool KRTexture::createGLTexture() {
if(height < 1) {
height = 1;
}
i++;
}
return true;
}
GLuint KRTexture::getHandle(long &textureMemUsed) {
if(m_iName == 0) {
if(createGLTexture()) {
GLuint KRTexture::getHandle(long &textureMemUsed, int max_dim, bool can_resize) {
// Constrain target LOD to be within mipmap levels of texture
int target_dim = max_dim;
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
if(target_dim > m_max_lod_max_dim) target_dim = m_max_lod_max_dim;
if(can_resize && m_current_lod_max_dim != target_dim) {
releaseHandle(textureMemUsed);
}
if(m_iHandle == 0) {
if(createGLTexture(target_dim)) {
textureMemUsed += getMemSize();
} else {
assert(false);
@@ -218,17 +242,18 @@ GLuint KRTexture::getHandle(long &textureMemUsed) {
//createGLTexture();
}
return m_iName;
return m_iHandle;
}
void KRTexture::releaseHandle(long &textureMemUsed) {
if(m_iName != 0) {
if(m_iHandle != 0) {
textureMemUsed -= getMemSize();
GLDEBUG(glDeleteTextures(1, &m_iName));
m_iName = 0;
GLDEBUG(glDeleteTextures(1, &m_iHandle));
m_iHandle = 0;
m_textureMemUsed = 0;
}
}
long KRTexture::getMemSize() {
return m_pData->getSize(); // TODO - This is not 100% accurate, as loaded format may differ in size while in GPU memory
return m_textureMemUsed; // TODO - This is not 100% accurate, as loaded format may differ in size while in GPU memory
}

View File

@@ -48,15 +48,15 @@ public:
KRTexture(KRDataBlock *data, KRTextureManager *manager);
~KRTexture();
bool createGLTexture();
GLuint getHandle(long &textureMemUsed);
bool createGLTexture(int lod_max_dim);
GLuint getHandle(long &textureMemUsed, int max_dim, bool can_resize);
void releaseHandle(long &textureMemUsed);
long getMemSize();
private:
GLuint m_iName;
GLuint m_iHandle;
uint32_t m_iWidth;
uint32_t m_iHeight;
GLenum m_internalFormat;
@@ -74,7 +74,13 @@ private:
bool load();
KRTextureManager *m_pManager;
int m_current_lod_max_dim;
uint32_t m_max_lod_max_dim;
uint32_t m_min_lod_max_dim;
uint32_t m_textureMemUsed;
};
#endif

View File

@@ -35,6 +35,8 @@
KRTextureManager::KRTextureManager(KRContext &context) : KRContextObject(context) {
m_textureMemUsed = 0;
m_activeTextureMemUsed = 0;
m_lod_max_dim_cap = 2048;
for(int iTexture=0; iTexture<KRENGINE_MAX_TEXTURE_UNITS; iTexture++) {
m_boundTextures[iTexture] = NULL;
}
@@ -79,16 +81,25 @@ KRTexture *KRTextureManager::getTexture(const char *szName) {
}
void KRTextureManager::selectTexture(int iTextureUnit, KRTexture *pTexture) {
void KRTextureManager::selectTexture(int iTextureUnit, KRTexture *pTexture, int lod_max_dim) {
if(m_boundTextures[iTextureUnit] != pTexture) {
GLDEBUG(glActiveTexture(GL_TEXTURE0 + iTextureUnit));
if(pTexture != NULL) {
m_poolTextures.erase(pTexture);
bool bActive = true;
if(m_activeTextures.find(pTexture) == m_activeTextures.end()) {
bActive = false;
m_activeTextures.insert(pTexture);
}
GLDEBUG(glBindTexture(GL_TEXTURE_2D, pTexture->getHandle(m_textureMemUsed)));
long textureMemChange = 0;
GLDEBUG(glBindTexture(GL_TEXTURE_2D, pTexture->getHandle(textureMemChange, lod_max_dim < m_lod_max_dim_cap ? lod_max_dim : m_lod_max_dim_cap, !bActive)));
m_textureMemUsed += textureMemChange;
if(bActive) {
m_activeTextureMemUsed += textureMemChange;
} else {
m_activeTextureMemUsed += pTexture->getMemSize();
}
// TODO - These texture parameters should be assigned by the material or texture parameters
GLDEBUG(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
@@ -99,8 +110,9 @@ void KRTextureManager::selectTexture(int iTextureUnit, KRTexture *pTexture) {
m_boundTextures[iTextureUnit] = pTexture;
while(m_activeTextures.size() + m_poolTextures.size() > KRENGINE_MAX_TEXTURE_HANDLES || m_textureMemUsed > KRENGINE_MAX_TEXTURE_MEM) {
if(m_poolTextures.empty()) {
//fprintf(stderr, "flushBuffers due to texture exhaustion...\n");
m_pContext->rotateBuffers();
fprintf(stderr, "Kraken - Texture swapping...\n");
decreaseLODCap();
m_pContext->rotateBuffers(false);
}
// Keep texture size within limits
KRTexture *droppedTexture = (*m_poolTextures.begin());
@@ -117,11 +129,22 @@ long KRTextureManager::getMemUsed() {
return m_textureMemUsed;
}
long KRTextureManager::getActiveMemUsed() {
return m_activeTextureMemUsed;
}
void KRTextureManager::rotateBuffers()
void KRTextureManager::rotateBuffers(bool new_frame)
{
if(new_frame && m_activeTextureMemUsed < KRENGINE_TARGET_TEXTURE_MEM_MIN && m_activeTextureMemUsed * 4 < KRENGINE_TARGET_TEXTURE_MEM_MAX) {
// Increasing the LOD level will generally increase active texture memory usage by 4 times, don't increase the texture level until we can ensure that the LOD won't immediately be dropped back to the current level
increaseLODCap();
} else if(new_frame && m_activeTextureMemUsed > KRENGINE_TARGET_TEXTURE_MEM_MAX) {
decreaseLODCap();
}
m_poolTextures.insert(m_activeTextures.begin(), m_activeTextures.end());
m_activeTextures.clear();
m_activeTextureMemUsed = 0;
for(int iTexture=0; iTexture < KRENGINE_MAX_TEXTURE_UNITS; iTexture++) {
KRTexture *pBoundTexture = m_boundTextures[iTexture];
@@ -129,7 +152,28 @@ void KRTextureManager::rotateBuffers()
m_poolTextures.erase(pBoundTexture);
if(m_activeTextures.find(pBoundTexture) == m_activeTextures.end()) {
m_activeTextures.insert(pBoundTexture);
m_activeTextureMemUsed += pBoundTexture->getMemSize();
}
}
}
}
void KRTextureManager::decreaseLODCap()
{
if(m_lod_max_dim_cap > KRENGINE_MIN_TEXTURE_DIM) {
m_lod_max_dim_cap = m_lod_max_dim_cap >> 1;
}
}
void KRTextureManager::increaseLODCap()
{
if(m_lod_max_dim_cap < KRENGINE_MAX_TEXTURE_DIM) {
m_lod_max_dim_cap = m_lod_max_dim_cap << 1;
}
}
int KRTextureManager::getLODDimCap()
{
return m_lod_max_dim_cap;
}

View File

@@ -31,7 +31,11 @@
#define KRENGINE_MAX_TEXTURE_UNITS 8
#define KRENGINE_MAX_TEXTURE_HANDLES 10000
#define KRENGINE_MAX_TEXTURE_MEM 128000000
#define KRENGINE_MAX_TEXTURE_MEM 96000000
#define KRENGINE_TARGET_TEXTURE_MEM_MAX 64000000
#define KRENGINE_TARGET_TEXTURE_MEM_MIN 32000000
#define KRENGINE_MAX_TEXTURE_DIM 2048
#define KRENGINE_MIN_TEXTURE_DIM 16
#ifndef KRTEXTUREMANAGER_H
#define KRTEXTUREMANAGER_H
@@ -49,9 +53,9 @@ public:
KRTextureManager(KRContext &context);
virtual ~KRTextureManager();
void rotateBuffers();
void rotateBuffers(bool new_frame);
void selectTexture(int iTextureUnit, KRTexture *pTexture);
void selectTexture(int iTextureUnit, KRTexture *pTexture, int lod_max_dim);
#if TARGET_OS_IPHONE
@@ -62,8 +66,14 @@ public:
KRTexture *getTexture(const char *szFile);
long getMemUsed();
long getActiveMemUsed();
int getLODDimCap();
private:
void decreaseLODCap();
void increaseLODCap();
std::map<std::string, KRTexture *> m_textures;
KRTexture *m_boundTextures[KRENGINE_MAX_TEXTURE_UNITS];
@@ -71,6 +81,9 @@ private:
std::set<KRTexture *> m_poolTextures;
long m_textureMemUsed;
long m_activeTextureMemUsed;
int m_lod_max_dim_cap;
};
#endif

View File

@@ -106,7 +106,7 @@
}
[self.engine setNearZ: 5.0];
[self.engine setFarZ: 5000.0];
[self.engine setFarZ: 1000.0];
//[renderEngine setNearZ: 1.0];
//[renderEngine setFarZ: 3000.0];