diff --git a/_Design/glossary.md b/_Design/glossary.md index d06b4fd..01efd25 100644 --- a/_Design/glossary.md +++ b/_Design/glossary.md @@ -3,34 +3,55 @@ ## ResourceRegistry A ResourceRegistry owns GPU-backed resources on the caller's behalf and hands out -lightweight Handles instead of pointers or ownership. +lightweight Handles instead of pointers or ownership. It is engine-internal: +frontend code never sees it, and reaches it through a ResourceRegistryRef. -Internally it's a collection of per-type pools, each responsible for one -resource type: +Internally it's a collection of per-type pools, each a `Pool` +(a generation-checked slot pool). A type that needs extra behaviour wraps its +pool in a thin class instead: ``` ResourceRegistry - ├── MeshPool → MeshHandle - ├── TexturePool → TextureHandle (planned) - └── MaterialPool → MaterialHandle (planned) + ├── meshes Pool + ├── renderTargets RenderTargetPool → RenderTargetHandle + │ (wraps Pool; waits for the GPU on release, applies resizes) + ├── scenes Pool + ├── textures (planned) + └── materials (planned) ``` +Engine code (`Application`, `ImGuiRenderer`, `SceneRenderer`) uses the pools +directly, e.g. `resources.renderTargets.get(handle)`. + A Handle is a small (index, generation) pair. The index locates the slot in the pool; the generation is bumped when that slot is released, so a Handle kept around after release() is detected as stale instead of resolving to someone else's resource (or freed memory). +Think: "Where does the engine keep every GPU resource, and how does it look one +up by handle?" + +## ResourceRegistryRef + +A ResourceRegistryRef is the frontend's non-owning, cheap-to-copy view of the +ResourceRegistry, returned by `Application::resources()`. It exposes only what +frontend code needs and hands out no pools, so no Vulkan-facing types leak +through the public API: + +``` +create(...) load(path) release(handle) +requestResize(target, w, h) getExtent(target) isAlive(handle) +``` + Typical lifecycle: ``` load(path) / create(...) → MeshHandle │ - get(handle) → const Mesh& - │ release(handle) ``` -Think: "Where do I get or release a GPU resource by handle, without owning its +Think: "How do I create or release a GPU resource by handle, without owning its lifetime directly?" ## Buffer @@ -257,7 +278,7 @@ A PanelRegistry owns Panels on the caller's behalf and hands out lightweight PanelHandles instead of pointers or ownership. Internally it's a generation-checked slot pool, the same shape ResourceRegistry's -per-type pools use: +`Pool` uses: ``` PanelRegistry diff --git a/engine/include/sophia/application.hpp b/engine/include/sophia/application.hpp index 67360f3..88b333e 100644 --- a/engine/include/sophia/application.hpp +++ b/engine/include/sophia/application.hpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -45,7 +45,7 @@ class Application { virtual void onRender() {} virtual void onDestroy() {} - ResourceRegistry& resources() { return this->resourceRegistry; } + ResourceRegistryRef resources(); PanelRegistry& panels() { return this->panelRegistry; } UI& ui() { return this->_ui; } @@ -62,7 +62,7 @@ class Application { /** * Chooses where the scene is rendered. An invalid handle (the default) means * the swapchain; a target created with - * ResourceRegistry::create() redirects it offscreen, and the + * ResourceRegistryRef::create() redirects it offscreen, and the * swapchain then only receives the UI. FrameInfo::currentFramebufferExtent * and the camera projection follow the target's size. */ @@ -77,7 +77,6 @@ class Application { class Impl; std::unique_ptr impl; - ResourceRegistry resourceRegistry; PanelRegistry panelRegistry; UI _ui; diff --git a/engine/include/sophia/components.hpp b/engine/include/sophia/components.hpp index 76c783b..ac37353 100644 --- a/engine/include/sophia/components.hpp +++ b/engine/include/sophia/components.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #define GLM_FORCE_RADIANS diff --git a/engine/include/sophia/handles.hpp b/engine/include/sophia/handles.hpp index cd27a6a..acee081 100644 --- a/engine/include/sophia/handles.hpp +++ b/engine/include/sophia/handles.hpp @@ -27,9 +27,11 @@ struct Handle { struct MeshTag {}; struct PanelTag {}; struct RenderTargetTag {}; +struct SceneTag {}; using MeshHandle = Handle; using PanelHandle = Handle; using RenderTargetHandle = Handle; +using SceneHandle = Handle; } // namespace sophia diff --git a/engine/include/sophia/resource_registry.hpp b/engine/include/sophia/resource_registry_ref.hpp similarity index 55% rename from engine/include/sophia/resource_registry.hpp rename to engine/include/sophia/resource_registry_ref.hpp index c22657c..5823b63 100644 --- a/engine/include/sophia/resource_registry.hpp +++ b/engine/include/sophia/resource_registry_ref.hpp @@ -1,25 +1,23 @@ #pragma once -#include +#include #include +#include #include #include #include #include -#include "sophia/canvas.hpp" -#include "sophia/types.hpp" - #define GLM_FORCE_RADIANS #define GLM_FORCE_DEPTH_ZERO_TO_ONE #include namespace sophia { -class Device; class Mesh; class RenderTarget; -class ImGuiRenderer; +class Scene; +class ResourceRegistry; template struct ResourceTraits; @@ -34,13 +32,13 @@ struct ResourceTraits { using Handle = RenderTargetHandle; }; -class ResourceRegistry { +template <> +struct ResourceTraits { + using Handle = SceneHandle; +}; + +class ResourceRegistryRef { public: - ~ResourceRegistry(); - - ResourceRegistry(const ResourceRegistry&) = delete; - ResourceRegistry& operator=(const ResourceRegistry&) = delete; - template typename ResourceTraits::Handle load(const std::string& path); @@ -54,21 +52,16 @@ class ResourceRegistry { glm::vec2 getExtent(RenderTargetHandle handle) const; bool isAlive(RenderTargetHandle handle) const; + bool isAlive(SceneHandle handle) const; - /** - * Waits for the GPU to go idle, so don't call this every frame. Don't release - * the target the scene is currently rendering into. - */ template void release(typename ResourceTraits::Handle handle); private: friend class Application; - friend class ImGuiRenderer; - // `renderTargetFormat` is a VkFormat value; it must match the color format - // the scene pipelines are built against. - ResourceRegistry(Device& device, u32 renderTargetFormat); + explicit ResourceRegistryRef(ResourceRegistry& registry) + : registry{®istry} {} MeshHandle createResource(std::type_identity, std::vector vertices, @@ -77,27 +70,21 @@ class ResourceRegistry { RenderTargetHandle createResource(std::type_identity, u32 width = 1, u32 height = 1); - RenderTarget& getRenderTarget(RenderTargetHandle handle); - const RenderTarget& getRenderTarget(RenderTargetHandle handle) const; - void applyPendingResizes(); + SceneHandle createResource(std::type_identity); - template - const T& get(typename ResourceTraits::Handle handle) const; - - class Impl; - std::unique_ptr impl; + ResourceRegistry* registry; }; template <> -MeshHandle ResourceRegistry::load(const std::string& path); +MeshHandle ResourceRegistryRef::load(const std::string& path); template <> -void ResourceRegistry::release(MeshHandle handle); +void ResourceRegistryRef::release(MeshHandle handle); template <> -void ResourceRegistry::release(RenderTargetHandle handle); +void ResourceRegistryRef::release(RenderTargetHandle handle); template <> -const Mesh& ResourceRegistry::get(MeshHandle handle) const; +void ResourceRegistryRef::release(SceneHandle handle); } // namespace sophia diff --git a/engine/include/sophia/ui/ui.hpp b/engine/include/sophia/ui/ui.hpp index 17d419a..9db7074 100644 --- a/engine/include/sophia/ui/ui.hpp +++ b/engine/include/sophia/ui/ui.hpp @@ -3,11 +3,11 @@ #include #include +#include namespace sophia { class ImGuiRenderer; -class ResourceRegistry; class UI { public: @@ -31,9 +31,9 @@ class UI { private: friend class Application; - explicit UI(ResourceRegistry& resources) : resources{resources} {} + explicit UI(ResourceRegistryRef resources) : resources{resources} {} - ResourceRegistry& resources; + ResourceRegistryRef resources; ImGuiRenderer* renderer = nullptr; }; diff --git a/engine/src/imgui_renderer.cpp b/engine/src/imgui_renderer.cpp index 89b169f..de739d9 100644 --- a/engine/src/imgui_renderer.cpp +++ b/engine/src/imgui_renderer.cpp @@ -92,7 +92,7 @@ void ImGuiRenderer::beginFrame() { ImTextureID ImGuiRenderer::getTextureId(RenderTargetHandle handle) { vk::ImageView view = - std::as_const(resources).getRenderTarget(handle).getImage().getView(); + resources.renderTargetPool.get(handle).getImage().getView(); auto it = textures.find(handle.index); if (it != textures.end()) { @@ -116,10 +116,11 @@ ImTextureID ImGuiRenderer::getTextureId(RenderTargetHandle handle) { void ImGuiRenderer::releaseStaleTextures() { for (auto it = textures.begin(); it != textures.end();) { RenderTargetHandle handle{it->first, it->second.generation}; + RenderTargetPool& renderTargetPool = resources.renderTargetPool; + bool stale = - !resources.isAlive(handle) || - std::as_const(resources).getRenderTarget(handle).getImage().getView() != - it->second.view; + !renderTargetPool.isAlive(handle) || + renderTargetPool.get(handle).getImage().getView() != it->second.view; if (stale) { ImGui_ImplVulkan_RemoveTexture(it->second.descriptorSet); it = textures.erase(it); diff --git a/engine/src/imgui_renderer.hpp b/engine/src/imgui_renderer.hpp index 3fe3273..cfc79a1 100644 --- a/engine/src/imgui_renderer.hpp +++ b/engine/src/imgui_renderer.hpp @@ -3,12 +3,12 @@ #include #include -#include #include #include #include #include "device.hpp" +#include "resources/resource_registry.hpp" #include "window.hpp" namespace sophia { diff --git a/engine/src/mesh.hpp b/engine/src/mesh.hpp index d800dd7..f25f7db 100644 --- a/engine/src/mesh.hpp +++ b/engine/src/mesh.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include diff --git a/engine/src/resources/pools/mesh_pool.cpp b/engine/src/resources/pools/mesh_pool.cpp deleted file mode 100644 index 36ce528..0000000 --- a/engine/src/resources/pools/mesh_pool.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "resources/pools/mesh_pool.hpp" - -#include - -namespace sophia { - -namespace { -constexpr u32 GENERATION_MASK = (1u << 12) - 1; -} // namespace - -MeshPool::MeshPool(Device& device) : device{device} {} - -MeshPool::~MeshPool() = default; - -MeshHandle MeshPool::create(const Mesh::Builder& builder) { - auto mesh = std::make_unique(device, builder); - - if (!freeList.empty()) { - u32 index = freeList.back(); - freeList.pop_back(); - slots[index].mesh = std::move(mesh); - return MeshHandle{index, slots[index].generation}; - } - - slots.push_back(Slot{std::move(mesh), 0}); - return MeshHandle{static_cast(slots.size() - 1), 0}; -} - -const Mesh& MeshPool::get(MeshHandle handle) const { - SOPHIA_ASSERT(handle.isValid(), "invalid MeshHandle"); - SOPHIA_ASSERT(handle.index < slots.size(), - "MeshHandle index out of range:", handle.index); - - const Slot& slot = slots[handle.index]; - SOPHIA_ASSERT(slot.generation == handle.generation, - "stale MeshHandle (generation mismatch):", handle.index); - SOPHIA_ASSERT(slot.mesh != nullptr, - "MeshHandle refers to a released mesh:", handle.index); - return *slot.mesh; -} - -void MeshPool::release(MeshHandle handle) { - SOPHIA_ASSERT(handle.isValid(), "invalid MeshHandle"); - SOPHIA_ASSERT(handle.index < slots.size(), - "MeshHandle index out of range:", handle.index); - - Slot& slot = slots[handle.index]; - SOPHIA_ASSERT(slot.generation == handle.generation, - "stale MeshHandle (generation mismatch):", handle.index); - SOPHIA_ASSERT(slot.mesh != nullptr, - "MeshHandle already released:", handle.index); - - slot.mesh.reset(); - slot.generation = (slot.generation + 1) & GENERATION_MASK; - freeList.push_back(handle.index); -} - -} // namespace sophia diff --git a/engine/src/resources/pools/mesh_pool.hpp b/engine/src/resources/pools/mesh_pool.hpp deleted file mode 100644 index 218f0bb..0000000 --- a/engine/src/resources/pools/mesh_pool.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include - -#include "device.hpp" -#include "mesh.hpp" - -namespace sophia { - -class MeshPool { - public: - explicit MeshPool(Device& device); - ~MeshPool(); - - MeshPool(const MeshPool&) = delete; - MeshPool& operator=(const MeshPool&) = delete; - - MeshHandle create(const Mesh::Builder& builder); - const Mesh& get(MeshHandle handle) const; - void release(MeshHandle handle); - - private: - struct Slot { - std::unique_ptr mesh; - u32 generation = 0; - }; - - Device& device; - - std::vector slots; - std::vector freeList; -}; - -} // namespace sophia diff --git a/engine/src/resources/pools/pool.hpp b/engine/src/resources/pools/pool.hpp new file mode 100644 index 0000000..99669bd --- /dev/null +++ b/engine/src/resources/pools/pool.hpp @@ -0,0 +1,90 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace sophia { + +template +class Pool { + public: + explicit Pool(const char* name) : name{name} {} + + Pool(const Pool&) = delete; + Pool& operator=(const Pool&) = delete; + + template + HandleT create(Args&&... args) { + auto item = std::make_unique(std::forward(args)...); + + if (!freeList.empty()) { + u32 index = freeList.back(); + freeList.pop_back(); + slots[index].item = std::move(item); + return HandleT{index, slots[index].generation}; + } + + slots.push_back(Slot{std::move(item), 0}); + return HandleT{static_cast(slots.size() - 1), 0}; + } + + T& get(HandleT handle) { + return const_cast(std::as_const(*this).get(handle)); + } + + const T& get(HandleT handle) const { return *validate(handle).item; } + + void release(HandleT handle) { + validate(handle); + + Slot& slot = slots[handle.index]; + slot.item.reset(); + slot.generation = (slot.generation + 1) & GENERATION_MASK; + freeList.push_back(handle.index); + } + + bool isAlive(HandleT handle) const { + return handle.isValid() && handle.index < slots.size() && + slots[handle.index].generation == handle.generation && + slots[handle.index].item != nullptr; + } + + template + void forEach(Fn&& fn) { + for (Slot& slot : slots) { + if (slot.item) { + fn(*slot.item); + } + } + } + + private: + static constexpr u32 GENERATION_MASK = (1u << 12) - 1; + + struct Slot { + std::unique_ptr item; + u32 generation = 0; + }; + + const Slot& validate(HandleT handle) const { + SOPHIA_ASSERT(handle.isValid(), "invalid handle:", name); + SOPHIA_ASSERT(handle.index < slots.size(), name, + "handle index out of range:", handle.index); + + const Slot& slot = slots[handle.index]; + SOPHIA_ASSERT(slot.generation == handle.generation, "stale", name, + "handle (generation mismatch):", handle.index); + SOPHIA_ASSERT(slot.item != nullptr, name, + "handle refers to a released item:", handle.index); + return slot; + } + + const char* name; + std::vector slots; + std::vector freeList; +}; + +} // namespace sophia diff --git a/engine/src/resources/pools/render_target_pool.cpp b/engine/src/resources/pools/render_target_pool.cpp index f0c0d41..fb3ee70 100644 --- a/engine/src/resources/pools/render_target_pool.cpp +++ b/engine/src/resources/pools/render_target_pool.cpp @@ -1,81 +1,22 @@ #include "resources/pools/render_target_pool.hpp" -#include -#include - namespace sophia { -namespace { -constexpr u32 GENERATION_MASK = (1u << 12) - 1; -} // namespace - RenderTargetPool::RenderTargetPool(Device& device, vk::Format format) : device{device}, format{format} {} -RenderTargetPool::~RenderTargetPool() = default; - RenderTargetHandle RenderTargetPool::create(u32 width, u32 height) { - auto target = std::make_unique(device, format, width, height); - - if (!freeList.empty()) { - u32 index = freeList.back(); - freeList.pop_back(); - slots[index].target = std::move(target); - return RenderTargetHandle{index, slots[index].generation}; - } - - slots.push_back(Slot{std::move(target), 0}); - return RenderTargetHandle{static_cast(slots.size() - 1), 0}; -} - -const RenderTargetPool::Slot& RenderTargetPool::validate( - RenderTargetHandle handle) const { - SOPHIA_ASSERT(handle.isValid(), "invalid RenderTargetHandle"); - SOPHIA_ASSERT(handle.index < slots.size(), - "RenderTargetHandle index out of range:", handle.index); - - const Slot& slot = slots[handle.index]; - SOPHIA_ASSERT( - slot.generation == handle.generation, - "stale RenderTargetHandle (generation mismatch):", handle.index); - SOPHIA_ASSERT( - slot.target != nullptr, - "RenderTargetHandle refers to a released target:", handle.index); - return slot; -} - -RenderTarget& RenderTargetPool::get(RenderTargetHandle handle) { - return const_cast(std::as_const(*this).get(handle)); -} - -const RenderTarget& RenderTargetPool::get(RenderTargetHandle handle) const { - return *validate(handle).target; + return pool.create(device, format, width, height); } void RenderTargetPool::release(RenderTargetHandle handle) { - validate(handle); - - // Earlier frames may still be rendering into or sampling the target. + SOPHIA_ASSERT(pool.isAlive(handle), "invalid RenderTargetHandle"); device.waitIdle(); - - Slot& slot = slots[handle.index]; - slot.target.reset(); - slot.generation = (slot.generation + 1) & GENERATION_MASK; - freeList.push_back(handle.index); -} - -bool RenderTargetPool::isAlive(RenderTargetHandle handle) const { - return handle.isValid() && handle.index < slots.size() && - slots[handle.index].generation == handle.generation && - slots[handle.index].target != nullptr; + pool.release(handle); } void RenderTargetPool::applyPendingResizes() { - for (Slot& slot : slots) { - if (slot.target) { - slot.target->applyPendingResize(); - } - } + pool.forEach([](RenderTarget& target) { target.applyPendingResize(); }); } } // namespace sophia diff --git a/engine/src/resources/pools/render_target_pool.hpp b/engine/src/resources/pools/render_target_pool.hpp index 5e8055c..ff7ca0f 100644 --- a/engine/src/resources/pools/render_target_pool.hpp +++ b/engine/src/resources/pools/render_target_pool.hpp @@ -1,44 +1,36 @@ #pragma once -#include #include -#include #include "device.hpp" #include "render_target.hpp" +#include "resources/pools/pool.hpp" namespace sophia { class RenderTargetPool { public: RenderTargetPool(Device& device, vk::Format format); - ~RenderTargetPool(); RenderTargetPool(const RenderTargetPool&) = delete; RenderTargetPool& operator=(const RenderTargetPool&) = delete; RenderTargetHandle create(u32 width, u32 height); - RenderTarget& get(RenderTargetHandle handle); - const RenderTarget& get(RenderTargetHandle handle) const; + RenderTarget& get(RenderTargetHandle handle) { return pool.get(handle); } + const RenderTarget& get(RenderTargetHandle handle) const { + return pool.get(handle); + } void release(RenderTargetHandle handle); - bool isAlive(RenderTargetHandle handle) const; + bool isAlive(RenderTargetHandle handle) const { return pool.isAlive(handle); } void applyPendingResizes(); private: - struct Slot { - std::unique_ptr target; - u32 generation = 0; - }; - - const Slot& validate(RenderTargetHandle handle) const; - Device& device; vk::Format format; - std::vector slots; - std::vector freeList; + Pool pool{"RenderTarget"}; }; } // namespace sophia diff --git a/engine/src/resources/resource_registry.cpp b/engine/src/resources/resource_registry.cpp deleted file mode 100644 index 1f72aed..0000000 --- a/engine/src/resources/resource_registry.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#include -#include - -#include "mesh.hpp" -#include "pools/mesh_pool.hpp" -#include "pools/render_target_pool.hpp" -#include "render_target.hpp" - -namespace sophia { - -class ResourceRegistry::Impl { - public: - Impl(Device& device, vk::Format renderTargetFormat) - : meshPool{device}, renderTargetPool{device, renderTargetFormat} {} - - MeshPool meshPool; - RenderTargetPool renderTargetPool; - // TexturePool texturePool; - // MaterialPool materialPool; -}; - -ResourceRegistry::ResourceRegistry(Device& device, u32 renderTargetFormat) - : impl{std::make_unique( - device, static_cast(renderTargetFormat))} {} - -ResourceRegistry::~ResourceRegistry() = default; - -template <> -MeshHandle ResourceRegistry::load(const std::string& path) { - (void)path; - SOPHIA_ASSERT(false, - "Mesh::load(path) is not implemented yet - no model file " - "format is supported; build one via Mesh::Builder for now"); - return MeshHandle{}; -} - -template -typename ResourceTraits::Handle load(const std::string&) { - static_assert(sizeof(T) == 0, - "load is not implemented for this resource type"); -} - -template <> -void ResourceRegistry::release(MeshHandle handle) { - impl->meshPool.release(handle); -} - -template <> -void ResourceRegistry::release(RenderTargetHandle handle) { - impl->renderTargetPool.release(handle); -} - -template <> -const Mesh& ResourceRegistry::get(MeshHandle handle) const { - return impl->meshPool.get(handle); -} - -MeshHandle ResourceRegistry::createResource(std::type_identity, - std::vector vertices, - std::vector indices) { - Mesh::Builder builder{}; - builder.vertices.reserve(vertices.size()); - for (const CanvasVertex& vertex : vertices) { - builder.vertices.push_back({vertex.position, vertex.color}); - } - builder.indices = std::move(indices); - - return impl->meshPool.create(builder); -} - -RenderTargetHandle ResourceRegistry::createResource( - std::type_identity, u32 width, u32 height) { - return impl->renderTargetPool.create(width, height); -} - -void ResourceRegistry::requestResize(RenderTargetHandle handle, u32 width, - u32 height) { - impl->renderTargetPool.get(handle).requestResize(width, height); -} - -glm::vec2 ResourceRegistry::getExtent(RenderTargetHandle handle) const { - vk::Extent2D extent = - std::as_const(impl->renderTargetPool).get(handle).getExtent(); - return {static_cast(extent.width), static_cast(extent.height)}; -} - -bool ResourceRegistry::isAlive(RenderTargetHandle handle) const { - return impl->renderTargetPool.isAlive(handle); -} - -RenderTarget& ResourceRegistry::getRenderTarget(RenderTargetHandle handle) { - return impl->renderTargetPool.get(handle); -} - -const RenderTarget& ResourceRegistry::getRenderTarget( - RenderTargetHandle handle) const { - return std::as_const(impl->renderTargetPool).get(handle); -} - -void ResourceRegistry::applyPendingResizes() { - impl->renderTargetPool.applyPendingResizes(); -} - -} // namespace sophia diff --git a/engine/src/resources/resource_registry.hpp b/engine/src/resources/resource_registry.hpp new file mode 100644 index 0000000..6dc5629 --- /dev/null +++ b/engine/src/resources/resource_registry.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +#include "device.hpp" +#include "mesh.hpp" +#include "resources/pools/pool.hpp" +#include "resources/pools/render_target_pool.hpp" +#include "scene.hpp" + +namespace sophia { + +class ResourceRegistry { + public: + ResourceRegistry(const ResourceRegistry&) = delete; + ResourceRegistry& operator=(const ResourceRegistry&) = delete; + + ResourceRegistry(Device& device, vk::Format renderTargetFormat) + : device{device}, renderTargetPool{device, renderTargetFormat} {} + + Device& device; + Pool meshPool{"Mesh"}; + RenderTargetPool renderTargetPool; + Pool scenePool{"Scene"}; + // TexturePool textures; + // MaterialPool materials; +}; + +} // namespace sophia diff --git a/engine/src/resources/resource_registry_ref.cpp b/engine/src/resources/resource_registry_ref.cpp new file mode 100644 index 0000000..5e24d7b --- /dev/null +++ b/engine/src/resources/resource_registry_ref.cpp @@ -0,0 +1,72 @@ +#include +#include + +#include "resources/resource_registry.hpp" + +namespace sophia { + +template <> +MeshHandle ResourceRegistryRef::load(const std::string& path) { + (void)path; + SOPHIA_ASSERT(false, + "Mesh::load(path) is not implemented yet - no model file " + "format is supported; build one via Mesh::Builder for now"); + return MeshHandle{}; +} + +template <> +void ResourceRegistryRef::release(MeshHandle handle) { + registry->meshPool.release(handle); +} + +template <> +void ResourceRegistryRef::release(RenderTargetHandle handle) { + registry->renderTargetPool.release(handle); +} + +template <> +void ResourceRegistryRef::release(SceneHandle handle) { + registry->scenePool.release(handle); +} + +MeshHandle ResourceRegistryRef::createResource( + std::type_identity, std::vector vertices, + std::vector indices) { + Mesh::Builder builder{}; + builder.vertices.reserve(vertices.size()); + for (const CanvasVertex& vertex : vertices) { + builder.vertices.push_back({vertex.position, vertex.color}); + } + builder.indices = std::move(indices); + + return registry->meshPool.create(registry->device, builder); +} + +RenderTargetHandle ResourceRegistryRef::createResource( + std::type_identity, u32 width, u32 height) { + return registry->renderTargetPool.create(width, height); +} + +SceneHandle ResourceRegistryRef::createResource(std::type_identity) { + return registry->scenePool.create(); +} + +void ResourceRegistryRef::requestResize(RenderTargetHandle handle, u32 width, + u32 height) { + registry->renderTargetPool.get(handle).requestResize(width, height); +} + +glm::vec2 ResourceRegistryRef::getExtent(RenderTargetHandle handle) const { + vk::Extent2D extent = registry->renderTargetPool.get(handle).getExtent(); + return {static_cast(extent.width), static_cast(extent.height)}; +} + +bool ResourceRegistryRef::isAlive(RenderTargetHandle handle) const { + return registry->renderTargetPool.isAlive(handle); +} + +bool ResourceRegistryRef::isAlive(SceneHandle handle) const { + return registry->scenePool.isAlive(handle); +} + +} // namespace sophia diff --git a/engine/src/ui/ui.cpp b/engine/src/ui/ui.cpp index 5d18f70..8a08da7 100644 --- a/engine/src/ui/ui.cpp +++ b/engine/src/ui/ui.cpp @@ -1,4 +1,3 @@ -#include #include #include