Skip to content

Commit 09782e0

Browse files
committed
layers: Move AS addr tracking
From GPU-AV to core Add 08028
1 parent 430c8b9 commit 09782e0

File tree

9 files changed

+124
-101
lines changed

9 files changed

+124
-101
lines changed

layers/core_checks/cc_descriptor.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3535,6 +3535,15 @@ bool CoreChecks::PreCallValidateGetDescriptorEXT(VkDevice device, const VkDescri
35353535

35363536
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: // not full implemented
35373537
data_field = Field::accelerationStructure;
3538+
if (pDescriptorInfo->data.accelerationStructure != 0) {
3539+
if (auto as_array = GetAccelerationStructuresByAddress(pDescriptorInfo->data.accelerationStructure);
3540+
as_array.empty()) {
3541+
skip |= LogError("VUID-VkDescriptorGetInfoEXT-type-08028", device, descriptor_info_loc.dot(Field::type),
3542+
"is VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, but accelerationStructure (0x%" PRIx64
3543+
") is not an address obtained from a currently existing VkAccelerationStructureKHR.",
3544+
pDescriptorInfo->data.accelerationStructure);
3545+
}
3546+
}
35383547
break;
35393548
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
35403549
data_field = Field::accelerationStructure;

layers/gpuav/core/gpuav.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
/* Copyright (c) 2018-2025 The Khronos Group Inc.
2-
* Copyright (c) 2018-2025 Valve Corporation
3-
* Copyright (c) 2018-2025 LunarG, Inc.
1+
/* Copyright (c) 2018-2026 The Khronos Group Inc.
2+
* Copyright (c) 2018-2026 Valve Corporation
3+
* Copyright (c) 2018-2026 LunarG, Inc.
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
66
* you may not use this file except in compliance with the License.
@@ -173,12 +173,6 @@ class Validator : public GpuShaderInstrumentor {
173173
void PreCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
174174
uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ,
175175
const RecordObject& record_obj) final;
176-
void PreCallRecordDestroyAccelerationStructureKHR(VkDevice device, VkAccelerationStructureKHR accelerationStructure,
177-
const VkAllocationCallbacks* pAllocator,
178-
const RecordObject& record_obj) final;
179-
void PostCallRecordGetAccelerationStructureDeviceAddressKHR(VkDevice device,
180-
const VkAccelerationStructureDeviceAddressInfoKHR* pInfo,
181-
const RecordObject& record_obj) final;
182176
void PreCallRecordCmdBuildAccelerationStructuresKHR(VkCommandBuffer commandBuffer, uint32_t infoCount,
183177
const VkAccelerationStructureBuildGeometryInfoKHR* pInfos,
184178
const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos,

layers/gpuav/core/gpuav_record.cpp

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
/* Copyright (c) 2018-2025 The Khronos Group Inc.
2-
* Copyright (c) 2018-2025 Valve Corporation
3-
* Copyright (c) 2018-2025 LunarG, Inc.
1+
/* Copyright (c) 2018-2026 The Khronos Group Inc.
2+
* Copyright (c) 2018-2026 Valve Corporation
3+
* Copyright (c) 2018-2026 LunarG, Inc.
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
66
* you may not use this file except in compliance with the License.
@@ -606,18 +606,6 @@ void Validator::PreCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, u
606606
record_obj);
607607
}
608608

609-
void Validator::PreCallRecordDestroyAccelerationStructureKHR(VkDevice device, VkAccelerationStructureKHR accelerationStructure,
610-
const VkAllocationCallbacks *pAllocator,
611-
const RecordObject &record_obj) {
612-
gpuav::valcmd::RemoveAccelerationStrutureDeviceAddress(*this, accelerationStructure);
613-
}
614-
615-
void Validator::PostCallRecordGetAccelerationStructureDeviceAddressKHR(VkDevice device,
616-
const VkAccelerationStructureDeviceAddressInfoKHR *pInfo,
617-
const RecordObject &record_obj) {
618-
gpuav::valcmd::RecordGetAccelerationStructureDeviceAddress(*this, pInfo->accelerationStructure, record_obj.device_address);
619-
}
620-
621609
void Validator::PreCallRecordCmdBuildAccelerationStructuresKHR(
622610
VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR *pInfos,
623611
const VkAccelerationStructureBuildRangeInfoKHR *const *ppBuildRangeInfos, const RecordObject &record_obj) {

layers/gpuav/validation_cmd/gpuav_ray_tracing.cpp

Lines changed: 16 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -183,53 +183,6 @@ struct BuildAccelerationStructuresValidationShader {
183183
std::vector<VkWriteDescriptorSet> GetDescriptorWrites() const { return {}; }
184184
};
185185

186-
struct AccelerationStructuresWithAddressesArray {
187-
std::shared_mutex map_mutex;
188-
std::vector<vvl::AccelerationStructureKHR*> array;
189-
};
190-
191-
void RecordGetAccelerationStructureDeviceAddress(Validator& gpuav, VkAccelerationStructureKHR as, VkDeviceAddress as_addr) {
192-
if (!gpuav.gpuav_settings.validate_acceleration_structures_builds) {
193-
return;
194-
}
195-
196-
if (as_addr == 0) {
197-
return;
198-
}
199-
if (auto as_state = gpuav.Get<vvl::AccelerationStructureKHR>(as)) {
200-
as_state->acceleration_structure_address = as_addr;
201-
AccelerationStructuresWithAddressesArray& as_with_addresses =
202-
gpuav.shared_resources_cache.GetOrCreate<AccelerationStructuresWithAddressesArray>();
203-
WriteLockGuard lock(as_with_addresses.map_mutex);
204-
if (as_with_addresses.array.capacity() <= (as_with_addresses.array.size() + 1)) {
205-
as_with_addresses.array.reserve(as_with_addresses.array.capacity() * 2);
206-
}
207-
as_with_addresses.array.emplace_back(as_state.get());
208-
}
209-
}
210-
211-
void RemoveAccelerationStrutureDeviceAddress(Validator& gpuav, VkAccelerationStructureKHR as) {
212-
if (!gpuav.gpuav_settings.validate_acceleration_structures_builds) {
213-
return;
214-
}
215-
if (auto as_state = gpuav.Get<vvl::AccelerationStructureKHR>(as)) {
216-
if (as_state->acceleration_structure_address != 0) {
217-
auto* as_with_addresses = gpuav.shared_resources_cache.TryGet<AccelerationStructuresWithAddressesArray>();
218-
if (as_with_addresses) {
219-
WriteLockGuard lock(as_with_addresses->map_mutex);
220-
auto as_found_it = std::find(as_with_addresses->array.begin(), as_with_addresses->array.end(), as_state.get());
221-
while (as_found_it != as_with_addresses->array.end()) {
222-
const size_t i = std::distance(as_with_addresses->array.begin(), as_found_it);
223-
std::swap(as_with_addresses->array[i], as_with_addresses->array[as_with_addresses->array.size() - 1]);
224-
as_with_addresses->array.resize(as_with_addresses->array.size() - 1);
225-
as_found_it = as_with_addresses->array.begin() + i;
226-
}
227-
}
228-
as_state->acceleration_structure_address = 0;
229-
}
230-
}
231-
}
232-
233186
class DummyBLAS {
234187
public:
235188
DummyBLAS(Validator& gpuav, CommandBufferSubState& cb_state)
@@ -477,34 +430,29 @@ void BuildAccelerationStructures(Validator& gpuav, const Location& loc, CommandB
477430
VkCommandBuffer per_submission_cb) {
478431
VVL_ZoneScopedN("validate_as_builds_pre_submit");
479432

480-
auto* as_with_addresses = gpuav.shared_resources_cache.TryGet<AccelerationStructuresWithAddressesArray>();
481-
if (!as_with_addresses) {
482-
return;
483-
}
484-
485-
ReadLockGuard lock(as_with_addresses->map_mutex);
433+
ReadLockGuard lock(gpuav.device_state->as_with_addresses.array_mutex);
486434

487435
// valid AS addresses buffer
488436
vko::BufferRange as_addresses_buffer = cb.gpu_resources_manager.GetHostCoherentBufferRange(
489-
2 * sizeof(uint32_t) + as_with_addresses->array.size() * sizeof(uint64_t));
437+
2 * sizeof(uint32_t) + gpuav.device_state->as_with_addresses.array.size() * sizeof(uint64_t));
490438
auto accel_struct_addresses_buffer_u32_ptr = (uint32_t*)as_addresses_buffer.offset_mapped_ptr;
491439

492-
*accel_struct_addresses_buffer_u32_ptr = (uint32_t)as_with_addresses->array.size();
440+
*accel_struct_addresses_buffer_u32_ptr = (uint32_t)gpuav.device_state->as_with_addresses.array.size();
493441

494442
auto as_addresses_ptr = (uint64_t*)(accel_struct_addresses_buffer_u32_ptr + 2);
495443

496444
// valid AS metadata buffer
497-
vko::BufferRange as_metadatas_buffer =
498-
cb.gpu_resources_manager.GetHostCachedBufferRange(as_with_addresses->array.size() * sizeof(uint32_t));
445+
vko::BufferRange as_metadatas_buffer = cb.gpu_resources_manager.GetHostCachedBufferRange(
446+
gpuav.device_state->as_with_addresses.array.size() * sizeof(uint32_t));
499447
auto as_metadatas_ptr = (uint32_t*)(as_metadatas_buffer.offset_mapped_ptr);
500448

501449
// valid AS buffer address ranges buffer
502-
vko::BufferRange as_buffer_addr_ranges_buffer =
503-
cb.gpu_resources_manager.GetHostCoherentBufferRange(as_with_addresses->array.size() * (2 * sizeof(uint64_t)));
450+
vko::BufferRange as_buffer_addr_ranges_buffer = cb.gpu_resources_manager.GetHostCoherentBufferRange(
451+
gpuav.device_state->as_with_addresses.array.size() * (2 * sizeof(uint64_t)));
504452
auto as_buffer_addr_ranges_ptr = (uint64_t*)(as_buffer_addr_ranges_buffer.offset_mapped_ptr);
505453

506454
uint32_t written_count = 0;
507-
for (const vvl::AccelerationStructureKHR* as : as_with_addresses->array) {
455+
for (const vvl::AccelerationStructureKHR* as : gpuav.device_state->as_with_addresses.array) {
508456
as_addresses_ptr[written_count] = as->acceleration_structure_address;
509457
uint32_t metadata = 0;
510458
metadata |= SET_BUILD_AS_METADATA_BUFFER_STATUS(as->buffer_state && !as->buffer_state->Destroyed());
@@ -648,14 +596,14 @@ void BuildAccelerationStructures(Validator& gpuav, const Location& loc, CommandB
648596
const char* vvl_bug_msg =
649597
"this is most likely a validation layer bug. Please file an issue at "
650598
"https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues ";
651-
auto& as_with_addresses = gpuav.shared_resources_cache.Get<AccelerationStructuresWithAddressesArray>();
652-
const auto as_found_it = std::find_if(as_with_addresses.array.begin(), as_with_addresses.array.end(),
653-
[blas_in_tlas_addr](vvl::AccelerationStructureKHR* as) {
654-
return as->acceleration_structure_address == blas_in_tlas_addr;
655-
});
599+
const auto as_found_it =
600+
std::find_if(gpuav.device_state->as_with_addresses.array.begin(), gpuav.device_state->as_with_addresses.array.end(),
601+
[blas_in_tlas_addr](vvl::AccelerationStructureKHR* as) {
602+
return as->acceleration_structure_address == blas_in_tlas_addr;
603+
});
656604
std::stringstream ss_as;
657605
std::stringstream ss_as_buffer;
658-
if (as_found_it != as_with_addresses.array.end()) {
606+
if (as_found_it != gpuav.device_state->as_with_addresses.array.end()) {
659607
ss_as << "Acceleration structure corresponding to reference: " << gpuav.FormatHandle((*as_found_it)->VkHandle());
660608
if ((*as_found_it)->buffer_state) {
661609
ss_as_buffer << "(" << gpuav.FormatHandle((*as_found_it)->buffer_state->VkHandle()) << ") ";
@@ -691,7 +639,7 @@ void BuildAccelerationStructures(Validator& gpuav, const Location& loc, CommandB
691639
}
692640
case kErrorSubCode_PreBuildAccelerationStructures_InvalidASType: {
693641
std::stringstream ss_as_type;
694-
if (as_found_it != as_with_addresses.array.end()) {
642+
if (as_found_it != gpuav.device_state->as_with_addresses.array.end()) {
695643
ss_as_type << ", but has type " << string_VkAccelerationStructureTypeKHR((*as_found_it)->create_info.type)
696644
<< ". ";
697645
}
@@ -705,7 +653,7 @@ void BuildAccelerationStructures(Validator& gpuav, const Location& loc, CommandB
705653
const uint32_t blas_built_in_cmd_i = error_record[kValCmdErrorPayloadDword_4];
706654
const BlasBuiltInCmd& blas_built_in_cmd = blas_built_in_cmd_array[blas_built_in_cmd_i];
707655
std::stringstream error_ss;
708-
if (as_found_it != as_with_addresses.array.end()) {
656+
if (as_found_it != gpuav.device_state->as_with_addresses.array.end()) {
709657
const vvl::range<VkDeviceAddress> blas_in_tlas_buffer_addr_range = (*as_found_it)->GetDeviceAddressRange();
710658
const vvl::range<VkDeviceAddress> blas_built_in_cmd_buffer_addr_range =
711659
blas_built_in_cmd.blas->GetDeviceAddressRange();

layers/gpuav/validation_cmd/gpuav_ray_tracing.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
/* Copyright (c) 2018-2025 The Khronos Group Inc.
2-
* Copyright (c) 2018-2025 Valve Corporation
3-
* Copyright (c) 2018-2025 LunarG, Inc.
1+
/* Copyright (c) 2018-2026 The Khronos Group Inc.
2+
* Copyright (c) 2018-2026 Valve Corporation
3+
* Copyright (c) 2018-2026 LunarG, Inc.
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
66
* you may not use this file except in compliance with the License.
@@ -30,9 +30,6 @@ namespace valcmd {
3030
void TraceRaysIndirect(Validator &gpuav, const Location &loc, CommandBufferSubState &cb_state, const LastBound &last_bound,
3131
VkDeviceAddress indirect_data_address);
3232

33-
void RecordGetAccelerationStructureDeviceAddress(Validator &gpuav, VkAccelerationStructureKHR as, VkDeviceAddress as_addr);
34-
void RemoveAccelerationStrutureDeviceAddress(Validator &gpuav, VkAccelerationStructureKHR as);
35-
3633
void BuildAccelerationStructures(Validator &gpuav, const Location &loc, CommandBufferSubState &cb_state,
3734
const LastBound &last_bound, uint32_t info_count,
3835
const VkAccelerationStructureBuildGeometryInfoKHR *infos,

layers/state_tracker/state_tracker.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2768,6 +2768,19 @@ void DeviceState::PostCallRecordCmdCopyAccelerationStructureNV(VkCommandBuffer c
27682768
void DeviceState::PreCallRecordDestroyAccelerationStructureKHR(VkDevice device, VkAccelerationStructureKHR accelerationStructure,
27692769
const VkAllocationCallbacks *pAllocator,
27702770
const RecordObject &record_obj) {
2771+
if (auto as_state = Get<vvl::AccelerationStructureKHR>(accelerationStructure)) {
2772+
if (as_state->acceleration_structure_address != 0) {
2773+
WriteLockGuard lock(as_with_addresses.array_mutex);
2774+
auto as_found_it = std::find(as_with_addresses.array.begin(), as_with_addresses.array.end(), as_state.get());
2775+
while (as_found_it != as_with_addresses.array.end()) {
2776+
const size_t i = std::distance(as_with_addresses.array.begin(), as_found_it);
2777+
std::swap(as_with_addresses.array[i], as_with_addresses.array[as_with_addresses.array.size() - 1]);
2778+
as_with_addresses.array.resize(as_with_addresses.array.size() - 1);
2779+
as_found_it = as_with_addresses.array.begin() + i;
2780+
}
2781+
as_state->acceleration_structure_address = 0;
2782+
}
2783+
}
27712784
Destroy<AccelerationStructureKHR>(accelerationStructure);
27722785
}
27732786

@@ -6037,6 +6050,46 @@ void DeviceState::PostCallRecordCmdBindTransformFeedbackBuffersEXT(VkCommandBuff
60376050
cb_state->transform_feedback_buffers_bound = bindingCount;
60386051
}
60396052

6053+
void DeviceState::PostCallRecordGetAccelerationStructureDeviceAddressKHR(VkDevice device,
6054+
const VkAccelerationStructureDeviceAddressInfoKHR *pInfo,
6055+
const RecordObject &record_obj) {
6056+
if (!pInfo) {
6057+
return;
6058+
}
6059+
if (record_obj.device_address == 0) {
6060+
return;
6061+
}
6062+
if (auto as_state = Get<vvl::AccelerationStructureKHR>(pInfo->accelerationStructure)) {
6063+
as_state->acceleration_structure_address = record_obj.device_address;
6064+
WriteLockGuard lock(as_with_addresses.array_mutex);
6065+
if (as_with_addresses.array.capacity() <= (as_with_addresses.array.size() + 1)) {
6066+
as_with_addresses.array.reserve(as_with_addresses.array.capacity() * 2);
6067+
}
6068+
as_with_addresses.array.emplace_back(as_state.get());
6069+
}
6070+
}
6071+
6072+
small_vector<const vvl::AccelerationStructureKHR *, 2> DeviceState::GetAccelerationStructuresByAddress(
6073+
VkDeviceAddress address) const {
6074+
small_vector<const vvl::AccelerationStructureKHR *, 2> as_vector;
6075+
if (address == 0) {
6076+
return as_vector;
6077+
}
6078+
6079+
ReadLockGuard lock(as_with_addresses.array_mutex);
6080+
auto as_found_it =
6081+
std::find_if(as_with_addresses.array.begin(), as_with_addresses.array.end(),
6082+
[address](vvl::AccelerationStructureKHR *as) { return as->acceleration_structure_address == address; });
6083+
6084+
while (as_found_it != as_with_addresses.array.end()) {
6085+
as_vector.emplace_back(*as_found_it);
6086+
as_found_it = std::find_if(as_found_it + 1, as_with_addresses.array.end(), [address](vvl::AccelerationStructureKHR *as) {
6087+
return as->acceleration_structure_address == address;
6088+
});
6089+
}
6090+
return as_vector;
6091+
}
6092+
60406093
void DeviceState::PreCallRecordLatencySleepNV(VkDevice device, VkSwapchainKHR swapchain, const VkLatencySleepInfoNV *pSleepInfo,
60416094
const RecordObject &record_obj) {
60426095
if (auto semaphore_state = Get<Semaphore>(pSleepInfo->signalSemaphore)) {

0 commit comments

Comments
 (0)