Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions layers/best_practices/bp_pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ bool BestPractices::PreCallValidateCreatePipelineLayout(VkDevice device, const V
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
case VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV:
descriptor_type_size = 8;
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
Expand Down
7 changes: 7 additions & 0 deletions layers/chassis/dispatch_object_manual.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1609,6 +1609,12 @@ void *BuildUnwrappedUpdateTemplateBuffer(Device *layer_data, uint64_t descriptor
template_entries.emplace_back(offset, kVulkanObjectTypeAccelerationStructureKHR, CastToUint64(wrapped_entry),
0);
} break;
case VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV: {
// PTLAS uses VkDeviceAddress directly, not an opaque handle - no unwrapping needed
allocation_size = std::max(allocation_size, offset + sizeof(VkDeviceAddress));
template_entries.emplace_back(offset, kVulkanObjectTypeUnknown, CastToUint64(update_entry),
sizeof(VkDeviceAddress));
} break;
default:
assert(false);
break;
Expand Down Expand Up @@ -2287,6 +2293,7 @@ void Device::GetDescriptorEXT(VkDevice device, const VkDescriptorGetInfoEXT *pDe
break;
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
case VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV:
local_pDescriptorInfo.data.accelerationStructure = pDescriptorInfo->data.accelerationStructure;
break;
default:
Expand Down
25 changes: 22 additions & 3 deletions layers/core_checks/cc_descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1504,6 +1504,7 @@ vvl::DecodedTemplateUpdate::DecodedTemplateUpdate(const vvl::DeviceState &device
inline_infos.resize(create_info.descriptorUpdateEntryCount); // Make sure we have one if we need it
inline_infos_khr.resize(create_info.descriptorUpdateEntryCount);
inline_infos_nv.resize(create_info.descriptorUpdateEntryCount);
inline_infos_ptlas.resize(create_info.descriptorUpdateEntryCount);
desc_writes.reserve(create_info.descriptorUpdateEntryCount); // emplaced, so reserved without initialization
VkDescriptorSetLayout effective_dsl = create_info.templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET
? create_info.descriptorSetLayout
Expand Down Expand Up @@ -1594,6 +1595,17 @@ vvl::DecodedTemplateUpdate::DecodedTemplateUpdate(const vvl::DeviceState &device
write_entry.descriptorCount = inline_info_nv->accelerationStructureCount;
break;
}
case VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV: {
VkWriteDescriptorSetPartitionedAccelerationStructureNV *inline_info_ptlas = &inline_infos_ptlas[i];
inline_info_ptlas->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_PARTITIONED_ACCELERATION_STRUCTURE_NV;
inline_info_ptlas->pNext = nullptr;
inline_info_ptlas->accelerationStructureCount = descriptor_update_entry.descriptorCount;
inline_info_ptlas->pAccelerationStructures = reinterpret_cast<const VkDeviceAddress *>(update_entry);
write_entry.pNext = inline_info_ptlas;
// descriptorCount must match the accelerationStructureCount
write_entry.descriptorCount = inline_info_ptlas->accelerationStructureCount;
break;
}
default:
assert(false);
break;
Expand All @@ -1603,7 +1615,8 @@ vvl::DecodedTemplateUpdate::DecodedTemplateUpdate(const vvl::DeviceState &device
// If acceleration structure, we only create a single VkWriteDescriptorSet and map the actually AS into
// VkWriteDescriptorSetAccelerationStructureKHR
if (descriptor_update_entry.descriptorType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR ||
descriptor_update_entry.descriptorType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV) {
descriptor_update_entry.descriptorType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV ||
descriptor_update_entry.descriptorType == VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV) {
break;
}
}
Expand Down Expand Up @@ -5475,8 +5488,7 @@ bool CoreChecks::PreCallValidateWriteResourceDescriptorsEXT(VkDevice device, uin
skip |=
ValidateDeviceAddressRange(address_range.address, address_range.size, false, data_loc.dot(Field::pAddressRange),
LogObjectList(device), buffer_usage, usage_vuid);
} else if (resource.type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR ||
resource.type == VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV) {
} else if (resource.type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR) {
// TODO - not sure what this covers that VUID-VkResourceDescriptorInfoEXT-type-11484 doesn't
if (auto as_array = GetAccelerationStructuresByAddress(address_range.address); as_array.empty()) {
std::stringstream ss;
Expand All @@ -5496,6 +5508,13 @@ bool CoreChecks::PreCallValidateWriteResourceDescriptorsEXT(VkDevice device, uin
skip |= LogError("VUID-VkResourceDescriptorInfoEXT-type-11483", device,
data_loc.dot(Field::pAddressRange).dot(Field::address), "%s", ss.str().c_str());
}
} else if (resource.type == VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV) {
// PTLAS uses buffer addresses directly, not VkAccelerationStructureKHR objects
// Validate that the address points to a buffer with ACCELERATION_STRUCTURE_STORAGE_BIT
skip |= ValidateDeviceAddressRange(address_range.address, address_range.size, false,
data_loc.dot(Field::pAddressRange), LogObjectList(device),
VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR,
"VUID-VkResourceDescriptorInfoEXT-type-11483");
} else if (resource.type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV) {
if (address_range.size != 0) {
skip |= LogError("VUID-VkResourceDescriptorInfoEXT-type-11468", device,
Expand Down
28 changes: 16 additions & 12 deletions layers/core_checks/cc_ray_tracing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2453,22 +2453,26 @@ bool CoreChecks::PreCallValidateCmdBuildPartitionedAccelerationStructuresNV(
}
}

if (pBuildInfo->srcAccelerationStructureData && pBuildInfo->dstAccelerationStructureData) {
// Check for src vs dst overlap, but only if they are different addresses (in-place update is allowed)
if (pBuildInfo->srcAccelerationStructureData && pBuildInfo->dstAccelerationStructureData &&
pBuildInfo->srcAccelerationStructureData != pBuildInfo->dstAccelerationStructureData) {
const auto src_buffer_states = GetBuffersByAddress(pBuildInfo->srcAccelerationStructureData);
const auto dst_buffer_states = GetBuffersByAddress(pBuildInfo->dstAccelerationStructureData);
for (const auto &src_buffer_state : src_buffer_states) {
vvl::range<VkDeviceAddress> src_address_range = src_buffer_state->DeviceAddressRange();
const vvl::range<VkDeviceAddress> src_address_range = src_buffer_state->DeviceAddressRange();
if (!src_address_range.empty()) {
for (const auto &buffer_state : dst_buffer_states) {
const vvl::range<VkDeviceAddress> buffer_address_range = buffer_state->DeviceAddressRange();
if (buffer_address_range.intersects(src_address_range)) {
const LogObjectList objlist(commandBuffer, buffer_state->Handle(), src_buffer_state->Handle());
skip |=
LogError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10549", objlist,
error_obj.location.dot(Field::pBuildInfo).dot(Field::dstAccelerationStructureData),
"%s address range %s intersects srcAccelerationStructureData address range %s",
FormatHandle(buffer_state->Handle()).c_str(), string_range_hex(buffer_address_range).c_str(),
string_range_hex(src_address_range).c_str());
for (const auto &dst_buffer_state : dst_buffer_states) {
const vvl::range<VkDeviceAddress> dst_address_range = dst_buffer_state->DeviceAddressRange();
if (src_address_range.intersects(dst_address_range)) {
const LogObjectList objlist(commandBuffer, src_buffer_state->Handle(), dst_buffer_state->Handle());
skip |= LogError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10549", objlist,
error_obj.location.dot(Field::pBuildInfo),
"srcAccelerationStructureData %s address range %s intersects "
"dstAccelerationStructureData %s address range %s",
FormatHandle(src_buffer_state->Handle()).c_str(),
string_range_hex(src_address_range).c_str(),
FormatHandle(dst_buffer_state->Handle()).c_str(),
string_range_hex(dst_address_range).c_str());
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions layers/core_checks/cc_spirv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,13 +384,13 @@ static void TypeToDescriptorTypeSet(const spirv::Module &module_state, uint32_t

// The OpType are alias, but the Descriptor Types are different
case spv::OpTypeAccelerationStructureKHR:
// Only KHR or NV base accelleration structure is selected
// Only KHR or NV base acceleration structure is selected
if (module_state.HasCapability(spv::CapabilityRayTracingNV)) {
out_data.descriptor_type_set.insert(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV);
} else {
out_data.descriptor_type_set.insert(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
}

// Additionally allow PTLAS if shader uses cluster acceleration structure features
if (module_state.HasCapability(spv::CapabilityRayTracingClusterAccelerationStructureNV)) {
out_data.descriptor_type_set.insert(VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV);
}
Expand Down Expand Up @@ -3637,4 +3637,4 @@ bool CoreChecks::ValidateDescriptorHeapStructs(const spirv::Module &module_state
}

return skip;
}
}
2 changes: 1 addition & 1 deletion layers/object_tracker/object_lifetime_validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ bool Device::ValidateDescriptorWrite(VkWriteDescriptorSet const *desc, bool is_p
break;
}

// VkWriteDescriptorSetPartitionedAccelerationStructureNV contains no VkObjects to validate
// PTLAS uses VkDeviceAddress values, not VkAccelerationStructureKHR handles - no objects to validate
case VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV:
// Inline has no objects, so nothing to validate
case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
Expand Down
1 change: 1 addition & 0 deletions layers/state_tracker/descriptor_sets.h
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,7 @@ struct DecodedTemplateUpdate {
std::vector<VkWriteDescriptorSetInlineUniformBlock> inline_infos;
std::vector<VkWriteDescriptorSetAccelerationStructureKHR> inline_infos_khr;
std::vector<VkWriteDescriptorSetAccelerationStructureNV> inline_infos_nv;
std::vector<VkWriteDescriptorSetPartitionedAccelerationStructureNV> inline_infos_ptlas;
DecodedTemplateUpdate(const DeviceState &device_data, VkDescriptorSet descriptorSet,
const DescriptorUpdateTemplate &template_state, const void *pData,
VkDescriptorSetLayout push_layout = VK_NULL_HANDLE);
Expand Down
4 changes: 3 additions & 1 deletion layers/sync/sync_commandbuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,9 @@ static SyncAccessIndex GetSyncStageAccessIndexsByDescriptorSet(VkDescriptorType
if (descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
return stage_accesses.uniform_read;
}
if (descriptor_type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR) {
if (descriptor_type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR ||
descriptor_type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV ||
descriptor_type == VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV) {
return stage_accesses.acceleration_structure_read;
}

Expand Down
3 changes: 2 additions & 1 deletion tests/icd/test_icd.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
** Copyright (c) 2015-2018, 2023-2025 The Khronos Group Inc.
** Copyright (c) 2015-2018, 2023-2026 The Khronos Group Inc.
** Modifications Copyright (C) 2024-2026 Advanced Micro Devices, Inc. All rights reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -2010,6 +2010,7 @@ static VKAPI_ATTR VkDeviceSize VKAPI_CALL GetPhysicalDeviceDescriptorSizeEXT(VkP
case VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM:
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
case VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
return 256;
default:
Expand Down
29 changes: 29 additions & 0 deletions tests/unit/descriptor_heap_positive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3575,4 +3575,33 @@ TEST_F(PositiveDescriptorHeap, SingleElementNoArray) {
uint32_t* data = static_cast<uint32_t*>(buffer.Memory().Map());
ASSERT_EQ(data[0], src_data);
}
}

TEST_F(PositiveDescriptorHeap, PartitionedAccelerationStructure) {
TEST_DESCRIPTION("Test WriteResourceDescriptorsEXT with PTLAS descriptor type");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_NV_PARTITIONED_ACCELERATION_STRUCTURE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::rayTracingPipeline);
AddRequiredFeature(vkt::Feature::accelerationStructure);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
AddRequiredFeature(vkt::Feature::partitionedAccelerationStructure);
RETURN_IF_SKIP(InitBasicDescriptorHeap());

const VkDeviceSize descriptor_size =
vk::GetPhysicalDeviceDescriptorSizeEXT(gpu_, VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI is failing because in test_icd.cpp there is a GetPhysicalDeviceDescriptorSizeEXT implementation that is just missing VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV from it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pushed the fix, want to get this in tonight, tomorrow morning is cut off for SDK

std::vector<uint8_t> data(static_cast<size_t>(descriptor_size));

// Create buffer with required usage flags for PTLAS
vkt::Buffer ptlas_buffer(*m_device, 4096,
VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
vkt::device_address);

VkDeviceAddressRangeEXT device_address_range = {ptlas_buffer.Address(), descriptor_size};

VkResourceDescriptorInfoEXT resource_info = vku::InitStructHelper();
resource_info.type = VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV;
resource_info.data.pAddressRange = &device_address_range;

VkHostAddressRangeEXT descriptor = {data.data(), static_cast<size_t>(descriptor_size)};
vk::WriteResourceDescriptorsEXT(*m_device, 1u, &resource_info, &descriptor);
}
20 changes: 15 additions & 5 deletions tests/unit/ray_tracing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4244,10 +4244,12 @@ TEST_F(NegativeRayTracing, BuildPartitionedAccelerationStructureInfo) {
command_info.srcInfosCount = count_buffer_address;

m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkBuildPartitionedAccelerationStructureInfoNV-dstAccelerationStructureData-10561");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now we have no test testing 10561 ... please add one

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, is it needed? We have "m_errorMonitor->SetDesiredError("VUID-VkBuildPartitionedAccelerationStructureInfoNV-dstAccelerationStructureData-parameter");"

That should trigger if dstAccelerationStructureData is 0

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess what I am trying to say is if we can't write a test for 10561, but are still trying to validate it, something is wrong

I agree looking at the spec now these just seem like extra, redundant VUs... I will make a spec MR and allow this tests as they are now

m_errorMonitor->SetDesiredError("VUID-VkBuildPartitionedAccelerationStructureInfoNV-dstAccelerationStructureData-parameter");
m_errorMonitor->SetDesiredError("VUID-VkBuildPartitionedAccelerationStructureInfoNV-srcInfos-parameter");
vk::CmdBuildPartitionedAccelerationStructuresNV(m_command_buffer, &command_info);
m_errorMonitor->VerifyFound();
command_info.dstAccelerationStructureData = ptlas_buffer_address;
command_info.srcInfos = count_buffer_address; // Use a valid address going forward
m_command_buffer.End();

// add 1 to cause aligned error
Expand All @@ -4267,7 +4269,7 @@ TEST_F(NegativeRayTracing, BuildPartitionedAccelerationStructureInfo) {
command_info.scratchData = 0;
m_command_buffer.Begin();
// scratchData must not be NULL
m_errorMonitor->SetDesiredError("VUID-VkBuildPartitionedAccelerationStructureInfoNV-scratchData-10558");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now we need another test to test 10558

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing with "m_errorMonitor->SetDesiredError("VUID-VkBuildPartitionedAccelerationStructureInfoNV-scratchData-parameter"

m_errorMonitor->SetDesiredError("VUID-VkBuildPartitionedAccelerationStructureInfoNV-scratchData-parameter");
vk::CmdBuildPartitionedAccelerationStructuresNV(m_command_buffer, &command_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
Expand All @@ -4290,8 +4292,6 @@ TEST_F(NegativeRayTracing, BuildPartitionedAccelerationStructureInfo) {
m_errorMonitor->SetDesiredError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10542");
m_errorMonitor->SetDesiredError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10544");
m_errorMonitor->SetDesiredError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10545");
// Add this VU to avoid dst and src addres overlap warning
m_errorMonitor->SetDesiredError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10549");
vk::CmdBuildPartitionedAccelerationStructuresNV(m_command_buffer, &command_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
Expand All @@ -4300,12 +4300,22 @@ TEST_F(NegativeRayTracing, BuildPartitionedAccelerationStructureInfo) {
command_info.dstAccelerationStructureData = scratch_buffer_address;
command_info.srcAccelerationStructureData = scratch_buffer_address;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10549");
m_errorMonitor->SetDesiredError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10548");
m_errorMonitor->SetDesiredError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10547");
vk::CmdBuildPartitionedAccelerationStructuresNV(m_command_buffer, &command_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();

// Test src vs dst overlap when they are different addresses (in-place update src==dst is allowed)
// Use 256-byte aligned offset so alignment checks pass, but still within same buffer (overlapping)
command_info.scratchData = scratch_buffer_address;
command_info.dstAccelerationStructureData = correct_ptlas_buffer_address;
command_info.srcAccelerationStructureData = correct_ptlas_buffer_address + 256; // Different but overlapping (same buffer)
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdBuildPartitionedAccelerationStructuresNV-pBuildInfo-10549");
vk::CmdBuildPartitionedAccelerationStructuresNV(m_command_buffer, &command_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}

TEST_F(NegativeRayTracing, BuildPartitionedAccelerationStrutureInfoBadMemory) {
Expand Down
Loading