From 3fcea6a3d7df289a79d0d31fe29d78dfcba15998 Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Fri, 10 Apr 2026 22:26:15 +0200 Subject: [PATCH] writing ui descriptors --- implementations/Crafter.Graphics-Window.cpp | 8 +- ...Crafter.Graphics-DescriptorHeapVulkan.cppm | 4 +- interfaces/Crafter.Graphics-ImageVulkan.cppm | 2 +- interfaces/Crafter.Graphics-Mesh.cppm | 8 +- .../Crafter.Graphics-PipelineRTVulkan.cppm | 2 +- ...ter.Graphics-RenderingElement2DVulkan.cppm | 80 +++++++++++++++++-- .../Crafter.Graphics-RenderingElement3D.cppm | 6 +- interfaces/Crafter.Graphics-VulkanBuffer.cppm | 67 +++++----------- 8 files changed, 108 insertions(+), 69 deletions(-) diff --git a/implementations/Crafter.Graphics-Window.cpp b/implementations/Crafter.Graphics-Window.cpp index 103d220..7b795ad 100644 --- a/implementations/Crafter.Graphics-Window.cpp +++ b/implementations/Crafter.Graphics-Window.cpp @@ -821,9 +821,9 @@ void Window::Render() { .sType = VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT, .heapRange = { .address = descriptorHeap->resourceHeap[currentBuffer].address, - .size = static_cast(descriptorHeap->resourceHeap[currentBuffer].descriptor.range) + .size = static_cast(descriptorHeap->resourceHeap[currentBuffer].size) }, - .reservedRangeOffset = (descriptorHeap->resourceHeap[currentBuffer].descriptor.range - Device::descriptorHeapProperties.minResourceHeapReservedRange) & ~(Device::descriptorHeapProperties.imageDescriptorAlignment - 1), + .reservedRangeOffset = (descriptorHeap->resourceHeap[currentBuffer].size - Device::descriptorHeapProperties.minResourceHeapReservedRange) & ~(Device::descriptorHeapProperties.imageDescriptorAlignment - 1), .reservedRangeSize = Device::descriptorHeapProperties.minResourceHeapReservedRange }; Device::vkCmdBindResourceHeapEXT(drawCmdBuffers[currentBuffer], &resourceHeapInfo); @@ -832,9 +832,9 @@ void Window::Render() { .sType = VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT, .heapRange = { .address = descriptorHeap->samplerHeap[currentBuffer].address, - .size = static_cast(descriptorHeap->samplerHeap[currentBuffer].descriptor.range) + .size = static_cast(descriptorHeap->samplerHeap[currentBuffer].size) }, - .reservedRangeOffset = descriptorHeap->samplerHeap[currentBuffer].descriptor.range - Device::descriptorHeapProperties.minSamplerHeapReservedRange, + .reservedRangeOffset = descriptorHeap->samplerHeap[currentBuffer].size - Device::descriptorHeapProperties.minSamplerHeapReservedRange, .reservedRangeSize = Device::descriptorHeapProperties.minSamplerHeapReservedRange }; Device::vkCmdBindSamplerHeapEXT(drawCmdBuffers[currentBuffer], &samplerHeapInfo); diff --git a/interfaces/Crafter.Graphics-DescriptorHeapVulkan.cppm b/interfaces/Crafter.Graphics-DescriptorHeapVulkan.cppm index 18627a4..614c19c 100644 --- a/interfaces/Crafter.Graphics-DescriptorHeapVulkan.cppm +++ b/interfaces/Crafter.Graphics-DescriptorHeapVulkan.cppm @@ -31,8 +31,8 @@ import :VulkanBuffer; export namespace Crafter { struct DescriptorHeapVulkan { - VulkanBuffer resourceHeap[Window::numFrames]; - VulkanBuffer samplerHeap[Window::numFrames]; + VulkanBuffer resourceHeap[Window::numFrames]; + VulkanBuffer samplerHeap[Window::numFrames]; std::uint32_t bufferStartOffset; std::uint16_t bufferStartElement; diff --git a/interfaces/Crafter.Graphics-ImageVulkan.cppm b/interfaces/Crafter.Graphics-ImageVulkan.cppm index a8f2672..5ded767 100644 --- a/interfaces/Crafter.Graphics-ImageVulkan.cppm +++ b/interfaces/Crafter.Graphics-ImageVulkan.cppm @@ -37,7 +37,7 @@ export namespace Crafter { std::uint8_t mipLevels; VkImage image; VkDeviceMemory imageMemory; - VulkanBuffer buffer; + VulkanBuffer buffer; VkImageView imageView; VkDescriptorImageInfo descriptor; diff --git a/interfaces/Crafter.Graphics-Mesh.cppm b/interfaces/Crafter.Graphics-Mesh.cppm index 54ab6be..300d8a6 100644 --- a/interfaces/Crafter.Graphics-Mesh.cppm +++ b/interfaces/Crafter.Graphics-Mesh.cppm @@ -32,10 +32,10 @@ export namespace Crafter { #ifdef CRAFTER_GRAPHICS_RENDERER_VULKAN class Mesh { public: - VulkanBuffer scratchBuffer; - VulkanBuffer blasBuffer; - VulkanBuffer, true, true> vertexBuffer; - VulkanBuffer indexBuffer; + VulkanBuffer scratchBuffer; + VulkanBuffer blasBuffer; + VulkanBuffer, true> vertexBuffer; + VulkanBuffer indexBuffer; VkAccelerationStructureGeometryTrianglesDataKHR blasData; VkAccelerationStructureGeometryKHR blas; VkAccelerationStructureKHR accelerationStructure; diff --git a/interfaces/Crafter.Graphics-PipelineRTVulkan.cppm b/interfaces/Crafter.Graphics-PipelineRTVulkan.cppm index c24b7d9..ac34b11 100644 --- a/interfaces/Crafter.Graphics-PipelineRTVulkan.cppm +++ b/interfaces/Crafter.Graphics-PipelineRTVulkan.cppm @@ -33,7 +33,7 @@ export namespace Crafter { struct PipelineRTVulkan { VkPipeline pipeline; std::vector shaderHandles; - VulkanBuffer sbtBuffer; + VulkanBuffer sbtBuffer; VkStridedDeviceAddressRegionKHR raygenRegion; VkStridedDeviceAddressRegionKHR missRegion; VkStridedDeviceAddressRegionKHR hitRegion; diff --git a/interfaces/Crafter.Graphics-RenderingElement2DVulkan.cppm b/interfaces/Crafter.Graphics-RenderingElement2DVulkan.cppm index e9aaac1..dce5f22 100644 --- a/interfaces/Crafter.Graphics-RenderingElement2DVulkan.cppm +++ b/interfaces/Crafter.Graphics-RenderingElement2DVulkan.cppm @@ -30,6 +30,7 @@ import :Transform2D; import :VulkanBuffer; import :Types; import :Window; +import :DescriptorHeapVulkan; export namespace Crafter { struct __attribute__((packed)) RenderingElement2DVulkanTransformInfo { @@ -43,32 +44,35 @@ export namespace Crafter { std::uint16_t index; std::uint16_t bufferX; std::uint16_t bufferY; + std::array buffers; 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) { + } }; std::vector renderingElement2DVulkans; - VulkanBuffer renderingElement2DVulkanTransformBuffer[Window::numFrames]; + VulkanBuffer renderingElement2DVulkanTransformBuffer[Window::numFrames]; template struct RenderingElement2DVulkan : RenderingElement2DVulkanBase { - std::array, Mapped, true>*, Window::numFrames> buffers; RenderingElement2DVulkan(Anchor2D anchor, std::uint16_t bufferX, std::uint16_t bufferY) requires(Owning) : RenderingElement2DVulkanBase(anchor, bufferX, bufferY) { renderingElement2DVulkans.push_back(this); for(std::uint8_t i = 0; i < Window::numFrames; i++) { - buffers[i] = new VulkanBuffer, Mapped, true>(); - 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); + buffers[i] = new VulkanBuffer, Mapped>(); + reinterpret_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*, Window::numFrames> buffers) requires(!Owning) : buffers(buffers), RenderingElement2DVulkanBase(anchor, 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)) { renderingElement2DVulkans.push_back(this); } ~RenderingElement2DVulkan() { if constexpr(Owning) { - for(VulkanBuffer, Mapped, true>* buffer : buffers) { - delete buffer; + for(VulkanBufferBase* buffer : buffers) { + delete reinterpret_cast, Mapped>*>(buffer); } } auto it = std::find(renderingElement2DVulkans.begin(), renderingElement2DVulkans.end(), this); @@ -90,6 +94,68 @@ export namespace Crafter { } }; + void WriteRenderingElement2DVulkanDescriptors(std::span infos, std::span ranges, std::uint16_t start, std::uint32_t bufferOffset, DescriptorHeapVulkan& descriptorHeap) { + VkDeviceAddressRangeKHR transformRanges[Window::numFrames] = { + { + .address = renderingElement2DVulkanTransformBuffer[0].address, + .size = renderingElement2DVulkanTransformBuffer[0].size + }, + { + .address = renderingElement2DVulkanTransformBuffer[1].address, + .size = renderingElement2DVulkanTransformBuffer[1].size + }, + { + .address = renderingElement2DVulkanTransformBuffer[2].address, + .size = renderingElement2DVulkanTransformBuffer[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 bufferRanges(renderingElement2DVulkans.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 < renderingElement2DVulkans.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, + .data = { .pAddressRange = &bufferRanges[i]} + }; + bufferRanges[rangeOffset + i] = { + .address = renderingElement2DVulkans[i]->buffers[i2]->address, + .size = renderingElement2DVulkans[i]->buffers[i2]->size + }; + } + start += renderingElement2DVulkans.size(); + rangeOffset += renderingElement2DVulkans.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 InitializeRenderingElement2DVulkanBuffer() { for(std::uint8_t frame = 0; frame < Window::numFrames; frame++) { renderingElement2DVulkanTransformBuffer[frame].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, renderingElement2DVulkans.size()+1); diff --git a/interfaces/Crafter.Graphics-RenderingElement3D.cppm b/interfaces/Crafter.Graphics-RenderingElement3D.cppm index d753c7a..9a6a031 100644 --- a/interfaces/Crafter.Graphics-RenderingElement3D.cppm +++ b/interfaces/Crafter.Graphics-RenderingElement3D.cppm @@ -32,16 +32,16 @@ import :Window; export namespace Crafter { struct TlasWithBuffer { VkDeviceAddress address; - VulkanBuffer buffer; + VulkanBuffer buffer; VkAccelerationStructureKHR accelerationStructure; - VulkanBuffer instanceBuffer; + VulkanBuffer instanceBuffer; }; class RenderingElement3D { public: VkAccelerationStructureInstanceKHR instance; static std::vector elements; - inline static VulkanBuffer scratchBuffer; + inline static VulkanBuffer scratchBuffer; inline static TlasWithBuffer tlases[Window::numFrames]; static void BuildTLAS(VkCommandBuffer cmd, std::uint32_t index); }; diff --git a/interfaces/Crafter.Graphics-VulkanBuffer.cppm b/interfaces/Crafter.Graphics-VulkanBuffer.cppm index 002902f..1b13027 100644 --- a/interfaces/Crafter.Graphics-VulkanBuffer.cppm +++ b/interfaces/Crafter.Graphics-VulkanBuffer.cppm @@ -31,24 +31,12 @@ import :Device; namespace Crafter { export class VulkanBufferBase { public: - VkDescriptorBufferInfo descriptor; + VkDeviceAddress address; + std::uint32_t size; VkBuffer buffer = VK_NULL_HANDLE; VkDeviceMemory memory; }; - export class VulkanBufferAdressable { - public: - VkDeviceAddress address; - }; - export class VulkanBufferAdressableEmpty {}; - template - using VulkanBufferAdressableConditional = - std::conditional_t< - Adressable, - VulkanBufferAdressable, - VulkanBufferAdressableEmpty - >; - export template class VulkanBufferMapped { public: @@ -63,16 +51,12 @@ namespace Crafter { VulkanBufferMappedEmpty >; - - export template - class VulkanBuffer; - - - export template - class VulkanBuffer : public VulkanBufferBase, public VulkanBufferMappedConditional, public VulkanBufferAdressableConditional { + export template + class VulkanBuffer : public VulkanBufferBase, public VulkanBufferMappedConditional { public: VulkanBuffer() = default; void Create(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, std::uint32_t count) { + size = count * sizeof(T); VkBufferCreateInfo bufferCreateInfo {}; bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; @@ -87,30 +71,21 @@ namespace Crafter { .allocationSize = memReqs.size, .memoryTypeIndex = Device::GetMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags) }; - if constexpr(Adressable) { - VkMemoryAllocateFlagsInfoKHR allocFlagsInfo { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR, - .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR, - }; - memAlloc.pNext = &allocFlagsInfo; - Device::CheckVkResult(vkAllocateMemory(Device::device, &memAlloc, nullptr, &memory)); - } else { - Device::CheckVkResult(vkAllocateMemory(Device::device, &memAlloc, nullptr, &memory)); - } - - descriptor.offset = 0; - descriptor.buffer = buffer; - descriptor.range = sizeof(T)*count; + + VkMemoryAllocateFlagsInfoKHR allocFlagsInfo { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR, + .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR, + }; + memAlloc.pNext = &allocFlagsInfo; + Device::CheckVkResult(vkAllocateMemory(Device::device, &memAlloc, nullptr, &memory)); Device::CheckVkResult(vkBindBufferMemory(Device::device, buffer, memory, 0)); - if constexpr(Adressable) { - VkBufferDeviceAddressInfo addressInfo = { - .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, - .buffer = buffer - }; - VulkanBufferAdressableConditional::address = vkGetBufferDeviceAddress(Device::device, &addressInfo); - } + VkBufferDeviceAddressInfo addressInfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + .buffer = buffer + }; + address = vkGetBufferDeviceAddress(Device::device, &addressInfo); if constexpr(Mapped) { Device::CheckVkResult(vkMapMemory(Device::device, memory, 0, memReqs.size, 0, reinterpret_cast(&(VulkanBufferMappedConditional::value)))); @@ -137,7 +112,7 @@ namespace Crafter { VkBufferCopy copyRegion = { .srcOffset = 0, .dstOffset = 0, - .size = descriptor.range + .size = size }; vkCmdCopyBuffer( @@ -219,13 +194,11 @@ namespace Crafter { } VulkanBuffer(VulkanBuffer&& other) { - descriptor = other.descriptor; buffer = other.buffer; memory = other.memory; + size = other.size; other.buffer = VK_NULL_HANDLE; - if constexpr(Adressable) { - VulkanBufferAdressableConditional::address = other.VulkanBufferAdressableConditional::address; - } + address = other.address; if constexpr(Mapped) { VulkanBufferMappedConditional::value = other.VulkanBufferMappedConditional::value; }