diff --git a/layers/core_checks/cc_ray_tracing.cpp b/layers/core_checks/cc_ray_tracing.cpp index 6d3ea6b9ef3..ef44100e571 100644 --- a/layers/core_checks/cc_ray_tracing.cpp +++ b/layers/core_checks/cc_ray_tracing.cpp @@ -28,6 +28,8 @@ #include "state_tracker/ray_tracing_state.h" #include "error_message/error_strings.h" +#include + bool CoreChecks::ValidateInsertAccelerationStructureMemoryRange(VkAccelerationStructureNV as, const vvl::DeviceMemory &mem_info, VkDeviceSize mem_offset, const Location &loc) const { return ValidateInsertMemoryRange(VulkanTypedHandle(as, kVulkanObjectTypeAccelerationStructureNV), mem_info, mem_offset, loc); @@ -215,67 +217,219 @@ bool CoreChecks::ValidateAccelerationStructuresMemoryAlisasing(const LogObjectLi return skip; } -bool CoreChecks::ValidateAccelerationStructuresDeviceScratchBufferMemoryAlisasing( - const LogObjectList &objlist, uint32_t info_count, const VkAccelerationStructureBuildGeometryInfoKHR *p_infos, uint32_t info_i, +bool CoreChecks::ValidateAccelerationStructuresDeviceScratchBufferMemoryAliasing( + VkCommandBuffer cmd_buffer, uint32_t info_count, const VkAccelerationStructureBuildGeometryInfoKHR *p_infos, const VkAccelerationStructureBuildRangeInfoKHR *const *pp_range_infos, const ErrorObject &error_obj) const { - using vvl::range; - bool skip = false; - const VkAccelerationStructureBuildGeometryInfoKHR &info = p_infos[info_i]; - const Location info_i_loc = error_obj.location.dot(Field::pInfos, info_i); - const auto src_as_state = Get(info.srcAccelerationStructure); - const auto dst_as_state = Get(info.dstAccelerationStructure); - const rt::BuildType rt_build_type = - error_obj.location.function == Func::vkBuildAccelerationStructuresKHR ? rt::BuildType::Host : rt::BuildType::Device; - const bool info_in_mode_update = info.mode == VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR; + enum class AddressRangeOrigin : uint8_t { Undefined, SrcAccelStruct, DstAccelStruct, Scratch }; + struct AddressRange { + vvl::range range = {}; + uint32_t info_i = 0; + AddressRangeOrigin origin = AddressRangeOrigin::Undefined; + }; + // Gather all address ranges from source acceleration structtures, destination acceleration structures + // and scratch buffers in a single sorted vector, to more rapidly lookup overlaps + std::vector address_ranges; + address_ranges.reserve(3 * info_count); + + const auto insert_address = [](std::vector &address_ranges, const AddressRange address_range) { + std::optional overlapped_range = std::nullopt; + auto insert_pos = std::lower_bound( + address_ranges.begin(), address_ranges.end(), address_range, + [&overlapped_range](const AddressRange iter, const AddressRange new_elt) -> bool { + const vvl::range intersection = iter.range & new_elt.range; + if (intersection.non_empty()) { + const bool both_src_as_ranges = + iter.origin == AddressRangeOrigin::SrcAccelStruct && new_elt.origin == AddressRangeOrigin::SrcAccelStruct; + // #ARNO_TODO make sure VUID 03668 is correctly handled + const bool as_update = + iter.info_i == new_elt.info_i && ((iter.origin == AddressRangeOrigin::SrcAccelStruct && + new_elt.origin == AddressRangeOrigin::DstAccelStruct) || + (new_elt.origin == AddressRangeOrigin::SrcAccelStruct && + iter.origin == AddressRangeOrigin::DstAccelStruct)); + + if (!both_src_as_ranges && !as_update) { + overlapped_range = iter; + } + } - // Cannot compute scratch buffer size from the CPU with indirect calls, - // so cannot perform validation - vvl::span info_scratches = GetBuffersByAddress(info.scratchData.deviceAddress); - const VkDeviceSize assumed_scratch_size = rt::ComputeScratchSize(rt_build_type, device, info, pp_range_infos[info_i]); + return iter.range < new_elt.range; + }); - if (dst_as_state) { - vvl::span dummy(nullptr, 0); - skip |= ValidateScratchMemoryNoOverlap(error_obj.location, objlist, info_scratches, info.scratchData.deviceAddress, - assumed_scratch_size, info_i_loc.dot(Field::scratchData).dot(Field::deviceAddress), - info_in_mode_update ? src_as_state.get() : nullptr, - info_i_loc.dot(Field::srcAccelerationStructure), *dst_as_state, - info_i_loc.dot(Field::dstAccelerationStructure), dummy, 0, 0, nullptr); - } + address_ranges.insert(insert_pos, address_range); + return overlapped_range; + }; - // Loop on other acceleration structure builds info. - // Given that comparisons are commutative, only need to consider elements after info_i - assert(info_count > info_i); - for (uint32_t other_info_j = info_i + 1; other_info_j < info_count; ++other_info_j) { - // Validate that scratch buffer's memory does not overlap destination acceleration structure's memory, or source - // acceleration structure's memory if build mode is update, or other scratch buffers' memory. - // Here validation is pessimistic: if one buffer associated to pInfos[other_info_j].scratchData.deviceAddress has an - // overlap, an error will be logged. + for (const auto [info_i, info] : vvl::enumerate(p_infos, info_count)) { + const Location info_i_loc = error_obj.location.dot(Field::pInfos, info_i); - const VkAccelerationStructureBuildGeometryInfoKHR &other_info = p_infos[other_info_j]; - const Location other_info_j_loc = error_obj.location.dot(Field::pInfos, other_info_j); + const auto dst_as_state = Get(info.dstAccelerationStructure); - const auto other_dst_as_state = Get(other_info.dstAccelerationStructure); - const auto other_src_as_state = Get(other_info.srcAccelerationStructure); + if (const auto src_as_state = Get(info.srcAccelerationStructure); + src_as_state && info.mode == VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR) { + const vvl::range src_as_range = src_as_state->GetDeviceAddressRange(); - const bool other_info_in_update_mode = other_info.mode == VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR; + if (dst_as_state && dst_as_state->VkHandle() != src_as_state->VkHandle()) { + const vvl::range dst_as_range = dst_as_state->GetDeviceAddressRange(); - if (other_dst_as_state) { - auto other_info_scratches = GetBuffersByAddress(other_info.scratchData.deviceAddress); - const VkDeviceSize assumed_other_scratch_size = - rt::ComputeScratchSize(rt_build_type, device, other_info, pp_range_infos[other_info_j]); + if (const vvl::range dst_as_src_as_intersection = dst_as_range & src_as_range; + dst_as_src_as_intersection.non_empty()) { + skip |= LogError("VUID-vkCmdBuildAccelerationStructuresKHR-pInfos-03668", + LogObjectList(cmd_buffer, src_as_state->VkHandle(), dst_as_state->VkHandle()), + info_i_loc.dot(Field::dstAccelerationStructure), + "overlaps with srcAccelerationStructure, which is in update mode, on device address range %s.", + string_range_hex(dst_as_src_as_intersection).c_str()); + } + } - const Location other_scratch_loc = other_info_j_loc.dot(Field::scratchData); - const Location other_scratch_address_loc = other_scratch_loc.dot(Field::deviceAddress); + const AddressRange src_as_address_range = {src_as_range, info_i, AddressRangeOrigin::SrcAccelStruct}; + const std::optional overlapped_address_range = insert_address(address_ranges, src_as_address_range); + if (overlapped_address_range.has_value()) { + switch (overlapped_address_range->origin) { + case AddressRangeOrigin::SrcAccelStruct: { + // Valid overlap, source acceleration structures being read only + break; + } + case AddressRangeOrigin::DstAccelStruct: { + const auto other_dst_as_state = + Get(p_infos[overlapped_address_range->info_i].dstAccelerationStructure); + const vvl::range src_as_other_dst_as_intersection = + src_as_address_range.range & overlapped_address_range->range; + + skip |= + LogError("VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03701", + LogObjectList(cmd_buffer, src_as_state->VkHandle(), other_dst_as_state->VkHandle()), + info_i_loc.dot(Field::srcAccelerationStructure), + ", in update mode, overlaps with dstAccelerationStructure of pInfos[%" PRIu32 + "], on device address range %s.", + overlapped_address_range->info_i, string_range_hex(src_as_other_dst_as_intersection).c_str()); + break; + } + case AddressRangeOrigin::Scratch: { + const vvl::range src_as_other_scratch_intersection = + src_as_address_range.range & overlapped_address_range->range; + skip |= LogError( + "VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03705", + LogObjectList(cmd_buffer, src_as_state->VkHandle()), info_i_loc.dot(Field::srcAccelerationStructure), + "overlaps with scratch buffer of pInfos[%" PRIu32 "] on device address range %s.", + overlapped_address_range->info_i, string_range_hex(src_as_other_scratch_intersection).c_str()); + break; + } + default: + assert(false); + break; + } + } + } - skip |= ValidateScratchMemoryNoOverlap( - error_obj.location, objlist, info_scratches, info.scratchData.deviceAddress, assumed_scratch_size, - info_i_loc.dot(Field::scratchData).dot(Field::deviceAddress), - other_info_in_update_mode ? other_src_as_state.get() : nullptr, - other_info_j_loc.dot(Field::srcAccelerationStructure), *other_dst_as_state, - other_info_j_loc.dot(Field::dstAccelerationStructure), other_info_scratches, other_info.scratchData.deviceAddress, - assumed_other_scratch_size, &other_scratch_address_loc); + if (dst_as_state) { + const AddressRange dst_as_address_range = {dst_as_state->GetDeviceAddressRange(), info_i, + AddressRangeOrigin::DstAccelStruct}; + const std::optional overlapped_address_range = insert_address(address_ranges, dst_as_address_range); + if (overlapped_address_range.has_value()) { + switch (overlapped_address_range->origin) { + case AddressRangeOrigin::SrcAccelStruct: { + const auto other_src_as_state = + Get(p_infos[overlapped_address_range->info_i].srcAccelerationStructure); + const vvl::range dst_as_other_src_as_intersection = + dst_as_address_range.range & overlapped_address_range->range; + + skip |= + LogError("VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03701", + LogObjectList(cmd_buffer, dst_as_state->VkHandle(), other_src_as_state->VkHandle()), + info_i_loc.dot(Field::dstAccelerationStructure), + ", overlaps with srcAccelerationStructure of pInfos[%" PRIu32 + "], which is in update mode, on device address range %s.", + overlapped_address_range->info_i, string_range_hex(dst_as_other_src_as_intersection).c_str()); + break; + } + case AddressRangeOrigin::DstAccelStruct: { + const auto other_dst_as_state = + Get(p_infos[overlapped_address_range->info_i].dstAccelerationStructure); + const vvl::range dst_as_other_dst_as_intersection = + dst_as_address_range.range & overlapped_address_range->range; + + skip |= + LogError("VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03702", + LogObjectList(cmd_buffer, dst_as_state->VkHandle(), other_dst_as_state->VkHandle()), + info_i_loc.dot(Field::dstAccelerationStructure), + "overlaps with dstAccelerationStructure of pInfos[%" PRIu32 "], on device address range %s.", + overlapped_address_range->info_i, string_range_hex(dst_as_other_dst_as_intersection).c_str()); + break; + } + case AddressRangeOrigin::Scratch: { + const vvl::range src_as_other_scratch_intersection = + dst_as_address_range.range & overlapped_address_range->range; + skip |= LogError( + "VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03703", + LogObjectList(cmd_buffer, dst_as_state->VkHandle()), info_i_loc.dot(Field::dstAccelerationStructure), + "overlaps with scratch buffer of pInfos[%" PRIu32 "] on device address range %s.", + overlapped_address_range->info_i, string_range_hex(src_as_other_scratch_intersection).c_str()); + break; + } + default: + assert(false); + break; + } + } + } + + { + const rt::BuildType rt_build_type = + error_obj.location.function == Func::vkBuildAccelerationStructuresKHR ? rt::BuildType::Host : rt::BuildType::Device; + + const VkDeviceSize assumed_scratch_size = rt::ComputeScratchSize(rt_build_type, device, info, pp_range_infos[info_i]); + + const vvl::range scratch_range = {info.scratchData.deviceAddress, + info.scratchData.deviceAddress + assumed_scratch_size}; + + const AddressRange scratch_address_range = {scratch_range, info_i, AddressRangeOrigin::Scratch}; + const std::optional overlapped_address_range = insert_address(address_ranges, scratch_address_range); + if (overlapped_address_range.has_value()) { + switch (overlapped_address_range->origin) { + case AddressRangeOrigin::SrcAccelStruct: { + const auto other_src_as_state = + Get(p_infos[overlapped_address_range->info_i].srcAccelerationStructure); + const vvl::range scratch_other_src_as_intersection = + scratch_address_range.range & overlapped_address_range->range; + + skip |= + LogError("VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03705", + LogObjectList(cmd_buffer, other_src_as_state->VkHandle()), info_i_loc.dot(Field::scratchData), + ", overlaps with srcAccelerationStructure of pInfos[%" PRIu32 + "], which is in update mode, on device address range %s.", + overlapped_address_range->info_i, string_range_hex(scratch_other_src_as_intersection).c_str()); + break; + } + case AddressRangeOrigin::DstAccelStruct: { + const auto other_dst_as_state = + Get(p_infos[overlapped_address_range->info_i].dstAccelerationStructure); + const vvl::range dst_as_other_dst_as_intersection = + scratch_address_range.range & overlapped_address_range->range; + + skip |= + LogError("VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03703", + LogObjectList(cmd_buffer, other_dst_as_state->VkHandle()), info_i_loc.dot(Field::scratchData), + "overlaps with dstAccelerationStructure of pInfos[%" PRIu32 "], on device address range %s.", + overlapped_address_range->info_i, string_range_hex(dst_as_other_dst_as_intersection).c_str()); + break; + } + case AddressRangeOrigin::Scratch: { + const vvl::range src_as_other_scratch_intersection = + scratch_address_range.range & overlapped_address_range->range; + skip |= + LogError("VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03704", LogObjectList(cmd_buffer), + info_i_loc.dot(Field::scratchData), + "overlaps with scratch buffer of pInfos[%" PRIu32 "] on device address range %s.", + overlapped_address_range->info_i, string_range_hex(src_as_other_scratch_intersection).c_str()); + break; + } + default: + assert(false); + break; + } + } } } @@ -906,13 +1060,11 @@ bool CoreChecks::PreCallValidateCmdBuildAccelerationStructuresKHR( skip |= CommonBuildAccelerationStructureValidation(info, info_loc, commandBuffer); skip |= ValidateAccelerationBuffers(commandBuffer, info_i, info, ppBuildRangeInfos[info_i], info_loc); - - skip |= ValidateAccelerationStructuresMemoryAlisasing(commandBuffer, infoCount, pInfos, info_i, error_obj); - - skip |= ValidateAccelerationStructuresDeviceScratchBufferMemoryAlisasing(commandBuffer, infoCount, pInfos, info_i, - ppBuildRangeInfos, error_obj); } + skip |= ValidateAccelerationStructuresDeviceScratchBufferMemoryAliasing(commandBuffer, infoCount, pInfos, ppBuildRangeInfos, + error_obj); + return skip; } diff --git a/layers/core_checks/core_validation.h b/layers/core_checks/core_validation.h index 1cbd24e42f0..55b7cfd8548 100644 --- a/layers/core_checks/core_validation.h +++ b/layers/core_checks/core_validation.h @@ -1689,9 +1689,9 @@ class CoreChecks : public vvl::Device { bool ValidateAccelerationStructuresMemoryAlisasing(const LogObjectList& objlist, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, uint32_t info_i, const ErrorObject& error_obj) const; - bool ValidateAccelerationStructuresDeviceScratchBufferMemoryAlisasing( - const LogObjectList& objlist, uint32_t info_count, const VkAccelerationStructureBuildGeometryInfoKHR* p_infos, - uint32_t info_i, const VkAccelerationStructureBuildRangeInfoKHR* const* pp_range_infos, const ErrorObject& error_obj) const; + bool ValidateAccelerationStructuresDeviceScratchBufferMemoryAliasing( + VkCommandBuffer cmd_buffer, uint32_t info_count, const VkAccelerationStructureBuildGeometryInfoKHR* p_infos, + const VkAccelerationStructureBuildRangeInfoKHR* const* pp_range_infos, const ErrorObject& error_obj) const; bool PreCallValidateCmdBuildAccelerationStructuresKHR(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos, diff --git a/layers/gpuav/core/gpuav_setup.cpp b/layers/gpuav/core/gpuav_setup.cpp index 2dd4c429add..c6b50f7e549 100644 --- a/layers/gpuav/core/gpuav_setup.cpp +++ b/layers/gpuav/core/gpuav_setup.cpp @@ -53,7 +53,7 @@ std::shared_ptr Validator::CreateSamplerState(VkSampler handle, co std::shared_ptr Validator::CreateAccelerationStructureState( VkAccelerationStructureKHR handle, const VkAccelerationStructureCreateInfoKHR *create_info, std::shared_ptr &&buf_state) { - return std::make_shared(handle, create_info, std::move(buf_state), *desc_heap_); + return std::make_shared(device, handle, create_info, std::move(buf_state), *desc_heap_); } std::shared_ptr Validator::CreateDescriptorSet(VkDescriptorSet handle, vvl::DescriptorPool *pool, diff --git a/layers/gpuav/resources/gpuav_state_trackers.cpp b/layers/gpuav/resources/gpuav_state_trackers.cpp index 5908e77570d..ffd27e8802b 100644 --- a/layers/gpuav/resources/gpuav_state_trackers.cpp +++ b/layers/gpuav/resources/gpuav_state_trackers.cpp @@ -90,9 +90,10 @@ void Sampler::NotifyInvalidate(const NodeList &invalid_nodes, bool unlink) { vvl::Sampler::NotifyInvalidate(invalid_nodes, unlink); } -AccelerationStructureKHR::AccelerationStructureKHR(VkAccelerationStructureKHR as, const VkAccelerationStructureCreateInfoKHR *ci, +AccelerationStructureKHR::AccelerationStructureKHR(VkDevice device, VkAccelerationStructureKHR as, + const VkAccelerationStructureCreateInfoKHR *ci, std::shared_ptr &&buf_state, DescriptorHeap &desc_heap_) - : vvl::AccelerationStructureKHR(as, ci, std::move(buf_state)), + : vvl::AccelerationStructureKHR(device, as, ci, std::move(buf_state)), desc_heap(desc_heap_), id(desc_heap.NextId(VulkanTypedHandle(as, kVulkanObjectTypeAccelerationStructureKHR))) {} diff --git a/layers/gpuav/resources/gpuav_state_trackers.h b/layers/gpuav/resources/gpuav_state_trackers.h index 63eecee6bea..ae3e7f3257c 100644 --- a/layers/gpuav/resources/gpuav_state_trackers.h +++ b/layers/gpuav/resources/gpuav_state_trackers.h @@ -229,7 +229,7 @@ class Sampler : public vvl::Sampler { class AccelerationStructureKHR : public vvl::AccelerationStructureKHR { public: - AccelerationStructureKHR(VkAccelerationStructureKHR as, const VkAccelerationStructureCreateInfoKHR *ci, + AccelerationStructureKHR(VkDevice device, VkAccelerationStructureKHR as, const VkAccelerationStructureCreateInfoKHR *ci, std::shared_ptr &&buf_state, DescriptorHeap &desc_heap_); void Destroy() final; diff --git a/layers/state_tracker/ray_tracing_state.h b/layers/state_tracker/ray_tracing_state.h index 35cb75d9370..d4d6dc37a8a 100644 --- a/layers/state_tracker/ray_tracing_state.h +++ b/layers/state_tracker/ray_tracing_state.h @@ -75,12 +75,16 @@ class AccelerationStructureNV : public Bindable { class AccelerationStructureKHR : public StateObject { public: - AccelerationStructureKHR(VkAccelerationStructureKHR handle, const VkAccelerationStructureCreateInfoKHR *pCreateInfo, - std::shared_ptr &&buf_state) + AccelerationStructureKHR(VkDevice device, VkAccelerationStructureKHR handle, + const VkAccelerationStructureCreateInfoKHR *pCreateInfo, std::shared_ptr &&buf_state) : StateObject(handle, kVulkanObjectTypeAccelerationStructureKHR), safe_create_info(pCreateInfo), create_info(*safe_create_info.ptr()), - buffer_state(buf_state) {} + buffer_state(buf_state) { + VkAccelerationStructureDeviceAddressInfoKHR device_addr_info = vku::InitStructHelper(); + device_addr_info.accelerationStructure = handle; + device_address = DispatchGetAccelerationStructureDeviceAddressKHR(device, &device_addr_info); + } AccelerationStructureKHR(const AccelerationStructureKHR &rh_obj) = delete; virtual ~AccelerationStructureKHR() { @@ -120,10 +124,13 @@ class AccelerationStructureKHR : public StateObject { } } + vvl::range GetDeviceAddressRange() const { return {device_address, device_address + safe_create_info.size}; } + const vku::safe_VkAccelerationStructureCreateInfoKHR safe_create_info; const VkAccelerationStructureCreateInfoKHR &create_info; uint64_t opaque_handle = 0; + VkDeviceAddress device_address = 0; std::shared_ptr buffer_state{}; std::optional build_info_khr{}; std::vector build_range_infos{}; diff --git a/layers/state_tracker/state_tracker.cpp b/layers/state_tracker/state_tracker.cpp index c5261862035..c9b0ac1cdde 100644 --- a/layers/state_tracker/state_tracker.cpp +++ b/layers/state_tracker/state_tracker.cpp @@ -368,6 +368,21 @@ std::shared_ptr Device::CreateBufferState(VkBuffer handle, const VkBuffe return std::make_shared(*this, handle, create_info); } +void Device::PreCallRecordCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer, const RecordObject &record_obj, + chassis::CreateBuffer &chassis_state) { + if (pCreateInfo->usage & VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR) { + // When it comes to validation acceleration memory overlaps, it is much faster to + // work on device address ranges directly, but for that to be possible, + // buffers used to back acceleration structures must have been created with the + // VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT usage flag + // => Enforce it. + // Doing so will not modify VVL state tracking, and if the application forgot to set + // this flag, it will still be detected. + chassis_state.modified_create_info.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + } +} + void Device::PostCallRecordCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer, const RecordObject &record_obj) { @@ -2233,7 +2248,7 @@ void Device::PostCallRecordCreateAccelerationStructureNV(VkDevice device, const std::shared_ptr Device::CreateAccelerationStructureState( VkAccelerationStructureKHR handle, const VkAccelerationStructureCreateInfoKHR *create_info, std::shared_ptr &&buf_state) { - return std::make_shared(handle, create_info, std::move(buf_state)); + return std::make_shared(device, handle, create_info, std::move(buf_state)); } void Device::PostCallRecordCreateAccelerationStructureKHR(VkDevice device, const VkAccelerationStructureCreateInfoKHR *pCreateInfo, diff --git a/layers/state_tracker/state_tracker.h b/layers/state_tracker/state_tracker.h index b5bd7c618c2..6a522e6da44 100644 --- a/layers/state_tracker/state_tracker.h +++ b/layers/state_tracker/state_tracker.h @@ -788,6 +788,9 @@ class Device : public vvl::base::Device { const RecordObject& record_obj) override; virtual std::shared_ptr CreateBufferState(VkBuffer handle, const VkBufferCreateInfo* create_info); + void PreCallRecordCreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, + VkBuffer* pBuffer, const RecordObject& record_obj, + chassis::CreateBuffer& chassis_state) override; void PostCallRecordCreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer, const RecordObject& record_obj) override; void PreCallRecordDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator, diff --git a/tests/icd/test_icd.cpp b/tests/icd/test_icd.cpp index 53c3a224e19..9aa070ad9a2 100644 --- a/tests/icd/test_icd.cpp +++ b/tests/icd/test_icd.cpp @@ -1696,8 +1696,7 @@ static VKAPI_ATTR void VKAPI_CALL GetShaderModuleIdentifierEXT(VkDevice device, static VKAPI_ATTR VkDeviceAddress VKAPI_CALL GetAccelerationStructureDeviceAddressKHR(VkDevice device, const VkAccelerationStructureDeviceAddressInfoKHR* pInfo) { - // arbitrary - need to be aligned to 256 bytes - return 0x262144; + return (VkDeviceAddress)(pInfo->accelerationStructure) & ~(VkDeviceAddress)0xff; } static VKAPI_ATTR void VKAPI_CALL GetAccelerationStructureBuildSizesKHR( diff --git a/tests/unit/ray_tracing.cpp b/tests/unit/ray_tracing.cpp index 1649acecf32..9af37c408a0 100644 --- a/tests/unit/ray_tracing.cpp +++ b/tests/unit/ray_tracing.cpp @@ -1861,11 +1861,11 @@ TEST_F(NegativeRayTracing, AccelerationStructuresOverlappingMemory) { build_infos.emplace_back(std::move(blas)); } - // Since all the destination acceleration structures are bound to the same memory, 03702 will be triggered for each pair of - // elements in `build_infos` - for (size_t i = 0; i < binom(build_info_count, 2); ++i) { - m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03702"); - } + // Since all the destination acceleration structures are bound to the same memory, 03702 should be triggered for each pair + // of elements in `build_infos` + // => due to validation code optimisations, not *all* overlaps will be detected, + // but if there is *at least one*, it will *always+ be detected. + m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03702", 2); m_command_buffer.Begin(); vkt::as::BuildAccelerationStructuresKHR(m_command_buffer.handle(), build_infos); m_command_buffer.End(); @@ -1910,12 +1910,13 @@ TEST_F(NegativeRayTracing, AccelerationStructuresOverlappingMemory) { blas_vec.emplace_back(std::move(blas)); } - // Since all the source and destination acceleration structures are bound to the same memory, 03701 and 03702 will be + // Since all the source and destination acceleration structures are bound to the same memory, 03701 and 03702 should be // triggered for each pair of elements in `build_infos`, and 03668 for each element - for (size_t i = 0; i < binom(build_info_count, 2); ++i) { - m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03701"); - m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03702"); - } + // => due to validation code optimisations, not *all* overlaps described by 03701 and 03702 will be detected, + // but if there is *at least one*, it will *always+ be detected. + m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03701", 2); + m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03702", 2); + for (size_t i = 0; i < build_info_count; ++i) { m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-pInfos-03668"); } @@ -1976,9 +1977,9 @@ TEST_F(NegativeRayTracing, AccelerationStructuresOverlappingMemory2) { // Since all the scratch buffers are bound to the same memory, 03704 will be triggered for each pair of elements in // `build_infos` - for (size_t i = 0; i < binom(build_info_count, 2); ++i) { - m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03704"); - } + // => due to validation code optimisations, not *all* overlaps will be detected, + // but if there is *at least one*, it will *always+ be detected. + m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03704", 2); m_command_buffer.Begin(); vkt::as::BuildAccelerationStructuresKHR(m_command_buffer.handle(), build_infos); m_command_buffer.End(); @@ -2044,15 +2045,12 @@ TEST_F(NegativeRayTracing, AccelerationStructuresOverlappingMemory3) { } // Since all the destination acceleration structures and scratch buffers are bound to the same memory, 03702, 03703 and - // 03704 will be triggered for each pair of elements in `build_infos`. 03703 will also be triggered for individual elements. - for (size_t i = 0; i < binom(build_info_count, 2); ++i) { - m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03702"); - m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03703"); - m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03704"); - } - for (size_t i = 0; i < build_info_count; ++i) { - m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03703"); - } + // 03704 *should* be triggered for each pair of elements in `build_infos`. 03703 *should* also be triggered for individual + // elements. + // => due to validation code optimisations, not *all* overlaps will be detected, + // but if there is *at least one*, it will *always+ be detected. + m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03703", 3); + m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03704", 2); m_command_buffer.Begin(); vkt::as::BuildAccelerationStructuresKHR(m_command_buffer.handle(), blas_vec); m_command_buffer.End(); @@ -2134,15 +2132,12 @@ TEST_F(NegativeRayTracing, AccelerationStructuresOverlappingMemory4) { blas_vec.emplace_back(std::move(blas)); } - // Since all the source and destination acceleration structures are bound to the same memory, 03704 and 03705 will be - // triggered for each pair of elements in `build_infos`. 03705 will also be triggered for individual elements. - for (size_t i = 0; i < binom(build_info_count, 2); ++i) { - m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03704"); - m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03705"); - } - for (size_t i = 0; i < build_info_count; ++i) { - m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03705"); - } + // Since all the source and destination acceleration structures are bound to the same memory, 03704 and 03705 *should* be + // triggered for each pair of elements in `build_infos`. 03705 *should* also be triggered for individual elements. + // => due to validation code optimisations, not *all* overlaps will be detected, + // but if there is *at least one*, it will *always+ be detected. + m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03704", 2); + m_errorMonitor->SetDesiredError("VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03705", 3); m_command_buffer.Begin(); vkt::as::BuildAccelerationStructuresKHR(m_command_buffer.handle(), blas_vec);