Changed mip-map handling to use mip/lod levels rather than maximum dimensions of the lod.
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, clang, clang++, macos-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, clang, clang++, ubuntu-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, gcc, g++, ubuntu-latest) (push) Has been cancelled

This commit is contained in:
2026-03-17 00:03:12 -07:00
parent d1299ccc13
commit d652d747a2
22 changed files with 150 additions and 241 deletions

View File

@@ -57,7 +57,8 @@ int KRContext::KRENGINE_MAX_PIPELINE_HANDLES = 4000;
int KRContext::KRENGINE_GPU_MEM_MAX = 256000000; int KRContext::KRENGINE_GPU_MEM_MAX = 256000000;
int KRContext::KRENGINE_GPU_MEM_TARGET = 192000000; int KRContext::KRENGINE_GPU_MEM_TARGET = 192000000;
int KRContext::KRENGINE_MAX_TEXTURE_DIM = 8192; 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? // TODO - This should be configured per-scene? Or auto/dynamic?
int KRContext::KRENGINE_PRESTREAM_DISTANCE = 1000.0f; int KRContext::KRENGINE_PRESTREAM_DISTANCE = 1000.0f;

View File

@@ -65,8 +65,9 @@ public:
static int KRENGINE_GPU_MEM_MAX; static int KRENGINE_GPU_MEM_MAX;
static int KRENGINE_GPU_MEM_TARGET; static int KRENGINE_GPU_MEM_TARGET;
static int KRENGINE_MAX_TEXTURE_DIM; static int KRENGINE_MAX_TEXTURE_DIM;
static int KRENGINE_MIN_TEXTURE_DIM;
static int KRENGINE_PRESTREAM_DISTANCE; static int KRENGINE_PRESTREAM_DISTANCE;
static int KRENGINE_TEXTURE_HQ_LOD;
static int KRENGINE_TEXTURE_LQ_LOD;
KRContext(const KrInitializeInfo* initializeInfo); KRContext(const KrInitializeInfo* initializeInfo);

View File

