2026-04-11 18:48:00 +02:00
|
|
|
/*
|
|
|
|
|
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;
|
|
|
|
|
#ifdef CRAFTER_GRAPHICS_RENDERER_VULKAN
|
|
|
|
|
#include <vulkan/vulkan.h>
|
|
|
|
|
#endif
|
|
|
|
|
module Crafter.Graphics:Rendertarget_impl;
|
|
|
|
|
#ifdef CRAFTER_GRAPHICS_RENDERER_VULKAN
|
|
|
|
|
import :Rendertarget;
|
|
|
|
|
import :Window;
|
|
|
|
|
import :DescriptorHeapVulkan;
|
|
|
|
|
import :RenderingElement2DVulkan;
|
|
|
|
|
import std;
|
|
|
|
|
using namespace Crafter;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RendertargetVulkan::RendertargetVulkan(std::uint16_t sizeX, std::uint16_t sizeY) : RendertargetBase(sizeX, sizeY) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-11 23:18:41 +02:00
|
|
|
void RendertargetVulkan::UpdateElements() {
|
2026-04-11 18:48:00 +02:00
|
|
|
elements.clear();
|
2026-04-11 23:22:52 +02:00
|
|
|
std::sort(transform.children.begin(), transform.children.end(), [](Transform2D* a, Transform2D* b){ return a->anchor.z < b->anchor.z; });
|
2026-04-11 18:48:00 +02:00
|
|
|
for(Transform2D* child : transform.children) {
|
|
|
|
|
SetOrderResursive(child);
|
|
|
|
|
}
|
2026-04-11 23:18:41 +02:00
|
|
|
}
|
|
|
|
|
|
2026-04-13 18:36:07 +02:00
|
|
|
void RendertargetVulkan::CreateBuffer(std::uint8_t frame) {
|
2026-04-11 18:48:00 +02:00
|
|
|
transformBuffer[frame].Resize(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, elements.size()+1);
|
|
|
|
|
RenderingElement2DVulkanTransformInfo* val = reinterpret_cast<RenderingElement2DVulkanTransformInfo*>(reinterpret_cast<char*>(transformBuffer[frame].value) + sizeof(RenderingElement2DVulkanTransformInfo));
|
|
|
|
|
std::uint16_t* sizePtr = reinterpret_cast<std::uint16_t*>(transformBuffer[frame].value);
|
|
|
|
|
*sizePtr = static_cast<std::uint16_t>(elements.size());
|
|
|
|
|
for(std::uint16_t i = 0; i < elements.size(); i++) {
|
|
|
|
|
val[i].bufferX = elements[i]->bufferX;
|
|
|
|
|
val[i].bufferY = elements[i]->bufferY;
|
|
|
|
|
}
|
|
|
|
|
transformBuffer[frame].FlushDevice();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RendertargetVulkan::ReorderBuffer(std::uint8_t frame) {
|
|
|
|
|
RenderingElement2DVulkanTransformInfo* val = reinterpret_cast<RenderingElement2DVulkanTransformInfo*>(reinterpret_cast<char*>(transformBuffer[frame].value) + sizeof(RenderingElement2DVulkanTransformInfo));
|
|
|
|
|
for(std::uint16_t i = 0; i < elements.size(); i++) {
|
|
|
|
|
val[i].scaled = elements[i]->scaled;
|
|
|
|
|
val[i].bufferX = elements[i]->bufferX;
|
|
|
|
|
val[i].bufferY = elements[i]->bufferY;
|
|
|
|
|
}
|
2026-04-13 18:36:07 +02:00
|
|
|
transformBuffer[frame].FlushDevice();
|
2026-04-11 18:48:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RendertargetVulkan::WriteDescriptors(std::span<VkResourceDescriptorInfoEXT> infos, std::span<VkHostAddressRangeEXT> ranges, std::uint16_t start, std::uint32_t bufferOffset, DescriptorHeapVulkan& descriptorHeap) {
|
|
|
|
|
VkDeviceAddressRangeKHR transformRanges[Window::numFrames] = {
|
|
|
|
|
{
|
|
|
|
|
.address = transformBuffer[0].address,
|
|
|
|
|
.size = transformBuffer[0].size
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.address = transformBuffer[1].address,
|
|
|
|
|
.size = transformBuffer[1].size
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.address = transformBuffer[2].address,
|
|
|
|
|
.size = transformBuffer[2].size
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for(std::uint8_t i = 0; i < Window::numFrames; i++) {
|
|
|
|
|
ranges[start + i] = {
|
|
|
|
|
.address = descriptorHeap.resourceHeap[i].value + bufferOffset,
|
|
|
|
|
.size = Device::descriptorHeapProperties.bufferDescriptorSize
|
|
|
|
|
};
|
|
|
|
|
infos[start + i] = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT,
|
|
|
|
|
.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
|
|
|
|
.data = { .pAddressRange = &transformRanges[i]}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
start += 3;
|
|
|
|
|
bufferOffset += Device::descriptorHeapProperties.bufferDescriptorSize;
|
|
|
|
|
|
|
|
|
|
std::vector<VkDeviceAddressRangeKHR> bufferRanges(elements.size() * Window::numFrames);
|
|
|
|
|
|
|
|
|
|
std::uint16_t rangeOffset = 0;
|
|
|
|
|
|
|
|
|
|
for(std::uint8_t i2 = 0; i2 < Window::numFrames; i2++) {
|
|
|
|
|
for(std::uint16_t i = 0; i < elements.size(); i++) {
|
|
|
|
|
ranges[start + i] = {
|
|
|
|
|
.address = descriptorHeap.resourceHeap[i2].value + bufferOffset + Device::descriptorHeapProperties.bufferDescriptorSize * i,
|
|
|
|
|
.size = Device::descriptorHeapProperties.bufferDescriptorSize
|
|
|
|
|
};
|
|
|
|
|
infos[start + i] = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT,
|
|
|
|
|
.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
2026-04-11 23:18:41 +02:00
|
|
|
.data = { .pAddressRange = &bufferRanges[i]}
|
2026-04-11 18:48:00 +02:00
|
|
|
};
|
|
|
|
|
bufferRanges[rangeOffset + i] = {
|
|
|
|
|
.address = elements[i]->buffers[i2]->address,
|
|
|
|
|
.size = elements[i]->buffers[i2]->size
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
start += elements.size();
|
|
|
|
|
rangeOffset += elements.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Device::vkWriteResourceDescriptorsEXT(Device::device, start, infos.data(), ranges.data());
|
|
|
|
|
|
|
|
|
|
for(std::uint8_t i = 0; i < Window::numFrames; i++) {
|
|
|
|
|
descriptorHeap.resourceHeap[i].FlushDevice();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RendertargetVulkan::SetOrderResursive(Transform2D* elementTransform) {
|
2026-04-11 23:18:41 +02:00
|
|
|
RenderingElement2DVulkanBase* renderer = dynamic_cast<RenderingElement2DVulkanBase*>(elementTransform);
|
|
|
|
|
if(renderer) {
|
|
|
|
|
renderer->index = elements.size();
|
|
|
|
|
elements.push_back(renderer);
|
|
|
|
|
}
|
2026-04-11 18:48:00 +02:00
|
|
|
std::sort(elementTransform->children.begin(), elementTransform->children.end(), [](Transform2D* a, Transform2D* b){ return a->anchor.z < b->anchor.z; });
|
|
|
|
|
for(Transform2D* childTransform : elementTransform->children) {
|
|
|
|
|
SetOrderResursive(childTransform);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|