Updated texture memory management code to eliminate inter-frame texture swapping and glFinish() calls, favouring performance over maximum texture resolution when memory is insufficient for textures at full resolution.
--HG-- extra : convert_revision : svn%3A7752d6cf-9f14-4ad2-affc-04f1e67b81a5/trunk%40159
This commit is contained in:
@@ -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 */,
|
||||
|
||||
@@ -164,8 +164,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);
|
||||
|
||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO));
|
||||
@@ -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<KRLight *>(), 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<KRLight *>(), 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<KRLight *>(), 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<KRLight *>(), 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
void KRContext::startFrame()
|
||||
{
|
||||
m_pTextureManager->startFrame();
|
||||
}
|
||||
|
||||
void KRContext::endFrame()
|
||||
{
|
||||
m_pTextureManager->endFrame();
|
||||
rotateBuffers(true);
|
||||
m_current_frame++;
|
||||
}
|
||||
|
||||
long KRContext::getCurrentFrame()
|
||||
{
|
||||
return m_current_frame;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -107,7 +107,7 @@ void KRInstance::render(KRCamera *pCamera, std::vector<KRLight *> &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);
|
||||
|
||||
@@ -190,7 +190,7 @@ void KRLight::render(KRCamera *pCamera, std::vector<KRLight *> &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));
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -67,7 +67,7 @@ void KRParticleSystemBrownian::render(KRCamera *pCamera, std::vector<KRLight *>
|
||||
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;
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -6,60 +6,104 @@
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
#include "KRTexture.h"
|
||||
#include "KRDataBlock.h"
|
||||
#include <assert.h>
|
||||
#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;
|
||||
void KRTexture::resize(int max_dim)
|
||||
{
|
||||
if(max_dim == 0) {
|
||||
releaseHandle();
|
||||
} else {
|
||||
int requiredMemoryTransfer = getThroughputRequiredForResize(max_dim);
|
||||
int requiredMemoryDelta = getMemRequiredForSize(max_dim) - getMemSize();
|
||||
|
||||
// ---- 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;
|
||||
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;
|
||||
}
|
||||
// ---- 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(getContext().getTextureManager()->getMemUsed() + requiredMemoryDelta > getContext().KRENGINE_MAX_TEXTURE_MEM) {
|
||||
// Exceeding total memory allocated to textures; can't resize now
|
||||
return;
|
||||
}
|
||||
|
||||
if(can_resize && m_current_lod_max_dim != target_dim) {
|
||||
size_t memFreed = 0;
|
||||
releaseHandle(memFreed);
|
||||
if(m_current_lod_max_dim != max_dim || m_iHandle == 0) {
|
||||
releaseHandle();
|
||||
}
|
||||
if(m_iHandle == 0) {
|
||||
if(!createGLTexture(target_dim)) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
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));
|
||||
|
||||
textureMemUsed += getMemSize();
|
||||
}
|
||||
}
|
||||
|
||||
int KRTexture2D::getMaxMipMap() {
|
||||
@@ -96,4 +98,3 @@ int KRTexture2D::getMinMipMap() {
|
||||
bool KRTexture2D::hasMipmaps() {
|
||||
return m_max_lod_max_dim != m_min_lod_max_dim;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#import <assert.h>
|
||||
#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();
|
||||
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;
|
||||
}
|
||||
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_CUBE_MAP, getHandle(max_dim, can_resize)));
|
||||
|
||||
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));
|
||||
|
||||
textureMemUsed += getMemSize();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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; iTexture<KRENGINE_MAX_TEXTURE_UNITS; iTexture++) {
|
||||
m_boundTextures[iTexture] = NULL;
|
||||
}
|
||||
m_memoryTransferredThisFrame = 0;
|
||||
}
|
||||
|
||||
KRTextureManager::~KRTextureManager() {
|
||||
@@ -109,99 +108,144 @@ KRTexture *KRTextureManager::getTexture(const char *szName) {
|
||||
|
||||
}
|
||||
|
||||
void KRTextureManager::selectTexture(int iTextureUnit, KRTexture *pTexture, int lod_max_dim) {
|
||||
void KRTextureManager::selectTexture(int iTextureUnit, KRTexture *pTexture) {
|
||||
|
||||
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);
|
||||
}
|
||||
size_t textureMemChange = 0;
|
||||
pTexture->bind(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::rotateBuffers(bool new_frame)
|
||||
void KRTextureManager::startFrame()
|
||||
{
|
||||
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_memoryTransferredThisFrame = 0;
|
||||
balanceTextureMemory();
|
||||
rotateBuffers();
|
||||
}
|
||||
|
||||
void KRTextureManager::endFrame()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
// Determine the additional amount of memory required in order to resize all active textures to the maximum size
|
||||
long wantedTextureMem = 0;
|
||||
for(std::set<KRTexture *>::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<KRTexture *>::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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Strip off mipmap levels of inactive textures to free up memory
|
||||
long inactive_texture_mem_used_target = 0;
|
||||
for(std::set<KRTexture *>::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();
|
||||
}
|
||||
}
|
||||
|
||||
// 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<KRTexture *>::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<KRTexture *>::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);
|
||||
}
|
||||
|
||||
void KRTextureManager::rotateBuffers()
|
||||
{
|
||||
const long KRENGINE_TEXTURE_EXPIRY_FRAMES = 120;
|
||||
|
||||
// ----====---- Expire textures that haven't been used in a long time ----====----
|
||||
std::set<KRTexture *> expiredTextures;
|
||||
for(std::set<KRTexture *>::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<KRTexture *>::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();
|
||||
m_activeTextureMemUsed = 0;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KRTextureManager::decreaseLODCap()
|
||||
long KRTextureManager::getMemoryTransferedThisFrame()
|
||||
{
|
||||
if(m_lod_max_dim_cap > KRContext::KRENGINE_MIN_TEXTURE_DIM) {
|
||||
m_lod_max_dim_cap = m_lod_max_dim_cap >> 1;
|
||||
}
|
||||
return m_memoryTransferredThisFrame;
|
||||
}
|
||||
|
||||
void KRTextureManager::increaseLODCap()
|
||||
void KRTextureManager::addMemoryTransferredThisFrame(long memoryTransferred)
|
||||
{
|
||||
if(m_lod_max_dim_cap < KRContext::KRENGINE_MAX_TEXTURE_DIM) {
|
||||
m_lod_max_dim_cap = m_lod_max_dim_cap << 1;
|
||||
}
|
||||
m_memoryTransferredThisFrame += memoryTransferred;
|
||||
}
|
||||
|
||||
int KRTextureManager::getLODDimCap()
|
||||
void KRTextureManager::memoryChanged(long memoryDelta)
|
||||
{
|
||||
return m_lod_max_dim_cap;
|
||||
m_textureMemUsed += memoryDelta;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<std::string, KRTexture *> m_textures;
|
||||
|
||||
@@ -72,10 +74,11 @@ private:
|
||||
std::set<KRTexture *> m_activeTextures;
|
||||
std::set<KRTexture *> m_poolTextures;
|
||||
|
||||
size_t m_textureMemUsed;
|
||||
size_t m_activeTextureMemUsed;
|
||||
long m_textureMemUsed;
|
||||
|
||||
int m_lod_max_dim_cap;
|
||||
|
||||
void rotateBuffers();
|
||||
void balanceTextureMemory();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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<dataBlockStruct>::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<dataBlockStruct>::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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user