Fixes for mipmap streaming system.
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

Added KRNode::alwaysStreamResources()
KRCamera now set to always stream its resources, so that the debug font texture and textures used for post-processing will always be loaded.
This commit is contained in:
2026-03-23 22:45:51 -07:00
parent b205fe2e0d
commit 9d5d269feb
10 changed files with 194 additions and 159 deletions

View File

@@ -479,6 +479,22 @@ void KRCamera::renderPost(RenderInfo& ri)
void KRCamera::renderDebug(RenderInfo& ri) void KRCamera::renderDebug(RenderInfo& ri)
{ {
const char* szText = settings.m_debug_text.c_str(); const char* szText = settings.m_debug_text.c_str();
if (*szText == '\0') {
if (m_debug_text_vertices.getSize() > 0) {
m_debug_text_vertices = Block();
}
return;
}
if (!m_fontTexture.isBound())
{
return;
}
KRTexture* fontTexture = m_fontTexture.get();
if (fontTexture->getStreamLevel() == kraken_stream_level::STREAM_LEVEL_OUT) {
return;
}
std::string debug_text; std::string debug_text;
if (settings.debug_display != KRRenderSettings::KRENGINE_DEBUG_DISPLAY_NONE) { if (settings.debug_display != KRRenderSettings::KRENGINE_DEBUG_DISPLAY_NONE) {
@@ -488,7 +504,6 @@ void KRCamera::renderDebug(RenderInfo& ri)
} }
} }
if (*szText) {
int row_count = 1; int row_count = 1;
const int MAX_TABS = 5; const int MAX_TABS = 5;
const int TAB_EXTRA = 2; const int TAB_EXTRA = 2;
@@ -604,9 +619,6 @@ void KRCamera::renderDebug(RenderInfo& ri)
m_debug_text_vbo_data.load(ri.commandBuffer); m_debug_text_vbo_data.load(ri.commandBuffer);
KRTexture* fontTexture = m_fontTexture.get();
if (fontTexture->getStreamLevel() != kraken_stream_level::STREAM_LEVEL_OUT) {
PipelineInfo info{}; PipelineInfo info{};
std::string shader_name("debug_font"); std::string shader_name("debug_font");
info.shader_name = &shader_name; info.shader_name = &shader_name;
@@ -624,15 +636,8 @@ void KRCamera::renderDebug(RenderInfo& ri)
m_debug_text_vbo_data.bind(ri.commandBuffer); m_debug_text_vbo_data.bind(ri.commandBuffer);
vkCmdDraw(ri.commandBuffer, vertex_count, 1, 0, 0); vkCmdDraw(ri.commandBuffer, vertex_count, 1, 0, 0);
}
m_debug_text_vertices.unlock(); m_debug_text_vertices.unlock();
} else {
if (m_debug_text_vertices.getSize() > 0) {
m_debug_text_vertices = Block();
}
}
} }
@@ -853,3 +858,8 @@ bool KRCamera::getShaderValue(ShaderValue value, hydra::Vector4* output) const
return KRNode::getShaderValue(value, output); return KRNode::getShaderValue(value, output);
} }
bool KRCamera::alwaysStreamResources()
{
return true;
}

View File

@@ -63,6 +63,7 @@ public:
void getResourceBindings(std::list<KRResourceBinding*>& bindings) final; void getResourceBindings(std::list<KRResourceBinding*>& bindings) final;
void render(KRNode::RenderInfo& ri) final; void render(KRNode::RenderInfo& ri) final;
bool alwaysStreamResources() override;
KRRenderSettings settings; KRRenderSettings settings;

View File

@@ -671,6 +671,11 @@ void KRNode::getResourceBindings(std::list<KRResourceBinding*>& bindings)
} }
bool KRNode::alwaysStreamResources()
{
return false;
}
void KRNode::render(RenderInfo& ri) void KRNode::render(RenderInfo& ri)
{ {
m_lastRenderFrame = getContext().getCurrentFrame(); m_lastRenderFrame = getContext().getCurrentFrame();

View File

@@ -240,6 +240,7 @@ public:
virtual void preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests); virtual void preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests);
virtual void getResourceBindings(std::list<KRResourceBinding*>& bindings); virtual void getResourceBindings(std::list<KRResourceBinding*>& bindings);
virtual bool alwaysStreamResources();
virtual void render(RenderInfo& ri); virtual void render(RenderInfo& ri);
virtual void physicsUpdate(float deltaTime); virtual void physicsUpdate(float deltaTime);

View File

