diff --git a/KREngine/KREngine.xcodeproj/project.pbxproj b/KREngine/KREngine.xcodeproj/project.pbxproj index ffb3844..fe9c786 100644 --- a/KREngine/KREngine.xcodeproj/project.pbxproj +++ b/KREngine/KREngine.xcodeproj/project.pbxproj @@ -519,10 +519,10 @@ E491018013C99BDC0098455B /* KRTextureManager.cpp */, E491018613C99BDC0098455B /* KRTexture2D.h */, E491018113C99BDC0098455B /* KRTexture2D.cpp */, - E4B175AA161F5A1000B8FB80 /* KRTexture.cpp */, E4B175AB161F5A1000B8FB80 /* KRTexture.h */, - E4B175B0161F5FAE00B8FB80 /* KRTextureCube.cpp */, + E4B175AA161F5A1000B8FB80 /* KRTexture.cpp */, E4B175B1161F5FAF00B8FB80 /* KRTextureCube.h */, + E4B175B0161F5FAE00B8FB80 /* KRTextureCube.cpp */, E4CA10E41637BD0A005D9400 /* KRTexturePVR.h */, E4CA10E81637BD2B005D9400 /* KRTexturePVR.cpp */, E4CA10EB1637BD47005D9400 /* KRTextureTGA.h */, diff --git a/KREngine/KREngine/Classes/KRCamera.cpp b/KREngine/KREngine/Classes/KRCamera.cpp index 50f8f78..5d8b345 100644 --- a/KREngine/KREngine/Classes/KRCamera.cpp +++ b/KREngine/KREngine/Classes/KRCamera.cpp @@ -163,8 +163,6 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, float deltaTime) setViewportSize(KRVector2(backingWidth, backingHeight)); m_viewport = KRViewport(getViewportSize(), viewMatrix, getProjectionMatrix()); - - m_pContext->rotateBuffers(true); renderFrame(scene, deltaTime); @@ -232,10 +230,10 @@ void KRCamera::renderFrame(KRScene &scene, float deltaTime) { GLDEBUG(glDepthMask(GL_FALSE)); // Set source to buffers from pass 1 - m_pContext->getTextureManager()->selectTexture(6, NULL, 0); + m_pContext->getTextureManager()->selectTexture(6, NULL); GLDEBUG(glActiveTexture(GL_TEXTURE6)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeColorTexture)); - m_pContext->getTextureManager()->selectTexture(7, NULL, 0); + m_pContext->getTextureManager()->selectTexture(7, NULL); GLDEBUG(glActiveTexture(GL_TEXTURE7)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeDepthTexture)); @@ -255,7 +253,7 @@ void KRCamera::renderFrame(KRScene &scene, float deltaTime) { GLDEBUG(glClear(GL_COLOR_BUFFER_BIT)); // Set source to buffers from pass 2 - m_pContext->getTextureManager()->selectTexture(6, NULL, 0); + m_pContext->getTextureManager()->selectTexture(6, NULL); GLDEBUG(glActiveTexture(GL_TEXTURE6)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, lightAccumulationTexture)); @@ -276,10 +274,10 @@ void KRCamera::renderFrame(KRScene &scene, float deltaTime) { scene.render(this, emptyBoundsSet, m_viewport, KRNode::RENDER_PASS_DEFERRED_OPAQUE, newVisibleBounds); // Deactivate source buffer texture units - m_pContext->getTextureManager()->selectTexture(6, NULL, 0); + m_pContext->getTextureManager()->selectTexture(6, NULL); GLDEBUG(glActiveTexture(GL_TEXTURE6)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); - m_pContext->getTextureManager()->selectTexture(7, NULL, 0); + m_pContext->getTextureManager()->selectTexture(7, NULL); GLDEBUG(glActiveTexture(GL_TEXTURE7)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); } else { @@ -342,7 +340,7 @@ void KRCamera::renderFrame(KRScene &scene, float deltaTime) { if(m_pSkyBoxTexture) { getContext().getShaderManager()->selectShader("sky_box", this, std::vector(), m_viewport, KRMat4(), false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_OPAQUE); - getContext().getTextureManager()->selectTexture(0, m_pSkyBoxTexture, 2048); + getContext().getTextureManager()->selectTexture(0, m_pSkyBoxTexture); // Render a full screen quad m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_2D_SQUARE, KRENGINE_VBO_2D_SQUARE_SIZE, true, false, false, true, false); @@ -414,7 +412,7 @@ void KRCamera::renderFrame(KRScene &scene, float deltaTime) { // Disable z-buffer test GLDEBUG(glDisable(GL_DEPTH_TEST)); - m_pContext->getTextureManager()->selectTexture(0, NULL, 0); + m_pContext->getTextureManager()->selectTexture(0, NULL); GLDEBUG(glActiveTexture(GL_TEXTURE0)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeDepthTexture)); @@ -665,16 +663,16 @@ void KRCamera::renderPost() KRShader *postShader = m_pContext->getShaderManager()->getShader("PostShader", this, std::vector(), false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); getContext().getShaderManager()->selectShader(postShader, m_viewport, KRMat4(), std::vector(), KRNode::RENDER_PASS_FORWARD_TRANSPARENT); - m_pContext->getTextureManager()->selectTexture(0, NULL, 0); + m_pContext->getTextureManager()->selectTexture(0, NULL); GLDEBUG(glActiveTexture(GL_TEXTURE0)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeDepthTexture)); - m_pContext->getTextureManager()->selectTexture(1, NULL, 0); + m_pContext->getTextureManager()->selectTexture(1, NULL); GLDEBUG(glActiveTexture(GL_TEXTURE1)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeColorTexture)); if(volumetric_environment_enable) { - m_pContext->getTextureManager()->selectTexture(2, NULL, 0); + m_pContext->getTextureManager()->selectTexture(2, NULL); GLDEBUG(glActiveTexture(GL_TEXTURE2)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, volumetricLightAccumulationTexture)); } @@ -684,11 +682,11 @@ void KRCamera::renderPost() GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); - m_pContext->getTextureManager()->selectTexture(0, NULL, 0); + m_pContext->getTextureManager()->selectTexture(0, NULL); GLDEBUG(glActiveTexture(GL_TEXTURE0)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); - m_pContext->getTextureManager()->selectTexture(1, NULL, 0); + m_pContext->getTextureManager()->selectTexture(1, NULL); GLDEBUG(glActiveTexture(GL_TEXTURE1)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); @@ -701,7 +699,7 @@ void KRCamera::renderPost() // viewMatrix.scale(0.20, 0.20, 0.20); // viewMatrix.translate(-0.70, 0.70 - 0.45 * iShadow, 0.0); // getContext().getShaderManager()->selectShader(blitShader, KRViewport(getViewportSize(), viewMatrix, KRMat4()), shadowViewports, KRMat4(), KRVector3(), NULL, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); -// m_pContext->getTextureManager()->selectTexture(1, NULL, 0); +// m_pContext->getTextureManager()->selectTexture(1, NULL); // m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_2D_SQUARE, KRENGINE_VBO_2D_SQUARE_SIZE, true, false, false, true, false); // GLDEBUG(glActiveTexture(GL_TEXTURE0)); // GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow])); @@ -714,7 +712,7 @@ void KRCamera::renderPost() //#endif // } // -// m_pContext->getTextureManager()->selectTexture(0, NULL, 0); +// m_pContext->getTextureManager()->selectTexture(0, NULL); // GLDEBUG(glActiveTexture(GL_TEXTURE0)); // GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); // } @@ -725,7 +723,7 @@ void KRCamera::renderPost() if(*szText) { KRShader *fontShader = m_pContext->getShaderManager()->getShader("debug_font", this, std::vector(), false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); - m_pContext->getTextureManager()->selectTexture(0, m_pContext->getTextureManager()->getTexture("font"), 2048); + m_pContext->getTextureManager()->selectTexture(0, m_pContext->getTextureManager()->getTexture("font")); const char *pChar = szText; int iPos=0; @@ -763,7 +761,7 @@ void KRCamera::renderPost() GLDEBUG(glActiveTexture(GL_TEXTURE0)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); - m_pContext->getTextureManager()->selectTexture(1, NULL, 0); + m_pContext->getTextureManager()->selectTexture(1, NULL); } } diff --git a/KREngine/KREngine/Classes/KRContext.cpp b/KREngine/KREngine/Classes/KRContext.cpp index 60ef956..6917745 100644 --- a/KREngine/KREngine/Classes/KRContext.cpp +++ b/KREngine/KREngine/Classes/KRContext.cpp @@ -20,6 +20,7 @@ int KRContext::KRENGINE_TARGET_TEXTURE_MEM_MAX; int KRContext::KRENGINE_TARGET_TEXTURE_MEM_MIN; int KRContext::KRENGINE_MAX_TEXTURE_DIM; int KRContext::KRENGINE_MIN_TEXTURE_DIM; +int KRContext::KRENGINE_MAX_TEXTURE_THROUGHPUT; const char *KRContext::extension_names[KRENGINE_NUM_EXTENSIONS] = { "GL_EXT_texture_storage" @@ -33,6 +34,7 @@ KRContext::KRContext() { m_pModelManager = new KRModelManager(*this); m_pSceneManager = new KRSceneManager(*this); m_bDetectedExtensions = false; + m_current_frame = 0; } KRContext::~KRContext() { @@ -130,13 +132,29 @@ void KRContext::loadResource(std::string path) { void KRContext::rotateBuffers(bool new_frame) { //fprintf(stderr, "Rotating Buffers...\n"); - GLDEBUG(glFinish()); + if(!new_frame) GLDEBUG(glFinish()); m_pModelManager->rotateBuffers(new_frame); - m_pTextureManager->rotateBuffers(new_frame); } void KRContext::detectExtensions() { m_bDetectedExtensions = true; -} \ No newline at end of file +} + +void KRContext::startFrame() +{ + m_pTextureManager->startFrame(); +} + +void KRContext::endFrame() +{ + m_pTextureManager->endFrame(); + rotateBuffers(true); + m_current_frame++; +} + +long KRContext::getCurrentFrame() +{ + return m_current_frame; +} diff --git a/KREngine/KREngine/Classes/KRContext.h b/KREngine/KREngine/Classes/KRContext.h index d38d2e7..da298f8 100644 --- a/KREngine/KREngine/Classes/KRContext.h +++ b/KREngine/KREngine/Classes/KRContext.h @@ -28,6 +28,7 @@ public: static int KRENGINE_TARGET_TEXTURE_MEM_MIN; static int KRENGINE_MAX_TEXTURE_DIM; static int KRENGINE_MIN_TEXTURE_DIM; + static int KRENGINE_MAX_TEXTURE_THROUGHPUT; KRContext(); @@ -55,6 +56,11 @@ public: static const char * extension_names[KRENGINE_NUM_EXTENSIONS]; static bool extension_available[KRENGINE_NUM_EXTENSIONS]; + void startFrame(); + void endFrame(); + + long getCurrentFrame(); + private: KRBundleManager *m_pBundleManager; KRSceneManager *m_pSceneManager; @@ -65,6 +71,8 @@ private: void detectExtensions(); bool m_bDetectedExtensions; + + long m_current_frame; }; #endif diff --git a/KREngine/KREngine/Classes/KREngine.mm b/KREngine/KREngine/Classes/KREngine.mm index 2d78d8a..4d1325c 100644 --- a/KREngine/KREngine/Classes/KREngine.mm +++ b/KREngine/KREngine/Classes/KREngine.mm @@ -79,6 +79,7 @@ float const PI = 3.141592653589793f; KRContext::KRENGINE_TARGET_TEXTURE_MEM_MIN = 32000000 * 2; KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048; KRContext::KRENGINE_MIN_TEXTURE_DIM = 64; + KRContext::KRENGINE_MAX_TEXTURE_THROUGHPUT = 32000000; } else { KRContext::KRENGINE_MAX_VBO_HANDLES = 10000; KRContext::KRENGINE_MAX_VBO_MEM = 128000000; @@ -89,6 +90,7 @@ float const PI = 3.141592653589793f; KRContext::KRENGINE_TARGET_TEXTURE_MEM_MIN = 32000000; KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048; KRContext::KRENGINE_MIN_TEXTURE_DIM = 64; + KRContext::KRENGINE_MAX_TEXTURE_THROUGHPUT = 32000000; } _camera = NULL; @@ -158,7 +160,9 @@ float const PI = 3.141592653589793f; - (void)renderScene: (KRScene *)pScene WithViewMatrix: (KRMat4)viewMatrix AndDeltaTime: (float)deltaTime { + _context->startFrame(); _camera->renderFrame(*pScene, viewMatrix, deltaTime); + _context->endFrame(); } - (BOOL)loadShaders diff --git a/KREngine/KREngine/Classes/KRInstance.cpp b/KREngine/KREngine/Classes/KRInstance.cpp index 0218c15..c07e028 100644 --- a/KREngine/KREngine/Classes/KRInstance.cpp +++ b/KREngine/KREngine/Classes/KRInstance.cpp @@ -107,7 +107,7 @@ void KRInstance::render(KRCamera *pCamera, std::vector &lights, const } if(m_pLightMap && pCamera->bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP && renderPass != RENDER_PASS_GENERATE_SHADOWMAPS) { - m_pContext->getTextureManager()->selectTexture(5, m_pLightMap, 2048); + m_pContext->getTextureManager()->selectTexture(5, m_pLightMap); } pModel->render(pCamera, lights, viewport, getModelMatrix(), m_pLightMap, renderPass); diff --git a/KREngine/KREngine/Classes/KRLight.cpp b/KREngine/KREngine/Classes/KRLight.cpp index b37ffd2..281dcaa 100644 --- a/KREngine/KREngine/Classes/KRLight.cpp +++ b/KREngine/KREngine/Classes/KRLight.cpp @@ -190,7 +190,7 @@ void KRLight::render(KRCamera *pCamera, std::vector &lights, const KR pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_FLARE_SIZE], m_flareSize )); - m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture, 2048); + m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture); 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)); } @@ -270,6 +270,12 @@ void KRLight::renderShadowBuffers(KRCamera *pCamera) glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y); GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow])); + + GLDEBUG(glClearDepthf(0.0f)); + GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT)); + + glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y); + GLDEBUG(glClearDepthf(1.0f)); GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT)); diff --git a/KREngine/KREngine/Classes/KRMaterial.cpp b/KREngine/KREngine/Classes/KRMaterial.cpp index fac2e42..f297624 100644 --- a/KREngine/KREngine/Classes/KRMaterial.cpp +++ b/KREngine/KREngine/Classes/KRMaterial.cpp @@ -343,24 +343,24 @@ bool KRMaterial::bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, con GLDEBUG(glUniform1f(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA], m_tr)); if(bDiffuseMap) { - m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap, 2048); + m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap); } if(bSpecMap) { - m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap, 2048); + m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap); } if(bNormalMap) { - m_pContext->getTextureManager()->selectTexture(2, m_pNormalMap, 2048); + m_pContext->getTextureManager()->selectTexture(2, m_pNormalMap); } if(bReflectionCubeMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) { - m_pContext->getTextureManager()->selectTexture(4, m_pReflectionCube, 2048); + m_pContext->getTextureManager()->selectTexture(4, m_pReflectionCube); } 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, 2048); + m_pContext->getTextureManager()->selectTexture(7, m_pReflectionMap); } *prevBoundMaterial = this; diff --git a/KREngine/KREngine/Classes/KRModelManager.cpp b/KREngine/KREngine/Classes/KRModelManager.cpp index cab8e59..51e64c0 100644 --- a/KREngine/KREngine/Classes/KRModelManager.cpp +++ b/KREngine/KREngine/Classes/KRModelManager.cpp @@ -124,9 +124,9 @@ void KRModelManager::bindVBO(GLvoid *data, GLsizeiptr size, bool enable_vertex, configureAttribs(enable_vertex, enable_normal, enable_tangent, enable_uva, enable_uvb); #endif } else { - m_vboMemUsed += size; - while(m_vbosPool.size() + m_vbosActive.size() >= KRContext::KRENGINE_MAX_VBO_HANDLES || m_vboMemUsed >= KRContext::KRENGINE_MAX_VBO_MEM) { + + while(m_vbosPool.size() + m_vbosActive.size() + 1 >= KRContext::KRENGINE_MAX_VBO_HANDLES || m_vboMemUsed + size >= KRContext::KRENGINE_MAX_VBO_MEM) { if(m_vbosPool.empty()) { fprintf(stderr, "flushBuffers due to VBO exhaustion...\n"); m_pContext->rotateBuffers(false); @@ -152,6 +152,7 @@ void KRModelManager::bindVBO(GLvoid *data, GLsizeiptr size, bool enable_vertex, GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, m_currentVBO.vbo_handle)); GLDEBUG(glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW)); + m_vboMemUsed += size; configureAttribs(enable_vertex, enable_normal, enable_tangent, enable_uva, enable_uvb); m_currentVBO.size = size; diff --git a/KREngine/KREngine/Classes/KRParticleSystemBrownian.cpp b/KREngine/KREngine/Classes/KRParticleSystemBrownian.cpp index 1d3d4c9..9c674c0 100644 --- a/KREngine/KREngine/Classes/KRParticleSystemBrownian.cpp +++ b/KREngine/KREngine/Classes/KRParticleSystemBrownian.cpp @@ -67,7 +67,7 @@ void KRParticleSystemBrownian::render(KRCamera *pCamera, std::vector GLDEBUG(glDepthRangef(0.0, 1.0)); KRTexture *pParticleTexture = m_pContext->getTextureManager()->getTexture("flare"); - m_pContext->getTextureManager()->selectTexture(0, pParticleTexture, 2048); + m_pContext->getTextureManager()->selectTexture(0, pParticleTexture); int particle_count = 10000; diff --git a/KREngine/KREngine/Classes/KRShader.cpp b/KREngine/KREngine/Classes/KRShader.cpp index 022da51..66ac368 100644 --- a/KREngine/KREngine/Classes/KRShader.cpp +++ b/KREngine/KREngine/Classes/KRShader.cpp @@ -238,7 +238,7 @@ bool KRShader::bind(const KRViewport &viewport, const KRMat4 &matModel, const st if(light_directional_count == 0) { int cShadowBuffers = directional_light->getShadowBufferCount(); if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE1] != -1 && cShadowBuffers > 0) { - m_pContext->getTextureManager()->selectTexture(3, NULL, 0); + m_pContext->getTextureManager()->selectTexture(3, NULL); GLDEBUG(glActiveTexture(GL_TEXTURE3)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, directional_light->getShadowTextures()[0])); GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); @@ -248,7 +248,7 @@ bool KRShader::bind(const KRViewport &viewport, const KRMat4 &matModel, const st } if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE2] != -1 && cShadowBuffers > 1) { - m_pContext->getTextureManager()->selectTexture(4, NULL, 0); + m_pContext->getTextureManager()->selectTexture(4, NULL); GLDEBUG(glActiveTexture(GL_TEXTURE4)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, directional_light->getShadowTextures()[1])); GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); @@ -258,7 +258,7 @@ bool KRShader::bind(const KRViewport &viewport, const KRMat4 &matModel, const st } if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE3] != -1 && cShadowBuffers > 2) { - m_pContext->getTextureManager()->selectTexture(5, NULL, 0); + m_pContext->getTextureManager()->selectTexture(5, NULL); GLDEBUG(glActiveTexture(GL_TEXTURE5)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, directional_light->getShadowTextures()[2])); GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); diff --git a/KREngine/KREngine/Classes/KRTexture.cpp b/KREngine/KREngine/Classes/KRTexture.cpp index 0e06a4c..f6f76cc 100644 --- a/KREngine/KREngine/Classes/KRTexture.cpp +++ b/KREngine/KREngine/Classes/KRTexture.cpp @@ -6,60 +6,104 @@ // Copyright (c) 2012 Kearwood Software. All rights reserved. // +#include #include "KRTexture.h" #include "KRDataBlock.h" -#include +#include "KRContext.h" +#include "KRTextureManager.h" KRTexture::KRTexture(KRContext &context) : KRContextObject(context) { m_iHandle = 0; m_textureMemUsed = 0; + m_last_frame_used = 0; } KRTexture::~KRTexture() { - size_t textureMemFreed = 0; - releaseHandle(textureMemFreed); + releaseHandle(); } -void KRTexture::releaseHandle(size_t &textureMemUsed) { - textureMemUsed -= getMemSize(); +void KRTexture::releaseHandle() { if(m_iHandle != 0) { GLDEBUG(glDeleteTextures(1, &m_iHandle)); + getContext().getTextureManager()->memoryChanged(-getMemSize()); m_iHandle = 0; m_textureMemUsed = 0; } - textureMemUsed += getMemSize(); } long KRTexture::getMemSize() { return m_textureMemUsed; // TODO - This is not 100% accurate, as loaded format may differ in size while in GPU memory } -GLuint KRTexture::getHandle(int max_dim, bool can_resize) { - // Constrain target LOD to be within mipmap levels of texture - int target_dim = max_dim; - - // ---- Start: incremental texture loading ---- - if(m_current_lod_max_dim == 0) { - target_dim = m_min_lod_max_dim; - } else if((m_current_lod_max_dim << 1) < target_dim) { - target_dim = m_current_lod_max_dim << 1; - } - // ---- End: incremental texture loading ---- - - 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) { - size_t memFreed = 0; - releaseHandle(memFreed); - } - if(m_iHandle == 0) { - if(!createGLTexture(target_dim)) { - assert(false); +void KRTexture::resize(int max_dim) +{ + if(max_dim == 0) { + releaseHandle(); + } else { + int requiredMemoryTransfer = getThroughputRequiredForResize(max_dim); + int requiredMemoryDelta = getMemRequiredForSize(max_dim) - getMemSize(); + + if(requiredMemoryDelta) { + // Only resize / regenerate the texture if it actually changes the size of the texture (Assumption: textures of different sizes will always consume different amounts of memory) + + if(getContext().getTextureManager()->getMemoryTransferedThisFrame() + requiredMemoryTransfer > getContext().KRENGINE_MAX_TEXTURE_THROUGHPUT) { + // Exceeding per-frame transfer throughput; can't resize now + return; + } + + if(getContext().getTextureManager()->getMemUsed() + requiredMemoryDelta > getContext().KRENGINE_MAX_TEXTURE_MEM) { + // Exceeding total memory allocated to textures; can't resize now + return; + } + + if(m_current_lod_max_dim != max_dim || m_iHandle == 0) { + releaseHandle(); + } + if(m_iHandle == 0) { + if(!createGLTexture(max_dim)) { + assert(false); + } + } } } +} + + +GLuint KRTexture::getHandle() { + if(m_iHandle == 0) { + resize(getContext().KRENGINE_MIN_TEXTURE_DIM); + } + + m_last_frame_used = getContext().getCurrentFrame(); + return m_iHandle; } + +long KRTexture::getThroughputRequiredForResize(int max_dim) +{ + // Calculate the throughput required for GPU texture upload if the texture is resized to max_dim. + // This default behaviour assumes that the texture will need to be deleted and regenerated to change the maximum mip-map level. + // If an OpenGL extension is present that allows a texture to be resized incrementally, then this method should be overridden + if(max_dim != m_current_lod_max_dim && max_dim != 0) { + int requiredMemory = getMemRequiredForSize(max_dim); + int requiredMemoryDelta = requiredMemory - getMemSize(); + + if(requiredMemoryDelta == 0) { + // Only resize / regenerate the texture if it actually changes the size of the texture (Assumption: textures of different sizes will always consume different amounts of memory) + return 0; + } + return requiredMemory; + } else { + return 0; + } +} + +long KRTexture::getLastFrameUsed() +{ + return m_last_frame_used; +} + + diff --git a/KREngine/KREngine/Classes/KRTexture.h b/KREngine/KREngine/Classes/KRTexture.h index 535de79..7b5365b 100644 --- a/KREngine/KREngine/Classes/KRTexture.h +++ b/KREngine/KREngine/Classes/KRTexture.h @@ -45,24 +45,30 @@ public: KRTexture(KRContext &context); virtual ~KRTexture(); - virtual void bind(size_t &textureMemUsed, int max_dim, bool can_resize) = 0; - void releaseHandle(size_t &textureMemUsed); + virtual void bind() = 0; + void releaseHandle(); long getMemSize(); - - + + virtual long getMemRequiredForSize(int max_dim) = 0; + virtual long getThroughputRequiredForResize(int max_dim); + virtual void resize(int max_dim); + + long getLastFrameUsed(); protected: virtual bool createGLTexture(int lod_max_dim) = 0; - GLuint getHandle(int max_dim, bool can_resize); + GLuint getHandle(); GLuint m_iHandle; - size_t m_textureMemUsed; + long m_textureMemUsed; int m_current_lod_max_dim; uint32_t m_max_lod_max_dim; uint32_t m_min_lod_max_dim; + + long m_last_frame_used; }; diff --git a/KREngine/KREngine/Classes/KRTexture2D.cpp b/KREngine/KREngine/Classes/KRTexture2D.cpp index 0ed465e..1c0edda 100644 --- a/KREngine/KREngine/Classes/KRTexture2D.cpp +++ b/KREngine/KREngine/Classes/KRTexture2D.cpp @@ -63,6 +63,7 @@ bool KRTexture2D::createGLTexture(int lod_max_dim) { } else { GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); } + if(!uploadTexture(GL_TEXTURE_2D, lod_max_dim, m_current_lod_max_dim, m_textureMemUsed)) { GLDEBUG(glDeleteTextures(1, &m_iHandle)); m_iHandle = 0; @@ -70,19 +71,20 @@ bool KRTexture2D::createGLTexture(int lod_max_dim) { return false; } + return true; } -void KRTexture2D::bind(size_t &textureMemUsed, int max_dim, bool can_resize) { - textureMemUsed -= getMemSize(); - GLDEBUG(glBindTexture(GL_TEXTURE_2D, getHandle(max_dim, can_resize))); +void KRTexture2D::bind() { + GLuint handle = getHandle(); - // 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)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)); - - textureMemUsed += getMemSize(); + GLDEBUG(glBindTexture(GL_TEXTURE_2D, handle)); + if(handle) { + // 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)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)); + } } int KRTexture2D::getMaxMipMap() { @@ -95,5 +97,4 @@ int KRTexture2D::getMinMipMap() { bool KRTexture2D::hasMipmaps() { return m_max_lod_max_dim != m_min_lod_max_dim; -} - +} \ No newline at end of file diff --git a/KREngine/KREngine/Classes/KRTexture2D.h b/KREngine/KREngine/Classes/KRTexture2D.h index 0515336..1384a3b 100644 --- a/KREngine/KREngine/Classes/KRTexture2D.h +++ b/KREngine/KREngine/Classes/KRTexture2D.h @@ -52,8 +52,8 @@ public: int getMaxMipMap(); int getMinMipMap(); - virtual bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, size_t &textureMemUsed) = 0; - virtual void bind(size_t &textureMemUsed, int max_dim, bool can_resize); + virtual bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed) = 0; + virtual void bind(); protected: KRDataBlock *m_pData; diff --git a/KREngine/KREngine/Classes/KRTextureCube.cpp b/KREngine/KREngine/Classes/KRTextureCube.cpp index 4023342..eedb838 100644 --- a/KREngine/KREngine/Classes/KRTextureCube.cpp +++ b/KREngine/KREngine/Classes/KRTextureCube.cpp @@ -29,6 +29,7 @@ // or implied, of Kearwood Gilbert. // +#import #include "KRTextureCube.h" #include "KRTexture2D.h" #include "KRContext.h" @@ -85,14 +86,27 @@ bool KRTextureCube::createGLTexture(int lod_max_dim) return true; } - -void KRTextureCube::bind(size_t &textureMemUsed, int max_dim, bool can_resize) +long KRTextureCube::getMemRequiredForSize(int max_dim) { - textureMemUsed -= getMemSize(); - - GLDEBUG(glBindTexture(GL_TEXTURE_CUBE_MAP, getHandle(max_dim, can_resize))); - GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); - - textureMemUsed += getMemSize(); -} \ No newline at end of file + long memoryRequired = 0; + for(int i=0; i<6; i++) { + std::string faceName = m_name + SUFFIXES[i]; + KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName.c_str()); + if(faceTexture) { + memoryRequired += faceTexture->getMemRequiredForSize(max_dim); + } + } + return memoryRequired; +} + + +void KRTextureCube::bind() +{ + GLuint handle = getHandle(); + GLDEBUG(glBindTexture(GL_TEXTURE_CUBE_MAP, handle)); + if(handle) { + GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + } +} + diff --git a/KREngine/KREngine/Classes/KRTextureCube.h b/KREngine/KREngine/Classes/KRTextureCube.h index 8502f82..9fb8af9 100644 --- a/KREngine/KREngine/Classes/KRTextureCube.h +++ b/KREngine/KREngine/Classes/KRTextureCube.h @@ -39,7 +39,9 @@ public: KRTextureCube(KRContext &context, std::string name); virtual ~KRTextureCube(); - virtual void bind(size_t &textureMemUsed, int max_dim, bool can_resize); + virtual void bind(); + virtual long getMemRequiredForSize(int max_dim); + private: virtual bool createGLTexture(int lod_max_dim); diff --git a/KREngine/KREngine/Classes/KRTextureManager.cpp b/KREngine/KREngine/Classes/KRTextureManager.cpp index 310ab5e..a94f165 100644 --- a/KREngine/KREngine/Classes/KRTextureManager.cpp +++ b/KREngine/KREngine/Classes/KRTextureManager.cpp @@ -40,11 +40,10 @@ KRTextureManager::KRTextureManager(KRContext &context) : KRContextObject(context) { m_textureMemUsed = 0; - m_activeTextureMemUsed = 0; - m_lod_max_dim_cap = 2048; for(int iTexture=0; iTexturebind(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(); - } + pTexture->bind(); } else { GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); } m_boundTextures[iTextureUnit] = pTexture; - while(m_activeTextures.size() + m_poolTextures.size() > KRContext::KRENGINE_MAX_TEXTURE_HANDLES || m_textureMemUsed > KRContext::KRContext::KRENGINE_MAX_TEXTURE_MEM) { - if(m_poolTextures.empty()) { - fprintf(stderr, "Kraken - Texture swapping...\n"); - decreaseLODCap(); - m_pContext->rotateBuffers(false); - } - // Keep texture size within limits - KRTexture *droppedTexture = (*m_poolTextures.begin()); - if(droppedTexture == NULL) { - break; - } else { - droppedTexture->releaseHandle(m_textureMemUsed); - m_poolTextures.erase(droppedTexture); - } - } } - -// fprintf(stderr, "VBO Mem: %i Kbyte Texture Mem: %i Kbyte\n", (int)m_pContext->getModelManager()->getMemUsed() / 1024, (int)m_pContext->getTextureManager()->getMemUsed() / 1024); + } -size_t KRTextureManager::getMemUsed() { +long KRTextureManager::getMemUsed() { return m_textureMemUsed; } -size_t KRTextureManager::getActiveMemUsed() { - return m_activeTextureMemUsed; +void KRTextureManager::startFrame() +{ + m_memoryTransferredThisFrame = 0; + balanceTextureMemory(); + rotateBuffers(); } - -void KRTextureManager::rotateBuffers(bool new_frame) +void KRTextureManager::endFrame() { - if(new_frame && m_activeTextureMemUsed < KRContext::KRENGINE_TARGET_TEXTURE_MEM_MIN && m_activeTextureMemUsed * 4 < KRContext::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 > KRContext::KRENGINE_TARGET_TEXTURE_MEM_MAX) { - decreaseLODCap(); - } - m_poolTextures.insert(m_activeTextures.begin(), m_activeTextures.end()); - m_activeTextures.clear(); - m_activeTextureMemUsed = 0; + +} + +void KRTextureManager::balanceTextureMemory() +{ + // Balance texture memory by reducing and increasing the maximum mip-map level of both active and inactive textures + // Favour performance over maximum texture resolution when memory is insufficient for textures at full resolution. - for(int iTexture=0; iTexture < KRENGINE_MAX_TEXTURE_UNITS; iTexture++) { - KRTexture *pBoundTexture = m_boundTextures[iTexture]; - if(pBoundTexture != NULL) { - m_poolTextures.erase(pBoundTexture); - if(m_activeTextures.find(pBoundTexture) == m_activeTextures.end()) { - m_activeTextures.insert(pBoundTexture); - m_activeTextureMemUsed += pBoundTexture->getMemSize(); + // Determine the additional amount of memory required in order to resize all active textures to the maximum size + long wantedTextureMem = 0; + for(std::set::iterator itr=m_activeTextures.begin(); itr != m_activeTextures.end(); itr++) { + KRTexture *activeTexture = *itr; + + wantedTextureMem = activeTexture->getMemRequiredForSize(getContext().KRENGINE_MAX_TEXTURE_DIM) - activeTexture->getMemSize(); + } + + // Determine how much memory we need to free up + long memoryDeficit = wantedTextureMem - (getContext().KRENGINE_MAX_TEXTURE_MEM - getMemUsed()); + + + // Determine how many mip map levels we need to strip off of inactive textures to free the memory we need + long maxDimInactive = getContext().KRENGINE_MAX_TEXTURE_DIM; + long potentialMemorySaving = 0; + while(potentialMemorySaving < memoryDeficit && maxDimInactive > getContext().KRENGINE_MIN_TEXTURE_DIM) { + maxDimInactive = maxDimInactive >> 1; + potentialMemorySaving = 0; + + for(std::set::iterator itr=m_poolTextures.begin(); itr != m_poolTextures.end(); itr++) { + KRTexture *poolTexture = *itr; + long potentialMemoryDelta = poolTexture->getMemRequiredForSize(maxDimInactive) - poolTexture->getMemSize(); + if(potentialMemoryDelta < 0) { + potentialMemorySaving += -potentialMemoryDelta; } } } -} - -void KRTextureManager::decreaseLODCap() -{ - if(m_lod_max_dim_cap > KRContext::KRENGINE_MIN_TEXTURE_DIM) { - m_lod_max_dim_cap = m_lod_max_dim_cap >> 1; + + // Strip off mipmap levels of inactive textures to free up memory + long inactive_texture_mem_used_target = 0; + for(std::set::iterator itr=m_poolTextures.begin(); itr != m_poolTextures.end(); itr++) { + KRTexture *poolTexture = *itr; + long potentialMemoryDelta = poolTexture->getMemRequiredForSize(maxDimInactive) - poolTexture->getMemSize(); + if(potentialMemoryDelta < 0) { + poolTexture->resize(maxDimInactive); + inactive_texture_mem_used_target += poolTexture->getMemRequiredForSize(maxDimInactive); + } else { + inactive_texture_mem_used_target += poolTexture->getMemSize(); + } } -} - -void KRTextureManager::increaseLODCap() -{ - if(m_lod_max_dim_cap < KRContext::KRENGINE_MAX_TEXTURE_DIM) { - m_lod_max_dim_cap = m_lod_max_dim_cap << 1; + + // Determine the maximum mipmap level for the active textures we can achieve with the memory that is available + long memory_available = 0; + long maxDimActive = getContext().KRENGINE_MAX_TEXTURE_DIM; + while(memory_available <= 0 && maxDimActive >= getContext().KRENGINE_MIN_TEXTURE_DIM) { + memory_available = getContext().KRENGINE_MAX_TEXTURE_MEM - inactive_texture_mem_used_target; + for(std::set::iterator itr=m_activeTextures.begin(); itr != m_activeTextures.end() && memory_available > 0; itr++) { + KRTexture *activeTexture = *itr; + memory_available -= activeTexture->getMemRequiredForSize(maxDimActive); + } + + if(memory_available <= 0) { + maxDimActive = maxDimActive >> 1; // Try the next smaller mipmap size + } } + + // Resize active textures to balance the memory usage and mipmap levels + for(std::set::iterator itr=m_activeTextures.begin(); itr != m_activeTextures.end() && memory_available > 0; itr++) { + KRTexture *activeTexture = *itr; + activeTexture->resize(maxDimActive); + } + + //fprintf(stderr, "Active mipmap size: %i Inactive mapmap size: %i\n", (int)maxDimActive, (int)maxDimInactive); } -int KRTextureManager::getLODDimCap() +void KRTextureManager::rotateBuffers() { - return m_lod_max_dim_cap; + const long KRENGINE_TEXTURE_EXPIRY_FRAMES = 120; + + // ----====---- Expire textures that haven't been used in a long time ----====---- + std::set expiredTextures; + for(std::set::iterator itr=m_poolTextures.begin(); itr != m_poolTextures.end(); itr++) { + KRTexture *poolTexture = *itr; + if(poolTexture->getLastFrameUsed() + KRENGINE_TEXTURE_EXPIRY_FRAMES < getContext().getCurrentFrame()) { + expiredTextures.insert(poolTexture); + poolTexture->releaseHandle(); + } + } + for(std::set::iterator itr=expiredTextures.begin(); itr != expiredTextures.end(); itr++) { + m_poolTextures.erase(*itr); + } + + // ----====---- Swap the buffers ----====---- + m_poolTextures.insert(m_activeTextures.begin(), m_activeTextures.end()); + m_activeTextures.clear(); } +long KRTextureManager::getMemoryTransferedThisFrame() +{ + return m_memoryTransferredThisFrame; +} + +void KRTextureManager::addMemoryTransferredThisFrame(long memoryTransferred) +{ + m_memoryTransferredThisFrame += memoryTransferred; +} + +void KRTextureManager::memoryChanged(long memoryDelta) +{ + m_textureMemUsed += memoryDelta; +} diff --git a/KREngine/KREngine/Classes/KRTextureManager.h b/KREngine/KREngine/Classes/KRTextureManager.h index fe77b7f..42e6643 100644 --- a/KREngine/KREngine/Classes/KRTextureManager.h +++ b/KREngine/KREngine/Classes/KRTextureManager.h @@ -49,22 +49,24 @@ public: KRTextureManager(KRContext &context); virtual ~KRTextureManager(); - void rotateBuffers(bool new_frame); - - void selectTexture(int iTextureUnit, KRTexture *pTexture, int lod_max_dim); + void selectTexture(int iTextureUnit, KRTexture *pTexture); KRTexture *loadTexture(const char *szName, const char *szExtension, KRDataBlock *data); KRTexture *getTextureCube(const char *szName); KRTexture *getTexture(const char *szFile); - size_t getMemUsed(); - size_t getActiveMemUsed(); + long getMemUsed(); - int getLODDimCap(); + long getMemoryTransferedThisFrame(); + void addMemoryTransferredThisFrame(long memoryTransferred); + + void memoryChanged(long memoryDelta); + + void startFrame(); + void endFrame(); private: - void decreaseLODCap(); - void increaseLODCap(); + long m_memoryTransferredThisFrame; std::map m_textures; @@ -72,10 +74,11 @@ private: std::set m_activeTextures; std::set m_poolTextures; - size_t m_textureMemUsed; - size_t m_activeTextureMemUsed; + long m_textureMemUsed; + - int m_lod_max_dim_cap; + void rotateBuffers(); + void balanceTextureMemory(); }; #endif diff --git a/KREngine/KREngine/Classes/KRTexturePVR.cpp b/KREngine/KREngine/Classes/KRTexturePVR.cpp index 13f6088..4c0f919 100644 --- a/KREngine/KREngine/Classes/KRTexturePVR.cpp +++ b/KREngine/KREngine/Classes/KRTexturePVR.cpp @@ -150,20 +150,53 @@ KRTexturePVR::~KRTexturePVR() { } -bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, size_t &textureMemUsed) +long KRTexturePVR::getMemRequiredForSize(int max_dim) { + // Determine how much memory will be consumed int width = m_iWidth; int height = m_iHeight; + long memoryRequired = 0; + + for(std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { + dataBlockStruct block = *itr; + if(width <= max_dim && height <= max_dim) { + memoryRequired += block.length; + } + + width = width >> 1; + if(width < 1) { + width = 1; + } + height = height >> 1; + if(height < 1) { + height = 1; + } + } + + return memoryRequired; +} + +bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed) +{ + GLenum err; if(m_blocks.size() == 0) { return false; } + // Determine how much memory will be consumed + int width = m_iWidth; + int height = m_iHeight; + long memoryRequired = 0; + + + // Upload texture data int i=0; for(std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { dataBlockStruct block = *itr; if(width <= lod_max_dim && height <= lod_max_dim) { + memoryRequired += block.length; if(width > current_lod_max_dim) { current_lod_max_dim = width; } @@ -173,9 +206,11 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo glCompressedTexImage2D(target, i, m_internalFormat, width, height, 0, block.length, block.start); err = glGetError(); if (err != GL_NO_ERROR) { + assert(false); return false; } - textureMemUsed += block.length; + + i++; } @@ -189,6 +224,10 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo } } + textureMemUsed += memoryRequired; + getContext().getTextureManager()->memoryChanged(memoryRequired); + getContext().getTextureManager()->addMemoryTransferredThisFrame(memoryRequired); + return true; } diff --git a/KREngine/KREngine/Classes/KRTexturePVR.h b/KREngine/KREngine/Classes/KRTexturePVR.h index cc76f42..50d1f68 100644 --- a/KREngine/KREngine/Classes/KRTexturePVR.h +++ b/KREngine/KREngine/Classes/KRTexturePVR.h @@ -17,7 +17,9 @@ public: KRTexturePVR(KRContext &context, KRDataBlock *data); virtual ~KRTexturePVR(); - bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, size_t &textureMemUsed); + bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed); + + virtual long getMemRequiredForSize(int max_dim); protected: diff --git a/KREngine/KREngine/Classes/KRTextureTGA.cpp b/KREngine/KREngine/Classes/KRTextureTGA.cpp index 9cc5c29..534014b 100644 --- a/KREngine/KREngine/Classes/KRTextureTGA.cpp +++ b/KREngine/KREngine/Classes/KRTextureTGA.cpp @@ -8,6 +8,7 @@ #include "KRTextureTGA.h" #include "KREngine-common.h" +#include "KRContext.h" typedef struct { char idlength; @@ -38,10 +39,10 @@ KRTextureTGA::~KRTextureTGA() } -bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, size_t &textureMemUsed) +bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed) { TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart(); - unsigned char *pData = (unsigned char *)pHeader + (size_t)pHeader->idlength + (size_t)pHeader->colourmaplength * (size_t)pHeader->colourmaptype + sizeof(TGA_HEADER); + unsigned char *pData = (unsigned char *)pHeader + (long)pHeader->idlength + (long)pHeader->colourmaplength * (long)pHeader->colourmaptype + sizeof(TGA_HEADER); if(pHeader->colourmaptype != 0) { return false; // Mapped colors not supported @@ -74,8 +75,13 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo glTexImage2D(target, 0, GL_RGBA, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image); delete converted_image; err = glGetError(); - if (err != GL_NO_ERROR) return false; - textureMemUsed += pHeader->width * pHeader->height * 4; + if (err != GL_NO_ERROR) { + return false; + } + int memAllocated = pHeader->width * pHeader->height * 4; + textureMemUsed += memAllocated; + getContext().getTextureManager()->memoryChanged(memAllocated); + getContext().getTextureManager()->addMemoryTransferredThisFrame(memAllocated); current_lod_max_dim = m_max_lod_max_dim; } break; @@ -83,8 +89,13 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo { glTexImage2D(target, 0, GL_RGBA, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)pData); err = glGetError(); - if (err != GL_NO_ERROR) return false; - textureMemUsed += pHeader->width * pHeader->height * 4; + if (err != GL_NO_ERROR) { + return false; + } + int memAllocated = pHeader->width * pHeader->height * 4; + textureMemUsed += memAllocated; + getContext().getTextureManager()->memoryChanged(memAllocated); + getContext().getTextureManager()->addMemoryTransferredThisFrame(memAllocated); current_lod_max_dim = m_max_lod_max_dim; } break; @@ -98,3 +109,26 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo return true; } + +long KRTextureTGA::getMemRequiredForSize(int max_dim) +{ + TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart(); + switch(pHeader->imagetype) { + case 2: // rgb + switch(pHeader->bitsperpixel) { + case 24: + { + return pHeader->width * pHeader->height * 4; + } + break; + case 32: + { + return pHeader->width * pHeader->height * 4; + } + break; + } + break; + } + + return 0; +} diff --git a/KREngine/KREngine/Classes/KRTextureTGA.h b/KREngine/KREngine/Classes/KRTextureTGA.h index 36c86cb..53ce2f0 100644 --- a/KREngine/KREngine/Classes/KRTextureTGA.h +++ b/KREngine/KREngine/Classes/KRTextureTGA.h @@ -17,7 +17,9 @@ public: KRTextureTGA(KRContext &context, KRDataBlock *data); virtual ~KRTextureTGA(); - bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, size_t &textureMemUsed); + bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed); + + virtual long getMemRequiredForSize(int max_dim); }; #endif