diff --git a/kraken/KRContext.cpp b/kraken/KRContext.cpp index d7792d1..022302b 100755 --- a/kraken/KRContext.cpp +++ b/kraken/KRContext.cpp @@ -57,7 +57,8 @@ int KRContext::KRENGINE_MAX_PIPELINE_HANDLES = 4000; int KRContext::KRENGINE_GPU_MEM_MAX = 256000000; int KRContext::KRENGINE_GPU_MEM_TARGET = 192000000; int KRContext::KRENGINE_MAX_TEXTURE_DIM = 8192; -int KRContext::KRENGINE_MIN_TEXTURE_DIM = 64; +int KRContext::KRENGINE_TEXTURE_HQ_LOD = 0; +int KRContext::KRENGINE_TEXTURE_LQ_LOD = 4; // TODO - This should be configured per-scene? Or auto/dynamic? int KRContext::KRENGINE_PRESTREAM_DISTANCE = 1000.0f; diff --git a/kraken/KRContext.h b/kraken/KRContext.h index 56e2db0..0e2755c 100755 --- a/kraken/KRContext.h +++ b/kraken/KRContext.h @@ -65,8 +65,9 @@ public: static int KRENGINE_GPU_MEM_MAX; static int KRENGINE_GPU_MEM_TARGET; static int KRENGINE_MAX_TEXTURE_DIM; - static int KRENGINE_MIN_TEXTURE_DIM; static int KRENGINE_PRESTREAM_DISTANCE; + static int KRENGINE_TEXTURE_HQ_LOD; + static int KRENGINE_TEXTURE_LQ_LOD; KRContext(const KrInitializeInfo* initializeInfo); diff --git a/kraken/KREngine.mm b/kraken/KREngine.mm index 33f3caa..2120871 100755 --- a/kraken/KREngine.mm +++ b/kraken/KREngine.mm @@ -89,7 +89,8 @@ void kraken::set_debug_text(const std::string &print_text) KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048; - KRContext::KRENGINE_MIN_TEXTURE_DIM = 64; + KRContext::KRENGINE_TEXTURE_HQ_LOD = 0; + KRContext::KRENGINE_TEXTURE_LQ_LOD = 4; KRContext::KRENGINE_PRESTREAM_DISTANCE = 1000.0f; @@ -105,19 +106,22 @@ void kraken::set_debug_text(const std::string &print_text) KRContext::KRENGINE_GPU_MEM_MAX = 64000000 * 2; KRContext::KRENGINE_GPU_MEM_TARGET = 48000000 * 2; KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048; - KRContext::KRENGINE_MIN_TEXTURE_DIM = 64; + KRContext::KRENGINE_TEXTURE_HQ_LOD = 0; + KRContext::KRENGINE_TEXTURE_LQ_LOD = 4; } else { KRContext::KRENGINE_GPU_MEM_MAX = 64000000; KRContext::KRENGINE_GPU_MEM_TARGET = 48000000; KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048; - KRContext::KRENGINE_MIN_TEXTURE_DIM = 64; + KRContext::KRENGINE_TEXTURE_HQ_LOD = 0; + KRContext::KRENGINE_TEXTURE_LQ_LOD = 4; } */ #else KRContext::KRENGINE_GPU_MEM_MAX = 256000000; KRContext::KRENGINE_GPU_MEM_TARGET = 192000000; KRContext::KRENGINE_MAX_TEXTURE_DIM = 8192; - KRContext::KRENGINE_MIN_TEXTURE_DIM = 64; + KRContext::KRENGINE_TEXTURE_HQ_LOD = 0; + KRContext::KRENGINE_TEXTURE_LQ_LOD = 4; KRContext::KRENGINE_PRESTREAM_DISTANCE = 1000.0f; #endif diff --git a/kraken/resources/texture/KRTexture.cpp b/kraken/resources/texture/KRTexture.cpp index 0702944..5d3ac6c 100755 --- a/kraken/resources/texture/KRTexture.cpp +++ b/kraken/resources/texture/KRTexture.cpp @@ -37,8 +37,8 @@ KRTexture::KRTexture(KRContext& context, std::string name) : KRResource(context, name) { - m_current_lod_max_dim = 0; - m_new_lod_max_dim = 0; + m_current_lod = -1; + m_new_lod = -1; m_textureMemUsed = 0; m_newTextureMemUsed = 0; m_last_frame_used = 0; @@ -96,8 +96,8 @@ void KRTexture::releaseHandles() destroyNewHandles(); destroyHandles(); - m_current_lod_max_dim = 0; - m_new_lod_max_dim = 0; + m_current_lod = -1; + m_new_lod = -1; m_handle_lock.clear(); @@ -115,25 +115,24 @@ long KRTexture::getReferencedMemSize() return 0; } -void KRTexture::resize(int max_dim) +void KRTexture::resize(int lod) { while (m_handle_lock.test_and_set()) { }; // Spin lock if (!m_haveNewHandles) { - if (max_dim > 0) { - int target_dim = max_dim; - if (target_dim < (int)m_min_lod_max_dim) target_dim = m_min_lod_max_dim; + if (lod != -1) { + int target_lod = KRMIN(lod, m_lod_count); - if (m_new_lod_max_dim != target_dim || m_handles.empty()) { + if (m_new_lod != target_lod || m_handles.empty()) { assert(m_newTextureMemUsed == 0); - m_newTextureMemUsed = getMemRequiredForSize(target_dim); + m_newTextureMemUsed = getMemRequiredForLod(target_lod); getContext().getTextureManager()->memoryChanged(m_newTextureMemUsed); getContext().getTextureManager()->addMemoryTransferredThisFrame(m_newTextureMemUsed); - if (createGPUTexture(target_dim)) { - m_new_lod_max_dim = target_dim; + if (createGPUTexture(target_lod)) { + m_new_lod = target_lod; } else { getContext().getTextureManager()->memoryChanged(-m_newTextureMemUsed); m_newTextureMemUsed = 0; @@ -168,14 +167,12 @@ void KRTexture::requestResidency(float lodCoverage, KRTexture::texture_usage_t t kraken_stream_level KRTexture::getStreamLevel() { - if (m_current_lod_max_dim == 0) { + if (m_current_lod == -1) { return kraken_stream_level::STREAM_LEVEL_OUT; - } else if (m_current_lod_max_dim == KRMIN(getContext().KRENGINE_MAX_TEXTURE_DIM, (int)m_max_lod_max_dim)) { + } else if (m_current_lod <= getContext().KRENGINE_TEXTURE_HQ_LOD) { return kraken_stream_level::STREAM_LEVEL_IN_HQ; - } else if (m_current_lod_max_dim >= KRMAX(getContext().KRENGINE_MIN_TEXTURE_DIM, (int)m_min_lod_max_dim)) { - return kraken_stream_level::STREAM_LEVEL_IN_LQ; } else { - return kraken_stream_level::STREAM_LEVEL_OUT; + return kraken_stream_level::STREAM_LEVEL_IN_LQ; } } @@ -225,29 +222,34 @@ KRTexture* KRTexture::compress(bool premultiply_alpha) return NULL; } -int KRTexture::getCurrentLodMaxDim() +int KRTexture::getLodCount() const { - return m_current_lod_max_dim; + return m_lod_count; } -int KRTexture::getNewLodMaxDim() +int KRTexture::getCurrentLodMaxDim() { - return m_new_lod_max_dim; + if (m_current_lod == -1) { + return 0; + } else { + return getMaxMipMap() >> m_current_lod; + } +} + +int KRTexture::getNewLod() +{ + return m_new_lod; } int KRTexture::getMaxMipMap() { - return m_max_lod_max_dim; -} - -int KRTexture::getMinMipMap() -{ - return m_min_lod_max_dim; + hydra::Vector3i size = getDimensions(); + return std::max(size.x, std::max(size.y, size.z)); } bool KRTexture::hasMipmaps() { - return m_max_lod_max_dim != m_min_lod_max_dim; + return m_lod_count > 0; } void KRTexture::_swapHandles() @@ -259,7 +261,7 @@ void KRTexture::_swapHandles() m_handles.swap(m_newHandles); m_textureMemUsed = (long)m_newTextureMemUsed; m_newTextureMemUsed = 0; - m_current_lod_max_dim = m_new_lod_max_dim; + m_current_lod = m_new_lod; m_haveNewHandles = false; } m_handle_lock.clear(); diff --git a/kraken/resources/texture/KRTexture.h b/kraken/resources/texture/KRTexture.h index af682cd..f67dcab 100755 --- a/kraken/resources/texture/KRTexture.h +++ b/kraken/resources/texture/KRTexture.h @@ -52,8 +52,8 @@ public: long getMemSize(); virtual long getReferencedMemSize(); - virtual long getMemRequiredForSize(int max_dim) = 0; - virtual void resize(int max_dim); + virtual long getMemRequiredForLod(int lod) = 0; + virtual void resize(int lod); long getLastFrameUsed(); @@ -83,13 +83,13 @@ public: virtual KRTexture* compress(bool premultiply_alpha = false); int getCurrentLodMaxDim(); - int getNewLodMaxDim(); // For use by streamer only + int getNewLod(); // For use by streamer only int getMaxMipMap(); - int getMinMipMap(); bool hasMipmaps(); virtual int getFaceCount() const = 0; virtual VkFormat getFormat() const = 0; virtual hydra::Vector3i getDimensions() const = 0; + int getLodCount() const; kraken_stream_level getStreamLevel(); float getLastFrameLodCoverage() const; @@ -100,7 +100,7 @@ public: VkImage getImage(KrDeviceHandle device); protected: - virtual bool createGPUTexture(int lod_max_dim) = 0; + virtual bool createGPUTexture(int lod) = 0; void destroyHandles(); void destroyNewHandles(); @@ -120,11 +120,10 @@ protected: std::atomic_flag m_handle_lock; - int m_current_lod_max_dim; - int m_new_lod_max_dim; + int m_current_lod; + int m_new_lod; - uint32_t m_max_lod_max_dim; - uint32_t m_min_lod_max_dim; + int m_lod_count; long m_last_frame_used; float m_last_frame_max_lod_coverage; diff --git a/kraken/resources/texture/KRTexture2D.cpp b/kraken/resources/texture/KRTexture2D.cpp index 486ff82..5602022 100755 --- a/kraken/resources/texture/KRTexture2D.cpp +++ b/kraken/resources/texture/KRTexture2D.cpp @@ -46,24 +46,24 @@ KRTexture2D::~KRTexture2D() delete m_pData; } -bool KRTexture2D::createGPUTexture(int lod_max_dim) +bool KRTexture2D::createGPUTexture(int lod) { if (m_haveNewHandles) { return true; } Vector3i dimensions = getDimensions(); - size_t bufferSize = getMemRequiredForSize(lod_max_dim); + size_t bufferSize = getMemRequiredForLod(lod); void* buffer = malloc(bufferSize); - if (!getLodData(buffer, lod_max_dim)) { + if (!getLodData(buffer, lod)) { delete buffer; return false; } bool success = true; - int prev_lod_max_dim = m_new_lod_max_dim; - m_new_lod_max_dim = 0; + int prev_lod = m_new_lod; + m_new_lod = -1; KRDeviceManager* deviceManager = getContext().getDeviceManager(); @@ -107,7 +107,7 @@ bool KRTexture2D::createGPUTexture(int lod_max_dim) delete buffer; if (success) { - m_new_lod_max_dim = prev_lod_max_dim; + m_new_lod = prev_lod; m_haveNewHandles = true; } else { destroyNewHandles(); diff --git a/kraken/resources/texture/KRTexture2D.h b/kraken/resources/texture/KRTexture2D.h index e05cdd8..cd77184 100755 --- a/kraken/resources/texture/KRTexture2D.h +++ b/kraken/resources/texture/KRTexture2D.h @@ -48,10 +48,10 @@ public: virtual bool save(const std::string& path) override; virtual bool save(mimir::Block& data) override; - virtual bool getLodData(void* buffer, int lod_max_dim) = 0; + virtual bool getLodData(void* buffer, int lod) = 0; protected: mimir::Block* m_pData; - bool createGPUTexture(int lod_max_dim) override; + bool createGPUTexture(int lod) override; }; diff --git a/kraken/resources/texture/KRTextureAnimated.cpp b/kraken/resources/texture/KRTextureAnimated.cpp index 12244ee..b6125b9 100755 --- a/kraken/resources/texture/KRTextureAnimated.cpp +++ b/kraken/resources/texture/KRTextureAnimated.cpp @@ -51,8 +51,7 @@ KRTextureAnimated::KRTextureAnimated(KRContext& context, std::string name) : KRT m_frame_count = atoi(name.substr(first_comma_pos + 1, second_comma_pos - first_comma_pos - 1).c_str()); m_frame_rate = (float)atof(name.substr(second_comma_pos + 1).c_str()); - m_max_lod_max_dim = 2048; - m_min_lod_max_dim = 64; + m_lod_count = 0; m_dimensions = Vector2i::Create(0, 0); for (int i = 0; i < m_frame_count; i++) { @@ -60,8 +59,7 @@ KRTextureAnimated::KRTextureAnimated(KRContext& context, std::string name) : KRT if (frame_texture) { m_dimensions.x = std::max(m_dimensions.x, frame_texture->getDimensions().x); m_dimensions.y = std::max(m_dimensions.y, frame_texture->getDimensions().y); - if (frame_texture->getMaxMipMap() < (int)m_max_lod_max_dim) m_max_lod_max_dim = frame_texture->getMaxMipMap(); - if (frame_texture->getMinMipMap() > (int)m_min_lod_max_dim) m_min_lod_max_dim = frame_texture->getMinMipMap(); + m_lod_count = std::max(m_lod_count, frame_texture->getLodCount()); } } } @@ -83,12 +81,12 @@ KRTextureAnimated::~KRTextureAnimated() } -bool KRTextureAnimated::createGPUTexture(int lod_max_dim) +bool KRTextureAnimated::createGPUTexture(int lod) { return true; } -long KRTextureAnimated::getMemRequiredForSize(int max_dim) +long KRTextureAnimated::getMemRequiredForLod(int lod) { return 0; // Memory is allocated by individual frame textures } @@ -151,7 +149,7 @@ bool KRTextureAnimated::save(Block& data) return true; // Animated textures are just references; there are no files to output } -void KRTextureAnimated::resize(int max_dim) +void KRTextureAnimated::resize(int lod) { // Purposely not calling the superclass method } diff --git a/kraken/resources/texture/KRTextureAnimated.h b/kraken/resources/texture/KRTextureAnimated.h index fcaebcb..3f75f7b 100755 --- a/kraken/resources/texture/KRTextureAnimated.h +++ b/kraken/resources/texture/KRTextureAnimated.h @@ -46,19 +46,19 @@ public: virtual bool save(const std::string& path) override; virtual bool save(Block& data) override; - virtual long getMemRequiredForSize(int max_dim) override; + virtual long getMemRequiredForLod(int lod) override; virtual void requestResidency(float lodCoverage, texture_usage_t textureUsage) override; virtual long getReferencedMemSize() override; virtual bool isAnimated() override; - virtual void resize(int max_dim) override; + virtual void resize(int lod) override; virtual int getFaceCount() const override; virtual VkFormat getFormat() const override; virtual hydra::Vector3i getDimensions() const override; private: - bool createGPUTexture(int lod_max_dim) override; + bool createGPUTexture(int lod) override; float m_frame_rate; int m_frame_count; diff --git a/kraken/resources/texture/KRTextureCube.cpp b/kraken/resources/texture/KRTextureCube.cpp index 0a6065e..666ff40 100755 --- a/kraken/resources/texture/KRTextureCube.cpp +++ b/kraken/resources/texture/KRTextureCube.cpp @@ -38,16 +38,14 @@ using namespace hydra; KRTextureCube::KRTextureCube(KRContext& context, std::string name) : KRTexture(context, name) { - m_max_lod_max_dim = 2048; - m_min_lod_max_dim = 64; + m_lod_count = 0; for (int i = 0; i < 6; i++) { m_textures[i] = NULL; std::string faceName = getName() + SUFFIXES[i]; m_textures[i] = (KRTexture2D*)getContext().getTextureManager()->getTexture(faceName); if (m_textures[i]) { - if (m_textures[i]->getMaxMipMap() < (int)m_max_lod_max_dim) m_max_lod_max_dim = m_textures[i]->getMaxMipMap(); - if (m_textures[i]->getMinMipMap() > (int)m_min_lod_max_dim) m_min_lod_max_dim = m_textures[i]->getMinMipMap(); + m_lod_count = std::max(m_lod_count, m_textures[i]->getLodCount()); } else { assert(false); } @@ -57,14 +55,14 @@ KRTextureCube::KRTextureCube(KRContext& context, std::string name) : KRTexture(c KRTextureCube::~KRTextureCube() {} -bool KRTextureCube::createGPUTexture(int lod_max_dim) +bool KRTextureCube::createGPUTexture(int lod) { assert(!m_haveNewHandles); // Only allow one resize per frame bool success = true; - int prev_lod_max_dim = m_new_lod_max_dim; - m_new_lod_max_dim = 0; + int prev_lod = m_new_lod; + m_new_lod = -1; bool bMipMaps = false; Vector2i dimensions = Vector2i::Zero(); @@ -95,9 +93,9 @@ bool KRTextureCube::createGPUTexture(int lod_max_dim) size_t bufferSizes[6] = {}; void* buffers[6] = {}; for (int i = 0; i < 6; i++) { - bufferSizes[i] = getMemRequiredForSize(lod_max_dim); + bufferSizes[i] = getMemRequiredForLod(lod); buffers[i] = malloc(bufferSizes[i]); - m_textures[i]->getLodData(buffers[i], lod_max_dim); + m_textures[i]->getLodData(buffers[i], lod); } KRDeviceManager* deviceManager = getContext().getDeviceManager(); @@ -132,7 +130,7 @@ bool KRTextureCube::createGPUTexture(int lod_max_dim) m_haveNewHandles = true; } else { destroyHandles(); - m_new_lod_max_dim = prev_lod_max_dim; + m_new_lod = prev_lod; } for (int i = 0; i < 6; i++) { @@ -144,15 +142,12 @@ bool KRTextureCube::createGPUTexture(int lod_max_dim) return success; } -long KRTextureCube::getMemRequiredForSize(int max_dim) +long KRTextureCube::getMemRequiredForLod(int lod) { - int target_dim = max_dim; - if (target_dim < (int)m_min_lod_max_dim) target_dim = m_min_lod_max_dim; - long memoryRequired = 0; for (int i = 0; i < 6; i++) { if (m_textures[i]) { - memoryRequired += m_textures[i]->getMemRequiredForSize(target_dim); + memoryRequired += m_textures[i]->getMemRequiredForLod(lod); } } return memoryRequired; diff --git a/kraken/resources/texture/KRTextureCube.h b/kraken/resources/texture/KRTextureCube.h index c4e5137..445916f 100755 --- a/kraken/resources/texture/KRTextureCube.h +++ b/kraken/resources/texture/KRTextureCube.h @@ -44,14 +44,14 @@ public: virtual bool save(const std::string& path) override; virtual bool save(mimir::Block& data) override; - virtual long getMemRequiredForSize(int max_dim) override; + virtual long getMemRequiredForLod(int lod) override; virtual void requestResidency(float lodCoverage, texture_usage_t textureUsage) override; virtual int getFaceCount() const override; virtual VkFormat getFormat() const override; virtual hydra::Vector3i getDimensions() const override; private: - bool createGPUTexture(int lod_max_dim) override; + bool createGPUTexture(int lod) override; const char* SUFFIXES[6] = { "_positive_x", diff --git a/kraken/resources/texture/KRTextureKTX.cpp b/kraken/resources/texture/KRTextureKTX.cpp index 57b0879..ba96f9c 100755 --- a/kraken/resources/texture/KRTextureKTX.cpp +++ b/kraken/resources/texture/KRTextureKTX.cpp @@ -82,8 +82,7 @@ KRTextureKTX::KRTextureKTX(KRContext& context, Block* data, std::string name) : } } - m_max_lod_max_dim = KRMAX(m_header.pixelWidth, m_header.pixelHeight); - m_min_lod_max_dim = KRMAX(width, height); + m_lod_count = (int)KRMAX(m_header.numberOfMipmapLevels, 1) - 1; } KRTextureKTX::KRTextureKTX(KRContext& context, std::string name, unsigned int internal_format, unsigned int base_internal_format, int width, int height, const std::list& blocks) : KRTexture2D(context, new Block(), name) @@ -361,59 +360,43 @@ VkFormat KRTextureKTX::getFormat() const } } -long KRTextureKTX::getMemRequiredForSize(int max_dim) +long KRTextureKTX::getMemRequiredForLod(int lod) { - int target_dim = max_dim; - if (target_dim < (int)m_min_lod_max_dim) target_dim = target_dim; - // Determine how much memory will be consumed - int width = m_header.pixelWidth; - int height = m_header.pixelHeight; long memoryRequired = 0; + int level = 0; for (std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { Block* block = *itr; - if (width <= target_dim && height <= target_dim) { + if (level >= lod) { memoryRequired += (long)block->getSize(); } - width = width >> 1; - if (width < 1) { - width = 1; - } - height = height >> 1; - if (height < 1) { - height = 1; - } + level++; } return memoryRequired; } -bool KRTextureKTX::getLodData(void* buffer, int lod_max_dim) +bool KRTextureKTX::getLodData(void* buffer, int lod) { unsigned char* converted_image = (unsigned char*)buffer; - int target_dim = lod_max_dim; - if (target_dim < (int)m_min_lod_max_dim) target_dim = m_min_lod_max_dim; + int target_lod = KRMIN(lod, m_lod_count); if (m_blocks.size() == 0) { return false; } // Determine how much memory will be consumed - int width = m_header.pixelWidth; - int height = m_header.pixelHeight; long memoryRequired = 0; long memoryTransferred = 0; - // Upload texture data - int destination_level = 0; - int source_level = 0; + int level = 0; for (std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { Block* block = *itr; - if (width <= target_dim && height <= target_dim) { + if (level >= target_lod) { /* if (width > current_lod_max_dim) { @@ -440,22 +423,9 @@ bool KRTextureKTX::getLodData(void* buffer, int lod_max_dim) // return false; // } // - - destination_level++; } - if (width <= m_current_lod_max_dim && height <= m_current_lod_max_dim) { - source_level++; - } - - width = width >> 1; - if (width < 1) { - width = 1; - } - height = height >> 1; - if (height < 1) { - height = 1; - } + level++; } return true; diff --git a/kraken/resources/texture/KRTextureKTX.h b/kraken/resources/texture/KRTextureKTX.h index 386be74..aa17682 100755 --- a/kraken/resources/texture/KRTextureKTX.h +++ b/kraken/resources/texture/KRTextureKTX.h @@ -43,9 +43,9 @@ public: virtual ~KRTextureKTX(); virtual std::string getExtension() override; - bool getLodData(void* buffer, int lod_max_dim) override; + bool getLodData(void* buffer, int lod) override; - virtual long getMemRequiredForSize(int max_dim) override; + virtual long getMemRequiredForLod(int lod) override; virtual hydra::Vector3i getDimensions() const override; virtual int getFaceCount() const override; virtual VkFormat getFormat() const override; diff --git a/kraken/resources/texture/KRTextureKTX2.cpp b/kraken/resources/texture/KRTextureKTX2.cpp index 60dc71f..4cfddb5 100644 --- a/kraken/resources/texture/KRTextureKTX2.cpp +++ b/kraken/resources/texture/KRTextureKTX2.cpp @@ -68,8 +68,7 @@ KRTextureKTX2::KRTextureKTX2(KRContext& context, Block* data, std::string name) if (height < 1) { height = 1; } - m_max_lod_max_dim = KRMAX(m_header.pixelWidth, m_header.pixelHeight); - m_min_lod_max_dim = KRMAX(width, height); + m_lod_count = (int)KRMAX(m_header.levelCount, 1) - 1; } KRTextureKTX2::~KRTextureKTX2() @@ -81,59 +80,42 @@ Vector3i KRTextureKTX2::getDimensions() const return Vector3i::Create(Vector3i::Create(m_header.pixelWidth, m_header.pixelHeight, m_header.pixelDepth)); } -long KRTextureKTX2::getMemRequiredForSize(int max_dim) +long KRTextureKTX2::getMemRequiredForLod(int lod) { - int target_dim = max_dim; - if (target_dim < (int)m_min_lod_max_dim) target_dim = target_dim; + int target_lod = KRMIN(lod, m_lod_count); // Determine how much memory will be consumed - - int width = m_header.pixelWidth; - int height = m_header.pixelHeight; long memoryRequired = 0; + int level = 0; for (__uint32_t level = 0; level < m_header.levelCount; level++) { KTX2LevelIndex levelIndex; m_pData->copy(&levelIndex, sizeof(m_header) + sizeof(KTX2LevelIndex) * level, sizeof(KTX2LevelIndex)); - if (width <= target_dim && height <= target_dim) { + if (level >= target_lod) { memoryRequired += (long)levelIndex.byteLength; } - - width = width >> 1; - if (width < 1) { - width = 1; - } - height = height >> 1; - if (height < 1) { - height = 1; - } + level++; } return memoryRequired; } -bool KRTextureKTX2::getLodData(void* buffer, int lod_max_dim) +bool KRTextureKTX2::getLodData(void* buffer, int lod) { unsigned char* converted_image = (unsigned char*)buffer; - int target_dim = lod_max_dim; - if (target_dim < (int)m_min_lod_max_dim) target_dim = m_min_lod_max_dim; + int target_lod = KRMIN(lod, m_lod_count); // Determine how much memory will be consumed - int width = m_header.pixelWidth; - int height = m_header.pixelHeight; long memoryRequired = 0; long memoryTransferred = 0; - - // Upload texture data - int destination_level = 0; - int source_level = 0; + int level = 0; for (__uint32_t level = 0; level < m_header.levelCount; level++) { KTX2LevelIndex levelIndex; m_pData->copy(&levelIndex, sizeof(m_header) + sizeof(KTX2LevelIndex) * level, sizeof(KTX2LevelIndex)); - if (width <= target_dim && height <= target_dim) { + if (level >= target_lod) { /* * TODO - Vulkan Refactoring @@ -150,21 +132,9 @@ bool KRTextureKTX2::getLodData(void* buffer, int lod_max_dim) // } // - destination_level++; } - if (width <= m_current_lod_max_dim && height <= m_current_lod_max_dim) { - source_level++; - } - - width = width >> 1; - if (width < 1) { - width = 1; - } - height = height >> 1; - if (height < 1) { - height = 1; - } + level++; } return true; diff --git a/kraken/resources/texture/KRTextureKTX2.h b/kraken/resources/texture/KRTextureKTX2.h index 1d2373e..7fbb9f2 100644 --- a/kraken/resources/texture/KRTextureKTX2.h +++ b/kraken/resources/texture/KRTextureKTX2.h @@ -40,9 +40,9 @@ public: virtual ~KRTextureKTX2(); virtual std::string getExtension() override; - bool getLodData(void* buffer, int lod_max_dim) override; + bool getLodData(void* buffer, int lod) override; - virtual long getMemRequiredForSize(int max_dim) override; + virtual long getMemRequiredForLod(int lod) override; virtual hydra::Vector3i getDimensions() const override; virtual int getFaceCount() const override; virtual VkFormat getFormat() const override; diff --git a/kraken/resources/texture/KRTextureManager.cpp b/kraken/resources/texture/KRTextureManager.cpp index 9be9bc6..b142341 100755 --- a/kraken/resources/texture/KRTextureManager.cpp +++ b/kraken/resources/texture/KRTextureManager.cpp @@ -302,13 +302,13 @@ void KRTextureManager::balanceTextureMemory(long& memoryRemaining, long& memoryR for (auto itr = m_activeTextures_streamer.begin(); itr != m_activeTextures_streamer.end(); itr++) { KRTexture* texture = (*itr).second; - int min_mip_level = KRMAX(getContext().KRENGINE_MIN_TEXTURE_DIM, texture->getMinMipMap()); - long minLodMem = texture->getMemRequiredForSize(min_mip_level); + int min_lod_level = KRMIN(getContext().KRENGINE_TEXTURE_LQ_LOD, texture->getLodCount()); + long minLodMem = texture->getMemRequiredForLod(min_lod_level); memoryRemaining -= minLodMem; - if (memoryRemainingThisFrame > minLodMem && texture->getNewLodMaxDim() < min_mip_level) { + if (memoryRemainingThisFrame > minLodMem && (texture->getNewLod() != -1 || texture->getNewLod() > min_lod_level)) { memoryRemainingThisFrame -= minLodMem; - texture->resize(min_mip_level); + texture->resize(min_lod_level); } } @@ -331,24 +331,29 @@ void KRTextureManager::balanceTextureMemory(long& memoryRemaining, long& memoryR } KRTexture* texture = (*itr).second; - int min_mip_level = KRMAX(getContext().KRENGINE_MIN_TEXTURE_DIM, texture->getMinMipMap()); - int max_mip_level = KRMIN(getContext().KRENGINE_MAX_TEXTURE_DIM, texture->getMaxMipMap()); - int target_mip_level = (max_mip_level >> mip_drop); - long targetMem = texture->getMemRequiredForSize(target_mip_level); - long additionalMemRequired = targetMem - texture->getMemRequiredForSize(min_mip_level); + int min_lod_level = KRMIN(getContext().KRENGINE_TEXTURE_LQ_LOD, texture->getLodCount()); + int target_lod_level = KRMIN(getContext().KRENGINE_TEXTURE_HQ_LOD + mip_drop, texture->getLodCount()); + long targetMem = texture->getMemRequiredForLod(target_lod_level); + long additionalMemRequired = targetMem - texture->getMemRequiredForLod(min_lod_level); memoryRemainingThisMip -= additionalMemRequired; memoryRemaining -= additionalMemRequired; if (memoryRemainingThisMip > 0 && memoryRemainingThisFrame > targetMem) { - int current_mip_level = texture->getNewLodMaxDim(); - if (current_mip_level == (target_mip_level >> 1) || target_mip_level < current_mip_level) { + int current_lod_level = texture->getNewLod(); + if (current_lod_level == (target_lod_level + 1) || target_lod_level > current_lod_level) { + // We are are just one lod level away from the target, or we are reducing the quality. + // Advance directly to the target 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); + texture->resize(target_lod_level); + } else if (current_lod_level == (target_lod_level + 2)) { + // We are two lod levels away from the target. + // Advance to the lod level inbetween. + memoryRemainingThisFrame -= texture->getMemRequiredForLod(target_lod_level + 1); + texture->resize(target_lod_level + 1); + } else if (current_lod_level > (target_lod_level + 2)) { + // We are more than two lod levels away from the target. + // Advance directly to the lod 2 levels away from the target. + memoryRemainingThisFrame -= texture->getMemRequiredForLod(target_lod_level + 2); + texture->resize(target_lod_level + 2); } } diff --git a/kraken/resources/texture/KRTexturePNG.cpp b/kraken/resources/texture/KRTexturePNG.cpp index 79ac47d..156198c 100644 --- a/kraken/resources/texture/KRTexturePNG.cpp +++ b/kraken/resources/texture/KRTexturePNG.cpp @@ -77,8 +77,7 @@ KRTexturePNG::KRTexturePNG(KRContext& context, Block* data, std::string name) : m_dimensions.x = SWAP_4(pHeader->chunk_IHDR.width); m_dimensions.y = SWAP_4(pHeader->chunk_IHDR.height); - m_max_lod_max_dim = m_dimensions.x > m_dimensions.y ? m_dimensions.x : m_dimensions.y; - m_min_lod_max_dim = m_max_lod_max_dim; // Mipmaps not yet supported for PNG images + m_lod_count = 0; // Mipmaps not yet supported for PNG images switch (pHeader->chunk_IHDR.colorType) { case 0: // greyscale @@ -113,9 +112,9 @@ KRTexturePNG::~KRTexturePNG() } -bool KRTexturePNG::getLodData(void* buffer, int lod_max_dim) +bool KRTexturePNG::getLodData(void* buffer, int lod) { - unsigned char* converted_image = (unsigned char*)buffer; + unsigned char* converted_image = (unsigned char*)buffer; // TODO - Vulkan Refactoring - Perhaps it would be more efficient to reformat the color channels during the copy to the staging buffer. m_pData->lock(); PNG_HEADER* pHeader = (PNG_HEADER*)m_pData->getStart(); @@ -158,7 +157,7 @@ KRTexture* KRTexturePNG::compress(bool premultiply_alpha) } #endif -long KRTexturePNG::getMemRequiredForSize(int max_dim) +long KRTexturePNG::getMemRequiredForLod(int lod) { return m_imageSize; } diff --git a/kraken/resources/texture/KRTexturePNG.h b/kraken/resources/texture/KRTexturePNG.h index c644033..9d3a6ce 100644 --- a/kraken/resources/texture/KRTexturePNG.h +++ b/kraken/resources/texture/KRTexturePNG.h @@ -42,13 +42,13 @@ public: virtual ~KRTexturePNG(); virtual std::string getExtension() override; - bool getLodData(void* buffer, int lod_max_dim) override; + bool getLodData(void* buffer, int lod) override; #if !TARGET_OS_IPHONE && !defined(ANDROID) virtual KRTexture* compress(bool premultiply_alpha = false) override; #endif - virtual long getMemRequiredForSize(int max_dim) override; + virtual long getMemRequiredForLod(int lod) override; virtual hydra::Vector3i getDimensions() const override; virtual VkFormat getFormat() const override; virtual int getFaceCount() const override; diff --git a/kraken/resources/texture/KRTexturePVR.cpp b/kraken/resources/texture/KRTexturePVR.cpp index be27511..6bca62b 100755 --- a/kraken/resources/texture/KRTexturePVR.cpp +++ b/kraken/resources/texture/KRTexturePVR.cpp @@ -172,39 +172,27 @@ VkFormat KRTexturePVR::getFormat() const } } -long KRTexturePVR::getMemRequiredForSize(int max_dim) +long KRTexturePVR::getMemRequiredForLod(int lod) { - int target_dim = max_dim; - if (target_dim < (int)m_min_lod_max_dim) target_dim = target_dim; - // Determine how much memory will be consumed - int width = m_iWidth; - int height = m_iHeight; long memoryRequired = 0; + int level = 0; for (std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { Block* block = *itr; - if (width <= target_dim && height <= target_dim) { + if (level >= lod) { memoryRequired += (long)block->getSize(); } - width = width >> 1; - if (width < 1) { - width = 1; - } - height = height >> 1; - if (height < 1) { - height = 1; - } + level++; } return memoryRequired; } -bool KRTexturePVR::getLodData(void* buffer, int lod_max_dim) +bool KRTexturePVR::getLodData(void* buffer, int lod) { - int target_dim = lod_max_dim; - if (target_dim < (int)m_min_lod_max_dim) target_dim = m_min_lod_max_dim; + int target_lod = KRMIN(lod, m_lod_count); if (m_blocks.size() == 0) { return false; @@ -217,19 +205,10 @@ bool KRTexturePVR::getLodData(void* buffer, int lod_max_dim) long memoryTransferred = 0; // Upload texture data - int destination_level = 0; - int source_level = 0; + int level = 0; for (std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { Block* block = *itr; - if (width <= target_dim && height <= target_dim) { - /* - if (width > current_lod_max_dim) { - current_lod_max_dim = width; - } - if (height > current_lod_max_dim) { - current_lod_max_dim = height; - } - */ + if (level >= target_lod) { block->lock(); /* @@ -245,23 +224,10 @@ bool KRTexturePVR::getLodData(void* buffer, int lod_max_dim) // assert(false); // return false; // } - // - - destination_level++; + // } - if (width <= m_current_lod_max_dim && height <= m_current_lod_max_dim) { - source_level++; - } - - width = width >> 1; - if (width < 1) { - width = 1; - } - height = height >> 1; - if (height < 1) { - height = 1; - } + level++; } return true; diff --git a/kraken/resources/texture/KRTexturePVR.h b/kraken/resources/texture/KRTexturePVR.h index 94531fe..1e4471d 100755 --- a/kraken/resources/texture/KRTexturePVR.h +++ b/kraken/resources/texture/KRTexturePVR.h @@ -40,9 +40,9 @@ public: virtual ~KRTexturePVR(); virtual std::string getExtension() override; - bool getLodData(void* buffer, int lod_max_dim) override; + bool getLodData(void* buffer, int lod) override; - virtual long getMemRequiredForSize(int max_dim) override; + virtual long getMemRequiredForLod(int lod) override; virtual hydra::Vector3i getDimensions() const override; virtual VkFormat getFormat() const override; virtual int getFaceCount() const override; diff --git a/kraken/resources/texture/KRTextureTGA.cpp b/kraken/resources/texture/KRTextureTGA.cpp index 5184803..b35e3e4 100755 --- a/kraken/resources/texture/KRTextureTGA.cpp +++ b/kraken/resources/texture/KRTextureTGA.cpp @@ -79,8 +79,7 @@ KRTextureTGA::KRTextureTGA(KRContext& context, Block* data, std::string name) : m_dimensions.x = pHeader->width; m_dimensions.y = pHeader->height; - m_max_lod_max_dim = pHeader->width > pHeader->height ? pHeader->width : pHeader->height; - m_min_lod_max_dim = m_max_lod_max_dim; // Mipmaps not yet supported for TGA images + m_lod_count = 0; // Mipmaps not yet supported for TGA images switch (pHeader->imagetype) { case 2: // rgb case 10: // rgb + rle @@ -118,7 +117,7 @@ KRTextureTGA::~KRTextureTGA() } -bool KRTextureTGA::getLodData(void* buffer, int lod_max_dim) +bool KRTextureTGA::getLodData(void* buffer, int lod) { unsigned char* converted_image = (unsigned char*)buffer; @@ -338,7 +337,7 @@ KRTexture* KRTextureTGA::compress(bool premultiply_alpha) } #endif -long KRTextureTGA::getMemRequiredForSize(int max_dim) +long KRTextureTGA::getMemRequiredForLod(int lod) { return m_imageSize; } diff --git a/kraken/resources/texture/KRTextureTGA.h b/kraken/resources/texture/KRTextureTGA.h index ed0edcc..fc1412e 100755 --- a/kraken/resources/texture/KRTextureTGA.h +++ b/kraken/resources/texture/KRTextureTGA.h @@ -42,13 +42,13 @@ public: virtual ~KRTextureTGA(); virtual std::string getExtension() override; - bool getLodData(void* buffer, int lod_max_dim) override; + bool getLodData(void* buffer, int lod) override; #if !TARGET_OS_IPHONE && !defined(ANDROID) virtual KRTexture* compress(bool premultiply_alpha = false) override; #endif - virtual long getMemRequiredForSize(int max_dim) override; + virtual long getMemRequiredForLod(int lod) override; virtual hydra::Vector3i getDimensions() const override; virtual VkFormat getFormat() const override; virtual int getFaceCount() const override;