/* 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 "../lib/stb_truetype.h" #ifdef CRAFTER_GRAPHICS_RENDERER_VULKAN #include #endif export module Crafter.Graphics:RenderingElement2DVulkan; #ifdef CRAFTER_GRAPHICS_RENDERER_VULKAN import Crafter.Asset; import std; import :Transform2D; import :VulkanBuffer; import :Types; import :Window; import :DescriptorHeapVulkan; export namespace Crafter { struct RenderingElement2DVulkanBase : Transform2D { std::uint16_t index; std::uint16_t bufferX; std::uint16_t bufferY; std::array buffers; RenderingElement2DVulkanBase(Anchor2D anchor) : Transform2D(anchor) { } RenderingElement2DVulkanBase(Anchor2D anchor, std::uint16_t bufferX, std::uint16_t bufferY) : bufferX(bufferX), bufferY(bufferY), Transform2D(anchor) { } RenderingElement2DVulkanBase(Anchor2D anchor, std::uint16_t bufferX, std::uint16_t bufferY, std::array&& buffers) : bufferX(bufferX), bufferY(bufferY), buffers(std::move(buffers)), Transform2D(anchor) { } }; template struct RenderingElement2DVulkan : RenderingElement2DVulkanBase { RenderingElement2DVulkan(Anchor2D anchor, RendertargetBase& target, Transform2D& parent) requires(Owning) : RenderingElement2DVulkanBase(anchor) { GetScale(target, parent); this->bufferX = this->scaled.size.x; this->bufferY = this->scaled.size.y; for(std::uint8_t i = 0; i < Window::numFrames; i++) { buffers[i] = new VulkanBuffer, Mapped>(); static_cast, Mapped>*>(buffers[i])->Create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bufferX * bufferY); } } RenderingElement2DVulkan(Anchor2D anchor, std::uint16_t bufferX, std::uint16_t bufferY) requires(Owning) : RenderingElement2DVulkanBase(anchor, bufferX, bufferY) { for(std::uint8_t i = 0; i < Window::numFrames; i++) { buffers[i] = new VulkanBuffer, Mapped>(); static_cast, Mapped>*>(buffers[i])->Create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bufferX * bufferY); } } RenderingElement2DVulkan(Anchor2D anchor, std::uint16_t bufferX, std::uint16_t bufferY, std::array&& buffers) requires(!Owning) : RenderingElement2DVulkanBase(anchor, bufferX, bufferY, std::move(buffers)) { } RenderingElement2DVulkan(Anchor2D anchor, const std::filesystem::path& assetPath, bool single) requires(Owning && Mapped) : RenderingElement2DVulkanBase(anchor) { TextureAssetInfo info = TextureAsset<_Float16>::LoadInfo(assetPath); this->bufferX = info.sizeX; this->bufferY = info.sizeY; if(single) { buffers[0] = new VulkanBuffer, Mapped>(); static_cast, Mapped>*>(buffers[0])->Create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bufferX * bufferY); for(std::uint8_t i = 1; i < Window::numFrames; i++) { buffers[i] = buffers[0]; } TextureAsset<_Float16>::Load(assetPath, reinterpret_cast<_Float16*>(static_cast, Mapped>*>(buffers[0])->value), this->bufferX, this->bufferY); } else { for(std::uint8_t i = 0; i < Window::numFrames; i++) { buffers[i] = new VulkanBuffer, Mapped>(); static_cast, Mapped>*>(buffers[i])->Create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bufferX * bufferY); } TextureAsset<_Float16>::Load(assetPath, reinterpret_cast<_Float16*>(static_cast, Mapped>*>(buffers[0])->value), this->bufferX, this->bufferY); for(std::uint8_t i = 1; i < Window::numFrames; i++) { std::memcpy(static_cast, Mapped>*>(buffers[i])->value, static_cast, Mapped>*>(buffers[0])->value, this->bufferX * this->bufferY * sizeof(_Float16)); } } } ~RenderingElement2DVulkan() { if constexpr(Owning) { for(VulkanBufferBase* buffer : buffers) { delete static_cast, Mapped>*>(buffer); } } } RenderingElement2DVulkan(RenderingElement2DVulkan&) = delete; RenderingElement2DVulkan& operator=(RenderingElement2DVulkan&) = delete; void UpdatePosition(RendertargetBase& window2, Transform2D& parent) override { RendertargetVulkan& window = static_cast(window2); this->ScaleElement(parent); RenderingElement2DVulkanTransformInfo* val = reinterpret_cast(reinterpret_cast(window.transformBuffer[window.frame].value) + sizeof(RenderingElement2DVulkanTransformInfo)); val[index].scaled = this->scaled; for(Transform2D* child : this->children) { child->UpdatePosition(window, *this); } } void GetScale(RendertargetBase& window, Transform2D& parent) { this->ScaleElement(parent); for(Transform2D* child : this->children) { child->UpdatePosition(window, *this); } } }; } #endif