| /* Copyright (c) 2025 The Khronos Group Inc. |
| * Copyright (c) 2025 Valve Corporation |
| * Copyright (c) 2025 LunarG, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "../framework/sync_val_tests.h" |
| #include "../framework/pipeline_helper.h" |
| #include "../framework/ray_tracing_objects.h" |
| |
| struct NegativeSyncValRayTracing : public VkSyncValTest {}; |
| |
| TEST_F(NegativeSyncValRayTracing, ScratchBufferHazard) { |
| TEST_DESCRIPTION("Write to scratch buffer during acceleration structure build"); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| if (IsPlatformMockICD()) { |
| GTEST_SKIP() << "Test not supported by MockICD: buffer device address consistent support across different functions"; |
| } |
| |
| vkt::as::BuildGeometryInfoKHR blas = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| blas.SetDeviceScratchAdditionalFlags(VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| const vkt::Buffer& scratch_buffer = *blas.GetScratchBuffer(); |
| |
| m_command_buffer.Begin(); |
| blas.BuildCmdBuffer(m_command_buffer); |
| |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-WRITE"); |
| vk::CmdFillBuffer(m_command_buffer, scratch_buffer, 0, sizeof(uint32_t), 0x42); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, AccelerationStructureBufferHazard) { |
| TEST_DESCRIPTION("Write to accelerationn structure buffer during acceleration structure build"); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| vkt::as::BuildGeometryInfoKHR blas = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| blas.GetDstAS()->SetBufferUsageFlags(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| blas.SetupBuild(true); |
| |
| const vkt::Buffer& accel_buffer = blas.GetDstAS()->GetBuffer(); |
| vkt::Buffer copy_buffer(*m_device, accel_buffer.CreateInfo().size, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.Copy(accel_buffer, copy_buffer); // READ acceleration structure |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-READ"); |
| blas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); // WRITE without proper barrier |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, SourceAccelerationStructureHazard) { |
| TEST_DESCRIPTION("Use acceleration structure as a source during update (READ) while it is still being built (WRITE)"); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| auto blas = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| blas.AddFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR); |
| blas.SetupBuild(true); |
| |
| auto blas2 = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| blas2.AddFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR); |
| blas2.SetMode(VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR); |
| blas2.SetSrcAS(blas.GetDstAS()); |
| blas2.SetupBuild(true); |
| |
| m_command_buffer.Begin(); |
| blas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-READ-AFTER-WRITE"); |
| blas2.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, WriteVertexDataDuringBuild) { |
| TEST_DESCRIPTION("Use vertex buffer as a copy destination while it is used by the AS build operation"); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| auto geometry = vkt::as::blueprint::GeometrySimpleOnDeviceIndexedTriangleInfo(*m_device, 1, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| auto blas = vkt::as::blueprint::BuildGeometryInfoOnDeviceBottomLevel(*m_device, std::move(geometry)); |
| const auto& triangles_geometry = blas.GetGeometries()[0].GetTriangles(); |
| const vkt::Buffer& vertex_buffer = triangles_geometry.device_vertex_buffer; |
| blas.SetupBuild(true); |
| |
| vkt::Buffer src_buffer(*m_device, 4, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| VkBufferCopy region{}; |
| region.size = 4; |
| |
| // Test validation |
| m_command_buffer.Begin(); |
| vk::CmdCopyBuffer(m_command_buffer, src_buffer, vertex_buffer, 1, ®ion); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-READ-AFTER-WRITE"); |
| blas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| |
| // Test access update (that copy can see previous AS access) |
| m_command_buffer.Begin(); |
| blas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-READ"); |
| vk::CmdCopyBuffer(m_command_buffer, src_buffer, vertex_buffer, 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, WriteVertexDataDuringBuild2) { |
| TEST_DESCRIPTION("Use vertex buffer for non-indexed geometry as a copy destination while it is used by the AS build operation"); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| auto geometry = vkt::as::blueprint::GeometrySimpleOnDeviceTriangleInfo(*m_device, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| auto blas = vkt::as::blueprint::BuildGeometryInfoOnDeviceBottomLevel(*m_device, std::move(geometry)); |
| const auto& triangles_geometry = blas.GetGeometries()[0].GetTriangles(); |
| const vkt::Buffer& vertex_buffer = triangles_geometry.device_vertex_buffer; |
| blas.SetupBuild(true); |
| |
| vkt::Buffer src_buffer(*m_device, 4, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| VkBufferCopy region{}; |
| region.size = 4; |
| |
| // Test validation |
| m_command_buffer.Begin(); |
| vk::CmdCopyBuffer(m_command_buffer, src_buffer, vertex_buffer, 1, ®ion); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-READ-AFTER-WRITE"); |
| blas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| |
| // Test access update (that copy can see previous AS access) |
| m_command_buffer.Begin(); |
| blas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-READ"); |
| vk::CmdCopyBuffer(m_command_buffer, src_buffer, vertex_buffer, 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, WriteIndexDataDuringBuild) { |
| TEST_DESCRIPTION("Use index buffer as a copy destination while it is used by the AS build operation"); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| auto geometry = vkt::as::blueprint::GeometrySimpleOnDeviceIndexedTriangleInfo(*m_device, 1, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| auto blas = vkt::as::blueprint::BuildGeometryInfoOnDeviceBottomLevel(*m_device, std::move(geometry)); |
| const auto& triangles_geometry = blas.GetGeometries()[0].GetTriangles(); |
| const vkt::Buffer& index_buffer = triangles_geometry.device_index_buffer; |
| blas.SetupBuild(true); |
| |
| vkt::Buffer src_buffer(*m_device, 4, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| VkBufferCopy region{}; |
| region.size = 4; |
| |
| // Test validation |
| m_command_buffer.Begin(); |
| vk::CmdCopyBuffer(m_command_buffer, src_buffer, index_buffer, 1, ®ion); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-READ-AFTER-WRITE"); |
| blas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| |
| // Test access update (that copy can see previous AS access) |
| m_command_buffer.Begin(); |
| blas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-READ"); |
| vk::CmdCopyBuffer(m_command_buffer, src_buffer, index_buffer, 1, ®ion); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, WriteTransformDataDuringBuild) { |
| TEST_DESCRIPTION("Use transform data as a copy destination while it is used by the AS build operation"); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| auto geometry = vkt::as::blueprint::GeometrySimpleOnDeviceTriangleInfo(*m_device, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| auto blas = vkt::as::blueprint::BuildGeometryInfoOnDeviceBottomLevel(*m_device, std::move(geometry)); |
| const auto& triangles_geometry = blas.GetGeometries()[0].GetTriangles(); |
| const vkt::Buffer& transform_data = triangles_geometry.device_transform_buffer; |
| blas.SetupBuild(true); |
| |
| vkt::Buffer src_buffer(*m_device, transform_data.CreateInfo().size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| |
| // Test validation |
| m_command_buffer.Begin(); |
| m_command_buffer.Copy(src_buffer, transform_data); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-READ-AFTER-WRITE"); |
| blas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| |
| // Test access update (that copy can see previous AS access) |
| m_command_buffer.Begin(); |
| blas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-READ"); |
| m_command_buffer.Copy(src_buffer, transform_data); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, WriteAABBDataDuringBuild) { |
| TEST_DESCRIPTION("Use AABB data as a copy destination while it is used by the AS build operation"); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| auto geometry = vkt::as::blueprint::GeometrySimpleOnDeviceAABBInfo(*m_device, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| auto blas = vkt::as::blueprint::BuildGeometryInfoOnDeviceBottomLevel(*m_device, std::move(geometry)); |
| const auto& aabbs_geometry = blas.GetGeometries()[0].GetAABBs(); |
| const vkt::Buffer& aabb_buffer = aabbs_geometry.device_buffer; |
| blas.SetupBuild(true); |
| |
| vkt::Buffer src_buffer(*m_device, aabb_buffer.CreateInfo().size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| |
| // Test validation |
| m_command_buffer.Begin(); |
| m_command_buffer.Copy(src_buffer, aabb_buffer); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-READ-AFTER-WRITE"); |
| blas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| |
| // Test access update (that copy can see previous AS access) |
| m_command_buffer.Begin(); |
| blas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-READ"); |
| m_command_buffer.Copy(src_buffer, aabb_buffer); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, WriteInstanceDataDuringBuild) { |
| TEST_DESCRIPTION("Use instance data as a copy destination while it is used by the AS build operation"); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> blas = BuildBLAS(); |
| |
| vkt::as::BuildGeometryInfoKHR tlas = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceTopLevel(*m_device, *blas->GetDstAS()); |
| const auto& instance = tlas.GetGeometries()[0].GetInstance(); |
| tlas.SetupBuild(true); |
| |
| vkt::Buffer src_buffer(*m_device, instance.buffer.CreateInfo().size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| |
| // Test validation |
| m_command_buffer.Begin(); |
| m_command_buffer.Copy(src_buffer, instance.buffer); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-READ-AFTER-WRITE"); |
| tlas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| |
| // Test access update (that copy can see previous AS access) |
| m_command_buffer.Begin(); |
| tlas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-READ"); |
| m_command_buffer.Copy(src_buffer, instance.buffer); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, TraceAfterBuild) { |
| TEST_DESCRIPTION("Trace rays against TLAS without waiting for TLAS build completion"); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| // Create TLAS (but not build it yet) |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> blas = BuildBLAS(); |
| vkt::as::BuildGeometryInfoKHR tlas = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceTopLevel(*m_device, *blas->GetDstAS()); |
| tlas.SetupBuild(true); |
| |
| std::unique_ptr<vkt::rt::Pipeline> pipeline = GetTraceRaysPipeline(tlas.GetDstAS()->handle()); |
| const vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline->GetTraceRaysSbt(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline->GetPipelineLayout(), 0, 1, |
| &pipeline->GetDescriptorSet().set_, 0, nullptr); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline); |
| |
| // Build TLAS |
| tlas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| |
| // Start tracing ways without synchronization with TLAS build command |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-READ-AFTER-WRITE"); |
| vk::CmdTraceRaysKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt, |
| &trace_rays_sbt.callable_sbt, 1, 1, 1); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, TraceAfterBuildIndirect) { |
| TEST_DESCRIPTION("Build TLAS and trace rays"); |
| AddRequiredFeature(vkt::Feature::rayTracingPipelineTraceRaysIndirect); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| // Create TLAS (but not build it yet) |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> blas = BuildBLAS(); |
| vkt::as::BuildGeometryInfoKHR tlas = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceTopLevel(*m_device, *blas->GetDstAS()); |
| tlas.SetupBuild(true); |
| |
| std::unique_ptr<vkt::rt::Pipeline> pipeline = GetTraceRaysPipeline(tlas.GetDstAS()->handle()); |
| const vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline->GetTraceRaysSbt(); |
| |
| vkt::Buffer indirect_buffer(*m_device, 3 * sizeof(uint32_t), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline->GetPipelineLayout(), 0, 1, |
| &pipeline->GetDescriptorSet().set_, 0, nullptr); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline); |
| |
| // Build TLAS |
| tlas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| |
| // Start tracing rays while TLAS build is still in progress |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-READ-AFTER-WRITE"); |
| vk::CmdTraceRaysIndirectKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt, |
| &trace_rays_sbt.callable_sbt, indirect_buffer.Address()); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, TraceAfterBuildIndirect2) { |
| TEST_DESCRIPTION("Build TLAS and trace rays"); |
| AddRequiredExtensions(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::rayTracingPipelineTraceRaysIndirect2); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| // Create TLAS (but not build it yet) |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> blas = BuildBLAS(); |
| vkt::as::BuildGeometryInfoKHR tlas = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceTopLevel(*m_device, *blas->GetDstAS()); |
| tlas.SetupBuild(true); |
| |
| std::unique_ptr<vkt::rt::Pipeline> pipeline = GetTraceRaysPipeline(tlas.GetDstAS()->handle()); |
| |
| vkt::Buffer indirect_buffer(*m_device, 3 * sizeof(uint32_t), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline->GetPipelineLayout(), 0, 1, |
| &pipeline->GetDescriptorSet().set_, 0, nullptr); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline); |
| |
| // Build TLAS |
| tlas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| |
| // Start tracing rays while TLAS build is still in progress |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-READ-AFTER-WRITE"); |
| vk::CmdTraceRaysIndirect2KHR(m_command_buffer, indirect_buffer.Address()); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, WriteTLASDuringTrace) { |
| TEST_DESCRIPTION("Write to TLAS buffer while AS is being used by CmdTraceRays"); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> blas = BuildBLAS(); |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> tlas = BuildTLAS(*blas->GetDstAS()); |
| |
| const vkt::Buffer& tlas_buffer = tlas->GetDstAS()->GetBuffer(); |
| |
| std::unique_ptr<vkt::rt::Pipeline> pipeline = GetTraceRaysPipeline(tlas->GetDstAS()->handle()); |
| const vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline->GetTraceRaysSbt(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline->GetPipelineLayout(), 0, 1, |
| &pipeline->GetDescriptorSet().set_, 0, nullptr); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline); |
| vk::CmdTraceRaysKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt, |
| &trace_rays_sbt.callable_sbt, 1, 1, 1); |
| |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-READ"); |
| vk::CmdFillBuffer(m_command_buffer, tlas_buffer, 0, sizeof(uint32_t), 0x42); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, WriteTLASDuringTraceIndirect) { |
| TEST_DESCRIPTION("Write to TLAS buffer while AS is being used by CmdTraceRays"); |
| AddRequiredFeature(vkt::Feature::rayTracingPipelineTraceRaysIndirect); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> blas = BuildBLAS(); |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> tlas = BuildTLAS(*blas->GetDstAS()); |
| |
| const vkt::Buffer& tlas_buffer = tlas->GetDstAS()->GetBuffer(); |
| |
| std::unique_ptr<vkt::rt::Pipeline> pipeline = GetTraceRaysPipeline(tlas->GetDstAS()->handle()); |
| const vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline->GetTraceRaysSbt(); |
| |
| vkt::Buffer indirect_buffer(*m_device, 3 * sizeof(uint32_t), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline->GetPipelineLayout(), 0, 1, |
| &pipeline->GetDescriptorSet().set_, 0, nullptr); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline); |
| vk::CmdTraceRaysIndirectKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt, |
| &trace_rays_sbt.callable_sbt, indirect_buffer.Address()); |
| |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-READ"); |
| vk::CmdFillBuffer(m_command_buffer, tlas_buffer, 0, sizeof(uint32_t), 0x42); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, WriteTLASDuringTraceIndirect2) { |
| TEST_DESCRIPTION("Write to TLAS buffer while AS is being used by CmdTraceRays"); |
| AddRequiredExtensions(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::rayTracingPipelineTraceRaysIndirect2); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> blas = BuildBLAS(); |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> tlas = BuildTLAS(*blas->GetDstAS()); |
| |
| const vkt::Buffer& tlas_buffer = tlas->GetDstAS()->GetBuffer(); |
| |
| std::unique_ptr<vkt::rt::Pipeline> pipeline = GetTraceRaysPipeline(tlas->GetDstAS()->handle()); |
| |
| vkt::Buffer indirect_buffer(*m_device, 1024, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, vkt::device_address); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline->GetPipelineLayout(), 0, 1, |
| &pipeline->GetDescriptorSet().set_, 0, nullptr); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline); |
| vk::CmdTraceRaysIndirect2KHR(m_command_buffer, indirect_buffer.Address()); |
| |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-READ"); |
| vk::CmdFillBuffer(m_command_buffer, tlas_buffer, 0, sizeof(uint32_t), 0x42); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, WriteToTraceIndirectBuffer) { |
| TEST_DESCRIPTION("Run trace indirect command and write to indirect buffer at the same time"); |
| AddRequiredFeature(vkt::Feature::rayTracingPipelineTraceRaysIndirect); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> blas = BuildBLAS(); |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> tlas = BuildTLAS(*blas->GetDstAS()); |
| |
| std::unique_ptr<vkt::rt::Pipeline> pipeline = GetTraceRaysPipeline(tlas->GetDstAS()->handle()); |
| const vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline->GetTraceRaysSbt(); |
| |
| vkt::Buffer indirect_buffer(*m_device, 3 * sizeof(uint32_t), |
| VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, vkt::device_address); |
| |
| // Test indirect buffer validation |
| m_command_buffer.Begin(); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline->GetPipelineLayout(), 0, 1, |
| &pipeline->GetDescriptorSet().set_, 0, nullptr); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline); |
| vk::CmdFillBuffer(m_command_buffer, indirect_buffer, 0, sizeof(uint32_t), 19937); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-READ-AFTER-WRITE"); |
| vk::CmdTraceRaysIndirectKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt, |
| &trace_rays_sbt.callable_sbt, indirect_buffer.Address()); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| |
| // Test indirect buffer access update |
| m_command_buffer.Begin(); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline->GetPipelineLayout(), 0, 1, |
| &pipeline->GetDescriptorSet().set_, 0, nullptr); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline); |
| vk::CmdTraceRaysIndirectKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt, |
| &trace_rays_sbt.callable_sbt, indirect_buffer.Address()); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-READ"); |
| vk::CmdFillBuffer(m_command_buffer, indirect_buffer, 0, sizeof(uint32_t), 19937); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, WriteToTraceIndirectBuffer2) { |
| TEST_DESCRIPTION("Run trace indirect command and write to indirect buffer at the same time"); |
| AddRequiredExtensions(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::rayTracingPipelineTraceRaysIndirect2); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> blas = BuildBLAS(); |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> tlas = BuildTLAS(*blas->GetDstAS()); |
| |
| std::unique_ptr<vkt::rt::Pipeline> pipeline = GetTraceRaysPipeline(tlas->GetDstAS()->handle()); |
| |
| vkt::Buffer indirect_buffer(*m_device, 1024 * sizeof(uint32_t), |
| VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, vkt::device_address); |
| |
| // Test indirect buffer validation |
| m_command_buffer.Begin(); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline->GetPipelineLayout(), 0, 1, |
| &pipeline->GetDescriptorSet().set_, 0, nullptr); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline); |
| vk::CmdFillBuffer(m_command_buffer, indirect_buffer, 0, sizeof(uint32_t), 19937); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-READ-AFTER-WRITE"); |
| vk::CmdTraceRaysIndirect2KHR(m_command_buffer, indirect_buffer.Address()); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| |
| // Test indirect buffer access update |
| m_command_buffer.Begin(); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline->GetPipelineLayout(), 0, 1, |
| &pipeline->GetDescriptorSet().set_, 0, nullptr); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipeline); |
| vk::CmdTraceRaysIndirect2KHR(m_command_buffer, indirect_buffer.Address()); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-READ"); |
| vk::CmdFillBuffer(m_command_buffer, indirect_buffer, 0, sizeof(uint32_t), 19937); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, RayQueryAfterBuild) { |
| TEST_DESCRIPTION("Trace rays against TLAS using ray queries without waiting for TLAS build completion"); |
| AddRequiredExtensions(VK_KHR_RAY_QUERY_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::rayQuery); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> blas = BuildBLAS(); |
| |
| // Create TLAS (but not build it yet) |
| vkt::as::BuildGeometryInfoKHR tlas = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceTopLevel(*m_device, *blas->GetDstAS()); |
| tlas.SetupBuild(true); |
| |
| CreateComputePipelineHelper pipeline = GetRayQueryComputePipeline(tlas.GetDstAS()->handle()); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.pipeline_layout_, 0, 1, |
| &pipeline.descriptor_set_.set_, 0, nullptr); |
| |
| // Build TLAS |
| tlas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| |
| // Start tracing rays without synchronization with TLAS build command |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-READ-AFTER-WRITE"); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, CopyAfterRayQuery) { |
| TEST_DESCRIPTION("Copy to TLAS backing buffer without waiting for ray query operation"); |
| AddRequiredExtensions(VK_KHR_RAY_QUERY_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::rayQuery); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> blas = BuildBLAS(); |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> tlas = BuildTLAS(*blas->GetDstAS()); |
| |
| CreateComputePipelineHelper pipeline = GetRayQueryComputePipeline(tlas->GetDstAS()->handle()); |
| |
| const vkt::Buffer& tlas_buffer = tlas->GetDstAS()->GetBuffer(); |
| vkt::Buffer src_buffer(*m_device, tlas_buffer.CreateInfo().size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.pipeline_layout_, 0, 1, |
| &pipeline.descriptor_set_.set_, 0, nullptr); |
| |
| // Trace rays |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| |
| // Write to the TLAS backing buffer while it is still being used by the dispatch call |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-READ"); |
| m_command_buffer.Copy(src_buffer, tlas_buffer); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, ASCopySourceHazard) { |
| TEST_DESCRIPTION("Hazard when accessing AS copy source"); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> blas_src = BuildBLAS(); |
| |
| vkt::as::BuildGeometryInfoKHR blas_dst = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| blas_dst.SetupBuild(true); |
| |
| VkCopyAccelerationStructureInfoKHR copy_info = vku::InitStructHelper(); |
| copy_info.src = blas_src->GetDstAS()->handle(); |
| copy_info.dst = blas_dst.GetDstAS()->handle(); |
| copy_info.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR; |
| |
| const vkt::Buffer& blas_src_buffer = blas_src->GetDstAS()->GetBuffer(); |
| vkt::Buffer buffer(*m_device, blas_src_buffer.CreateInfo().size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| |
| // Test validation |
| m_command_buffer.Begin(); |
| m_command_buffer.Copy(buffer, blas_src_buffer); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-READ-AFTER-WRITE"); |
| vk::CmdCopyAccelerationStructureKHR(m_command_buffer, ©_info); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| |
| // Test update |
| m_command_buffer.Begin(); |
| vk::CmdCopyAccelerationStructureKHR(m_command_buffer, ©_info); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-READ"); |
| m_command_buffer.Copy(buffer, blas_src_buffer); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, ASCopyDestinationHazard) { |
| TEST_DESCRIPTION("Hazard when accessing AS copy destination"); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> blas_src = BuildBLAS(); |
| |
| vkt::as::BuildGeometryInfoKHR blas_dst = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| blas_dst.GetDstAS()->SetBufferUsageFlags(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | |
| VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| blas_dst.SetupBuild(true); |
| |
| VkCopyAccelerationStructureInfoKHR copy_info = vku::InitStructHelper(); |
| copy_info.src = blas_src->GetDstAS()->handle(); |
| copy_info.dst = blas_dst.GetDstAS()->handle(); |
| copy_info.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR; |
| |
| const vkt::Buffer& blas_dst_buffer = blas_dst.GetDstAS()->GetBuffer(); |
| vkt::Buffer buffer(*m_device, blas_dst_buffer.CreateInfo().size, |
| VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| |
| // Test validation |
| m_command_buffer.Begin(); |
| m_command_buffer.Copy(blas_dst_buffer, buffer); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-READ"); |
| vk::CmdCopyAccelerationStructureKHR(m_command_buffer, ©_info); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| |
| // Test update |
| m_command_buffer.Begin(); |
| vk::CmdCopyAccelerationStructureKHR(m_command_buffer, ©_info); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-WRITE"); |
| m_command_buffer.Copy(buffer, blas_dst_buffer); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, SerializeASHazard) { |
| TEST_DESCRIPTION("Test read accesses when acceleration structure is serialized to a buffer"); |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| if (IsPlatformMockICD()) { |
| GTEST_SKIP() << "Test not supported by TestICD: serialization size query"; |
| } |
| |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> blas = BuildBLAS(); |
| const vkt::Buffer& blas_buffer = blas->GetDstAS()->GetBuffer(); |
| |
| vkt::Buffer serialization_buffer = GetSerializationDeserializationBuffer(*blas->GetDstAS()); |
| |
| VkCopyAccelerationStructureToMemoryInfoKHR copy_to_memory_info = vku::InitStructHelper(); |
| copy_to_memory_info.src = blas->GetDstAS()->handle(); |
| copy_to_memory_info.dst = VkDeviceOrHostAddressKHR{serialization_buffer.Address()}; |
| copy_to_memory_info.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR; |
| |
| // Test Validation |
| m_command_buffer.Begin(); |
| vk::CmdFillBuffer(m_command_buffer, blas_buffer, 0, sizeof(uint32_t), 0x314159); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-READ-AFTER-WRITE"); |
| vk::CmdCopyAccelerationStructureToMemoryKHR(m_command_buffer, ©_to_memory_info); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| |
| // Test update |
| m_command_buffer.Begin(); |
| vk::CmdCopyAccelerationStructureToMemoryKHR(m_command_buffer, ©_to_memory_info); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-READ"); |
| vk::CmdFillBuffer(m_command_buffer, blas_buffer, 0, sizeof(uint32_t), 0x314159); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, DeserializeASHazard) { |
| TEST_DESCRIPTION("Test write accesses when acceleration structure is deserialized from a buffer"); |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| if (IsPlatformMockICD()) { |
| GTEST_SKIP() << "Test not supported by TestICD: serialization size query"; |
| } |
| |
| std::unique_ptr<vkt::as::BuildGeometryInfoKHR> blas = BuildBLAS(); |
| |
| vkt::as::BuildGeometryInfoKHR blas2 = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| blas2.GetDstAS()->SetBufferUsageFlags(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | |
| VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| blas2.SetupBuild(true); |
| const vkt::Buffer& blas2_buffer = blas2.GetDstAS()->GetBuffer(); |
| |
| vkt::Buffer serialization_buffer = GetSerializationDeserializationBuffer(*blas->GetDstAS()); |
| |
| VkCopyMemoryToAccelerationStructureInfoKHR copy_from_memory_info = vku::InitStructHelper(); |
| copy_from_memory_info.src = VkDeviceOrHostAddressConstKHR{serialization_buffer.Address()}; |
| copy_from_memory_info.dst = blas2.GetDstAS()->handle(); |
| copy_from_memory_info.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR; |
| |
| // Test Validation |
| m_command_buffer.Begin(); |
| vk::CmdFillBuffer(m_command_buffer, blas2_buffer, 0, sizeof(uint32_t), 0x314159); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-WRITE"); |
| vk::CmdCopyMemoryToAccelerationStructureKHR(m_command_buffer, ©_from_memory_info); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| |
| // Test update |
| m_command_buffer.Begin(); |
| vk::CmdCopyMemoryToAccelerationStructureKHR(m_command_buffer, ©_from_memory_info); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-WRITE"); |
| vk::CmdFillBuffer(m_command_buffer, blas2_buffer, 0, sizeof(uint32_t), 0x314159); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, BuildAfterBuildSyncASBufferButNotScratch) { |
| TEST_DESCRIPTION("Build BLAS after BLAS. Barrier BLAS buffer but not syncs scratch buffer"); |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| AddRequiredFeature(vkt::Feature::synchronization2); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| vkt::as::BuildGeometryInfoKHR blas = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| blas.GetDstAS()->SetBufferUsageFlags(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR); |
| blas.SetupBuild(true); |
| |
| const vkt::Buffer& accel_buffer = blas.GetDstAS()->GetBuffer(); |
| |
| VkBufferMemoryBarrier2 blas_buffer_barrier = vku::InitStructHelper(); |
| blas_buffer_barrier.srcStageMask = VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR; |
| blas_buffer_barrier.srcAccessMask = VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR; |
| blas_buffer_barrier.dstStageMask = VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR; |
| blas_buffer_barrier.dstAccessMask = |
| VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| blas_buffer_barrier.buffer = accel_buffer; |
| blas_buffer_barrier.offset = 0; |
| blas_buffer_barrier.size = accel_buffer.CreateInfo().size; |
| |
| m_command_buffer.Begin(); |
| blas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_command_buffer.Barrier(blas_buffer_barrier); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-WRITE"); |
| blas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativeSyncValRayTracing, BuildAfterBuildSyncScratchButNotASBuffer) { |
| TEST_DESCRIPTION("Build BLAS after BLAS. Barrier syncs scratch buffer but not BLAS buffer"); |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| AddRequiredFeature(vkt::Feature::synchronization2); |
| RETURN_IF_SKIP(InitRayTracing()); |
| |
| vkt::as::BuildGeometryInfoKHR blas = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| blas.GetDstAS()->SetBufferUsageFlags(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR); |
| blas.SetupBuild(true); |
| |
| VkBufferMemoryBarrier2 scratch_buffer_barrier = vku::InitStructHelper(); |
| scratch_buffer_barrier.srcStageMask = VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR; |
| scratch_buffer_barrier.srcAccessMask = VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR; |
| scratch_buffer_barrier.dstStageMask = VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR; |
| scratch_buffer_barrier.dstAccessMask = |
| VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| scratch_buffer_barrier.buffer = *blas.GetScratchBuffer(); |
| scratch_buffer_barrier.offset = 0; |
| scratch_buffer_barrier.size = blas.GetScratchBuffer()->CreateInfo().size; |
| |
| m_command_buffer.Begin(); |
| blas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_command_buffer.Barrier(scratch_buffer_barrier); |
| m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-WRITE"); |
| blas.VkCmdBuildAccelerationStructuresKHR(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |