Skip to content

Commit 88714cc

Browse files
committed
layers: Fix PTLAS descriptor handling and overlap validation
tests: Fix some VUIDs and added more PTLAS coverage
1 parent 971893e commit 88714cc

File tree

11 files changed

+138
-25
lines changed

11 files changed

+138
-25
lines changed

layers/best_practices/bp_pipeline.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ bool BestPractices::PreCallValidateCreatePipelineLayout(VkDevice device, const V
416416
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
417417
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
418418
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
419+
case VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV:
419420
descriptor_type_size = 8;
420421
break;
421422
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:

layers/chassis/dispatch_object_manual.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,6 +1609,12 @@ void *BuildUnwrappedUpdateTemplateBuffer(Device *layer_data, uint64_t descriptor
16091609
template_entries.emplace_back(offset, kVulkanObjectTypeAccelerationStructureKHR, CastToUint64(wrapped_entry),
16101610
0);
16111611
} break;
1612+
case VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV: {
1613+
// PTLAS uses VkDeviceAddress directly, not an opaque handle - no unwrapping needed
1614+
allocation_size = std::max(allocation_size, offset + sizeof(VkDeviceAddress));
1615+
template_entries.emplace_back(offset, kVulkanObjectTypeUnknown, CastToUint64(update_entry),
1616+
sizeof(VkDeviceAddress));
1617+
} break;
16121618
default:
16131619
assert(false);
16141620
break;
@@ -2287,6 +2293,7 @@ void Device::GetDescriptorEXT(VkDevice device, const VkDescriptorGetInfoEXT *pDe
22872293
break;
22882294
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
22892295
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
2296+
case VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV:
22902297
local_pDescriptorInfo.data.accelerationStructure = pDescriptorInfo->data.accelerationStructure;
22912298
break;
22922299
default:

layers/core_checks/cc_descriptor.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,6 +1504,7 @@ vvl::DecodedTemplateUpdate::DecodedTemplateUpdate(const vvl::DeviceState &device
15041504
inline_infos.resize(create_info.descriptorUpdateEntryCount); // Make sure we have one if we need it
15051505
inline_infos_khr.resize(create_info.descriptorUpdateEntryCount);
15061506
inline_infos_nv.resize(create_info.descriptorUpdateEntryCount);
1507+
inline_infos_ptlas.resize(create_info.descriptorUpdateEntryCount);
15071508
desc_writes.reserve(create_info.descriptorUpdateEntryCount); // emplaced, so reserved without initialization
15081509
VkDescriptorSetLayout effective_dsl = create_info.templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET
15091510
? create_info.descriptorSetLayout
@@ -1594,6 +1595,17 @@ vvl::DecodedTemplateUpdate::DecodedTemplateUpdate(const vvl::DeviceState &device
15941595
write_entry.descriptorCount = inline_info_nv->accelerationStructureCount;
15951596
break;
15961597
}
1598+
case VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV: {
1599+
VkWriteDescriptorSetPartitionedAccelerationStructureNV *inline_info_ptlas = &inline_infos_ptlas[i];
1600+
inline_info_ptlas->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_PARTITIONED_ACCELERATION_STRUCTURE_NV;
1601+
inline_info_ptlas->pNext = nullptr;
1602+
inline_info_ptlas->accelerationStructureCount = descriptor_update_entry.descriptorCount;
1603+
inline_info_ptlas->pAccelerationStructures = reinterpret_cast<const VkDeviceAddress *>(update_entry);
1604+
write_entry.pNext = inline_info_ptlas;
1605+
// descriptorCount must match the accelerationStructureCount
1606+
write_entry.descriptorCount = inline_info_ptlas->accelerationStructureCount;
1607+
break;
1608+
}
15971609
default:
15981610
assert(false);
15991611
break;
@@ -1603,7 +1615,8 @@ vvl::DecodedTemplateUpdate::DecodedTemplateUpdate(const vvl::DeviceState &device
16031615
// If acceleration structure, we only create a single VkWriteDescriptorSet and map the actually AS into
16041616
// VkWriteDescriptorSetAccelerationStructureKHR
16051617
if (descriptor_update_entry.descriptorType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR ||
1606-
descriptor_update_entry.descriptorType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV) {
1618+
descriptor_update_entry.descriptorType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV ||
1619+
descriptor_update_entry.descriptorType == VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV) {
16071620
break;
16081621
}
16091622
}
@@ -5475,8 +5488,7 @@ bool CoreChecks::PreCallValidateWriteResourceDescriptorsEXT(VkDevice device, uin
54755488
skip |=
54765489
ValidateDeviceAddressRange(address_range.address, address_range.size, false, data_loc.dot(Field::pAddressRange),
54775490
LogObjectList(device), buffer_usage, usage_vuid);
5478-
} else if (resource.type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR ||
5479-
resource.type == VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV) {
5491+
} else if (resource.type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR) {
54805492
// TODO - not sure what this covers that VUID-VkResourceDescriptorInfoEXT-type-11484 doesn't
54815493
if (auto as_array = GetAccelerationStructuresByAddress(address_range.address); as_array.empty()) {
54825494
std::stringstream ss;
@@ -5496,6 +5508,13 @@ bool CoreChecks::PreCallValidateWriteResourceDescriptorsEXT(VkDevice device, uin
54965508
skip |= LogError("VUID-VkResourceDescriptorInfoEXT-type-11483", device,
54975509
data_loc.dot(Field::pAddressRange).dot(Field::address), "%s", ss.str().c_str());
54985510
}
5511+
} else if (resource.type == VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV) {
5512+
// PTLAS uses buffer addresses directly, not VkAccelerationStructureKHR objects
5513+
// Validate that the address points to a buffer with ACCELERATION_STRUCTURE_STORAGE_BIT
5514+
skip |= ValidateDeviceAddressRange(address_range.address, address_range.size, false,
5515+
data_loc.dot(Field::pAddressRange), LogObjectList(device),
5516+
VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR,
5517+
"VUID-VkResourceDescriptorInfoEXT-type-11483");
54995518
} else if (resource.type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV) {
55005519
if (address_range.size != 0) {
55015520
skip |= LogError("VUID-VkResourceDescriptorInfoEXT-type-11468", device,

layers/core_checks/cc_ray_tracing.cpp

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2453,22 +2453,26 @@ bool CoreChecks::PreCallValidateCmdBuildPartitionedAccelerationStructuresNV(
24532453
}
24542454
}
24552455

2456-
if (pBuildInfo->srcAccelerationStructureData && pBuildInfo->dstAccelerationStructureData) {
2456+
// Check for src vs dst overlap, but only if they are different addresses (in-place update is allowed)
2457+
if (pBuildInfo->srcAccelerationStructureData && pBuildInfo->dstAccelerationStructureData &&
2458+
pBuildInfo->srcAccelerationStructureData != pBuildInfo->dstAccelerationStructureData) {
24572459
const auto src_buffer_states = GetBuffersByAddress(pBuildInfo->srcAccelerationStructureData);
24582460
const auto dst_buffer_states = GetBuffersByAddress(pBuildInfo->dstAccelerationStructureData);
24592461
for (const auto &src_buffer_state : src_buffer_states) {
2460-
vvl::range<VkDeviceAddress> src_address_range = src_buffer_state->DeviceAddressRange();
2462+
const vvl::range<VkDeviceAddress> src_address_range = src_buffer_state->DeviceAddressRange();
24612463
if (!src_address_range.empty()) {
2462-
for (const auto &buffer_state : dst_buffer_states) {
2463-
const vvl::range<VkDeviceAddress> buffer_address_range = buffer_state->DeviceAddressRange();
2464-
if (buffer_address_range.intersects(src_address_range)) {
2465-
const LogObjectList objlist(commandBuffer, buffer_state->Handle(), src_buffer_state->Handle());
2466-
skip |=
2467-
LogError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10549", objlist,
2468-
error_obj.location.dot(Field::pBuildInfo).dot(Field::dstAccelerationStructureData),
2469-
"%s address range %s intersects srcAccelerationStructureData address range %s",
2470-
FormatHandle(buffer_state->Handle()).c_str(), string_range_hex(buffer_address_range).c_str(),
2471-
string_range_hex(src_address_range).c_str());
2464+
for (const auto &dst_buffer_state : dst_buffer_states) {
2465+
const vvl::range<VkDeviceAddress> dst_address_range = dst_buffer_state->DeviceAddressRange();
2466+
if (src_address_range.intersects(dst_address_range)) {
2467+
const LogObjectList objlist(commandBuffer, src_buffer_state->Handle(), dst_buffer_state->Handle());
2468+
skip |= LogError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10549", objlist,
2469+
error_obj.location.dot(Field::pBuildInfo),
2470+
"srcAccelerationStructureData %s address range %s intersects "
2471+
"dstAccelerationStructureData %s address range %s",
2472+
FormatHandle(src_buffer_state->Handle()).c_str(),
2473+
string_range_hex(src_address_range).c_str(),
2474+
FormatHandle(dst_buffer_state->Handle()).c_str(),
2475+
string_range_hex(dst_address_range).c_str());
24722476
}
24732477
}
24742478
}

layers/core_checks/cc_spirv.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,13 +384,13 @@ static void TypeToDescriptorTypeSet(const spirv::Module &module_state, uint32_t
384384

385385
// The OpType are alias, but the Descriptor Types are different
386386
case spv::OpTypeAccelerationStructureKHR:
387-
// Only KHR or NV base accelleration structure is selected
387+
// Only KHR or NV base acceleration structure is selected
388388
if (module_state.HasCapability(spv::CapabilityRayTracingNV)) {
389389
out_data.descriptor_type_set.insert(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV);
390390
} else {
391391
out_data.descriptor_type_set.insert(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
392392
}
393-
393+
// Additionally allow PTLAS if shader uses cluster acceleration structure features
394394
if (module_state.HasCapability(spv::CapabilityRayTracingClusterAccelerationStructureNV)) {
395395
out_data.descriptor_type_set.insert(VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV);
396396
}
@@ -3637,4 +3637,4 @@ bool CoreChecks::ValidateDescriptorHeapStructs(const spirv::Module &module_state
36373637
}
36383638

36393639
return skip;
3640-
}
3640+
}

layers/object_tracker/object_lifetime_validation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ bool Device::ValidateDescriptorWrite(VkWriteDescriptorSet const *desc, bool is_p
541541
break;
542542
}
543543

544-
// VkWriteDescriptorSetPartitionedAccelerationStructureNV contains no VkObjects to validate
544+
// PTLAS uses VkDeviceAddress values, not VkAccelerationStructureKHR handles - no objects to validate
545545
case VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV:
546546
// Inline has no objects, so nothing to validate
547547
case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:

layers/state_tracker/descriptor_sets.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,7 @@ struct DecodedTemplateUpdate {
844844
std::vector<VkWriteDescriptorSetInlineUniformBlock> inline_infos;
845845
std::vector<VkWriteDescriptorSetAccelerationStructureKHR> inline_infos_khr;
846846
std::vector<VkWriteDescriptorSetAccelerationStructureNV> inline_infos_nv;
847+
std::vector<VkWriteDescriptorSetPartitionedAccelerationStructureNV> inline_infos_ptlas;
847848
DecodedTemplateUpdate(const DeviceState &device_data, VkDescriptorSet descriptorSet,
848849
const DescriptorUpdateTemplate &template_state, const void *pData,
849850
VkDescriptorSetLayout push_layout = VK_NULL_HANDLE);

layers/sync/sync_commandbuffer.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,9 @@ static SyncAccessIndex GetSyncStageAccessIndexsByDescriptorSet(VkDescriptorType
195195
if (descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
196196
return stage_accesses.uniform_read;
197197
}
198-
if (descriptor_type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR) {
198+
if (descriptor_type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR ||
199+
descriptor_type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV ||
200+
descriptor_type == VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV) {
199201
return stage_accesses.acceleration_structure_read;
200202
}
201203

tests/unit/descriptor_heap_positive.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3575,4 +3575,33 @@ TEST_F(PositiveDescriptorHeap, SingleElementNoArray) {
35753575
uint32_t* data = static_cast<uint32_t*>(buffer.Memory().Map());
35763576
ASSERT_EQ(data[0], src_data);
35773577
}
3578+
}
3579+
3580+
TEST_F(PositiveDescriptorHeap, PartitionedAccelerationStructure) {
3581+
TEST_DESCRIPTION("Test WriteResourceDescriptorsEXT with PTLAS descriptor type");
3582+
SetTargetApiVersion(VK_API_VERSION_1_2);
3583+
AddRequiredExtensions(VK_NV_PARTITIONED_ACCELERATION_STRUCTURE_EXTENSION_NAME);
3584+
AddRequiredFeature(vkt::Feature::rayTracingPipeline);
3585+
AddRequiredFeature(vkt::Feature::accelerationStructure);
3586+
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
3587+
AddRequiredFeature(vkt::Feature::partitionedAccelerationStructure);
3588+
RETURN_IF_SKIP(InitBasicDescriptorHeap());
3589+
3590+
const VkDeviceSize descriptor_size =
3591+
vk::GetPhysicalDeviceDescriptorSizeEXT(gpu_, VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV);
3592+
std::vector<uint8_t> data(static_cast<size_t>(descriptor_size));
3593+
3594+
// Create buffer with required usage flags for PTLAS
3595+
vkt::Buffer ptlas_buffer(*m_device, 4096,
3596+
VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
3597+
vkt::device_address);
3598+
3599+
VkDeviceAddressRangeEXT device_address_range = {ptlas_buffer.Address(), descriptor_size};
3600+
3601+
VkResourceDescriptorInfoEXT resource_info = vku::InitStructHelper();
3602+
resource_info.type = VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV;
3603+
resource_info.data.pAddressRange = &device_address_range;
3604+
3605+
VkHostAddressRangeEXT descriptor = {data.data(), static_cast<size_t>(descriptor_size)};
3606+
vk::WriteResourceDescriptorsEXT(*m_device, 1u, &resource_info, &descriptor);
35783607
}

tests/unit/ray_tracing.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4244,10 +4244,12 @@ TEST_F(NegativeRayTracing, BuildPartitionedAccelerationStructureInfo) {
42444244
command_info.srcInfosCount = count_buffer_address;
42454245

42464246
m_command_buffer.Begin();
4247-
m_errorMonitor->SetDesiredError("VUID-VkBuildPartitionedAccelerationStructureInfoNV-dstAccelerationStructureData-10561");
4247+
m_errorMonitor->SetDesiredError("VUID-VkBuildPartitionedAccelerationStructureInfoNV-dstAccelerationStructureData-parameter");
4248+
m_errorMonitor->SetDesiredError("VUID-VkBuildPartitionedAccelerationStructureInfoNV-srcInfos-parameter");
42484249
vk::CmdBuildPartitionedAccelerationStructuresNV(m_command_buffer, &command_info);
42494250
m_errorMonitor->VerifyFound();
42504251
command_info.dstAccelerationStructureData = ptlas_buffer_address;
4252+
command_info.srcInfos = count_buffer_address; // Use a valid address going forward
42514253
m_command_buffer.End();
42524254

42534255
// add 1 to cause aligned error
@@ -4267,7 +4269,7 @@ TEST_F(NegativeRayTracing, BuildPartitionedAccelerationStructureInfo) {
42674269
command_info.scratchData = 0;
42684270
m_command_buffer.Begin();
42694271
// scratchData must not be NULL
4270-
m_errorMonitor->SetDesiredError("VUID-VkBuildPartitionedAccelerationStructureInfoNV-scratchData-10558");
4272+
m_errorMonitor->SetDesiredError("VUID-VkBuildPartitionedAccelerationStructureInfoNV-scratchData-parameter");
42714273
vk::CmdBuildPartitionedAccelerationStructuresNV(m_command_buffer, &command_info);
42724274
m_errorMonitor->VerifyFound();
42734275
m_command_buffer.End();
@@ -4290,8 +4292,6 @@ TEST_F(NegativeRayTracing, BuildPartitionedAccelerationStructureInfo) {
42904292
m_errorMonitor->SetDesiredError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10542");
42914293
m_errorMonitor->SetDesiredError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10544");
42924294
m_errorMonitor->SetDesiredError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10545");
4293-
// Add this VU to avoid dst and src addres overlap warning
4294-
m_errorMonitor->SetDesiredError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10549");
42954295
vk::CmdBuildPartitionedAccelerationStructuresNV(m_command_buffer, &command_info);
42964296
m_errorMonitor->VerifyFound();
42974297
m_command_buffer.End();
@@ -4300,12 +4300,22 @@ TEST_F(NegativeRayTracing, BuildPartitionedAccelerationStructureInfo) {
43004300
command_info.dstAccelerationStructureData = scratch_buffer_address;
43014301
command_info.srcAccelerationStructureData = scratch_buffer_address;
43024302
m_command_buffer.Begin();
4303-
m_errorMonitor->SetDesiredError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10549");
43044303
m_errorMonitor->SetDesiredError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10548");
43054304
m_errorMonitor->SetDesiredError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10547");
43064305
vk::CmdBuildPartitionedAccelerationStructuresNV(m_command_buffer, &command_info);
43074306
m_errorMonitor->VerifyFound();
43084307
m_command_buffer.End();
4308+
4309+
// Test src vs dst overlap when they are different addresses (in-place update src==dst is allowed)
4310+
// Use 256-byte aligned offset so alignment checks pass, but still within same buffer (overlapping)
4311+
command_info.scratchData = scratch_buffer_address;
4312+
command_info.dstAccelerationStructureData = correct_ptlas_buffer_address;
4313+
command_info.srcAccelerationStructureData = correct_ptlas_buffer_address + 256; // Different but overlapping (same buffer)
4314+
m_command_buffer.Begin();
4315+
m_errorMonitor->SetDesiredError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10549");
4316+
vk::CmdBuildPartitionedAccelerationStructuresNV(m_command_buffer, &command_info);
4317+
m_errorMonitor->VerifyFound();
4318+
m_command_buffer.End();
43094319
}
43104320

43114321
TEST_F(NegativeRayTracing, BuildPartitionedAccelerationStrutureInfoBadMemory) {

0 commit comments

Comments
 (0)