From dec5872cf65b7c9a28ad73a82d852d8c79e3b624 Mon Sep 17 00:00:00 2001 From: Kearwood Gilbert Date: Fri, 14 Nov 2025 22:30:08 -0800 Subject: [PATCH] WIP refactoring to move resource streaming to use KRResourceRequest lists --- kraken/nodes/KRCamera.cpp | 6 ++-- kraken/nodes/KRCamera.h | 2 +- kraken/nodes/KRModel.cpp | 4 +-- kraken/nodes/KRModel.h | 2 +- kraken/nodes/KRNode.cpp | 2 +- kraken/nodes/KRNode.h | 3 +- kraken/nodes/KRSprite.cpp | 6 ++-- kraken/nodes/KRSprite.h | 2 +- kraken/resources/KRResource.cpp | 5 +++ kraken/resources/KRResource.h | 4 +++ kraken/resources/KRResourceRequest.h | 50 ++++++++++++++++++++++++++ kraken/resources/scene/KRScene.cpp | 21 +++++++---- kraken/resources/scene/KRScene.h | 2 +- kraken/resources/texture/KRTexture.cpp | 6 ++++ kraken/resources/texture/KRTexture.h | 1 + 15 files changed, 95 insertions(+), 21 deletions(-) create mode 100644 kraken/resources/KRResourceRequest.h diff --git a/kraken/nodes/KRCamera.cpp b/kraken/nodes/KRCamera.cpp index 96c2b14..87b3786 100755 --- a/kraken/nodes/KRCamera.cpp +++ b/kraken/nodes/KRCamera.cpp @@ -143,14 +143,14 @@ const std::string KRCamera::getSkyBox() const return m_skyBox.getName(); } -void KRCamera::preStream(const KRViewport& viewport) +void KRCamera::preStream(const KRViewport& viewport, std::list& resourceRequests) { - KRNode::preStream(viewport); + KRNode::preStream(viewport, resourceRequests); m_skyBox.bind(&getContext()); if (m_skyBox.isBound()) { - m_skyBox.get()->requestResidency(0.0f, KRTexture::TEXTURE_USAGE_SKY_CUBE); + resourceRequests.emplace_back(m_skyBox.get(), KRTexture::TEXTURE_USAGE_SKY_CUBE); } } diff --git a/kraken/nodes/KRCamera.h b/kraken/nodes/KRCamera.h index 2119217..0dc6fe2 100755 --- a/kraken/nodes/KRCamera.h +++ b/kraken/nodes/KRCamera.h @@ -61,7 +61,7 @@ public: void renderFrame(VkCommandBuffer& commandBuffer, KRSurface& compositeSurface, KRRenderGraph& renderGraph); - void preStream(const KRViewport& viewport) final; + void preStream(const KRViewport& viewport, std::list& resourceRequests) final; void render(KRNode::RenderInfo& ri) final; KRRenderSettings settings; diff --git a/kraken/nodes/KRModel.cpp b/kraken/nodes/KRModel.cpp index 2f54a44..55096ac 100755 --- a/kraken/nodes/KRModel.cpp +++ b/kraken/nodes/KRModel.cpp @@ -313,9 +313,9 @@ void KRModel::render(KRNode::RenderInfo& ri) } } -void KRModel::preStream(const KRViewport& viewport) +void KRModel::preStream(const KRViewport& viewport, std::list& resourceRequests) { - KRNode::preStream(viewport); + KRNode::preStream(viewport, resourceRequests); loadModel(); float lod_coverage = viewport.coverage(getBounds()); diff --git a/kraken/nodes/KRModel.h b/kraken/nodes/KRModel.h index c2d03d6..ff38bcc 100755 --- a/kraken/nodes/KRModel.h +++ b/kraken/nodes/KRModel.h @@ -63,7 +63,7 @@ public: virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent); virtual void render(KRNode::RenderInfo& ri) override; - virtual void preStream(const KRViewport& viewport) override; + virtual void preStream(const KRViewport& viewport, std::list& resourceRequests) override; virtual hydra::AABB getBounds(); diff --git a/kraken/nodes/KRNode.cpp b/kraken/nodes/KRNode.cpp index 15be250..bdc96dd 100755 --- a/kraken/nodes/KRNode.cpp +++ b/kraken/nodes/KRNode.cpp @@ -684,7 +684,7 @@ KRNode* KRNode::LoadXML(KRScene& scene, tinyxml2::XMLElement* e) return new_node; } -void KRNode::preStream(const KRViewport& viewport) +void KRNode::preStream(const KRViewport& viewport, std::list& resourceRequests) { } diff --git a/kraken/nodes/KRNode.h b/kraken/nodes/KRNode.h index b6ad220..2ddc206 100755 --- a/kraken/nodes/KRNode.h +++ b/kraken/nodes/KRNode.h @@ -32,6 +32,7 @@ #pragma once #include "resources/KRResource.h" +#include "resources/KRResourceRequest.h" #include "KRViewport.h" #include "KROctreeNode.h" #include "KRBehavior.h" @@ -216,7 +217,7 @@ public: KRScene& getScene(); - virtual void preStream(const KRViewport& viewport); + virtual void preStream(const KRViewport& viewport, std::list& resourceRequests); virtual void render(RenderInfo& ri); virtual void physicsUpdate(float deltaTime); diff --git a/kraken/nodes/KRSprite.cpp b/kraken/nodes/KRSprite.cpp index 4f1ce77..41c4a80 100755 --- a/kraken/nodes/KRSprite.cpp +++ b/kraken/nodes/KRSprite.cpp @@ -112,15 +112,15 @@ AABB KRSprite::getBounds() } -void KRSprite::preStream(const KRViewport& viewport) +void KRSprite::preStream(const KRViewport& viewport, std::list& resourceRequests) { - KRNode::preStream(viewport); + KRNode::preStream(viewport, resourceRequests); // Pre-stream sprites, even if the alpha is zero m_spriteTexture.bind(&getContext()); if (m_spriteTexture.isBound()) { - m_spriteTexture.get()->requestResidency(0.0f, KRTexture::TEXTURE_USAGE_SPRITE); + resourceRequests.emplace_back(m_spriteTexture.get(), KRTexture::TEXTURE_USAGE_SPRITE); } } diff --git a/kraken/nodes/KRSprite.h b/kraken/nodes/KRSprite.h index 7d75a20..da3ed77 100755 --- a/kraken/nodes/KRSprite.h +++ b/kraken/nodes/KRSprite.h @@ -52,7 +52,7 @@ public: void setSpriteAlpha(float alpha); float getSpriteAlpha() const; - virtual void preStream(const KRViewport& viewport) override; + virtual void preStream(const KRViewport& viewport, std::list& resourceRequests) override; virtual void render(RenderInfo& ri) override; virtual hydra::AABB getBounds() override; diff --git a/kraken/resources/KRResource.cpp b/kraken/resources/KRResource.cpp index 344a75f..185a303 100755 --- a/kraken/resources/KRResource.cpp +++ b/kraken/resources/KRResource.cpp @@ -71,3 +71,8 @@ KrResult KRResource::moveToBundle(KRBundle* bundle) delete data; return KR_SUCCESS; } + +void KRResource::requestResidency(uint32_t usage, float lodCoverage) +{ + +} diff --git a/kraken/resources/KRResource.h b/kraken/resources/KRResource.h index 1566618..f228eeb 100755 --- a/kraken/resources/KRResource.h +++ b/kraken/resources/KRResource.h @@ -48,6 +48,10 @@ public: KrResult moveToBundle(KRBundle* bundle); + // TODO: requestResidency is a temporary interface until the streaming system is updated + // to directly balance memory from KRResourceRequest's + virtual void requestResidency(uint32_t usage, float lodCoverage); + virtual ~KRResource(); static KRMesh* LoadObj(KRContext& context, const std::string& path); diff --git a/kraken/resources/KRResourceRequest.h b/kraken/resources/KRResourceRequest.h new file mode 100644 index 0000000..6affc4c --- /dev/null +++ b/kraken/resources/KRResourceRequest.h @@ -0,0 +1,50 @@ +// +// KRResource.h +// Kraken Engine +// +// Copyright 2025 Kearwood Gilbert. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of Kearwood Gilbert. +// + +#pragma once + +#include "KREngine-common.h" + +class KRResource; +class KRResourceRequest +{ +public: + KRResourceRequest(KRResource* resource, uint32_t usage, float lodCoverage = 0.0f) + : resource(resource) + , usage(usage) + , coverage(static_cast(KRCLAMP(lodCoverage / 1.0f * 255.f, 0, 255.f))) + { + + } + KRResource* resource; + unsigned int usage : 24; + uint8_t coverage : 8; +}; diff --git a/kraken/resources/scene/KRScene.cpp b/kraken/resources/scene/KRScene.cpp index f4d78af..a84a5b4 100755 --- a/kraken/resources/scene/KRScene.cpp +++ b/kraken/resources/scene/KRScene.cpp @@ -39,6 +39,7 @@ #include "nodes/KRSpotLight.h" #include "nodes/KRPointLight.h" #include "resources/audio/KRAudioManager.h" +#include "resources/KRResourceRequest.h" #include "KRRenderPass.h" using namespace mimir; @@ -103,6 +104,7 @@ std::set& KRScene::getLights() void KRScene::render(KRNode::RenderInfo& ri) { + std::list resourceRequests; // ---------- Start: Vulkan Debug Code ---------- /* @@ -153,7 +155,7 @@ void KRScene::render(KRNode::RenderInfo& ri) KRNode* node = (*itr); if (ri.renderPass->getType() == RenderPassType::RENDER_PASS_PRESTREAM) { if ((*itr)->getLODVisibility() >= KRNode::LOD_VISIBILITY_PRESTREAM) { - node->preStream(*ri.viewport); + node->preStream(*ri.viewport, resourceRequests); } } else { if ((*itr)->getLODVisibility() > KRNode::LOD_VISIBILITY_PRESTREAM) { @@ -177,10 +179,10 @@ void KRScene::render(KRNode::RenderInfo& ri) newRemainingOctrees.clear(); newRemainingOctreesTestResults.clear(); for (std::vector::iterator octree_itr = remainingOctrees.begin(); octree_itr != remainingOctrees.end(); octree_itr++) { - render(ri, *octree_itr, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, false, false); + render(ri, resourceRequests, *octree_itr, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, false, false); } for (std::vector::iterator octree_itr = remainingOctreesTestResults.begin(); octree_itr != remainingOctreesTestResults.end(); octree_itr++) { - render(ri, *octree_itr, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, true, false); + render(ri, resourceRequests, *octree_itr, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, true, false); } remainingOctrees = newRemainingOctrees; remainingOctreesTestResults = newRemainingOctreesTestResults; @@ -189,11 +191,16 @@ void KRScene::render(KRNode::RenderInfo& ri) newRemainingOctrees.clear(); newRemainingOctreesTestResults.clear(); for (std::vector::iterator octree_itr = remainingOctreesTestResultsOnly.begin(); octree_itr != remainingOctreesTestResultsOnly.end(); octree_itr++) { - render(ri, *octree_itr, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, true, true); + render(ri, resourceRequests, *octree_itr, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, true, true); + } + + // TODO: WIP Refactoring, this will be moved to the streaming system + for (KRResourceRequest request : resourceRequests) { + request.resource->requestResidency(request.usage, static_cast(request.coverage) / 255.f); } } -void KRScene::render(KRNode::RenderInfo& ri, KROctreeNode* pOctreeNode, std::vector& remainingOctrees, std::vector& remainingOctreesTestResults, std::vector& remainingOctreesTestResultsOnly, bool bOcclusionResultsPass, bool bOcclusionTestResultsOnly) +void KRScene::render(KRNode::RenderInfo& ri, std::list& resourceRequests, KROctreeNode* pOctreeNode, std::vector& remainingOctrees, std::vector& remainingOctreesTestResults, std::vector& remainingOctreesTestResultsOnly, bool bOcclusionResultsPass, bool bOcclusionTestResultsOnly) { unordered_map& visibleBounds = ri.viewport->getVisibleBounds(); if (pOctreeNode) { @@ -358,7 +365,7 @@ void KRScene::render(KRNode::RenderInfo& ri, KROctreeNode* pOctreeNode, std::vec //assert(pOctreeNode->getBounds().contains((*itr)->getBounds())); // Sanity check if (ri.renderPass->getType() == RenderPassType::RENDER_PASS_PRESTREAM) { if ((*itr)->getLODVisibility() >= KRNode::LOD_VISIBILITY_PRESTREAM) { - (*itr)->preStream(*ri.viewport); + (*itr)->preStream(*ri.viewport, resourceRequests); } } else { if ((*itr)->getLODVisibility() > KRNode::LOD_VISIBILITY_PRESTREAM) @@ -374,7 +381,7 @@ void KRScene::render(KRNode::RenderInfo& ri, KROctreeNode* pOctreeNode, std::vec const int* childOctreeOrder = ri.renderPass->getType() == RenderPassType::RENDER_PASS_FORWARD_TRANSPARENT || ri.renderPass->getType() == RenderPassType::RENDER_PASS_ADDITIVE_PARTICLES || ri.renderPass->getType() == RenderPassType::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE ? ri.viewport->getBackToFrontOrder() : ri.viewport->getFrontToBackOrder(); for (int i = 0; i < 8; i++) { - render(ri, pOctreeNode->getChildren()[childOctreeOrder[i]], remainingOctrees, remainingOctreesTestResults, remainingOctreesTestResultsOnly, false, false); + render(ri, resourceRequests, pOctreeNode->getChildren()[childOctreeOrder[i]], remainingOctrees, remainingOctreesTestResults, remainingOctreesTestResultsOnly, false, false); } // Remove lights added at this octree level from the stack diff --git a/kraken/resources/scene/KRScene.h b/kraken/resources/scene/KRScene.h index 01d161d..35e4d00 100755 --- a/kraken/resources/scene/KRScene.h +++ b/kraken/resources/scene/KRScene.h @@ -92,7 +92,7 @@ public: std::set& getLights(); private: - void render(KRNode::RenderInfo& ri, KROctreeNode* pOctreeNode, std::vector& remainingOctrees, std::vector& remainingOctreesTestResults, std::vector& remainingOctreesTestResultsOnly, bool bOcclusionResultsPass, bool bOcclusionTestResultsOnly); + void render(KRNode::RenderInfo& ri, std::list& resourceRequests, KROctreeNode* pOctreeNode, std::vector& remainingOctrees, std::vector& remainingOctreesTestResults, std::vector& remainingOctreesTestResultsOnly, bool bOcclusionResultsPass, bool bOcclusionTestResultsOnly); KRNode* m_pRootNode; KRLight* m_pFirstLight; diff --git a/kraken/resources/texture/KRTexture.cpp b/kraken/resources/texture/KRTexture.cpp index 810b785..8477635 100755 --- a/kraken/resources/texture/KRTexture.cpp +++ b/kraken/resources/texture/KRTexture.cpp @@ -146,6 +146,12 @@ void KRTexture::resize(int max_dim) m_handle_lock.clear(); } +void KRTexture::requestResidency(uint32_t usage, float lodCoverage) +{ + KRResource::requestResidency(usage, lodCoverage); + requestResidency(lodCoverage, static_cast(usage)); +} + void KRTexture::requestResidency(float lodCoverage, KRTexture::texture_usage_t textureUsage) { long current_frame = getContext().getCurrentFrame(); diff --git a/kraken/resources/texture/KRTexture.h b/kraken/resources/texture/KRTexture.h index b6e1b61..658ef72 100755 --- a/kraken/resources/texture/KRTexture.h +++ b/kraken/resources/texture/KRTexture.h @@ -78,6 +78,7 @@ public: float getStreamPriority(); virtual void requestResidency(float lodCoverage, texture_usage_t textureUsage); + void requestResidency(uint32_t usage, float lodCoverage = 0.0f) override; virtual bool isAnimated(); virtual KRTexture* compress(bool premultiply_alpha = false);