From 0d145f615d404abbfde19fde54af608e57a1def0 Mon Sep 17 00:00:00 2001 From: Caleb Burke Date: Fri, 25 Sep 2026 20:22:29 -0700 Subject: [PATCH] changes --- engine/include/sophia/util/pool.hpp | 11 ++++++++ engine/src/rendering/render_graph.cpp | 11 +++++++- engine/src/rendering/render_graph.hpp | 4 ++- engine/src/rendering/scene_renderer.cpp | 12 ++++++--- engine/src/rendering/scene_renderer.hpp | 11 ++++---- engine/src/resources/render_target.cpp | 2 +- engine/src/vulkan/debug_label.cpp | 34 +++++++++++++++++++++++++ engine/src/vulkan/debug_label.hpp | 13 ++++++++++ engine/src/vulkan/device.cpp | 4 +++ testbed/main.cpp | 14 +++++++--- 10 files changed, 100 insertions(+), 16 deletions(-) create mode 100644 engine/src/vulkan/debug_label.cpp create mode 100644 engine/src/vulkan/debug_label.hpp diff --git a/engine/include/sophia/util/pool.hpp b/engine/include/sophia/util/pool.hpp index 083aa95..6ab2416 100644 --- a/engine/include/sophia/util/pool.hpp +++ b/engine/include/sophia/util/pool.hpp @@ -75,6 +75,17 @@ class Pool { } } + /** Calls `fn(handle, item)` for every live item. */ + template + void forEachWithHandle(Fn&& fn) const { + for (u32 index = 0; index < slots.size(); index++) { + const Slot& slot = slots[index]; + if (slot.item) { + fn(Handle{index, slot.generation}, *slot.item); + } + } + } + template T* findIf(Predicate&& predicate) { return const_cast( diff --git a/engine/src/rendering/render_graph.cpp b/engine/src/rendering/render_graph.cpp index b9a1e60..b15d6b6 100644 --- a/engine/src/rendering/render_graph.cpp +++ b/engine/src/rendering/render_graph.cpp @@ -3,6 +3,8 @@ #include #include +#include "vulkan/debug_label.hpp" + namespace sophia { ImageRef RenderGraph::importImage(Image& image, Access finalAccess) { @@ -74,6 +76,8 @@ void RenderGraph::flush(vk::CommandBuffer commandBuffer, } void RenderGraph::recordPass(vk::CommandBuffer commandBuffer, Pass& pass) { + beginDebugLabel(commandBuffer, pass.name.c_str()); + PendingBarriers pending; for (const ImageUse& use : pass.uses) { this->transitionTo(use.image, getAccessState(use.access), pending); @@ -82,9 +86,14 @@ void RenderGraph::recordPass(vk::CommandBuffer commandBuffer, Pass& pass) { if (pass.colorAttachments.empty()) { pass.execute(commandBuffer); - return; + } else { + this->recordRendering(commandBuffer, pass); } + endDebugLabel(commandBuffer); +} + +void RenderGraph::recordRendering(vk::CommandBuffer commandBuffer, Pass& pass) { std::vector attachments; attachments.reserve(pass.colorAttachments.size()); diff --git a/engine/src/rendering/render_graph.hpp b/engine/src/rendering/render_graph.hpp index d7374e3..ff2cd32 100644 --- a/engine/src/rendering/render_graph.hpp +++ b/engine/src/rendering/render_graph.hpp @@ -67,7 +67,8 @@ class RenderGraph { /** * Adds a pass. `setup` runs immediately and declares what the pass does to * images; `execute` runs later, from execute(), with the barriers already - * recorded and (if the pass writes color) rendering begun. + * recorded and (if the pass writes color) rendering begun. `name` labels + * the pass's commands in debugging tools such as RenderDoc. */ void addPass(std::string name, const SetupFn& setup, ExecuteFn execute); @@ -112,6 +113,7 @@ class RenderGraph { PendingBarriers& pending); void flush(vk::CommandBuffer commandBuffer, PendingBarriers& pending); void recordPass(vk::CommandBuffer commandBuffer, Pass& pass); + void recordRendering(vk::CommandBuffer commandBuffer, Pass& pass); std::vector images; std::vector passes; diff --git a/engine/src/rendering/scene_renderer.cpp b/engine/src/rendering/scene_renderer.cpp index dea107d..fc1e8be 100644 --- a/engine/src/rendering/scene_renderer.cpp +++ b/engine/src/rendering/scene_renderer.cpp @@ -12,13 +12,17 @@ struct PushConstantData { }; } // namespace -SceneRenderer::SceneRenderer(ResourceRegistry& resources) - : resources{resources} {} +SceneRenderer::SceneRenderer(const SceneRegistry& sceneRegistry, + ResourceRegistry& resources) + : sceneRegistry{sceneRegistry}, resources{resources} {} SceneRenderer::~SceneRenderer() {} -void SceneRenderer::render(const Scene& scene, Entity camera, - RenderTargetHandle target) { +void SceneRenderer::render(SceneView sceneView) { + auto& handle = sceneView.scene; + auto& scene = this->sceneRegistry.get(handle); + + auto& camera = sceneView.camera; SOPHIA_ASSERT(camera.hasComponent(), "camera does not have camera component!"); diff --git a/engine/src/rendering/scene_renderer.hpp b/engine/src/rendering/scene_renderer.hpp index 0eaf29c..abaf69b 100644 --- a/engine/src/rendering/scene_renderer.hpp +++ b/engine/src/rendering/scene_renderer.hpp @@ -1,9 +1,8 @@ #pragma once -#include -#include +#include +#include -#include "entity.hpp" #include "resources/resource_registry.hpp" namespace sophia { @@ -16,12 +15,14 @@ class SceneRenderer { SceneRenderer(const SceneRenderer&) = delete; SceneRenderer& operator=(const SceneRenderer&) = delete; - SceneRenderer(ResourceRegistry& resources); + SceneRenderer(const SceneRegistry& sceneRegistry, + ResourceRegistry& resources); ~SceneRenderer(); - void render(const Scene& scene, Entity camera, RenderTargetHandle target); + void render(SceneView sceneView); private: + const SceneRegistry& sceneRegistry; ResourceRegistry& resources; }; diff --git a/engine/src/resources/render_target.cpp b/engine/src/resources/render_target.cpp index 0005943..b4e81e1 100644 --- a/engine/src/resources/render_target.cpp +++ b/engine/src/resources/render_target.cpp @@ -32,8 +32,8 @@ void RenderTarget::applyPendingResize() { return; } - // Earlier frames may still be sampling the old image (e.g. through the UI). this->device.waitIdle(); + destroy(); create(extent.width, extent.height); } diff --git a/engine/src/vulkan/debug_label.cpp b/engine/src/vulkan/debug_label.cpp new file mode 100644 index 0000000..3d44e45 --- /dev/null +++ b/engine/src/vulkan/debug_label.cpp @@ -0,0 +1,34 @@ +#include "vulkan/debug_label.hpp" + +namespace sophia { + +static PFN_vkCmdBeginDebugUtilsLabelEXT cmdBeginDebugUtilsLabel = nullptr; +static PFN_vkCmdEndDebugUtilsLabelEXT cmdEndDebugUtilsLabel = nullptr; + +void loadDebugLabelFunctions(vk::Instance instance) { + cmdBeginDebugUtilsLabel = reinterpret_cast( + vkGetInstanceProcAddr(instance, "vkCmdBeginDebugUtilsLabelEXT")); + cmdEndDebugUtilsLabel = reinterpret_cast( + vkGetInstanceProcAddr(instance, "vkCmdEndDebugUtilsLabelEXT")); +} + +void beginDebugLabel(vk::CommandBuffer commandBuffer, const char* name) { + if (!cmdBeginDebugUtilsLabel) { + return; + } + + VkDebugUtilsLabelEXT label{}; + label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; + label.pLabelName = name; + cmdBeginDebugUtilsLabel(commandBuffer, &label); +} + +void endDebugLabel(vk::CommandBuffer commandBuffer) { + if (!cmdEndDebugUtilsLabel) { + return; + } + + cmdEndDebugUtilsLabel(commandBuffer); +} + +} // namespace sophia diff --git a/engine/src/vulkan/debug_label.hpp b/engine/src/vulkan/debug_label.hpp new file mode 100644 index 0000000..95401c4 --- /dev/null +++ b/engine/src/vulkan/debug_label.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include + +namespace sophia { + +void loadDebugLabelFunctions(vk::Instance instance); + +void beginDebugLabel(vk::CommandBuffer commandBuffer, const char* name); + +void endDebugLabel(vk::CommandBuffer commandBuffer); + +} // namespace sophia diff --git a/engine/src/vulkan/device.cpp b/engine/src/vulkan/device.cpp index 742f15b..2e8fc9c 100644 --- a/engine/src/vulkan/device.cpp +++ b/engine/src/vulkan/device.cpp @@ -5,6 +5,8 @@ #include #include +#include "vulkan/debug_label.hpp" + namespace sophia { static VKAPI_ATTR vk::Bool32 VKAPI_CALL @@ -288,6 +290,8 @@ void Device::setupDebugMessenger() { nullptr, &this->debugMessenger) != VK_SUCCESS) { throw std::runtime_error("failed to set up debug callback!"); } + + loadDebugLabelFunctions(*instance); } bool Device::checkValidationLayerSupport() { diff --git a/testbed/main.cpp b/testbed/main.cpp index dd39c5a..453c229 100644 --- a/testbed/main.cpp +++ b/testbed/main.cpp @@ -1,7 +1,9 @@ #include #include +#include #include +#include #include class Viewport : public sophia::Panel { @@ -25,11 +27,15 @@ class Testbed : public sophia::Application { Testbed() : Application{{.width = 750, .height = 1000, .name = "Testbed"}} {} void onCreate() override { - sophia::RenderTargetHandle target = - resources().create(); - setSceneTarget(target); - panels().emplace(ui(), target); + view = views().create({.scene = scenes().create(), + .target = resources().create(), + .clearColor = {0.1f, 0.1f, 0.15f, 1.f}}); + + panels().emplace(ui(), views().get(view).target); } + + private: + sophia::SceneViewHandle view; }; SOPHIA_MAIN(Testbed)