diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 92f58850..e8a6d24b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -55,6 +55,7 @@ jobs: - name: Install Dependencies run: | wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - + sudo apt update sudo apt-get install libsdl2-dev libfreetype-dev libvorbis-dev libogg-dev libopenal-dev libdwarf-dev libelf-dev wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo tee /etc/apt/trusted.gpg.d/lunarg.asc sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-jammy.list http://packages.lunarg.com/vulkan/lunarg-vulkan-jammy.list diff --git a/Makefile b/Makefile index 38e5e636..4c6b0083 100644 --- a/Makefile +++ b/Makefile @@ -75,7 +75,7 @@ SRC_vulkan = \ vulkan/vulkan_buffer vulkan/vulkan_command_queue vulkan/vulkan_descriptor_manager vulkan/vulkan_device \ vulkan/vulkan_framebuffer vulkan/vulkan_image vulkan/vulkan_instance vulkan/vulkan_internal \ vulkan/vulkan_memory_manager vulkan/vulkan_pipeline vulkan/vulkan_shader vulkan/vulkan_storage \ - vulkan/vulkan_swap_chain vulkan/vulkan_window vulkan_base + vulkan/vulkan_swap_chain vulkan/vulkan_window vulkan/vulkan_ray_tracing vulkan_base SRC_gfx_stbi = \ gfx/image_stbi gfx/image_stbir diff --git a/include/fwk/vulkan/vulkan_internal.h b/include/fwk/vulkan/vulkan_internal.h index f0296b31..5bed8b0d 100644 --- a/include/fwk/vulkan/vulkan_internal.h +++ b/include/fwk/vulkan/vulkan_internal.h @@ -12,11 +12,17 @@ namespace fwk { inline auto toVk(VShaderStage stage) { return VkShaderStageFlagBits(1u << int(stage)); } inline auto toVk(VShaderStages flags) { return VkShaderStageFlags(flags.bits); } -inline auto toVk(VDescriptorType type) { return VkDescriptorType(type); } +inline auto toVk(VDescriptorType type) { + return type == VDescriptorType::accel_struct ? VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR : + VkDescriptorType(type); +} inline auto toVk(VDescriptorPoolFlags flags) { return VkDescriptorPoolCreateFlagBits(flags.bits); } inline auto toVk(VPrimitiveTopology type) { return VkPrimitiveTopology(type); } inline auto toVk(VImageUsageFlags usage) { return VkImageUsageFlags{usage.bits}; } -inline auto toVk(VBufferUsageFlags usage) { return VkBufferUsageFlags{usage.bits}; } +inline auto toVk(VBufferUsageFlags usage) { + uint32_t base_bits{usage.bits & 0x1ffu}, accel_bits{usage.bits & 0x600u}; + return VkBufferUsageFlags{base_bits | (accel_bits << 10)}; +} inline auto toVk(VCommandPoolFlags flags) { return VkCommandPoolCreateFlagBits(flags.bits); } inline auto toVk(VMemoryFlags flags) { return VkMemoryPropertyFlags(flags.bits); } inline auto toVk(VPresentMode mode) { return VkPresentModeKHR(mode); } diff --git a/include/fwk/vulkan/vulkan_pipeline.h b/include/fwk/vulkan/vulkan_pipeline.h index 5d3f7a9f..f7767db1 100644 --- a/include/fwk/vulkan/vulkan_pipeline.h +++ b/include/fwk/vulkan/vulkan_pipeline.h @@ -282,6 +282,7 @@ struct VDescriptorSet { void set(int first_index, VDescriptorType type, CSpan>); void set(int first_index, CSpan>); + void set(int first_index, PVAccelStruct); void setStorageImage(int index, PVImageView, VImageLayout); diff --git a/include/fwk/vulkan/vulkan_ray_tracing.h b/include/fwk/vulkan/vulkan_ray_tracing.h new file mode 100644 index 00000000..7be28ecc --- /dev/null +++ b/include/fwk/vulkan/vulkan_ray_tracing.h @@ -0,0 +1,28 @@ +// Copyright (C) Krzysztof Jakubowski +// This file is part of libfwk. See license.txt for details. + +#pragma once + +#include "fwk/vulkan/vulkan_storage.h" +#include "fwk/vulkan_base.h" + +namespace fwk { + +DEFINE_ENUM(VAccelStructType, top_level, bottom_level); + +class VulkanAccelStruct : public VulkanObjectBase { + public: + static Ex create(VulkanDevice &, VAccelStructType, VBufferSpan); + + static Ex build(VulkanDevice &, VBufferSpan vertices, + VBufferSpan indices); + + private: + friend class VulkanDevice; + VulkanAccelStruct(VkAccelerationStructureKHR, VObjectId, PVBuffer); + ~VulkanAccelStruct(); + + PVBuffer m_buffer; +}; + +} diff --git a/include/fwk/vulkan/vulkan_type_list.h b/include/fwk/vulkan/vulkan_type_list.h index 74112393..313c1a94 100644 --- a/include/fwk/vulkan/vulkan_type_list.h +++ b/include/fwk/vulkan/vulkan_type_list.h @@ -16,5 +16,6 @@ CASE_TYPE(RenderPass, VkRenderPass, render_pass) CASE_TYPE(ShaderModule, VkShaderModule, shader_module) CASE_TYPE(SwapChain, VkSwapchainKHR, swap_chain) CASE_TYPE(Sampler, VkSampler, sampler) +CASE_TYPE(AccelStruct, VkAccelerationStructureKHR, accel_struct) #undef CASE_TYPE diff --git a/include/fwk/vulkan_base.h b/include/fwk/vulkan_base.h index f0813e4e..fbabcb8d 100644 --- a/include/fwk/vulkan_base.h +++ b/include/fwk/vulkan_base.h @@ -59,8 +59,8 @@ struct VulkanVersion { DEFINE_ENUM(VVendorId, intel, nvidia, amd, unknown); -DEFINE_ENUM(VTypeId, buffer, buffer_view, framebuffer, image, image_view, pipeline, pipeline_layout, - render_pass, sampler, shader_module, swap_chain); +DEFINE_ENUM(VTypeId, accel_struct, buffer, buffer_view, framebuffer, image, image_view, pipeline, + pipeline_layout, render_pass, sampler, shader_module, swap_chain); // device: fastest memory with device_local (always available) // host: fastest memory with host_visible (always available) @@ -90,7 +90,8 @@ using VCommandPoolFlags = EnumFlags; DEFINE_ENUM(VBindPoint, graphics, compute); DEFINE_ENUM(VBufferUsage, transfer_src, transfer_dst, uniform_texel_buffer, storage_texel_buffer, - uniform_buffer, storage_buffer, index_buffer, vertex_buffer, indirect_buffer); + uniform_buffer, storage_buffer, index_buffer, vertex_buffer, indirect_buffer, + accel_struct_build_input, accel_struct_storage); using VBufferUsageFlags = EnumFlags; DEFINE_ENUM(VImageUsage, transfer_src, transfer_dst, sampled, storage, color_att, depth_stencil_att, @@ -106,7 +107,7 @@ using VShaderStages = EnumFlags; DEFINE_ENUM(VDescriptorType, sampler, combined_image_sampler, sampled_image, storage_image, uniform_texel_buffer, storage_texel_buffer, uniform_buffer, storage_buffer, - uniform_buffer_dynamic, storage_buffer_dynamic, input_att); + uniform_buffer_dynamic, storage_buffer_dynamic, input_att, accel_struct); using VDescriptorTypes = EnumFlags; DEFINE_ENUM(VDescriptorPoolFlag, free_descriptor_set, update_after_bind, host_only); diff --git a/src/vulkan/vulkan_device.cpp b/src/vulkan/vulkan_device.cpp index 26f8ed4e..9c833c05 100644 --- a/src/vulkan/vulkan_device.cpp +++ b/src/vulkan/vulkan_device.cpp @@ -19,6 +19,7 @@ #include "fwk/vulkan/vulkan_framebuffer.h" #include "fwk/vulkan/vulkan_image.h" #include "fwk/vulkan/vulkan_pipeline.h" +#include "fwk/vulkan/vulkan_ray_tracing.h" #include "fwk/vulkan/vulkan_shader.h" #include "fwk/vulkan/vulkan_swap_chain.h" #include "fwk/vulkan/vulkan_window.h" diff --git a/src/vulkan/vulkan_pipeline.cpp b/src/vulkan/vulkan_pipeline.cpp index b6b93c22..7bd722a9 100644 --- a/src/vulkan/vulkan_pipeline.cpp +++ b/src/vulkan/vulkan_pipeline.cpp @@ -9,6 +9,7 @@ #include "fwk/vulkan/vulkan_device.h" #include "fwk/vulkan/vulkan_instance.h" #include "fwk/vulkan/vulkan_internal.h" +#include "fwk/vulkan/vulkan_ray_tracing.h" #include "fwk/vulkan/vulkan_shader.h" namespace fwk { @@ -165,6 +166,25 @@ void VDescriptorSet::setStorageImage(int index, PVImageView image_view, VImageLa vkUpdateDescriptorSets(device->handle(), 1, &write, 0, nullptr); } +void VDescriptorSet::set(int index, PVAccelStruct as) { + if(!(bindings_map & (1ull << index))) + return; + VkWriteDescriptorSetAccelerationStructureKHR as_info{ + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR}; + auto as_handle = as->handle(); + as_info.pAccelerationStructures = &as_handle; + as_info.accelerationStructureCount = 1; + + VkWriteDescriptorSet write{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET}; + write.descriptorCount = 1; + write.dstSet = handle; + write.dstBinding = index; + write.dstArrayElement = 0; + write.descriptorType = toVk(VDescriptorType::storage_image); + write.pNext = &as_info; + vkUpdateDescriptorSets(device->handle(), 1, &write, 0, nullptr); +} + VulkanRenderPass::VulkanRenderPass(VkRenderPass handle, VObjectId id) : VulkanObjectBase(handle, id) {} VulkanRenderPass ::~VulkanRenderPass() { diff --git a/src/vulkan/vulkan_ray_tracing.cpp b/src/vulkan/vulkan_ray_tracing.cpp new file mode 100644 index 00000000..f35e056c --- /dev/null +++ b/src/vulkan/vulkan_ray_tracing.cpp @@ -0,0 +1,102 @@ +// Copyright (C) Krzysztof Jakubowski +// This file is part of libfwk. See license.txt for details. + +#include "fwk/vulkan/vulkan_ray_tracing.h" + +#include "fwk/enum_map.h" +#include "fwk/sys/assert.h" +#include "fwk/vulkan/vulkan_command_queue.h" +#include "fwk/vulkan/vulkan_device.h" +#include "fwk/vulkan/vulkan_internal.h" +#include "fwk/vulkan/vulkan_memory_manager.h" + +namespace fwk { + +VulkanAccelStruct::VulkanAccelStruct(VkAccelerationStructureKHR handle, VObjectId id, + PVBuffer buffer) + : VulkanObjectBase(handle, id), m_buffer(std::move(buffer)) {} + +VulkanAccelStruct::~VulkanAccelStruct() { + deferredRelease(vkDestroyAccelerationStructureKHR, m_handle); +} + +Ex VulkanAccelStruct::create(VulkanDevice &device, VAccelStructType type, + VBufferSpan buffer) { + DASSERT(buffer.byteOffset() % 256 == 0); + + VkAccelerationStructureCreateInfoKHR create_info{ + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR}; + create_info.buffer = buffer.buffer().handle(); + create_info.offset = buffer.byteOffset(); + create_info.size = buffer.byteOffset(); + create_info.type = VkAccelerationStructureTypeKHR(type); + + VkAccelerationStructureKHR handle = 0; + FWK_VK_EXPECT_CALL(vkCreateAccelerationStructureKHR, device.handle(), &create_info, nullptr, + &handle); + return device.createObject(handle, buffer.buffer()); +} + +template static u64 getAddress(VulkanDevice &device, VBufferSpan buffer) { + VkBufferDeviceAddressInfo info = {VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO}; + info.buffer = buffer.buffer().handle(); + return vkGetBufferDeviceAddress(device.handle(), &info) + buffer.byteOffset(); +} + +Ex VulkanAccelStruct::build(VulkanDevice &device, VBufferSpan vertices, + VBufferSpan indices) { + VkAccelerationStructureGeometryTrianglesDataKHR triangles{ + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR}; + triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; + triangles.vertexData.deviceAddress = getAddress(device, vertices); + triangles.vertexStride = sizeof(float3); + triangles.indexType = VK_INDEX_TYPE_UINT32; + triangles.indexData.deviceAddress = getAddress(device, indices); + DASSERT(vertices.size() > 0); + triangles.maxVertex = vertices.size() - 1; + + VkAccelerationStructureGeometryKHR geometry{ + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR}; + geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + geometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; + geometry.geometry.triangles = triangles; + + VkAccelerationStructureBuildRangeInfoKHR offset; + offset.firstVertex = vertices.byteOffset() / sizeof(float3); + offset.primitiveCount = indices.size() / 3; + offset.primitiveOffset = 0; + offset.transformOffset = 0; + + VkAccelerationStructureBuildGeometryInfoKHR build_info{ + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR}; + build_info.type = + VkAccelerationStructureTypeKHR::VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; + build_info.flags = 0; // TODO: compaction + build_info.pGeometries = &geometry; + build_info.geometryCount = 1; + + VkAccelerationStructureBuildSizesInfoKHR size_info{ + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR}; + uint32_t prim_count = indices.size() / 3; + + vkGetAccelerationStructureBuildSizesKHR( + device.handle(), + VkAccelerationStructureBuildTypeKHR::VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, + &build_info, &prim_count, &size_info); + + auto buffer = EX_PASS(VulkanBuffer::create(device, size_info.accelerationStructureSize, + VBufferUsage::accel_struct_storage)); + auto accel = EX_PASS(VulkanAccelStruct::create(device, VAccelStructType::bottom_level, buffer)); + + build_info.srcAccelerationStructure = accel->handle(); + build_info.dstAccelerationStructure = accel->handle(); + + auto *offsets = &offset; + + auto result = + vkBuildAccelerationStructuresKHR(device.handle(), nullptr, 1, &build_info, &offsets); + + return accel; +} + +} \ No newline at end of file diff --git a/windows/libfwk.vcxproj b/windows/libfwk.vcxproj index 59f2903b..493cc704 100644 --- a/windows/libfwk.vcxproj +++ b/windows/libfwk.vcxproj @@ -148,6 +148,7 @@ + @@ -345,6 +346,7 @@ + diff --git a/windows/libfwk.vcxproj.filters b/windows/libfwk.vcxproj.filters index 7469eea5..90769231 100644 --- a/windows/libfwk.vcxproj.filters +++ b/windows/libfwk.vcxproj.filters @@ -660,6 +660,9 @@ include\gfx + + include\vulkan + @@ -1091,6 +1094,9 @@ src\gfx + + src\vulkan +