From 762f6710f6f8382c6dd4f50b97a4cd68e60930e2 Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Tue, 14 Apr 2020 11:55:14 +0200 Subject: [PATCH 01/15] swapchain: set swapchain image layout to general when used as storage --- vulkano/src/image/swapchain.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vulkano/src/image/swapchain.rs b/vulkano/src/image/swapchain.rs index 0dec2a576e..c820e518e7 100644 --- a/vulkano/src/image/swapchain.rs +++ b/vulkano/src/image/swapchain.rs @@ -193,7 +193,7 @@ unsafe impl ImageViewAccess for SwapchainImage { #[inline] fn descriptor_set_storage_image_layout(&self) -> ImageLayout { - ImageLayout::ShaderReadOnlyOptimal + ImageLayout::General } #[inline] From f0996eb6ece7caef9d30c1028bedd88bd4599fb7 Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Tue, 14 Apr 2020 13:50:52 +0200 Subject: [PATCH 02/15] vk-sys: Add missing primitives for raytracing --- CHANGELOG_VK_SYS.md | 285 ++++++++++++++++++ vk-sys/src/lib.rs | 686 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 965 insertions(+), 6 deletions(-) diff --git a/CHANGELOG_VK_SYS.md b/CHANGELOG_VK_SYS.md index 14369ec51e..09873b4e23 100644 --- a/CHANGELOG_VK_SYS.md +++ b/CHANGELOG_VK_SYS.md @@ -1,5 +1,290 @@ # Unreleased +- Added support for `NV_ray_tracing` and `KHR_ray_tracing` + + type `DeviceAddress` + + type `AccelerationStructureKHR` + + type `AccelerationStructureNV` + + type `RayTracingShaderGroupTypeKHR` + + type `RayTracingShaderGroupTypeNV` + + type `GeometryTypeKHR` + + type `GeometryTypeNV` + + type `AccelerationStructureTypeKHR` + + type `AccelerationStructureTypeNV` + + type `CopyAccelerationStructureModeKHR` + + type `CopyAccelerationStructureModeNV` + + type `AccelerationStructureMemoryRequirementsTypeKHR` + + type `AccelerationStructureMemoryRequirementsTypeNV` + + type `GeometryFlagBitsKHR` + + type `GeometryFlagsKHR` + + type `GeometryFlagsNV` + + type `GeometryFlagBitsNV` + + type `GeometryInstanceFlagBitsKHR` + + type `GeometryInstanceFlagsKHR` + + type `GeometryInstanceFlagsNV` + + type `GeometryInstanceFlagBitsNV` + + type `BuildAccelerationStructureFlagBitsKHR` + + type `BuildAccelerationStructureFlagsKHR` + + type `BuildAccelerationStructureFlagsNV` + + type `BuildAccelerationStructureFlagBitsNV` + + type `AccelerationStructureBuildTypeKHR` + + const `SHADER_UNUSED` + + const `STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2` + + const `STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES` + + const `STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR` + + const `STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR` + + const `STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR` + + const `STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR` + + const `STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR` + + const `STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR` + + const `STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR` + + const `STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR` + + const `STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR` + + const `STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR` + + const `STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR` + + const `STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_KHR` + + const `STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR` + + const `STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR` + + const `STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR` + + const `STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR` + + const `STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR` + + const `STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR` + + const `STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR` + + const `STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR` + + const `STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR` + + const `STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV` + + const `STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV` + + const `STRUCTURE_TYPE_GEOMETRY_NV` + + const `STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV` + + const `STRUCTURE_TYPE_GEOMETRY_AABB_NV` + + const `STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV` + + const `STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV` + + const `STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV` + + const `STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV` + + const `STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO` + + const `STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR` + + const `STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV` + + const `STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV` + + const `DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT` + + const `DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR` + + const `DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV` + + const `PIPELINE_BIND_POINT_RAY_TRACING_KHR` + + const `PIPELINE_BIND_POINT_RAY_TRACING_NV` + + const `INDEX_TYPE_NONE_KHR` + + const `INDEX_TYPE_UINT8_EXT` + + const `INDEX_TYPE_NONE_NV` + + const `PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT` + + const `PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT` + + const `PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR` + + const `PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR` + + const `PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV` + + const `PIPELINE_STAGE_TASK_SHADER_BIT_NV` + + const `PIPELINE_STAGE_MESH_SHADER_BIT_NV` + + const `PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT` + + const `PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV` + + const `PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV` + + const `PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV` + + const `BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT` + + const `BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT` + + const `BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT` + + const `BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT` + + const `BUFFER_USAGE_RAY_TRACING_BIT_KHR` + + const `BUFFER_USAGE_RAY_TRACING_BIT_NV` + + const `BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT` + + const `BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR` + + const `SHADER_STAGE_RAYGEN_BIT_KHR` + + const `SHADER_STAGE_ANY_HIT_BIT_KHR` + + const `SHADER_STAGE_CLOSEST_HIT_BIT_KHR` + + const `SHADER_STAGE_MISS_BIT_KHR` + + const `SHADER_STAGE_INTERSECTION_BIT_KHR` + + const `SHADER_STAGE_CALLABLE_BIT_KHR` + + const `SHADER_STAGE_TASK_BIT_NV` + + const `SHADER_STAGE_MESH_BIT_NV` + + const `SHADER_STAGE_RAYGEN_BIT_NV` + + const `SHADER_STAGE_ANY_HIT_BIT_NV` + + const `SHADER_STAGE_CLOSEST_HIT_BIT_NV` + + const `SHADER_STAGE_MISS_BIT_NV` + + const `SHADER_STAGE_INTERSECTION_BIT_NV` + + const `SHADER_STAGE_CALLABLE_BIT_NV` + + const `ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT` + + const `ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT` + + const `ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT` + + const `ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT` + + const `ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT` + + const `ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR` + + const `ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR` + + const `ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV` + + const `ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT` + + const `ACCESS_COMMAND_PREPROCESS_READ_BIT_NV` + + const `ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV` + + const `ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV` + + const `ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV` + + const `OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR` + + const `RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR` + + const `RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR` + + const `RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR` + + const `RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV` + + const `RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV` + + const `RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV` + + const `RAY_TRACING_SHADER_GROUP_TYPE_BEGIN_RANGE_KHR` + + const `RAY_TRACING_SHADER_GROUP_TYPE_END_RANGE_KHR` + + const `RAY_TRACING_SHADER_GROUP_TYPE_RANGE_SIZE_KHR` + + const `RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR` + + const `GEOMETRY_TYPE_TRIANGLES_KHR` + + const `GEOMETRY_TYPE_AABBS_KHR` + + const `GEOMETRY_TYPE_INSTANCES_KHR` + + const `GEOMETRY_TYPE_TRIANGLES_NV` + + const `GEOMETRY_TYPE_AABBS_NV` + + const `GEOMETRY_TYPE_BEGIN_RANGE_KHR` + + const `GEOMETRY_TYPE_END_RANGE_KHR` + + const `GEOMETRY_TYPE_RANGE_SIZE_KHR` + + const `GEOMETRY_TYPE_MAX_ENUM_KHR` + + const `ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR` + + const `ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR` + + const `ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV` + + const `ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV` + + const `ACCELERATION_STRUCTURE_TYPE_BEGIN_RANGE_KHR` + + const `ACCELERATION_STRUCTURE_TYPE_END_RANGE_KHR` + + const `ACCELERATION_STRUCTURE_TYPE_RANGE_SIZE_KHR` + + const `ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_KHR` + + const `COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR` + + const `COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR` + + const `COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR` + + const `COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR` + + const `COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV` + + const `COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV` + + const `COPY_ACCELERATION_STRUCTURE_MODE_BEGIN_RANGE_KHR` + + const `COPY_ACCELERATION_STRUCTURE_MODE_END_RANGE_KHR` + + const `COPY_ACCELERATION_STRUCTURE_MODE_RANGE_SIZE_KHR` + + const `COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR` + + const `ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR` + + const `ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR` + + const `ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR` + + const `ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV` + + const `ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV` + + const `ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV` + + const `ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BEGIN_RANGE_KHR` + + const `ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_END_RANGE_KHR` + + const `ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_RANGE_SIZE_KHR` + + const `ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_KHR` + + const `GEOMETRY_OPAQUE_BIT_KHR` + + const `GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR` + + const `GEOMETRY_OPAQUE_BIT_NV` + + const `GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV` + + const `GEOMETRY_FLAG_BITS_MAX_ENUM_KHR` + + const `GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR` + + const `GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR` + + const `GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR` + + const `GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR` + + const `GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV` + + const `GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV` + + const `GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV` + + const `GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV` + + const `GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_KHR` + + const `BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR` + + const `BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR` + + const `BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR` + + const `BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR` + + const `BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR` + + const `BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV` + + const `BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV` + + const `BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV` + + const `BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV` + + const `BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV` + + const `BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_KHR` + + const `ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR` + + const `ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR` + + const `ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR` + + const `ACCELERATION_STRUCTURE_BUILD_TYPE_BEGIN_RANGE_KHR` + + const `ACCELERATION_STRUCTURE_BUILD_TYPE_END_RANGE_KHR` + + const `ACCELERATION_STRUCTURE_BUILD_TYPE_RANGE_SIZE_KHR` + + const `ACCELERATION_STRUCTURE_BUILD_TYPE_MAX_ENUM_KHR` + + union `DeviceOrHostAddressKHR` + + union `DeviceOrHostAddressConstKHR` + + struct `PhysicalDeviceFeatures2` + + struct `PhysicalDeviceBufferDeviceAddressFeatures` + + struct `BufferMemoryRequirementsInfo2` + + struct `ImageMemoryRequirementsInfo2` + + struct `MemoryRequirements2` + + struct `PipelineLibraryCreateInfoKHR` + + struct `AccelerationStructureBuildOffsetInfoKHR` + + struct `RayTracingShaderGroupCreateInfoNV` + + struct `RayTracingShaderGroupCreateInfoKHR` + + struct `RayTracingPipelineCreateInfoNV` + + struct `RayTracingPipelineInterfaceCreateInfoKHR` + + struct `RayTracingPipelineCreateInfoKHR` + + struct `GeometryTrianglesNV` + + struct `GeometryAABBNV` + + struct `GeometryDataNV` + + struct `GeometryNV` + + struct `AccelerationStructureInfoNV` + + struct `AccelerationStructureCreateInfoNV` + + struct `AccelerationStructureCreateGeometryTypeInfoKHR` + + struct `AccelerationStructureCreateInfoKHR` + + struct `BindAccelerationStructureMemoryInfoKHR` + + struct `BindAccelerationStructureMemoryInfoNV` + + struct `WriteDescriptorSetAccelerationStructureKHR` + + struct `WriteDescriptorSetAccelerationStructureNV` + + struct `AccelerationStructureMemoryRequirementsInfoNV` + + struct `AccelerationStructureMemoryRequirementsInfoKHR` + + struct `PhysicalDeviceRayTracingFeaturesKHR` + + struct `PhysicalDeviceRayTracingPropertiesNV` + + struct `PhysicalDeviceRayTracingPropertiesKHR` + + struct `TransformMatrixKHR` + + struct `TransformMatrixNV` + + struct `AabbPositionsKHR` + + struct `AabbPositionsNV` + + struct `AccelerationStructureInstanceKHR` + + struct `AccelerationStructureInstanceNV` + + struct `AccelerationStructureGeometryTrianglesDataKHR` + + struct `AccelerationStructureGeometryAabbsDataKHR` + + struct `AccelerationStructureGeometryInstancesDataKHR` + + struct `AccelerationStructureGeometryDataKHR` + + struct `AccelerationStructureGeometryKHR` + + struct `AccelerationStructureBuildGeometryInfoKHR` + + struct `BufferDeviceAddressInfo` + + struct `BufferDeviceAddressInfoKHR` + + struct `AccelerationStructureDeviceAddressInfoKHR` + + struct `AccelerationStructureVersionKHR` + + struct `StridedBufferRegionKHR` + + struct `TraceRaysIndirectCommandKHR` + + struct `CopyAccelerationStructureToMemoryInfoKHR` + + struct `CopyMemoryToAccelerationStructureInfoKHR` + + struct `CopyAccelerationStructureInfoKHR` + + function `GetPhysicalDeviceFeatures2` + + function `CreateAccelerationStructureNV` + + function `DestroyAccelerationStructureKHR` + + function `DestroyAccelerationStructureNV` + + function `GetAccelerationStructureMemoryRequirementsNV` + + function `BindAccelerationStructureMemoryKHR` + + function `BindAccelerationStructureMemoryNV` + + function `CmdBuildAccelerationStructureNV` + + function `CmdCopyAccelerationStructureNV` + + function `CmdTraceRaysNV` + + function `CreateRayTracingPipelinesNV` + + function `GetRayTracingShaderGroupHandlesKHR` + + function `GetRayTracingShaderGroupHandlesNV` + + function `GetAccelerationStructureHandleNV` + + function `CmdWriteAccelerationStructuresPropertiesNV` + + function `CompileDeferredNV` + + function `CreateAccelerationStructureKHR` + + function `GetAccelerationStructureMemoryRequirementsKHR` + + function `CmdBuildAccelerationStructureIndirectKHR` + + function `BuildAccelerationStructureKHR` + + function `CopyAccelerationStructureKHR` + + function `CopyAccelerationStructureToMemoryKHR` + + function `CopyMemoryToAccelerationStructureKHR` + + function `WriteAccelerationStructuresPropertiesKHR` + + function `CmdCopyAccelerationStructureKHR` + + function `CmdCopyAccelerationStructureToMemoryKHR` + + function `CmdCopyMemoryToAccelerationStructureKHR` + + function `CmdTraceRaysKHR` + + function `CreateRayTracingPipelinesKHR` + + function `GetBufferDeviceAddressKHR` + + function `GetAccelerationStructureDeviceAddressKHR` + + function `GetRayTracingCaptureReplayShaderGroupHandlesKHR` + + function `CmdTraceRaysIndirectKHR` + + function `GetDeviceAccelerationStructureCompatibilityKHR` + # Version 0.5.1 (2020-02-09) - Added support for `VK_EXT_full_screen_exclusive` diff --git a/vk-sys/src/lib.rs b/vk-sys/src/lib.rs index 9e8316eba8..02320845fb 100644 --- a/vk-sys/src/lib.rs +++ b/vk-sys/src/lib.rs @@ -25,6 +25,7 @@ pub type Flags = u32; pub type Bool32 = u32; pub type DeviceSize = u64; pub type SampleMask = u32; +pub type DeviceAddress = u64; pub type Instance = usize; pub type PhysicalDevice = usize; @@ -58,6 +59,9 @@ pub type DisplayKHR = u64; pub type DisplayModeKHR = u64; pub type DescriptorUpdateTemplateKHR = u64; +pub type AccelerationStructureKHR = u64; +pub type AccelerationStructureNV = AccelerationStructureKHR; + pub const LOD_CLAMP_NONE: f32 = 1000.0; pub const REMAINING_MIP_LEVELS: u32 = 0xffffffff; pub const REMAINING_ARRAY_LAYERS: u32 = 0xffffffff; @@ -74,6 +78,7 @@ pub const MAX_MEMORY_HEAPS: u32 = 16; pub const MAX_EXTENSION_NAME_SIZE: u32 = 256; pub const MAX_DESCRIPTION_SIZE: u32 = 256; pub const NULL_HANDLE: u64 = 0; +pub const SHADER_UNUSED: u32 = 0xffffffff; pub type PipelineCacheHeaderVersion = u32; pub const PIPELINE_CACHE_HEADER_VERSION_ONE: u32 = 1; @@ -173,7 +178,7 @@ pub const STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT:u32 = 1000128001; pub const STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT:u32 = 1000128002; pub const STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT:u32 = 1000128003; pub const STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT:u32 = 1000128004; -pub const STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: u32 = 1000059000; +pub const STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: u32 = 1000059000; pub const STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR: u32 = 1000059001; pub const STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: u32 = 1000059002; pub const STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR: u32 = 1000059003; @@ -194,7 +199,42 @@ pub const STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR: u32 = 1000146001; pub const STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR: u32 = 1000146002; pub const STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR: u32 = 1000146003; pub const STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR: u32 = 1000146004; +pub const STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR: u32 = 1000165006; +pub const STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR: u32 = 1000165007; +pub const STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR: u32 = 1000150000; +pub const STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR: u32 = 1000150001; +pub const STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR: u32 = 1000150002; +pub const STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR: u32 = 1000150003; +pub const STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR: u32 = 1000150004; +pub const STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR: u32 = 1000150005; +pub const STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR: u32 = 1000150006; +pub const STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR: u32 = 1000150008; +pub const STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_KHR: u32 = 1000150009; +pub const STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR: u32 = 1000150010; +pub const STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR: u32 = 1000150011; +pub const STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR: u32 = 1000150012; +pub const STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR: u32 = 1000150013; +pub const STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR: u32 = 1000150014; +pub const STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR: u32 = 1000150015; +pub const STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR: u32 = 1000150016; +pub const STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR: u32 = 1000150017; +pub const STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR: u32 = 1000150018; +pub const STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV: u32 = 1000165000; +pub const STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV: u32 = 1000165001; +pub const STRUCTURE_TYPE_GEOMETRY_NV: u32 = 1000165003; +pub const STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV: u32 = 1000165004; +pub const STRUCTURE_TYPE_GEOMETRY_AABB_NV: u32 = 1000165005; +pub const STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV: u32 = 1000165008; +pub const STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV: u32 = 1000165009; +pub const STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV: u32 = 1000165011; +pub const STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV: u32 = 1000165012; +pub const STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO: u32 = 1000244001; pub const STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT: u32 = 1000255000; +pub const STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES: u32 = 1000257000; +pub const STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: u32 = 1000290000; +pub const STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: u32 = STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; +pub const STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV: u32 = STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR; +pub const STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV: u32 = STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR; pub type SystemAllocationScope = u32; pub const SYSTEM_ALLOCATION_SCOPE_COMMAND: u32 = 0; @@ -586,6 +626,9 @@ pub const DESCRIPTOR_TYPE_STORAGE_BUFFER: u32 = 7; pub const DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: u32 = 8; pub const DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: u32 = 9; pub const DESCRIPTOR_TYPE_INPUT_ATTACHMENT: u32 = 10; +pub const DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: u32 = 1000138000; +pub const DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: u32 = 1000165000; +pub const DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: u32 = DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; pub type AttachmentLoadOp = u32; pub const ATTACHMENT_LOAD_OP_LOAD: u32 = 0; @@ -599,6 +642,8 @@ pub const ATTACHMENT_STORE_OP_DONT_CARE: u32 = 1; pub type PipelineBindPoint = u32; pub const PIPELINE_BIND_POINT_GRAPHICS: u32 = 0; pub const PIPELINE_BIND_POINT_COMPUTE: u32 = 1; +pub const PIPELINE_BIND_POINT_RAY_TRACING_KHR: u32 = 1000165000; +pub const PIPELINE_BIND_POINT_RAY_TRACING_NV: u32 = PIPELINE_BIND_POINT_RAY_TRACING_KHR; pub type CommandBufferLevel = u32; pub const COMMAND_BUFFER_LEVEL_PRIMARY: u32 = 0; @@ -607,6 +652,9 @@ pub const COMMAND_BUFFER_LEVEL_SECONDARY: u32 = 1; pub type IndexType = u32; pub const INDEX_TYPE_UINT16: u32 = 0; pub const INDEX_TYPE_UINT32: u32 = 1; +pub const INDEX_TYPE_NONE_KHR: u32 = 1000165000; +pub const INDEX_TYPE_UINT8_EXT: u32 = 1000265000; +pub const INDEX_TYPE_NONE_NV: u32 = INDEX_TYPE_NONE_KHR; pub type SubpassContents = u32; pub const SUBPASS_CONTENTS_INLINE: u32 = 0; @@ -708,6 +756,17 @@ pub const PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT: u32 = 0x00002000; pub const PIPELINE_STAGE_HOST_BIT: u32 = 0x00004000; pub const PIPELINE_STAGE_ALL_GRAPHICS_BIT: u32 = 0x00008000; pub const PIPELINE_STAGE_ALL_COMMANDS_BIT: u32 = 0x00010000; +pub const PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT: u32 = 0x01000000; +pub const PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT: u32 = 0x00040000; +pub const PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR: u32 = 0x00200000; +pub const PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR: u32 = 0x02000000; +pub const PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV: u32 = 0x00400000; +pub const PIPELINE_STAGE_TASK_SHADER_BIT_NV: u32 = 0x00080000; +pub const PIPELINE_STAGE_MESH_SHADER_BIT_NV: u32 = 0x00100000; +pub const PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT: u32 = 0x00800000; +pub const PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV: u32 = 0x00020000; +pub const PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV: u32 = PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR; +pub const PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV: u32 = PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR; pub type PipelineStageFlags = Flags; pub type MemoryMapFlags = Flags; @@ -780,6 +839,14 @@ pub const BUFFER_USAGE_STORAGE_BUFFER_BIT: u32 = 0x00000020; pub const BUFFER_USAGE_INDEX_BUFFER_BIT: u32 = 0x00000040; pub const BUFFER_USAGE_VERTEX_BUFFER_BIT: u32 = 0x00000080; pub const BUFFER_USAGE_INDIRECT_BUFFER_BIT: u32 = 0x00000100; +pub const BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT: u32 = 0x00020000; +pub const BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT: u32 = 0x00000800; +pub const BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT: u32 = 0x00001000; +pub const BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT: u32 = 0x00000200; +pub const BUFFER_USAGE_RAY_TRACING_BIT_KHR: u32 = 0x00000400; +pub const BUFFER_USAGE_RAY_TRACING_BIT_NV: u32 = BUFFER_USAGE_RAY_TRACING_BIT_KHR; +pub const BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT: u32 = BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; +pub const BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR: u32 = BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; pub type BufferUsageFlags = Flags; pub type BufferViewCreateFlags = Flags; pub type ImageViewCreateFlags = Flags; @@ -804,6 +871,20 @@ pub const SHADER_STAGE_FRAGMENT_BIT: u32 = 0x00000010; pub const SHADER_STAGE_COMPUTE_BIT: u32 = 0x00000020; pub const SHADER_STAGE_ALL_GRAPHICS: u32 = 0x1F; pub const SHADER_STAGE_ALL: u32 = 0x7FFFFFFF; +pub const SHADER_STAGE_RAYGEN_BIT_KHR: u32 = 0x00000100; +pub const SHADER_STAGE_ANY_HIT_BIT_KHR: u32 = 0x00000200; +pub const SHADER_STAGE_CLOSEST_HIT_BIT_KHR: u32 = 0x00000400; +pub const SHADER_STAGE_MISS_BIT_KHR: u32 = 0x00000800; +pub const SHADER_STAGE_INTERSECTION_BIT_KHR: u32 = 0x00001000; +pub const SHADER_STAGE_CALLABLE_BIT_KHR: u32 = 0x00002000; +pub const SHADER_STAGE_TASK_BIT_NV: u32 = 0x00000040; +pub const SHADER_STAGE_MESH_BIT_NV: u32 = 0x00000080; +pub const SHADER_STAGE_RAYGEN_BIT_NV: u32 = SHADER_STAGE_RAYGEN_BIT_KHR; +pub const SHADER_STAGE_ANY_HIT_BIT_NV: u32 = SHADER_STAGE_ANY_HIT_BIT_KHR; +pub const SHADER_STAGE_CLOSEST_HIT_BIT_NV: u32 = SHADER_STAGE_CLOSEST_HIT_BIT_KHR; +pub const SHADER_STAGE_MISS_BIT_NV: u32 = SHADER_STAGE_MISS_BIT_KHR; +pub const SHADER_STAGE_INTERSECTION_BIT_NV: u32 = SHADER_STAGE_INTERSECTION_BIT_KHR; +pub const SHADER_STAGE_CALLABLE_BIT_NV: u32 = SHADER_STAGE_CALLABLE_BIT_KHR; pub type PipelineVertexInputStateCreateFlags = Flags; pub type PipelineInputAssemblyStateCreateFlags = Flags; pub type PipelineTessellationStateCreateFlags = Flags; @@ -867,6 +948,19 @@ pub const ACCESS_HOST_READ_BIT: u32 = 0x00002000; pub const ACCESS_HOST_WRITE_BIT: u32 = 0x00004000; pub const ACCESS_MEMORY_READ_BIT: u32 = 0x00008000; pub const ACCESS_MEMORY_WRITE_BIT: u32 = 0x00010000; +pub const ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT: u32 = 0x02000000; +pub const ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT: u32 = 0x04000000; +pub const ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT: u32 = 0x08000000; +pub const ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT: u32 = 0x00100000; +pub const ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT: u32 = 0x00080000; +pub const ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR: u32 = 0x00200000; +pub const ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR: u32 = 0x00400000; +pub const ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV: u32 = 0x00800000; +pub const ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT: u32 = 0x01000000; +pub const ACCESS_COMMAND_PREPROCESS_READ_BIT_NV: u32 = 0x00020000; +pub const ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV: u32 = 0x00040000; +pub const ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV: u32 = ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; +pub const ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV: u32 = ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR; pub type AccessFlags = Flags; @@ -1002,10 +1096,11 @@ pub const OBJECT_TYPE_OBJECT_TABLE_NVX: u32 = 1000086000; pub const OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX: u32 = 1000086001; pub const OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT: u32 = 1000128000; pub const OBJECT_TYPE_VALIDATION_CACHE_EXT: u32 = 1000160000; -pub const OBJECT_TYPE_ACCELERATION_STRUCTURE_NV: u32 = 1000165000; +pub const OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR: u32 = 1000165000; pub const OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL: u32 = 1000210000; pub const OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR: u32 = OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE; pub const OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR: u32 = OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION; +pub const OBJECT_TYPE_ACCELERATION_STRUCTURE_NV: u32 = OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR; pub type DebugUtilsMessageSeverityFlagBitsEXT = u32; pub const DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: u32 = 0x00000001; @@ -1057,6 +1152,117 @@ pub const FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT: u32 = 2; pub const FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT: u32 = 3; pub const FULL_SCREEN_EXCLUSIVE_MAX_ENUM_EXT: u32 = 0x7FFFFFFF; +pub type RayTracingShaderGroupTypeKHR = u32; +pub const RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR: u32 = 0; +pub const RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR: u32 = 1; +pub const RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR: u32 = 2; +pub const RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV: u32 = RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; +pub const RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV: u32 = RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; +pub const RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV: u32 = RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR; +pub const RAY_TRACING_SHADER_GROUP_TYPE_BEGIN_RANGE_KHR: u32 = RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; +pub const RAY_TRACING_SHADER_GROUP_TYPE_END_RANGE_KHR: u32 = RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR; +pub const RAY_TRACING_SHADER_GROUP_TYPE_RANGE_SIZE_KHR: u32 = (RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR - RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR + 1); +pub const RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR: u32 = 0x7FFFFFFF; +pub type RayTracingShaderGroupTypeNV = RayTracingShaderGroupTypeKHR; + +pub type GeometryTypeKHR = u32; +pub const GEOMETRY_TYPE_TRIANGLES_KHR: u32 = 0; +pub const GEOMETRY_TYPE_AABBS_KHR: u32 = 1; +pub const GEOMETRY_TYPE_INSTANCES_KHR: u32 = 1000150000; +pub const GEOMETRY_TYPE_TRIANGLES_NV: u32 = GEOMETRY_TYPE_TRIANGLES_KHR; +pub const GEOMETRY_TYPE_AABBS_NV: u32 = GEOMETRY_TYPE_AABBS_KHR; +pub const GEOMETRY_TYPE_BEGIN_RANGE_KHR: u32 = GEOMETRY_TYPE_TRIANGLES_KHR; +pub const GEOMETRY_TYPE_END_RANGE_KHR: u32 = GEOMETRY_TYPE_AABBS_KHR; +pub const GEOMETRY_TYPE_RANGE_SIZE_KHR: u32 = (GEOMETRY_TYPE_AABBS_KHR - GEOMETRY_TYPE_TRIANGLES_KHR + 1); +pub const GEOMETRY_TYPE_MAX_ENUM_KHR: u32 = 0x7FFFFFF; +pub type GeometryTypeNV = GeometryTypeKHR; + +pub type AccelerationStructureTypeKHR = u32; +pub const ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR: u32 = 0; +pub const ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR: u32 = 1; +pub const ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV: u32 = ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; +pub const ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV: u32 = ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; +pub const ACCELERATION_STRUCTURE_TYPE_BEGIN_RANGE_KHR: u32 = ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; +pub const ACCELERATION_STRUCTURE_TYPE_END_RANGE_KHR: u32 = ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; +pub const ACCELERATION_STRUCTURE_TYPE_RANGE_SIZE_KHR: u32 = (ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR - ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR + 1); +pub const ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_KHR: u32 = 0x7FFFFFFF; +pub type AccelerationStructureTypeNV = AccelerationStructureTypeKHR; + +pub type CopyAccelerationStructureModeKHR = u32; +pub const COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR: u32 = 0; +pub const COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR: u32 = 1; +pub const COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR: u32 = 2; +pub const COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR: u32 = 3; +pub const COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV: u32 = COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR; +pub const COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV: u32 = COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR; +pub const COPY_ACCELERATION_STRUCTURE_MODE_BEGIN_RANGE_KHR: u32 = COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR; +pub const COPY_ACCELERATION_STRUCTURE_MODE_END_RANGE_KHR: u32 = COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR; +pub const COPY_ACCELERATION_STRUCTURE_MODE_RANGE_SIZE_KHR: u32 = (COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR - COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR + 1); +pub const COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR: u32 = 0x7FFFFFFF; +pub type CopyAccelerationStructureModeNV = CopyAccelerationStructureModeKHR; + +pub type AccelerationStructureMemoryRequirementsTypeKHR = u32; +pub const ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR: u32 = 0; +pub const ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR: u32 = 1; +pub const ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR: u32 = 2; +pub const ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV: u32 = ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR; +pub const ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV: u32 = ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR; +pub const ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV: u32 = ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR; +pub const ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BEGIN_RANGE_KHR: u32 = ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR; +pub const ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_END_RANGE_KHR: u32 = ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR; +pub const ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_RANGE_SIZE_KHR: u32 = (ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR - ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR + 1); +pub const ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_KHR: u32 = 0x7FFFFFFF; +pub type AccelerationStructureMemoryRequirementsTypeNV = AccelerationStructureMemoryRequirementsTypeKHR; + +pub type GeometryFlagBitsKHR = u32; +pub const GEOMETRY_OPAQUE_BIT_KHR: u32 = 0x00000001; +pub const GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR: u32 = 0x00000002; +pub const GEOMETRY_OPAQUE_BIT_NV: u32 = GEOMETRY_OPAQUE_BIT_KHR; +pub const GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV: u32 = GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR; +pub const GEOMETRY_FLAG_BITS_MAX_ENUM_KHR: u32 = 0x7FFFFFFF; +pub type GeometryFlagsKHR = Flags; +pub type GeometryFlagsNV = GeometryFlagsKHR; +pub type GeometryFlagBitsNV = GeometryFlagBitsKHR; + +pub type GeometryInstanceFlagBitsKHR = u8; +pub const GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR: u8 = 0x00000001; +pub const GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR: u8 = 0x00000002; +pub const GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR: u8 = 0x00000004; +pub const GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR: u8 = 0x00000008; +pub const GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV: u8 = GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; +pub const GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV: u8 = GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR; +pub const GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV: u8 = GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR; +pub const GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV: u8 = GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR; +pub const GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_KHR: u32 = 0x7FFFFFFF; +pub type GeometryInstanceFlagsKHR = u8; +pub type GeometryInstanceFlagsNV = GeometryInstanceFlagsKHR; +pub type GeometryInstanceFlagBitsNV = GeometryInstanceFlagBitsKHR; + +pub type BuildAccelerationStructureFlagBitsKHR = u32; +pub const BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR: u32 = 0x00000001; +pub const BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR: u32 = 0x00000002; +pub const BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR: u32 = 0x00000004; +pub const BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR: u32 = 0x00000008; +pub const BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR: u32 = 0x00000010; +pub const BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV: u32 = BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR; +pub const BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV: u32 = BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR; +pub const BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV: u32 = BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; +pub const BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV: u32 = BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR; +pub const BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV: u32 = BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR; +pub const BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_KHR: u32 = 0x7FFFFFFF; +pub type BuildAccelerationStructureFlagsKHR = Flags; +pub type BuildAccelerationStructureFlagsNV = BuildAccelerationStructureFlagsKHR; +pub type BuildAccelerationStructureFlagBitsNV = BuildAccelerationStructureFlagBitsKHR; + +pub type AccelerationStructureBuildTypeKHR = u32; +pub const ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR: u32 = 0; +pub const ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR: u32 = 1; +pub const ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR: u32 = 2; +pub const ACCELERATION_STRUCTURE_BUILD_TYPE_BEGIN_RANGE_KHR: u32 = ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR; +pub const ACCELERATION_STRUCTURE_BUILD_TYPE_END_RANGE_KHR: u32 = ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR; +pub const ACCELERATION_STRUCTURE_BUILD_TYPE_RANGE_SIZE_KHR: u32 = (ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR - ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR + 1); +pub const ACCELERATION_STRUCTURE_BUILD_TYPE_MAX_ENUM_KHR: u32 = 0x7FFFFFFF; + #[repr(C)] pub struct ApplicationInfo { pub sType: StructureType, @@ -2474,11 +2680,12 @@ pub struct MVKSwapchainPerformance { } #[repr(C)] -pub struct PhysicalDeviceFeatures2KHR { +pub struct PhysicalDeviceFeatures2 { pub sType: StructureType, pub pNext: *const c_void, pub features: PhysicalDeviceFeatures, } +pub type PhysicalDeviceFeatures2KHR = PhysicalDeviceFeatures2; #[repr(C)] pub struct PhysicalDeviceProperties2KHR { @@ -2602,25 +2809,28 @@ pub struct MemoryDedicatedAllocateInfoKHR { } #[repr(C)] -pub struct BufferMemoryRequirementsInfo2KHR { +pub struct BufferMemoryRequirementsInfo2 { pub sType: StructureType, pub pNext: *mut c_void, pub buffer: Buffer, } +pub type BufferMemoryRequirementsInfo2KHR = BufferMemoryRequirementsInfo2; #[repr(C)] -pub struct ImageMemoryRequirementsInfo2KHR { +pub struct ImageMemoryRequirementsInfo2 { pub sType: StructureType, pub pNext: *mut c_void, pub image: Image, } +pub type ImageMemoryRequirementsInfo2KHR = ImageMemoryRequirementsInfo2; #[repr(C)] -pub struct MemoryRequirements2KHR { +pub struct MemoryRequirements2 { pub sType: StructureType, pub pNext: *mut c_void, pub memoryRequirements: MemoryRequirements, } +pub type MemoryRequirements2KHR = MemoryRequirements2; #[repr(C)] pub struct RectLayerKHR { @@ -2704,6 +2914,434 @@ pub struct SurfaceFullScreenExclusiveInfoEXT { pub fullScreenExclusive: FullScreenExclusiveEXT, } +#[repr(C)] +pub union DeviceOrHostAddressKHR { + pub deviceAddress: DeviceAddress, + pub hostAddress: *mut c_void, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub union DeviceOrHostAddressConstKHR { + pub deviceAddress: DeviceAddress, + pub hostAddress: *const c_void, +} + +#[repr(C)] +pub struct PipelineLibraryCreateInfoKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub libraryCount: u32, + pub pLibraries: *const Pipeline, +} + +#[repr(C)] +pub struct AccelerationStructureBuildOffsetInfoKHR { + pub primitiveCount: u32, + pub primitiveOffset: u32, + pub firstVertex: u32, + pub transformOffset: u32, +} + +#[repr(C)] +pub struct RayTracingShaderGroupCreateInfoNV { + pub sType: StructureType, + pub pNext: *const c_void, + pub type_: RayTracingShaderGroupTypeKHR, + pub generalShader: u32, + pub closestHitShader: u32, + pub anyHitShader: u32, + pub intersectionShader: u32, +} + +#[repr(C)] +pub struct RayTracingShaderGroupCreateInfoKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub type_: RayTracingShaderGroupTypeKHR, + pub generalShader: u32, + pub closestHitShader: u32, + pub anyHitShader: u32, + pub intersectionShader: u32, + pub pShaderGroupCaptureReplayHandle: *const c_void, +} + +#[repr(C)] +pub struct RayTracingPipelineCreateInfoNV { + pub sType: StructureType, + pub pNext: *const c_void, + pub flags: PipelineCreateFlags, + pub stageCount: u32, + pub pStages: *const PipelineShaderStageCreateInfo, + pub groupCount: u32, + pub pGroups: *const RayTracingShaderGroupCreateInfoNV, + pub maxRecursionDepth: u32, + pub layout: PipelineLayout, + pub basePipelineHandle: Pipeline, + pub basePipelineIndex: i32, +} + +#[repr(C)] +pub struct RayTracingPipelineInterfaceCreateInfoKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub maxPayloadSize: u32, + pub maxAttributeSize: u32, + pub maxCallableSize: u32, +} + +#[repr(C)] +pub struct RayTracingPipelineCreateInfoKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub flags: PipelineCreateFlags, + pub stageCount: u32, + pub pStages: *const PipelineShaderStageCreateInfo, + pub groupCount: u32, + pub pGroups: *const RayTracingShaderGroupCreateInfoKHR, + pub maxRecursionDepth: u32, + pub libraries: PipelineLibraryCreateInfoKHR, + pub pLibraryInterface: *const RayTracingPipelineInterfaceCreateInfoKHR, + pub layout: PipelineLayout, + pub basePipelineHandle: Pipeline, + pub basePipelineIndex: i32, +} + +#[repr(C)] +pub struct GeometryTrianglesNV { + pub sType: StructureType, + pub pNext: *const c_void, + pub vertexData: Buffer, + pub vertexOffset: DeviceSize, + pub vertexCount: u32, + pub vertexStride: DeviceSize, + pub vertexFormat: Format, + pub indexData: Buffer, + pub indexOffset: DeviceSize, + pub indexCount: u32, + pub indexType: IndexType, + pub transformData: Buffer, + pub transformOffset: DeviceSize, +} + +#[repr(C)] +pub struct GeometryAABBNV { + pub sType: StructureType, + pub pNext: *const c_void, + pub aabbData: Buffer, + pub numAABBs: u32, + pub stride: u32, + pub offset: DeviceSize, +} + +#[repr(C)] +pub struct GeometryDataNV { + pub triangles: GeometryTrianglesNV, + pub aabbs: GeometryAABBNV, +} + +#[repr(C)] +pub struct GeometryNV { + pub sType: StructureType, + pub pNext: *const c_void, + pub geometryType: GeometryTypeKHR, + pub geometry: GeometryDataNV, + pub flags: GeometryFlagsKHR, +} + +#[repr(C)] +pub struct AccelerationStructureInfoNV { + pub sType: StructureType, + pub pNext: *const c_void, + pub type_: AccelerationStructureTypeNV, + pub flags: BuildAccelerationStructureFlagsNV, + pub instanceCount: u32, + pub geometryCount: u32, + pub pGeometries: *const GeometryNV, +} + +#[repr(C)] +pub struct AccelerationStructureCreateInfoNV { + pub sType: StructureType, + pub pNext: *const c_void, + pub compactedSize: DeviceSize, + pub info: AccelerationStructureInfoNV, +} + +#[repr(C)] +pub struct AccelerationStructureCreateGeometryTypeInfoKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub geometryType: GeometryTypeKHR, + pub maxPrimitiveCount: u32, + pub indexType: IndexType, + pub maxVertexCount: u32, + pub vertexFormat: Format, + pub allowsTransforms: Bool32, +} + +#[repr(C)] +pub struct AccelerationStructureCreateInfoKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub compactedSize: DeviceSize, + pub type_: AccelerationStructureTypeKHR, + pub flags: BuildAccelerationStructureFlagsKHR, + pub maxGeometryCount: u32, + pub pGeometryInfos: *const AccelerationStructureCreateGeometryTypeInfoKHR, + pub deviceAddress: DeviceAddress, +} + +#[repr(C)] +pub struct BindAccelerationStructureMemoryInfoKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub accelerationStructure: AccelerationStructureKHR, + pub memory: DeviceMemory, + pub memoryOffset: DeviceSize, + pub deviceIndexCount: u32, + pub pDeviceIndices: *const u32, +} + +pub type BindAccelerationStructureMemoryInfoNV = BindAccelerationStructureMemoryInfoKHR; + +#[repr(C)] +pub struct WriteDescriptorSetAccelerationStructureKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub accelerationStructureCount: u32, + pub pAccelerationStructures: *const AccelerationStructureKHR, +} + +pub type WriteDescriptorSetAccelerationStructureNV = WriteDescriptorSetAccelerationStructureKHR; + +#[repr(C)] +pub struct AccelerationStructureMemoryRequirementsInfoNV { + pub sType: StructureType, + pub pNext: *const c_void, + pub type_: AccelerationStructureMemoryRequirementsTypeNV, + pub accelerationStructure: AccelerationStructureNV, +} + +#[repr(C)] +pub struct AccelerationStructureMemoryRequirementsInfoKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub type_: AccelerationStructureMemoryRequirementsTypeKHR, + pub buildType: AccelerationStructureBuildTypeKHR, + pub accelerationStructure: AccelerationStructureKHR, +} + +#[repr(C)] +pub struct PhysicalDeviceRayTracingFeaturesKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub rayTracing: Bool32, + pub rayTracingShaderGroupHandleCaptureReplay: Bool32, + pub rayTracingShaderGroupHandleCaptureReplayMixed: Bool32, + pub rayTracingAccelerationStructureCaptureReplay: Bool32, + pub rayTracingIndirectTraceRays: Bool32, + pub rayTracingIndirectAccelerationStructureBuild: Bool32, + pub rayTracingHostAccelerationStructureCommands: Bool32, + pub rayQuery: Bool32, + pub rayTracingPrimitiveCulling: Bool32, +} + +#[repr(C)] +pub struct PhysicalDeviceRayTracingPropertiesNV { + pub sType: StructureType, + pub pNext: *const c_void, + pub shaderGroupHandleSize: u32, + pub maxRecursionDepth: u32, + pub maxShaderGroupStride: u32, + pub shaderGroupBaseAlignment: u32, + pub maxGeometryCount: u64, + pub maxInstanceCount: u64, + pub maxTriangleCount: u64, + pub maxDescriptorSetAccelerationStructures: u32, +} + +#[repr(C)] +pub struct PhysicalDeviceRayTracingPropertiesKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub shaderGroupHandleSize: u32, + pub maxRecursionDepth: u32, + pub maxShaderGroupStride: u32, + pub shaderGroupBaseAlignment: u32, + pub maxGeometryCount: u64, + pub maxInstanceCount: u64, + pub maxPrimitiveCount: u64, + pub maxDescriptorSetAccelerationStructures: u32, + pub shaderGroupHandleCaptureReplaySize: u32, +} + +#[repr(C)] +pub struct TransformMatrixKHR { + pub matrix: [[f32; 4]; 3], +} + +pub type TransformMatrixNV = TransformMatrixKHR; + +#[repr(C)] +pub struct AabbPositionsKHR { + pub minX: f32, + pub minY: f32, + pub minZ: f32, + pub maxX: f32, + pub maxY: f32, + pub maxZ: f32, +} + +pub type AabbPositionsNV = AabbPositionsKHR; + +#[repr(C, align(1))] +pub struct AccelerationStructureInstanceKHR { + pub transform: TransformMatrixKHR, + pub instanceCustomIndex: [u8; 3], // first 24 bits of a u32 + pub mask: u8, // last 8 bits of a u32 + pub instanceShaderBindingTableRecordOffset: [u8; 3], // first 24 bits of a u32 + pub flags: GeometryInstanceFlagsKHR, + pub accelerationStructureReference: u64, +} + +pub type AccelerationStructureInstanceNV = AccelerationStructureInstanceKHR; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct AccelerationStructureGeometryTrianglesDataKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub vertexFormat: Format, + pub vertexData: DeviceOrHostAddressConstKHR, + pub vertexStride: DeviceSize, + pub indexType: IndexType, + pub indexData: DeviceOrHostAddressConstKHR, + pub transformData: DeviceOrHostAddressConstKHR, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct AccelerationStructureGeometryAabbsDataKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub data: DeviceOrHostAddressConstKHR, + pub stride: DeviceSize, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct AccelerationStructureGeometryInstancesDataKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub arrayOfPointers: Bool32, + pub data: DeviceOrHostAddressConstKHR, +} + +#[repr(C)] +pub union AccelerationStructureGeometryDataKHR { + pub triangles: AccelerationStructureGeometryTrianglesDataKHR, + pub aabbs: AccelerationStructureGeometryAabbsDataKHR, + pub instances: AccelerationStructureGeometryInstancesDataKHR, +} + +#[repr(C)] +pub struct AccelerationStructureGeometryKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub geometryType: GeometryTypeKHR, + pub geometry: AccelerationStructureGeometryDataKHR, + pub flags: GeometryFlagsKHR, +} + +#[repr(C)] +pub struct AccelerationStructureBuildGeometryInfoKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub type_: AccelerationStructureTypeKHR, + pub flags: BuildAccelerationStructureFlagsKHR, + pub update: Bool32, + pub srcAccelerationStructure: AccelerationStructureKHR, + pub dstAccelerationStructure: AccelerationStructureKHR, + pub geometryArrayOfPointers: Bool32, + pub geometryCount: u32, + pub ppGeometries: *const *const AccelerationStructureGeometryKHR, + pub scratchData: DeviceOrHostAddressKHR, +} + +#[repr(C)] +pub struct PhysicalDeviceBufferDeviceAddressFeatures { + pub sType: StructureType, + pub pNext: *const c_void, + pub bufferDeviceAddress: Bool32, + pub bufferDeviceAddressCaptureReplay: Bool32, + pub bufferDeviceAddressMultiDevice: Bool32, +} + +#[repr(C)] +pub struct BufferDeviceAddressInfo { + pub sType: StructureType, + pub pNext: *const c_void, + pub buffer: Buffer, +} +pub type BufferDeviceAddressInfoKHR = BufferDeviceAddressInfo; + +#[repr(C)] +pub struct AccelerationStructureDeviceAddressInfoKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub accelerationStructure: AccelerationStructureKHR, +} + +#[repr(C)] +pub struct AccelerationStructureVersionKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub versionData: *const u8, +} + +#[repr(C)] +pub struct StridedBufferRegionKHR { + pub buffer: Buffer, + pub offset: DeviceSize, + pub stride: DeviceSize, + pub size: DeviceSize, +} + +#[repr(C)] +pub struct TraceRaysIndirectCommandKHR { + pub width: u32, + pub height: u32, + pub depth: u32, +} + +#[repr(C)] +pub struct CopyAccelerationStructureToMemoryInfoKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub src: AccelerationStructureKHR, + pub dst: DeviceOrHostAddressKHR, + pub mode: CopyAccelerationStructureModeKHR, +} + +#[repr(C)] +pub struct CopyMemoryToAccelerationStructureInfoKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub src: DeviceOrHostAddressConstKHR, + pub dst: AccelerationStructureKHR, + pub mode: CopyAccelerationStructureModeKHR, +} + +#[repr(C)] +pub struct CopyAccelerationStructureInfoKHR { + pub sType: StructureType, + pub pNext: *const c_void, + pub src: AccelerationStructureKHR, + pub dst: AccelerationStructureKHR, + pub mode: CopyAccelerationStructureModeKHR, +} + macro_rules! ptrs { ($struct_name:ident, { $($name:ident => ($($param_n:ident: $param_ty:ty),*) -> $ret:ty,)+ }) => ( pub struct $struct_name { @@ -2805,6 +3443,7 @@ ptrs!(InstancePointers, { GetPhysicalDeviceMetalFeaturesMVK => (physicalDevice: PhysicalDevice, pMetalFeatures: *mut MVKPhysicalDeviceMetalFeatures) -> Result, GetSwapchainPerformanceMVK => (device: Device, swapchain: SwapchainKHR, pSwapchainPerf: *mut MVKSwapchainPerformance) -> Result, CreateViSurfaceNN => (instance: Instance, pCreateInfo: *const ViSurfaceCreateInfoNN, pAllocator: *const AllocationCallbacks, pSurface: *mut SurfaceKHR) -> Result, + GetPhysicalDeviceFeatures2 => (physicalDevice: PhysicalDevice, pFeatures: *mut PhysicalDeviceFeatures2) -> (), GetPhysicalDeviceFeatures2KHR => (physicalDevice: PhysicalDevice, pFeatures: *mut PhysicalDeviceFeatures2KHR) -> (), GetPhysicalDeviceProperties2KHR => (physicalDevice: PhysicalDevice, pProperties: *mut PhysicalDeviceProperties2KHR) -> (), GetPhysicalDeviceFormatProperties2KHR => (physicalDevice: PhysicalDevice, pFormatProperties: *mut FormatProperties2KHR) -> (), @@ -2955,4 +3594,39 @@ ptrs!(DevicePointers, { CmdInsertDebugUtilsLabelEXT => (commandBuffer: CommandBuffer, pLabelInfo: *const DebugUtilsLabelEXT) -> Result, AcquireFullScreenExclusiveModeEXT => (device: Device, swapchain: SwapchainKHR) -> Result, ReleaseFullScreenExclusiveModeEXT => (device: Device, swapchain: SwapchainKHR) -> Result, + CreateAccelerationStructureNV => (device: Device, pCreateInfo: *const AccelerationStructureCreateInfoNV, pAllocator: *const AllocationCallbacks, pAccelerationStructure: *mut AccelerationStructureNV) -> Result, + DestroyAccelerationStructureKHR => (device: Device, accelerationStructure: AccelerationStructureKHR, pAllocator: *const AllocationCallbacks) -> (), + DestroyAccelerationStructureNV => (device: Device, accelerationStructure: AccelerationStructureKHR, pAllocator: *const AllocationCallbacks) -> (), + GetAccelerationStructureMemoryRequirementsNV => (device: Device, pInfo: *const AccelerationStructureMemoryRequirementsInfoNV, pMemoryRequirements: *mut MemoryRequirements2KHR) -> (), + BindAccelerationStructureMemoryKHR => (device: Device, bindInfoCount: u32, pBindInfos: *const BindAccelerationStructureMemoryInfoKHR) -> Result, + BindAccelerationStructureMemoryNV => (device: Device, bindInfoCount: u32, pBindInfos: *const BindAccelerationStructureMemoryInfoKHR) -> Result, + CmdBuildAccelerationStructureNV => (commandBuffer: CommandBuffer, pInfo: *const AccelerationStructureInfoNV, instanceData: Buffer, instanceOffset: DeviceSize, update: Bool32, dst: AccelerationStructureKHR, src: AccelerationStructureKHR, scratch: Buffer, scratchOffset: DeviceSize) -> (), + CmdCopyAccelerationStructureNV => (commandBuffer: CommandBuffer, dst: AccelerationStructureKHR, src: AccelerationStructureKHR, mode: CopyAccelerationStructureModeKHR) -> (), + CmdTraceRaysNV => (commandBuffer: CommandBuffer, raygenShaderBindingTableBuffer: Buffer, raygenShaderBindingOffset: DeviceSize, missShaderBindingTableBuffer: Buffer, missShaderBindingOffset: DeviceSize, missShaderBindingStride: DeviceSize, hitShaderBindingTableBuffer: Buffer, hitShaderBindingOffset: DeviceSize, hitShaderBindingStride: DeviceSize, callableShaderBindingTableBuffer: Buffer, callableShaderBindingOffset: DeviceSize, callableShaderBindingStride: DeviceSize, width: u32, height: u32, depth: u32) -> (), + CreateRayTracingPipelinesNV => (device: Device, pipelineCache: PipelineCache, createInfoCount: u32, pCreateInfos: *const RayTracingPipelineCreateInfoNV, pAllocator: *const AllocationCallbacks, pPipelines: *mut Pipeline) -> Result, + GetRayTracingShaderGroupHandlesKHR => (device: Device, pipeline: Pipeline, firstGroup: u32, groupCount: u32, dataSize: usize, pData: *mut c_void) -> Result, + GetRayTracingShaderGroupHandlesNV => (device: Device, pipeline: Pipeline, firstGroup: u32, groupCount: u32, dataSize: usize, pData: *mut c_void) -> Result, + GetAccelerationStructureHandleNV => (device: Device, accelerationStructure: AccelerationStructureKHR, dataSize: usize, pData: *mut c_void) -> Result, + CmdWriteAccelerationStructuresPropertiesKHR => (commandBuffer: CommandBuffer, accelerationStructureCount: u32, pAccelerationStructures: *const AccelerationStructureKHR, queryType: QueryType, queryPool: QueryPool, firstQuery: u32) -> (), + CmdWriteAccelerationStructuresPropertiesNV => (commandBuffer: CommandBuffer, accelerationStructureCount: u32, pAccelerationStructures: *const AccelerationStructureKHR, queryType: QueryType, queryPool: QueryPool, firstQuery: u32) -> (), + CompileDeferredNV => (device: Device, pipeline: Pipeline, shader: u32) -> Result, + CreateAccelerationStructureKHR => (device: Device, pCreateInfo: *const AccelerationStructureCreateInfoKHR, pAllocator: *const AllocationCallbacks, pAccelerationStructure: *mut AccelerationStructureKHR) -> Result, + GetAccelerationStructureMemoryRequirementsKHR => (device: Device, pInfo: *const AccelerationStructureMemoryRequirementsInfoKHR, pMemoryRequirements: *mut MemoryRequirements2) -> (), + CmdBuildAccelerationStructureKHR => (commandBuffer: CommandBuffer, infoCount: u32, pInfos: *const AccelerationStructureBuildGeometryInfoKHR, ppOffsetInfos: *const*const AccelerationStructureBuildOffsetInfoKHR) -> (), + CmdBuildAccelerationStructureIndirectKHR => (commandBuffer: CommandBuffer, pInfo: *const AccelerationStructureBuildGeometryInfoKHR, indirectBuffer: Buffer, indirectOffset: DeviceSize, indirectStride: u32) -> (), + BuildAccelerationStructureKHR => (device: Device, infoCount: u32, pInfos: *const AccelerationStructureBuildGeometryInfoKHR, ppOffsetInfos: *const*const AccelerationStructureBuildOffsetInfoKHR) -> Result, + CopyAccelerationStructureKHR => (device: Device, pInfo: *const CopyAccelerationStructureInfoKHR) -> Result, + CopyAccelerationStructureToMemoryKHR => (device: Device, pInfo: *const CopyAccelerationStructureToMemoryInfoKHR) -> Result, + CopyMemoryToAccelerationStructureKHR => (device: Device, pInfo: *const CopyMemoryToAccelerationStructureInfoKHR) -> Result, + WriteAccelerationStructuresPropertiesKHR => (device: Device, accelerationStructureCount: u32, pAccelerationStructures: *const AccelerationStructureKHR, queryType: QueryType, dataSize: usize, pData: *mut c_void, stride: usize) -> Result, + CmdCopyAccelerationStructureKHR => (commandBuffer: CommandBuffer, pInfo: *const CopyAccelerationStructureInfoKHR) -> (), + CmdCopyAccelerationStructureToMemoryKHR => (commandBuffer: CommandBuffer, pInfo: *const CopyAccelerationStructureToMemoryInfoKHR) -> (), + CmdCopyMemoryToAccelerationStructureKHR => (commandBuffer: CommandBuffer, pInfo: *const CopyMemoryToAccelerationStructureInfoKHR) -> (), + CmdTraceRaysKHR => (commandBuffer: CommandBuffer, pRaygenShaderBindingTable: *const StridedBufferRegionKHR, pMissShaderBindingTable: *const StridedBufferRegionKHR, pHitShaderBindingTable: *const StridedBufferRegionKHR, pCallableShaderBindingTable: *const StridedBufferRegionKHR, width: u32, height: u32, depth: u32) -> (), + CreateRayTracingPipelinesKHR => (device: Device, pipelineCache: PipelineCache, createInfoCount: u32, pCreateInfos: *const RayTracingPipelineCreateInfoKHR, pAllocator: *const AllocationCallbacks, pPipelines: *mut Pipeline) -> Result, + GetBufferDeviceAddressKHR => (device: Device, pInfo: *const BufferDeviceAddressInfoKHR) -> DeviceAddress, + GetAccelerationStructureDeviceAddressKHR => (device: Device, pInfo: *const AccelerationStructureDeviceAddressInfoKHR) -> DeviceAddress, + GetRayTracingCaptureReplayShaderGroupHandlesKHR => (device: Device, pipeline: Pipeline, firstGroup: u32, groupCount: u32, dataSize: usize, pData: *mut c_void) -> Result, + CmdTraceRaysIndirectKHR => (commandBuffer: CommandBuffer, pRaygenShaderBindingTable: *const StridedBufferRegionKHR, pMissShaderBindingTable: *const StridedBufferRegionKHR, pHitShaderBindingTable: *const StridedBufferRegionKHR, pCallableShaderBindingTable: *const StridedBufferRegionKHR, buffer: Buffer, offset: DeviceSize) -> (), + GetDeviceAccelerationStructureCompatibilityKHR => (device: Device, version: *const AccelerationStructureVersionKHR) -> Result, }); From 4b232f420276deb1d6daa84884663d9e8354eb0e Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Tue, 14 Apr 2020 17:08:11 +0200 Subject: [PATCH 03/15] vulkano-shaders: Support for ray_tracing shaders Refactor write entry point to later support raytracing class of execution models. https://github.com/KhronosGroup/SPIRV-Headers/commit/0350b1d426709a8ea6a9d4988e256fbc58cebf57 https://github.com/KhronosGroup/SPIRV-Headers/commit/95b48cedd07d4134ef0005898f8354615ca64282 --- vulkano-shaders/src/codegen.rs | 28 +++++++++++++++ vulkano-shaders/src/entry_point.rs | 35 ++++++++++++------- vulkano-shaders/src/enums.rs | 55 ++++++++++++++++++++++++++++++ vulkano-shaders/src/lib.rs | 15 +++++++- 4 files changed, 119 insertions(+), 14 deletions(-) diff --git a/vulkano-shaders/src/codegen.rs b/vulkano-shaders/src/codegen.rs index c5dc5be847..38f182d453 100644 --- a/vulkano-shaders/src/codegen.rs +++ b/vulkano-shaders/src/codegen.rs @@ -400,6 +400,10 @@ fn capability_requirement(cap: &Capability) -> DeviceRequirement { DeviceRequirement::Extensions(&["khr_16bit_storage"]), Capability::CapabilityStorageInputOutput16 => DeviceRequirement::Extensions(&["khr_16bit_storage"]), + Capability::CapabilityRayTracingNV => + DeviceRequirement::Extensions(&["nv_ray_tracing"]), + Capability::CapabilityRayTracingProvisionalKHR => + DeviceRequirement::Extensions(&["khr_ray_tracing"]), } } @@ -420,6 +424,30 @@ fn storage_class_requirement(storage_class: &StorageClass) -> DeviceRequirement StorageClass::StorageClassImage => DeviceRequirement::None, StorageClass::StorageClassStorageBuffer => DeviceRequirement::Extensions(&["khr_storage_buffer_storage_class"]), + StorageClass::StorageClassCallableDataKHR => + DeviceRequirement::Extensions(&["khr_ray_tracing"]), + StorageClass::StorageClassCallableDataNV => + DeviceRequirement::Extensions(&["nv_ray_tracing"]), + StorageClass::StorageClassIncomingCallableDataKHR => + DeviceRequirement::Extensions(&["khr_ray_tracing"]), + StorageClass::StorageClassIncomingCallableDataNV => + DeviceRequirement::Extensions(&["nv_ray_tracing"]), + StorageClass::StorageClassRayPayloadKHR => + DeviceRequirement::Extensions(&["khr_ray_tracing"]), + StorageClass::StorageClassRayPayloadNV => + DeviceRequirement::Extensions(&["nv_ray_tracing"]), + StorageClass::StorageClassHitAttributeKHR => + DeviceRequirement::Extensions(&["khr_ray_tracing"]), + StorageClass::StorageClassHitAttributeNV => + DeviceRequirement::Extensions(&["nv_ray_tracing"]), + StorageClass::StorageClassIncomingRayPayloadKHR => + DeviceRequirement::Extensions(&["khr_ray_tracing"]), + StorageClass::StorageClassIncomingRayPayloadNV => + DeviceRequirement::Extensions(&["nv_ray_tracing"]), + StorageClass::StorageClassShaderRecordBufferKHR => + DeviceRequirement::Extensions(&["khr_ray_tracing"]), + StorageClass::StorageClassShaderRecordBufferNV => + DeviceRequirement::Extensions(&["nv_ray_tracing"]), } } diff --git a/vulkano-shaders/src/entry_point.rs b/vulkano-shaders/src/entry_point.rs index 2b77eaf9c4..ab188535e2 100644 --- a/vulkano-shaders/src/entry_point.rs +++ b/vulkano-shaders/src/entry_point.rs @@ -54,15 +54,16 @@ pub fn write_entry_point(doc: &Spirv, instruction: &Instruction) -> (TokenStream }; let (ty, f_call) = { - if let ExecutionModel::ExecutionModelGLCompute = *execution { - ( - quote!{ ::vulkano::pipeline::shader::ComputeEntryPoint<#spec_consts_struct, Layout> }, - quote!{ compute_entry_point( - ::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), - Layout(ShaderStages { compute: true, .. ShaderStages::none() }) - )} - ) - } else { + if let ExecutionModel::ExecutionModelKernel = *execution { + panic!("Kernels are not supported"); + } else if match *execution { + ExecutionModel::ExecutionModelVertex => true, + ExecutionModel::ExecutionModelTessellationControl => true, + ExecutionModel::ExecutionModelTessellationEvaluation => true, + ExecutionModel::ExecutionModelGeometry => true, + ExecutionModel::ExecutionModelFragment => true, + _ => false, + } { let entry_ty = match *execution { ExecutionModel::ExecutionModelVertex => quote!{ ::vulkano::pipeline::shader::GraphicsShaderType::Vertex }, @@ -104,9 +105,8 @@ pub fn write_entry_point(doc: &Spirv, instruction: &Instruction) -> (TokenStream ExecutionModel::ExecutionModelFragment => quote!{ ::vulkano::pipeline::shader::GraphicsShaderType::Fragment }, - ExecutionModel::ExecutionModelGLCompute => unreachable!(), - ExecutionModel::ExecutionModelKernel => panic!("Kernels are not supported"), + _ => unreachable!(), }; let stage = match *execution { @@ -125,8 +125,7 @@ pub fn write_entry_point(doc: &Spirv, instruction: &Instruction) -> (TokenStream ExecutionModel::ExecutionModelFragment => quote!{ ShaderStages { fragment: true, .. ShaderStages::none() } }, - ExecutionModel::ExecutionModelGLCompute => unreachable!(), - ExecutionModel::ExecutionModelKernel => unreachable!(), + _ => unreachable!(), }; let mut capitalized_ep_name_input = capitalized_ep_name.clone(); @@ -155,6 +154,16 @@ pub fn write_entry_point(doc: &Spirv, instruction: &Instruction) -> (TokenStream }; (ty, f_call) + } else if let ExecutionModel::ExecutionModelGLCompute = *execution { + ( + quote! { ::vulkano::pipeline::shader::ComputeEntryPoint<#spec_consts_struct, Layout> }, + quote! { compute_entry_point( + ::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), + Layout(ShaderStages { compute: true, .. ShaderStages::none() }) + )}, + ) + } else { + panic!("Execution Model is not supported"); } }; diff --git a/vulkano-shaders/src/enums.rs b/vulkano-shaders/src/enums.rs index ba9be74b36..0d79e73321 100644 --- a/vulkano-shaders/src/enums.rs +++ b/vulkano-shaders/src/enums.rs @@ -53,6 +53,18 @@ enumeration! { ExecutionModelFragment = 4, ExecutionModelGLCompute = 5, ExecutionModelKernel = 6, + ExecutionModelRayGenerationKHR = 5313, + ExecutionModelRayGenerationNV = 5313, + ExecutionModelIntersectionKHR = 5314, + ExecutionModelIntersectionNV = 5314, + ExecutionModelAnyHitKHR = 5315, + ExecutionModelAnyHitNV = 5315, + ExecutionModelClosestHitKHR = 5316, + ExecutionModelClosestHitNV = 5316, + ExecutionModelMissKHR = 5317, + ExecutionModelMissNV = 5317, + ExecutionModelCallableKHR = 5318, + ExecutionModelCallableNV = 5318, } ExecutionModel; typedef enum AddressingModel_ { @@ -115,6 +127,18 @@ enumeration! { StorageClassAtomicCounter = 10, StorageClassImage = 11, StorageClassStorageBuffer = 12, + StorageClassCallableDataKHR = 5328, + StorageClassCallableDataNV = 5328, + StorageClassIncomingCallableDataKHR = 5329, + StorageClassIncomingCallableDataNV = 5329, + StorageClassRayPayloadKHR = 5338, + StorageClassRayPayloadNV = 5338, + StorageClassHitAttributeKHR = 5339, + StorageClassHitAttributeNV = 5339, + StorageClassIncomingRayPayloadKHR = 5342, + StorageClassIncomingRayPayloadNV = 5342, + StorageClassShaderRecordBufferKHR = 5343, + StorageClassShaderRecordBufferNV = 5343, } StorageClass; typedef enum Dim_ { @@ -382,6 +406,35 @@ enumeration! { BuiltInSubgroupLocalInvocationId = 41, BuiltInVertexIndex = 42, BuiltInInstanceIndex = 43, + BuiltInLaunchIdKHR = 5319, + BuiltInLaunchIdNV = 5319, + BuiltInLaunchSizeKHR = 5320, + BuiltInLaunchSizeNV = 5320, + BuiltInWorldRayOriginKHR = 5321, + BuiltInWorldRayOriginNV = 5321, + BuiltInWorldRayDirectionKHR = 5322, + BuiltInWorldRayDirectionNV = 5322, + BuiltInObjectRayOriginKHR = 5323, + BuiltInObjectRayOriginNV = 5323, + BuiltInObjectRayDirectionKHR = 5324, + BuiltInObjectRayDirectionNV = 5324, + BuiltInRayTminKHR = 5325, + BuiltInRayTminNV = 5325, + BuiltInRayTmaxKHR = 5326, + BuiltInRayTmaxNV = 5326, + BuiltInInstanceCustomIndexKHR = 5327, + BuiltInInstanceCustomIndexNV = 5327, + BuiltInObjectToWorldKHR = 5330, + BuiltInObjectToWorldNV = 5330, + BuiltInWorldToObjectKHR = 5331, + BuiltInWorldToObjectNV = 5331, + BuiltInHitTKHR = 5332, + BuiltInHitTNV = 5332, + BuiltInHitKindKHR = 5333, + BuiltInHitKindNV = 5333, + BuiltInIncomingRayFlagsKHR = 5351, + BuiltInIncomingRayFlagsNV = 5351, + BuiltInRayGeometryIndexKHR = 5352, } BuiltIn; typedef enum SelectionControlShift_ { @@ -551,5 +604,7 @@ enumeration! { CapabilityStorageUniform16 = 4434, CapabilityStoragePushConstant16 = 4435, CapabilityStorageInputOutput16 = 4436, + CapabilityRayTracingNV = 5340, + CapabilityRayTracingProvisionalKHR = 5353, // TODO: At time of writing, this is provisional and may be renamed } Capability; } diff --git a/vulkano-shaders/src/lib.rs b/vulkano-shaders/src/lib.rs index e6e707f4f3..eb7596e229 100644 --- a/vulkano-shaders/src/lib.rs +++ b/vulkano-shaders/src/lib.rs @@ -113,6 +113,12 @@ //! * `tess_ctrl` //! * `tess_eval` //! * `compute` +//! * `ray_generation` +//! * `intersection` +//! * `any_hit` +//! * `closest_hit` +//! * `miss` +//! * `callable` //! //! For details on what these shader types mean, [see Vulkano's documentation][pipeline]. //! @@ -220,7 +226,14 @@ impl Parse for MacroInput { "tess_ctrl" => ShaderKind::TessControl, "tess_eval" => ShaderKind::TessEvaluation, "compute" => ShaderKind::Compute, - _ => panic!("Unexpected shader type, valid values: vertex, fragment, geometry, tess_ctrl, tess_eval, compute") + "ray_generation" => ShaderKind::RayGeneration, + "intersection" => ShaderKind::Intersection, + "any_hit" => ShaderKind::AnyHit, + "closest_hit" => ShaderKind::ClosestHit, + "miss" => ShaderKind::Miss, + "callable" => ShaderKind::Callable, + _ => panic!("Unexpected shader type, valid values: vertex, fragment, geometry, tess_ctrl, tess_eval, compute, \ + ray_generation, intersection, any_hit, closest_hit, miss, callable") }; shader_kind = Some(ty); } From e6da13f58fb161fe5a6e48661a9a4c4b0ffaf326 Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Tue, 14 Apr 2020 18:06:25 +0200 Subject: [PATCH 04/15] buffer: Add 5 new sages Add shader_device_address Add transform_feedback_buffer Add transform_feedback_counter_buffer Add conditional_rendering Add ray_tracing --- vulkano/src/buffer/sys.rs | 25 +++++++++++++++++++++ vulkano/src/buffer/usage.rs | 44 +++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/vulkano/src/buffer/sys.rs b/vulkano/src/buffer/sys.rs index 32e12b396f..702ccf7433 100644 --- a/vulkano/src/buffer/sys.rs +++ b/vulkano/src/buffer/sys.rs @@ -298,6 +298,31 @@ impl UnsafeBuffer { (self.usage & vk::BUFFER_USAGE_INDIRECT_BUFFER_BIT) != 0 } + #[inline] + pub fn usage_shader_device_address(&self) -> bool { + (self.usage & vk::BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR) != 0 + } + + #[inline] + pub fn usage_transform_feedback_buffer(&self) -> bool { + (self.usage & vk::BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT) != 0 + } + + #[inline] + pub fn usage_transform_feedback_counter_buffer(&self) -> bool { + (self.usage & vk::BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT) != 0 + } + + #[inline] + pub fn usage_conditional_rendering(&self) -> bool { + (self.usage & vk::BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT) != 0 + } + + #[inline] + pub fn usage_ray_tracing(&self) -> bool { + (self.usage & vk::BUFFER_USAGE_RAY_TRACING_BIT_KHR) != 0 + } + /// Returns a key unique to each `UnsafeBuffer`. Can be used for the `conflicts_key` method. #[inline] pub fn key(&self) -> u64 { diff --git a/vulkano/src/buffer/usage.rs b/vulkano/src/buffer/usage.rs index bc1b7b0e8a..5dcaad60be 100644 --- a/vulkano/src/buffer/usage.rs +++ b/vulkano/src/buffer/usage.rs @@ -27,6 +27,11 @@ pub struct BufferUsage { pub index_buffer: bool, pub vertex_buffer: bool, pub indirect_buffer: bool, + pub shader_device_address: bool, + pub transform_feedback_buffer: bool, + pub transform_feedback_counter_buffer: bool, + pub conditional_rendering: bool, + pub ray_tracing: bool, } impl BufferUsage { @@ -60,6 +65,21 @@ impl BufferUsage { if self.indirect_buffer { result |= vk::BUFFER_USAGE_INDIRECT_BUFFER_BIT; } + if self.shader_device_address { + result |= vk::BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + } + if self.transform_feedback_buffer { + result |= vk::BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; + } + if self.transform_feedback_counter_buffer { + result |= vk::BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT; + } + if self.conditional_rendering { + result |= vk::BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT; + } + if self.ray_tracing { + result |= vk::BUFFER_USAGE_RAY_TRACING_BIT_KHR; + } result } @@ -76,6 +96,11 @@ impl BufferUsage { index_buffer: false, vertex_buffer: false, indirect_buffer: false, + shader_device_address: false, + transform_feedback_buffer: false, + transform_feedback_counter_buffer: false, + conditional_rendering: false, + ray_tracing: false, } } @@ -92,6 +117,11 @@ impl BufferUsage { index_buffer: true, vertex_buffer: true, indirect_buffer: true, + shader_device_address: true, + transform_feedback_buffer: true, + transform_feedback_counter_buffer: true, + conditional_rendering: true, + ray_tracing: true, } } @@ -172,6 +202,15 @@ impl BufferUsage { } } + /// Builds a `BufferUsage` with `ray_tracing` set to true and the rest to false. + #[inline] + pub fn ray_tracing() -> BufferUsage { + BufferUsage { + ray_tracing: true, + ..BufferUsage::none() + } + } + /// Builds a `BufferUsage` with `indirect_buffer` set to true and the rest to false. #[inline] pub fn indirect_buffer() -> BufferUsage { @@ -208,6 +247,11 @@ impl BitOr for BufferUsage { index_buffer: self.index_buffer || rhs.index_buffer, vertex_buffer: self.vertex_buffer || rhs.vertex_buffer, indirect_buffer: self.indirect_buffer || rhs.indirect_buffer, + shader_device_address: self.shader_device_address || rhs.shader_device_address, + transform_feedback_buffer: self.transform_feedback_buffer || rhs.transform_feedback_buffer, + transform_feedback_counter_buffer: self.transform_feedback_counter_buffer || rhs.transform_feedback_counter_buffer, + conditional_rendering: self.conditional_rendering || rhs.conditional_rendering, + ray_tracing: self.ray_tracing || rhs.ray_tracing, } } } From 2d6e8b84669e1347d650bb4c5d470465076cd661 Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Tue, 14 Apr 2020 18:19:12 +0200 Subject: [PATCH 05/15] descriptor: add ray tracing shader types --- vulkano/src/descriptor/descriptor.rs | 97 +++++++++++++++++++++++++++- vulkano/src/sync/pipeline.rs | 15 ++++- 2 files changed, 109 insertions(+), 3 deletions(-) diff --git a/vulkano/src/descriptor/descriptor.rs b/vulkano/src/descriptor/descriptor.rs index e3f7acaf8c..a16b79cf31 100644 --- a/vulkano/src/descriptor/descriptor.rs +++ b/vulkano/src/descriptor/descriptor.rs @@ -636,6 +636,18 @@ pub struct ShaderStages { pub fragment: bool, /// `True` means that the descriptor will be used by the compute shader. pub compute: bool, + /// `True` means that the descriptor will be used by the raygen shader. + pub raygen: bool, + /// `True` means that the descriptor will be used by the intersection shader. + pub intersection: bool, + /// `True` means that the descriptor will be used by the any hit shader. + pub any_hit: bool, + /// `True` means that the descriptor will be used by the closest hit shader. + pub closest_hit: bool, + /// `True` means that the descriptor will be used by the miss shader. + pub miss: bool, + /// `True` means that the descriptor will be used by the callable shader. + pub callable: bool, } impl ShaderStages { @@ -650,6 +662,12 @@ impl ShaderStages { geometry: true, fragment: true, compute: true, + raygen: true, + intersection: true, + any_hit: true, + closest_hit: true, + miss: true, + callable: true, } } @@ -664,6 +682,12 @@ impl ShaderStages { geometry: false, fragment: false, compute: false, + raygen: false, + intersection: false, + any_hit: false, + closest_hit: false, + miss: false, + callable: false, } } @@ -678,6 +702,12 @@ impl ShaderStages { geometry: true, fragment: true, compute: false, + raygen: false, + intersection: false, + any_hit: false, + closest_hit: false, + miss: false, + callable: false, } } @@ -692,6 +722,32 @@ impl ShaderStages { geometry: false, fragment: false, compute: true, + raygen: false, + intersection: false, + any_hit: false, + closest_hit: false, + miss: false, + callable: false, + } + } + + /// Creates a `ShaderStages` struct with all ray tracing stages set to `true`. + // TODO: add example + #[inline] + pub fn all_ray_tracing() -> ShaderStages { + ShaderStages { + vertex: false, + tessellation_control: false, + tessellation_evaluation: false, + geometry: false, + fragment: false, + compute: false, + raygen: true, + intersection: true, + any_hit: true, + closest_hit: true, + miss: true, + callable: true, } } @@ -703,7 +759,13 @@ impl ShaderStages { (self.tessellation_control || !other.tessellation_control) && (self.tessellation_evaluation || !other.tessellation_evaluation) && (self.geometry || !other.geometry) && - (self.fragment || !other.fragment) && (self.compute || !other.compute) + (self.fragment || !other.fragment) && (self.compute || !other.compute) && + (self.raygen || !other.raygen) && + (self.intersection || !other.intersection) && + (self.any_hit || !other.any_hit) && + (self.closest_hit || !other.closest_hit) && + (self.miss || !other.miss) && + (self.callable || !other.callable) { Ok(()) } else { @@ -719,7 +781,13 @@ impl ShaderStages { (self.tessellation_control && other.tessellation_control) || (self.tessellation_evaluation && other.tessellation_evaluation) || (self.geometry && other.geometry) || (self.fragment && other.fragment) || - (self.compute && other.compute) + (self.compute && other.compute) || + (self.raygen && other.raygen) || + (self.intersection && other.intersection) || + (self.any_hit && other.any_hit) || + (self.closest_hit && other.closest_hit) || + (self.miss && other.miss) || + (self.callable && other.callable) } #[inline] @@ -743,6 +811,24 @@ impl ShaderStages { if self.compute { result |= vk::SHADER_STAGE_COMPUTE_BIT; } + if self.raygen { + result |= vk::SHADER_STAGE_RAYGEN_BIT_KHR; + } + if self.intersection { + result |= vk::SHADER_STAGE_INTERSECTION_BIT_KHR; + } + if self.any_hit { + result |= vk::SHADER_STAGE_ANY_HIT_BIT_KHR; + } + if self.closest_hit { + result |= vk::SHADER_STAGE_CLOSEST_HIT_BIT_KHR; + } + if self.miss { + result |= vk::SHADER_STAGE_MISS_BIT_KHR; + } + if self.callable { + result |= vk::SHADER_STAGE_CALLABLE_BIT_KHR; + } result } } @@ -759,6 +845,12 @@ impl BitOr for ShaderStages { geometry: self.geometry || other.geometry, fragment: self.fragment || other.fragment, compute: self.compute || other.compute, + raygen: self.raygen || other.raygen, + intersection: self.intersection || other.intersection, + any_hit: self.any_hit || other.any_hit, + closest_hit: self.closest_hit || other.closest_hit, + miss: self.miss || other.miss, + callable: self.callable || other.callable, } } } @@ -773,6 +865,7 @@ impl From for PipelineStages { geometry_shader: stages.geometry, fragment_shader: stages.fragment, compute_shader: stages.compute, + ray_tracing_shader: stages.intersects(&ShaderStages::all_ray_tracing()), ..PipelineStages::none() } } diff --git a/vulkano/src/sync/pipeline.rs b/vulkano/src/sync/pipeline.rs index 3a201f9d75..5907b75a38 100644 --- a/vulkano/src/sync/pipeline.rs +++ b/vulkano/src/sync/pipeline.rs @@ -82,6 +82,8 @@ pipeline_stages!{ host => vk::PIPELINE_STAGE_HOST_BIT, all_graphics => vk::PIPELINE_STAGE_ALL_GRAPHICS_BIT, all_commands => vk::PIPELINE_STAGE_ALL_COMMANDS_BIT, + ray_tracing_shader => vk::PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, + acceleration_structure_build => vk::PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, } macro_rules! access_flags { @@ -165,6 +167,8 @@ access_flags!{ host_write => vk::ACCESS_HOST_WRITE_BIT, memory_read => vk::ACCESS_MEMORY_READ_BIT, memory_write => vk::ACCESS_MEMORY_WRITE_BIT, + acceleration_structure_read => vk::ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, + acceleration_structure_write => vk::ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, } impl AccessFlagBits { @@ -191,7 +195,7 @@ impl AccessFlagBits { !stages.vertex_shader && !stages.tessellation_control_shader && !stages.tessellation_evaluation_shader && !stages.geometry_shader && !stages.fragment_shader && - !stages.compute_shader && !stages.all_graphics + !stages.compute_shader && !stages.all_graphics && !stages.ray_tracing_shader { return false; } @@ -221,6 +225,15 @@ impl AccessFlagBits { return false; } + if self.acceleration_structure_read && !stages.ray_tracing_shader && + !stages.acceleration_structure_build { + return false; + } + + if self.acceleration_structure_write && !stages.acceleration_structure_build { + return false; + } + true } } From 16761e75dfd6c0d09cb749d8449fa02fea4250ab Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Tue, 14 Apr 2020 18:31:31 +0200 Subject: [PATCH 06/15] instance: store ray tracing properties Chain `PhysicalDeviceRayTracingPropertiesKHR` and `PhysicalDeviceRayTracingPropertiesNV` in `PhysicalDeviceProperties2KHR` in order to retrieve the same data from two different extensions if they are available. In the case both are unavailable the values are 0. In the case of one or both extensions being supported, grab the maximum, overwriting the 0s in the case of one of both unsupported and reconciling both properties if they are available. One exception is the property `shaderGroupHandleCaptureReplaySize` which is not available in the nvidia ray tracing extension. --- vulkano/src/device/extensions.rs | 6 +++ vulkano/src/instance/instance.rs | 86 ++++++++++++++++++++++++++++---- 2 files changed, 81 insertions(+), 11 deletions(-) diff --git a/vulkano/src/device/extensions.rs b/vulkano/src/device/extensions.rs index cd4376d3b3..5862e6f02b 100644 --- a/vulkano/src/device/extensions.rs +++ b/vulkano/src/device/extensions.rs @@ -118,6 +118,12 @@ device_extensions! { ext_debug_utils => b"VK_EXT_debug_utils", khr_multiview => b"VK_KHR_multiview", ext_full_screen_exclusive => b"VK_EXT_full_screen_exclusive", + nv_ray_tracing => b"VK_NV_ray_tracing", + khr_ray_tracing => b"VK_KHR_ray_tracing", + ext_descriptor_indexing => b"VK_EXT_descriptor_indexing", + khr_buffer_device_address => b"VK_KHR_buffer_device_address", + khr_deferred_host_operations => b"VK_KHR_deferred_host_operations", + khr_pipeline_library => b"VK_KHR_pipeline_library", } /// This helper type can only be instantiated inside this module. diff --git a/vulkano/src/instance/instance.rs b/vulkano/src/instance/instance.rs index 69a667c184..92fa5292a2 100644 --- a/vulkano/src/instance/instance.rs +++ b/vulkano/src/instance/instance.rs @@ -9,6 +9,7 @@ use smallvec::SmallVec; use std::borrow::Cow; +use std::cmp::max; use std::error; use std::ffi::CStr; use std::ffi::CString; @@ -341,10 +342,11 @@ impl Instance { }; output.push(PhysicalDeviceInfos { - device: device, - properties: properties, - memory: memory, - queue_families: queue_families, + device, + properties, + properties_ray_tracing: Default::default(), + memory, + queue_families, available_features: Features::from_vulkan_features(available_features), }); } @@ -360,15 +362,50 @@ impl Instance { let mut output = Vec::with_capacity(physical_devices.len()); for device in physical_devices.into_iter() { - let properties: vk::PhysicalDeviceProperties = unsafe { + let (properties, properties_ray_tracing) = unsafe { + let mut nv_rt_output = Box::new(vk::PhysicalDeviceRayTracingPropertiesNV { + sType: vk::STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV, + pNext: ptr::null_mut(), + shaderGroupHandleSize: mem::zeroed(), + maxRecursionDepth: mem::zeroed(), + maxShaderGroupStride: mem::zeroed(), + shaderGroupBaseAlignment: mem::zeroed(), + maxGeometryCount: mem::zeroed(), + maxInstanceCount: mem::zeroed(), + maxTriangleCount: mem::zeroed(), + maxDescriptorSetAccelerationStructures: mem::zeroed(), + }); + let mut khr_rt_output = Box::new(vk::PhysicalDeviceRayTracingPropertiesKHR { + sType: vk::STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR, + pNext: nv_rt_output.as_mut() as *mut vk::PhysicalDeviceRayTracingPropertiesNV as *mut _, + shaderGroupHandleSize: mem::zeroed(), + maxRecursionDepth: mem::zeroed(), + maxShaderGroupStride: mem::zeroed(), + shaderGroupBaseAlignment: mem::zeroed(), + maxGeometryCount: mem::zeroed(), + maxInstanceCount: mem::zeroed(), + maxPrimitiveCount: mem::zeroed(), + maxDescriptorSetAccelerationStructures: mem::zeroed(), + shaderGroupHandleCaptureReplaySize: mem::zeroed(), + }); let mut output = vk::PhysicalDeviceProperties2KHR { sType: vk::STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR, - pNext: ptr::null_mut(), + pNext: khr_rt_output.as_mut() as *mut vk::PhysicalDeviceRayTracingPropertiesKHR as *mut _, properties: mem::zeroed(), }; vk.GetPhysicalDeviceProperties2KHR(device, &mut output); - output.properties + (output.properties, PhysicalDeviceRayTracingProperties { + shaderGroupHandleSize: max(nv_rt_output.shaderGroupHandleSize, khr_rt_output.shaderGroupHandleSize), + maxRecursionDepth: max(nv_rt_output.maxRecursionDepth, khr_rt_output.maxRecursionDepth), + maxShaderGroupStride: max(nv_rt_output.maxShaderGroupStride, khr_rt_output.maxShaderGroupStride), + shaderGroupBaseAlignment: max(nv_rt_output.shaderGroupBaseAlignment, khr_rt_output.shaderGroupBaseAlignment), + maxGeometryCount: max(nv_rt_output.maxGeometryCount, khr_rt_output.maxGeometryCount), + maxInstanceCount: max(nv_rt_output.maxInstanceCount, khr_rt_output.maxInstanceCount), + maxPrimitiveCount: max(nv_rt_output.maxTriangleCount, khr_rt_output.maxPrimitiveCount), + maxDescriptorSetAccelerationStructures: max(nv_rt_output.maxDescriptorSetAccelerationStructures, khr_rt_output.maxDescriptorSetAccelerationStructures), + shaderGroupHandleCaptureReplaySize: khr_rt_output.shaderGroupHandleCaptureReplaySize, + }) }; let queue_families = unsafe { @@ -415,10 +452,11 @@ impl Instance { }; output.push(PhysicalDeviceInfos { - device: device, - properties: properties, - memory: memory, - queue_families: queue_families, + device, + properties, + properties_ray_tracing, + memory, + queue_families, available_features: Features::from_vulkan_features(available_features), }); } @@ -687,9 +725,23 @@ impl From for InstanceCreationError { } } +#[derive(Default)] +struct PhysicalDeviceRayTracingProperties { + shaderGroupHandleSize: u32, + maxRecursionDepth: u32, + maxShaderGroupStride: u32, + shaderGroupBaseAlignment: u32, + maxGeometryCount: u64, + maxInstanceCount: u64, + maxPrimitiveCount: u64, + maxDescriptorSetAccelerationStructures: u32, + shaderGroupHandleCaptureReplaySize: u32, +} + struct PhysicalDeviceInfos { device: vk::PhysicalDevice, properties: vk::PhysicalDeviceProperties, + properties_ray_tracing: PhysicalDeviceRayTracingProperties, queue_families: Vec, memory: vk::PhysicalDeviceMemoryProperties, available_features: Features, @@ -961,6 +1013,18 @@ impl<'a> PhysicalDevice<'a> { &self.infos().properties.pipelineCacheUUID } + /// Returns the size of a shader group handle + #[inline] + pub fn shader_group_handle_size(&self) -> u32 { + self.infos().properties_ray_tracing.shaderGroupHandleSize + } + + /// Returns the maximum ray tracing recursion depth for a trace call + #[inline] + pub fn max_recursion_depth(&self) -> u32 { + self.infos().properties_ray_tracing.maxRecursionDepth + } + // Internal function to make it easier to get the infos of this device. #[inline] fn infos(&self) -> &'a PhysicalDeviceInfos { From 81b0dc86cd8b2ac3b83fa55458d410d38cbe1a24 Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Tue, 14 Apr 2020 18:43:41 +0200 Subject: [PATCH 07/15] command_buffer: Use pipeline type enum instead of gfx bool --- vulkano/src/command_buffer/auto.rs | 20 +++++++++---------- vulkano/src/command_buffer/state_cacher.rs | 15 +++++++------- vulkano/src/command_buffer/synced/commands.rs | 10 +++++----- vulkano/src/command_buffer/sys.rs | 11 +++++----- vulkano/src/pipeline/mod.rs | 6 ++++++ 5 files changed, 34 insertions(+), 28 deletions(-) diff --git a/vulkano/src/command_buffer/auto.rs b/vulkano/src/command_buffer/auto.rs index c8dc5692e0..8af8cf3275 100644 --- a/vulkano/src/command_buffer/auto.rs +++ b/vulkano/src/command_buffer/auto.rs @@ -65,7 +65,7 @@ use framebuffer::SubpassContents; use image::ImageAccess; use image::ImageLayout; use instance::QueueFamily; -use pipeline::ComputePipelineAbstract; +use pipeline::{ComputePipelineAbstract, PipelineType}; use pipeline::GraphicsPipelineAbstract; use pipeline::input_assembly::Index; use pipeline::vertex::VertexSource; @@ -969,7 +969,7 @@ impl

AutoCommandBufferBuilder

{ push_constants(&mut self.inner, pipeline.clone(), constants); descriptor_sets(&mut self.inner, &mut self.state_cacher, - false, + PipelineType::Compute, pipeline.clone(), sets)?; @@ -1009,7 +1009,7 @@ impl

AutoCommandBufferBuilder

{ set_state(&mut self.inner, &dynamic); descriptor_sets(&mut self.inner, &mut self.state_cacher, - true, + PipelineType::Graphics, pipeline.clone(), sets)?; vertex_buffers(&mut self.inner, @@ -1066,7 +1066,7 @@ impl

AutoCommandBufferBuilder

{ set_state(&mut self.inner, &dynamic); descriptor_sets(&mut self.inner, &mut self.state_cacher, - true, + PipelineType::Graphics, pipeline.clone(), sets)?; vertex_buffers(&mut self.inner, @@ -1125,7 +1125,7 @@ impl

AutoCommandBufferBuilder

{ set_state(&mut self.inner, &dynamic); descriptor_sets(&mut self.inner, &mut self.state_cacher, - true, + PipelineType::Graphics, pipeline.clone(), sets)?; vertex_buffers(&mut self.inner, @@ -1190,7 +1190,7 @@ impl

AutoCommandBufferBuilder

{ set_state(&mut self.inner, &dynamic); descriptor_sets(&mut self.inner, &mut self.state_cacher, - true, + PipelineType::Graphics, pipeline.clone(), sets)?; vertex_buffers(&mut self.inner, @@ -1461,8 +1461,8 @@ unsafe fn vertex_buffers

(destination: &mut SyncCommandBufferBuilder

, } unsafe fn descriptor_sets(destination: &mut SyncCommandBufferBuilder

, - state_cacher: &mut StateCacher, gfx: bool, pipeline: Pl, - sets: S) + state_cacher: &mut StateCacher, pipeline_type: PipelineType, + pipeline: Pl, sets: S) -> Result<(), SyncCommandBufferBuilderError> where Pl: PipelineLayoutAbstract + Send + Sync + Clone + 'static, S: DescriptorSetsCollection @@ -1470,7 +1470,7 @@ unsafe fn descriptor_sets(destination: &mut SyncCommandBufferBuilder

(destination: &mut SyncCommandBufferBuilder

StateCacherDescriptorSets { + pub fn bind_descriptor_sets( + &mut self, + pipeline_type: PipelineType, + ) -> StateCacherDescriptorSets { if self.poisoned_descriptor_sets { self.compute_descriptor_sets = SmallVec::new(); self.graphics_descriptor_sets = SmallVec::new(); @@ -135,10 +137,9 @@ impl StateCacher { StateCacherDescriptorSets { poisoned: &mut self.poisoned_descriptor_sets, - state: if graphics { - &mut self.graphics_descriptor_sets - } else { - &mut self.compute_descriptor_sets + state: match pipeline_type { + PipelineType::Graphics => &mut self.graphics_descriptor_sets, + PipelineType::Compute => &mut self.compute_descriptor_sets, }, offset: 0, found_diff: None, diff --git a/vulkano/src/command_buffer/synced/commands.rs b/vulkano/src/command_buffer/synced/commands.rs index cfa422c9d1..71103b6dfc 100644 --- a/vulkano/src/command_buffer/synced/commands.rs +++ b/vulkano/src/command_buffer/synced/commands.rs @@ -37,7 +37,7 @@ use framebuffer::FramebufferAbstract; use framebuffer::SubpassContents; use image::ImageAccess; use image::ImageLayout; -use pipeline::ComputePipelineAbstract; +use pipeline::{ComputePipelineAbstract, PipelineType}; use pipeline::GraphicsPipelineAbstract; use pipeline::input_assembly::IndexType; use pipeline::viewport::Scissor; @@ -1924,7 +1924,7 @@ impl<'b, P> SyncCommandBufferBuilderBindDescriptorSets<'b, P> { } #[inline] - pub unsafe fn submit(self, graphics: bool, pipeline_layout: Pl, first_binding: u32, + pub unsafe fn submit(self, pipeline_type: PipelineType, pipeline_layout: Pl, first_binding: u32, dynamic_offsets: I) -> Result<(), SyncCommandBufferBuilderError> where Pl: PipelineLayoutAbstract + Send + Sync + 'static, @@ -1936,7 +1936,7 @@ impl<'b, P> SyncCommandBufferBuilderBindDescriptorSets<'b, P> { struct Cmd { inner: SmallVec<[Box; 12]>, - graphics: bool, + pipeline_type: PipelineType, pipeline_layout: Pl, first_binding: u32, dynamic_offsets: Option, @@ -1951,7 +1951,7 @@ impl<'b, P> SyncCommandBufferBuilderBindDescriptorSets<'b, P> { } unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { - out.bind_descriptor_sets(self.graphics, + out.bind_descriptor_sets(self.pipeline_type, &self.pipeline_layout, self.first_binding, self.inner.iter().map(|s| s.inner()), @@ -2106,7 +2106,7 @@ impl<'b, P> SyncCommandBufferBuilderBindDescriptorSets<'b, P> { self.builder.append_command(Cmd { inner: self.inner, - graphics, + pipeline_type, pipeline_layout, first_binding, dynamic_offsets: Some(dynamic_offsets), diff --git a/vulkano/src/command_buffer/sys.rs b/vulkano/src/command_buffer/sys.rs index dff5fa80b6..6a76df85c9 100644 --- a/vulkano/src/command_buffer/sys.rs +++ b/vulkano/src/command_buffer/sys.rs @@ -41,7 +41,7 @@ use framebuffer::SubpassContents; use image::ImageAccess; use image::ImageLayout; use instance::QueueFamily; -use pipeline::ComputePipelineAbstract; +use pipeline::{ComputePipelineAbstract, PipelineType}; use pipeline::GraphicsPipelineAbstract; use pipeline::input_assembly::IndexType; use pipeline::viewport::Scissor; @@ -455,7 +455,7 @@ impl

UnsafeCommandBufferBuilder

{ /// Does nothing if the list of descriptor sets is empty, as it would be a no-op and isn't a /// valid usage of the command anyway. #[inline] - pub unsafe fn bind_descriptor_sets<'s, Pl, S, I>(&mut self, graphics: bool, + pub unsafe fn bind_descriptor_sets<'s, Pl, S, I>(&mut self, pipeline_type: PipelineType, pipeline_layout: &Pl, first_binding: u32, sets: S, dynamic_offsets: I) where Pl: ?Sized + PipelineLayoutAbstract, @@ -474,10 +474,9 @@ impl

UnsafeCommandBufferBuilder

{ let num_bindings = sets.len() as u32; debug_assert!(first_binding + num_bindings <= pipeline_layout.num_sets() as u32); - let bind_point = if graphics { - vk::PIPELINE_BIND_POINT_GRAPHICS - } else { - vk::PIPELINE_BIND_POINT_COMPUTE + let bind_point = match pipeline_type { + PipelineType::Graphics => vk::PIPELINE_BIND_POINT_GRAPHICS, + PipelineType::Compute => vk::PIPELINE_BIND_POINT_COMPUTE, }; vk.CmdBindDescriptorSets(cmd, diff --git a/vulkano/src/pipeline/mod.rs b/vulkano/src/pipeline/mod.rs index 5235199367..32225edb00 100644 --- a/vulkano/src/pipeline/mod.rs +++ b/vulkano/src/pipeline/mod.rs @@ -97,3 +97,9 @@ pub mod raster; pub mod shader; pub mod vertex; pub mod viewport; + +#[derive(Copy, Clone)] +pub enum PipelineType { + Graphics, + Compute, +} From 6e6d975c7e4409b457c154c3daadb1fa29f2f714 Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Tue, 14 Apr 2020 21:13:41 +0200 Subject: [PATCH 08/15] pipeline: Add ray tracing pipeline --- examples/src/bin/nv-ray-tracing.rs | 289 +++++++++++++++ vulkano-shaders/src/codegen.rs | 31 +- vulkano-shaders/src/entry_point.rs | 95 +++++ vulkano-shaders/src/enums.rs | 18 +- vulkano/src/command_buffer/state_cacher.rs | 8 + vulkano/src/command_buffer/sys.rs | 1 + vulkano/src/pipeline/mod.rs | 42 ++- .../pipeline/ray_tracing_pipeline/builder.rs | 333 ++++++++++++++++++ .../ray_tracing_pipeline/creation_error.rs | 113 ++++++ .../src/pipeline/ray_tracing_pipeline/mod.rs | 258 ++++++++++++++ vulkano/src/pipeline/shader.rs | 92 +++++ 11 files changed, 1241 insertions(+), 39 deletions(-) create mode 100644 examples/src/bin/nv-ray-tracing.rs create mode 100644 vulkano/src/pipeline/ray_tracing_pipeline/builder.rs create mode 100644 vulkano/src/pipeline/ray_tracing_pipeline/creation_error.rs create mode 100644 vulkano/src/pipeline/ray_tracing_pipeline/mod.rs diff --git a/examples/src/bin/nv-ray-tracing.rs b/examples/src/bin/nv-ray-tracing.rs new file mode 100644 index 0000000000..b1150d4f6b --- /dev/null +++ b/examples/src/bin/nv-ray-tracing.rs @@ -0,0 +1,289 @@ +// Copyright (c) 2016 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +// Welcome to the ray tracing example! +// +// While real-time rendering has traditionally been using rasterization to render +// primitives, advances in computing power of graphics cards have enabled ray tracing, +// the tracing of paths of light throughout a scene to be performed in real time. +// This example demonstrates simple ray tracing. + +extern crate vulkano; +extern crate vulkano_shaders; +extern crate vulkano_win; +extern crate winit; + +use vulkano::buffer::{BufferUsage, ImmutableBuffer}; +use vulkano::command_buffer::AutoCommandBufferBuilder; +use vulkano::descriptor::descriptor_set::PersistentDescriptorSet; +use vulkano::device::{Device, DeviceExtensions}; +use vulkano::instance::{Instance, PhysicalDevice}; +use vulkano::pipeline::RayTracingPipeline; +use vulkano::swapchain; +use vulkano::swapchain::{ + AcquireError, ColorSpace, FullscreenExclusive, PresentMode, SurfaceTransform, Swapchain, + SwapchainCreationError, +}; +use vulkano::sync; +use vulkano::sync::{FlushError, GpuFuture}; + +use vulkano_win::VkSurfaceBuild; +use winit::event::{Event, WindowEvent}; +use winit::event_loop::{ControlFlow, EventLoop}; +use winit::window::WindowBuilder; + +use std::sync::Arc; + +fn main() { + let required_extensions = vulkano_win::required_extensions(); + let instance = Instance::new(None, &required_extensions, None).unwrap(); + let physical = PhysicalDevice::enumerate(&instance).next().unwrap(); + println!( + "Using device: {} (type: {:?})", + physical.name(), + physical.ty() + ); + + let event_loop = EventLoop::new(); + let surface = WindowBuilder::new() + .build_vk_surface(&event_loop, instance.clone()) + .unwrap(); + + let queue_family = physical + .queue_families() + .find(|&q| { + // TODO: use QUEUE_TRANSFER_BIT? + q.supports_graphics() && surface.is_supported(q).unwrap_or(false) + }) + .unwrap(); + + let device_ext = DeviceExtensions { + khr_swapchain: true, + khr_get_memory_requirements2: true, + nv_ray_tracing: true, + ..DeviceExtensions::none() + }; + let (device, mut queues) = Device::new( + physical, + physical.supported_features(), + &device_ext, + [(queue_family, 0.5)].iter().cloned(), + ) + .unwrap(); + + let queue = queues.next().unwrap(); + + let (mut swapchain, images) = { + let caps = surface.capabilities(physical).unwrap(); + assert!(caps.supported_usage_flags.storage); + let usage = caps.supported_usage_flags; + let alpha = caps.supported_composite_alpha.iter().next().unwrap(); + let format = caps.supported_formats[0].0; + let dimensions: [u32; 2] = surface.window().inner_size().into(); + let mode = if caps.present_modes.mailbox { + PresentMode::Mailbox + } else if caps.present_modes.immediate { + PresentMode::Immediate + } else { + PresentMode::Fifo + }; + + Swapchain::new( + device.clone(), + surface.clone(), + caps.min_image_count, + format, + dimensions, + 1, + usage, + &queue, + SurfaceTransform::Identity, + alpha, + mode, + FullscreenExclusive::Default, + true, + ColorSpace::SrgbNonLinear, + ) + .unwrap() + }; + + mod rs { + vulkano_shaders::shader! { + ty: "ray_generation", + src: "#version 460 core +#extension GL_NV_ray_tracing : enable + +layout(set = 0, binding = 0, rgba8) uniform image2D result; +layout(location = 0) rayPayloadNV vec4 payload; + +void main() { + ivec2 coord = ivec2(gl_LaunchIDNV); + const vec2 pixelCenter = coord + vec2(0.5); + const vec2 inUV = pixelCenter / vec2(gl_LaunchSizeNV.xy); + + payload = vec4(inUV.x, inUV.y, 1.0f, 1.0f); + imageStore(result, coord, payload); +} +" + } + } + let rs = rs::Shader::load(device.clone()).unwrap(); + + // We set a limit to the recursion of a ray so that the shader does not run infinitely + let max_recursion_depth = 5; + + let pipeline = Arc::new( + RayTracingPipeline::nv(max_recursion_depth) + // We need at least one ray generation shader to describe where rays go + // and to store the result of their path tracing + .raygen_shader(rs.main_entry_point(), ()) + .build(device.clone()) + .unwrap(), + ); + + let layout = pipeline.layout().descriptor_set_layout(0).unwrap(); + let mut sets = images + .iter() + .map(|image| { + Arc::new( + PersistentDescriptorSet::start(layout.clone()) + .add_image(image.clone()) + .unwrap() + .build() + .unwrap(), + ) + }) + .collect::>(); + + // TODO: Auto-generate a shader binding table buffer and return 4 views + // TODO: Return 1 buffer with 4 slices instead of 4 different buffers + // TODO: `miss_shader_binding_table`, `hit_shader_binding_table`, + // `callable_shader_binding_table` should empty buffers (size 0 and no handles) + // if there are no handles + let group_handles = pipeline.group_handles(queue.clone()); + let group_handle_size = device.physical_device().shader_group_handle_size() as usize; + + let (raygen_shader_binding_table, raygen_buffer_future) = ImmutableBuffer::from_iter( + group_handles[0..group_handle_size].iter().copied(), + BufferUsage::ray_tracing(), + queue.clone(), + ) + .unwrap(); + let (miss_shader_binding_table, miss_buffer_future) = ImmutableBuffer::from_iter( + (0..0).map(|_| 5u8), + BufferUsage::ray_tracing(), + queue.clone(), + ) + .unwrap(); + let (hit_shader_binding_table, hit_buffer_future) = ImmutableBuffer::from_iter( + (0..0).map(|_| 5u8), + BufferUsage::ray_tracing(), + queue.clone(), + ) + .unwrap(); + let (callable_shader_binding_table, callable_buffer_future) = ImmutableBuffer::from_iter( + (0..0).map(|_| 5u8), + BufferUsage::ray_tracing(), + queue.clone(), + ) + .unwrap(); + + raygen_buffer_future + .join(miss_buffer_future) + .join(hit_buffer_future) + .join(callable_buffer_future) + .then_signal_fence_and_flush() + .unwrap() + .wait(None) + .unwrap(); + + + let mut recreate_swapchain = false; + let mut previous_frame_end = Some(Box::new(sync::now(device.clone())) as Box); + + event_loop.run(move |event, _, control_flow| match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + *control_flow = ControlFlow::Exit; + } + Event::WindowEvent { + event: WindowEvent::Resized(_), + .. + } => { + recreate_swapchain = true; + } + Event::RedrawEventsCleared => { + previous_frame_end.as_mut().unwrap().cleanup_finished(); + + if recreate_swapchain { + let dimensions: [u32; 2] = surface.window().inner_size().into(); + let (new_swapchain, new_images) = + match swapchain.recreate_with_dimensions(dimensions) { + Ok(r) => r, + Err(SwapchainCreationError::UnsupportedDimensions) => return, + Err(e) => panic!("Failed to recreate swapchain: {:?}", e), + }; + + swapchain = new_swapchain; + let layout = pipeline.layout().descriptor_set_layout(0).unwrap(); + sets = new_images + .iter() + .map(|image| { + Arc::new( + PersistentDescriptorSet::start(layout.clone()) + .add_image(image.clone()) + .unwrap() + .build() + .unwrap(), + ) + }) + .collect::>(); + recreate_swapchain = false; + } + + let (image_num, suboptimal, acquire_future) = + match swapchain::acquire_next_image(swapchain.clone(), None) { + Ok(r) => r, + Err(AcquireError::OutOfDate) => { + recreate_swapchain = true; + return; + } + Err(e) => panic!("Failed to acquire next image: {:?}", e), + }; + + if suboptimal { + recreate_swapchain = true; + } + + let future = previous_frame_end + .take() + .unwrap() + .join(acquire_future) + .then_swapchain_present(queue.clone(), swapchain.clone(), image_num) + .then_signal_fence_and_flush(); + + match future { + Ok(future) => { + previous_frame_end = Some(Box::new(future) as Box<_>); + } + Err(FlushError::OutOfDate) => { + recreate_swapchain = true; + previous_frame_end = Some(Box::new(sync::now(device.clone())) as Box<_>); + } + Err(e) => { + println!("Failed to flush future: {:?}", e); + previous_frame_end = Some(Box::new(sync::now(device.clone())) as Box<_>); + } + } + } + _ => (), + }); +} diff --git a/vulkano-shaders/src/codegen.rs b/vulkano-shaders/src/codegen.rs index 38f182d453..41e461efba 100644 --- a/vulkano-shaders/src/codegen.rs +++ b/vulkano-shaders/src/codegen.rs @@ -424,30 +424,13 @@ fn storage_class_requirement(storage_class: &StorageClass) -> DeviceRequirement StorageClass::StorageClassImage => DeviceRequirement::None, StorageClass::StorageClassStorageBuffer => DeviceRequirement::Extensions(&["khr_storage_buffer_storage_class"]), - StorageClass::StorageClassCallableDataKHR => - DeviceRequirement::Extensions(&["khr_ray_tracing"]), - StorageClass::StorageClassCallableDataNV => - DeviceRequirement::Extensions(&["nv_ray_tracing"]), - StorageClass::StorageClassIncomingCallableDataKHR => - DeviceRequirement::Extensions(&["khr_ray_tracing"]), - StorageClass::StorageClassIncomingCallableDataNV => - DeviceRequirement::Extensions(&["nv_ray_tracing"]), - StorageClass::StorageClassRayPayloadKHR => - DeviceRequirement::Extensions(&["khr_ray_tracing"]), - StorageClass::StorageClassRayPayloadNV => - DeviceRequirement::Extensions(&["nv_ray_tracing"]), - StorageClass::StorageClassHitAttributeKHR => - DeviceRequirement::Extensions(&["khr_ray_tracing"]), - StorageClass::StorageClassHitAttributeNV => - DeviceRequirement::Extensions(&["nv_ray_tracing"]), - StorageClass::StorageClassIncomingRayPayloadKHR => - DeviceRequirement::Extensions(&["khr_ray_tracing"]), - StorageClass::StorageClassIncomingRayPayloadNV => - DeviceRequirement::Extensions(&["nv_ray_tracing"]), - StorageClass::StorageClassShaderRecordBufferKHR => - DeviceRequirement::Extensions(&["khr_ray_tracing"]), - StorageClass::StorageClassShaderRecordBufferNV => - DeviceRequirement::Extensions(&["nv_ray_tracing"]), + // TODO: requires either "khr_ray_tracing" or "nv_ray_tracing" + StorageClass::StorageClassCallableData => DeviceRequirement::None, + StorageClass::StorageClassIncomingCallableData => DeviceRequirement::None, + StorageClass::StorageClassRayPayload => DeviceRequirement::None, + StorageClass::StorageClassHitAttribute => DeviceRequirement::None, + StorageClass::StorageClassIncomingRayPayload => DeviceRequirement::None, + StorageClass::StorageClassShaderRecordBuffer => DeviceRequirement::None, } } diff --git a/vulkano-shaders/src/entry_point.rs b/vulkano-shaders/src/entry_point.rs index ab188535e2..3b95bd2adc 100644 --- a/vulkano-shaders/src/entry_point.rs +++ b/vulkano-shaders/src/entry_point.rs @@ -162,6 +162,101 @@ pub fn write_entry_point(doc: &Spirv, instruction: &Instruction) -> (TokenStream Layout(ShaderStages { compute: true, .. ShaderStages::none() }) )}, ) + } else if match *execution { + ExecutionModel::ExecutionModelRayGenerationNV => true, + ExecutionModel::ExecutionModelIntersectionNV => true, + ExecutionModel::ExecutionModelAnyHitNV => true, + ExecutionModel::ExecutionModelClosestHitNV => true, + ExecutionModel::ExecutionModelMissNV => true, + ExecutionModel::ExecutionModelCallableNV => true, + ExecutionModel::ExecutionModelRayGenerationKHR => true, + ExecutionModel::ExecutionModelIntersectionKHR => true, + ExecutionModel::ExecutionModelAnyHitKHR => true, + ExecutionModel::ExecutionModelClosestHitKHR => true, + ExecutionModel::ExecutionModelMissKHR => true, + ExecutionModel::ExecutionModelCallableKHR => true, + _ => false, + } { + let entry_ty = match *execution { + ExecutionModel::ExecutionModelRayGenerationNV + | ExecutionModel::ExecutionModelRayGenerationKHR => { + quote! { ::vulkano::pipeline::shader::RayTracingShaderType::Raygen } + } + + ExecutionModel::ExecutionModelIntersectionNV + | ExecutionModel::ExecutionModelIntersectionKHR => { + quote! { ::vulkano::pipeline::shader::RayTracingShaderType::AnyHit } + } + + ExecutionModel::ExecutionModelAnyHitNV + | ExecutionModel::ExecutionModelAnyHitKHR => { + quote! { ::vulkano::pipeline::shader::RayTracingShaderType::ClosestHit } + } + + ExecutionModel::ExecutionModelClosestHitNV + | ExecutionModel::ExecutionModelClosestHitKHR => { + quote! { ::vulkano::pipeline::shader::RayTracingShaderType::Miss } + } + + ExecutionModel::ExecutionModelMissNV | ExecutionModel::ExecutionModelMissKHR => { + quote! { ::vulkano::pipeline::shader::RayTracingShaderType::Intersection } + } + + ExecutionModel::ExecutionModelCallableNV + | ExecutionModel::ExecutionModelCallableKHR => { + quote! { ::vulkano::pipeline::shader::RayTracingShaderType::Callable } + } + + _ => unreachable!(), + }; + + let stage = match *execution { + ExecutionModel::ExecutionModelRayGenerationNV + | ExecutionModel::ExecutionModelRayGenerationKHR => { + quote! { ShaderStages { raygen: true, .. ShaderStages::none() } } + } + + ExecutionModel::ExecutionModelIntersectionNV + | ExecutionModel::ExecutionModelIntersectionKHR => { + quote! { ShaderStages { intersection: true, .. ShaderStages::none() } } + } + + ExecutionModel::ExecutionModelAnyHitNV + | ExecutionModel::ExecutionModelAnyHitKHR => { + quote! { ShaderStages { any_hit: true, .. ShaderStages::none() } } + } + + ExecutionModel::ExecutionModelClosestHitNV + | ExecutionModel::ExecutionModelClosestHitKHR => { + quote! { ShaderStages { closest_hit: true, .. ShaderStages::none() } } + } + + ExecutionModel::ExecutionModelMissNV | ExecutionModel::ExecutionModelMissKHR => { + quote! { ShaderStages { miss: true, .. ShaderStages::none() } } + } + + ExecutionModel::ExecutionModelCallableNV + | ExecutionModel::ExecutionModelCallableKHR => { + quote! { ShaderStages { callable: true, .. ShaderStages::none() } } + } + + _ => unreachable!(), + }; + + let ty = quote! { + ::vulkano::pipeline::shader::RayTracingEntryPoint< + #spec_consts_struct, + Layout> + }; + let f_call = quote! { + ray_tracing_entry_point( + ::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), + Layout(#stage), + #entry_ty + ) + }; + + (ty, f_call) } else { panic!("Execution Model is not supported"); } diff --git a/vulkano-shaders/src/enums.rs b/vulkano-shaders/src/enums.rs index 0d79e73321..db97ac8c40 100644 --- a/vulkano-shaders/src/enums.rs +++ b/vulkano-shaders/src/enums.rs @@ -127,18 +127,12 @@ enumeration! { StorageClassAtomicCounter = 10, StorageClassImage = 11, StorageClassStorageBuffer = 12, - StorageClassCallableDataKHR = 5328, - StorageClassCallableDataNV = 5328, - StorageClassIncomingCallableDataKHR = 5329, - StorageClassIncomingCallableDataNV = 5329, - StorageClassRayPayloadKHR = 5338, - StorageClassRayPayloadNV = 5338, - StorageClassHitAttributeKHR = 5339, - StorageClassHitAttributeNV = 5339, - StorageClassIncomingRayPayloadKHR = 5342, - StorageClassIncomingRayPayloadNV = 5342, - StorageClassShaderRecordBufferKHR = 5343, - StorageClassShaderRecordBufferNV = 5343, + StorageClassCallableData = 5328, + StorageClassIncomingCallableData = 5329, + StorageClassRayPayload = 5338, + StorageClassHitAttribute = 5339, + StorageClassIncomingRayPayload = 5342, + StorageClassShaderRecordBuffer = 5343, } StorageClass; typedef enum Dim_ { diff --git a/vulkano/src/command_buffer/state_cacher.rs b/vulkano/src/command_buffer/state_cacher.rs index 77ba80649f..a4eac11d2a 100644 --- a/vulkano/src/command_buffer/state_cacher.rs +++ b/vulkano/src/command_buffer/state_cacher.rs @@ -29,10 +29,14 @@ pub struct StateCacher { compute_pipeline: vk::Pipeline, // The graphics pipeline currently bound. 0 if nothing bound. graphics_pipeline: vk::Pipeline, + // The ray tracing pipeline currently bound. 0 if nothing bound. + ray_tracing_pipeline: vk::Pipeline, // The descriptor sets for the compute pipeline. compute_descriptor_sets: SmallVec<[vk::DescriptorSet; 12]>, // The descriptor sets for the graphics pipeline. graphics_descriptor_sets: SmallVec<[vk::DescriptorSet; 12]>, + // The descriptor sets for the graphics pipeline. + ray_tracing_descriptor_sets: SmallVec<[vk::DescriptorSet; 12]>, // If the user starts comparing descriptor sets, but drops the helper struct in the middle of // the processing then we will end up in a weird state. This bool is true when we start // comparing sets, and is set to false when we end up comparing. If it was true when we start @@ -63,8 +67,10 @@ impl StateCacher { dynamic_state: DynamicState::none(), compute_pipeline: 0, graphics_pipeline: 0, + ray_tracing_pipeline: 0, compute_descriptor_sets: SmallVec::new(), graphics_descriptor_sets: SmallVec::new(), + ray_tracing_descriptor_sets: SmallVec::new(), poisoned_descriptor_sets: false, vertex_buffers: SmallVec::new(), poisoned_vertex_buffers: false, @@ -131,6 +137,7 @@ impl StateCacher { if self.poisoned_descriptor_sets { self.compute_descriptor_sets = SmallVec::new(); self.graphics_descriptor_sets = SmallVec::new(); + self.ray_tracing_descriptor_sets = SmallVec::new(); } self.poisoned_descriptor_sets = true; @@ -140,6 +147,7 @@ impl StateCacher { state: match pipeline_type { PipelineType::Graphics => &mut self.graphics_descriptor_sets, PipelineType::Compute => &mut self.compute_descriptor_sets, + PipelineType::RayTracing => &mut self.ray_tracing_descriptor_sets, }, offset: 0, found_diff: None, diff --git a/vulkano/src/command_buffer/sys.rs b/vulkano/src/command_buffer/sys.rs index 6a76df85c9..dc8386cc58 100644 --- a/vulkano/src/command_buffer/sys.rs +++ b/vulkano/src/command_buffer/sys.rs @@ -477,6 +477,7 @@ impl

UnsafeCommandBufferBuilder

{ let bind_point = match pipeline_type { PipelineType::Graphics => vk::PIPELINE_BIND_POINT_GRAPHICS, PipelineType::Compute => vk::PIPELINE_BIND_POINT_COMPUTE, + PipelineType::RayTracing => vk::PIPELINE_BIND_POINT_RAY_TRACING_KHR, }; vk.CmdBindDescriptorSets(cmd, diff --git a/vulkano/src/pipeline/mod.rs b/vulkano/src/pipeline/mod.rs index 32225edb00..c722c1eeca 100644 --- a/vulkano/src/pipeline/mod.rs +++ b/vulkano/src/pipeline/mod.rs @@ -17,12 +17,14 @@ //! the CPU). Consequently it is a CPU-intensive operation that should be performed at //! initialization or during a loading screen. //! -//! There are two kinds of pipelines: +//! There are three kinds of pipelines: //! //! - `ComputePipeline`s, for compute operations (general-purpose operations that read/write data //! in buffers or raw pixels in images). -//! - `GraphicsPipeline`s, for graphical operations (operations that take vertices as input and -//! write pixels to a framebuffer). +//! - `GraphicsPipeline`s, for depth-buffer based graphical operations (operations that take +//! vertices as input and write pixels to a framebuffer). +//! - `RayTracingPipeline`s, for ray tracing based graphical operations (operations that take +//! acceleration structures and geometry as input and write pixels to a storage image). //! //! # Creating a compute pipeline. //! @@ -70,6 +72,33 @@ //! you must pass multiple shaders alongside with configuration for the other steps. //! //! TODO: add an example +//! +//! # Creating a ray tracing pipeline +//! +//! A ray tracing operation takes a scene as input. The scene is represented as an acceleration +//! structure in order for rays to quickly access geometry. The acceleration structures is +//! typically a bounding volume hiearchy of axis-aligned bounding boxes. The acceleration structure +//! is filled with triangles (vertices and indices) or with axis-aligned bounding boxes for +//! procedural geometry. Tracing consists of multiple steps: +//! +//! - A *shaders* called the *ray-generation shader* is run once for every ray created and can call +//! a trace command on the scene and from its result, it can store color in the storage image from +//! the resulting ray payload. +//! - A number of optional shaders called the *miss shaders* are run for every ray which does not +//! encounter geometry. It can create a new trace command or write data to the ray payload. +//! - A number of optional *shader groups* containing the following shaders: +//! - Optionally, a shader called the *closest-hit shader* is run once for each ray which has +//! finished traversing the scene and has encountered geometry. It may read the intersection +//! data and read or write to the ray payload. +//! - Optionally, a shader called the *any-hit shader* is run for every interesction each ray has +//! in the scene. It can evaluate if a geometry intersection should be accepted or not. It may +//! read the intersection data and read or write to the ray payload +//! - Optionally an *intersection shader* is run for procedural geometry is run for every +//! bounding box each ray intersects. It then reports if the procedural geometry in the +//! bounding box is intersected by the ray by writing to the intersection data. +//! - A number of optional shaders called the *callable shaders* are run from ray-generation, +//! closest-hit, miss or other callable shaders to run on arbitrary data similarly to an +//! indirect compute shader call. // TODO: graphics pipeline params are deprecated, but are still the primary implementation in order // to avoid duplicating code, so we hide the warnings for now @@ -84,9 +113,15 @@ pub use self::graphics_pipeline::GraphicsPipelineAbstract; pub use self::graphics_pipeline::GraphicsPipelineBuilder; pub use self::graphics_pipeline::GraphicsPipelineCreationError; pub use self::graphics_pipeline::GraphicsPipelineSys; +pub use self::ray_tracing_pipeline::RayTracingPipeline; +pub use self::ray_tracing_pipeline::RayTracingPipelineAbstract; +pub use self::ray_tracing_pipeline::RayTracingPipelineBuilder; +pub use self::ray_tracing_pipeline::RayTracingPipelineCreationError; +pub use self::ray_tracing_pipeline::RayTracingPipelineSys; mod compute_pipeline; mod graphics_pipeline; +mod ray_tracing_pipeline; pub mod blend; pub mod cache; @@ -102,4 +137,5 @@ pub mod viewport; pub enum PipelineType { Graphics, Compute, + RayTracing, } diff --git a/vulkano/src/pipeline/ray_tracing_pipeline/builder.rs b/vulkano/src/pipeline/ray_tracing_pipeline/builder.rs new file mode 100644 index 0000000000..ff631ecb6e --- /dev/null +++ b/vulkano/src/pipeline/ray_tracing_pipeline/builder.rs @@ -0,0 +1,333 @@ +// Copyright (c) 2017 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +use smallvec::SmallVec; +use std::mem; +use std::mem::MaybeUninit; +use std::ptr; +use std::sync::Arc; +use std::u32; + +use descriptor::pipeline_layout::PipelineLayoutAbstract; +use descriptor::pipeline_layout::PipelineLayoutDesc; +use descriptor::pipeline_layout::PipelineLayoutDescTweaks; +use device::Device; +use pipeline::ray_tracing_pipeline::Inner as RayTracingPipelineInner; +use pipeline::ray_tracing_pipeline::RayTracingPipeline; +use pipeline::ray_tracing_pipeline::RayTracingPipelineCreationError; +use pipeline::shader::EmptyEntryPointDummy; +use pipeline::shader::RayTracingEntryPointAbstract; +use pipeline::shader::SpecializationConstants; + +use check_errors; +use vk; +use VulkanObject; + +/// Prototype for a `RayTracingPipeline`. +// TODO: we can optimize this by filling directly the raw vk structs +pub struct RayTracingPipelineBuilder { + nv_extension: bool, + raygen_shader: Option<(Rs, Rss)>, + max_recursion_depth: u32, +} + +impl RayTracingPipelineBuilder { + /// Builds a new empty builder using the `nv_ray_tracing` extension. + pub(super) fn nv(max_recursion_depth: u32) -> Self { + RayTracingPipelineBuilder { + nv_extension: true, + raygen_shader: None, + max_recursion_depth, + } + } + + /// Builds a new empty builder using the `khr_ray_tracing` extension. + pub(super) fn khr(max_recursion_depth: u32) -> Self { + RayTracingPipelineBuilder { + nv_extension: false, + raygen_shader: None, + max_recursion_depth, + } + } +} + +impl RayTracingPipelineBuilder +where + Rs: RayTracingEntryPointAbstract, + Rss: SpecializationConstants, + Rs::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required +{ + /// Builds the ray tracing pipeline, using an inferred a pipeline layout. + // TODO: replace Box with a PipelineUnion struct without template params + pub fn build( + self, + device: Arc, + ) -> Result< + RayTracingPipeline>, + RayTracingPipelineCreationError, + > { + self.with_auto_layout(device, &[]) + } + + /// Builds the ray tracing pipeline using the `nv_ray_tracing` extension. + /// + /// Does the same as `build`, except that `build` automatically builds the pipeline layout + /// object corresponding to the union of your shaders while this function allows you to specify + /// the pipeline layout. + pub fn with_pipeline_layout_nv( + self, + device: Arc, + pipeline_layout: L, + ) -> Result, RayTracingPipelineCreationError> + where + L: PipelineLayoutAbstract, + { + self.with_pipeline_layout(device, pipeline_layout) + } + + fn with_auto_layout( + self, + device: Arc, + dynamic_buffers: &[(usize, usize)], + ) -> Result< + RayTracingPipeline>, + RayTracingPipelineCreationError, + > { + let pipeline_layout; + + // Must be at least one stage with raygen + if let Some(ref raygen_shader) = self.raygen_shader { + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + self.raygen_shader.as_ref().unwrap().0.layout().clone(), + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } else { + return Err(RayTracingPipelineCreationError::NoRaygenShader); + } + + if self.max_recursion_depth > device.physical_device().max_recursion_depth() { + return Err(RayTracingPipelineCreationError::MaxRecursionDepthExceeded { + max: device.physical_device().max_recursion_depth() as usize, + obtained: self.max_recursion_depth as usize, + }); + } + + // TODO: Callable, Miss and Raygen are alone in a General Shader Group + // TODO: Intersection shader is required in procedural group and disallowed in triangle group + // TODO: Anyhit and closest hit are optional in procedural group and disallowed in triangle group + // TODO: groupCount must be greater than 0 + // TODO: layout must be consistent with all shaders specified in pStages + // TODO: The number of resources in layout accessible to each shader stage that is used by + // the pipeline must be less than or equal to VkPhysicalDeviceLimits::maxPerStageResources + // TODO: If VkPhysicalDeviceRayTracingFeaturesKHR::rayTracingShaderGroupHandleCaptureReplayMixed + // is VK_FALSE then pShaderGroupCaptureReplayHandle must not be provided if it has not been + // provided on a previous call to ray tracing pipeline creation + // TODO: If VkPhysicalDeviceRayTracingFeaturesKHR::rayTracingShaderGroupHandleCaptureReplayMixed + // is VK_FALSE then the caller must guarantee that no ray tracing pipeline creation commands + // with pShaderGroupCaptureReplayHandle provided execute simultaneously with ray tracing + // pipeline creation commands without pShaderGroupCaptureReplayHandle provided + self.with_pipeline_layout(device, pipeline_layout) + } + + fn with_pipeline_layout( + self, + device: Arc, + pipeline_layout: L, + ) -> Result, RayTracingPipelineCreationError> + where + L: PipelineLayoutAbstract, + { + let vk = device.pointers(); + + // Creating the specialization constants of the various stages. + let raygen_shader_specialization = { + let spec_descriptors = Rss::descriptors(); + let constants = &self.raygen_shader.as_ref().unwrap().1; + vk::SpecializationInfo { + mapEntryCount: spec_descriptors.len() as u32, + pMapEntries: spec_descriptors.as_ptr() as *const _, + dataSize: mem::size_of_val(constants), + pData: constants as *const Rss as *const _, + } + }; + let raygen_stage = vk::PipelineShaderStageCreateInfo { + sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + pNext: ptr::null(), + flags: 0, // reserved + stage: vk::SHADER_STAGE_RAYGEN_BIT_KHR, + module: self + .raygen_shader + .as_ref() + .unwrap() + .0 + .module() + .internal_object(), + pName: self.raygen_shader.as_ref().unwrap().0.name().as_ptr(), + pSpecializationInfo: &raygen_shader_specialization as *const _, + }; + + let (pipeline, group_count) = if self.nv_extension { + let mut stages = SmallVec::<[_; 1]>::new(); + let mut groups = SmallVec::<[_; 1]>::new(); + + // Raygen + groups.push(vk::RayTracingShaderGroupCreateInfoNV { + sType: vk::STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV, + pNext: ptr::null(), + type_: vk::RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV, + generalShader: stages.len() as u32, + closestHitShader: vk::SHADER_UNUSED, + anyHitShader: vk::SHADER_UNUSED, + intersectionShader: vk::SHADER_UNUSED, + }); + stages.push(raygen_stage); + + unsafe { + let infos = vk::RayTracingPipelineCreateInfoNV { + sType: vk::STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV, + pNext: ptr::null(), + flags: 0, + stageCount: stages.len() as u32, + pStages: stages.as_ptr(), + groupCount: groups.len() as u32, + pGroups: groups.as_ptr(), + layout: PipelineLayoutAbstract::sys(&pipeline_layout).internal_object(), + maxRecursionDepth: self.max_recursion_depth, + basePipelineHandle: 0, // TODO: + basePipelineIndex: -1, // TODO: + }; + + let mut output = MaybeUninit::uninit(); + check_errors(vk.CreateRayTracingPipelinesNV( + device.internal_object(), + 0, + 1, + &infos, + ptr::null(), + output.as_mut_ptr(), + ))?; + (output.assume_init(), groups.len() as u32) + } + } else { + let mut stages = SmallVec::<[_; 1]>::new(); + let mut groups = SmallVec::<[_; 1]>::new(); + + // Raygen + groups.push(vk::RayTracingShaderGroupCreateInfoKHR { + sType: vk::STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR, + pNext: ptr::null(), + type_: vk::RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR, + generalShader: stages.len() as u32, + closestHitShader: vk::SHADER_UNUSED, + anyHitShader: vk::SHADER_UNUSED, + intersectionShader: vk::SHADER_UNUSED, + pShaderGroupCaptureReplayHandle: ptr::null(), // TODO: + }); + stages.push(raygen_stage); + + let library_info = vk::PipelineLibraryCreateInfoKHR { + sType: vk::STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR, + pNext: ptr::null(), + libraryCount: 0, // TODO: + pLibraries: ptr::null(), // TODO: + }; + + unsafe { + let infos = vk::RayTracingPipelineCreateInfoKHR { + sType: vk::STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR, + pNext: ptr::null(), + flags: 0, + stageCount: stages.len() as u32, + pStages: stages.as_ptr(), + groupCount: groups.len() as u32, + pGroups: groups.as_ptr(), + maxRecursionDepth: self.max_recursion_depth, + libraries: library_info, + pLibraryInterface: ptr::null(), // TODO: + layout: PipelineLayoutAbstract::sys(&pipeline_layout).internal_object(), + basePipelineHandle: 0, // TODO: + basePipelineIndex: -1, // TODO: + }; + + let mut output = MaybeUninit::uninit(); + check_errors(vk.CreateRayTracingPipelinesKHR( + device.internal_object(), + 0, + 1, + &infos, + ptr::null(), + output.as_mut_ptr(), + ))?; + (output.assume_init(), groups.len() as u32) + } + }; + + // Some drivers return `VK_SUCCESS` but provide a null handle if they + // fail to create the pipeline (due to invalid shaders, etc) + // This check ensures that we don't create an invalid `RayTracingPipeline` instance + if pipeline == vk::NULL_HANDLE { + panic!("vkCreateRayTracingPipelines provided a NULL handle"); + } + + Ok(RayTracingPipeline { + inner: RayTracingPipelineInner { + device: device.clone(), + pipeline, + }, + layout: pipeline_layout, + group_count, + max_recursion_depth: self.max_recursion_depth, + nv_extension: self.nv_extension, + }) + } + + // TODO: add build_with_cache method +} + +impl RayTracingPipelineBuilder { + // TODO: add pipeline derivate system + + /// Adds a raygen shader group to use. + // TODO: raygen_shader should be a list + // TODO: correct specialization constants + #[inline] + pub fn raygen_shader( + self, + shader: Rs2, + specialization_constants: Rss2, + ) -> RayTracingPipelineBuilder + where + Rs2: RayTracingEntryPointAbstract, + Rss2: SpecializationConstants, + { + RayTracingPipelineBuilder { + nv_extension: self.nv_extension, + max_recursion_depth: self.max_recursion_depth, + raygen_shader: Some((shader, specialization_constants)), + } + } +} + +impl Clone for RayTracingPipelineBuilder +where + Rs: Clone, + Rss: Clone, +{ + fn clone(&self) -> Self { + RayTracingPipelineBuilder { + nv_extension: self.nv_extension, + raygen_shader: self.raygen_shader.clone(), + max_recursion_depth: self.max_recursion_depth, + } + } +} diff --git a/vulkano/src/pipeline/ray_tracing_pipeline/creation_error.rs b/vulkano/src/pipeline/ray_tracing_pipeline/creation_error.rs new file mode 100644 index 0000000000..19194f5e5d --- /dev/null +++ b/vulkano/src/pipeline/ray_tracing_pipeline/creation_error.rs @@ -0,0 +1,113 @@ +// Copyright (c) 2017 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +use std::error; +use std::fmt; + +use descriptor::pipeline_layout::PipelineLayoutNotSupersetError; +use Error; +use OomError; + +/// Error that can happen when creating a graphics pipeline. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum RayTracingPipelineCreationError { + /// Not enough memory. + OomError(OomError), + + /// The pipeline layout is not compatible with what the shaders expect. + IncompatiblePipelineLayout(PipelineLayoutNotSupersetError), + + /// There are no raygen shaders passed to pipeline. + NoRaygenShader, + + /// The wrong type of shader has been passed. + /// + /// For example you passed a hit shader as the raygen. + WrongShaderType, + + /// The `rayTracing` feature must be enabled in order to use ray tracing. + RayTracingFeatureNotEnabled, + + /// The maximum recursion depth of the pipeline has been exceeded. + MaxRecursionDepthExceeded { + /// Maximum allowed value. + max: usize, + /// Value that was passed. + obtained: usize, + }, +} + +impl error::Error for RayTracingPipelineCreationError { + #[inline] + fn description(&self) -> &str { + match *self { + RayTracingPipelineCreationError::OomError(_) => "not enough memory available", + RayTracingPipelineCreationError::IncompatiblePipelineLayout(_) => { + "the pipeline layout is not compatible with what the shaders expect" + } + RayTracingPipelineCreationError::NoRaygenShader => { + "at least one of the shader stages must be a raygen shader" + } + RayTracingPipelineCreationError::WrongShaderType => { + "the wrong type of shader has been passed" + } + RayTracingPipelineCreationError::RayTracingFeatureNotEnabled => { + "the `rayTracing` feature must be enabled in order to use ray tracing." + } + RayTracingPipelineCreationError::MaxRecursionDepthExceeded { .. } => { + "the maximum recursion depth has been exceeded" + } + } + } + + #[inline] + fn cause(&self) -> Option<&dyn error::Error> { + match *self { + RayTracingPipelineCreationError::OomError(ref err) => Some(err), + RayTracingPipelineCreationError::IncompatiblePipelineLayout(ref err) => Some(err), + _ => None, + } + } +} + +impl fmt::Display for RayTracingPipelineCreationError { + #[inline] + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(fmt, "{}", error::Error::description(self)) + } +} + +impl From for RayTracingPipelineCreationError { + #[inline] + fn from(err: OomError) -> RayTracingPipelineCreationError { + RayTracingPipelineCreationError::OomError(err) + } +} + +impl From for RayTracingPipelineCreationError { + #[inline] + fn from(err: PipelineLayoutNotSupersetError) -> RayTracingPipelineCreationError { + RayTracingPipelineCreationError::IncompatiblePipelineLayout(err) + } +} + +impl From for RayTracingPipelineCreationError { + #[inline] + fn from(err: Error) -> RayTracingPipelineCreationError { + match err { + err @ Error::OutOfHostMemory => { + RayTracingPipelineCreationError::OomError(OomError::from(err)) + } + err @ Error::OutOfDeviceMemory => { + RayTracingPipelineCreationError::OomError(OomError::from(err)) + } + _ => panic!("unexpected error: {:?}", err), + } + } +} diff --git a/vulkano/src/pipeline/ray_tracing_pipeline/mod.rs b/vulkano/src/pipeline/ray_tracing_pipeline/mod.rs new file mode 100644 index 0000000000..0ff483722e --- /dev/null +++ b/vulkano/src/pipeline/ray_tracing_pipeline/mod.rs @@ -0,0 +1,258 @@ +// Copyright (c) 2017 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +use std::fmt; +use std::marker::PhantomData; +use std::sync::Arc; +use std::u32; + +use check_errors; +use descriptor::descriptor::DescriptorDesc; +use descriptor::descriptor_set::UnsafeDescriptorSetLayout; +use descriptor::pipeline_layout::PipelineLayoutDesc; +use descriptor::pipeline_layout::PipelineLayoutDescPcRange; +use descriptor::pipeline_layout::PipelineLayoutSys; +use descriptor::PipelineLayoutAbstract; +use device::{Device, DeviceOwned, Queue}; +use pipeline::shader::EmptyEntryPointDummy; +use vk; +use SafeDeref; +use VulkanObject; + +pub use self::builder::RayTracingPipelineBuilder; +pub use self::creation_error::RayTracingPipelineCreationError; + +mod builder; +mod creation_error; +// FIXME: restore +//mod tests; + +/// Defines how the implementation should perform a draw operation. +/// +/// This object contains the shaders and the various fixed states that describe how the +/// implementation should perform the various operations needed by a draw command. +pub struct RayTracingPipeline { + inner: Inner, + layout: Layout, + + group_count: u32, + max_recursion_depth: u32, + nv_extension: bool, +} + +struct Inner { + pipeline: vk::Pipeline, + device: Arc, +} + +impl RayTracingPipeline<()> { + /// Starts the building process of a ray tracing pipeline using the + /// `nv_ray_tracing` extension. + /// Returns a builder object that you can fill with the various parameters. + pub fn nv<'a>( + max_recursion_depth: u32, + ) -> RayTracingPipelineBuilder { + RayTracingPipelineBuilder::nv(max_recursion_depth) + } + + /// Starts the building process of a ray tracing pipeline using the + /// `khr_ray_tracing` extension. + /// Returns a builder object that you can fill with the various parameters. + pub fn khr<'a>( + max_recursion_depth: u32, + ) -> RayTracingPipelineBuilder { + RayTracingPipelineBuilder::khr(max_recursion_depth) + } +} + +impl RayTracingPipeline { + #[inline] + pub fn group_handles(&self, queue: Arc) -> Vec { + if self.nv_extension { + self.group_handles_nv(queue) + } else { + self.group_handles_khr(queue) + } + } + + #[inline] + fn group_handles_nv(&self, queue: Arc) -> Vec { + let binding_table_size = (self.group_count + * self.device().physical_device().shader_group_handle_size()) + as usize; + let mut shader_handle_storage = Vec::::with_capacity(binding_table_size.clone()); + shader_handle_storage.resize(binding_table_size.clone(), 0); + + debug_assert!(self.device().loaded_extensions().nv_ray_tracing); + + unsafe { + let vk = self.device().pointers(); + check_errors(vk.GetRayTracingShaderGroupHandlesNV( + self.device().internal_object(), + self.inner.pipeline.clone(), + 0, + self.group_count, + binding_table_size, + shader_handle_storage.as_mut_ptr() as *mut _, + )) + .unwrap(); + }; + shader_handle_storage + } + + #[inline] + fn group_handles_khr(&self, queue: Arc) -> Vec { + let binding_table_size = (self.group_count + * self.device().physical_device().shader_group_handle_size()) + as usize; + let mut shader_handle_storage = Vec::::with_capacity(binding_table_size.clone()); + shader_handle_storage.resize(binding_table_size.clone(), 0); + + debug_assert!(self.device().loaded_extensions().khr_ray_tracing); + + unsafe { + let vk = self.device().pointers(); + check_errors(vk.GetRayTracingShaderGroupHandlesKHR( + self.device().internal_object(), + self.inner.pipeline.clone(), + 0, + self.group_count, + binding_table_size, + shader_handle_storage.as_mut_ptr() as *mut _, + )) + .unwrap(); + }; + shader_handle_storage + } +} + +impl fmt::Debug for RayTracingPipeline { + #[inline] + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + fmt, + "", + self.inner.pipeline + ) + } +} + +impl RayTracingPipeline { + /// Returns the `Device` this ray tracing pipeline was created with. + #[inline] + pub fn device(&self) -> &Arc { + &self.inner.device + } + + /// Returns the pipeline layout used in this ray tracing pipeline. + #[inline] + pub fn layout(&self) -> &L { + &self.layout + } + + /// Returns the if the pipeline is using `nv_ray_tracing` + #[inline] + pub fn use_nv_extension(&self) -> bool { + self.nv_extension.clone() + } +} + +/// Trait implemented on all ray tracing pipelines. +pub unsafe trait RayTracingPipelineAbstract: PipelineLayoutAbstract { + /// Returns an opaque object that represents the inside of the ray tracing pipeline. + fn inner(&self) -> RayTracingPipelineSys; +} + +unsafe impl RayTracingPipelineAbstract for RayTracingPipeline +where + L: PipelineLayoutAbstract, +{ + #[inline] + fn inner(&self) -> RayTracingPipelineSys { + RayTracingPipelineSys(self.inner.pipeline, PhantomData) + } +} + +unsafe impl RayTracingPipelineAbstract for T +where + T: SafeDeref, + T::Target: RayTracingPipelineAbstract, +{ + #[inline] + fn inner(&self) -> RayTracingPipelineSys { + (**self).inner() + } +} + +/// Opaque object that represents the inside of the ray tracing pipeline. +#[derive(Debug, Copy, Clone)] +pub struct RayTracingPipelineSys<'a>(vk::Pipeline, PhantomData<&'a ()>); + +unsafe impl<'a> VulkanObject for RayTracingPipelineSys<'a> { + type Object = vk::Pipeline; + + const TYPE: vk::ObjectType = vk::OBJECT_TYPE_PIPELINE; + + #[inline] + fn internal_object(&self) -> vk::Pipeline { + self.0 + } +} + +unsafe impl PipelineLayoutAbstract for RayTracingPipeline +where + L: PipelineLayoutAbstract, +{ + #[inline] + fn sys(&self) -> PipelineLayoutSys { + self.layout.sys() + } + + #[inline] + fn descriptor_set_layout(&self, index: usize) -> Option<&Arc> { + self.layout.descriptor_set_layout(index) + } +} + +unsafe impl PipelineLayoutDesc for RayTracingPipeline +where + L: PipelineLayoutDesc, +{ + #[inline] + fn num_sets(&self) -> usize { + self.layout.num_sets() + } + + #[inline] + fn num_bindings_in_set(&self, set: usize) -> Option { + self.layout.num_bindings_in_set(set) + } + + #[inline] + fn descriptor(&self, set: usize, binding: usize) -> Option { + self.layout.descriptor(set, binding) + } + + #[inline] + fn num_push_constants_ranges(&self) -> usize { + self.layout.num_push_constants_ranges() + } + + #[inline] + fn push_constants_range(&self, num: usize) -> Option { + self.layout.push_constants_range(num) + } +} + +unsafe impl DeviceOwned for RayTracingPipeline { + #[inline] + fn device(&self) -> &Arc { + &self.inner.device + } +} diff --git a/vulkano/src/pipeline/shader.rs b/vulkano/src/pipeline/shader.rs index 3e6a81e94a..b899dd4666 100644 --- a/vulkano/src/pipeline/shader.rs +++ b/vulkano/src/pipeline/shader.rs @@ -162,6 +162,30 @@ impl ShaderModule { marker: PhantomData, } } + + /// Gets access to an entry point contained in this module. + /// + /// This is purely a *logical* operation. It returns a struct that *represents* the entry + /// point but doesn't actually do anything. + /// + /// # Safety + /// + /// - The user must check that the entry point exists in the module, as this is not checked + /// by Vulkan. + /// - The layout must correctly describe the layout used by this stage. + /// + #[inline] + pub unsafe fn ray_tracing_entry_point<'a, S, L>(&'a self, name: &'a CStr, layout: L, + ty: RayTracingShaderType) + -> RayTracingEntryPoint<'a, S, L> { + RayTracingEntryPoint { + module: self, + name: name, + layout: layout, + ty: ty, + marker: PhantomData, + } + } } unsafe impl VulkanObject for ShaderModule { @@ -306,6 +330,21 @@ impl GeometryShaderExecutionMode { } } +pub unsafe trait RayTracingEntryPointAbstract: EntryPointAbstract { + /// Returns the type of shader. + fn ty(&self) -> RayTracingShaderType; +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum RayTracingShaderType { + Raygen, + AnyHit, + ClosestHit, + Miss, + Intersection, + Callable, +} + pub unsafe trait EntryPointAbstract { type PipelineLayout: PipelineLayoutDesc; type SpecializationConstants: SpecializationConstants; @@ -354,6 +393,52 @@ unsafe impl<'a, S, L> EntryPointAbstract for ComputeEntryPoint<'a, S, L> } } +/// Represents the entry point of a ray tracing shader in a shader module. +/// +/// Can be obtained by calling `ray_tracing_shader_entry_point()` on the shader module. +#[derive(Debug, Copy, Clone)] +pub struct RayTracingEntryPoint<'a, S, L> { + module: &'a ShaderModule, + name: &'a CStr, + layout: L, + ty: RayTracingShaderType, + marker: PhantomData, +} + +unsafe impl<'a, S, L> EntryPointAbstract for RayTracingEntryPoint<'a, S, L> + where L: PipelineLayoutDesc, + S: SpecializationConstants +{ + type PipelineLayout = L; + type SpecializationConstants = S; + + #[inline] + fn module(&self) -> &ShaderModule { + self.module + } + + #[inline] + fn name(&self) -> &CStr { + self.name + } + + #[inline] + fn layout(&self) -> &L { + &self.layout + } +} + +unsafe impl<'a, S, L> RayTracingEntryPointAbstract for RayTracingEntryPoint<'a, S, L> + where L: PipelineLayoutDesc, + S: SpecializationConstants +{ + #[inline] + fn ty(&self) -> RayTracingShaderType { + self.ty + } +} + + /// A dummy that implements `GraphicsEntryPointAbstract` and `EntryPointAbstract`. /// /// When a function has a signature like: `fn foo(shader: Option)`, you @@ -405,6 +490,13 @@ unsafe impl GraphicsEntryPointAbstract for EmptyEntryPointDummy { } } +unsafe impl RayTracingEntryPointAbstract for EmptyEntryPointDummy { + #[inline] + fn ty(&self) -> RayTracingShaderType { + unreachable!() + } +} + /// Types that contain the definition of an interface between two shader stages, or between /// the outside and a shader stage. /// From d768ba7ad45b0b952fbfe2cd3ca65568e940824b Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Tue, 14 Apr 2020 21:32:15 +0200 Subject: [PATCH 09/15] command_buffer: Add trace commands --- examples/src/bin/nv-ray-tracing.rs | 20 +- vulkano/src/command_buffer/auto.rs | 147 ++++++++++- vulkano/src/command_buffer/mod.rs | 8 + vulkano/src/command_buffer/state_cacher.rs | 27 +- vulkano/src/command_buffer/synced/commands.rs | 236 ++++++++++++++++- vulkano/src/command_buffer/sys.rs | 243 +++++++++++++++++- .../src/pipeline/ray_tracing_pipeline/mod.rs | 11 + 7 files changed, 682 insertions(+), 10 deletions(-) diff --git a/examples/src/bin/nv-ray-tracing.rs b/examples/src/bin/nv-ray-tracing.rs index b1150d4f6b..215a5556c8 100644 --- a/examples/src/bin/nv-ray-tracing.rs +++ b/examples/src/bin/nv-ray-tracing.rs @@ -203,7 +203,6 @@ void main() { .wait(None) .unwrap(); - let mut recreate_swapchain = false; let mut previous_frame_end = Some(Box::new(sync::now(device.clone())) as Box); @@ -263,10 +262,29 @@ void main() { recreate_swapchain = true; } + let command_buffer = + AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()) + .unwrap() + .trace_rays( + pipeline.clone(), + raygen_shader_binding_table.clone(), + miss_shader_binding_table.clone(), + hit_shader_binding_table.clone(), + callable_shader_binding_table.clone(), + [swapchain.dimensions()[0], swapchain.dimensions()[1], 1], + sets[image_num].clone(), + (), + ) + .unwrap() + .build() + .unwrap(); + let future = previous_frame_end .take() .unwrap() .join(acquire_future) + .then_execute(queue.clone(), command_buffer) + .unwrap() .then_swapchain_present(queue.clone(), swapchain.clone(), image_num) .then_signal_fence_and_flush(); diff --git a/vulkano/src/command_buffer/auto.rs b/vulkano/src/command_buffer/auto.rs index 8af8cf3275..1d5a4cc1d5 100644 --- a/vulkano/src/command_buffer/auto.rs +++ b/vulkano/src/command_buffer/auto.rs @@ -19,7 +19,7 @@ use std::sync::atomic::Ordering; use OomError; use buffer::BufferAccess; use buffer::TypedBufferAccess; -use command_buffer::CommandBuffer; +use command_buffer::{CommandBuffer, TraceRaysIndirectCommandKHR}; use command_buffer::CommandBufferExecError; use command_buffer::DrawIndirectCommand; use command_buffer::DrawIndexedIndirectCommand; @@ -65,7 +65,7 @@ use framebuffer::SubpassContents; use image::ImageAccess; use image::ImageLayout; use instance::QueueFamily; -use pipeline::{ComputePipelineAbstract, PipelineType}; +use pipeline::{ComputePipelineAbstract, PipelineType, RayTracingPipelineAbstract}; use pipeline::GraphicsPipelineAbstract; use pipeline::input_assembly::Index; use pipeline::vertex::VertexSource; @@ -1207,6 +1207,135 @@ impl

AutoCommandBufferBuilder

{ } } + /// Performs a ray tracing dispatch using the binding tables. + /// + /// To use only some data in a buffer, wrap it in a `vulkano::buffer::BufferSlice`. + #[inline] + pub fn trace_rays( + mut self, + pipeline: Rp, + raygen_shader_binding_table: Rb, + miss_shader_binding_table: Mb, + hit_shader_binding_table: Hb, + callable_shader_binding_table: Cb, + dimensions: [u32; 3], + sets: S, + constants: Pc, + ) -> Result + where + Rp: RayTracingPipelineAbstract + Send + Sync + 'static + Clone, + Rb: BufferAccess + Send + Sync + 'static, + Mb: BufferAccess + Send + Sync + 'static, + Hb: BufferAccess + Send + Sync + 'static, + Cb: BufferAccess + Send + Sync + 'static, + S: DescriptorSetsCollection, + { + unsafe { + // TODO: check binding table validity + // TODO: Check if the pipeline is using `nv_ray_tracing` + + check_push_constants_validity(&pipeline, &constants)?; + check_descriptor_sets_validity(&pipeline, &sets)?; + + if let StateCacherOutcome::NeedChange = + self.state_cacher.bind_ray_tracing_pipeline(&pipeline) + { + self.inner.bind_pipeline_ray_tracing(pipeline.clone()); + } + + push_constants(&mut self.inner, pipeline.clone(), constants); + descriptor_sets( + &mut self.inner, + &mut self.state_cacher, + PipelineType::RayTracing, + pipeline.clone(), + sets, + )?; + + if pipeline.use_nv_extension() { + debug_assert!(self.device().loaded_extensions().nv_ray_tracing); + } else { + debug_assert!(self.device().loaded_extensions().khr_ray_tracing); + } + + self.inner.trace_rays( + pipeline.use_nv_extension(), + raygen_shader_binding_table, + miss_shader_binding_table, + hit_shader_binding_table, + callable_shader_binding_table, + dimensions, + )?; + Ok(self) + } + } + + /// Performs a ray tracing dispatch from the `vulkano::command_buffer::TraceRaysIndirectKhrCommand` + /// struct in `indirect_buffer` using the binding tables. + /// + /// This will use the `khr_ray_tracing` device extension. + /// To use only some data in a buffer, wrap it in a `vulkano::buffer::BufferSlice`. + #[inline] + pub fn trace_rays_indirect( + mut self, + pipeline: Rp, + raygen_shader_binding_table: Rb, + miss_shader_binding_table: Mb, + hit_shader_binding_table: Hb, + callable_shader_binding_table: Cb, + indirect_buffer: Ib, + sets: S, + constants: Pc, + ) -> Result + where + Rp: RayTracingPipelineAbstract + Send + Sync + 'static + Clone, + Rb: BufferAccess + Send + Sync + 'static, + Mb: BufferAccess + Send + Sync + 'static, + Hb: BufferAccess + Send + Sync + 'static, + Cb: BufferAccess + Send + Sync + 'static, + S: DescriptorSetsCollection, + Ib: BufferAccess + + TypedBufferAccess + + Send + + Sync + + 'static, + { + unsafe { + // TODO: check binding table validity + // TODO: Check if the pipeline is using `nv_ray_tracing` + + check_push_constants_validity(&pipeline, &constants)?; + check_descriptor_sets_validity(&pipeline, &sets)?; + + if let StateCacherOutcome::NeedChange = + self.state_cacher.bind_ray_tracing_pipeline(&pipeline) + { + self.inner.bind_pipeline_ray_tracing(pipeline.clone()); + } + + push_constants(&mut self.inner, pipeline.clone(), constants); + descriptor_sets( + &mut self.inner, + &mut self.state_cacher, + PipelineType::RayTracing, + pipeline.clone(), + sets, + )?; + + debug_assert!(!pipeline.use_nv_extension()); + debug_assert!(self.device().loaded_extensions().khr_ray_tracing); + + self.inner.trace_rays_indirect_khr( + raygen_shader_binding_table, + miss_shader_binding_table, + hit_shader_binding_table, + callable_shader_binding_table, + indirect_buffer, + )?; + Ok(self) + } + } + /// Adds a command that ends the current render pass. /// /// This must be called after you went through all the subpasses and before you can build @@ -1754,6 +1883,20 @@ err_gen!(UpdateBufferError { CheckUpdateBufferError, }); +err_gen!(TraceRaysError { + AutoCommandBufferBuilderContextError, + CheckPushConstantsValidityError, + CheckDescriptorSetsValidityError, + SyncCommandBufferBuilderError, + }); + +err_gen!(TraceRaysIndirectError { + AutoCommandBufferBuilderContextError, + CheckPushConstantsValidityError, + CheckDescriptorSetsValidityError, + SyncCommandBufferBuilderError, + }); + #[derive(Debug, Copy, Clone)] pub enum AutoCommandBufferBuilderContextError { /// Operation forbidden in a secondary command buffer. diff --git a/vulkano/src/command_buffer/mod.rs b/vulkano/src/command_buffer/mod.rs index f308758bb6..c863015952 100644 --- a/vulkano/src/command_buffer/mod.rs +++ b/vulkano/src/command_buffer/mod.rs @@ -138,6 +138,14 @@ pub struct DispatchIndirectCommand { pub z: u32, } +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct TraceRaysIndirectCommandKHR { + pub width: u32, + pub height: u32, + pub depth: u32, +} + /// The dynamic state to use for a draw command. // TODO: probably not the right location #[derive(Debug, Clone)] diff --git a/vulkano/src/command_buffer/state_cacher.rs b/vulkano/src/command_buffer/state_cacher.rs index a4eac11d2a..8452f92b7b 100644 --- a/vulkano/src/command_buffer/state_cacher.rs +++ b/vulkano/src/command_buffer/state_cacher.rs @@ -7,15 +7,17 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use VulkanObject; use buffer::BufferAccess; use command_buffer::DynamicState; use descriptor::DescriptorSet; -use pipeline::{ComputePipelineAbstract, GraphicsPipelineAbstract, PipelineType}; use pipeline::input_assembly::IndexType; +use pipeline::{ + ComputePipelineAbstract, GraphicsPipelineAbstract, PipelineType, RayTracingPipelineAbstract, +}; use smallvec::SmallVec; use std::ops::Range; use vk; +use VulkanObject; /// Keep track of the state of a command buffer builder, so that you don't need to bind objects /// that were already bound. @@ -85,8 +87,10 @@ impl StateCacher { self.dynamic_state = DynamicState::none(); self.compute_pipeline = 0; self.graphics_pipeline = 0; + self.ray_tracing_pipeline = 0; self.compute_descriptor_sets = SmallVec::new(); self.graphics_descriptor_sets = SmallVec::new(); + self.ray_tracing_descriptor_sets = SmallVec::new(); self.vertex_buffers = SmallVec::new(); self.index_buffer = None; } @@ -190,6 +194,25 @@ impl StateCacher { } } + /// Checks whether we need to bind a ray tracing. Returns `StateCacherOutcome::AlreadyOk` + /// if the pipeline was already bound earlier, and `StateCacherOutcome::NeedChange` if you need + /// to actually bind the pipeline. + /// + /// This function also updates the state cacher. The state cacher assumes that the state + /// changes are going to be performed after this function returns. + pub fn bind_ray_tracing_pipeline

(&mut self, pipeline: &P) -> StateCacherOutcome + where + P: RayTracingPipelineAbstract, + { + let inner = RayTracingPipelineAbstract::inner(pipeline).internal_object(); + if inner == self.ray_tracing_pipeline { + StateCacherOutcome::AlreadyOk + } else { + self.ray_tracing_pipeline = inner; + StateCacherOutcome::NeedChange + } + } + /// Starts the process of comparing a list of vertex buffers to the vertex buffers currently /// in cache. /// diff --git a/vulkano/src/command_buffer/synced/commands.rs b/vulkano/src/command_buffer/synced/commands.rs index 71103b6dfc..03a55bad90 100644 --- a/vulkano/src/command_buffer/synced/commands.rs +++ b/vulkano/src/command_buffer/synced/commands.rs @@ -37,13 +37,14 @@ use framebuffer::FramebufferAbstract; use framebuffer::SubpassContents; use image::ImageAccess; use image::ImageLayout; -use pipeline::{ComputePipelineAbstract, PipelineType}; -use pipeline::GraphicsPipelineAbstract; +use pipeline::depth_stencil::DynamicStencilValue; +use pipeline::depth_stencil::StencilFaceFlags; use pipeline::input_assembly::IndexType; use pipeline::viewport::Scissor; use pipeline::viewport::Viewport; -use pipeline::depth_stencil::DynamicStencilValue; -use pipeline::depth_stencil::StencilFaceFlags; +use pipeline::{ + ComputePipelineAbstract, GraphicsPipelineAbstract, PipelineType, RayTracingPipelineAbstract, +}; use sampler::Filter; use sync::AccessFlagBits; use sync::Event; @@ -281,6 +282,45 @@ impl

SyncCommandBufferBuilder

{ self.append_command(Cmd { pipeline }); } + /// Calls `vkCmdBindPipeline` on the builder with a ray tracing pipeline. + #[inline] + pub unsafe fn bind_pipeline_ray_tracing(&mut self, pipeline: Rp) + where + Rp: RayTracingPipelineAbstract + Send + Sync + 'static, + { + struct Cmd { + pipeline: Rp, + } + + impl Command

for Cmd + where + Rp: RayTracingPipelineAbstract + Send + Sync + 'static, + { + fn name(&self) -> &'static str { + "vkCmdBindPipeline" + } + + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { + out.bind_pipeline_ray_tracing(&self.pipeline); + } + + fn into_final_command(self: Box) -> Box { + struct Fin(Rp); + impl FinalCommand for Fin + where + Rp: Send + Sync + 'static, + { + fn name(&self) -> &'static str { + "vkCmdBindPipeline" + } + } + Box::new(Fin(self.pipeline)) + } + } + + self.append_command(Cmd { pipeline }); + } + /// Starts the process of binding descriptor sets. Returns an intermediate struct which can be /// used to add the sets. #[inline] @@ -1907,6 +1947,194 @@ impl

SyncCommandBufferBuilder

{ ImageLayout::Undefined) .unwrap(); } + + /// Calls `vkCmdTraceRaysKHR` / `vkCmdTraceRaysNV` on the builder. + // TODO: `miss_shader_binding_table`, `hit_shader_binding_table`, + // `callable_shader_binding_table` should be optional + #[inline] + pub unsafe fn trace_rays( + &mut self, + use_nv_extension: bool, + raygen_shader_binding_table: Rb, + miss_shader_binding_table: Mb, + hit_shader_binding_table: Hb, + callable_shader_binding_table: Cb, + dimensions: [u32; 3], + ) -> Result<(), SyncCommandBufferBuilderError> + where + Rb: BufferAccess + Send + Sync + 'static, + Mb: BufferAccess + Send + Sync + 'static, + Hb: BufferAccess + Send + Sync + 'static, + Cb: BufferAccess + Send + Sync + 'static, + { + struct Cmd { + use_nv_extension: bool, + raygen_shader_binding_table: Rb, + miss_shader_binding_table: Mb, + hit_shader_binding_table: Hb, + callable_shader_binding_table: Cb, + dimensions: [u32; 3], + } + + impl Command

for Cmd + where + Rb: BufferAccess + Send + Sync + 'static, + Mb: BufferAccess + Send + Sync + 'static, + Hb: BufferAccess + Send + Sync + 'static, + Cb: BufferAccess + Send + Sync + 'static, + { + fn name(&self) -> &'static str + { + if self.use_nv_extension { + "vkCmdTraceRaysNV" + } else { + "vkCmdTraceRaysKHR" + } + } + + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { + if self.use_nv_extension { + out.trace_rays_nv( + &self.raygen_shader_binding_table, + &self.miss_shader_binding_table, + &self.hit_shader_binding_table, + &self.callable_shader_binding_table, + self.dimensions, + ); + } else { + out.trace_rays_khr( + &self.raygen_shader_binding_table, + &self.miss_shader_binding_table, + &self.hit_shader_binding_table, + &self.callable_shader_binding_table, + self.dimensions, + ); + } + } + + fn into_final_command(self: Box) -> Box { + if self.use_nv_extension { + Box::new("vkCmdTraceRaysNV") + } else { + Box::new("vkCmdTraceRaysKHR") + } + } + } + + self.append_command(Cmd { + use_nv_extension, + raygen_shader_binding_table, + miss_shader_binding_table, + hit_shader_binding_table, + callable_shader_binding_table, + dimensions, + }); + Ok(()) + } + + /// Calls `vkCmdTraceRaysIndirectKHR` on the builder. + #[inline] + pub unsafe fn trace_rays_indirect_khr( + &mut self, + raygen_shader_binding_table: Rb, + miss_shader_binding_table: Mb, + hit_shader_binding_table: Hb, + callable_shader_binding_table: Cb, + buffer: B, + ) -> Result<(), SyncCommandBufferBuilderError> + where + Rb: BufferAccess + Send + Sync + 'static, + Mb: BufferAccess + Send + Sync + 'static, + Hb: BufferAccess + Send + Sync + 'static, + Cb: BufferAccess + Send + Sync + 'static, + B: BufferAccess + Send + Sync + 'static, + { + struct Cmd { + raygen_shader_binding_table: Rb, + miss_shader_binding_table: Mb, + hit_shader_binding_table: Hb, + callable_shader_binding_table: Cb, + buffer: B, + } + + impl Command

for Cmd + where + Rb: BufferAccess + Send + Sync + 'static, + Mb: BufferAccess + Send + Sync + 'static, + Hb: BufferAccess + Send + Sync + 'static, + Cb: BufferAccess + Send + Sync + 'static, + B: BufferAccess + Send + Sync + 'static, + { + fn name(&self) -> &'static str { + "vkCmdTraceRaysIndirectKHR" + } + + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { + out.trace_rays_indirect_khr( + &self.raygen_shader_binding_table, + &self.miss_shader_binding_table, + &self.hit_shader_binding_table, + &self.callable_shader_binding_table, + &self.buffer, + ); + } + + fn into_final_command(self: Box) -> Box { + struct Fin(B); + impl FinalCommand for Fin + where + B: BufferAccess + Send + Sync + 'static, + { + fn name(&self) -> &'static str { + "vkCmdTraceRaysIndirectKHR" + } + fn buffer(&self, num: usize) -> &dyn BufferAccess { + assert_eq!(num, 0); + &self.0 + } + fn buffer_name(&self, num: usize) -> Cow<'static, str> { + assert_eq!(num, 0); + "indirect buffer".into() + } + } + Box::new(Fin(self.buffer)) + } + + fn buffer(&self, num: usize) -> &dyn BufferAccess { + assert_eq!(num, 0); + &self.buffer + } + + fn buffer_name(&self, num: usize) -> Cow<'static, str> { + assert_eq!(num, 0); + "indirect buffer".into() + } + } + + self.append_command(Cmd { + raygen_shader_binding_table, + miss_shader_binding_table, + hit_shader_binding_table, + callable_shader_binding_table, + buffer, + }); + self.prev_cmd_resource( + KeyTy::Buffer, + 0, + false, + PipelineStages { + draw_indirect: true, + ..PipelineStages::none() + }, // TODO: is draw_indirect correct? + AccessFlagBits { + indirect_command_read: true, + ..AccessFlagBits::none() + }, + ImageLayout::Undefined, + ImageLayout::Undefined, + )?; + Ok(()) + } } pub struct SyncCommandBufferBuilderBindDescriptorSets<'b, P: 'b> { diff --git a/vulkano/src/command_buffer/sys.rs b/vulkano/src/command_buffer/sys.rs index dc8386cc58..6ff66c8631 100644 --- a/vulkano/src/command_buffer/sys.rs +++ b/vulkano/src/command_buffer/sys.rs @@ -41,7 +41,7 @@ use framebuffer::SubpassContents; use image::ImageAccess; use image::ImageLayout; use instance::QueueFamily; -use pipeline::{ComputePipelineAbstract, PipelineType}; +use pipeline::{ComputePipelineAbstract, RayTracingPipelineAbstract, PipelineType}; use pipeline::GraphicsPipelineAbstract; use pipeline::input_assembly::IndexType; use pipeline::viewport::Scissor; @@ -531,6 +531,17 @@ impl

UnsafeCommandBufferBuilder

{ vk.CmdBindPipeline(cmd, vk::PIPELINE_BIND_POINT_GRAPHICS, inner); } + /// Calls `vkCmdBindPipeline` on the builder with a ray tracing pipeline. + #[inline] + pub unsafe fn bind_pipeline_ray_tracing(&mut self, pipeline: &Rp) + where Rp: ?Sized + RayTracingPipelineAbstract + { + let vk = self.device().pointers(); + let cmd = self.internal_object(); + let inner = RayTracingPipelineAbstract::inner(pipeline).internal_object(); + vk.CmdBindPipeline(cmd, vk::PIPELINE_BIND_POINT_RAY_TRACING_KHR, inner); + } + /// Calls `vkCmdBindVertexBuffers` on the builder. /// /// Does nothing if the list of buffers is empty, as it would be a no-op and isn't a valid @@ -1519,6 +1530,236 @@ impl

UnsafeCommandBufferBuilder

{ }; vk.CmdInsertDebugUtilsLabelEXT(cmd, &info); } + + /// Calls `vkCmdTraceRaysNV` on the builder. + #[inline] + pub unsafe fn trace_rays_nv( + &mut self, + raygen_shader_binding_table: &R, + miss_shader_binding_table: &M, + hit_shader_binding_table: &H, + callable_shader_binding_table: &C, + dimensions: [u32; 3], + ) where + R: ?Sized + BufferAccess, + M: ?Sized + BufferAccess, + H: ?Sized + BufferAccess, + C: ?Sized + BufferAccess, + { + let vk = self.device().pointers(); + let cmd = self.internal_object(); + + let inner_raygen = raygen_shader_binding_table.inner(); + debug_assert!(inner_raygen.offset < inner_raygen.buffer.size()); + debug_assert!( + inner_raygen.offset + raygen_shader_binding_table.size() <= inner_raygen.buffer.size() + ); + debug_assert!(inner_raygen.buffer.usage_ray_tracing()); + + let inner_miss = miss_shader_binding_table.inner(); + debug_assert!(inner_miss.offset < inner_miss.buffer.size()); + debug_assert!( + inner_miss.offset + miss_shader_binding_table.size() <= inner_miss.buffer.size() + ); + debug_assert!(inner_miss.buffer.usage_ray_tracing()); + + let inner_hit = hit_shader_binding_table.inner(); + debug_assert!(inner_hit.offset < inner_hit.buffer.size()); + debug_assert!( + inner_hit.offset + hit_shader_binding_table.size() <= inner_hit.buffer.size() + ); + debug_assert!(inner_hit.buffer.usage_ray_tracing()); + + let inner_callable = callable_shader_binding_table.inner(); + debug_assert!(inner_callable.offset < inner_callable.buffer.size()); + debug_assert!( + inner_callable.offset + callable_shader_binding_table.size() + <= inner_callable.buffer.size() + ); + debug_assert!(inner_callable.buffer.usage_ray_tracing()); + + vk.CmdTraceRaysNV( + cmd, + inner_raygen.buffer.internal_object(), + inner_raygen.offset as vk::DeviceSize, + inner_miss.buffer.internal_object(), + inner_miss.offset as vk::DeviceSize, + 0, // TODO: Support strided buffers + inner_hit.buffer.internal_object(), + inner_hit.offset as vk::DeviceSize, + 0, // TODO: Support strided buffers + inner_callable.buffer.internal_object(), + inner_callable.offset as vk::DeviceSize, + 0, // TODO: Support strided buffers + dimensions[0], + dimensions[1], + dimensions[2], + ); + } + + /// Calls `vkCmdTraceRaysKHR` on the builder. + #[inline] + pub unsafe fn trace_rays_khr( + &mut self, + raygen_shader_binding_table: &R, + miss_shader_binding_table: &M, + hit_shader_binding_table: &H, + callable_shader_binding_table: &C, + dimensions: [u32; 3], + ) where + R: ?Sized + BufferAccess, + M: ?Sized + BufferAccess, + H: ?Sized + BufferAccess, + C: ?Sized + BufferAccess, + { + let vk = self.device().pointers(); + let cmd = self.internal_object(); + + let inner_raygen = raygen_shader_binding_table.inner(); + debug_assert!(inner_raygen.offset < inner_raygen.buffer.size()); + debug_assert!( + inner_raygen.offset + raygen_shader_binding_table.size() <= inner_raygen.buffer.size() + ); + debug_assert!(inner_raygen.buffer.usage_ray_tracing()); + let region_raygen = vk::StridedBufferRegionKHR { + buffer: inner_raygen.buffer.internal_object(), + offset: inner_raygen.offset as vk::DeviceSize, + stride: 0, // TODO: Support strided buffers + size: raygen_shader_binding_table.size() as vk::DeviceSize, + }; + + let inner_miss = miss_shader_binding_table.inner(); + debug_assert!(inner_miss.offset < inner_miss.buffer.size()); + debug_assert!( + inner_miss.offset + miss_shader_binding_table.size() <= inner_miss.buffer.size() + ); + debug_assert!(inner_miss.buffer.usage_ray_tracing()); + let region_miss = vk::StridedBufferRegionKHR { + buffer: inner_miss.buffer.internal_object(), + offset: inner_miss.offset as vk::DeviceSize, + stride: 0, // TODO: Support strided buffers + size: miss_shader_binding_table.size() as vk::DeviceSize, + }; + + let inner_hit = hit_shader_binding_table.inner(); + debug_assert!(inner_hit.offset < inner_hit.buffer.size()); + debug_assert!( + inner_hit.offset + hit_shader_binding_table.size() <= inner_hit.buffer.size() + ); + debug_assert!(inner_hit.buffer.usage_ray_tracing()); + let region_hit = vk::StridedBufferRegionKHR { + buffer: inner_hit.buffer.internal_object(), + offset: inner_hit.offset as vk::DeviceSize, + stride: 0, // TODO: Support strided buffers + size: hit_shader_binding_table.size() as vk::DeviceSize, + }; + + let inner_callable = callable_shader_binding_table.inner(); + debug_assert!(inner_callable.offset < inner_callable.buffer.size()); + debug_assert!( + inner_callable.offset + callable_shader_binding_table.size() + <= inner_callable.buffer.size() + ); + debug_assert!(inner_callable.buffer.usage_ray_tracing()); + let region_callable = vk::StridedBufferRegionKHR { + buffer: inner_callable.buffer.internal_object(), + offset: inner_callable.offset as vk::DeviceSize, + stride: 0, // TODO: Support strided buffers + size: callable_shader_binding_table.size() as vk::DeviceSize, + }; + + vk.CmdTraceRaysKHR( + cmd, + ®ion_raygen, + ®ion_miss, + ®ion_hit, + ®ion_callable, + dimensions[0], + dimensions[1], + dimensions[2], + ); + } + + /// Calls `vkCmdTraceRaysIndirectKHR` on the builder. + #[inline] + pub unsafe fn trace_rays_indirect_khr( + &mut self, raygen_shader_binding_table: &R, miss_shader_binding_table: &M, + hit_shader_binding_table: &H, callable_shader_binding_table: &C, buffer: &B, + ) where + R: ?Sized + BufferAccess, + M: ?Sized + BufferAccess, + H: ?Sized + BufferAccess, + C: ?Sized + BufferAccess, + B: ?Sized + BufferAccess, + { + let vk = self.device().pointers(); + let cmd = self.internal_object(); + + let inner_raygen = raygen_shader_binding_table.inner(); + debug_assert!(inner_raygen.offset < inner_raygen.buffer.size()); + debug_assert!( + inner_raygen.offset + raygen_shader_binding_table.size() < inner_raygen.buffer.size() + ); + debug_assert!(inner_raygen.buffer.usage_ray_tracing()); + let region_raygen = vk::StridedBufferRegionKHR { + buffer: inner_raygen.buffer.internal_object(), + offset: inner_raygen.offset as vk::DeviceSize, + stride: 0, // TODO: Support strided buffers + size: raygen_shader_binding_table.size() as vk::DeviceSize, + }; + + let inner_miss = miss_shader_binding_table.inner(); + debug_assert!(inner_miss.offset < inner_miss.buffer.size()); + debug_assert!( + inner_miss.offset + miss_shader_binding_table.size() < inner_miss.buffer.size() + ); + debug_assert!(inner_miss.buffer.usage_ray_tracing()); + let region_miss = vk::StridedBufferRegionKHR { + buffer: inner_miss.buffer.internal_object(), + offset: inner_miss.offset as vk::DeviceSize, + stride: 0, // TODO: Support strided buffers + size: miss_shader_binding_table.size() as vk::DeviceSize, + }; + + let inner_hit = hit_shader_binding_table.inner(); + debug_assert!(inner_hit.offset < inner_hit.buffer.size()); + debug_assert!(inner_hit.offset + hit_shader_binding_table.size() < inner_hit.buffer.size()); + debug_assert!(inner_hit.buffer.usage_ray_tracing()); + let region_hit = vk::StridedBufferRegionKHR { + buffer: inner_hit.buffer.internal_object(), + offset: inner_hit.offset as vk::DeviceSize, + stride: 0, // TODO: Support strided buffers + size: hit_shader_binding_table.size() as vk::DeviceSize, + }; + + let inner_callable = callable_shader_binding_table.inner(); + debug_assert!(inner_callable.offset < inner_callable.buffer.size()); + debug_assert!( + inner_callable.offset + callable_shader_binding_table.size() + < inner_callable.buffer.size() + ); + debug_assert!(inner_callable.buffer.usage_ray_tracing()); + let region_callable = vk::StridedBufferRegionKHR { + buffer: inner_callable.buffer.internal_object(), + offset: inner_callable.offset as vk::DeviceSize, + stride: 0, // TODO: Support strided buffers + size: callable_shader_binding_table.size() as vk::DeviceSize, + }; + + let inner = buffer.inner(); + debug_assert!(inner.offset < inner.buffer.size()); + debug_assert!(inner.buffer.usage_indirect_buffer()); + + vk.CmdTraceRaysIndirectKHR( + cmd, + ®ion_raygen, + ®ion_miss, + ®ion_hit, + ®ion_callable, + inner.buffer.internal_object(), + inner.offset as vk::DeviceSize, + ); + } } unsafe impl

DeviceOwned for UnsafeCommandBufferBuilder

{ diff --git a/vulkano/src/pipeline/ray_tracing_pipeline/mod.rs b/vulkano/src/pipeline/ray_tracing_pipeline/mod.rs index 0ff483722e..611c20e7b7 100644 --- a/vulkano/src/pipeline/ray_tracing_pipeline/mod.rs +++ b/vulkano/src/pipeline/ray_tracing_pipeline/mod.rs @@ -167,6 +167,7 @@ impl RayTracingPipeline { pub unsafe trait RayTracingPipelineAbstract: PipelineLayoutAbstract { /// Returns an opaque object that represents the inside of the ray tracing pipeline. fn inner(&self) -> RayTracingPipelineSys; + fn use_nv_extension(&self) -> bool; } unsafe impl RayTracingPipelineAbstract for RayTracingPipeline @@ -177,6 +178,11 @@ where fn inner(&self) -> RayTracingPipelineSys { RayTracingPipelineSys(self.inner.pipeline, PhantomData) } + + #[inline] + fn use_nv_extension(&self) -> bool { + self.nv_extension + } } unsafe impl RayTracingPipelineAbstract for T @@ -188,6 +194,11 @@ where fn inner(&self) -> RayTracingPipelineSys { (**self).inner() } + + #[inline] + fn use_nv_extension(&self) -> bool { + (**self).use_nv_extension() + } } /// Opaque object that represents the inside of the ray tracing pipeline. From 8c8789f8e066d79be8a8ab7f4a4c8a02fb7ebe31 Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Fri, 24 Apr 2020 18:21:41 +0200 Subject: [PATCH 10/15] command_buffer: Add build acceleration structure --- examples/src/bin/nv-ray-tracing.rs | 45 + vulkano/src/acceleration_structure.rs | 1124 +++++++++++++++++ vulkano/src/command_buffer/auto.rs | 18 + vulkano/src/command_buffer/synced/commands.rs | 184 +++ vulkano/src/command_buffer/sys.rs | 201 +++ vulkano/src/lib.rs | 1 + 6 files changed, 1573 insertions(+) create mode 100644 vulkano/src/acceleration_structure.rs diff --git a/examples/src/bin/nv-ray-tracing.rs b/examples/src/bin/nv-ray-tracing.rs index 215a5556c8..0dafcd237f 100644 --- a/examples/src/bin/nv-ray-tracing.rs +++ b/examples/src/bin/nv-ray-tracing.rs @@ -19,6 +19,7 @@ extern crate vulkano_shaders; extern crate vulkano_win; extern crate winit; +use vulkano::acceleration_structure::{AabbPositions, AccelerationStructure}; use vulkano::buffer::{BufferUsage, ImmutableBuffer}; use vulkano::command_buffer::AutoCommandBufferBuilder; use vulkano::descriptor::descriptor_set::PersistentDescriptorSet; @@ -113,6 +114,37 @@ fn main() { .unwrap() }; + // We now create a buffer that will store the AABBs for custom intersections. + let (aabb_buffer, aabb_buffer_future) = { + ImmutableBuffer::from_iter( + [ + AabbPositions { + min: [-2.0, -0.5, -2.5], + max: [-1.0, 0.5, -1.5], + }, + AabbPositions { + min: [-0.5, -0.5, -2.5], + max: [0.5, 0.5, -1.5], + }, + AabbPositions { + min: [1.0, -0.5, -2.5], + max: [2.0, 0.5, -1.5], + }, + ] + .iter() + .cloned(), + BufferUsage::ray_tracing(), + queue.clone(), + ) + .unwrap() + }; + + aabb_buffer_future + .then_signal_fence_and_flush() + .unwrap() + .wait(None) + .unwrap(); + mod rs { vulkano_shaders::shader! { ty: "ray_generation", @@ -147,6 +179,17 @@ void main() { .unwrap(), ); + // We create an acceleration structure allow traversal of the scene by rays + // There can be any number of acceleration structures grouped under a top + // level structure. + let acceleration_structure = Arc::new( + AccelerationStructure::nv() + .add_aabbs(aabb_buffer.clone()) + .unwrap() + .build(device.clone(), queue.clone()) + .unwrap(), + ); + let layout = pipeline.layout().descriptor_set_layout(0).unwrap(); let mut sets = images .iter() @@ -264,6 +307,8 @@ void main() { let command_buffer = AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()) + .unwrap() + .build_acceleration_structure(acceleration_structure.as_ref()) .unwrap() .trace_rays( pipeline.clone(), diff --git a/vulkano/src/acceleration_structure.rs b/vulkano/src/acceleration_structure.rs new file mode 100644 index 0000000000..746242d17c --- /dev/null +++ b/vulkano/src/acceleration_structure.rs @@ -0,0 +1,1124 @@ +// Copyright (c) 2016 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +use std::error; +use std::fmt; +use std::mem::size_of; +use std::mem::MaybeUninit; +use std::ops; +use std::ptr; + +use buffer::{BufferAccess, BufferUsage, ImmutableBuffer}; +use device::Device; +use device::Queue; +use format::Format; +use memory::pool::{ + AllocFromRequirementsFilter, AllocLayout, MappingRequirement, MemoryPoolAlloc, + PotentialDedicatedAllocation, StdMemoryPoolAlloc, +}; +use memory::{DedicatedAlloc, MemoryPool, MemoryRequirements}; +use pipeline::input_assembly::IndexType; +use smallvec::alloc::sync::Arc; +use std::os::raw::c_void; +use sync::GpuFuture; + +use check_errors; +use vk; +use Error; +use OomError; +use VulkanObject; + +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct AabbPositions { + pub min: [f32; 3], + pub max: [f32; 3], +} + +#[derive(Clone)] +pub struct Level { + pub inner_object: vk::AccelerationStructureKHR, + pub type_: vk::AccelerationStructureTypeKHR, + pub flags: vk::BuildAccelerationStructureFlagsKHR, + pub instance_count: u32, + pub geometries: Vec, +} + +/// Structure used by rays to find geometry in a scene +pub struct AccelerationStructure { + nv_extension: bool, + top_level: Level, + bottom_level: Level, + + // Memory allocated for the acceleration structure. + memory: PotentialDedicatedAllocation, + + instance_buffer: Arc>, + scratch_buffer: Arc>, +} + +impl AccelerationStructure { + /// Creates a new `AccelerationStructure` using the `nv_ray_tracing` extension + #[inline] + pub fn nv() -> AccelerationStructureBuilder { + AccelerationStructureBuilder::nv() + } + + /// Creates a new `AccelerationStructure` using the `khr_ray_tracing` extension + #[inline] + pub fn khr() -> AccelerationStructureBuilder { + AccelerationStructureBuilder::khr() + } + + #[inline] + pub fn nv_extension(&self) -> bool { + self.nv_extension + } + + #[inline] + pub fn top_level(&self) -> Level { + self.top_level.clone() + } + + #[inline] + pub fn bottom_level(&self) -> Level { + self.bottom_level.clone() + } + + #[inline] + pub fn instance_buffer(&self) -> &Arc> { + &self.instance_buffer + } + + #[inline] + pub fn scratch_buffer(&self) -> &Arc> { + &self.scratch_buffer + } +} + +/// Prototype of a `AccelerationStructure`. +/// +/// See the docs of `AccelerationStructure` for an example. +pub struct AccelerationStructureBuilder { + nv_extension: bool, + // TODO: Associate `BuildAccelerationStructureFlags` + aabbs: Vec>, +} + +impl AccelerationStructureBuilder { + #[inline] + pub fn nv() -> Self { + AccelerationStructureBuilder { + nv_extension: true, + aabbs: vec![], + } + } + + #[inline] + pub fn khr() -> Self { + AccelerationStructureBuilder { + nv_extension: false, + aabbs: vec![], + } + } + + /// Builds an `AccelerationStructure` from the builder + #[inline] + pub fn build( + self, + device: Arc, + queue: Arc, + ) -> Result { + if self.nv_extension { + self.build_nv(device, queue) + } else { + self.build_khr(device, queue) + } + } + + /// Builds an `AccelerationStructure` from the builder using the + /// `nv_ray_tracing` extension + #[inline] + fn build_nv( + self, + device: Arc, + queue: Arc, + ) -> Result { + let vk = device.pointers(); + + // TODO: Expose to user + let build_flag = vk::BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV; + + let geometries: Vec = self + .aabbs + .into_iter() + .map(|aabb| { + let geometry = vk::GeometryAABBNV { + sType: vk::STRUCTURE_TYPE_GEOMETRY_AABB_NV, + pNext: ptr::null(), + aabbData: aabb.inner().buffer.internal_object(), + numAABBs: (aabb.size() / size_of::()) as u32, + stride: size_of::() as u32, // TODO: + offset: aabb.inner().offset as vk::DeviceSize, + }; + vk::GeometryNV { + sType: vk::STRUCTURE_TYPE_GEOMETRY_NV, + pNext: ptr::null(), + geometryType: vk::GEOMETRY_TYPE_AABBS_NV, + geometry: vk::GeometryDataNV { + triangles: vk::GeometryTrianglesNV { + sType: vk::STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV, + pNext: ptr::null(), + vertexData: 0, + vertexOffset: 0, + vertexCount: 0, + vertexStride: 0, + vertexFormat: 0, + indexData: 0, + indexOffset: 0, + indexCount: 0, + indexType: 0, + transformData: 0, + transformOffset: 0, + }, + aabbs: geometry, + }, + flags: vk::GEOMETRY_OPAQUE_BIT_NV, // TODO + } + }) + .collect(); + + let bottom_level = { + let info = vk::AccelerationStructureInfoNV { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV, + pNext: ptr::null(), + type_: vk::ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV, + flags: build_flag, + instanceCount: 0, // must be 0 for bottom level + geometryCount: geometries.len() as u32, + pGeometries: geometries.as_ptr(), + }; + let create_info = vk::AccelerationStructureCreateInfoNV { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV, + pNext: ptr::null(), + compactedSize: 0, // TODO: + info, + }; + let structure = unsafe { + let mut output = MaybeUninit::uninit(); + check_errors(vk.CreateAccelerationStructureNV( + device.internal_object(), + &create_info, + ptr::null(), + output.as_mut_ptr(), + ))?; + output.assume_init() + }; + Level { + inner_object: structure, + type_: create_info.info.type_, + flags: create_info.info.flags, + instance_count: create_info.info.instanceCount, + geometries: geometries.iter().map(|g| Geometry::from(g)).collect(), + } + }; + + let top_level = { + let info = vk::AccelerationStructureInfoNV { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV, + pNext: ptr::null(), + type_: vk::ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV, + flags: 0, + instanceCount: 1, // number bottom level acceleration structure + geometryCount: 0, // must be 0 for top level + pGeometries: ptr::null(), + }; + let create_info = vk::AccelerationStructureCreateInfoNV { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV, + pNext: ptr::null(), + compactedSize: 0, // TODO: + info, + }; + let structure = unsafe { + let mut output = MaybeUninit::uninit(); + check_errors(vk.CreateAccelerationStructureNV( + device.internal_object(), + &create_info, + ptr::null(), + output.as_mut_ptr(), + ))?; + output.assume_init() + }; + Level { + inner_object: structure, + type_: create_info.info.type_, + flags: create_info.info.flags, + instance_count: create_info.info.instanceCount, + geometries: vec![], + } + }; + + let structures = [&top_level, &bottom_level]; + + // Get requirements + let memory_requirements: Vec = structures + .iter() + .map(|structure| unsafe { + let info = vk::AccelerationStructureMemoryRequirementsInfoNV { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV, + pNext: ptr::null(), + type_: vk::ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV, + accelerationStructure: structure.inner_object, + }; + let mut requirements = vk::MemoryRequirements2 { + sType: vk::STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR, + pNext: ptr::null_mut(), + memoryRequirements: vk::MemoryRequirements { + size: 0, + alignment: 0, + memoryTypeBits: 0, + }, + }; + vk.GetAccelerationStructureMemoryRequirementsNV( + device.internal_object(), + &info, + &mut requirements, + ); + requirements + }) + .collect(); + + // Allocate structure memory + let memory = { + let requirements = MemoryRequirements { + size: memory_requirements + .iter() + .map(|requirements| requirements.memoryRequirements.size) + .sum::() as usize, + alignment: memory_requirements + .first() + .unwrap() + .memoryRequirements + .alignment as usize, + memory_type_bits: memory_requirements + .first() + .unwrap() + .memoryRequirements + .memoryTypeBits as u32, + prefer_dedicated: true, + }; + MemoryPool::alloc_from_requirements( + &Device::standard_pool(&device), + &requirements, + AllocLayout::Optimal, + MappingRequirement::DoNotMap, + DedicatedAlloc::None, + |t| AllocFromRequirementsFilter::Preferred, + ) + .unwrap() + }; + + // Bind memory to structure + let mut memory_offset = 0; + let bind_infos: Vec = structures + .iter() + .zip(memory_requirements.iter()) + .map(|(structure, requirements)| { + let info = vk::BindAccelerationStructureMemoryInfoNV { + sType: vk::STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV, + pNext: ptr::null(), + accelerationStructure: structure.inner_object, + memory: memory.memory().internal_object(), + memoryOffset: memory_offset, + deviceIndexCount: 0, // TODO: + pDeviceIndices: ptr::null(), // TODO: + }; + memory_offset += requirements.memoryRequirements.size; + info + }) + .collect(); + unsafe { + check_errors(vk.BindAccelerationStructureMemoryNV( + device.internal_object(), + bind_infos.len() as u32, + bind_infos.as_ptr(), + ))?; + }; + + let (instance_buffer, instance_buffer_future) = { + // Get handles for lower level structures + let bottom_level_handle = unsafe { + let mut output: u64 = 0; + check_errors(vk.GetAccelerationStructureHandleNV( + device.internal_object(), + bottom_level.inner_object.clone(), + size_of::(), + &mut output as *mut u64 as *mut c_void, + ))?; + output + }; + + let instance = vk::AccelerationStructureInstanceNV { + transform: vk::TransformMatrixNV { + matrix: [ + [1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.0], + ], + }, + instanceCustomIndex: [0, 0, 0], + mask: 0xFF, + instanceShaderBindingTableRecordOffset: [0, 0, 0], + flags: 0, + accelerationStructureReference: bottom_level_handle, + }; + ImmutableBuffer::from_data(instance, BufferUsage::ray_tracing(), queue.clone()).unwrap() + }; + + // Allocate Scratch of size of the max of any level + let (scratch_buffer, scratch_buffer_initialization) = unsafe { + let size = structures + .iter() + .map(|structure| unsafe { + let info = vk::AccelerationStructureMemoryRequirementsInfoNV { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV, + pNext: ptr::null(), + type_: vk::ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV, + accelerationStructure: structure.inner_object, + }; + let mut requirements = vk::MemoryRequirements2 { + sType: vk::STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR, + pNext: ptr::null_mut(), + memoryRequirements: vk::MemoryRequirements { + size: 0, + alignment: 0, + memoryTypeBits: 0, + }, + }; + vk.GetAccelerationStructureMemoryRequirementsNV( + device.internal_object(), + &info, + &mut requirements, + ); + requirements.memoryRequirements.size + }) + .max() + .unwrap(); + + ImmutableBuffer::::raw( + device.clone(), + size as usize, + BufferUsage::ray_tracing(), + device.active_queue_families(), + ) + } + .unwrap(); + + instance_buffer_future + .then_signal_fence_and_flush() + .unwrap() + .wait(None) + .unwrap(); + + Ok(AccelerationStructure { + nv_extension: true, + top_level, + bottom_level, + memory, + instance_buffer, + scratch_buffer, + }) + } + + /// Builds an `AccelerationStructure` from the builder using the + /// `khr_ray_tracing` extension + #[inline] + fn build_khr( + self, + device: Arc, + queue: Arc, + ) -> Result { + let vk = device.pointers(); + + // TODO: Expose to user + let build_flag = vk::BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; + + let bottom_level = { + let geometry_infos: Vec = self + .aabbs + .iter() + .map(|aabb| { + vk::AccelerationStructureCreateGeometryTypeInfoKHR { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR, + pNext: ptr::null(), + geometryType: vk::GEOMETRY_TYPE_AABBS_KHR, + maxPrimitiveCount: (aabb.size() / size_of::()) as u32, + indexType: 0, + maxVertexCount: 0, + vertexFormat: 0, + allowsTransforms: vk::FALSE, + } + }) + .collect(); + let create_info = vk::AccelerationStructureCreateInfoKHR { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR, + pNext: ptr::null(), + compactedSize: 0, // TODO: + type_: vk::ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, + flags: build_flag, + maxGeometryCount: geometry_infos.len() as u32, + pGeometryInfos: geometry_infos.as_ptr(), + deviceAddress: 0, // TODO: if the rayTracingAccelerationStructureCaptureReplay feature is being used + }; + let structure = unsafe { + let mut output = MaybeUninit::uninit(); + check_errors(vk.CreateAccelerationStructureKHR( + device.internal_object(), + &create_info, + ptr::null(), + output.as_mut_ptr(), + ))?; + output.assume_init() + }; + Level { + inner_object: structure, + type_: create_info.type_, + flags: create_info.flags, + instance_count: create_info.maxGeometryCount, + geometries: self + .aabbs + .into_iter() + .map(|aabb| { + Geometry { + geometry_type: GeometryType::Aabbs, + geometry: GeometryData { + aabbs: GeometryAabbsData { + data: aabb.inner().buffer.internal_object() as u64, + stride: size_of::(), // TODO: + count: (aabb.size() / size_of::()) as u32, + }, + }, + flags: GeometryFlags { + opaque: true, + no_duplicate_any_hit_invocation: false, + }, + } + }).collect(), + } + }; + + let top_level = { + let info = vk::AccelerationStructureCreateGeometryTypeInfoKHR { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR, + pNext: ptr::null(), + geometryType: vk::GEOMETRY_TYPE_INSTANCES_KHR, + maxPrimitiveCount: 1, // number bottom level acceleration structure + indexType: 0, + maxVertexCount: 0, + vertexFormat: 0, + allowsTransforms: 0 + }; + let create_info = vk::AccelerationStructureCreateInfoKHR { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR, + pNext: ptr::null(), + compactedSize: 0, // TODO: + type_: vk::ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, + flags: build_flag, + maxGeometryCount: 1, // if compactedSize is 0, maxGeometryCount must be 1 for top level + pGeometryInfos: &info, + deviceAddress: 0, // TODO: if the rayTracingAccelerationStructureCaptureReplay feature is being used + }; + let structure = unsafe { + let mut output = MaybeUninit::uninit(); + check_errors(vk.CreateAccelerationStructureKHR( + device.internal_object(), + &create_info, + ptr::null(), + output.as_mut_ptr(), + ))?; + output.assume_init() + }; + Level { + inner_object: structure, + type_: create_info.type_, + flags: create_info.flags, + instance_count: create_info.maxGeometryCount, + geometries: vec![], + } + }; + + let structures = [&top_level, &bottom_level]; + + // Get requirements + let memory_requirements: Vec = structures + .iter() + .map(|structure| unsafe { + let info = vk::AccelerationStructureMemoryRequirementsInfoKHR { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR, + pNext: ptr::null(), + type_: vk::ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR, + buildType: vk::ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR, // TODO + accelerationStructure: structure.inner_object, + }; + let mut requirements = vk::MemoryRequirements2 { + sType: vk::STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR, + pNext: ptr::null_mut(), + memoryRequirements: vk::MemoryRequirements { + size: 0, + alignment: 0, + memoryTypeBits: 0, + }, + }; + vk.GetAccelerationStructureMemoryRequirementsKHR( + device.internal_object(), + &info, + &mut requirements, + ); + requirements + }) + .collect(); + + // Allocate structure memory + let memory = { + let requirements = MemoryRequirements { + size: memory_requirements + .iter() + .map(|requirements| requirements.memoryRequirements.size) + .sum::() as usize, + alignment: memory_requirements + .first() + .unwrap() + .memoryRequirements + .alignment as usize, + memory_type_bits: memory_requirements + .first() + .unwrap() + .memoryRequirements + .memoryTypeBits as u32, + prefer_dedicated: true, + }; + MemoryPool::alloc_from_requirements( + &Device::standard_pool(&device), + &requirements, + AllocLayout::Optimal, + MappingRequirement::DoNotMap, + DedicatedAlloc::None, + |t| AllocFromRequirementsFilter::Preferred, + ) + .unwrap() + }; + + // Bind memory to structure + let mut memory_offset = 0; + let bind_infos: Vec = structures + .iter() + .zip(memory_requirements.iter()) + .map(|(structure, requirements)| { + let info = vk::BindAccelerationStructureMemoryInfoKHR { + sType: vk::STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR, + pNext: ptr::null(), + accelerationStructure: structure.inner_object, + memory: memory.memory().internal_object(), + memoryOffset: memory_offset, + deviceIndexCount: 0, // TODO: + pDeviceIndices: ptr::null(), // TODO: + }; + memory_offset += requirements.memoryRequirements.size; + info + }) + .collect(); + unsafe { + check_errors(vk.BindAccelerationStructureMemoryKHR( + device.internal_object(), + bind_infos.len() as u32, + bind_infos.as_ptr(), + ))?; + }; + + let (instance_buffer, instance_buffer_future) = { + // Get handles for lower level structures + let bottom_level_address = unsafe { + let info = vk::AccelerationStructureDeviceAddressInfoKHR { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR, + pNext: ptr::null(), + accelerationStructure: bottom_level.inner_object.clone(), + }; + vk.GetAccelerationStructureDeviceAddressKHR(device.internal_object(), &info) + }; + + let instance = vk::AccelerationStructureInstanceKHR { + transform: vk::TransformMatrixKHR { + matrix: [ + [1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.0], + ], + }, + instanceCustomIndex: [0, 0, 0], + mask: 0xFF, + instanceShaderBindingTableRecordOffset: [0, 0, 0], + flags: 0, + accelerationStructureReference: bottom_level_address, + }; + ImmutableBuffer::from_data(instance, BufferUsage::ray_tracing(), queue.clone()).unwrap() + }; + + // Allocate Scratch of size of the max of any level + let (scratch_buffer, scratch_buffer_initialization) = unsafe { + let size = structures + .iter() + .map(|structure| unsafe { + let info = vk::AccelerationStructureMemoryRequirementsInfoKHR { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR, + pNext: ptr::null(), + type_: vk::ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR, + buildType: vk::ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR, // TODO + accelerationStructure: structure.inner_object, + }; + let mut requirements = vk::MemoryRequirements2 { + sType: vk::STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR, + pNext: ptr::null_mut(), + memoryRequirements: vk::MemoryRequirements { + size: 0, + alignment: 0, + memoryTypeBits: 0, + }, + }; + vk.GetAccelerationStructureMemoryRequirementsKHR( + device.internal_object(), + &info, + &mut requirements, + ); + requirements.memoryRequirements.size + }) + .max() + .unwrap(); + + ImmutableBuffer::::raw( + device.clone(), + size as usize, + BufferUsage{ray_tracing: true, shader_device_address: true, ..BufferUsage::none()}, + device.active_queue_families(), + ) + } + .unwrap(); + + instance_buffer_future + .then_signal_fence_and_flush() + .unwrap() + .wait(None) + .unwrap(); + + Ok(AccelerationStructure { + nv_extension: false, + top_level, + bottom_level, + memory, + instance_buffer, + scratch_buffer, + }) + } + + /// Add a Triangle Mesh to the acceleration structure + #[inline] + pub fn add_triangles( + mut self, buffer: T, + ) -> Result + where + T: BufferAccess + Send + Sync + 'static, + { + // TODO + unimplemented!("Adding triangles is not yet implemented") + } + + /// Add Custom Intersection Geometry to the acceleration structure + #[inline] + pub fn add_aabbs( + mut self, buffer: T, + ) -> Result + where + T: BufferAccess + Send + Sync + 'static, + { + self.aabbs.push(Box::new(buffer)); + Ok(self) + } +} + +macro_rules! build_acceleration_struct_flags { + ($($elem:ident => $val:expr,)+) => ( + #[derive(Debug, Copy, Clone)] + #[allow(missing_docs)] + pub struct BuildAccelerationStructureFlags { + $( + pub $elem: bool, + )+ + } + + impl BuildAccelerationStructureFlags { + /// Builds an `BuildAccelerationStructureFlag` struct with all bits set. + pub fn all() -> BuildAccelerationStructureFlags { + BuildAccelerationStructureFlags { + $( + $elem: true, + )+ + } + } + + /// Builds an `BuildAccelerationStructureFlag` struct with none of the bits set. + pub fn none() -> BuildAccelerationStructureFlags { + BuildAccelerationStructureFlags { + $( + $elem: false, + )+ + } + } + + #[inline] + pub(crate) fn into_vulkan_bits(self) -> vk::BuildAccelerationStructureFlagBitsKHR { + let mut result = 0; + $( + if self.$elem { result |= $val } + )+ + result + } + } + + impl ops::BitOr for BuildAccelerationStructureFlags { + type Output = BuildAccelerationStructureFlags; + + #[inline] + fn bitor(self, rhs: BuildAccelerationStructureFlags) -> BuildAccelerationStructureFlags { + BuildAccelerationStructureFlags { + $( + $elem: self.$elem || rhs.$elem, + )+ + } + } + } + + impl ops::BitOrAssign for BuildAccelerationStructureFlags { + #[inline] + fn bitor_assign(&mut self, rhs: BuildAccelerationStructureFlags) { + $( + self.$elem = self.$elem || rhs.$elem; + )+ + } + } + ); +} + +build_acceleration_struct_flags! { + allow_update => vk::BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, + allow_compaction => vk::BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, + prefer_fast_trace => vk::BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, + prefer_fast_build => vk::BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR, + low_memory => vk::BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR, +} + +macro_rules! geometry_flags { + ($($elem:ident => $val:expr,)+) => ( + #[derive(Debug, Copy, Clone)] + #[allow(missing_docs)] + pub struct GeometryFlags { + $( + pub $elem: bool, + )+ + } + + impl GeometryFlags { + /// Builds an `GeometryFlags` struct with all bits set. + pub fn all() -> GeometryFlags { + GeometryFlags { + $( + $elem: true, + )+ + } + } + + /// Builds an `GeometryFlags` struct with none of the bits set. + pub fn none() -> GeometryFlags { + GeometryFlags { + $( + $elem: false, + )+ + } + } + + #[inline] + pub(crate) fn into_vulkan_bits(self) -> vk::GeometryFlagBitsKHR { + let mut result = 0; + $( + if self.$elem { result |= $val } + )+ + result + } + } + + impl ops::BitOr for GeometryFlags { + type Output = GeometryFlags; + + #[inline] + fn bitor(self, rhs: GeometryFlags) -> GeometryFlags { + GeometryFlags { + $( + $elem: self.$elem || rhs.$elem, + )+ + } + } + } + + impl ops::BitOrAssign for GeometryFlags { + #[inline] + fn bitor_assign(&mut self, rhs: GeometryFlags) { + $( + self.$elem = self.$elem || rhs.$elem; + )+ + } + } + ); +} + +geometry_flags! { + opaque => vk::GEOMETRY_OPAQUE_BIT_KHR, + no_duplicate_any_hit_invocation => vk::GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR, +} + +/// An enumeration of all valid geometry types. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[allow(missing_docs)] +#[repr(u32)] +pub enum GeometryType { + Triangles = vk::GEOMETRY_TYPE_TRIANGLES_KHR, + Aabbs = vk::GEOMETRY_TYPE_AABBS_KHR, + Instances = vk::GEOMETRY_TYPE_INSTANCES_KHR, +} + +#[derive(Copy, Clone)] +pub struct GeometryTrianglesData { + pub vertex_format: Format, + pub vertex_data: u64, + pub vertex_stride: usize, + pub index_type: IndexType, + pub index_data: u64, + pub transform_data: u64, +} + +#[derive(Copy, Clone)] +pub struct GeometryAabbsData { + pub data: u64, + pub stride: usize, + pub count: u32, +} + +#[derive(Copy, Clone)] +pub struct GeometryInstancesData { + pub array_of_pointers: bool, + pub data: u64, +} + +#[derive(Copy, Clone)] +pub union GeometryData { + pub triangles: GeometryTrianglesData, + pub aabbs: GeometryAabbsData, + pub instances: GeometryInstancesData, +} + +#[derive(Copy, Clone)] +pub struct Geometry { + pub geometry_type: GeometryType, + pub geometry: GeometryData, + pub flags: GeometryFlags, +} + +impl<'a> From<&'a vk::GeometryNV> for Geometry { + fn from(geometry_nv: &'a vk::GeometryNV) -> Self { + let geometry_type = match geometry_nv.geometryType { + vk::GEOMETRY_TYPE_TRIANGLES_KHR => GeometryType::Triangles, + vk::GEOMETRY_TYPE_AABBS_KHR => GeometryType::Aabbs, + _ => unreachable!(), + }; + + let geometry = match geometry_nv.geometryType { + vk::GEOMETRY_TYPE_TRIANGLES_KHR => GeometryData { + triangles: GeometryTrianglesData { + vertex_format: Format::from_vulkan_num( + geometry_nv.geometry.triangles.vertexFormat, + ) + .unwrap(), + vertex_data: geometry_nv.geometry.triangles.vertexData, + vertex_stride: geometry_nv.geometry.triangles.vertexStride as usize, + index_type: match geometry_nv.geometry.triangles.indexType { + vk::INDEX_TYPE_UINT16 => IndexType::U16, + vk::INDEX_TYPE_UINT32 => IndexType::U32, + _ => unreachable!(), + }, + index_data: geometry_nv.geometry.triangles.indexData, + transform_data: geometry_nv.geometry.triangles.transformData, + }, + }, + vk::GEOMETRY_TYPE_AABBS_KHR => GeometryData { + aabbs: GeometryAabbsData { + data: geometry_nv.geometry.aabbs.aabbData, + stride: geometry_nv.geometry.aabbs.stride as usize, + count: geometry_nv.geometry.aabbs.numAABBs, + }, + }, + _ => unreachable!(), + }; + + let flags = match geometry_nv.flags { + vk::GEOMETRY_OPAQUE_BIT_KHR => GeometryFlags { + opaque: true, + no_duplicate_any_hit_invocation: false, + }, + vk::GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR => GeometryFlags { + opaque: false, + no_duplicate_any_hit_invocation: true, + }, + _ => unreachable!(), + }; + + Geometry { + geometry_type, + geometry, + flags, + } + } +} + +impl<'a> From<&'a Geometry> for vk::GeometryNV { + fn from(geometry: &'a Geometry) -> Self { + let geometry_type = geometry.geometry_type as vk::GeometryTypeNV; + + let geometry_nv = unsafe { + match geometry.geometry_type { + GeometryType::Triangles => vk::GeometryDataNV { + triangles: vk::GeometryTrianglesNV { + sType: vk::STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV, + pNext: ptr::null(), + vertexData: geometry.geometry.triangles.vertex_data, + vertexOffset: 0, // TODO: + vertexCount: 0, // TODO: + vertexStride: geometry.geometry.triangles.vertex_stride as vk::DeviceSize, + vertexFormat: geometry.geometry.triangles.vertex_format as u32, + indexData: geometry.geometry.triangles.index_data, + indexOffset: 0, // TODO: + indexCount: 0, // TODO: + indexType: match geometry.geometry.triangles.index_type { + IndexType::U16 => vk::INDEX_TYPE_UINT16, + IndexType::U32 => vk::INDEX_TYPE_UINT32, + }, + transformData: geometry.geometry.triangles.transform_data, + transformOffset: 0, // TODO: + }, + aabbs: vk::GeometryAABBNV { + sType: vk::STRUCTURE_TYPE_GEOMETRY_AABB_NV, + pNext: ptr::null(), + aabbData: 0, + numAABBs: 0, + stride: 0, + offset: 0, + }, + }, + GeometryType::Aabbs => vk::GeometryDataNV { + triangles: vk::GeometryTrianglesNV { + sType: vk::STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV, + pNext: ptr::null(), + vertexData: 0, + vertexOffset: 0, + vertexCount: 0, + vertexStride: 0, + vertexFormat: 0, + indexData: 0, + indexOffset: 0, + indexCount: 0, + indexType: 0, + transformData: 0, + transformOffset: 0, + }, + aabbs: vk::GeometryAABBNV { + sType: vk::STRUCTURE_TYPE_GEOMETRY_AABB_NV, + pNext: ptr::null(), + aabbData: geometry.geometry.aabbs.data, + numAABBs: geometry.geometry.aabbs.count, + stride: geometry.geometry.aabbs.stride as u32, + offset: 0, // TODO: + }, + }, + _ => unreachable!(), + } + }; + + let flags = if geometry.flags.opaque { + vk::GEOMETRY_OPAQUE_BIT_KHR + } else { + vk::GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR + }; + + vk::GeometryNV { + sType: vk::STRUCTURE_TYPE_GEOMETRY_NV, + pNext: ptr::null(), + geometryType: geometry_type, + geometry: geometry_nv, + flags, + } + } +} + +/// Error when building a persistent descriptor set. +#[derive(Debug, Clone)] +pub enum AccelerationStructureCreationError { + /// Out of memory. + OomError(OomError), +} + +impl error::Error for AccelerationStructureCreationError { + #[inline] + fn description(&self) -> &str { + match *self { + AccelerationStructureCreationError::OomError(_) => "not enough memory available", + } + } + + #[inline] + fn cause(&self) -> Option<&dyn error::Error> { + match *self { + AccelerationStructureCreationError::OomError(ref err) => Some(err), + } + } +} + +impl From for AccelerationStructureCreationError { + #[inline] + fn from(err: OomError) -> AccelerationStructureCreationError { + AccelerationStructureCreationError::OomError(err) + } +} + +impl From for AccelerationStructureCreationError { + #[inline] + fn from(err: Error) -> AccelerationStructureCreationError { + match err { + err @ Error::OutOfHostMemory => { + AccelerationStructureCreationError::OomError(OomError::from(err)) + } + err @ Error::OutOfDeviceMemory => { + AccelerationStructureCreationError::OomError(OomError::from(err)) + } + _ => panic!("unexpected error: {:?}", err), + } + } +} + +impl fmt::Display for AccelerationStructureCreationError { + #[inline] + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(fmt, "{}", error::Error::description(self)) + } +} diff --git a/vulkano/src/command_buffer/auto.rs b/vulkano/src/command_buffer/auto.rs index 1d5a4cc1d5..b076911044 100644 --- a/vulkano/src/command_buffer/auto.rs +++ b/vulkano/src/command_buffer/auto.rs @@ -17,6 +17,7 @@ use std::sync::atomic::AtomicBool; use std::sync::atomic::Ordering; use OomError; +use acceleration_structure::AccelerationStructure; use buffer::BufferAccess; use buffer::TypedBufferAccess; use command_buffer::{CommandBuffer, TraceRaysIndirectCommandKHR}; @@ -1207,6 +1208,19 @@ impl

AutoCommandBufferBuilder

{ } } + /// Performs a build acceleration structure dispatch + // TODO: should accept a list of acceleration structures + #[inline] + pub fn build_acceleration_structure( + mut self, acceleration_structure: &AccelerationStructure, + ) -> Result { + assert_eq!(acceleration_structure.top_level().geometries.len(), 0); + unsafe { + self.inner.build_acceleration_structure(acceleration_structure); + Ok(self) + } + } + /// Performs a ray tracing dispatch using the binding tables. /// /// To use only some data in a buffer, wrap it in a `vulkano::buffer::BufferSlice`. @@ -1883,6 +1897,10 @@ err_gen!(UpdateBufferError { CheckUpdateBufferError, }); +err_gen!(BuildAccelerationStructureError { + AutoCommandBufferBuilderContextError, + }); + err_gen!(TraceRaysError { AutoCommandBufferBuilderContextError, CheckPushConstantsValidityError, diff --git a/vulkano/src/command_buffer/synced/commands.rs b/vulkano/src/command_buffer/synced/commands.rs index 03a55bad90..21f817c361 100644 --- a/vulkano/src/command_buffer/synced/commands.rs +++ b/vulkano/src/command_buffer/synced/commands.rs @@ -14,7 +14,10 @@ use std::mem; use std::ptr; use std::sync::Arc; +use acceleration_structure::AccelerationStructure; +use acceleration_structure::Level; use buffer::BufferAccess; +use buffer::ImmutableBuffer; use command_buffer::CommandBuffer; use command_buffer::synced::base::Command; use command_buffer::synced::base::FinalCommand; @@ -28,6 +31,7 @@ use command_buffer::sys::UnsafeCommandBufferBuilderColorImageClear; use command_buffer::sys::UnsafeCommandBufferBuilderExecuteCommands; use command_buffer::sys::UnsafeCommandBufferBuilderImageCopy; use command_buffer::sys::UnsafeCommandBufferBuilderImageBlit; +use command_buffer::sys::UnsafeCommandBufferBuilderPipelineBarrier; use descriptor::descriptor::DescriptorDescTy; use descriptor::descriptor::ShaderStages; use descriptor::descriptor_set::DescriptorSet; @@ -1948,6 +1952,186 @@ impl

SyncCommandBufferBuilder

{ .unwrap(); } + /// Calls `vkCmdBuildAccelerationStructureNV`/`vkCmdBuildAccelerationStructureKHR` on the builder. + /// // TODO: should accept a list of acceleration structures + pub unsafe fn build_acceleration_structure( + &mut self, acceleration_structure: &AccelerationStructure, + ) -> Result<(), SyncCommandBufferBuilderError> { + struct Cmd { + use_nv_extension: bool, + dst: Level, + instance_buffer: Option, + scratch_buffer: S, + } + + impl Command

for Cmd + where + I: BufferAccess + Send + Sync + 'static, + S: BufferAccess + Send + Sync + 'static, + { + fn name(&self) -> &'static str { + if self.use_nv_extension { + "vkCmdBuildAccelerationStructureNV" + } else { + "vkCmdBuildAccelerationStructureKHR" + } + } + + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { + if self.use_nv_extension { + let geometries: Vec = + self.dst.geometries.iter().map(|g| g.into()).collect(); + out.build_acceleration_structure_nv( + vk::AccelerationStructureInfoNV { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV, + pNext: ptr::null(), + type_: self.dst.type_, + flags: self.dst.flags, + instanceCount: self.dst.instance_count, + geometryCount: geometries.len() as u32, + pGeometries: geometries.as_ptr(), + }, + self.instance_buffer.as_ref(), + false, + self.dst.inner_object, + vk::NULL_HANDLE, + &self.scratch_buffer, + ); + } else { + // TODO: should pass a list of acceleration structures + out.build_acceleration_structure_khr( + self.dst.type_, + self.dst.flags, + false, + self.dst.inner_object, + vk::NULL_HANDLE, + &self.scratch_buffer, + self.dst.geometries.clone(), + self.dst.instance_count, + ); + } + } + + fn into_final_command(self: Box) -> Box { + if self.use_nv_extension { + Box::new("vkCmdBuildAccelerationStructureNV") + } else { + Box::new("vkCmdBuildAccelerationStructureKHR") + } + } + + fn buffer(&self, num: usize) -> &dyn BufferAccess { + assert_eq!(num, 0); + &self.scratch_buffer + } + + fn buffer_name(&self, num: usize) -> Cow<'static, str> { + assert_eq!(num, 0); + "scratch".into() + } + } + + // TODO convert to prev_cmd_resource + struct Cmd2 { + destination_stage: PipelineStages, + } + impl

Command

for Cmd2 { + fn name(&self) -> &'static str { + "vkCmdPipelineBarrier" + } + + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { + let mut barrier = UnsafeCommandBufferBuilderPipelineBarrier::new(); + barrier.add_memory_barrier( + PipelineStages { + acceleration_structure_build: true, + ..PipelineStages::none() + }, + AccessFlagBits { + acceleration_structure_write: true, + ..AccessFlagBits::none() + }, + self.destination_stage, + AccessFlagBits { + acceleration_structure_read: true, + ..AccessFlagBits::none() + }, + false, + ); + out.pipeline_barrier(&barrier); + } + + fn into_final_command(self: Box) -> Box { + Box::new("vkCmdPipelineBarrier") + } + } + + self.append_command(Cmd { + use_nv_extension: acceleration_structure.nv_extension(), + dst: acceleration_structure.bottom_level(), + instance_buffer: None::>, + scratch_buffer: acceleration_structure.scratch_buffer().clone(), + }); + + self.append_command(Cmd2 { + destination_stage: PipelineStages { + acceleration_structure_build: true, + ..PipelineStages::none() + }, + }); + + // TODO + // self.prev_cmd_resource( + // KeyTy::AccelerationStructure, + // 0, + // true, + // PipelineStages { + // acceleration_structure_build: true, + // ..PipelineStages::none() + // }, + // AccessFlagBits { + // acceleration_structure_write: true, + // ..AccessFlagBits::none() + // }, + // ImageLayout::Undefined, + // ImageLayout::Undefined, + // ) + // .unwrap(); + + self.append_command(Cmd { + use_nv_extension: acceleration_structure.nv_extension(), + dst: acceleration_structure.top_level(), + instance_buffer: Some(acceleration_structure.instance_buffer().clone()), + scratch_buffer: acceleration_structure.scratch_buffer().clone(), + }); + + self.append_command(Cmd2 { + destination_stage: PipelineStages { + ray_tracing_shader: true, + ..PipelineStages::none() + }, + }); + // TODO + // self.prev_cmd_resource( + // KeyTy::AccelerationStructure, + // 0, + // true, + // PipelineStages { + // acceleration_structure_build: true, + // ..PipelineStages::none() + // }, + // AccessFlagBits { + // acceleration_structure_write: true, + // ..AccessFlagBits::none() + // }, + // ImageLayout::Undefined, + // ImageLayout::Undefined, + // ) + // .unwrap(); + + Ok(()) + } + /// Calls `vkCmdTraceRaysKHR` / `vkCmdTraceRaysNV` on the builder. // TODO: `miss_shader_binding_table`, `hit_shader_binding_table`, // `callable_shader_binding_table` should be optional diff --git a/vulkano/src/command_buffer/sys.rs b/vulkano/src/command_buffer/sys.rs index 6ff66c8631..b5efe2dee5 100644 --- a/vulkano/src/command_buffer/sys.rs +++ b/vulkano/src/command_buffer/sys.rs @@ -56,6 +56,7 @@ use sync::Event; use sync::PipelineStages; use vk; use std::ffi::CStr; +use acceleration_structure::{Geometry, GeometryType}; /// Determines the kind of command buffer that we want to create. #[derive(Debug, Clone)] @@ -1531,6 +1532,206 @@ impl

UnsafeCommandBufferBuilder

{ vk.CmdInsertDebugUtilsLabelEXT(cmd, &info); } + /// Calls `vkCmdBuildAccelerationStructureNV` on the builder. + #[inline] + pub unsafe fn build_acceleration_structure_nv( + &mut self, + info: vk::AccelerationStructureInfoNV, + instance_buffer: Option<&I>, + update: bool, + dst: vk::AccelerationStructureNV, + src: vk::AccelerationStructureNV, + scratch_buffer: &S, + ) where + S: ?Sized + BufferAccess, + I: ?Sized + BufferAccess, + { + let vk = self.device().pointers(); + let cmd = self.internal_object(); + + let (inner_instance_buffer_object, inner_instance_buffer_offset) = match instance_buffer { + Some(instance) => { + let inner_instance_buffer = instance.inner(); + debug_assert!(inner_instance_buffer.offset < inner_instance_buffer.buffer.size()); + ( + inner_instance_buffer.buffer.internal_object(), + inner_instance_buffer.offset as vk::DeviceSize, + ) + } + None => (0, 0), + }; + + let inner_scratch_buffer = scratch_buffer.inner(); + debug_assert!(update == (src != vk::NULL_HANDLE)); + debug_assert!(inner_scratch_buffer.offset < inner_scratch_buffer.buffer.size()); + + vk.CmdBuildAccelerationStructureNV( + cmd, + &info, + inner_instance_buffer_object, + inner_instance_buffer_offset, + update as vk::Bool32, + dst, + src, + inner_scratch_buffer.buffer.internal_object(), + inner_scratch_buffer.offset as vk::DeviceSize, + ); + } + + /// Calls `vkCmdBuildAccelerationStructureKHR` on the builder. + // TODO: should accept a list of acceleration structures + #[inline] + pub unsafe fn build_acceleration_structure_khr( + &mut self, + type_: vk::AccelerationStructureTypeKHR, + flags: vk::BuildAccelerationStructureFlagsKHR, + update: bool, + dst: vk::AccelerationStructureKHR, + src: vk::AccelerationStructureKHR, + scratch_buffer: &S, + geometries: G, + primitive_count: u32, + ) where + S: ?Sized + BufferAccess, + G: IntoIterator, + { + let vk = self.device().pointers(); + let cmd = self.internal_object(); + + let inner_scratch_buffer = scratch_buffer.inner(); + debug_assert!(update == (src != vk::NULL_HANDLE)); + debug_assert!(inner_scratch_buffer.offset < inner_scratch_buffer.buffer.size()); + + let info = { + let geometries_khr: Vec = geometries + .into_iter() + .map(|g| { + vk::AccelerationStructureGeometryKHR { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, + pNext: ptr::null(), + geometryType: g.geometry_type as u32, + geometry: { + match g.geometry_type { + GeometryType::Triangles => vk::AccelerationStructureGeometryDataKHR { + triangles: vk::AccelerationStructureGeometryTrianglesDataKHR { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR, + pNext: ptr::null(), + vertexData: vk::DeviceOrHostAddressConstKHR { + deviceAddress: { + let info = vk::BufferDeviceAddressInfoKHR { + sType: vk::STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + pNext: ptr::null(), + buffer: g.geometry.triangles.vertex_data, + }; + vk.GetBufferDeviceAddressKHR(self.device().internal_object(), & info) + } + }, + vertexStride: g.geometry.triangles.vertex_stride as vk::DeviceSize, + vertexFormat: g.geometry.triangles.vertex_format as u32, + indexData: vk::DeviceOrHostAddressConstKHR { + deviceAddress: { + let info = vk::BufferDeviceAddressInfoKHR { + sType: vk::STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + pNext: ptr::null(), + buffer: g.geometry.triangles.index_data, + }; + vk.GetBufferDeviceAddressKHR(self.device().internal_object(), & info) + } + }, + indexType: match g.geometry.triangles.index_type { + IndexType::U16 => vk::INDEX_TYPE_UINT16, + IndexType::U32 => vk::INDEX_TYPE_UINT32, + }, + transformData: vk::DeviceOrHostAddressConstKHR { + deviceAddress: { + let info = vk::BufferDeviceAddressInfoKHR { + sType: vk::STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + pNext: ptr::null(), + buffer: g.geometry.triangles.transform_data, + }; + vk.GetBufferDeviceAddressKHR(self.device().internal_object(), & info) + } + }, + }, + }, + GeometryType::Aabbs => vk::AccelerationStructureGeometryDataKHR { + aabbs: vk::AccelerationStructureGeometryAabbsDataKHR { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR, + pNext: ptr::null(), + data: vk::DeviceOrHostAddressConstKHR { + deviceAddress: { + let info = vk::BufferDeviceAddressInfoKHR { + sType: vk::STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + pNext: ptr::null(), + buffer: g.geometry.aabbs.data, + }; + vk.GetBufferDeviceAddressKHR(self.device().internal_object(), & info) + } + }, + stride: g.geometry.aabbs.stride as u64, + }, + }, + GeometryType::Instances => vk::AccelerationStructureGeometryDataKHR { + instances: vk::AccelerationStructureGeometryInstancesDataKHR { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR, + pNext: ptr::null(), + arrayOfPointers: g.geometry.instances.array_of_pointers as u32, + data: vk::DeviceOrHostAddressConstKHR { + deviceAddress: { + let info = vk::BufferDeviceAddressInfoKHR { + sType: vk::STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + pNext: ptr::null(), + buffer: g.geometry.instances.data, + }; + vk.GetBufferDeviceAddressKHR( self.device().internal_object(), & info) + } + }, + }, + }, + } + }, + flags: g.flags.into_vulkan_bits(), + } + }) + .collect(); + let p_geometries: Vec<*const vk::AccelerationStructureGeometryKHR> = geometries_khr.into_iter().map(|g| {&g as *const _}).collect(); + vk::AccelerationStructureBuildGeometryInfoKHR { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR, + pNext: ptr::null(), + type_, + flags, + update: update as vk::Bool32, + srcAccelerationStructure: src, + dstAccelerationStructure: dst, + geometryArrayOfPointers: vk::TRUE, + geometryCount: p_geometries.len() as u32, + ppGeometries: p_geometries.as_ptr(), + scratchData: vk::DeviceOrHostAddressKHR { + deviceAddress: { + let info = vk::BufferDeviceAddressInfoKHR { + sType: vk::STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + pNext: ptr::null(), + buffer: scratch_buffer.inner().buffer.internal_object(), + }; + vk.GetBufferDeviceAddressKHR( self.device.clone().internal_object(), & info) + } + }, + } + }; + let offset_info = vk::AccelerationStructureBuildOffsetInfoKHR { + primitiveCount: primitive_count, + primitiveOffset: 0, + firstVertex: 0, + transformOffset: 0 + }; + let infos = [info]; + let offsets = [&offset_info as *const _]; + + assert_eq!(infos.len(), offsets.len()); + + vk.CmdBuildAccelerationStructureKHR(cmd, infos.len() as u32, infos.as_ptr(), offsets.as_ptr()); + } + /// Calls `vkCmdTraceRaysNV` on the builder. #[inline] pub unsafe fn trace_rays_nv( diff --git a/vulkano/src/lib.rs b/vulkano/src/lib.rs index d2cf38271e..5492d516bb 100644 --- a/vulkano/src/lib.rs +++ b/vulkano/src/lib.rs @@ -79,6 +79,7 @@ mod extensions; mod features; mod version; +pub mod acceleration_structure; pub mod buffer; pub mod command_buffer; pub mod descriptor; From 5144ab8b2a7d3992d3024ec8ae80975301ba1e28 Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Sat, 25 Apr 2020 12:06:16 +0200 Subject: [PATCH 11/15] descriptor: Add acceleration structure descriptor --- examples/src/bin/nv-ray-tracing.rs | 5 + vulkano-shaders/src/descriptor_sets.rs | 4 + vulkano-shaders/src/parse.rs | 2 + vulkano/src/acceleration_structure.rs | 66 +++++++++- vulkano/src/descriptor/descriptor.rs | 11 ++ .../descriptor_set/fixed_size_pool.rs | 23 ++++ .../descriptor/descriptor_set/persistent.rs | 115 ++++++++++++++++++ vulkano/src/descriptor/descriptor_set/sys.rs | 60 +++++++++ .../pipeline_layout/limits_check.rs | 4 + 9 files changed, 289 insertions(+), 1 deletion(-) diff --git a/examples/src/bin/nv-ray-tracing.rs b/examples/src/bin/nv-ray-tracing.rs index 0dafcd237f..2c37640b97 100644 --- a/examples/src/bin/nv-ray-tracing.rs +++ b/examples/src/bin/nv-ray-tracing.rs @@ -152,6 +152,7 @@ fn main() { #extension GL_NV_ray_tracing : enable layout(set = 0, binding = 0, rgba8) uniform image2D result; +layout(set = 0, binding = 1) uniform accelerationStructureNV scene; layout(location = 0) rayPayloadNV vec4 payload; void main() { @@ -198,6 +199,8 @@ void main() { PersistentDescriptorSet::start(layout.clone()) .add_image(image.clone()) .unwrap() + .add_acceleration_structure(acceleration_structure.clone()) + .unwrap() .build() .unwrap(), ) @@ -283,6 +286,8 @@ void main() { PersistentDescriptorSet::start(layout.clone()) .add_image(image.clone()) .unwrap() + .add_acceleration_structure(acceleration_structure.clone()) + .unwrap() .build() .unwrap(), ) diff --git a/vulkano-shaders/src/descriptor_sets.rs b/vulkano-shaders/src/descriptor_sets.rs index d0ec81a4f9..5e10b67ffe 100644 --- a/vulkano-shaders/src/descriptor_sets.rs +++ b/vulkano-shaders/src/descriptor_sets.rs @@ -295,6 +295,10 @@ fn descriptor_infos(doc: &Spirv, pointed_ty: u32, pointer_storage: StorageClass, let len = len.iter().rev().fold(0, |a, &b| (a << 32) | b as u64); Some((desc, readonly, len)) } + &Instruction::TypeAccelerationStructure{result_id} if result_id == pointed_ty => { + let desc = quote!{ DescriptorDescTy::AccelerationStructure }; + Some((desc, true, 1)) + }, _ => None, // TODO: other types } }).next() diff --git a/vulkano-shaders/src/parse.rs b/vulkano-shaders/src/parse.rs index 505b454321..192fcec55c 100644 --- a/vulkano-shaders/src/parse.rs +++ b/vulkano-shaders/src/parse.rs @@ -176,6 +176,7 @@ pub enum Instruction { Branch { result_id: u32 }, Kill, Return, + TypeAccelerationStructure { result_id: u32 }, } fn parse_instruction(i: &[u32]) -> Result<(Instruction, &[u32]), ParseError> { @@ -357,6 +358,7 @@ fn decode_instruction(opcode: u16, operands: &[u32]) -> Result Instruction::Branch { result_id: operands[0] }, 252 => Instruction::Kill, 253 => Instruction::Return, + 5341 => Instruction::TypeAccelerationStructure { result_id: operands[0] }, _ => Instruction::Unknown(opcode, operands.to_owned()), }) } diff --git a/vulkano/src/acceleration_structure.rs b/vulkano/src/acceleration_structure.rs index 746242d17c..46a2f93523 100644 --- a/vulkano/src/acceleration_structure.rs +++ b/vulkano/src/acceleration_structure.rs @@ -15,8 +15,8 @@ use std::ops; use std::ptr; use buffer::{BufferAccess, BufferUsage, ImmutableBuffer}; -use device::Device; use device::Queue; +use device::{Device, DeviceOwned}; use format::Format; use memory::pool::{ AllocFromRequirementsFilter, AllocLayout, MappingRequirement, MemoryPoolAlloc, @@ -52,6 +52,7 @@ pub struct Level { /// Structure used by rays to find geometry in a scene pub struct AccelerationStructure { + device: Arc, nv_extension: bool, top_level: Level, bottom_level: Level, @@ -427,6 +428,7 @@ impl AccelerationStructureBuilder { .unwrap(); Ok(AccelerationStructure { + device: device.clone(), nv_extension: true, top_level, bottom_level, @@ -716,6 +718,7 @@ impl AccelerationStructureBuilder { .unwrap(); Ok(AccelerationStructure { + device: device.clone(), nv_extension: false, top_level, bottom_level, @@ -1071,6 +1074,67 @@ impl<'a> From<&'a Geometry> for vk::GeometryNV { } } +unsafe impl DeviceOwned for AccelerationStructure { + #[inline] + fn device(&self) -> &Arc { + &self.device + } +} + +unsafe impl VulkanObject for AccelerationStructure { + type Object = vk::AccelerationStructureKHR; + + const TYPE: vk::ObjectType = vk::OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR; + + #[inline] + fn internal_object(&self) -> vk::AccelerationStructureKHR { + self.top_level.inner_object + } +} + +impl fmt::Debug for AccelerationStructure { + #[inline] + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + fmt, + "", + self.top_level.inner_object + ) + } +} + +impl Drop for AccelerationStructure { + #[inline] + fn drop(&mut self) { + unsafe { + let vk = self.device.pointers(); + if self.nv_extension { + vk.DestroyAccelerationStructureNV( + self.device.internal_object(), + self.top_level.inner_object, + ptr::null(), + ); + vk.DestroyAccelerationStructureNV( + self.device.internal_object(), + self.aabb_bottom_level.inner_object, + ptr::null(), + ); + } else { + vk.DestroyAccelerationStructureKHR( + self.device.internal_object(), + self.top_level.inner_object, + ptr::null(), + ); + vk.DestroyAccelerationStructureKHR( + self.device.internal_object(), + self.aabb_bottom_level.inner_object, + ptr::null(), + ); + } + } + } +} + /// Error when building a persistent descriptor set. #[derive(Debug, Clone)] pub enum AccelerationStructureCreationError { diff --git a/vulkano/src/descriptor/descriptor.rs b/vulkano/src/descriptor/descriptor.rs index a16b79cf31..b93e5865b1 100644 --- a/vulkano/src/descriptor/descriptor.rs +++ b/vulkano/src/descriptor/descriptor.rs @@ -225,6 +225,12 @@ impl DescriptorDesc { } } }, + DescriptorDescTy::AccelerationStructure => { + AccessFlagBits { + acceleration_structure_read: true, + ..AccessFlagBits::none() + } + }, }; (stages, access) @@ -253,6 +259,7 @@ pub enum DescriptorDescTy { array_layers: DescriptorImageDescArray, }, Buffer(DescriptorBufferDesc), + AccelerationStructure, } impl DescriptorDescTy { @@ -291,6 +298,7 @@ impl DescriptorDescTy { DescriptorType::UniformTexelBuffer } }, + DescriptorDescTy::AccelerationStructure => DescriptorType::AccelerationStructure, }) } @@ -380,6 +388,8 @@ impl DescriptorDescTy { } }, + (&DescriptorDescTy::AccelerationStructure, &DescriptorDescTy::AccelerationStructure) => Ok(()), + // Any other combination is invalid. _ => Err(DescriptorDescSupersetError::TypeMismatch), } @@ -535,6 +545,7 @@ pub enum DescriptorType { UniformBufferDynamic = vk::DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, StorageBufferDynamic = vk::DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, InputAttachment = vk::DESCRIPTOR_TYPE_INPUT_ATTACHMENT, + AccelerationStructure = vk::DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, } /// Error when checking whether a descriptor is a superset of another one. diff --git a/vulkano/src/descriptor/descriptor_set/fixed_size_pool.rs b/vulkano/src/descriptor/descriptor_set/fixed_size_pool.rs index 7b6d6cb355..f9637154d3 100644 --- a/vulkano/src/descriptor/descriptor_set/fixed_size_pool.rs +++ b/vulkano/src/descriptor/descriptor_set/fixed_size_pool.rs @@ -14,6 +14,7 @@ use std::sync::Arc; use OomError; use VulkanObject; +use acceleration_structure::AccelerationStructure; use buffer::BufferAccess; use buffer::BufferViewRef; use descriptor::descriptor::DescriptorDesc; @@ -555,4 +556,26 @@ impl<'a, R> FixedSizeDescriptorSetBuilderArray<'a, R> inner: self.inner.add_sampler(sampler)?, }) } + + /// Binds an acceleration structure as the next element in the array. + /// + /// An error is returned if the acceleration structure isn't compatible with the descriptor. + /// + /// # Panic + /// + /// Panics if the acceleration structure doesn't have the same device as the descriptor set layout. + /// + pub fn add_acceleration_structure( + self, acceleration_structure: Arc, + ) -> Result< + FixedSizeDescriptorSetBuilderArray<'a, (R, PersistentDescriptorSetAccelerationStructure)>, + PersistentDescriptorSetError, + > { + Ok(FixedSizeDescriptorSetBuilderArray { + pool: self.pool, + inner: self + .inner + .add_acceleration_structure(acceleration_structure)?, + }) + } } diff --git a/vulkano/src/descriptor/descriptor_set/persistent.rs b/vulkano/src/descriptor/descriptor_set/persistent.rs index 48b2fd926d..394021b3fe 100644 --- a/vulkano/src/descriptor/descriptor_set/persistent.rs +++ b/vulkano/src/descriptor/descriptor_set/persistent.rs @@ -15,6 +15,7 @@ use std::sync::Arc; use OomError; use VulkanObject; +use acceleration_structure::AccelerationStructure; use buffer::BufferAccess; use buffer::BufferViewRef; use descriptor::descriptor::DescriptorDesc; @@ -352,6 +353,26 @@ impl PersistentDescriptorSetBuilder PersistentDescriptorSetError> { self.enter_array()?.add_sampler(sampler)?.leave_array() } + + /// Binds an acceleration structure as the next descriptor. + /// + /// An error is returned if the acceleration structure isn't compatible with the descriptor. + /// + /// # Panic + /// + /// Panics if the acceleration structure doesn't have the same device as the descriptor set layout. + /// + #[inline] + pub fn add_acceleration_structure( + self, acceleration_structure: Arc, + ) -> Result< + PersistentDescriptorSetBuilder<(R, PersistentDescriptorSetAccelerationStructure)>, + PersistentDescriptorSetError, + > { + self.enter_array()? + .add_acceleration_structure(acceleration_structure)? + .leave_array() + } } /// Same as `PersistentDescriptorSetBuilder`, but we're in an array. @@ -751,6 +772,64 @@ impl PersistentDescriptorSetBuilderArray array_element: self.array_element + 1, }) } + + /// Binds a Acceleration Structure as the next element in the array. + /// + /// An error is returned if the acceleration structure isn't compatible with the descriptor. + /// + /// # Panic + /// + /// Panics if the acceleration structure doesn't have the same device as the descriptor set layout. + /// + pub fn add_acceleration_structure( + mut self, acceleration_structure: Arc, + ) -> Result< + PersistentDescriptorSetBuilderArray<(R, PersistentDescriptorSetAccelerationStructure)>, + PersistentDescriptorSetError, + > { + assert_eq!( + self.builder.layout.device().internal_object(), + acceleration_structure.device().internal_object() + ); + + if self.array_element as u32 >= self.desc.array_count { + return Err(PersistentDescriptorSetError::ArrayOutOfBounds); + } + + let desc = match self.builder.layout.descriptor(self.builder.binding_id) { + Some(d) => d, + None => return Err(PersistentDescriptorSetError::EmptyExpected), + }; + + self.builder.writes.push(match desc.ty { + DescriptorDescTy::AccelerationStructure => DescriptorWrite::acceleration_structure( + self.builder.binding_id as u32, + self.array_element as u32, + &acceleration_structure, + ), + ty => { + return Err(PersistentDescriptorSetError::WrongDescriptorTy { + expected: ty.ty().unwrap(), + }); + } + }); + + Ok(PersistentDescriptorSetBuilderArray { + builder: PersistentDescriptorSetBuilder { + layout: self.builder.layout, + binding_id: self.builder.binding_id, + writes: self.builder.writes, + resources: ( + self.builder.resources, + PersistentDescriptorSetAccelerationStructure { + acceleration_structure, + }, + ), + }, + desc: self.desc, + array_element: self.array_element + 1, + }) + } } // Checks whether an image view matches the descriptor. @@ -988,6 +1067,35 @@ unsafe impl PersistentDescriptorSetResources for (R, PersistentDescriptorSetS } } +/// Internal object related to the `PersistentDescriptorSetAccelerationStructure` system. +pub struct PersistentDescriptorSetAccelerationStructure { + acceleration_structure: Arc, +} + +unsafe impl PersistentDescriptorSetResources for (R, PersistentDescriptorSetAccelerationStructure) + where R: PersistentDescriptorSetResources +{ + #[inline] + fn num_buffers(&self) -> usize { + self.0.num_buffers() + } + + #[inline] + fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> { + self.0.buffer(index) + } + + #[inline] + fn num_images(&self) -> usize { + self.0.num_images() + } + + #[inline] + fn image(&self, index: usize) -> Option<(&dyn ImageViewAccess, u32)> { + self.0.image(index) + } +} + // Part of the PersistentDescriptorSetError for the case // of missing usage on a buffer. #[derive(Debug, Clone)] @@ -1002,6 +1110,13 @@ pub enum MissingImageUsage { InputAttachment, Sampled, Storage } +// Part of the PersistentDescriptorSetError for the case +// of missing usage on an acceleration structure. +#[derive(Debug, Clone)] +pub enum MissingAccelerationStructureUsage { + AccelerationStructure +} + /// Error related to the persistent descriptor set. #[derive(Debug, Clone)] pub enum PersistentDescriptorSetError { diff --git a/vulkano/src/descriptor/descriptor_set/sys.rs b/vulkano/src/descriptor/descriptor_set/sys.rs index 6da3f7fb93..9325bc2cfe 100644 --- a/vulkano/src/descriptor/descriptor_set/sys.rs +++ b/vulkano/src/descriptor/descriptor_set/sys.rs @@ -13,10 +13,12 @@ use std::error; use std::fmt; use std::mem::MaybeUninit; use std::ops; +use std::os::raw::c_void; use std::ptr; use std::sync::Arc; use std::vec::IntoIter as VecIntoIter; +use acceleration_structure::AccelerationStructure; use buffer::BufferAccess; use buffer::BufferInner; use buffer::BufferView; @@ -104,6 +106,7 @@ macro_rules! descriptors_count { DescriptorType::UniformBufferDynamic => self.uniform_buffer_dynamic += 1, DescriptorType::StorageBufferDynamic => self.storage_buffer_dynamic += 1, DescriptorType::InputAttachment => self.input_attachment += 1, + DescriptorType::AccelerationStructure => self.acceleration_structure += 1, }; } } @@ -220,6 +223,7 @@ descriptors_count! { sampler, combined_image_sampler, input_attachment, + acceleration_structure, } /// Pool from which descriptor sets are allocated from. @@ -281,6 +285,10 @@ impl UnsafeDescriptorPool { elem!(combined_image_sampler, vk::DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); elem!(input_attachment, vk::DESCRIPTOR_TYPE_INPUT_ATTACHMENT); + elem!( + acceleration_structure, + vk::DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + ); assert!(!pool_sizes.is_empty(), "All the descriptors count of a pool are 0"); @@ -585,11 +593,14 @@ impl UnsafeDescriptorSet { let mut buffer_descriptors: SmallVec<[_; 64]> = SmallVec::new(); let mut image_descriptors: SmallVec<[_; 64]> = SmallVec::new(); let mut buffer_views_descriptors: SmallVec<[_; 64]> = SmallVec::new(); + let mut acceleration_structure_descriptions: SmallVec<[_; 64]> = SmallVec::new(); let mut raw_writes: SmallVec<[_; 64]> = SmallVec::new(); + let mut raw_acceleration_structure_writes: SmallVec<[_; 64]> = SmallVec::new(); let mut raw_writes_img_infos: SmallVec<[_; 64]> = SmallVec::new(); let mut raw_writes_buf_infos: SmallVec<[_; 64]> = SmallVec::new(); let mut raw_writes_buf_view_infos: SmallVec<[_; 64]> = SmallVec::new(); + let mut raw_writes_acc_info: SmallVec<[_; 64]> = SmallVec::new(); for indiv_write in writes { // Since the `DescriptorWrite` objects are built only through functions, we know for @@ -610,6 +621,15 @@ impl UnsafeDescriptorSet { pBufferInfo: ptr::null(), pTexelBufferView: ptr::null(), }); + // The ray tracing pNext extension + raw_acceleration_structure_writes.push( + vk::WriteDescriptorSetAccelerationStructureKHR { + sType: vk::STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, + pNext: ptr::null(), + accelerationStructureCount: indiv_write.inner.len() as u32, + pAccelerationStructures: ptr::null(), + }, + ); match indiv_write.inner[0] { DescriptorWriteInner::Sampler(_) | @@ -620,6 +640,7 @@ impl UnsafeDescriptorSet { raw_writes_img_infos.push(Some(image_descriptors.len())); raw_writes_buf_infos.push(None); raw_writes_buf_view_infos.push(None); + raw_writes_acc_info.push(None); }, DescriptorWriteInner::UniformBuffer(_, _, _) | DescriptorWriteInner::StorageBuffer(_, _, _) | @@ -628,12 +649,20 @@ impl UnsafeDescriptorSet { raw_writes_img_infos.push(None); raw_writes_buf_infos.push(Some(buffer_descriptors.len())); raw_writes_buf_view_infos.push(None); + raw_writes_acc_info.push(None); }, DescriptorWriteInner::UniformTexelBuffer(_) | DescriptorWriteInner::StorageTexelBuffer(_) => { raw_writes_img_infos.push(None); raw_writes_buf_infos.push(None); raw_writes_buf_view_infos.push(Some(buffer_views_descriptors.len())); + raw_writes_acc_info.push(None); + }, + DescriptorWriteInner::AccelerationStructure(_) => { + raw_writes_img_infos.push(None); + raw_writes_buf_infos.push(None); + raw_writes_buf_view_infos.push(None); + raw_writes_acc_info.push(Some(acceleration_structure_descriptions.len())); }, } @@ -694,6 +723,9 @@ impl UnsafeDescriptorSet { DescriptorWriteInner::StorageTexelBuffer(view) => { buffer_views_descriptors.push(view); }, + DescriptorWriteInner::AccelerationStructure(acceleration_structure) => { + acceleration_structure_descriptions.push(acceleration_structure); + }, } } } @@ -715,6 +747,19 @@ impl UnsafeDescriptorSet { Some(off) => buffer_views_descriptors.as_ptr().offset(off as isize), None => ptr::null(), }; + + match raw_writes_acc_info[i] { + Some(off) => { + raw_acceleration_structure_writes[i].pAccelerationStructures = + acceleration_structure_descriptions + .as_ptr() + .offset(off as isize); + write.pNext = &raw_acceleration_structure_writes[i] + as *const vk::WriteDescriptorSetAccelerationStructureKHR + as *const c_void; + } + None => {} + }; } // It is forbidden to call `vkUpdateDescriptorSets` with 0 writes, so we need to perform @@ -770,6 +815,7 @@ enum DescriptorWriteInner { DynamicUniformBuffer(vk::Buffer, usize, usize), DynamicStorageBuffer(vk::Buffer, usize, usize), InputAttachment(vk::ImageView, vk::ImageLayout), + AccelerationStructure(vk::AccelerationStructureKHR), } macro_rules! smallvec { @@ -1013,6 +1059,19 @@ impl DescriptorWrite { } } + #[inline] + pub fn acceleration_structure( + binding: u32, array_element: u32, acceleration_structure: &Arc, + ) -> DescriptorWrite { + DescriptorWrite { + binding, + first_array_element: array_element, + inner: smallvec!(DescriptorWriteInner::AccelerationStructure( + acceleration_structure.internal_object() + )), + } + } + /// Returns the type corresponding to this write. #[inline] pub fn ty(&self) -> DescriptorType { @@ -1031,6 +1090,7 @@ impl DescriptorWrite { DescriptorWriteInner::DynamicStorageBuffer(_, _, _) => DescriptorType::StorageBufferDynamic, DescriptorWriteInner::InputAttachment(_, _) => DescriptorType::InputAttachment, + DescriptorWriteInner::AccelerationStructure(_) => DescriptorType::AccelerationStructure, } } } diff --git a/vulkano/src/descriptor/pipeline_layout/limits_check.rs b/vulkano/src/descriptor/pipeline_layout/limits_check.rs index 1fcb2972fb..6d7fdaf63c 100644 --- a/vulkano/src/descriptor/pipeline_layout/limits_check.rs +++ b/vulkano/src/descriptor/pipeline_layout/limits_check.rs @@ -32,6 +32,7 @@ pub fn check_desc_against_limits(desc: &D, limits: Limits) let mut num_sampled_images = Counter::default(); let mut num_storage_images = Counter::default(); let mut num_input_attachments = Counter::default(); + let mut num_acceleration_structures = Counter::default(); for set in 0 .. desc.num_sets() { let num_bindings_in_set = match desc.num_bindings_in_set(set) { @@ -80,6 +81,9 @@ pub fn check_desc_against_limits(desc: &D, limits: Limits) DescriptorType::InputAttachment => { num_input_attachments.increment(descriptor.array_count, &descriptor.stages); }, + DescriptorType::AccelerationStructure => { + num_acceleration_structures.increment(descriptor.array_count, &descriptor.stages); + }, } } } From 1ce3b49c3dba540671867696aa5aa9f5c7f555d8 Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Sat, 25 Apr 2020 16:40:56 +0200 Subject: [PATCH 12/15] ray_tracing_pipeline: Add miss shader --- examples/src/bin/nv-ray-tracing.rs | 30 ++++- .../pipeline/ray_tracing_pipeline/builder.rs | 122 +++++++++++++++--- .../src/pipeline/ray_tracing_pipeline/mod.rs | 4 +- 3 files changed, 137 insertions(+), 19 deletions(-) diff --git a/examples/src/bin/nv-ray-tracing.rs b/examples/src/bin/nv-ray-tracing.rs index 2c37640b97..74df758b51 100644 --- a/examples/src/bin/nv-ray-tracing.rs +++ b/examples/src/bin/nv-ray-tracing.rs @@ -160,7 +160,14 @@ void main() { const vec2 pixelCenter = coord + vec2(0.5); const vec2 inUV = pixelCenter / vec2(gl_LaunchSizeNV.xy); - payload = vec4(inUV.x, inUV.y, 1.0f, 1.0f); + float aspect = float(gl_LaunchSizeNV.x) / gl_LaunchSizeNV.y; + vec3 lower_left_corner = vec3(-aspect, 1.0, -1.0); + vec3 horizontal = vec3(2.0 * aspect, 0.0, 0.0); + vec3 vertical = vec3(0.0, -2.0, 0.0); + vec3 origin = vec3(0.0, 0.0, 0.0); + vec3 direction = normalize(lower_left_corner + inUV.x * horizontal + inUV.y * vertical); + + traceNV(scene, gl_RayFlagsOpaqueNV, 0xFF, 0, 0, 0, origin, 0.001, direction, 1000.0, 0); imageStore(result, coord, payload); } " @@ -168,6 +175,24 @@ void main() { } let rs = rs::Shader::load(device.clone()).unwrap(); + mod ms { + vulkano_shaders::shader! { + ty: "miss", + src: "#version 460 core +#extension GL_NV_ray_tracing : enable + +layout(location = 0) rayPayloadInNV vec4 payload; + +void main() { + vec3 unit_direction = normalize(gl_WorldRayDirectionNV); + float t = 0.5 * (unit_direction.y + 1.0); + payload = vec4(mix(vec3(0.5, 0.7, 1.0), vec3(1.0, 1.0, 1.0), t), 1.0f); +} +" + } + } + let ms = ms::Shader::load(device.clone()).unwrap(); + // We set a limit to the recursion of a ray so that the shader does not run infinitely let max_recursion_depth = 5; @@ -176,6 +201,7 @@ void main() { // We need at least one ray generation shader to describe where rays go // and to store the result of their path tracing .raygen_shader(rs.main_entry_point(), ()) + .miss_shader(ms.main_entry_point(), ()) .build(device.clone()) .unwrap(), ); @@ -222,7 +248,7 @@ void main() { ) .unwrap(); let (miss_shader_binding_table, miss_buffer_future) = ImmutableBuffer::from_iter( - (0..0).map(|_| 5u8), + group_handles[group_handle_size..2 * group_handle_size].iter().copied(), BufferUsage::ray_tracing(), queue.clone(), ) diff --git a/vulkano/src/pipeline/ray_tracing_pipeline/builder.rs b/vulkano/src/pipeline/ray_tracing_pipeline/builder.rs index ff631ecb6e..5b5b1b77da 100644 --- a/vulkano/src/pipeline/ray_tracing_pipeline/builder.rs +++ b/vulkano/src/pipeline/ray_tracing_pipeline/builder.rs @@ -31,18 +31,21 @@ use VulkanObject; /// Prototype for a `RayTracingPipeline`. // TODO: we can optimize this by filling directly the raw vk structs -pub struct RayTracingPipelineBuilder { +pub struct RayTracingPipelineBuilder { nv_extension: bool, raygen_shader: Option<(Rs, Rss)>, + // TODO: Should be a list + miss_shader: Option<(Ms, Mss)>, max_recursion_depth: u32, } -impl RayTracingPipelineBuilder { +impl RayTracingPipelineBuilder { /// Builds a new empty builder using the `nv_ray_tracing` extension. pub(super) fn nv(max_recursion_depth: u32) -> Self { RayTracingPipelineBuilder { nv_extension: true, raygen_shader: None, + miss_shader: None, max_recursion_depth, } } @@ -52,16 +55,20 @@ impl RayTracingPipelineBuilder { RayTracingPipelineBuilder { nv_extension: false, raygen_shader: None, + miss_shader: None, max_recursion_depth, } } } -impl RayTracingPipelineBuilder +impl RayTracingPipelineBuilder where Rs: RayTracingEntryPointAbstract, Rss: SpecializationConstants, Rs::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required + Ms: RayTracingEntryPointAbstract, + Mss: SpecializationConstants, + Ms::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required { /// Builds the ray tracing pipeline, using an inferred a pipeline layout. // TODO: replace Box with a PipelineUnion struct without template params @@ -102,15 +109,28 @@ where let pipeline_layout; // Must be at least one stage with raygen - if let Some(ref raygen_shader) = self.raygen_shader { - pipeline_layout = Box::new( - PipelineLayoutDescTweaks::new( - self.raygen_shader.as_ref().unwrap().0.layout().clone(), - dynamic_buffers.into_iter().cloned(), - ) - .build(device.clone()) - .unwrap(), - ) as Box<_>; // TODO: error + if let Some((ref shader, _)) = self.raygen_shader { + let layout = shader.layout().clone(); + if let Some((ref shader, _)) = self.miss_shader { + let layout = layout.union(shader.layout().clone()); + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } else { + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } } else { return Err(RayTracingPipelineCreationError::NoRaygenShader); } @@ -175,6 +195,31 @@ where pName: self.raygen_shader.as_ref().unwrap().0.name().as_ptr(), pSpecializationInfo: &raygen_shader_specialization as *const _, }; + let miss_shader_specialization = { + let spec_descriptors = Mss::descriptors(); + let constants = &self.miss_shader.as_ref().unwrap().1; + vk::SpecializationInfo { + mapEntryCount: spec_descriptors.len() as u32, + pMapEntries: spec_descriptors.as_ptr() as *const _, + dataSize: mem::size_of_val(constants), + pData: constants as *const Mss as *const _, + } + }; + let miss_stage = vk::PipelineShaderStageCreateInfo { + sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + pNext: ptr::null(), + flags: 0, // reserved + stage: vk::SHADER_STAGE_MISS_BIT_NV, + module: self + .miss_shader + .as_ref() + .unwrap() + .0 + .module() + .internal_object(), + pName: self.miss_shader.as_ref().unwrap().0.name().as_ptr(), + pSpecializationInfo: &miss_shader_specialization as *const _, + }; let (pipeline, group_count) = if self.nv_extension { let mut stages = SmallVec::<[_; 1]>::new(); @@ -192,6 +237,17 @@ where }); stages.push(raygen_stage); + // Miss + groups.push(vk::RayTracingShaderGroupCreateInfoNV { + sType: vk::STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV, + pNext: ptr::null(), + type_: vk::RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV, + generalShader: stages.len() as u32, + closestHitShader: vk::SHADER_UNUSED, + anyHitShader: vk::SHADER_UNUSED, + intersectionShader: vk::SHADER_UNUSED, + }); + stages.push(miss_stage); unsafe { let infos = vk::RayTracingPipelineCreateInfoNV { sType: vk::STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV, @@ -235,6 +291,19 @@ where }); stages.push(raygen_stage); + // Miss + groups.push(vk::RayTracingShaderGroupCreateInfoKHR { + sType: vk::STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR, + pNext: ptr::null(), + type_: vk::RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR, + generalShader: stages.len() as u32, + closestHitShader: vk::SHADER_UNUSED, + anyHitShader: vk::SHADER_UNUSED, + intersectionShader: vk::SHADER_UNUSED, + pShaderGroupCaptureReplayHandle: ptr::null(), // TODO: + }); + stages.push(miss_stage); + let library_info = vk::PipelineLibraryCreateInfoKHR { sType: vk::STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR, pNext: ptr::null(), @@ -294,7 +363,7 @@ where // TODO: add build_with_cache method } -impl RayTracingPipelineBuilder { +impl RayTracingPipelineBuilder { // TODO: add pipeline derivate system /// Adds a raygen shader group to use. @@ -305,7 +374,7 @@ impl RayTracingPipelineBuilder { self, shader: Rs2, specialization_constants: Rss2, - ) -> RayTracingPipelineBuilder + ) -> RayTracingPipelineBuilder where Rs2: RayTracingEntryPointAbstract, Rss2: SpecializationConstants, @@ -314,19 +383,42 @@ impl RayTracingPipelineBuilder { nv_extension: self.nv_extension, max_recursion_depth: self.max_recursion_depth, raygen_shader: Some((shader, specialization_constants)), + miss_shader: self.miss_shader, + } + } + + /// Adds a miss shader group to use. + // TODO: miss_shader should be a list + // TODO: correct specialization constants + #[inline] + pub fn miss_shader( + self, shader: Ms2, specialization_constants: Mss2, + ) -> RayTracingPipelineBuilder + where + Ms2: RayTracingEntryPointAbstract, + Mss2: SpecializationConstants, + { + RayTracingPipelineBuilder { + nv_extension: self.nv_extension, + max_recursion_depth: self.max_recursion_depth, + raygen_shader: self.raygen_shader, + miss_shader: Some((shader, specialization_constants)), } } } -impl Clone for RayTracingPipelineBuilder +impl Clone for RayTracingPipelineBuilder where Rs: Clone, Rss: Clone, + Ms: Clone, + Mss: Clone, { fn clone(&self) -> Self { RayTracingPipelineBuilder { nv_extension: self.nv_extension, raygen_shader: self.raygen_shader.clone(), + miss_shader: self.miss_shader.clone(), max_recursion_depth: self.max_recursion_depth, } } diff --git a/vulkano/src/pipeline/ray_tracing_pipeline/mod.rs b/vulkano/src/pipeline/ray_tracing_pipeline/mod.rs index 611c20e7b7..4cff57e353 100644 --- a/vulkano/src/pipeline/ray_tracing_pipeline/mod.rs +++ b/vulkano/src/pipeline/ray_tracing_pipeline/mod.rs @@ -57,7 +57,7 @@ impl RayTracingPipeline<()> { /// Returns a builder object that you can fill with the various parameters. pub fn nv<'a>( max_recursion_depth: u32, - ) -> RayTracingPipelineBuilder { + ) -> RayTracingPipelineBuilder { RayTracingPipelineBuilder::nv(max_recursion_depth) } @@ -66,7 +66,7 @@ impl RayTracingPipeline<()> { /// Returns a builder object that you can fill with the various parameters. pub fn khr<'a>( max_recursion_depth: u32, - ) -> RayTracingPipelineBuilder { + ) -> RayTracingPipelineBuilder { RayTracingPipelineBuilder::khr(max_recursion_depth) } } From a058267993ff8d6e5add419967f37754494a6687 Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Sat, 25 Apr 2020 21:59:11 +0200 Subject: [PATCH 13/15] ray_tracing_pipeline: Add hit group --- examples/src/bin/nv-ray-tracing.rs | 37 +- vulkano/src/instance/instance.rs | 72 +- .../pipeline/ray_tracing_pipeline/builder.rs | 692 +++++++++++++++--- .../src/pipeline/ray_tracing_pipeline/mod.rs | 38 +- 4 files changed, 722 insertions(+), 117 deletions(-) diff --git a/examples/src/bin/nv-ray-tracing.rs b/examples/src/bin/nv-ray-tracing.rs index 74df758b51..b63e25c4e6 100644 --- a/examples/src/bin/nv-ray-tracing.rs +++ b/examples/src/bin/nv-ray-tracing.rs @@ -193,6 +193,38 @@ void main() { } let ms = ms::Shader::load(device.clone()).unwrap(); + mod cs { + vulkano_shaders::shader! { + ty: "closest_hit", + src: "#version 460 core +#extension GL_NV_ray_tracing : enable + +layout(location = 0) rayPayloadInNV vec4 payload; + +void main() { + payload = vec4(1, 1, 0, 1); +} +" + } + } + let cs = cs::Shader::load(device.clone()).unwrap(); + + mod is { + vulkano_shaders::shader! { + ty: "intersection", + src: "#version 460 core +#extension GL_NV_ray_tracing : enable + +hitAttributeNV bool _unused_but_required; + +void main() { + reportIntersectionNV(0.01, 0); +} +" + } + } + let is = is::Shader::load(device.clone()).unwrap(); + // We set a limit to the recursion of a ray so that the shader does not run infinitely let max_recursion_depth = 5; @@ -202,6 +234,7 @@ void main() { // and to store the result of their path tracing .raygen_shader(rs.main_entry_point(), ()) .miss_shader(ms.main_entry_point(), ()) + .group(RayTracingPipeline::group().closest_hit_shader(cs.main_entry_point(), ()).intersection_shader(is.main_entry_point(), ())) .build(device.clone()) .unwrap(), ); @@ -254,7 +287,9 @@ void main() { ) .unwrap(); let (hit_shader_binding_table, hit_buffer_future) = ImmutableBuffer::from_iter( - (0..0).map(|_| 5u8), + group_handles[2 * group_handle_size..3 * group_handle_size] + .iter() + .copied(), BufferUsage::ray_tracing(), queue.clone(), ) diff --git a/vulkano/src/instance/instance.rs b/vulkano/src/instance/instance.rs index 92fa5292a2..e8f1c509c4 100644 --- a/vulkano/src/instance/instance.rs +++ b/vulkano/src/instance/instance.rs @@ -395,17 +395,45 @@ impl Instance { }; vk.GetPhysicalDeviceProperties2KHR(device, &mut output); - (output.properties, PhysicalDeviceRayTracingProperties { - shaderGroupHandleSize: max(nv_rt_output.shaderGroupHandleSize, khr_rt_output.shaderGroupHandleSize), - maxRecursionDepth: max(nv_rt_output.maxRecursionDepth, khr_rt_output.maxRecursionDepth), - maxShaderGroupStride: max(nv_rt_output.maxShaderGroupStride, khr_rt_output.maxShaderGroupStride), - shaderGroupBaseAlignment: max(nv_rt_output.shaderGroupBaseAlignment, khr_rt_output.shaderGroupBaseAlignment), - maxGeometryCount: max(nv_rt_output.maxGeometryCount, khr_rt_output.maxGeometryCount), - maxInstanceCount: max(nv_rt_output.maxInstanceCount, khr_rt_output.maxInstanceCount), - maxPrimitiveCount: max(nv_rt_output.maxTriangleCount, khr_rt_output.maxPrimitiveCount), - maxDescriptorSetAccelerationStructures: max(nv_rt_output.maxDescriptorSetAccelerationStructures, khr_rt_output.maxDescriptorSetAccelerationStructures), - shaderGroupHandleCaptureReplaySize: khr_rt_output.shaderGroupHandleCaptureReplaySize, - }) + ( + output.properties, + PhysicalDeviceRayTracingProperties { + shader_group_handle_size: max( + nv_rt_output.shaderGroupHandleSize, + khr_rt_output.shaderGroupHandleSize, + ), + max_recursion_depth: max( + nv_rt_output.maxRecursionDepth, + khr_rt_output.maxRecursionDepth, + ), + max_shader_group_stride: max( + nv_rt_output.maxShaderGroupStride, + khr_rt_output.maxShaderGroupStride, + ), + shader_group_base_alignment: max( + nv_rt_output.shaderGroupBaseAlignment, + khr_rt_output.shaderGroupBaseAlignment, + ), + max_geometry_count: max( + nv_rt_output.maxGeometryCount, + khr_rt_output.maxGeometryCount, + ), + max_instance_count: max( + nv_rt_output.maxInstanceCount, + khr_rt_output.maxInstanceCount, + ), + max_primitive_count: max( + nv_rt_output.maxTriangleCount, + khr_rt_output.maxPrimitiveCount, + ), + max_descriptor_set_acceleration_structures: max( + nv_rt_output.maxDescriptorSetAccelerationStructures, + khr_rt_output.maxDescriptorSetAccelerationStructures, + ), + shader_group_handle_capture_replay_size: khr_rt_output + .shaderGroupHandleCaptureReplaySize, + }, + ) }; let queue_families = unsafe { @@ -727,15 +755,15 @@ impl From for InstanceCreationError { #[derive(Default)] struct PhysicalDeviceRayTracingProperties { - shaderGroupHandleSize: u32, - maxRecursionDepth: u32, - maxShaderGroupStride: u32, - shaderGroupBaseAlignment: u32, - maxGeometryCount: u64, - maxInstanceCount: u64, - maxPrimitiveCount: u64, - maxDescriptorSetAccelerationStructures: u32, - shaderGroupHandleCaptureReplaySize: u32, + shader_group_handle_size: u32, + max_recursion_depth: u32, + max_shader_group_stride: u32, + shader_group_base_alignment: u32, + max_geometry_count: u64, + max_instance_count: u64, + max_primitive_count: u64, + max_descriptor_set_acceleration_structures: u32, + shader_group_handle_capture_replay_size: u32, } struct PhysicalDeviceInfos { @@ -1016,13 +1044,13 @@ impl<'a> PhysicalDevice<'a> { /// Returns the size of a shader group handle #[inline] pub fn shader_group_handle_size(&self) -> u32 { - self.infos().properties_ray_tracing.shaderGroupHandleSize + self.infos().properties_ray_tracing.shader_group_handle_size } /// Returns the maximum ray tracing recursion depth for a trace call #[inline] pub fn max_recursion_depth(&self) -> u32 { - self.infos().properties_ray_tracing.maxRecursionDepth + self.infos().properties_ray_tracing.max_recursion_depth } // Internal function to make it easier to get the infos of this device. diff --git a/vulkano/src/pipeline/ray_tracing_pipeline/builder.rs b/vulkano/src/pipeline/ray_tracing_pipeline/builder.rs index 5b5b1b77da..ba9f9df694 100644 --- a/vulkano/src/pipeline/ray_tracing_pipeline/builder.rs +++ b/vulkano/src/pipeline/ray_tracing_pipeline/builder.rs @@ -29,23 +29,140 @@ use check_errors; use vk; use VulkanObject; +pub struct RayTracingPipelineGroupBuilder { + pub closest_hit_shader: Option<(Cs, Css)>, + pub any_hit_shader: Option<(As, Ass)>, + pub intersection_shader: Option<(Is, Iss)>, +} + +impl + RayTracingPipelineGroupBuilder< + EmptyEntryPointDummy, + (), + EmptyEntryPointDummy, + (), + EmptyEntryPointDummy, + (), + > +{ + pub(super) fn new() -> Self { + RayTracingPipelineGroupBuilder { + closest_hit_shader: None, + any_hit_shader: None, + intersection_shader: None, + } + } +} + +impl + RayTracingPipelineGroupBuilder +where + Cs1: RayTracingEntryPointAbstract, + Css1: SpecializationConstants, + Cs1::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required + As1: RayTracingEntryPointAbstract, + Ass1: SpecializationConstants, + As1::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required + Is1: RayTracingEntryPointAbstract, + Iss1: SpecializationConstants, + Is1::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required +{ + /// Adds a closest hit shader to group. + // TODO: correct specialization constants + #[inline] + pub fn closest_hit_shader( + self, + shader: Cs2, + specialization_constants: Css2, + ) -> RayTracingPipelineGroupBuilder + where + Cs2: RayTracingEntryPointAbstract, + Css2: SpecializationConstants, + { + RayTracingPipelineGroupBuilder { + closest_hit_shader: Some((shader, specialization_constants)), + any_hit_shader: self.any_hit_shader, + intersection_shader: self.intersection_shader, + } + } + + /// Adds a any hit shader to group. + // TODO: correct specialization constants + #[inline] + pub fn any_hit_shader( + self, + shader: As2, + specialization_constants: Ass2, + ) -> RayTracingPipelineGroupBuilder + where + As2: RayTracingEntryPointAbstract, + Ass2: SpecializationConstants, + { + RayTracingPipelineGroupBuilder { + closest_hit_shader: self.closest_hit_shader, + any_hit_shader: Some((shader, specialization_constants)), + intersection_shader: self.intersection_shader, + } + } + + /// Adds an intersection shader to group. + // TODO: correct specialization constants + #[inline] + pub fn intersection_shader( + self, + shader: Is2, + specialization_constants: Iss2, + ) -> RayTracingPipelineGroupBuilder + where + Is2: RayTracingEntryPointAbstract, + Iss2: SpecializationConstants, + { + RayTracingPipelineGroupBuilder { + closest_hit_shader: self.closest_hit_shader, + any_hit_shader: self.any_hit_shader, + intersection_shader: Some((shader, specialization_constants)), + } + } +} + /// Prototype for a `RayTracingPipeline`. // TODO: we can optimize this by filling directly the raw vk structs -pub struct RayTracingPipelineBuilder { +pub struct RayTracingPipelineBuilder { nv_extension: bool, + // TODO: Should be a list raygen_shader: Option<(Rs, Rss)>, // TODO: Should be a list miss_shader: Option<(Ms, Mss)>, + // TODO: Should be a list + group: RayTracingPipelineGroupBuilder, max_recursion_depth: u32, } -impl RayTracingPipelineBuilder { +impl + RayTracingPipelineBuilder< + EmptyEntryPointDummy, + (), + EmptyEntryPointDummy, + (), + EmptyEntryPointDummy, + (), + EmptyEntryPointDummy, + (), + EmptyEntryPointDummy, + (), + > +{ /// Builds a new empty builder using the `nv_ray_tracing` extension. pub(super) fn nv(max_recursion_depth: u32) -> Self { RayTracingPipelineBuilder { nv_extension: true, raygen_shader: None, miss_shader: None, + group: RayTracingPipelineGroupBuilder { + closest_hit_shader: None, + any_hit_shader: None, + intersection_shader: None, + }, max_recursion_depth, } } @@ -56,12 +173,18 @@ impl RayTracingPipelineBuilder RayTracingPipelineBuilder +impl + RayTracingPipelineBuilder where Rs: RayTracingEntryPointAbstract, Rss: SpecializationConstants, @@ -69,6 +192,15 @@ where Ms: RayTracingEntryPointAbstract, Mss: SpecializationConstants, Ms::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required + Cs: RayTracingEntryPointAbstract, + Css: SpecializationConstants, + Cs::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required + As: RayTracingEntryPointAbstract, + Ass: SpecializationConstants, + As::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required + Is: RayTracingEntryPointAbstract, + Iss: SpecializationConstants, + Is::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required { /// Builds the ray tracing pipeline, using an inferred a pipeline layout. // TODO: replace Box with a PipelineUnion struct without template params @@ -113,23 +245,191 @@ where let layout = shader.layout().clone(); if let Some((ref shader, _)) = self.miss_shader { let layout = layout.union(shader.layout().clone()); - pipeline_layout = Box::new( - PipelineLayoutDescTweaks::new( - layout, - dynamic_buffers.into_iter().cloned(), - ) - .build(device.clone()) - .unwrap(), - ) as Box<_>; // TODO: error + if let Some((ref shader, _)) = self.group.closest_hit_shader { + let layout = layout.union(shader.layout().clone()); + if let Some((ref shader, _)) = self.group.intersection_shader { + let layout = layout.union(shader.layout().clone()); + if let Some((ref shader, _)) = self.group.any_hit_shader { + let layout = layout.union(shader.layout().clone()); + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } else { + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } + } else { + if let Some((ref shader, _)) = self.group.any_hit_shader { + let layout = layout.union(shader.layout().clone()); + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } else { + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } + } + } else { + if let Some((ref shader, _)) = self.group.intersection_shader { + let layout = layout.union(shader.layout().clone()); + if let Some((ref shader, _)) = self.group.any_hit_shader { + let layout = layout.union(shader.layout().clone()); + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } else { + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } + } else { + if let Some((ref shader, _)) = self.group.any_hit_shader { + let layout = layout.union(shader.layout().clone()); + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } else { + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } + } + } } else { - pipeline_layout = Box::new( - PipelineLayoutDescTweaks::new( - layout, - dynamic_buffers.into_iter().cloned(), - ) - .build(device.clone()) - .unwrap(), - ) as Box<_>; // TODO: error + if let Some((ref shader, _)) = self.group.closest_hit_shader { + let layout = layout.union(shader.layout().clone()); + if let Some((ref shader, _)) = self.group.intersection_shader { + let layout = layout.union(shader.layout().clone()); + if let Some((ref shader, _)) = self.group.any_hit_shader { + let layout = layout.union(shader.layout().clone()); + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } else { + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } + } else { + if let Some((ref shader, _)) = self.group.any_hit_shader { + let layout = layout.union(shader.layout().clone()); + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } else { + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } + } + } else { + if let Some((ref shader, _)) = self.group.intersection_shader { + let layout = layout.union(shader.layout().clone()); + if let Some((ref shader, _)) = self.group.any_hit_shader { + let layout = layout.union(shader.layout().clone()); + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } else { + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } + } else { + if let Some((ref shader, _)) = self.group.any_hit_shader { + let layout = layout.union(shader.layout().clone()); + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } else { + pipeline_layout = Box::new( + PipelineLayoutDescTweaks::new( + layout, + dynamic_buffers.into_iter().cloned(), + ) + .build(device.clone()) + .unwrap(), + ) as Box<_>; // TODO: error + } + } + } } } else { return Err(RayTracingPipelineCreationError::NoRaygenShader); @@ -170,60 +470,129 @@ where let vk = device.pointers(); // Creating the specialization constants of the various stages. - let raygen_shader_specialization = { - let spec_descriptors = Rss::descriptors(); - let constants = &self.raygen_shader.as_ref().unwrap().1; - vk::SpecializationInfo { - mapEntryCount: spec_descriptors.len() as u32, - pMapEntries: spec_descriptors.as_ptr() as *const _, - dataSize: mem::size_of_val(constants), - pData: constants as *const Rss as *const _, + let raygen_stage = { + let raygen_shader_specialization = { + let spec_descriptors = Rss::descriptors(); + let constants = &self.raygen_shader.as_ref().unwrap().1; + vk::SpecializationInfo { + mapEntryCount: spec_descriptors.len() as u32, + pMapEntries: spec_descriptors.as_ptr() as *const _, + dataSize: mem::size_of_val(constants), + pData: constants as *const Rss as *const _, + } + }; + vk::PipelineShaderStageCreateInfo { + sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + pNext: ptr::null(), + flags: 0, // reserved + stage: vk::SHADER_STAGE_RAYGEN_BIT_KHR, + module: self + .raygen_shader + .as_ref() + .unwrap() + .0 + .module() + .internal_object(), + pName: self.raygen_shader.as_ref().unwrap().0.name().as_ptr(), + pSpecializationInfo: &raygen_shader_specialization as *const _, } }; - let raygen_stage = vk::PipelineShaderStageCreateInfo { - sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - pNext: ptr::null(), - flags: 0, // reserved - stage: vk::SHADER_STAGE_RAYGEN_BIT_KHR, - module: self - .raygen_shader - .as_ref() - .unwrap() - .0 - .module() - .internal_object(), - pName: self.raygen_shader.as_ref().unwrap().0.name().as_ptr(), - pSpecializationInfo: &raygen_shader_specialization as *const _, + let miss_stage = match self.miss_shader { + Some((shader, constants)) => { + let specialization = { + let spec_descriptors = Mss::descriptors(); + vk::SpecializationInfo { + mapEntryCount: spec_descriptors.len() as u32, + pMapEntries: spec_descriptors.as_ptr() as *const _, + dataSize: mem::size_of_val(&constants), + pData: &constants as *const Mss as *const _, + } + }; + Some(vk::PipelineShaderStageCreateInfo { + sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + pNext: ptr::null(), + flags: 0, // reserved + stage: vk::SHADER_STAGE_MISS_BIT_KHR, + module: shader.module().internal_object(), + pName: shader.name().as_ptr(), + pSpecializationInfo: &specialization as *const _, + }) + } + None => None, }; - let miss_shader_specialization = { - let spec_descriptors = Mss::descriptors(); - let constants = &self.miss_shader.as_ref().unwrap().1; - vk::SpecializationInfo { - mapEntryCount: spec_descriptors.len() as u32, - pMapEntries: spec_descriptors.as_ptr() as *const _, - dataSize: mem::size_of_val(constants), - pData: constants as *const Mss as *const _, + let closest_hit_stage = match self.group.closest_hit_shader { + Some((shader, constants)) => { + let specialization = { + let spec_descriptors = Css::descriptors(); + vk::SpecializationInfo { + mapEntryCount: spec_descriptors.len() as u32, + pMapEntries: spec_descriptors.as_ptr() as *const _, + dataSize: mem::size_of_val(&constants), + pData: &constants as *const Css as *const _, + } + }; + Some(vk::PipelineShaderStageCreateInfo { + sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + pNext: ptr::null(), + flags: 0, // reserved + stage: vk::SHADER_STAGE_CLOSEST_HIT_BIT_KHR, + module: shader.module().internal_object(), + pName: shader.name().as_ptr(), + pSpecializationInfo: &specialization as *const _, + }) } + None => None, }; - let miss_stage = vk::PipelineShaderStageCreateInfo { - sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - pNext: ptr::null(), - flags: 0, // reserved - stage: vk::SHADER_STAGE_MISS_BIT_NV, - module: self - .miss_shader - .as_ref() - .unwrap() - .0 - .module() - .internal_object(), - pName: self.miss_shader.as_ref().unwrap().0.name().as_ptr(), - pSpecializationInfo: &miss_shader_specialization as *const _, + let any_hit_stage = match self.group.any_hit_shader { + Some((shader, constants)) => { + let specialization = { + let spec_descriptors = Ass::descriptors(); + vk::SpecializationInfo { + mapEntryCount: spec_descriptors.len() as u32, + pMapEntries: spec_descriptors.as_ptr() as *const _, + dataSize: mem::size_of_val(&constants), + pData: &constants as *const Ass as *const _, + } + }; + Some(vk::PipelineShaderStageCreateInfo { + sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + pNext: ptr::null(), + flags: 0, // reserved + stage: vk::SHADER_STAGE_ANY_HIT_BIT_KHR, + module: shader.module().internal_object(), + pName: shader.name().as_ptr(), + pSpecializationInfo: &specialization as *const _, + }) + } + None => None, + }; + let intersection_stage = match self.group.intersection_shader { + Some((shader, constants)) => { + let specialization = { + let spec_descriptors = Iss::descriptors(); + vk::SpecializationInfo { + mapEntryCount: spec_descriptors.len() as u32, + pMapEntries: spec_descriptors.as_ptr() as *const _, + dataSize: mem::size_of_val(&constants), + pData: &constants as *const Iss as *const _, + } + }; + Some(vk::PipelineShaderStageCreateInfo { + sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + pNext: ptr::null(), + flags: 0, // reserved + stage: vk::SHADER_STAGE_INTERSECTION_BIT_KHR, + module: shader.module().internal_object(), + pName: shader.name().as_ptr(), + pSpecializationInfo: &specialization as *const _, + }) + } + None => None, }; let (pipeline, group_count) = if self.nv_extension { - let mut stages = SmallVec::<[_; 1]>::new(); - let mut groups = SmallVec::<[_; 1]>::new(); + let mut stages = SmallVec::<[_; 5]>::new(); + let mut groups = SmallVec::<[_; 5]>::new(); // Raygen groups.push(vk::RayTracingShaderGroupCreateInfoNV { @@ -238,16 +607,66 @@ where stages.push(raygen_stage); // Miss - groups.push(vk::RayTracingShaderGroupCreateInfoNV { - sType: vk::STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV, - pNext: ptr::null(), - type_: vk::RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV, - generalShader: stages.len() as u32, - closestHitShader: vk::SHADER_UNUSED, - anyHitShader: vk::SHADER_UNUSED, - intersectionShader: vk::SHADER_UNUSED, - }); - stages.push(miss_stage); + match miss_stage { + Some(miss_stage) => { + groups.push(vk::RayTracingShaderGroupCreateInfoNV { + sType: vk::STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV, + pNext: ptr::null(), + type_: vk::RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV, + generalShader: stages.len() as u32, + closestHitShader: vk::SHADER_UNUSED, + anyHitShader: vk::SHADER_UNUSED, + intersectionShader: vk::SHADER_UNUSED, + }); + stages.push(miss_stage); + } + None => {} + } + + // Groups + if closest_hit_stage.is_some() + || any_hit_stage.is_some() + || intersection_stage.is_some() + { + let mut info = vk::RayTracingShaderGroupCreateInfoNV { + sType: vk::STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV, + pNext: ptr::null(), + type_: vk::RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV, + generalShader: vk::SHADER_UNUSED, + closestHitShader: vk::SHADER_UNUSED, + anyHitShader: vk::SHADER_UNUSED, + intersectionShader: vk::SHADER_UNUSED, + }; + + match closest_hit_stage { + Some(stage) => { + info.closestHitShader = stages.len() as u32; + stages.push(stage); + } + None => {} + } + + match any_hit_stage { + Some(stage) => { + info.anyHitShader = stages.len() as u32; + stages.push(stage); + } + None => {} + } + + match intersection_stage { + Some(stage) => { + // If there is an intersection stage, then the type is procedural, not triangles + info.type_ = vk::RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV; + info.intersectionShader = stages.len() as u32; + stages.push(stage); + } + None => {} + } + + groups.push(info); + } + unsafe { let infos = vk::RayTracingPipelineCreateInfoNV { sType: vk::STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV, @@ -275,8 +694,8 @@ where (output.assume_init(), groups.len() as u32) } } else { - let mut stages = SmallVec::<[_; 1]>::new(); - let mut groups = SmallVec::<[_; 1]>::new(); + let mut stages = SmallVec::<[_; 5]>::new(); + let mut groups = SmallVec::<[_; 5]>::new(); // Raygen groups.push(vk::RayTracingShaderGroupCreateInfoKHR { @@ -292,17 +711,67 @@ where stages.push(raygen_stage); // Miss - groups.push(vk::RayTracingShaderGroupCreateInfoKHR { - sType: vk::STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR, - pNext: ptr::null(), - type_: vk::RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR, - generalShader: stages.len() as u32, - closestHitShader: vk::SHADER_UNUSED, - anyHitShader: vk::SHADER_UNUSED, - intersectionShader: vk::SHADER_UNUSED, - pShaderGroupCaptureReplayHandle: ptr::null(), // TODO: - }); - stages.push(miss_stage); + match miss_stage { + Some(miss_stage) => { + groups.push(vk::RayTracingShaderGroupCreateInfoKHR { + sType: vk::STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR, + pNext: ptr::null(), + type_: vk::RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR, + generalShader: stages.len() as u32, + closestHitShader: vk::SHADER_UNUSED, + anyHitShader: vk::SHADER_UNUSED, + intersectionShader: vk::SHADER_UNUSED, + pShaderGroupCaptureReplayHandle: ptr::null(), // TODO: + }); + stages.push(miss_stage); + } + None => {} + } + + // Groups + if closest_hit_stage.is_some() + || any_hit_stage.is_some() + || intersection_stage.is_some() + { + let mut info = vk::RayTracingShaderGroupCreateInfoKHR { + sType: vk::STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR, + pNext: ptr::null(), + type_: vk::RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR, + generalShader: vk::SHADER_UNUSED, + closestHitShader: vk::SHADER_UNUSED, + anyHitShader: vk::SHADER_UNUSED, + intersectionShader: vk::SHADER_UNUSED, + pShaderGroupCaptureReplayHandle: ptr::null(), // TODO: + }; + + match closest_hit_stage { + Some(stage) => { + info.closestHitShader = stages.len() as u32; + stages.push(stage); + } + None => {} + } + + match any_hit_stage { + Some(stage) => { + info.anyHitShader = stages.len() as u32; + stages.push(stage); + } + None => {} + } + + match intersection_stage { + Some(stage) => { + // If there is an intersection stage, then the type is procedural, not triangles + info.type_ = vk::RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR; + info.intersectionShader = stages.len() as u32; + stages.push(stage); + } + None => {} + } + + groups.push(info); + } let library_info = vk::PipelineLibraryCreateInfoKHR { sType: vk::STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR, @@ -363,7 +832,9 @@ where // TODO: add build_with_cache method } -impl RayTracingPipelineBuilder { +impl + RayTracingPipelineBuilder +{ // TODO: add pipeline derivate system /// Adds a raygen shader group to use. @@ -374,7 +845,7 @@ impl RayTracingPipelineBuilder { self, shader: Rs2, specialization_constants: Rss2, - ) -> RayTracingPipelineBuilder + ) -> RayTracingPipelineBuilder where Rs2: RayTracingEntryPointAbstract, Rss2: SpecializationConstants, @@ -384,6 +855,7 @@ impl RayTracingPipelineBuilder { max_recursion_depth: self.max_recursion_depth, raygen_shader: Some((shader, specialization_constants)), miss_shader: self.miss_shader, + group: self.group, } } @@ -393,7 +865,7 @@ impl RayTracingPipelineBuilder { #[inline] pub fn miss_shader( self, shader: Ms2, specialization_constants: Mss2, - ) -> RayTracingPipelineBuilder + ) -> RayTracingPipelineBuilder where Ms2: RayTracingEntryPointAbstract, Mss2: SpecializationConstants, @@ -403,22 +875,58 @@ impl RayTracingPipelineBuilder { max_recursion_depth: self.max_recursion_depth, raygen_shader: self.raygen_shader, miss_shader: Some((shader, specialization_constants)), + group: self.group, + } + } + + /// Add a ray tracing group + #[inline] + pub fn group( + self, + group: RayTracingPipelineGroupBuilder, + ) -> RayTracingPipelineBuilder + where + Cs2: RayTracingEntryPointAbstract, + Css2: SpecializationConstants, + As2: RayTracingEntryPointAbstract, + Ass2: SpecializationConstants, + Is2: RayTracingEntryPointAbstract, + Iss2: SpecializationConstants, + { + RayTracingPipelineBuilder { + nv_extension: self.nv_extension, + max_recursion_depth: self.max_recursion_depth, + raygen_shader: self.raygen_shader, + miss_shader: self.miss_shader, + group, } } } -impl Clone for RayTracingPipelineBuilder +impl Clone + for RayTracingPipelineBuilder where Rs: Clone, Rss: Clone, Ms: Clone, Mss: Clone, + Cs: Clone, + Css: Clone, + As: Clone, + Ass: Clone, + Is: Clone, + Iss: Clone, { fn clone(&self) -> Self { RayTracingPipelineBuilder { nv_extension: self.nv_extension, raygen_shader: self.raygen_shader.clone(), miss_shader: self.miss_shader.clone(), + group: RayTracingPipelineGroupBuilder { + closest_hit_shader: self.group.closest_hit_shader.clone(), + any_hit_shader: self.group.any_hit_shader.clone(), + intersection_shader: self.group.intersection_shader.clone(), + }, max_recursion_depth: self.max_recursion_depth, } } diff --git a/vulkano/src/pipeline/ray_tracing_pipeline/mod.rs b/vulkano/src/pipeline/ray_tracing_pipeline/mod.rs index 4cff57e353..bbb68ace66 100644 --- a/vulkano/src/pipeline/ray_tracing_pipeline/mod.rs +++ b/vulkano/src/pipeline/ray_tracing_pipeline/mod.rs @@ -27,6 +27,7 @@ use VulkanObject; pub use self::builder::RayTracingPipelineBuilder; pub use self::creation_error::RayTracingPipelineCreationError; +use pipeline::ray_tracing_pipeline::builder::RayTracingPipelineGroupBuilder; mod builder; mod creation_error; @@ -57,7 +58,18 @@ impl RayTracingPipeline<()> { /// Returns a builder object that you can fill with the various parameters. pub fn nv<'a>( max_recursion_depth: u32, - ) -> RayTracingPipelineBuilder { + ) -> RayTracingPipelineBuilder< + EmptyEntryPointDummy, + (), + EmptyEntryPointDummy, + (), + EmptyEntryPointDummy, + (), + EmptyEntryPointDummy, + (), + EmptyEntryPointDummy, + (), + > { RayTracingPipelineBuilder::nv(max_recursion_depth) } @@ -66,9 +78,31 @@ impl RayTracingPipeline<()> { /// Returns a builder object that you can fill with the various parameters. pub fn khr<'a>( max_recursion_depth: u32, - ) -> RayTracingPipelineBuilder { + ) -> RayTracingPipelineBuilder< + EmptyEntryPointDummy, + (), + EmptyEntryPointDummy, + (), + EmptyEntryPointDummy, + (), + EmptyEntryPointDummy, + (), + EmptyEntryPointDummy, + (), + > { RayTracingPipelineBuilder::khr(max_recursion_depth) } + + pub fn group<'a>() -> RayTracingPipelineGroupBuilder< + EmptyEntryPointDummy, + (), + EmptyEntryPointDummy, + (), + EmptyEntryPointDummy, + (), + > { + RayTracingPipelineGroupBuilder::new() + } } impl RayTracingPipeline { From 0a5b4da375521c4033eaac372cdfec454b3522ab Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Mon, 27 Apr 2020 19:51:02 +0200 Subject: [PATCH 14/15] examples: make intersection shader into sdf Use storage buffer for AABBs. Make procedural geometry using ray marching for a signed distance function. --- examples/src/bin/nv-ray-tracing.rs | 159 +++++++++++++++++++++++++++-- 1 file changed, 148 insertions(+), 11 deletions(-) diff --git a/examples/src/bin/nv-ray-tracing.rs b/examples/src/bin/nv-ray-tracing.rs index b63e25c4e6..8a002010b0 100644 --- a/examples/src/bin/nv-ray-tracing.rs +++ b/examples/src/bin/nv-ray-tracing.rs @@ -40,6 +40,7 @@ use winit::event_loop::{ControlFlow, EventLoop}; use winit::window::WindowBuilder; use std::sync::Arc; +use std::time::Instant; fn main() { let required_extensions = vulkano_win::required_extensions(); @@ -68,6 +69,7 @@ fn main() { khr_swapchain: true, khr_get_memory_requirements2: true, nv_ray_tracing: true, + khr_storage_buffer_storage_class: true, ..DeviceExtensions::none() }; let (device, mut queues) = Device::new( @@ -133,7 +135,10 @@ fn main() { ] .iter() .cloned(), - BufferUsage::ray_tracing(), + BufferUsage { + storage_buffer: true, + ..BufferUsage::none() + }, queue.clone(), ) .unwrap() @@ -153,7 +158,13 @@ fn main() { layout(set = 0, binding = 0, rgba8) uniform image2D result; layout(set = 0, binding = 1) uniform accelerationStructureNV scene; -layout(location = 0) rayPayloadNV vec4 payload; + +struct payload_t { + vec3 color; + uint recursion_depth; +}; + +layout(location = 0) rayPayloadNV payload_t payload; void main() { ivec2 coord = ivec2(gl_LaunchIDNV); @@ -167,8 +178,9 @@ void main() { vec3 origin = vec3(0.0, 0.0, 0.0); vec3 direction = normalize(lower_left_corner + inUV.x * horizontal + inUV.y * vertical); + payload.recursion_depth = 0; traceNV(scene, gl_RayFlagsOpaqueNV, 0xFF, 0, 0, 0, origin, 0.001, direction, 1000.0, 0); - imageStore(result, coord, payload); + imageStore(result, coord, vec4(payload.color, 1.0)); } " } @@ -181,12 +193,17 @@ void main() { src: "#version 460 core #extension GL_NV_ray_tracing : enable -layout(location = 0) rayPayloadInNV vec4 payload; +struct payload_t { + vec3 color; + uint recursion_depth; +}; + +layout(location = 0) rayPayloadInNV payload_t payload; void main() { vec3 unit_direction = normalize(gl_WorldRayDirectionNV); float t = 0.5 * (unit_direction.y + 1.0); - payload = vec4(mix(vec3(0.5, 0.7, 1.0), vec3(1.0, 1.0, 1.0), t), 1.0f); + payload.color = mix(vec3(0.5, 0.7, 1.0), vec3(1.0, 1.0, 1.0), t); } " } @@ -199,10 +216,29 @@ void main() { src: "#version 460 core #extension GL_NV_ray_tracing : enable -layout(location = 0) rayPayloadInNV vec4 payload; +layout(set = 0, binding = 1) uniform accelerationStructureNV scene; + +struct payload_t { + vec3 color; + uint recursion_depth; +}; + +layout(location = 0) rayPayloadInNV payload_t payload; + +struct hit_record_t { + vec3 position; + vec3 normal; +}; +hitAttributeNV hit_record_t hit_record; void main() { - payload = vec4(1, 1, 0, 1); + payload.recursion_depth++; + if (payload.recursion_depth < 15) { + vec3 target = reflect(gl_WorldRayDirectionNV, hit_record.normal); + vec3 origin = hit_record.position + 0.001 * hit_record.normal; + traceNV(scene, gl_RayFlagsOpaqueNV, 0xFF, 0, 0, 0, origin, 0.001, target, 1000.0, 0); + payload.color *= 0.9f; + } } " } @@ -215,10 +251,101 @@ void main() { src: "#version 460 core #extension GL_NV_ray_tracing : enable -hitAttributeNV bool _unused_but_required; +struct Aabb { + float min_x; + float min_y; + float min_z; + float max_x; + float max_y; + float max_z; +}; + +layout(set = 0, binding = 2) readonly buffer AabbArray { Aabb[] aabbs; }; + +layout(push_constant) uniform PushConstants { + float time; +} push_constants; + +struct hit_record_t { + vec3 position; + vec3 normal; +}; +hitAttributeNV hit_record_t hit_record; + +const uint MAX_STEPS = 100; +const uint MAX_REFINE_STEPS = 4; +const float MIN_DISTANCE = 1e-6f; +const float MIN_STEP_SIZE = 0.5f; +float CUBE_SIDES = 0.45f; +float SPHERE_RADIUS = 0.55f; +float GRAD_STEP = 0.01f; + +float sphere_sdf(vec3 point, float radius) { + return length(point) - radius; +} + +float box_sdf(vec3 point, vec3 sides) { + vec3 q = abs(point) - sides; + return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0); +} + +vec3 twist_point(vec3 point, float amount) { + float c = cos(amount * point.y); + float s = sin(amount * point.y); + mat2 m = mat2(c, -s, s, c); + return vec3(m * point.xz, point.y); +} + +float signed_distance_function(vec3 point, vec3 size) { + vec3 twisted = twist_point(point, sin(push_constants.time) * (2 * gl_PrimitiveID - 1)); + return max(box_sdf(twisted, size * CUBE_SIDES), -sphere_sdf(point, min(size.x, min(size.y, size.z)) * SPHERE_RADIUS)); +} void main() { - reportIntersectionNV(0.01, 0); + vec3 aabb_min = vec3(aabbs[gl_PrimitiveID].min_x, aabbs[gl_PrimitiveID].min_y, aabbs[gl_PrimitiveID].min_z); + vec3 aabb_max = vec3(aabbs[gl_PrimitiveID].max_x, aabbs[gl_PrimitiveID].max_y, aabbs[gl_PrimitiveID].max_z); + vec3 center = (aabb_min + aabb_max) * 0.5; + vec3 size = aabb_max - aabb_min; + + float t = gl_RayTminNV; // TODO: start stepping at bounding box + float t_max = gl_RayTmaxNV; // TODO: stop stepping when out of the bb + float distance = gl_RayTmaxNV; + float step_size = 0.0f; + // Ray march + for (uint i = 0; i < MAX_STEPS; ++i) { + distance = signed_distance_function(gl_ObjectRayOriginNV + gl_ObjectRayDirectionNV * t - center, size); + // Ray has marched close enough to object, register a hit here + if (distance < MIN_DISTANCE) { + break; + } + // Not close enough, step forward + step_size = min(abs(distance), MIN_STEP_SIZE); + t += step_size; + // Ray has marched too far without any hits, register no hits + if (t > t_max) { + break; + } + } + // Ray has hit something + if (distance < MIN_DISTANCE) { + // refine the value for t by stepping back and taking smaller steps + t -= step_size; + for (uint i = 0; i < MAX_REFINE_STEPS; ++i) { + step_size *= 0.5; + distance = signed_distance_function(gl_ObjectRayOriginNV + gl_ObjectRayDirectionNV * t - center, size); + if (distance >= MIN_DISTANCE) { + t += step_size; + } + } + vec3 dx = vec3(GRAD_STEP, 0.0, 0.0); + vec3 dy = vec3(0.0, GRAD_STEP, 0.0); + vec3 dz = vec3(0.0, 0.0, GRAD_STEP); + hit_record.position = gl_ObjectRayOriginNV + gl_ObjectRayDirectionNV * t - center; + hit_record.normal = normalize(vec3(signed_distance_function(hit_record.position + dx, size) - signed_distance_function(hit_record.position - dx, size), + signed_distance_function(hit_record.position + dy, size) - signed_distance_function(hit_record.position - dy, size), + signed_distance_function(hit_record.position + dz, size) - signed_distance_function(hit_record.position - dz, size))); + reportIntersectionNV(t, 0); + } } " } @@ -226,7 +353,7 @@ void main() { let is = is::Shader::load(device.clone()).unwrap(); // We set a limit to the recursion of a ray so that the shader does not run infinitely - let max_recursion_depth = 5; + let max_recursion_depth = 15; let pipeline = Arc::new( RayTracingPipeline::nv(max_recursion_depth) @@ -260,6 +387,8 @@ void main() { .unwrap() .add_acceleration_structure(acceleration_structure.clone()) .unwrap() + .add_buffer(aabb_buffer.clone()) + .unwrap() .build() .unwrap(), ) @@ -313,6 +442,7 @@ void main() { let mut recreate_swapchain = false; let mut previous_frame_end = Some(Box::new(sync::now(device.clone())) as Box); + let time_start = Instant::now(); event_loop.run(move |event, _, control_flow| match event { Event::WindowEvent { event: WindowEvent::CloseRequested, @@ -349,6 +479,8 @@ void main() { .unwrap() .add_acceleration_structure(acceleration_structure.clone()) .unwrap() + .add_buffer(aabb_buffer.clone()) + .unwrap() .build() .unwrap(), ) @@ -384,7 +516,12 @@ void main() { callable_shader_binding_table.clone(), [swapchain.dimensions()[0], swapchain.dimensions()[1], 1], sets[image_num].clone(), - (), + is::ty::PushConstants { + time: { + let elapsed = time_start.elapsed(); + elapsed.as_secs() as f32 + elapsed.subsec_nanos() as f32 / 1e9 + }, + }, ) .unwrap() .build() From 507d330f7daa552f50d3fa8e887b68f68abf2731 Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Tue, 28 Apr 2020 21:11:46 +0200 Subject: [PATCH 15/15] acceleration structure: Implement adding triangles --- vulkano/src/acceleration_structure.rs | 158 ++++++++++++++++++++++---- 1 file changed, 138 insertions(+), 20 deletions(-) diff --git a/vulkano/src/acceleration_structure.rs b/vulkano/src/acceleration_structure.rs index 46a2f93523..befe7527eb 100644 --- a/vulkano/src/acceleration_structure.rs +++ b/vulkano/src/acceleration_structure.rs @@ -103,12 +103,21 @@ impl AccelerationStructure { } } +struct AccelerationStructureBuilderTriangles { + vertex_buffer: Arc, + vertex_stride: vk::DeviceSize, + vertex_format: Format, + index_buffer: Arc, + index_type: IndexType, +} + /// Prototype of a `AccelerationStructure`. /// /// See the docs of `AccelerationStructure` for an example. pub struct AccelerationStructureBuilder { nv_extension: bool, // TODO: Associate `BuildAccelerationStructureFlags` + triangles: Vec, aabbs: Vec>, } @@ -117,6 +126,7 @@ impl AccelerationStructureBuilder { pub fn nv() -> Self { AccelerationStructureBuilder { nv_extension: true, + triangles: vec![], aabbs: vec![], } } @@ -125,6 +135,7 @@ impl AccelerationStructureBuilder { pub fn khr() -> Self { AccelerationStructureBuilder { nv_extension: false, + triangles: vec![], aabbs: vec![], } } @@ -193,6 +204,45 @@ impl AccelerationStructureBuilder { flags: vk::GEOMETRY_OPAQUE_BIT_NV, // TODO } }) + .chain(self.triangles.into_iter().map(|ref triangle| { + let index_stride = match triangle.index_type { + IndexType::U16 => size_of::(), + IndexType::U32 => size_of::(), + }; + let geometry = vk::GeometryTrianglesNV { + sType: vk::STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV, + pNext: ptr::null(), + vertexData: triangle.vertex_buffer.inner().buffer.internal_object(), + vertexOffset: triangle.vertex_buffer.inner().offset as vk::DeviceSize, + vertexCount: (triangle.vertex_buffer.size() / triangle.vertex_stride as usize) + as u32, + vertexStride: triangle.vertex_stride, + vertexFormat: triangle.vertex_format as u32, + indexData: triangle.index_buffer.inner().buffer.internal_object(), + indexOffset: triangle.index_buffer.inner().offset as vk::DeviceSize, + indexCount: (triangle.index_buffer.size() / index_stride as usize) as u32, + indexType: triangle.index_type as u32, + transformData: vk::NULL_HANDLE, + transformOffset: 0, + }; + vk::GeometryNV { + sType: vk::STRUCTURE_TYPE_GEOMETRY_NV, + pNext: ptr::null(), + geometryType: vk::GEOMETRY_TYPE_TRIANGLES_NV, + geometry: vk::GeometryDataNV { + triangles: geometry, + aabbs: vk::GeometryAABBNV { + sType: vk::STRUCTURE_TYPE_GEOMETRY_AABB_NV, + pNext: ptr::null(), + aabbData: 0, + numAABBs: 0, + stride: 0, + offset: 0, + }, + }, + flags: vk::GEOMETRY_OPAQUE_BIT_NV, // TODO + } + })) .collect(); let bottom_level = { @@ -388,7 +438,8 @@ impl AccelerationStructureBuilder { .iter() .map(|structure| unsafe { let info = vk::AccelerationStructureMemoryRequirementsInfoNV { - sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV, + sType: + vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV, pNext: ptr::null(), type_: vk::ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV, accelerationStructure: structure.inner_object, @@ -467,7 +518,23 @@ impl AccelerationStructureBuilder { allowsTransforms: vk::FALSE, } }) - .collect(); + .chain(self.triangles.iter().map(|ref triangle| { + let index_stride = match triangle.index_type { + IndexType::U16 => size_of::(), + IndexType::U32 => size_of::(), + }; + vk::AccelerationStructureCreateGeometryTypeInfoKHR { + sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR, + pNext: ptr::null(), + geometryType: vk::GEOMETRY_TYPE_TRIANGLES_KHR, + maxPrimitiveCount: (triangle.index_buffer.size() / index_stride as usize) as u32 / 3, + indexType: triangle.index_type as u32, + maxVertexCount: (triangle.vertex_buffer.size() / triangle.vertex_stride as usize) as u32, + vertexFormat: triangle.vertex_format as u32, + allowsTransforms: vk::FALSE, // TODO + } + })) + .collect(); let create_info = vk::AccelerationStructureCreateInfoKHR { sType: vk::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR, pNext: ptr::null(), @@ -511,7 +578,36 @@ impl AccelerationStructureBuilder { no_duplicate_any_hit_invocation: false, }, } - }).collect(), + }) + .chain(self.triangles.into_iter().map(|triangle|{ + let index_stride = match triangle.index_type { + IndexType::U16 => size_of::(), + IndexType::U32 => size_of::(), + }; + Geometry { + geometry_type: GeometryType::Triangles, + geometry: GeometryData { + triangles: GeometryTrianglesData { + vertex_data: triangle.vertex_buffer.inner().buffer.internal_object(), + vertex_offset: triangle.vertex_buffer.inner().offset as vk::DeviceSize, + vertex_count: (triangle.vertex_buffer.size() / triangle.vertex_stride as usize) as u32, + vertex_stride: triangle.vertex_stride as usize, + vertex_format: triangle.vertex_format, + index_data: triangle.index_buffer.inner().buffer.internal_object(), + index_offset: triangle.index_buffer.inner().offset as vk::DeviceSize, + index_count: (triangle.index_buffer.size() / index_stride as usize) as u32, + index_type: triangle.index_type, + transform_data: vk::NULL_HANDLE, + transform_offset: 0, + }, + }, + flags: GeometryFlags { + opaque: true, + no_duplicate_any_hit_invocation: false, + }, + } + })) + .collect(), } }; @@ -730,14 +826,26 @@ impl AccelerationStructureBuilder { /// Add a Triangle Mesh to the acceleration structure #[inline] - pub fn add_triangles( - mut self, buffer: T, + pub fn add_triangles( + mut self, + vertex_buffer: Arc, + vertex_stride: vk::DeviceSize, + vertex_format: Format, + index_buffer: Arc, + index_type: IndexType, ) -> Result where - T: BufferAccess + Send + Sync + 'static, + V: BufferAccess + Send + Sync + 'static, + I: BufferAccess + Send + Sync + 'static, { - // TODO - unimplemented!("Adding triangles is not yet implemented") + self.triangles.push(AccelerationStructureBuilderTriangles { + vertex_buffer, + vertex_stride, + vertex_format, + index_buffer, + index_type, + }); + Ok(self) } /// Add Custom Intersection Geometry to the acceleration structure @@ -904,12 +1012,17 @@ pub enum GeometryType { #[derive(Copy, Clone)] pub struct GeometryTrianglesData { - pub vertex_format: Format, pub vertex_data: u64, + pub vertex_offset: vk::DeviceSize, + pub vertex_count: u32, pub vertex_stride: usize, - pub index_type: IndexType, + pub vertex_format: Format, pub index_data: u64, + pub index_offset: vk::DeviceSize, + pub index_count: u32, + pub index_type: IndexType, pub transform_data: u64, + pub transform_offset: vk::DeviceSize, } #[derive(Copy, Clone)] @@ -950,19 +1063,24 @@ impl<'a> From<&'a vk::GeometryNV> for Geometry { let geometry = match geometry_nv.geometryType { vk::GEOMETRY_TYPE_TRIANGLES_KHR => GeometryData { triangles: GeometryTrianglesData { + vertex_data: geometry_nv.geometry.triangles.vertexData, + vertex_offset: geometry_nv.geometry.triangles.vertexOffset, + vertex_count: geometry_nv.geometry.triangles.vertexCount, + vertex_stride: geometry_nv.geometry.triangles.vertexStride as usize, vertex_format: Format::from_vulkan_num( geometry_nv.geometry.triangles.vertexFormat, ) .unwrap(), - vertex_data: geometry_nv.geometry.triangles.vertexData, - vertex_stride: geometry_nv.geometry.triangles.vertexStride as usize, + index_data: geometry_nv.geometry.triangles.indexData, + index_offset: geometry_nv.geometry.triangles.indexOffset, + index_count: geometry_nv.geometry.triangles.indexCount, index_type: match geometry_nv.geometry.triangles.indexType { vk::INDEX_TYPE_UINT16 => IndexType::U16, vk::INDEX_TYPE_UINT32 => IndexType::U32, _ => unreachable!(), }, - index_data: geometry_nv.geometry.triangles.indexData, transform_data: geometry_nv.geometry.triangles.transformData, + transform_offset: geometry_nv.geometry.triangles.transformOffset, }, }, vk::GEOMETRY_TYPE_AABBS_KHR => GeometryData { @@ -1006,19 +1124,19 @@ impl<'a> From<&'a Geometry> for vk::GeometryNV { sType: vk::STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV, pNext: ptr::null(), vertexData: geometry.geometry.triangles.vertex_data, - vertexOffset: 0, // TODO: - vertexCount: 0, // TODO: + vertexOffset: geometry.geometry.triangles.vertex_offset, + vertexCount: geometry.geometry.triangles.vertex_count, vertexStride: geometry.geometry.triangles.vertex_stride as vk::DeviceSize, vertexFormat: geometry.geometry.triangles.vertex_format as u32, indexData: geometry.geometry.triangles.index_data, - indexOffset: 0, // TODO: - indexCount: 0, // TODO: + indexOffset: geometry.geometry.triangles.index_offset, + indexCount: geometry.geometry.triangles.index_count, indexType: match geometry.geometry.triangles.index_type { IndexType::U16 => vk::INDEX_TYPE_UINT16, IndexType::U32 => vk::INDEX_TYPE_UINT32, }, transformData: geometry.geometry.triangles.transform_data, - transformOffset: 0, // TODO: + transformOffset: geometry.geometry.triangles.transform_offset, }, aabbs: vk::GeometryAABBNV { sType: vk::STRUCTURE_TYPE_GEOMETRY_AABB_NV, @@ -1116,7 +1234,7 @@ impl Drop for AccelerationStructure { ); vk.DestroyAccelerationStructureNV( self.device.internal_object(), - self.aabb_bottom_level.inner_object, + self.bottom_level.inner_object, ptr::null(), ); } else { @@ -1127,7 +1245,7 @@ impl Drop for AccelerationStructure { ); vk.DestroyAccelerationStructureKHR( self.device.internal_object(), - self.aabb_bottom_level.inner_object, + self.bottom_level.inner_object, ptr::null(), ); }