From e4e7c6680881924943b319b1f52b39e6a42e2b52 Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Thu, 29 Jan 2026 01:31:17 +0100 Subject: [PATCH] RT descriptors --- examples/VulkanTriangle/main.cpp | 3 + .../Crafter.Graphics-Mesh_vulkan.cpp | 5 +- .../Crafter.Graphics-VulkanDevice.cpp | 7 ++ .../Crafter.Graphics-Window_vulkan.cpp | 96 +++++++++++-------- ...Crafter.Graphics-DescriptorPoolVulkan.cppm | 20 ++-- .../Crafter.Graphics-PipelineRTVulkan.cppm | 51 +++++++++- interfaces/Crafter.Graphics-Types.cppm | 5 + interfaces/Crafter.Graphics-VulkanDevice.cppm | 4 + interfaces/Crafter.Graphics-Window.cppm | 22 ++++- 9 files changed, 157 insertions(+), 56 deletions(-) diff --git a/examples/VulkanTriangle/main.cpp b/examples/VulkanTriangle/main.cpp index af4ad06..b674e90 100644 --- a/examples/VulkanTriangle/main.cpp +++ b/examples/VulkanTriangle/main.cpp @@ -42,6 +42,9 @@ int main() { */ window.FinishInit(); + window.SetPipelineRT(); + window.descriptorsRt = pool.sets; + window.Render(); window.StartSync(); } diff --git a/implementations/Crafter.Graphics-Mesh_vulkan.cpp b/implementations/Crafter.Graphics-Mesh_vulkan.cpp index 0da143e..abe0f4e 100644 --- a/implementations/Crafter.Graphics-Mesh_vulkan.cpp +++ b/implementations/Crafter.Graphics-Mesh_vulkan.cpp @@ -24,14 +24,11 @@ module; module Crafter.Graphics:Mesh_impl; import :Mesh; import :VulkanDevice; +import :Types; import std; using namespace Crafter; -constexpr std::size_t alignUp(std::size_t value, std::size_t alignment) { - return (value + alignment - 1) & ~(alignment - 1); -} - void Mesh::Build(std::span verticies, std::span indicies, VkCommandBuffer cmd) { vertexBuffer.Resize(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, verticies.size()); indexBuffer.Resize(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, indicies.size()); diff --git a/implementations/Crafter.Graphics-VulkanDevice.cpp b/implementations/Crafter.Graphics-VulkanDevice.cpp index 0eb7649..bafaae8 100644 --- a/implementations/Crafter.Graphics-VulkanDevice.cpp +++ b/implementations/Crafter.Graphics-VulkanDevice.cpp @@ -156,6 +156,12 @@ void VulkanDevice::CreateDevice() { { VkPhysicalDevice device = physDevices[i]; + VkPhysicalDeviceProperties2 properties2{ + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + .pNext = &rayTracingProperties + }; + vkGetPhysicalDeviceProperties2(device, &properties2); + VkPhysicalDeviceProperties properties; vkGetPhysicalDeviceProperties(device, &properties); @@ -294,6 +300,7 @@ void VulkanDevice::CreateDevice() { vkCmdBuildAccelerationStructuresKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdBuildAccelerationStructuresKHR")); vkGetAccelerationStructureDeviceAddressKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetAccelerationStructureDeviceAddressKHR")); vkCreateRayTracingPipelinesKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateRayTracingPipelinesKHR")); + vkGetRayTracingShaderGroupHandlesKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetRayTracingShaderGroupHandlesKHR")); } std::uint32_t VulkanDevice::GetMemoryType(uint32_t typeBits, VkMemoryPropertyFlags properties) { diff --git a/implementations/Crafter.Graphics-Window_vulkan.cpp b/implementations/Crafter.Graphics-Window_vulkan.cpp index b417fa3..8845e5d 100644 --- a/implementations/Crafter.Graphics-Window_vulkan.cpp +++ b/implementations/Crafter.Graphics-Window_vulkan.cpp @@ -297,53 +297,53 @@ WindowVulkan::WindowVulkan(std::uint32_t width, std::uint32_t height) : Window(w subpassDescription.pPreserveAttachments = nullptr; subpassDescription.pResolveAttachments = nullptr; - // Subpass dependencies for layout transitions - std::array dependencies{}; + // // Subpass dependencies for layout transitions + // std::array dependencies{}; - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dependencies[0].srcAccessMask = 0; - dependencies[0].dstAccessMask = 0; - dependencies[0].dependencyFlags = 0; + // dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + // dependencies[0].dstSubpass = 0; + // dependencies[0].srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + // dependencies[0].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + // dependencies[0].srcAccessMask = 0; + // dependencies[0].dstAccessMask = 0; + // dependencies[0].dependencyFlags = 0; - dependencies[1].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[1].dstSubpass = 0; - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].srcAccessMask = 0; - dependencies[1].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; - dependencies[1].dependencyFlags = 0; + // dependencies[1].srcSubpass = VK_SUBPASS_EXTERNAL; + // dependencies[1].dstSubpass = 0; + // dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + // dependencies[1].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + // dependencies[1].srcAccessMask = 0; + // dependencies[1].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + // dependencies[1].dependencyFlags = 0; - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = static_cast(attachments.size()); - renderPassInfo.pAttachments = attachments.data(); - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpassDescription; - renderPassInfo.dependencyCount = static_cast(dependencies.size()); - renderPassInfo.pDependencies = dependencies.data(); + // VkRenderPassCreateInfo renderPassInfo = {}; + // renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + // renderPassInfo.attachmentCount = static_cast(attachments.size()); + // renderPassInfo.pAttachments = attachments.data(); + // renderPassInfo.subpassCount = 1; + // renderPassInfo.pSubpasses = &subpassDescription; + // renderPassInfo.dependencyCount = static_cast(dependencies.size()); + // renderPassInfo.pDependencies = dependencies.data(); - VulkanDevice::CheckVkResult(vkCreateRenderPass(VulkanDevice::device, &renderPassInfo, nullptr, &renderPass)); + // VulkanDevice::CheckVkResult(vkCreateRenderPass(VulkanDevice::device, &renderPassInfo, nullptr, &renderPass)); // Create frame buffers for every swap chain image - frameBuffers.resize(images.size()); - for (uint32_t i = 0; i < frameBuffers.size(); i++) - { - const VkImageView attachments[1] = { - imageViews[i] - }; - VkFramebufferCreateInfo frameBufferCreateInfo{}; - frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - frameBufferCreateInfo.renderPass = renderPass; - frameBufferCreateInfo.attachmentCount = 1; - frameBufferCreateInfo.pAttachments = attachments; - frameBufferCreateInfo.width = width; - frameBufferCreateInfo.height = height; - frameBufferCreateInfo.layers = 1; - VulkanDevice::CheckVkResult(vkCreateFramebuffer(VulkanDevice::device, &frameBufferCreateInfo, nullptr, &frameBuffers[i])); - } + // frameBuffers.resize(images.size()); + // for (uint32_t i = 0; i < frameBuffers.size(); i++) + // { + // const VkImageView attachments[1] = { + // imageViews[i] + // }; + // VkFramebufferCreateInfo frameBufferCreateInfo{}; + // frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + // frameBufferCreateInfo.renderPass = VK_NULL_HANDLE; + // frameBufferCreateInfo.attachmentCount = 1; + // frameBufferCreateInfo.pAttachments = attachments; + // frameBufferCreateInfo.width = width; + // frameBufferCreateInfo.height = height; + // frameBufferCreateInfo.layers = 1; + // VulkanDevice::CheckVkResult(vkCreateFramebuffer(VulkanDevice::device, &frameBufferCreateInfo, nullptr, &frameBuffers[i])); + // } drawCmdBuffers.resize(images.size()); @@ -395,7 +395,7 @@ void WindowVulkan::Render() { VkCommandBufferBeginInfo cmdBufInfo {}; cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - + VulkanDevice::CheckVkResult(vkBeginCommandBuffer(drawCmdBuffers[currentBuffer], &cmdBufInfo)); VkImageSubresourceRange range{}; @@ -452,6 +452,18 @@ void WindowVulkan::Render() { scissor.offset.y = 0; vkCmdSetScissor(drawCmdBuffers[currentBuffer], 0, 1, &scissor); + vkCmdBindPipeline(drawCmdBuffers[currentBuffer], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, rtPipeline); + VkBindDescriptorSetsInfo bindDescriptorSetsInfo{ + .sType = VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_SETS_INFO, + .stageFlags = VK_SHADER_STAGE_ALL, + .layout = rtPipelineLayout, + .firstSet = 0, + .descriptorSetCount = 1, + .pDescriptorSets = descriptorsRt.data() + }; + + vkCmdBindDescriptorSets2(drawCmdBuffers[currentBuffer], &bindDescriptorSetsInfo); + //vkCmdTraceRaysKHR(drawCmdBuffers[currentBuffer], &raygenRegion, &missRegion, &hitRegion, &callableRegion, width, height, 1); VulkanDevice::vkCmdEndRenderingKHRProc(drawCmdBuffers[currentBuffer]); diff --git a/interfaces/Crafter.Graphics-DescriptorPoolVulkan.cppm b/interfaces/Crafter.Graphics-DescriptorPoolVulkan.cppm index 4ec2a3c..9b0f885 100644 --- a/interfaces/Crafter.Graphics-DescriptorPoolVulkan.cppm +++ b/interfaces/Crafter.Graphics-DescriptorPoolVulkan.cppm @@ -30,17 +30,21 @@ import :DescriptorLayoutVulkan; import Crafter.Event; export namespace Crafter { - template - class DescriptorPool { + class DescriptorPoolBase { public: - inline static Event onDescriptorRefresh; - inline static std::uint32_t setIndex = 0; - inline static std::uint32_t setsCount = 0; - inline static std::vector sets; - inline static VkDescriptorPool descriptorPool[PoolCount] = { VK_NULL_HANDLE }; + std::vector sets; + }; + + template + class DescriptorPool : public DescriptorPoolBase { + public: + Event onDescriptorRefresh; + std::uint32_t setIndex = 0; + std::uint32_t setsCount = 0; + VkDescriptorPool descriptorPool[PoolCount] = { VK_NULL_HANDLE }; public: - static void BuildPool(std::uint32_t poolIndex) { + void BuildPool(std::uint32_t poolIndex) { if(descriptorPool[poolIndex] != VK_NULL_HANDLE) { vkDestroyDescriptorPool(VulkanDevice::device, descriptorPool[poolIndex], nullptr); } diff --git a/interfaces/Crafter.Graphics-PipelineRTVulkan.cppm b/interfaces/Crafter.Graphics-PipelineRTVulkan.cppm index 990563d..74f6dee 100644 --- a/interfaces/Crafter.Graphics-PipelineRTVulkan.cppm +++ b/interfaces/Crafter.Graphics-PipelineRTVulkan.cppm @@ -26,6 +26,8 @@ export module Crafter.Graphics:PipelineRTVulkan; import std; import :VulkanDevice; import :DescriptorLayoutVulkan; +import :VulkanBuffer; +import :Types; export namespace Crafter { template @@ -33,6 +35,12 @@ export namespace Crafter { public: inline static VkPipeline pipeline; inline static VkPipelineLayout pipelineLayout; + inline static std::vector shaderHandles; + inline static VulkanBuffer sbtBuffer; + inline static VkStridedDeviceAddressRegionKHR raygenRegion; + inline static VkStridedDeviceAddressRegionKHR missRegion; + inline static VkStridedDeviceAddressRegionKHR hitRegion; + inline static VkStridedDeviceAddressRegionKHR callableRegion; static void Init() { VkPipelineLayoutCreateInfo pipelineLayoutInfo { @@ -71,7 +79,48 @@ export namespace Crafter { .layout = pipelineLayout }; - VulkanDevice::vkCreateRayTracingPipelinesKHR(VulkanDevice::device, {}, {}, 1, &rtPipelineInfo, nullptr, &pipeline); + VulkanDevice::CheckVkResult(VulkanDevice::vkCreateRayTracingPipelinesKHR(VulkanDevice::device, {}, {}, 1, &rtPipelineInfo, nullptr, &pipeline)); + + std::uint32_t handleSize = VulkanDevice::rayTracingProperties.shaderGroupHandleSize; + std::uint32_t handleAlignment = VulkanDevice::rayTracingProperties.shaderGroupHandleAlignment; + std::uint32_t baseAlignment = VulkanDevice::rayTracingProperties.shaderGroupBaseAlignment; + std::uint32_t groupCount = rtPipelineInfo.groupCount; + + std::size_t dataSize = handleSize * groupCount; + shaderHandles.resize(dataSize); + VulkanDevice::CheckVkResult(VulkanDevice::vkGetRayTracingShaderGroupHandlesKHR(VulkanDevice::device, pipeline, 0, groupCount, dataSize, shaderHandles.data())); + + std::uint32_t raygenSize = AlignUp(handleSize, handleAlignment); + std::uint32_t missSize = AlignUp(handleSize, handleAlignment); + std::uint32_t hitSize = AlignUp(handleSize, handleAlignment); + std::uint32_t callableSize = 0; + + std::uint32_t raygenOffset = 0; + std::uint32_t missOffset = AlignUp(raygenSize, baseAlignment); + std::uint32_t hitOffset = AlignUp(missOffset + missSize, baseAlignment); + std::uint32_t callableOffset = AlignUp(hitOffset + hitSize, baseAlignment); + + std::size_t bufferSize = callableOffset + callableSize; + + sbtBuffer.Create(VK_BUFFER_USAGE_2_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bufferSize); + + // Ray generation shader (group 0) + std::memcpy(sbtBuffer.value + raygenOffset, shaderHandles.data() + 0 * handleSize, handleSize); + raygenRegion.deviceAddress = sbtBuffer.address + raygenOffset; + raygenRegion.stride = raygenSize; + raygenRegion.size = raygenSize; + + missRegion.deviceAddress = 0; + missRegion.stride = 0; + missRegion.size = 0; + + hitRegion.deviceAddress = 0; + hitRegion.stride = 0; + hitRegion.size = 0; + + callableRegion.deviceAddress = 0; + callableRegion.stride = 0; + callableRegion.size = 0; } }; } diff --git a/interfaces/Crafter.Graphics-Types.cppm b/interfaces/Crafter.Graphics-Types.cppm index 8027d43..606595f 100644 --- a/interfaces/Crafter.Graphics-Types.cppm +++ b/interfaces/Crafter.Graphics-Types.cppm @@ -343,6 +343,11 @@ export namespace Crafter { CrafterKeysMax }; + template + constexpr T AlignUp(T value, T2 alignment) { + return (value + alignment - 1) & ~(alignment - 1); + } + #ifdef CRAFTER_GRAPHICS_VULKAN struct DescriptorBinding { VkDescriptorType type; diff --git a/interfaces/Crafter.Graphics-VulkanDevice.cppm b/interfaces/Crafter.Graphics-VulkanDevice.cppm index 76c555d..189428e 100644 --- a/interfaces/Crafter.Graphics-VulkanDevice.cppm +++ b/interfaces/Crafter.Graphics-VulkanDevice.cppm @@ -45,7 +45,11 @@ export namespace Crafter { inline static PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR; inline static PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR; inline static PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR; + inline static PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR; inline static VkPhysicalDeviceMemoryProperties memoryProperties; + inline static VkPhysicalDeviceRayTracingPipelinePropertiesKHR rayTracingProperties = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR + }; static void CreateDevice(); static void CheckVkResult(VkResult result); static std::uint32_t GetMemoryType(std::uint32_t typeBits, VkMemoryPropertyFlags properties); diff --git a/interfaces/Crafter.Graphics-Window.cppm b/interfaces/Crafter.Graphics-Window.cppm index 6686255..7ef5836 100644 --- a/interfaces/Crafter.Graphics-Window.cppm +++ b/interfaces/Crafter.Graphics-Window.cppm @@ -67,6 +67,9 @@ export module Crafter.Graphics:Window; import std; import :Types; import Crafter.Event; +#ifdef CRAFTER_GRAPHICS_VULKAN +import :PipelineRTVulkan; +#endif export namespace Crafter { class Transform; @@ -297,6 +300,7 @@ export namespace Crafter { xkb_keymap* xkb_keymap; xkb_context* xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); xkb_state* xkb_state; + std::vector descriptorsRt; void Render(); void QueueRender(); void Resize(std::uint32_t width, std::uint32_t height); @@ -306,6 +310,16 @@ export namespace Crafter { void SetTitle(const std::string_view title) override; VkCommandBuffer StartInit(); void FinishInit(); + + template + void SetPipelineRT() { + rtPipeline = PipelineRTVulkan::pipeline; + rtPipelineLayout = PipelineRTVulkan::pipelineLayout; + raygenRegion = PipelineRTVulkan::raygenRegion; + missRegion = PipelineRTVulkan::missRegion; + hitRegion = PipelineRTVulkan::hitRegion; + callableRegion = PipelineRTVulkan::callableRegion; + } inline static wl_compositor* compositor = nullptr; static void wl_surface_frame_done(void *data, wl_callback *cb, uint32_t time); static void PointerListenerHandleMotion(void* data, wl_pointer* wl_pointer, uint time, wl_fixed_t surface_x, wl_fixed_t surface_y); @@ -381,7 +395,13 @@ export namespace Crafter { Semaphores semaphores; uint32_t currentBuffer = 0; VkPipelineStageFlags submitPipelineStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - VkRenderPass renderPass = VK_NULL_HANDLE; + //VkRenderPass renderPass = VK_NULL_HANDLE; + VkPipeline rtPipeline; + VkPipelineLayout rtPipelineLayout; + VkStridedDeviceAddressRegionKHR raygenRegion; + VkStridedDeviceAddressRegionKHR missRegion; + VkStridedDeviceAddressRegionKHR hitRegion; + VkStridedDeviceAddressRegionKHR callableRegion; }; #endif } \ No newline at end of file