diff --git a/KREngine/KREngine/Classes/KRCamera.cpp b/KREngine/KREngine/Classes/KRCamera.cpp index e06d3c7..4332f4e 100644 --- a/KREngine/KREngine/Classes/KRCamera.cpp +++ b/KREngine/KREngine/Classes/KRCamera.cpp @@ -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); } } diff --git a/KREngine/KREngine/Classes/KRContext.cpp b/KREngine/KREngine/Classes/KRContext.cpp index 216290b..8e21d66 100644 --- a/KREngine/KREngine/Classes/KRContext.cpp +++ b/KREngine/KREngine/Classes/KRContext.cpp @@ -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); } \ No newline at end of file diff --git a/KREngine/KREngine/Classes/KRContext.h b/KREngine/KREngine/Classes/KRContext.h index 22cb4e2..cc12f55 100644 --- a/KREngine/KREngine/Classes/KRContext.h +++ b/KREngine/KREngine/Classes/KRContext.h @@ -34,7 +34,7 @@ public: KRCamera *createCamera(int width, int height); - void rotateBuffers(); + void rotateBuffers(bool new_frame); private: KRBundleManager *m_pBundleManager; diff --git a/KREngine/KREngine/Classes/KRInstance.cpp b/KREngine/KREngine/Classes/KRInstance.cpp index fbfd72c..75b90cd 100644 --- a/KREngine/KREngine/Classes/KRInstance.cpp +++ b/KREngine/KREngine/Classes/KRInstance.cpp @@ -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; diff --git a/KREngine/KREngine/Classes/KRLight.cpp b/KREngine/KREngine/Classes/KRLight.cpp index 17f426a..c26e657 100644 --- a/KREngine/KREngine/Classes/KRLight.cpp +++ b/KREngine/KREngine/Classes/KRLight.cpp @@ -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)); } diff --git a/KREngine/KREngine/Classes/KRMaterial.cpp b/KREngine/KREngine/Classes/KRMaterial.cpp index 1d7b787..057661e 100644 --- a/KREngine/KREngine/Classes/KRMaterial.cpp +++ b/KREngine/KREngine/Classes/KRMaterial.cpp @@ -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; diff --git a/KREngine/KREngine/Classes/KRModelManager.cpp b/KREngine/KREngine/Classes/KRModelManager.cpp index ff88be2..4e626a0 100644 --- a/KREngine/KREngine/Classes/KRModelManager.cpp +++ b/KREngine/KREngine/Classes/KRModelManager.cpp @@ -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::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(); diff --git a/KREngine/KREngine/Classes/KRModelManager.h b/KREngine/KREngine/Classes/KRModelManager.h index 4af45ef..acfc9de 100644 --- a/KREngine/KREngine/Classes/KRModelManager.h +++ b/KREngine/KREngine/Classes/KRModelManager.h @@ -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); diff --git a/KREngine/KREngine/Classes/KRScene.cpp b/KREngine/KREngine/Classes/KRScene.cpp index d4c0927..e1a7b82 100644 --- a/KREngine/KREngine/Classes/KRScene.cpp +++ b/KREngine/KREngine/Classes/KRScene.cpp @@ -63,7 +63,7 @@ void KRScene::render(KRCamera *pCamera, int childOrder[], std::set &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 &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 &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)); diff --git a/KREngine/KREngine/Classes/KRSkyBox.cpp b/KREngine/KREngine/Classes/KRSkyBox.cpp index 769a327..d76cb97 100644 --- a/KREngine/KREngine/Classes/KRSkyBox.cpp +++ b/KREngine/KREngine/Classes/KRSkyBox.cpp @@ -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)); diff --git a/KREngine/KREngine/Classes/KRTexture.cpp b/KREngine/KREngine/Classes/KRTexture.cpp index b623d1a..a961d39 100644 --- a/KREngine/KREngine/Classes/KRTexture.cpp +++ b/KREngine/KREngine/Classes/KRTexture.cpp @@ -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::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 } diff --git a/KREngine/KREngine/Classes/KRTexture.h b/KREngine/KREngine/Classes/KRTexture.h index 21e69ae..471005c 100644 --- a/KREngine/KREngine/Classes/KRTexture.h +++ b/KREngine/KREngine/Classes/KRTexture.h @@ -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 diff --git a/KREngine/KREngine/Classes/KRTextureManager.cpp b/KREngine/KREngine/Classes/KRTextureManager.cpp index b6b9e09..b6eb781 100644 --- a/KREngine/KREngine/Classes/KRTextureManager.cpp +++ b/KREngine/KREngine/Classes/KRTextureManager.cpp @@ -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; iTexturegetHandle(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; +} + diff --git a/KREngine/KREngine/Classes/KRTextureManager.h b/KREngine/KREngine/Classes/KRTextureManager.h index bc2837f..e12bdd2 100644 --- a/KREngine/KREngine/Classes/KRTextureManager.h +++ b/KREngine/KREngine/Classes/KRTextureManager.h @@ -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 m_textures; KRTexture *m_boundTextures[KRENGINE_MAX_TEXTURE_UNITS]; @@ -71,6 +81,9 @@ private: std::set m_poolTextures; long m_textureMemUsed; + long m_activeTextureMemUsed; + + int m_lod_max_dim_cap; }; #endif diff --git a/objview/Classes/KRObjViewGLView.mm b/objview/Classes/KRObjViewGLView.mm index 0833bc7..88b11d2 100644 --- a/objview/Classes/KRObjViewGLView.mm +++ b/objview/Classes/KRObjViewGLView.mm @@ -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];