| /* |
| * Copyright (c) 2024-2025 Valve Corporation |
| * Copyright (c) 2024-2025 LunarG, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| */ |
| |
| #pragma once |
| |
| #include "binding.h" |
| #include "descriptor_helper.h" |
| #include "shader_helper.h" |
| |
| #include <optional> |
| |
| namespace vkt { |
| // acceleration structure |
| namespace as { |
| |
| // Helper classes to create instances of: |
| // - VkAccelerationStructureGeometryKHR |
| // - VkAccelerationStructureCreateInfoKHR |
| // - VkAccelerationStructureBuildGeometryInfoKHR |
| |
| // The vkt::as::blueprint namespace (bottom of file) contains functions to readily create a valid instance of those classes. |
| // Those instances are typically modified using the available public methods. |
| // When done with modifications, call the Build() method to build the internal Vulkan objects. |
| // Access them using relevant methods, eg: handle(), GetVkObj()... |
| |
| // 3 types of geometry handled: Triangle, AABB and VkAccelerationStructureInstanceKHR (used in top level acceleration structures) |
| // Those objects can be managed on the device, using the ***Device*** methods, |
| // or on the host using the ***Host*** methods |
| class GeometryKHR { |
| public: |
| enum class Type { Triangle, AABB, Instance, Spheres, LSSpheres, _INTERNAL_UNSPECIFIED }; |
| struct Triangles { |
| vkt::Buffer device_vertex_buffer; |
| std::unique_ptr<float[]> host_vertex_buffer; |
| vkt::Buffer device_index_buffer; |
| std::unique_ptr<uint32_t[]> host_index_buffer; |
| vkt::Buffer device_transform_buffer; |
| }; |
| struct AABBs { |
| vkt::Buffer device_buffer; |
| std::unique_ptr<VkAabbPositionsKHR[]> host_buffer; |
| }; |
| struct Instances { |
| std::vector<VkAccelerationStructureInstanceKHR> vk_instances{}; |
| // Used to (eventually, no need for host instance) store on device instances |
| vkt::Buffer buffer; |
| }; |
| struct Spheres { |
| vkt::Buffer device_vertex_buffer; |
| std::unique_ptr<float[]> host_vertex_buffer; |
| vkt::Buffer device_index_buffer; |
| std::unique_ptr<uint32_t[]> host_index_buffer; |
| vkt::Buffer device_radius_buffer; |
| std::unique_ptr<float[]> host_radius_buffer; |
| std::shared_ptr<VkAccelerationStructureGeometrySpheresDataNV> sphere_geometry_ptr; |
| }; |
| struct LSSpheres { |
| vkt::Buffer device_vertex_buffer; |
| std::unique_ptr<float[]> host_vertex_buffer; |
| vkt::Buffer device_index_buffer; |
| std::unique_ptr<uint32_t[]> host_index_buffer; |
| vkt::Buffer device_radius_buffer; |
| std::unique_ptr<float[]> host_radius_buffer; |
| std::shared_ptr<VkAccelerationStructureGeometryLinearSweptSpheresDataNV> sphere_geometry_ptr; |
| }; |
| |
| ~GeometryKHR() = default; |
| GeometryKHR(); |
| GeometryKHR(const GeometryKHR&) = delete; |
| GeometryKHR(GeometryKHR&&) = default; |
| GeometryKHR& operator=(GeometryKHR&&) = default; |
| GeometryKHR& operator=(const GeometryKHR&) = delete; |
| |
| // Common methods for all types |
| GeometryKHR& SetFlags(VkGeometryFlagsKHR flags); |
| GeometryKHR& SetType(Type type); |
| GeometryKHR& SetPrimitiveCount(uint32_t primitiveCount); |
| GeometryKHR& SetStride(VkDeviceSize stride); |
| // Triangle |
| GeometryKHR& SetTrianglesDeviceVertexBuffer(vkt::Buffer&& vertex_buffer, uint32_t max_vertex, |
| VkFormat vertex_format = VK_FORMAT_R32G32B32_SFLOAT, |
| VkDeviceSize stride = 3 * sizeof(float), VkDeviceSize vertex_buffer_offset = 0); |
| GeometryKHR& SetTrianglesHostVertexBuffer(std::unique_ptr<float[]>&& vertex_buffer, uint32_t max_vertex, |
| VkDeviceSize stride = 3 * sizeof(float)); |
| GeometryKHR& SetTrianglesDeviceIndexBuffer(vkt::Buffer&& index_buffer, VkIndexType index_type = VK_INDEX_TYPE_UINT32); |
| GeometryKHR& SetTrianglesHostIndexBuffer(std::unique_ptr<uint32_t[]> index_buffer); |
| GeometryKHR& SetTrianglesIndexType(VkIndexType index_type); |
| GeometryKHR& SetTrianglesVertexFormat(VkFormat vertex_format); |
| GeometryKHR& SetTrianglesMaxVertex(uint32_t max_vertex); |
| GeometryKHR& SetTrianglesTransformBuffer(vkt::Buffer&& transform_buffer); |
| GeometryKHR& SetTrianglesTransformatData(VkDeviceAddress address); |
| GeometryKHR& SetTrianglesVertexBufferDeviceAddress(VkDeviceAddress address); |
| GeometryKHR& SetTrianglesIndexBufferDeviceAddress(VkDeviceAddress address); |
| // AABB |
| GeometryKHR& SetAABBsDeviceBuffer(vkt::Buffer&& buffer, VkDeviceSize stride = sizeof(VkAabbPositionsKHR)); |
| GeometryKHR& SetAABBsHostBuffer(std::unique_ptr<VkAabbPositionsKHR[]> buffer, VkDeviceSize stride = sizeof(VkAabbPositionsKHR)); |
| GeometryKHR& SetAABBsStride(VkDeviceSize stride); |
| GeometryKHR& SetAABBsDeviceAddress(VkDeviceAddress address); |
| |
| // Instance |
| GeometryKHR& AddInstanceDeviceAccelStructRef(const vkt::Device& device, VkAccelerationStructureKHR blas, |
| const VkAccelerationStructureInstanceKHR& instance); |
| |
| // Both the host stored and device stored instances will be updated |
| void UpdateAccelerationStructureInstance(size_t i, std::function<void(VkAccelerationStructureInstanceKHR&)> f); |
| GeometryKHR& AddInstanceHostAccelStructRef(VkAccelerationStructureKHR blas); |
| GeometryKHR& SetInstancesDeviceAddress(VkDeviceAddress address); |
| GeometryKHR& SetInstanceHostAccelStructRef(VkAccelerationStructureKHR blas, uint32_t instance_i); |
| GeometryKHR& SetInstanceHostAddress(void* address); |
| GeometryKHR& SetInstanceShaderBindingTableRecordOffset(uint32_t instance_i, uint32_t instance_sbt_record_offset); |
| // Spheres |
| GeometryKHR& SetSpheresVertexFormat(VkFormat vertex_format); |
| GeometryKHR& SetSpheresRadiusFormat(VkFormat radius_format); |
| GeometryKHR& SetSpheresDeviceVertexBuffer(vkt::Buffer&& vertex_buffer, VkFormat vertex_format = VK_FORMAT_R32G32B32_SFLOAT, |
| VkDeviceSize stride = 3 * sizeof(float)); |
| GeometryKHR& SetSpheresDeviceIndexBuffer(vkt::Buffer&& index_buffer, VkIndexType index_type = VK_INDEX_TYPE_UINT32); |
| GeometryKHR& SetSpheresDeviceRadiusBuffer(vkt::Buffer&& radius_buffer, VkDeviceSize stride = sizeof(float)); |
| GeometryKHR& SetSpheresHostVertexBuffer(std::unique_ptr<float[]>&& vertex_buffer, VkDeviceSize stride = 3 * sizeof(float)); |
| GeometryKHR& SetSpheresHostIndexBuffer(std::unique_ptr<uint32_t[]> index_buffer); |
| GeometryKHR& SetSpheresHostRadiusBuffer(std::unique_ptr<float[]> radius_buffer, VkDeviceSize stride = sizeof(float)); |
| GeometryKHR& SetSpheresIndexType(VkIndexType index_type); |
| GeometryKHR& SetSpheresVertexStride(VkDeviceSize stride); |
| GeometryKHR& SetSpheresRadiusStride(VkDeviceSize stride); |
| GeometryKHR& SetSpheresIndexAddressZero(); |
| GeometryKHR& SetSpheresVertexAddressZero(); |
| GeometryKHR& SetSpheresRadiusAddressZero(); |
| |
| // LSSpheres |
| GeometryKHR& SetLSSpheresVertexFormat(VkFormat vertex_format); |
| GeometryKHR& SetLSSpheresRadiusFormat(VkFormat radius_format); |
| GeometryKHR& SetLSSpheresDeviceVertexBuffer(vkt::Buffer&& vertex_buffer, VkFormat vertex_format = VK_FORMAT_R32G32B32_SFLOAT, |
| VkDeviceSize stride = 3 * sizeof(float)); |
| GeometryKHR& SetLSSpheresDeviceIndexBuffer(vkt::Buffer&& index_buffer, VkIndexType index_type = VK_INDEX_TYPE_UINT32); |
| GeometryKHR& SetLSSpheresDeviceRadiusBuffer(vkt::Buffer&& radius_buffer, VkDeviceSize stride = sizeof(float)); |
| GeometryKHR& SetLSSpheresHostVertexBuffer(std::unique_ptr<float[]>&& vertex_buffer, VkDeviceSize stride = 3 * sizeof(float)); |
| GeometryKHR& SetLSSpheresHostIndexBuffer(std::unique_ptr<uint32_t[]> index_buffer); |
| GeometryKHR& SetLSSpheresHostRadiusBuffer(std::unique_ptr<float[]> radius_buffer, VkDeviceSize stride = sizeof(float)); |
| GeometryKHR& SetLSSpheresIndexType(VkIndexType index_type); |
| GeometryKHR& SetLSSpheresVertexStride(VkDeviceSize stride); |
| GeometryKHR& SetLSSpheresRadiusStride(VkDeviceSize stride); |
| GeometryKHR& SetLSSpheresIndexingMode(VkRayTracingLssIndexingModeNV index_mode); |
| GeometryKHR& SetLSSpheresIndexDataNull(); |
| GeometryKHR& SetLSSpheresIndexAddressZero(); |
| GeometryKHR& SetLSSpheresVertexAddressZero(); |
| GeometryKHR& SetLSSpheresRadiusAddressZero(); |
| |
| const auto& GetVkObj() const { return vk_obj_; } |
| VkAccelerationStructureBuildRangeInfoKHR GetFullBuildRange() const; |
| const auto& GetTriangles() const { return triangles_; } |
| const auto& GetAABBs() const { return aabbs_; } |
| auto& GetInstance() { return instances_; } |
| VkGeometryFlagsKHR GetFlags() { return vk_obj_.flags; }; |
| |
| private: |
| VkAccelerationStructureGeometryKHR vk_obj_; |
| Type type_ = Type::_INTERNAL_UNSPECIFIED; |
| uint32_t primitive_count_ = 0; |
| Triangles triangles_; |
| AABBs aabbs_; |
| Instances instances_; |
| Spheres spheres_; |
| LSSpheres lsspheres_; |
| }; |
| |
| class AccelerationStructureKHR : public vkt::internal::NonDispHandle<VkAccelerationStructureKHR> { |
| public: |
| ~AccelerationStructureKHR() { Destroy(); } |
| AccelerationStructureKHR(const vkt::Device* device); |
| AccelerationStructureKHR(AccelerationStructureKHR&& rhs) = default; |
| AccelerationStructureKHR& operator=(AccelerationStructureKHR&&) = default; |
| AccelerationStructureKHR& operator=(const AccelerationStructureKHR&) = delete; |
| |
| AccelerationStructureKHR& SetSize(VkDeviceSize size); |
| AccelerationStructureKHR& SetOffset(VkDeviceSize offset); |
| AccelerationStructureKHR& SetType(VkAccelerationStructureTypeKHR type); |
| AccelerationStructureKHR& SetFlags(VkAccelerationStructureCreateFlagsKHR flags); |
| AccelerationStructureKHR& SetDeviceBuffer(vkt::Buffer&& buffer); |
| AccelerationStructureKHR& SetDeviceBufferMemoryAllocateFlags(VkMemoryAllocateFlags memory_allocate_flags); |
| AccelerationStructureKHR& SetDeviceBufferMemoryPropertyFlags(VkMemoryPropertyFlags memory_property_flags); |
| AccelerationStructureKHR& SetDeviceBufferInitNoMem(bool buffer_init_no_mem); |
| // Set it to 0 to skip buffer initialization at Build() step |
| AccelerationStructureKHR& SetBufferUsageFlags(VkBufferUsageFlags usage_flags); |
| |
| VkDeviceAddress GetBufferDeviceAddress() const; |
| VkDeviceAddress GetAccelerationStructureDeviceAddress() const; |
| |
| // Null check is done in BuildGeometryInfoKHR::Build(). Object is build iff it is not null. |
| void SetNull(bool is_null) { is_null_ = is_null; } |
| bool IsNull() const { return is_null_; } |
| void Create(); |
| bool IsBuilt() const { return initialized(); } |
| void Destroy(); |
| |
| auto& GetBuffer() { return device_buffer_; } |
| |
| private: |
| const vkt::Device* device_; |
| bool is_null_ = false; |
| VkAccelerationStructureCreateInfoKHR vk_info_; |
| vkt::Buffer device_buffer_; |
| VkMemoryAllocateFlags buffer_memory_allocate_flags_{}; |
| VkMemoryPropertyFlags buffer_memory_property_flags_{}; |
| VkBufferUsageFlags buffer_usage_flags_{}; |
| bool buffer_init_no_mem_ = false; |
| }; |
| |
| class BuildGeometryInfoKHR { |
| public: |
| ~BuildGeometryInfoKHR() = default; |
| BuildGeometryInfoKHR(const vkt::Device* device); |
| BuildGeometryInfoKHR(BuildGeometryInfoKHR&&) = default; |
| BuildGeometryInfoKHR& operator=(BuildGeometryInfoKHR&& rhs) = default; |
| BuildGeometryInfoKHR& operator=(const BuildGeometryInfoKHR&) = delete; |
| |
| BuildGeometryInfoKHR& SetType(VkAccelerationStructureTypeKHR type); |
| BuildGeometryInfoKHR& SetBuildType(VkAccelerationStructureBuildTypeKHR build_type); |
| BuildGeometryInfoKHR& SetMode(VkBuildAccelerationStructureModeKHR mode); |
| BuildGeometryInfoKHR& SetFlags(VkBuildAccelerationStructureFlagsKHR flags); |
| BuildGeometryInfoKHR& AddFlags(VkBuildAccelerationStructureFlagsKHR flags); |
| BuildGeometryInfoKHR& SetGeometries(std::vector<GeometryKHR>&& geometries); |
| BuildGeometryInfoKHR& SetBuildRanges(std::vector<VkAccelerationStructureBuildRangeInfoKHR> build_range_infos); |
| // Using the same pointers for src and dst is supported |
| BuildGeometryInfoKHR& SetSrcAS(std::shared_ptr<AccelerationStructureKHR> src_as); |
| BuildGeometryInfoKHR& SetDstAS(std::shared_ptr<AccelerationStructureKHR> dst_as); |
| BuildGeometryInfoKHR& SetScratchBuffer(std::shared_ptr<vkt::Buffer> scratch_buffer); |
| BuildGeometryInfoKHR& SetHostScratchBuffer(std::shared_ptr<std::vector<uint8_t>> host_scratch); |
| BuildGeometryInfoKHR& SetDeviceScratchOffset(VkDeviceAddress offset); |
| BuildGeometryInfoKHR& SetDeviceScratchAdditionalFlags(VkBufferUsageFlags additional_flags); |
| BuildGeometryInfoKHR& SetEnableScratchBuild(bool build_scratch); |
| // Should be 0 or 1 |
| BuildGeometryInfoKHR& SetInfoCount(uint32_t info_count); |
| BuildGeometryInfoKHR& SetNullInfos(bool use_null_infos); |
| BuildGeometryInfoKHR& SetNullGeometries(bool use_null_geometries); |
| BuildGeometryInfoKHR& SetNullBuildRangeInfos(bool use_null_build_range_infos); |
| BuildGeometryInfoKHR& SetDeferredOp(VkDeferredOperationKHR deferred_op); |
| BuildGeometryInfoKHR& SetUpdateDstAccelStructSizeBeforeBuild(bool update_before_build); |
| BuildGeometryInfoKHR& SetIndirectStride(uint32_t indirect_stride); |
| BuildGeometryInfoKHR& SetIndirectDeviceAddress(std::optional<VkDeviceAddress> indirect_buffer_address); |
| |
| // Those functions call Build() on internal resources (geometries, src and dst acceleration structures, scratch buffer), |
| // then will build/update an acceleration structure. |
| void BuildCmdBuffer(VkCommandBuffer cmd_buffer); |
| void BuildCmdBufferIndirect(VkCommandBuffer cmd_buffer); |
| void BuildHost(); |
| |
| void UpdateDstAccelStructSize(); |
| void SetupBuild(bool is_on_device_build, bool use_ppGeometries = true); |
| |
| // These will only setup the geometries lists and the pertaining build ranges |
| void VkCmdBuildAccelerationStructuresKHR(VkCommandBuffer cmd_buffer, bool use_ppGeometries = true); |
| // TODO - indirect build not fully implemented, only cared about having a valid call at time of writing |
| void VkCmdBuildAccelerationStructuresIndirectKHR(VkCommandBuffer cmd_buffer); |
| void VkBuildAccelerationStructuresKHR(); |
| |
| auto& GetInfo() { return vk_info_; } |
| auto& GetGeometries() { return geometries_; } |
| auto& GetSrcAS() { return src_as_; } |
| auto& GetDstAS() { return dst_as_; } |
| const auto& GetScratchBuffer() const { return device_scratch_; } |
| VkAccelerationStructureBuildSizesInfoKHR GetSizeInfo(bool use_ppGeometries = true); |
| std::vector<VkAccelerationStructureBuildRangeInfoKHR> GetBuildRangeInfosFromGeometries(); |
| |
| private: |
| friend void BuildAccelerationStructuresKHR(VkCommandBuffer cmd_buffer, std::vector<BuildGeometryInfoKHR>& infos); |
| friend void BuildHostAccelerationStructuresKHR(VkDevice device, std::vector<BuildGeometryInfoKHR>& infos); |
| |
| const vkt::Device* device_; |
| uint32_t vk_info_count_ = 1; |
| bool use_null_infos_ = false; |
| bool use_null_geometries_ = false; |
| bool use_null_build_range_infos_ = false; |
| bool update_dst_as_size_before_build_ = false; |
| VkAccelerationStructureBuildGeometryInfoKHR vk_info_; |
| VkAccelerationStructureBuildTypeKHR build_type_; |
| std::vector<GeometryKHR> geometries_; |
| std::shared_ptr<AccelerationStructureKHR> src_as_, dst_as_; |
| bool build_scratch_ = true; |
| VkDeviceAddress device_scratch_offset_ = 0; |
| VkBufferUsageFlags device_scratch_additional_flags_ = 0; |
| std::shared_ptr<vkt::Buffer> device_scratch_; |
| std::shared_ptr<std::vector<uint8_t>> host_scratch_; |
| std::unique_ptr<vkt::Buffer> indirect_buffer_; |
| std::optional<VkDeviceAddress> indirect_buffer_address_{}; |
| uint32_t indirect_stride_ = sizeof(VkAccelerationStructureBuildRangeInfoKHR); |
| std::vector<VkAccelerationStructureBuildRangeInfoKHR> build_range_infos_; |
| VkDeferredOperationKHR deferred_op_ = VK_NULL_HANDLE; |
| }; |
| |
| // Helper functions |
| void BuildAccelerationStructuresKHR(VkCommandBuffer cmd_buffer, std::vector<BuildGeometryInfoKHR>& infos); |
| void BuildHostAccelerationStructuresKHR(VkDevice device, std::vector<BuildGeometryInfoKHR>& infos); |
| |
| // Helper functions providing simple, valid objects. |
| // Calling Build() on them without further modifications results in a usable and valid Vulkan object. |
| // Typical usage probably is: |
| // { |
| // vkt::as::BuildGeometryInfoKHR as_build_info = BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| // |
| // // for instance: |
| // as_build_info.GetDstAS().SetBufferMemoryPropertyFlags(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); |
| // as_build_info.SetFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR); |
| // |
| // m_command_buffer.Begin(); |
| // as_build_info.BuildCmdBuffer(*m_device, m_command_buffer); |
| // m_command_buffer.End(); |
| // } |
| namespace blueprint { |
| GeometryKHR GeometrySimpleOnDeviceIndexedTriangleInfo(const vkt::Device& device, size_t triangles_count = 1, |
| VkBufferUsageFlags additional_geometry_buffer_flags = 0); |
| GeometryKHR GeometrySimpleOnDeviceTriangleInfo(const vkt::Device& device, VkBufferUsageFlags additional_geometry_buffer_flags = 0); |
| |
| GeometryKHR GeometrySimpleOnHostIndexedTriangleInfo(); |
| |
| // Cube centered at position (0,0,0), 2.0f wide |
| GeometryKHR GeometryCubeOnDeviceInfo(const vkt::Device& device); |
| |
| GeometryKHR GeometrySimpleOnDeviceAABBInfo(const vkt::Device& device, VkBufferUsageFlags additional_geometry_buffer_flags = 0); |
| GeometryKHR GeometrySimpleOnHostAABBInfo(); |
| |
| GeometryKHR GeometrySimpleDeviceInstance(const vkt::Device& device, VkAccelerationStructureKHR device_blas); |
| |
| GeometryKHR GeometrySimpleOnDeviceSpheresInfo(const vkt::Device& device); |
| GeometryKHR GeometrySimpleOnHostSpheresInfo(); |
| GeometryKHR GeometrySimpleOnDeviceLSSpheresInfo(const vkt::Device& device); |
| GeometryKHR GeometrySimpleOnHostLSSpheresInfo(); |
| |
| std::shared_ptr<AccelerationStructureKHR> AccelStructNull(const vkt::Device& device); |
| std::shared_ptr<AccelerationStructureKHR> AccelStructSimpleOnDeviceBottomLevel(const vkt::Device& device, VkDeviceSize size); |
| std::shared_ptr<AccelerationStructureKHR> AccelStructSimpleOnHostBottomLevel(const vkt::Device& device, VkDeviceSize size); |
| std::shared_ptr<AccelerationStructureKHR> AccelStructSimpleOnDeviceTopLevel(const vkt::Device& device, VkDeviceSize size); |
| |
| BuildGeometryInfoKHR BuildGeometryInfoSimpleOnDeviceBottomLevel(const vkt::Device& device, |
| GeometryKHR::Type geometry_type = GeometryKHR::Type::Triangle); |
| BuildGeometryInfoKHR BuildGeometryInfoOnDeviceBottomLevel(const vkt::Device& device, GeometryKHR&& geometry); |
| |
| BuildGeometryInfoKHR BuildGeometryInfoSimpleOnHostBottomLevel(const vkt::Device& device, |
| GeometryKHR::Type geometry_type = GeometryKHR::Type::Triangle); |
| |
| // Create an on device TLAS pointing to one BLAS |
| // on_device_bottom_level_geometry must have been built previously, and on the device |
| BuildGeometryInfoKHR BuildGeometryInfoSimpleOnDeviceTopLevel(const vkt::Device& device, |
| const vkt::as::AccelerationStructureKHR& on_device_blas); |
| // Create an on host TLAS pointing to one BLAS |
| // on_host_bottom_level_geometry must have been built previously, and on the host |
| BuildGeometryInfoKHR BuildGeometryInfoSimpleOnHostTopLevel(const vkt::Device& device, |
| std::shared_ptr<BuildGeometryInfoKHR> on_host_blas); |
| |
| // Create and build a top level acceleration structure |
| BuildGeometryInfoKHR BuildOnDeviceTopLevel(const vkt::Device& device, vkt::Queue& queue, vkt::CommandBuffer& cmd_buffer); |
| |
| // Build Top Level Acceleration Structure: |
| // 2 instances of the cube, at different positions |
| // They are supposed to invoke 2 different closest hist shaders, |
| // through different instanceShaderBindingTableRecordOffset |
| // clang-format off |
| /* |
| cube instance 2, translation (x = 0, y = 0, z = 50), instanceShaderBindingTableRecordOffset = 1 |
| +----+ |
| | 2 | |
| +----+ |
| |
| Z |
| ^ |
| | +----+ |
| +---> X | 1 | cube instance 1, translation (x = 50, y = 0, z = 0), instanceShaderBindingTableRecordOffset = 0 |
| +----+ |
| */ |
| // clang-format on |
| vkt::as::BuildGeometryInfoKHR GetCubesTLAS(vkt::Device& device, vkt::CommandBuffer& cb, vkt::Queue& queue, |
| std::shared_ptr<vkt::as::BuildGeometryInfoKHR>& out_cube_blas); |
| |
| vkt::as::BuildGeometryInfoKHR CreateTLAS(vkt::Device& device, std::vector<vkt::as::GeometryKHR>&& blas_vec); |
| |
| } // namespace blueprint |
| } // namespace as |
| |
| namespace rt { |
| |
| struct TraceRaysSbt { |
| VkStridedDeviceAddressRegionKHR ray_gen_sbt{}; |
| VkStridedDeviceAddressRegionKHR miss_sbt{}; |
| VkStridedDeviceAddressRegionKHR hit_sbt{}; |
| VkStridedDeviceAddressRegionKHR callable_sbt{}; |
| }; |
| |
| class Pipeline { |
| public: |
| Pipeline(VkLayerTest& test, vkt::Device* device); |
| ~Pipeline(); |
| |
| // Build settings |
| // -------------- |
| void AddCreateInfoFlags(VkPipelineCreateFlags flags); |
| void AddCreateInfoFlags2(VkPipelineCreateFlags2 flags); |
| void InitLibraryInfo(uint32_t max_pipeline_payload_size, bool is_exe_pipeline); |
| |
| void AddBinding(VkDescriptorType descriptor_type, uint32_t binding, uint32_t descriptor_count = 1); |
| void CreateDescriptorSet(); |
| void AddDescriptorIndexingBinding(VkDescriptorType descriptor_type, uint32_t binding, VkDescriptorBindingFlags flags = 0, |
| uint32_t descriptor_count = 1); |
| void CreateDescriptorIndexingSet(); |
| // *If CreateDescriptorSet() is never called*, this method will hook supplied descriptor set layouts |
| void SetPipelineSetLayouts(uint32_t set_layout_count, const VkDescriptorSetLayout* set_layouts); |
| |
| void SetPushConstantRangeSize(uint32_t byte_size); |
| void SetGlslRayGenShader(const char* glsl, void* pNext = nullptr); |
| void AddSpirvRayGenShader(const char* spirv, const char* entry_point); |
| void AddSlangRayGenShader(const char* slang, const char* entry_point); |
| void AddGlslMissShader(const char* glsl); |
| void AddSpirvMissShader(const char* spirv, const char* entry_point); |
| void AddSlangMissShader(const char* slang, const char* entry_point); |
| void AddGlslClosestHitShader(const char* glsl); |
| void AddSpirvClosestHitShader(const char* spirv, const char* entry_point); |
| void AddSlangClosestHitShader(const char* slang, const char* entry_point); |
| void AddLibrary(const Pipeline& library); |
| void AddDynamicState(VkDynamicState dynamic_state); |
| |
| // Build |
| // ----- |
| void Build(); |
| void BuildPipeline(); |
| void BuildSbt(); |
| void DeferBuild(); |
| |
| // Get |
| // --- |
| VkShaderObj& GetRayGenShader(uint32_t ray_gen_i); |
| const auto& Handle() { return rt_pipeline_; } |
| operator VkPipeline() const { return rt_pipeline_; } |
| vkt::PipelineLayout& GetPipelineLayout() { return pipeline_layout_; } |
| OneOffDescriptorSet& GetDescriptorSet() { |
| assert(desc_set_); |
| return *desc_set_; |
| } |
| OneOffDescriptorIndexingSet& GetDescriptorIndexingSet() { |
| assert(desc_indexing_set_); |
| return *desc_indexing_set_; |
| } |
| TraceRaysSbt GetTraceRaysSbt(uint32_t ray_gen_shader_i = 0); |
| const vkt::Buffer& GetTraceRaysSbtBuffer(); |
| vkt::Buffer GetTraceRaysSbtIndirectBuffer(uint32_t ray_gen_shader_i, uint32_t width, uint32_t height, uint32_t depth); |
| uint32_t GetShaderGroupsCount(); |
| std::vector<uint8_t> GetRayTracingShaderGroupHandles(); |
| std::vector<uint8_t> GetRayTracingCaptureReplayShaderGroupHandles(); |
| std::vector<VkRayTracingShaderGroupCreateInfoKHR> GetRayTracingShaderGroupCreateInfos(); |
| |
| private: |
| uint32_t GetRayGenShadersCount() const; |
| uint32_t GetMissShadersCount() const; |
| uint32_t GetClosestHitShadersCount() const; |
| |
| private: |
| VkLayerTest& test_; |
| vkt::Device* device_; |
| VkPipelineCreateFlags2CreateInfo create_flags_2_ = {}; |
| VkRayTracingPipelineCreateInfoKHR vk_info_{}; |
| uint32_t push_constant_range_size_ = 0; |
| std::vector<VkDescriptorSetLayoutBinding> bindings_{}; |
| std::unique_ptr<OneOffDescriptorSet> desc_set_{}; |
| std::vector<OneOffDescriptorIndexingSet::Binding> desc_indexing_bindings_{}; |
| std::unique_ptr<OneOffDescriptorIndexingSet> desc_indexing_set_{}; |
| VkPipelineLayoutCreateInfo pipeline_layout_ci_; |
| vkt::PipelineLayout pipeline_layout_{}; |
| std::vector<VkDynamicState> dynamic_states{}; |
| std::vector<std::unique_ptr<VkShaderObj>> ray_gen_shaders_{}; |
| std::vector<std::unique_ptr<VkShaderObj>> miss_shaders_{}; |
| std::vector<std::unique_ptr<VkShaderObj>> closest_hit_shaders_{}; |
| std::vector<VkRayTracingShaderGroupCreateInfoKHR> shader_group_cis_{}; |
| vkt::Pipeline rt_pipeline_{}; |
| VkDeferredOperationKHR deferred_op_ = VK_NULL_HANDLE; |
| vkt::Buffer sbt_buffer_{}; |
| VkRayTracingPipelineInterfaceCreateInfoKHR rt_pipeline_interface_info_{}; |
| VkPipelineLibraryCreateInfoKHR pipeline_lib_info_{}; |
| std::vector<const Pipeline*> libraries_{}; |
| std::vector<VkPipeline> library_handles_{}; |
| }; |
| } // namespace rt |
| |
| } // namespace vkt |