diff --git a/KREngine/kraken/KRLODSet.cpp b/KREngine/kraken/KRLODSet.cpp index b855815..d056e30 100644 --- a/KREngine/kraken/KRLODSet.cpp +++ b/KREngine/kraken/KRLODSet.cpp @@ -55,7 +55,7 @@ void KRLODSet::updateLODVisibility(const KRViewport &viewport) } else if(m_activeLODGroup == NULL) { m_activeLODGroup = new_active_lod_group; } else if(new_active_lod_group != m_activeLODGroup) { - if(/*true || */new_active_lod_group->getStreamLevel(true, viewport) >= kraken_stream_level::STREAM_LEVEL_IN_LQ) { // FINDME, HACK! Disabled due to performance issues. + if(true || new_active_lod_group->getStreamLevel(true, viewport) >= kraken_stream_level::STREAM_LEVEL_IN_LQ) { // FINDME, HACK! Disabled due to performance issues. // fprintf(stderr, "LOD %s -> %s\n", m_activeLODGroup->getName().c_str(), new_active_lod_group->getName().c_str()); m_activeLODGroup = new_active_lod_group; } else { diff --git a/KREngine/kraken/KRTexture.cpp b/KREngine/kraken/KRTexture.cpp index 0d9fa1d..5ce80d6 100644 --- a/KREngine/kraken/KRTexture.cpp +++ b/KREngine/kraken/KRTexture.cpp @@ -14,6 +14,8 @@ KRTexture::KRTexture(KRContext &context, std::string name) : KRResource(context, name) { + m_current_lod_max_dim = 0; + m_new_lod_max_dim = 0; m_iHandle = 0; m_iNewHandle = 0; m_textureMemUsed = 0; @@ -45,6 +47,8 @@ void KRTexture::releaseHandles() { m_iHandle = 0; m_textureMemUsed = 0; } + m_current_lod_max_dim = 0; + m_new_lod_max_dim = 0; m_handle_lock.clear(); @@ -71,7 +75,7 @@ void KRTexture::resize(int max_dim) int target_dim = max_dim; if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim; - if(m_current_lod_max_dim != target_dim || (m_iHandle == 0 && m_iNewHandle == 0)) { + if(m_new_lod_max_dim != target_dim || (m_iHandle == 0 && m_iNewHandle == 0)) { assert(m_newTextureMemUsed == 0); m_newTextureMemUsed = getMemRequiredForSize(target_dim); @@ -175,6 +179,10 @@ int KRTexture::getCurrentLodMaxDim() { return m_current_lod_max_dim; } +int KRTexture::getNewLodMaxDim() { + return m_new_lod_max_dim; +} + int KRTexture::getMaxMipMap() { return m_max_lod_max_dim; } @@ -207,6 +215,7 @@ void KRTexture::_swapHandles() m_textureMemUsed = (long)m_newTextureMemUsed; m_newTextureMemUsed = 0; m_iHandle = m_iNewHandle; + m_current_lod_max_dim = m_new_lod_max_dim; } m_handle_lock.clear(); } diff --git a/KREngine/kraken/KRTexture.h b/KREngine/kraken/KRTexture.h index cc741fb..fa338b5 100644 --- a/KREngine/kraken/KRTexture.h +++ b/KREngine/kraken/KRTexture.h @@ -80,6 +80,7 @@ public: virtual KRTexture *compress(bool premultiply_alpha = false); int getCurrentLodMaxDim(); + int getNewLodMaxDim(); // For use by streamer only int getMaxMipMap(); int getMinMipMap(); bool hasMipmaps(); @@ -100,6 +101,7 @@ protected: std::atomic_flag m_handle_lock; int m_current_lod_max_dim; + int m_new_lod_max_dim; uint32_t m_max_lod_max_dim; uint32_t m_min_lod_max_dim; diff --git a/KREngine/kraken/KRTexture2D.cpp b/KREngine/kraken/KRTexture2D.cpp index 11918d9..25a7a7e 100644 --- a/KREngine/kraken/KRTexture2D.cpp +++ b/KREngine/kraken/KRTexture2D.cpp @@ -34,7 +34,6 @@ #include "KRTextureManager.h" KRTexture2D::KRTexture2D(KRContext &context, KRDataBlock *data, std::string name) : KRTexture(context, name) { - m_current_lod_max_dim = 0; m_pData = data; } @@ -48,16 +47,11 @@ bool KRTexture2D::createGLTexture(int lod_max_dim) { } bool success = true; - int prev_lod_max_dim = 0; -#if GL_APPLE_copy_texture_levels && GL_EXT_texture_storage - - if(m_iHandle != 0) { - prev_lod_max_dim = m_current_lod_max_dim; - } -#endif + int prev_lod_max_dim = m_new_lod_max_dim; + m_iNewHandle = 0; - m_current_lod_max_dim = 0; + m_new_lod_max_dim = 0; GLDEBUG(glGenTextures(1, &m_iNewHandle)); if(m_iNewHandle == 0) { @@ -71,10 +65,10 @@ bool KRTexture2D::createGLTexture(int lod_max_dim) { GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); } - if(!uploadTexture(GL_TEXTURE_2D, lod_max_dim, m_current_lod_max_dim, prev_lod_max_dim)) { + if(!uploadTexture(GL_TEXTURE_2D, lod_max_dim, m_new_lod_max_dim)) { GLDEBUG(glDeleteTextures(1, &m_iNewHandle)); m_iNewHandle = m_iHandle; - m_current_lod_max_dim = prev_lod_max_dim; + m_new_lod_max_dim = prev_lod_max_dim; success = false; } } diff --git a/KREngine/kraken/KRTexture2D.h b/KREngine/kraken/KRTexture2D.h index 921370b..8b32bdd 100644 --- a/KREngine/kraken/KRTexture2D.h +++ b/KREngine/kraken/KRTexture2D.h @@ -46,7 +46,7 @@ public: virtual bool save(const std::string& path); virtual bool save(KRDataBlock &data); - virtual bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress = false, bool premultiply_alpha = false) = 0; + virtual bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, bool compress = false, bool premultiply_alpha = false) = 0; virtual void bind(GLuint texture_unit); protected: diff --git a/KREngine/kraken/KRTextureCube.cpp b/KREngine/kraken/KRTextureCube.cpp index 992fe79..57a7bef 100644 --- a/KREngine/kraken/KRTextureCube.cpp +++ b/KREngine/kraken/KRTextureCube.cpp @@ -46,6 +46,8 @@ KRTextureCube::KRTextureCube(KRContext &context, std::string name) : KRTexture(c if(m_textures[i]) { if(m_textures[i]->getMaxMipMap() < m_max_lod_max_dim) m_max_lod_max_dim = m_textures[i]->getMaxMipMap(); if(m_textures[i]->getMinMipMap() > m_min_lod_max_dim) m_min_lod_max_dim = m_textures[i]->getMinMipMap(); + } else { + assert(false); } } } @@ -59,21 +61,12 @@ bool KRTextureCube::createGLTexture(int lod_max_dim) assert(m_iNewHandle == m_iHandle); // Only allow one resize per frame bool success = true; - int prev_lod_max_dim = 0; -#if GL_APPLE_copy_texture_levels && GL_EXT_texture_storage - - if(m_iHandle != 0) { - prev_lod_max_dim = m_current_lod_max_dim; - } - - -#endif m_iNewHandle = 0; GLDEBUG(glGenTextures(1, &m_iNewHandle)); assert(m_iNewHandle != 0); - m_current_lod_max_dim = 0; + m_new_lod_max_dim = 0; GLDEBUG(glBindTexture(GL_TEXTURE_CUBE_MAP, m_iNewHandle)); bool bMipMaps = false; @@ -82,7 +75,7 @@ bool KRTextureCube::createGLTexture(int lod_max_dim) std::string faceName = getName() + SUFFIXES[i]; if(m_textures[i]) { if(m_textures[i]->hasMipmaps()) bMipMaps = true; - m_textures[i]->uploadTexture(TARGETS[i], lod_max_dim, m_current_lod_max_dim, prev_lod_max_dim); + m_textures[i]->uploadTexture(TARGETS[i], lod_max_dim, m_new_lod_max_dim); } } @@ -112,7 +105,7 @@ long KRTextureCube::getMemRequiredForSize(int max_dim) return memoryRequired; } - +/* void KRTextureCube::resetPoolExpiry(float lodCoverage, texture_usage_t textureUsage) { KRTexture::resetPoolExpiry(lodCoverage, textureUsage); @@ -122,6 +115,7 @@ void KRTextureCube::resetPoolExpiry(float lodCoverage, texture_usage_t textureUs } } } +*/ void KRTextureCube::bind(GLuint texture_unit) { diff --git a/KREngine/kraken/KRTextureCube.h b/KREngine/kraken/KRTextureCube.h index 95c29fd..c643e2b 100644 --- a/KREngine/kraken/KRTextureCube.h +++ b/KREngine/kraken/KRTextureCube.h @@ -46,7 +46,7 @@ public: virtual void bind(GLuint texture_unit); virtual long getMemRequiredForSize(int max_dim); - virtual void resetPoolExpiry(float lodCoverage, texture_usage_t textureUsage); +// virtual void resetPoolExpiry(float lodCoverage, texture_usage_t textureUsage); private: virtual bool createGLTexture(int lod_max_dim); diff --git a/KREngine/kraken/KRTextureKTX.cpp b/KREngine/kraken/KRTextureKTX.cpp index 863c624..a1bb5bd 100644 --- a/KREngine/kraken/KRTextureKTX.cpp +++ b/KREngine/kraken/KRTextureKTX.cpp @@ -153,7 +153,7 @@ long KRTextureKTX::getMemRequiredForSize(int max_dim) return memoryRequired; } -bool KRTextureKTX::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress, bool premultiply_alpha) +bool KRTextureKTX::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, bool compress, bool premultiply_alpha) { int target_dim = lod_max_dim; if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim; @@ -220,7 +220,7 @@ bool KRTextureKTX::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo current_lod_max_dim = height; } #if GL_APPLE_copy_texture_levels && GL_EXT_texture_storage - if(target == GL_TEXTURE_2D && width <= prev_lod_max_dim && height <= prev_lod_max_dim) { + if(target == GL_TEXTURE_2D && width <= m_current_lod_max_dim && height <= m_current_lod_max_dim) { //GLDEBUG(glCompressedTexImage2D(target, i, (GLenum)m_header.glInternalFormat, width, height, 0, block.length, NULL)); // Allocate, but don't copy // GLDEBUG(glTexImage2D(target, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL)); GLDEBUG(glCopyTextureLevelsAPPLE(m_iNewHandle, m_iHandle, source_level, 1)); @@ -253,7 +253,7 @@ bool KRTextureKTX::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo destination_level++; } - if(width <= prev_lod_max_dim && height <= prev_lod_max_dim) { + if(width <= m_current_lod_max_dim && height <= m_current_lod_max_dim) { source_level++; } diff --git a/KREngine/kraken/KRTextureKTX.h b/KREngine/kraken/KRTextureKTX.h index f9f5d30..4f1279e 100644 --- a/KREngine/kraken/KRTextureKTX.h +++ b/KREngine/kraken/KRTextureKTX.h @@ -19,7 +19,7 @@ public: virtual ~KRTextureKTX(); virtual std::string getExtension(); - bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress = false, bool premultiply_alpha = false); + bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, bool compress = false, bool premultiply_alpha = false); virtual long getMemRequiredForSize(int max_dim); diff --git a/KREngine/kraken/KRTextureManager.cpp b/KREngine/kraken/KRTextureManager.cpp index c6458e9..6222772 100644 --- a/KREngine/kraken/KRTextureManager.cpp +++ b/KREngine/kraken/KRTextureManager.cpp @@ -145,10 +145,42 @@ KRTexture *KRTextureManager::getTextureCube(const char *szName) { unordered_map::iterator itr = m_textures.find(lowerName); if(itr == m_textures.end()) { - KRTextureCube *pTexture = new KRTextureCube(getContext(), lowerName); - m_textures[lowerName] = pTexture; - return pTexture; + // Defer resolving the texture cube until its referenced textures are ready + const GLenum TARGETS[6] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + }; + + const char *SUFFIXES[6] = { + "_positive_x", + "_negative_x", + "_positive_y", + "_negative_y", + "_positive_z", + "_negative_z" + }; + bool found_all = true; + for(int i=0; i<6; i++) { + std::string faceName = lowerName + SUFFIXES[i]; + KRTexture *faceTexture = dynamic_cast(getContext().getTextureManager()->getTexture(faceName)); + if(faceTexture == NULL) { + found_all = false; + } + } + + if(found_all) { + KRTextureCube *pTexture = new KRTextureCube(getContext(), lowerName); + + m_textures[lowerName] = pTexture; + return pTexture; + } else { + return NULL; + } } else { return (*itr).second; } @@ -251,7 +283,7 @@ void KRTextureManager::doStreaming() { // TODO - Implement proper double-buffering to reduce copy operations m_streamerFenceMutex.lock(); - m_activeTextures_streamer = m_activeTextures_streamer_copy; + m_activeTextures_streamer = std::move(m_activeTextures_streamer_copy); m_streamerFenceMutex.unlock(); balanceTextureMemory(); @@ -277,15 +309,8 @@ void KRTextureManager::balanceTextureMemory() // --------------- - /* - // TODO - Would this be faster with int's for weights? - std::vector > sortedTextures; - for(auto itr=m_activeTextures_streamer.begin(); itr != m_activeTextures_streamer.end(); itr++) { - KRTexture *texture = *itr; - float priority = texture->getStreamPriority(); - sortedTextures.push_back(std::pair(priority, texture)); - } - */ + //long MAX_STREAM_TIME = 66; + //long startTime = getContext().getAbsoluteTimeMilliseconds(); std::sort(m_activeTextures_streamer.begin(), m_activeTextures_streamer.end(), std::greater>()); @@ -298,12 +323,14 @@ void KRTextureManager::balanceTextureMemory() long minLodMem = texture->getMemRequiredForSize(min_mip_level); memoryRemaining -= minLodMem; - if(memoryRemainingThisFrame > minLodMem && texture->getCurrentLodMaxDim() < min_mip_level) { + if(memoryRemainingThisFrame > minLodMem && texture->getNewLodMaxDim() < min_mip_level) { memoryRemainingThisFrame -= minLodMem; texture->resize(min_mip_level); } } + //long minMipTime = getContext().getAbsoluteTimeMilliseconds() - startTime; + std::vector mipPercents = {75, 75, 50, 50, 50}; int mip_drop = -1; auto mip_itr = mipPercents.begin(); @@ -329,13 +356,26 @@ void KRTextureManager::balanceTextureMemory() memoryRemainingThisMip -= additionalMemRequired; memoryRemaining -= additionalMemRequired; if(memoryRemainingThisMip > 0 && memoryRemainingThisFrame > targetMem) { - if(texture->getCurrentLodMaxDim() != target_mip_level) { + int current_mip_level = texture->getNewLodMaxDim(); + if(current_mip_level == (target_mip_level >> 1) || target_mip_level < current_mip_level) { memoryRemainingThisFrame -= targetMem; texture->resize(target_mip_level); + } else if(current_mip_level == (target_mip_level >> 2)) { + memoryRemainingThisFrame -= texture->getMemRequiredForSize(target_mip_level >> 1); + texture->resize(target_mip_level >> 1); + } else if(current_mip_level < (target_mip_level >> 2)) { + memoryRemainingThisFrame -= texture->getMemRequiredForSize(target_mip_level >> 2); + texture->resize(target_mip_level >> 2); } } + + //if(getContext().getAbsoluteTimeMilliseconds() - startTime > MAX_STREAM_TIME) { + // return; // Bail out early if we spend too long + //} } + //long streamerTime = getContext().getAbsoluteTimeMilliseconds() - startTime; + //fprintf(stderr, "%i / %i\n", (int)minMipTime, (int)streamerTime); } diff --git a/KREngine/kraken/KRTexturePVR.cpp b/KREngine/kraken/KRTexturePVR.cpp index 46f3ef4..24de4b4 100644 --- a/KREngine/kraken/KRTexturePVR.cpp +++ b/KREngine/kraken/KRTexturePVR.cpp @@ -173,7 +173,7 @@ long KRTexturePVR::getMemRequiredForSize(int max_dim) return memoryRequired; } -bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress, bool premultiply_alpha) +bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, bool compress, bool premultiply_alpha) { int target_dim = lod_max_dim; if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim; @@ -240,7 +240,7 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo current_lod_max_dim = height; } #if GL_APPLE_copy_texture_levels && GL_EXT_texture_storage - if(target == GL_TEXTURE_2D && width <= prev_lod_max_dim && height <= prev_lod_max_dim) { + if(target == GL_TEXTURE_2D && width <= m_current_lod_max_dim && height <= m_current_lod_max_dim) { //GLDEBUG(glCompressedTexImage2D(target, i, m_internalFormat, width, height, 0, block.length, NULL)); // Allocate, but don't copy // GLDEBUG(glTexImage2D(target, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL)); GLDEBUG(glCopyTextureLevelsAPPLE(m_iNewHandle, m_iHandle, source_level, 1)); @@ -273,7 +273,7 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo destination_level++; } - if(width <= prev_lod_max_dim && height <= prev_lod_max_dim) { + if(width <= m_current_lod_max_dim && height <= m_current_lod_max_dim) { source_level++; } diff --git a/KREngine/kraken/KRTexturePVR.h b/KREngine/kraken/KRTexturePVR.h index 3d973d4..0914960 100644 --- a/KREngine/kraken/KRTexturePVR.h +++ b/KREngine/kraken/KRTexturePVR.h @@ -18,7 +18,7 @@ public: virtual ~KRTexturePVR(); virtual std::string getExtension(); - bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress = false, bool premultiply_alpha = false); + bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, bool compress = false, bool premultiply_alpha = false); virtual long getMemRequiredForSize(int max_dim); diff --git a/KREngine/kraken/KRTextureTGA.cpp b/KREngine/kraken/KRTextureTGA.cpp index b8c97fb..e7f1d3c 100644 --- a/KREngine/kraken/KRTextureTGA.cpp +++ b/KREngine/kraken/KRTextureTGA.cpp @@ -71,7 +71,7 @@ KRTextureTGA::~KRTextureTGA() } -bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress, bool premultiply_alpha) +bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, bool compress, bool premultiply_alpha) { m_pData->lock(); TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart(); @@ -298,7 +298,7 @@ KRTexture *KRTextureTGA::compress(bool premultiply_alpha) GLDEBUG(glBindTexture(GL_TEXTURE_2D, compressed_handle)); int current_max_dim = 0; - if(!uploadTexture(GL_TEXTURE_2D, m_max_lod_max_dim, current_max_dim, 0, true, premultiply_alpha)) { + if(!uploadTexture(GL_TEXTURE_2D, m_max_lod_max_dim, current_max_dim, true, premultiply_alpha)) { assert(false); // Failed to upload the texture } GLDEBUG(glGenerateMipmap(GL_TEXTURE_2D)); diff --git a/KREngine/kraken/KRTextureTGA.h b/KREngine/kraken/KRTextureTGA.h index abca2a8..18e992a 100644 --- a/KREngine/kraken/KRTextureTGA.h +++ b/KREngine/kraken/KRTextureTGA.h @@ -18,7 +18,7 @@ public: virtual ~KRTextureTGA(); virtual std::string getExtension(); - bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim, bool compress = false, bool premultiply_alpha = false); + bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, bool compress = false, bool premultiply_alpha = false); #if !TARGET_OS_IPHONE virtual KRTexture *compress(bool premultiply_alpha = false);