@@ -145,6 +145,12 @@ void KRScene::render(KRNode::RenderInfo& ri)
} }
} }
// Stream assets for nodes that request having their assets always streamed in.
for (std::set<KRNode*>::iterator itr = m_alwaysStreamedNodes.begin(); itr != m_alwaysStreamedNodes.end(); itr++) {
KRNode* node = (*itr);
node->preStream(*ri.viewport, resourceRequests);
}
std::vector<KROctreeNode*> remainingOctrees; std::vector<KROctreeNode*> remainingOctrees;
if (m_nodeTree.getRootNode() != NULL) { if (m_nodeTree.getRootNode() != NULL) {
remainingOctrees.push_back(m_nodeTree.getRootNode()); remainingOctrees.push_back(m_nodeTree.getRootNode());
@@ -204,16 +210,17 @@ void KRScene::render(KRNode::RenderInfo& ri, std::list<KRResourceRequest>& resou
// Render objects that are at this octree level // Render objects that are at this octree level
for (std::set<KRNode*>::iterator itr = pOctreeNode->getSceneNodes().begin(); itr != pOctreeNode->getSceneNodes().end(); itr++) { for (std::set<KRNode*>::iterator itr = pOctreeNode->getSceneNodes().begin(); itr != pOctreeNode->getSceneNodes().end(); itr++) {
KRNode* node = (*itr);
//assert(pOctreeNode->getBounds().contains((*itr)->getBounds())); // Sanity check //assert(pOctreeNode->getBounds().contains((*itr)->getBounds())); // Sanity check
if (ri.renderPass->getType() == RenderPassType::RENDER_PASS_PRESTREAM) { if (ri.renderPass->getType() == RenderPassType::RENDER_PASS_PRESTREAM) {
if ((*itr)->getLODVisibility() >= KRNode::LOD_VISIBILITY_PRESTREAM) { if (node->getLODVisibility() >= KRNode::LOD_VISIBILITY_PRESTREAM) {
(*itr)->preStream(*ri.viewport, resourceRequests); node->preStream(*ri.viewport, resourceRequests);
} }
} else { } else {
if ((*itr)->getLODVisibility() > KRNode::LOD_VISIBILITY_PRESTREAM) if (node->getLODVisibility() > KRNode::LOD_VISIBILITY_PRESTREAM)
{ {
ri.reflectedObjects.push_back(*itr); ri.reflectedObjects.push_back(*itr);
(*itr)->render(ri); node->render(ri);
ri.reflectedObjects.pop_back(); ri.reflectedObjects.pop_back();
} }
} }
@@ -313,6 +320,9 @@ void KRScene::notify_sceneGraphDelete(KRNode* pNode)
{ {
m_nodeTree.remove(pNode); m_nodeTree.remove(pNode);
m_physicsNodes.erase(pNode); m_physicsNodes.erase(pNode);
if (pNode->alwaysStreamResources()) {
m_alwaysStreamedNodes.erase(pNode);
}
KRAmbientZone* AmbientZoneNode = dynamic_cast<KRAmbientZone*>(pNode); KRAmbientZone* AmbientZoneNode = dynamic_cast<KRAmbientZone*>(pNode);
if (AmbientZoneNode) { if (AmbientZoneNode) {
m_ambientZoneNodes.erase(AmbientZoneNode); m_ambientZoneNodes.erase(AmbientZoneNode);
@@ -351,6 +361,9 @@ void KRScene::updateOctree(const KRViewport& viewport)
if (node->hasPhysics()) { if (node->hasPhysics()) {
m_physicsNodes.insert(node); m_physicsNodes.insert(node);
} }
if (node->alwaysStreamResources()) {
m_alwaysStreamedNodes.insert(node);
}
KRAmbientZone* ambientZoneNode = dynamic_cast<KRAmbientZone*>(node); KRAmbientZone* ambientZoneNode = dynamic_cast<KRAmbientZone*>(node);
if (ambientZoneNode) { if (ambientZoneNode) {
m_ambientZoneNodes.insert(ambientZoneNode); m_ambientZoneNodes.insert(ambientZoneNode);
@@ -378,6 +391,12 @@ void KRScene::updateOctree(const KRViewport& viewport)
} else if (!node->hasPhysics()) { } else if (!node->hasPhysics()) {
m_physicsNodes.erase(node); m_physicsNodes.erase(node);
} }
if (node->alwaysStreamResources()) {
m_alwaysStreamedNodes.insert(node);
} else {
m_alwaysStreamedNodes.erase(node);
}
} }
} }

View File

@@ -108,6 +108,7 @@ private:
std::set<KRReverbZone*> m_reverbZoneNodes; std::set<KRReverbZone*> m_reverbZoneNodes;
std::set<KRLocator*> m_locatorNodes; std::set<KRLocator*> m_locatorNodes;
std::set<KRLight*> m_lights; std::set<KRLight*> m_lights;
std::set<KRNode*> m_alwaysStreamedNodes;
KROctree m_nodeTree; KROctree m_nodeTree;

View File

@@ -122,7 +122,7 @@ void KRTexture::resize(int lod)
if (!m_haveNewHandles) { if (!m_haveNewHandles) {
if (lod != -1) { if (lod != -1) {
int target_lod = KRMIN(lod, m_lod_count); int target_lod = KRMIN(lod, m_lod_count - 1);
if (m_new_lod != target_lod || m_handles.empty()) { if (m_new_lod != target_lod || m_handles.empty()) {
assert(m_newTextureMemUsed == 0); assert(m_newTextureMemUsed == 0);
@@ -340,8 +340,7 @@ long KRTexture::getMemRequiredForLodRange(int min_lod, int max_lod /* = 0xff */)
long memRequired = 0; long memRequired = 0;
for (int lod = target_min_lod; lod <= target_max_lod; lod++) { for (int lod = target_min_lod; lod <= target_max_lod; lod++) {
memRequired += memRequired += getMemRequiredForLod(lod);
(lod);
} }
return memRequired; return memRequired;
} }

View File

@@ -46,23 +46,22 @@ KRTexture2D::~KRTexture2D()
delete m_pData; delete m_pData;
} }
bool KRTexture2D::createGPUTexture(int lod) bool KRTexture2D::createGPUTexture(int targetLod)
{ {
if (m_haveNewHandles) { if (m_haveNewHandles) {
return true; return true;
} }
Vector3i dimensions = getDimensions(); Vector3i dimensions = getDimensions();
size_t bufferSize = getMemRequiredForLodRange(lod); size_t bufferSize = getMemRequiredForLodRange(targetLod);
void* buffer = malloc(bufferSize); void* buffer = malloc(bufferSize);
if (!getLodData(buffer, lod)) { if (!getLodData(buffer, targetLod)) {
delete buffer; delete buffer;
return false; return false;
} }
bool success = true; bool success = true;
int target_lod = m_new_lod;
m_new_lod = -1; m_new_lod = -1;
KRDeviceManager* deviceManager = getContext().getDeviceManager(); KRDeviceManager* deviceManager = getContext().getDeviceManager();
@@ -76,7 +75,7 @@ bool KRTexture2D::createGPUTexture(int lod)
texture.allocation = VK_NULL_HANDLE; texture.allocation = VK_NULL_HANDLE;
texture.image = VK_NULL_HANDLE; texture.image = VK_NULL_HANDLE;
if (!allocate(device, target_lod, 0, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &texture.image, &texture.allocation if (!allocate(device, targetLod, 0, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &texture.image, &texture.allocation
#if KRENGINE_DEBUG_GPU_LABELS #if KRENGINE_DEBUG_GPU_LABELS
, getName().c_str() , getName().c_str()
#endif #endif
@@ -85,7 +84,7 @@ bool KRTexture2D::createGPUTexture(int lod)
break; break;
} }
int min_mip = KRMIN(target_lod, m_lod_count - 1); int min_mip = KRMIN(targetLod, m_lod_count - 1);
int mip_count = m_lod_count - min_mip; int mip_count = m_lod_count - min_mip;
VkImageViewCreateInfo viewInfo{}; VkImageViewCreateInfo viewInfo{};
@@ -135,7 +134,7 @@ bool KRTexture2D::createGPUTexture(int lod)
delete buffer; delete buffer;
if (success) { if (success) {
m_new_lod = target_lod; m_new_lod = targetLod;
m_haveNewHandles = true; m_haveNewHandles = true;
} else { } else {
destroyNewHandles(); destroyNewHandles();

View File

@@ -53,5 +53,5 @@ public:
protected: protected:
mimir::Block* m_pData; mimir::Block* m_pData;
bool createGPUTexture(int lod) override; bool createGPUTexture(int targetLod) override;
}; };

View File

@@ -302,7 +302,7 @@ 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_lod_level = KRMIN(getContext().KRENGINE_TEXTURE_LQ_LOD, texture->getLodCount()); int min_lod_level = KRMIN(getContext().KRENGINE_TEXTURE_LQ_LOD, texture->getLodCount() - 1);
long minLodMem = texture->getMemRequiredForLodRange(min_lod_level); long minLodMem = texture->getMemRequiredForLodRange(min_lod_level);
memoryRemaining -= minLodMem; memoryRemaining -= minLodMem;