From b205fe2e0d44996502db248ad209d87ecf3d98de Mon Sep 17 00:00:00 2001 From: Kearwood Gilbert Date: Thu, 19 Mar 2026 00:54:36 -0700 Subject: [PATCH] KRTexture::getMemRequiredForLod and KRTexture::getLodData now interpret the passed lod level as a single mip rather than the mip chain starting at the passed lod level. Added KRTexture::getMemRequiredForLodRange --- kraken/resources/texture/KRTexture.cpp | 19 +++++- kraken/resources/texture/KRTexture.h | 1 + kraken/resources/texture/KRTexture2D.cpp | 45 ++++++++----- kraken/resources/texture/KRTextureCube.cpp | 3 +- kraken/resources/texture/KRTextureKTX.cpp | 66 ++----------------- kraken/resources/texture/KRTextureKTX.h | 2 +- kraken/resources/texture/KRTextureKTX2.cpp | 57 +++------------- kraken/resources/texture/KRTextureManager.cpp | 10 +-- kraken/resources/texture/KRTexturePNG.cpp | 2 +- kraken/resources/texture/KRTexturePVR.cpp | 55 ++-------------- kraken/resources/texture/KRTexturePVR.h | 2 +- kraken/resources/texture/KRTextureTGA.cpp | 2 +- 12 files changed, 77 insertions(+), 187 deletions(-) diff --git a/kraken/resources/texture/KRTexture.cpp b/kraken/resources/texture/KRTexture.cpp index 77282ed..994f10a 100755 --- a/kraken/resources/texture/KRTexture.cpp +++ b/kraken/resources/texture/KRTexture.cpp @@ -126,7 +126,7 @@ void KRTexture::resize(int lod) if (m_new_lod != target_lod || m_handles.empty()) { assert(m_newTextureMemUsed == 0); - m_newTextureMemUsed = getMemRequiredForLod(target_lod); + m_newTextureMemUsed = getMemRequiredForLodRange(target_lod); getContext().getTextureManager()->memoryChanged(m_newTextureMemUsed); getContext().getTextureManager()->addMemoryTransferredThisFrame(m_newTextureMemUsed); @@ -294,6 +294,8 @@ bool KRTexture::allocate(KRDevice& device, int target_lod, VkImageCreateFlags im #endif ) { + int min_mip = KRMIN(target_lod, m_lod_count - 1); + int mip_count = m_lod_count - min_mip; hydra::Vector3i dimensions = getDimensions() / (1 << target_lod); VkImageCreateInfo imageInfo{}; @@ -302,7 +304,7 @@ bool KRTexture::allocate(KRDevice& device, int target_lod, VkImageCreateFlags im imageInfo.extent.width = static_cast(dimensions.x); imageInfo.extent.height = static_cast(dimensions.y); imageInfo.extent.depth = static_cast(dimensions.z); - imageInfo.mipLevels = KRMAX(m_lod_count - target_lod, 1); + imageInfo.mipLevels = mip_count; imageInfo.arrayLayers = 1; imageInfo.format = getFormat(); imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; @@ -330,3 +332,16 @@ bool KRTexture::allocate(KRDevice& device, int target_lod, VkImageCreateFlags im #endif return true; } + +long KRTexture::getMemRequiredForLodRange(int min_lod, int max_lod /* = 0xff */) +{ + int target_max_lod = KRMIN(max_lod, m_lod_count - 1); + int target_min_lod = KRMIN(min_lod, m_lod_count - 1); + + long memRequired = 0; + for (int lod = target_min_lod; lod <= target_max_lod; lod++) { + memRequired += + (lod); + } + return memRequired; +} diff --git a/kraken/resources/texture/KRTexture.h b/kraken/resources/texture/KRTexture.h index b7fe8e4..9cea722 100755 --- a/kraken/resources/texture/KRTexture.h +++ b/kraken/resources/texture/KRTexture.h @@ -53,6 +53,7 @@ public: virtual long getReferencedMemSize(); virtual long getMemRequiredForLod(int lod) = 0; + long getMemRequiredForLodRange(int min_lod, int max_lod = 0xff); virtual void resize(int lod); long getLastFrameUsed(); diff --git a/kraken/resources/texture/KRTexture2D.cpp b/kraken/resources/texture/KRTexture2D.cpp index 45f1f03..9ab169d 100755 --- a/kraken/resources/texture/KRTexture2D.cpp +++ b/kraken/resources/texture/KRTexture2D.cpp @@ -53,7 +53,7 @@ bool KRTexture2D::createGPUTexture(int lod) } Vector3i dimensions = getDimensions(); - size_t bufferSize = getMemRequiredForLod(lod); + size_t bufferSize = getMemRequiredForLodRange(lod); void* buffer = malloc(bufferSize); if (!getLodData(buffer, lod)) { @@ -85,6 +85,9 @@ bool KRTexture2D::createGPUTexture(int lod) break; } + int min_mip = KRMIN(target_lod, m_lod_count - 1); + int mip_count = m_lod_count - min_mip; + VkImageViewCreateInfo viewInfo{}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; viewInfo.image = texture.image; @@ -92,7 +95,7 @@ bool KRTexture2D::createGPUTexture(int lod) viewInfo.format = getFormat(); viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; viewInfo.subresourceRange.baseMipLevel = 0; - viewInfo.subresourceRange.levelCount = KRMAX(m_lod_count - target_lod, 1); + viewInfo.subresourceRange.levelCount = mip_count; viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.layerCount = 1; VkResult res = vkCreateImageView(device.m_logicalDevice, &viewInfo, nullptr, &texture.fullImageView); @@ -101,24 +104,32 @@ bool KRTexture2D::createGPUTexture(int lod) break; } - VkBufferImageCopy region{}; - region.bufferOffset = 0; - region.bufferRowLength = 0; - region.bufferImageHeight = 0; + std::vector regions; + regions.resize(mip_count, VkBufferImageCopy{}); + int bufferOffset = 0; + for (int mip = min_mip; mip < min_mip + mip_count - 1; mip++) { + VkBufferImageCopy& region = regions[mip]; + region.bufferOffset = bufferOffset; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.mipLevel = 0; - region.imageSubresource.baseArrayLayer = 0; - region.imageSubresource.layerCount = 1; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = mip - min_mip; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; - region.imageOffset = { 0, 0, 0 }; - region.imageExtent = { - (unsigned int)dimensions.x, - (unsigned int)dimensions.y, - (unsigned int)dimensions.z - }; + region.imageOffset = { 0, 0, 0 }; + region.imageExtent = { + (unsigned int)dimensions.x, + (unsigned int)dimensions.y, + (unsigned int)dimensions.z + }; + regions.push_back(region); - device.streamUpload((void*)buffer, bufferSize, texture.image, ®ion, 1); + bufferOffset += getMemRequiredForLod(mip); + } + + device.streamUpload((void*)buffer, bufferSize, texture.image, regions.data(), regions.size()); } delete buffer; diff --git a/kraken/resources/texture/KRTextureCube.cpp b/kraken/resources/texture/KRTextureCube.cpp index c4340d3..2c925ad 100755 --- a/kraken/resources/texture/KRTextureCube.cpp +++ b/kraken/resources/texture/KRTextureCube.cpp @@ -93,7 +93,7 @@ bool KRTextureCube::createGPUTexture(int lod) size_t bufferSizes[6] = {}; void* buffers[6] = {}; for (int i = 0; i < 6; i++) { - bufferSizes[i] = getMemRequiredForLod(lod); + bufferSizes[i] = getMemRequiredForLodRange(lod); buffers[i] = malloc(bufferSizes[i]); m_textures[i]->getLodData(buffers[i], lod); } @@ -170,7 +170,6 @@ long KRTextureCube::getMemRequiredForLod(int lod) return memoryRequired; } - void KRTextureCube::requestResidency(float lodCoverage, texture_usage_t textureUsage) { KRTexture::requestResidency(lodCoverage, textureUsage); diff --git a/kraken/resources/texture/KRTextureKTX.cpp b/kraken/resources/texture/KRTextureKTX.cpp index ba96f9c..ac1929d 100755 --- a/kraken/resources/texture/KRTextureKTX.cpp +++ b/kraken/resources/texture/KRTextureKTX.cpp @@ -82,7 +82,7 @@ KRTextureKTX::KRTextureKTX(KRContext& context, Block* data, std::string name) : } } - m_lod_count = (int)KRMAX(m_header.numberOfMipmapLevels, 1) - 1; + m_lod_count = (int)KRMAX(m_header.numberOfMipmapLevels, 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) @@ -119,7 +119,7 @@ KRTextureKTX::KRTextureKTX(KRContext& context, std::string name, unsigned int in KRTextureKTX::~KRTextureKTX() { - for (std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { + for (std::vector::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { Block* block = *itr; delete block; } @@ -362,74 +362,20 @@ VkFormat KRTextureKTX::getFormat() const long KRTextureKTX::getMemRequiredForLod(int lod) { - // Determine how much memory will be consumed - - long memoryRequired = 0; - - int level = 0; - for (std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { - Block* block = *itr; - if (level >= lod) { - memoryRequired += (long)block->getSize(); - } - - level++; - } - - return memoryRequired; + int target_lod = KRMIN(lod, m_lod_count - 1); + return (long)m_blocks[target_lod]->getSize(); } bool KRTextureKTX::getLodData(void* buffer, int lod) { - unsigned char* converted_image = (unsigned char*)buffer; - int target_lod = KRMIN(lod, m_lod_count); - if (m_blocks.size() == 0) { return false; } - // Determine how much memory will be consumed - long memoryRequired = 0; - long memoryTransferred = 0; - - // Upload texture data - int level = 0; - for (std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { - Block* block = *itr; - if (level >= target_lod) { - - /* - if (width > current_lod_max_dim) { - current_lod_max_dim = width; - } - if (height > current_lod_max_dim) { - current_lod_max_dim = height; - } - */ - - block->lock(); - /* - * TODO - Vulkan Refactoring - GLDEBUG(glCompressedTexImage2D(target, destination_level, (unsigned int)m_header.glInternalFormat, width, height, 0, (int)block->getSize(), block->getStart())); - */ - - block->unlock(); - memoryTransferred += (long)block->getSize(); // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE - memoryRequired += (long)block->getSize(); - // - // err = glGetError(); - // if (err != GL_NO_ERROR) { - // assert(false); - // return false; - // } - // - } - - level++; - } + int target_lod = KRMIN(lod, m_lod_count - 1); + m_blocks[target_lod]->copy(buffer); return true; - } std::string KRTextureKTX::getExtension() diff --git a/kraken/resources/texture/KRTextureKTX.h b/kraken/resources/texture/KRTextureKTX.h index aa17682..0d2890e 100755 --- a/kraken/resources/texture/KRTextureKTX.h +++ b/kraken/resources/texture/KRTextureKTX.h @@ -52,7 +52,7 @@ public: protected: - std::list m_blocks; + std::vector m_blocks; typedef struct _KTXHeader { diff --git a/kraken/resources/texture/KRTextureKTX2.cpp b/kraken/resources/texture/KRTextureKTX2.cpp index 4cfddb5..a4be47f 100644 --- a/kraken/resources/texture/KRTextureKTX2.cpp +++ b/kraken/resources/texture/KRTextureKTX2.cpp @@ -68,7 +68,7 @@ KRTextureKTX2::KRTextureKTX2(KRContext& context, Block* data, std::string name) if (height < 1) { height = 1; } - m_lod_count = (int)KRMAX(m_header.levelCount, 1) - 1; + m_lod_count = (int)KRMAX(m_header.levelCount, 1); } KRTextureKTX2::~KRTextureKTX2() @@ -82,63 +82,26 @@ Vector3i KRTextureKTX2::getDimensions() const long KRTextureKTX2::getMemRequiredForLod(int lod) { - int target_lod = KRMIN(lod, m_lod_count); + int target_lod = KRMIN(lod, m_lod_count - 1); - // Determine how much memory will be consumed - long memoryRequired = 0; + KTX2LevelIndex levelIndex; + m_pData->copy(&levelIndex, sizeof(m_header) + sizeof(KTX2LevelIndex) * target_lod, sizeof(KTX2LevelIndex)); - 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 (level >= target_lod) { - memoryRequired += (long)levelIndex.byteLength; - } - level++; - } - - return memoryRequired; + return (long)levelIndex.byteLength; } bool KRTextureKTX2::getLodData(void* buffer, int lod) { unsigned char* converted_image = (unsigned char*)buffer; - int target_lod = KRMIN(lod, m_lod_count); + int target_lod = KRMIN(lod, m_lod_count - 1); - // Determine how much memory will be consumed - long memoryRequired = 0; - long memoryTransferred = 0; + KTX2LevelIndex levelIndex; + m_pData->copy(&levelIndex, sizeof(m_header) + sizeof(KTX2LevelIndex) * target_lod, sizeof(KTX2LevelIndex)); - 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 (level >= target_lod) { - - /* - * TODO - Vulkan Refactoring - GLDEBUG(glCompressedTexImage2D(target, destination_level, (unsigned int)m_header.glInternalFormat, width, height, 0, (int)block->getSize(), block->getStart())); - */ - - memoryTransferred += (long)levelIndex.byteLength; // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE - memoryRequired += (long)levelIndex.byteLength; - // - // err = glGetError(); - // if (err != GL_NO_ERROR) { - // assert(false); - // return false; - // } - // - - } - - level++; - } + // TODO - Implement copy of buffer data + assert(false); return true; - } std::string KRTextureKTX2::getExtension() diff --git a/kraken/resources/texture/KRTextureManager.cpp b/kraken/resources/texture/KRTextureManager.cpp index b142341..db67086 100755 --- a/kraken/resources/texture/KRTextureManager.cpp +++ b/kraken/resources/texture/KRTextureManager.cpp @@ -303,7 +303,7 @@ 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_lod_level = KRMIN(getContext().KRENGINE_TEXTURE_LQ_LOD, texture->getLodCount()); - long minLodMem = texture->getMemRequiredForLod(min_lod_level); + long minLodMem = texture->getMemRequiredForLodRange(min_lod_level); memoryRemaining -= minLodMem; if (memoryRemainingThisFrame > minLodMem && (texture->getNewLod() != -1 || texture->getNewLod() > min_lod_level)) { @@ -333,8 +333,8 @@ void KRTextureManager::balanceTextureMemory(long& memoryRemaining, long& memoryR KRTexture* texture = (*itr).second; 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); + long targetMem = texture->getMemRequiredForLodRange(target_lod_level); + long additionalMemRequired = targetMem - texture->getMemRequiredForLodRange(min_lod_level); memoryRemainingThisMip -= additionalMemRequired; memoryRemaining -= additionalMemRequired; if (memoryRemainingThisMip > 0 && memoryRemainingThisFrame > targetMem) { @@ -347,12 +347,12 @@ void KRTextureManager::balanceTextureMemory(long& memoryRemaining, long& memoryR } 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); + memoryRemainingThisFrame -= texture->getMemRequiredForLodRange(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); + memoryRemainingThisFrame -= texture->getMemRequiredForLodRange(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 156198c..15b03e0 100644 --- a/kraken/resources/texture/KRTexturePNG.cpp +++ b/kraken/resources/texture/KRTexturePNG.cpp @@ -77,7 +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_lod_count = 0; // Mipmaps not yet supported for PNG images + m_lod_count = 1; // Mipmaps not yet supported for PNG images switch (pHeader->chunk_IHDR.colorType) { case 0: // greyscale diff --git a/kraken/resources/texture/KRTexturePVR.cpp b/kraken/resources/texture/KRTexturePVR.cpp index 6bca62b..999ddcb 100755 --- a/kraken/resources/texture/KRTexturePVR.cpp +++ b/kraken/resources/texture/KRTexturePVR.cpp @@ -142,7 +142,7 @@ KRTexturePVR::KRTexturePVR(KRContext& context, Block* data, std::string name) : KRTexturePVR::~KRTexturePVR() { - for (std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { + for (std::vector::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { Block* block = *itr; delete block; } @@ -174,64 +174,19 @@ VkFormat KRTexturePVR::getFormat() const long KRTexturePVR::getMemRequiredForLod(int lod) { - // Determine how much memory will be consumed - long memoryRequired = 0; - int level = 0; - - for (std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { - Block* block = *itr; - if (level >= lod) { - memoryRequired += (long)block->getSize(); - } - - level++; - } - - return memoryRequired; + int target_lod = KRMIN(lod, m_lod_count - 1); + return m_blocks[target_lod]->getSize(); } bool KRTexturePVR::getLodData(void* buffer, int lod) { - 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_iWidth; - int height = m_iHeight; - long memoryRequired = 0; - long memoryTransferred = 0; - - // Upload texture data - int level = 0; - for (std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { - Block* block = *itr; - if (level >= target_lod) { - - block->lock(); - /* - * TODO - Vulkan Refactoring - GLDEBUG(glCompressedTexImage2D(target, destination_level, m_internalFormat, width, height, 0, (int)block->getSize(), block->getStart())); - */ - block->unlock(); - memoryTransferred += (long)block->getSize(); // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE - memoryRequired += (long)block->getSize(); - // - // err = glGetError(); - // if (err != GL_NO_ERROR) { - // assert(false); - // return false; - // } - // - } - - level++; - } - + int target_lod = KRMIN(lod, m_lod_count - 1); + m_blocks[target_lod]->copy(buffer); return true; - } std::string KRTexturePVR::getExtension() diff --git a/kraken/resources/texture/KRTexturePVR.h b/kraken/resources/texture/KRTexturePVR.h index 1e4471d..07d96c9 100755 --- a/kraken/resources/texture/KRTexturePVR.h +++ b/kraken/resources/texture/KRTexturePVR.h @@ -54,5 +54,5 @@ protected: unsigned int m_internalFormat; bool m_bHasAlpha; - std::list m_blocks; + std::vector m_blocks; }; diff --git a/kraken/resources/texture/KRTextureTGA.cpp b/kraken/resources/texture/KRTextureTGA.cpp index b35e3e4..c63363c 100755 --- a/kraken/resources/texture/KRTextureTGA.cpp +++ b/kraken/resources/texture/KRTextureTGA.cpp @@ -79,7 +79,7 @@ KRTextureTGA::KRTextureTGA(KRContext& context, Block* data, std::string name) : m_dimensions.x = pHeader->width; m_dimensions.y = pHeader->height; - m_lod_count = 0; // Mipmaps not yet supported for TGA images + m_lod_count = 1; // Mipmaps not yet supported for TGA images switch (pHeader->imagetype) { case 2: // rgb case 10: // rgb + rle