@@ -89,7 +89,8 @@ void kraken::set_debug_text(const std::string &print_text)
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048; 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; 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_MAX = 64000000 * 2;
KRContext::KRENGINE_GPU_MEM_TARGET = 48000000 * 2; KRContext::KRENGINE_GPU_MEM_TARGET = 48000000 * 2;
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048; 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 { } else {
KRContext::KRENGINE_GPU_MEM_MAX = 64000000; KRContext::KRENGINE_GPU_MEM_MAX = 64000000;
KRContext::KRENGINE_GPU_MEM_TARGET = 48000000; KRContext::KRENGINE_GPU_MEM_TARGET = 48000000;
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048; 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 #else
KRContext::KRENGINE_GPU_MEM_MAX = 256000000; KRContext::KRENGINE_GPU_MEM_MAX = 256000000;
KRContext::KRENGINE_GPU_MEM_TARGET = 192000000; KRContext::KRENGINE_GPU_MEM_TARGET = 192000000;
KRContext::KRENGINE_MAX_TEXTURE_DIM = 8192; 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; KRContext::KRENGINE_PRESTREAM_DISTANCE = 1000.0f;
#endif #endif

View File

@@ -37,8 +37,8 @@
KRTexture::KRTexture(KRContext& context, std::string name) : KRResource(context, name) KRTexture::KRTexture(KRContext& context, std::string name) : KRResource(context, name)
{ {
m_current_lod_max_dim = 0; m_current_lod = -1;
m_new_lod_max_dim = 0; m_new_lod = -1;
m_textureMemUsed = 0; m_textureMemUsed = 0;
m_newTextureMemUsed = 0; m_newTextureMemUsed = 0;
m_last_frame_used = 0; m_last_frame_used = 0;
@@ -96,8 +96,8 @@ void KRTexture::releaseHandles()
destroyNewHandles(); destroyNewHandles();
destroyHandles(); destroyHandles();
m_current_lod_max_dim = 0; m_current_lod = -1;
m_new_lod_max_dim = 0; m_new_lod = -1;
m_handle_lock.clear(); m_handle_lock.clear();
@@ -115,25 +115,24 @@ long KRTexture::getReferencedMemSize()
return 0; return 0;
} }
void KRTexture::resize(int max_dim) void KRTexture::resize(int lod)
{ {
while (m_handle_lock.test_and_set()) { while (m_handle_lock.test_and_set()) {
}; // Spin lock }; // Spin lock
if (!m_haveNewHandles) { if (!m_haveNewHandles) {
if (max_dim > 0) { if (lod != -1) {
int target_dim = max_dim; int target_lod = KRMIN(lod, m_lod_count);
if (target_dim < (int)m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
if (m_new_lod_max_dim != target_dim || m_handles.empty()) { if (m_new_lod != target_lod || m_handles.empty()) {
assert(m_newTextureMemUsed == 0); assert(m_newTextureMemUsed == 0);
m_newTextureMemUsed = getMemRequiredForSize(target_dim); m_newTextureMemUsed = getMemRequiredForLod(target_lod);
getContext().getTextureManager()->memoryChanged(m_newTextureMemUsed); getContext().getTextureManager()->memoryChanged(m_newTextureMemUsed);
getContext().getTextureManager()->addMemoryTransferredThisFrame(m_newTextureMemUsed); getContext().getTextureManager()->addMemoryTransferredThisFrame(m_newTextureMemUsed);
if (createGPUTexture(target_dim)) { if (createGPUTexture(target_lod)) {
m_new_lod_max_dim = target_dim; m_new_lod = target_lod;
} else { } else {
getContext().getTextureManager()->memoryChanged(-m_newTextureMemUsed); getContext().getTextureManager()->memoryChanged(-m_newTextureMemUsed);
m_newTextureMemUsed = 0; m_newTextureMemUsed = 0;
@@ -168,14 +167,12 @@ void KRTexture::requestResidency(float lodCoverage, KRTexture::texture_usage_t t
kraken_stream_level KRTexture::getStreamLevel() kraken_stream_level KRTexture::getStreamLevel()
{ {
if (m_current_lod_max_dim == 0) { if (m_current_lod == -1) {
return kraken_stream_level::STREAM_LEVEL_OUT; 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; 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 { } 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; 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() int KRTexture::getMaxMipMap()
{ {
return m_max_lod_max_dim; hydra::Vector3i size = getDimensions();
} return std::max(size.x, std::max(size.y, size.z));
int KRTexture::getMinMipMap()
{
return m_min_lod_max_dim;
} }
bool KRTexture::hasMipmaps() bool KRTexture::hasMipmaps()
{ {
return m_max_lod_max_dim != m_min_lod_max_dim; return m_lod_count > 0;
} }
void KRTexture::_swapHandles() void KRTexture::_swapHandles()
@@ -259,7 +261,7 @@ void KRTexture::_swapHandles()
m_handles.swap(m_newHandles); m_handles.swap(m_newHandles);
m_textureMemUsed = (long)m_newTextureMemUsed; m_textureMemUsed = (long)m_newTextureMemUsed;
m_newTextureMemUsed = 0; m_newTextureMemUsed = 0;
m_current_lod_max_dim = m_new_lod_max_dim; m_current_lod = m_new_lod;
m_haveNewHandles = false; m_haveNewHandles = false;
} }
m_handle_lock.clear(); m_handle_lock.clear();

View File

@@ -52,8 +52,8 @@ public:
long getMemSize(); long getMemSize();
virtual long getReferencedMemSize(); virtual long getReferencedMemSize();
virtual long getMemRequiredForSize(int max_dim) = 0; virtual long getMemRequiredForLod(int lod) = 0;
virtual void resize(int max_dim); virtual void resize(int lod);
long getLastFrameUsed(); long getLastFrameUsed();
@@ -83,13 +83,13 @@ public:
virtual KRTexture* compress(bool premultiply_alpha = false); virtual KRTexture* compress(bool premultiply_alpha = false);
int getCurrentLodMaxDim(); int getCurrentLodMaxDim();
int getNewLodMaxDim(); // For use by streamer only int getNewLod(); // For use by streamer only
int getMaxMipMap(); int getMaxMipMap();
int getMinMipMap();
bool hasMipmaps(); bool hasMipmaps();
virtual int getFaceCount() const = 0; virtual int getFaceCount() const = 0;
virtual VkFormat getFormat() const = 0; virtual VkFormat getFormat() const = 0;
virtual hydra::Vector3i getDimensions() const = 0; virtual hydra::Vector3i getDimensions() const = 0;
int getLodCount() const;
kraken_stream_level getStreamLevel(); kraken_stream_level getStreamLevel();
float getLastFrameLodCoverage() const; float getLastFrameLodCoverage() const;
@@ -100,7 +100,7 @@ public:
VkImage getImage(KrDeviceHandle device); VkImage getImage(KrDeviceHandle device);
protected: protected:
virtual bool createGPUTexture(int lod_max_dim) = 0; virtual bool createGPUTexture(int lod) = 0;
void destroyHandles(); void destroyHandles();
void destroyNewHandles(); void destroyNewHandles();
@@ -120,11 +120,10 @@ protected:
std::atomic_flag m_handle_lock; std::atomic_flag m_handle_lock;
int m_current_lod_max_dim; int m_current_lod;
int m_new_lod_max_dim; int m_new_lod;
uint32_t m_max_lod_max_dim; int m_lod_count;
uint32_t m_min_lod_max_dim;
long m_last_frame_used; long m_last_frame_used;
float m_last_frame_max_lod_coverage; float m_last_frame_max_lod_coverage;

View File

@@ -46,24 +46,24 @@ KRTexture2D::~KRTexture2D()
delete m_pData; delete m_pData;
} }
bool KRTexture2D::createGPUTexture(int lod_max_dim) bool KRTexture2D::createGPUTexture(int lod)
{ {
if (m_haveNewHandles) { if (m_haveNewHandles) {
return true; return true;
} }
Vector3i dimensions = getDimensions(); Vector3i dimensions = getDimensions();
size_t bufferSize = getMemRequiredForSize(lod_max_dim); size_t bufferSize = getMemRequiredForLod(lod);
void* buffer = malloc(bufferSize); void* buffer = malloc(bufferSize);
if (!getLodData(buffer, lod_max_dim)) { if (!getLodData(buffer, lod)) {
delete buffer; delete buffer;
return false; return false;
} }
bool success = true; bool success = true;
int prev_lod_max_dim = m_new_lod_max_dim; int prev_lod = m_new_lod;
m_new_lod_max_dim = 0; m_new_lod = -1;
KRDeviceManager* deviceManager = getContext().getDeviceManager(); KRDeviceManager* deviceManager = getContext().getDeviceManager();
@@ -107,7 +107,7 @@ bool KRTexture2D::createGPUTexture(int lod_max_dim)
delete buffer; delete buffer;
if (success) { if (success) {
m_new_lod_max_dim = prev_lod_max_dim; m_new_lod = prev_lod;
m_haveNewHandles = true; m_haveNewHandles = true;
} else { } else {
destroyNewHandles(); destroyNewHandles();

View File

@@ -48,10 +48,10 @@ public:
virtual bool save(const std::string& path) override; virtual bool save(const std::string& path) override;
virtual bool save(mimir::Block& data) 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: protected:
mimir::Block* m_pData; mimir::Block* m_pData;
bool createGPUTexture(int lod_max_dim) override; bool createGPUTexture(int lod) override;
}; };

View File

@@ -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_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_frame_rate = (float)atof(name.substr(second_comma_pos + 1).c_str());
m_max_lod_max_dim = 2048; m_lod_count = 0;
m_min_lod_max_dim = 64;
m_dimensions = Vector2i::Create(0, 0); m_dimensions = Vector2i::Create(0, 0);
for (int i = 0; i < m_frame_count; i++) { for (int i = 0; i < m_frame_count; i++) {
@@ -60,8 +59,7 @@ KRTextureAnimated::KRTextureAnimated(KRContext& context, std::string name) : KRT
if (frame_texture) { if (frame_texture) {
m_dimensions.x = std::max(m_dimensions.x, frame_texture->getDimensions().x); m_dimensions.x = std::max(m_dimensions.x, frame_texture->getDimensions().x);
m_dimensions.y = std::max(m_dimensions.y, frame_texture->getDimensions().y); 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(); m_lod_count = std::max(m_lod_count, frame_texture->getLodCount());
if (frame_texture->getMinMipMap() > (int)m_min_lod_max_dim) m_min_lod_max_dim = frame_texture->getMinMipMap();
} }
} }
} }
@@ -83,12 +81,12 @@ KRTextureAnimated::~KRTextureAnimated()
} }
bool KRTextureAnimated::createGPUTexture(int lod_max_dim) bool KRTextureAnimated::createGPUTexture(int lod)
{ {
return true; return true;
} }
long KRTextureAnimated::getMemRequiredForSize(int max_dim) long KRTextureAnimated::getMemRequiredForLod(int lod)
{ {
return 0; // Memory is allocated by individual frame textures 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 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 // Purposely not calling the superclass method
} }

View File

@@ -46,19 +46,19 @@ public:
virtual bool save(const std::string& path) override; virtual bool save(const std::string& path) override;
virtual bool save(Block& data) 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 void requestResidency(float lodCoverage, texture_usage_t textureUsage) override;
virtual long getReferencedMemSize() override; virtual long getReferencedMemSize() override;
virtual bool isAnimated() override; virtual bool isAnimated() override;
virtual void resize(int max_dim) override; virtual void resize(int lod) override;
virtual int getFaceCount() const override; virtual int getFaceCount() const override;
virtual VkFormat getFormat() const override; virtual VkFormat getFormat() const override;
virtual hydra::Vector3i getDimensions() const override; virtual hydra::Vector3i getDimensions() const override;
private: private:
bool createGPUTexture(int lod_max_dim) override; bool createGPUTexture(int lod) override;
float m_frame_rate; float m_frame_rate;
int m_frame_count; int m_frame_count;

View File

@@ -38,16 +38,14 @@ using namespace hydra;
KRTextureCube::KRTextureCube(KRContext& context, std::string name) : KRTexture(context, name) KRTextureCube::KRTextureCube(KRContext& context, std::string name) : KRTexture(context, name)
{ {
m_max_lod_max_dim = 2048; m_lod_count = 0;
m_min_lod_max_dim = 64;
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
m_textures[i] = NULL; m_textures[i] = NULL;
std::string faceName = getName() + SUFFIXES[i]; std::string faceName = getName() + SUFFIXES[i];
m_textures[i] = (KRTexture2D*)getContext().getTextureManager()->getTexture(faceName); m_textures[i] = (KRTexture2D*)getContext().getTextureManager()->getTexture(faceName);
if (m_textures[i]) { if (m_textures[i]) {
if (m_textures[i]->getMaxMipMap() < (int)m_max_lod_max_dim) m_max_lod_max_dim = m_textures[i]->getMaxMipMap(); m_lod_count = std::max(m_lod_count, m_textures[i]->getLodCount());
if (m_textures[i]->getMinMipMap() > (int)m_min_lod_max_dim) m_min_lod_max_dim = m_textures[i]->getMinMipMap();
} else { } else {
assert(false); assert(false);
} }
@@ -57,14 +55,14 @@ KRTextureCube::KRTextureCube(KRContext& context, std::string name) : KRTexture(c
KRTextureCube::~KRTextureCube() KRTextureCube::~KRTextureCube()
{} {}
bool KRTextureCube::createGPUTexture(int lod_max_dim) bool KRTextureCube::createGPUTexture(int lod)
{ {
assert(!m_haveNewHandles); // Only allow one resize per frame assert(!m_haveNewHandles); // Only allow one resize per frame
bool success = true; bool success = true;
int prev_lod_max_dim = m_new_lod_max_dim; int prev_lod = m_new_lod;
m_new_lod_max_dim = 0; m_new_lod = -1;
bool bMipMaps = false; bool bMipMaps = false;
Vector2i dimensions = Vector2i::Zero(); Vector2i dimensions = Vector2i::Zero();
@@ -95,9 +93,9 @@ bool KRTextureCube::createGPUTexture(int lod_max_dim)
size_t bufferSizes[6] = {}; size_t bufferSizes[6] = {};
void* buffers[6] = {}; void* buffers[6] = {};
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
bufferSizes[i] = getMemRequiredForSize(lod_max_dim); bufferSizes[i] = getMemRequiredForLod(lod);
buffers[i] = malloc(bufferSizes[i]); 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(); KRDeviceManager* deviceManager = getContext().getDeviceManager();
@@ -132,7 +130,7 @@ bool KRTextureCube::createGPUTexture(int lod_max_dim)
m_haveNewHandles = true; m_haveNewHandles = true;
} else { } else {
destroyHandles(); destroyHandles();
m_new_lod_max_dim = prev_lod_max_dim; m_new_lod = prev_lod;
} }
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
@@ -144,15 +142,12 @@ bool KRTextureCube::createGPUTexture(int lod_max_dim)
return success; 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; long memoryRequired = 0;
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
if (m_textures[i]) { if (m_textures[i]) {
memoryRequired += m_textures[i]->getMemRequiredForSize(target_dim); memoryRequired += m_textures[i]->getMemRequiredForLod(lod);
} }
} }
return memoryRequired; return memoryRequired;

View File

@@ -44,14 +44,14 @@ public:
virtual bool save(const std::string& path) override; virtual bool save(const std::string& path) override;
virtual bool save(mimir::Block& data) 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 void requestResidency(float lodCoverage, texture_usage_t textureUsage) override;
virtual int getFaceCount() const override; virtual int getFaceCount() const override;
virtual VkFormat getFormat() const override; virtual VkFormat getFormat() const override;
virtual hydra::Vector3i getDimensions() const override; virtual hydra::Vector3i getDimensions() const override;
private: private:
bool createGPUTexture(int lod_max_dim) override; bool createGPUTexture(int lod) override;
const char* SUFFIXES[6] = { const char* SUFFIXES[6] = {
"_positive_x", "_positive_x",

View File

@@ -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_lod_count = (int)KRMAX(m_header.numberOfMipmapLevels, 1) - 1;
m_min_lod_max_dim = KRMAX(width, height);
} }
KRTextureKTX::KRTextureKTX(KRContext& context, std::string name, unsigned int internal_format, unsigned int base_internal_format, int width, int height, const std::list<Block*>& blocks) : KRTexture2D(context, new Block(), name) KRTextureKTX::KRTextureKTX(KRContext& context, std::string name, unsigned int internal_format, unsigned int base_internal_format, int width, int height, const std::list<Block*>& 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 // Determine how much memory will be consumed
int width = m_header.pixelWidth;
int height = m_header.pixelHeight;
long memoryRequired = 0; long memoryRequired = 0;
int level = 0;
for (std::list<Block*>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { for (std::list<Block*>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
Block* block = *itr; Block* block = *itr;
if (width <= target_dim && height <= target_dim) { if (level >= lod) {
memoryRequired += (long)block->getSize(); memoryRequired += (long)block->getSize();
} }
width = width >> 1; level++;
if (width < 1) {
width = 1;
}
height = height >> 1;
if (height < 1) {
height = 1;
}
} }
return memoryRequired; 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; unsigned char* converted_image = (unsigned char*)buffer;
int target_dim = lod_max_dim; int target_lod = KRMIN(lod, m_lod_count);
if (target_dim < (int)m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
if (m_blocks.size() == 0) { if (m_blocks.size() == 0) {
return false; return false;
} }
// Determine how much memory will be consumed // Determine how much memory will be consumed
int width = m_header.pixelWidth;
int height = m_header.pixelHeight;
long memoryRequired = 0; long memoryRequired = 0;
long memoryTransferred = 0; long memoryTransferred = 0;
// Upload texture data // Upload texture data
int destination_level = 0; int level = 0;
int source_level = 0;
for (std::list<Block*>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { for (std::list<Block*>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
Block* block = *itr; Block* block = *itr;
if (width <= target_dim && height <= target_dim) { if (level >= target_lod) {
/* /*
if (width > current_lod_max_dim) { if (width > current_lod_max_dim) {
@@ -440,22 +423,9 @@ bool KRTextureKTX::getLodData(void* buffer, int lod_max_dim)
// return false; // return false;
// } // }
// //
destination_level++;
} }
if (width <= m_current_lod_max_dim && height <= m_current_lod_max_dim) { level++;
source_level++;
}
width = width >> 1;
if (width < 1) {
width = 1;
}
height = height >> 1;
if (height < 1) {
height = 1;
}
} }
return true; return true;

View File

@@ -43,9 +43,9 @@ public:
virtual ~KRTextureKTX(); virtual ~KRTextureKTX();
virtual std::string getExtension() override; 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 hydra::Vector3i getDimensions() const override;
virtual int getFaceCount() const override; virtual int getFaceCount() const override;
virtual VkFormat getFormat() const override; virtual VkFormat getFormat() const override;

View File

@@ -68,8 +68,7 @@ KRTextureKTX2::KRTextureKTX2(KRContext& context, Block* data, std::string name)
if (height < 1) { if (height < 1) {
height = 1; height = 1;
} }
m_max_lod_max_dim = KRMAX(m_header.pixelWidth, m_header.pixelHeight); m_lod_count = (int)KRMAX(m_header.levelCount, 1) - 1;
m_min_lod_max_dim = KRMAX(width, height);
} }
KRTextureKTX2::~KRTextureKTX2() KRTextureKTX2::~KRTextureKTX2()
@@ -81,59 +80,42 @@ Vector3i KRTextureKTX2::getDimensions() const
return Vector3i::Create(Vector3i::Create(m_header.pixelWidth, m_header.pixelHeight, m_header.pixelDepth)); 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; int target_lod = KRMIN(lod, m_lod_count);
if (target_dim < (int)m_min_lod_max_dim) target_dim = target_dim;
// Determine how much memory will be consumed // Determine how much memory will be consumed
int width = m_header.pixelWidth;
int height = m_header.pixelHeight;
long memoryRequired = 0; long memoryRequired = 0;
int level = 0;
for (__uint32_t level = 0; level < m_header.levelCount; level++) { for (__uint32_t level = 0; level < m_header.levelCount; level++) {
KTX2LevelIndex levelIndex; KTX2LevelIndex levelIndex;
m_pData->copy(&levelIndex, sizeof(m_header) + sizeof(KTX2LevelIndex) * level, sizeof(KTX2LevelIndex)); 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; memoryRequired += (long)levelIndex.byteLength;
} }
level++;
width = width >> 1;
if (width < 1) {
width = 1;
}
height = height >> 1;
if (height < 1) {
height = 1;
}
} }
return memoryRequired; 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; unsigned char* converted_image = (unsigned char*)buffer;
int target_dim = lod_max_dim; int target_lod = KRMIN(lod, m_lod_count);
if (target_dim < (int)m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
// Determine how much memory will be consumed // Determine how much memory will be consumed
int width = m_header.pixelWidth;
int height = m_header.pixelHeight;
long memoryRequired = 0; long memoryRequired = 0;
long memoryTransferred = 0; long memoryTransferred = 0;
int level = 0;
// Upload texture data
int destination_level = 0;
int source_level = 0;
for (__uint32_t level = 0; level < m_header.levelCount; level++) { for (__uint32_t level = 0; level < m_header.levelCount; level++) {
KTX2LevelIndex levelIndex; KTX2LevelIndex levelIndex;
m_pData->copy(&levelIndex, sizeof(m_header) + sizeof(KTX2LevelIndex) * level, sizeof(KTX2LevelIndex)); 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 * 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) { level++;
source_level++;
}
width = width >> 1;
if (width < 1) {
width = 1;
}
height = height >> 1;
if (height < 1) {
height = 1;
}
} }
return true; return true;

View File

@@ -40,9 +40,9 @@ public:
virtual ~KRTextureKTX2(); virtual ~KRTextureKTX2();
virtual std::string getExtension() override; 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 hydra::Vector3i getDimensions() const override;
virtual int getFaceCount() const override; virtual int getFaceCount() const override;
virtual VkFormat getFormat() const override; virtual VkFormat getFormat() const override;

View File

@@ -302,13 +302,13 @@ void KRTextureManager::balanceTextureMemory(long& memoryRemaining, long& memoryR
for (auto itr = m_activeTextures_streamer.begin(); itr != m_activeTextures_streamer.end(); itr++) { for (auto itr = m_activeTextures_streamer.begin(); itr != m_activeTextures_streamer.end(); itr++) {
KRTexture* texture = (*itr).second; KRTexture* texture = (*itr).second;
int min_mip_level = KRMAX(getContext().KRENGINE_MIN_TEXTURE_DIM, texture->getMinMipMap()); int min_lod_level = KRMIN(getContext().KRENGINE_TEXTURE_LQ_LOD, texture->getLodCount());
long minLodMem = texture->getMemRequiredForSize(min_mip_level); long minLodMem = texture->getMemRequiredForLod(min_lod_level);
memoryRemaining -= minLodMem; memoryRemaining -= minLodMem;
if (memoryRemainingThisFrame > minLodMem && texture->getNewLodMaxDim() < min_mip_level) { if (memoryRemainingThisFrame > minLodMem && (texture->getNewLod() != -1 || texture->getNewLod() > min_lod_level)) {
memoryRemainingThisFrame -= minLodMem; 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; KRTexture* texture = (*itr).second;
int min_mip_level = KRMAX(getContext().KRENGINE_MIN_TEXTURE_DIM, texture->getMinMipMap()); int min_lod_level = KRMIN(getContext().KRENGINE_TEXTURE_LQ_LOD, texture->getLodCount());
int max_mip_level = KRMIN(getContext().KRENGINE_MAX_TEXTURE_DIM, texture->getMaxMipMap()); int target_lod_level = KRMIN(getContext().KRENGINE_TEXTURE_HQ_LOD + mip_drop, texture->getLodCount());
int target_mip_level = (max_mip_level >> mip_drop); long targetMem = texture->getMemRequiredForLod(target_lod_level);
long targetMem = texture->getMemRequiredForSize(target_mip_level); long additionalMemRequired = targetMem - texture->getMemRequiredForLod(min_lod_level);
long additionalMemRequired = targetMem - texture->getMemRequiredForSize(min_mip_level);
memoryRemainingThisMip -= additionalMemRequired; memoryRemainingThisMip -= additionalMemRequired;
memoryRemaining -= additionalMemRequired; memoryRemaining -= additionalMemRequired;
if (memoryRemainingThisMip > 0 && memoryRemainingThisFrame > targetMem) { if (memoryRemainingThisMip > 0 && memoryRemainingThisFrame > targetMem) {
int current_mip_level = texture->getNewLodMaxDim(); int current_lod_level = texture->getNewLod();
if (current_mip_level == (target_mip_level >> 1) || target_mip_level < current_mip_level) { 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; memoryRemainingThisFrame -= targetMem;
texture->resize(target_mip_level); texture->resize(target_lod_level);
} else if (current_mip_level == (target_mip_level >> 2)) { } else if (current_lod_level == (target_lod_level + 2)) {
memoryRemainingThisFrame -= texture->getMemRequiredForSize(target_mip_level >> 1); // We are two lod levels away from the target.
texture->resize(target_mip_level >> 1); // Advance to the lod level inbetween.
} else if (current_mip_level < (target_mip_level >> 2)) { memoryRemainingThisFrame -= texture->getMemRequiredForLod(target_lod_level + 1);
memoryRemainingThisFrame -= texture->getMemRequiredForSize(target_mip_level >> 2); texture->resize(target_lod_level + 1);
texture->resize(target_mip_level >> 2); } 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);
} }
} }

View File

@@ -77,8 +77,7 @@ KRTexturePNG::KRTexturePNG(KRContext& context, Block* data, std::string name) :
m_dimensions.x = SWAP_4(pHeader->chunk_IHDR.width); m_dimensions.x = SWAP_4(pHeader->chunk_IHDR.width);
m_dimensions.y = SWAP_4(pHeader->chunk_IHDR.height); 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_lod_count = 0; // Mipmaps not yet supported for PNG images
m_min_lod_max_dim = m_max_lod_max_dim; // Mipmaps not yet supported for PNG images
switch (pHeader->chunk_IHDR.colorType) { switch (pHeader->chunk_IHDR.colorType) {
case 0: case 0:
// greyscale // 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. // TODO - Vulkan Refactoring - Perhaps it would be more efficient to reformat the color channels during the copy to the staging buffer.
m_pData->lock(); m_pData->lock();
PNG_HEADER* pHeader = (PNG_HEADER*)m_pData->getStart(); PNG_HEADER* pHeader = (PNG_HEADER*)m_pData->getStart();
@@ -158,7 +157,7 @@ KRTexture* KRTexturePNG::compress(bool premultiply_alpha)
} }
#endif #endif
long KRTexturePNG::getMemRequiredForSize(int max_dim) long KRTexturePNG::getMemRequiredForLod(int lod)
{ {
return m_imageSize; return m_imageSize;
} }

View File

@@ -42,13 +42,13 @@ public:
virtual ~KRTexturePNG(); virtual ~KRTexturePNG();
virtual std::string getExtension() override; 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) #if !TARGET_OS_IPHONE && !defined(ANDROID)
virtual KRTexture* compress(bool premultiply_alpha = false) override; virtual KRTexture* compress(bool premultiply_alpha = false) override;
#endif #endif
virtual long getMemRequiredForSize(int max_dim) override; virtual long getMemRequiredForLod(int lod) override;
virtual hydra::Vector3i getDimensions() const override; virtual hydra::Vector3i getDimensions() const override;
virtual VkFormat getFormat() const override; virtual VkFormat getFormat() const override;
virtual int getFaceCount() const override; virtual int getFaceCount() const override;

View File

@@ -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 // Determine how much memory will be consumed
int width = m_iWidth;
int height = m_iHeight;
long memoryRequired = 0; long memoryRequired = 0;
int level = 0;
for (std::list<Block*>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { for (std::list<Block*>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
Block* block = *itr; Block* block = *itr;
if (width <= target_dim && height <= target_dim) { if (level >= lod) {
memoryRequired += (long)block->getSize(); memoryRequired += (long)block->getSize();
} }
width = width >> 1; level++;
if (width < 1) {
width = 1;
}
height = height >> 1;
if (height < 1) {
height = 1;
}
} }
return memoryRequired; return memoryRequired;
} }
bool KRTexturePVR::getLodData(void* buffer, int lod_max_dim) bool KRTexturePVR::getLodData(void* buffer, int lod)
{ {
int target_dim = lod_max_dim; int target_lod = KRMIN(lod, m_lod_count);
if (target_dim < (int)m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
if (m_blocks.size() == 0) { if (m_blocks.size() == 0) {
return false; return false;
@@ -217,19 +205,10 @@ bool KRTexturePVR::getLodData(void* buffer, int lod_max_dim)
long memoryTransferred = 0; long memoryTransferred = 0;
// Upload texture data // Upload texture data
int destination_level = 0; int level = 0;
int source_level = 0;
for (std::list<Block*>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { for (std::list<Block*>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
Block* block = *itr; Block* block = *itr;
if (width <= target_dim && height <= target_dim) { 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(); block->lock();
/* /*
@@ -246,22 +225,9 @@ bool KRTexturePVR::getLodData(void* buffer, int lod_max_dim)
// return false; // return false;
// } // }
// //
destination_level++;
} }
if (width <= m_current_lod_max_dim && height <= m_current_lod_max_dim) { level++;
source_level++;
}
width = width >> 1;
if (width < 1) {
width = 1;
}
height = height >> 1;
if (height < 1) {
height = 1;
}
} }
return true; return true;

View File

@@ -40,9 +40,9 @@ public:
virtual ~KRTexturePVR(); virtual ~KRTexturePVR();
virtual std::string getExtension() override; 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 hydra::Vector3i getDimensions() const override;
virtual VkFormat getFormat() const override; virtual VkFormat getFormat() const override;
virtual int getFaceCount() const override; virtual int getFaceCount() const override;

View File

@@ -79,8 +79,7 @@ KRTextureTGA::KRTextureTGA(KRContext& context, Block* data, std::string name) :
m_dimensions.x = pHeader->width; m_dimensions.x = pHeader->width;
m_dimensions.y = pHeader->height; m_dimensions.y = pHeader->height;
m_max_lod_max_dim = pHeader->width > pHeader->height ? pHeader->width : pHeader->height; m_lod_count = 0; // Mipmaps not yet supported for TGA images
m_min_lod_max_dim = m_max_lod_max_dim; // Mipmaps not yet supported for TGA images
switch (pHeader->imagetype) { switch (pHeader->imagetype) {
case 2: // rgb case 2: // rgb
case 10: // rgb + rle 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; unsigned char* converted_image = (unsigned char*)buffer;
@@ -338,7 +337,7 @@ KRTexture* KRTextureTGA::compress(bool premultiply_alpha)
} }
#endif #endif
long KRTextureTGA::getMemRequiredForSize(int max_dim) long KRTextureTGA::getMemRequiredForLod(int lod)
{ {
return m_imageSize; return m_imageSize;
} }

View File

@@ -42,13 +42,13 @@ public:
virtual ~KRTextureTGA(); virtual ~KRTextureTGA();
virtual std::string getExtension() override; 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) #if !TARGET_OS_IPHONE && !defined(ANDROID)
virtual KRTexture* compress(bool premultiply_alpha = false) override; virtual KRTexture* compress(bool premultiply_alpha = false) override;
#endif #endif
virtual long getMemRequiredForSize(int max_dim) override; virtual long getMemRequiredForLod(int lod) override;
virtual hydra::Vector3i getDimensions() const override; virtual hydra::Vector3i getDimensions() const override;
virtual VkFormat getFormat() const override; virtual VkFormat getFormat() const override;
virtual int getFaceCount() const override; virtual int getFaceCount() const override;