110 lines
4.6 KiB
C++
110 lines
4.6 KiB
C++
/*
|
|
Crafter®.Graphics
|
|
Copyright (C) 2026 Catcrafts®
|
|
catcrafts.net
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License version 3.0 as published by the Free Software Foundation;
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
module;
|
|
#include "vulkan/vulkan.h"
|
|
export module Crafter.Graphics:UIRenderer;
|
|
import std;
|
|
import :Device;
|
|
import :Window;
|
|
import :RenderPass;
|
|
import :DescriptorHeapVulkan;
|
|
import :VulkanBuffer;
|
|
import :SamplerVulkan;
|
|
import :ShaderVulkan;
|
|
import :ImageVulkan;
|
|
import :UIDrawList;
|
|
import :UIAtlas;
|
|
|
|
export namespace Crafter::UI {
|
|
// The compute-pass-side renderer. Owns the compute pipeline, per-frame
|
|
// item buffers, the SDF glyph atlas, and the descriptor-heap slot
|
|
// allocations. Implements RenderPass so it plugs into Window::passes.
|
|
//
|
|
// Lifecycle:
|
|
// - Initialize(window, shaderPath) — once, after the window has a
|
|
// descriptor heap. Allocates slots, creates pipeline, atlas image.
|
|
// - SetItems(span<UIItem>) per frame, before Window::Render runs.
|
|
// - Record(...) — invoked by Window::Render's pass loop.
|
|
class UIRenderer : public RenderPass {
|
|
public:
|
|
// Defaulted bindless slot capacity — covers most game UIs without
|
|
// descriptor heap pressure. Override in Initialize.
|
|
static constexpr std::uint16_t kDefaultBindlessImageCount = 256;
|
|
|
|
FontAtlas atlas;
|
|
|
|
// Initialize. `initCmd` must be a command buffer in recording
|
|
// state — used to transition the atlas image. Window must already
|
|
// have a non-null descriptorHeap with enough free slots for
|
|
// (numFrames + 1 + bindlessImageCount) images, numFrames buffers,
|
|
// and 1 sampler.
|
|
void Initialize(Window& window,
|
|
VkCommandBuffer initCmd,
|
|
const std::filesystem::path& spvPath = "ui.comp.spv",
|
|
std::uint16_t bindlessImageCount = kDefaultBindlessImageCount);
|
|
|
|
// Stage `items` into the next-frame mapped buffer. Must be called
|
|
// BEFORE Window::Render so the buffer is flushed before the
|
|
// dispatch reads it.
|
|
void SetItems(std::span<const UIItem> items);
|
|
|
|
// RenderPass impl — invoked from Window::Render's pass loop.
|
|
void Record(VkCommandBuffer cmd, std::uint32_t frameIdx, Window& window) override;
|
|
|
|
// Heap slot accessors — UIScene reads these to populate DrawList.
|
|
std::uint32_t BindlessBaseHeapIdx() const { return bindlessBase_; }
|
|
FontAtlas& Atlas() { return atlas; }
|
|
|
|
// The frame currently being staged. Window::Render advances
|
|
// `currentBuffer` before passes record; SetItems writes to
|
|
// (currentBuffer + 1) so the previous frame's buffer is still in
|
|
// flight on the GPU. For V1 we ride on Window's currentBuffer
|
|
// directly since vkQueueWaitIdle gates each frame.
|
|
std::uint32_t pendingItemCount = 0;
|
|
|
|
private:
|
|
Window* window_ = nullptr;
|
|
|
|
VkPipeline pipeline_ = VK_NULL_HANDLE;
|
|
|
|
VulkanBuffer<UIItem, true> itemBufs_[Window::numFrames];
|
|
std::uint16_t itemCapacity_ = 0;
|
|
|
|
// Heap slot allocations (resource heap unless noted).
|
|
std::uint16_t outImageBase_ = 0; // images[outImageBase_ + frame] = swapchain view
|
|
std::uint16_t atlasImageSlot_ = 0; // sampled atlas image slot
|
|
std::uint16_t bindlessBase_ = 0; // first user-image slot
|
|
std::uint16_t bindlessCount_ = 0; // user-image slot count
|
|
std::uint16_t itemBufBase_ = 0; // SSBO slot base; per-frame at base + i
|
|
std::uint16_t linearSamplerSlot_ = 0; // sampler heap
|
|
|
|
// Stable VkImageViewCreateInfo for the atlas — descriptor heap
|
|
// writes need a pointer to one, so we keep it on the renderer.
|
|
VkImageViewCreateInfo atlasViewCreateInfo_{};
|
|
|
|
// Helpers.
|
|
void GrowItemBuffersIfNeeded(std::uint32_t needed);
|
|
void WriteSwapchainDescriptors();
|
|
void WriteAtlasDescriptor();
|
|
void WriteSamplerDescriptors();
|
|
void WriteItemBufferDescriptors();
|
|
void CreatePipeline(const std::filesystem::path& spvPath);
|
|
void CreateLinearSampler();
|
|
};
|
|
}
|