Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Portable Acceleration Structures #1955

Open
wants to merge 23 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
8ddaca1
Add utils handle->info-struct to AddressTracker, check build-sizes an…
fabian-lunarg Dec 10, 2024
b4667ad
cleanup refactor, stubs for replacement AS
fabian-lunarg Dec 10, 2024
9684691
shadow acceleration-structure creation
fabian-lunarg Dec 11, 2024
e23d6ae
work on shadow-AS cleanup and buffer-alignment
fabian-lunarg Dec 11, 2024
2c907c1
work on AccelerationStructure replacement. portable replay starts wor…
fabian-lunarg Dec 17, 2024
805405a
Add and integrate ProcessUpdateDescriptorSets
fabian-lunarg Dec 18, 2024
1e74976
Process meta-commands (rebuild AS when trimming)
fabian-lunarg Dec 18, 2024
c48e000
Implement ProcessBuildVulkanAccelerationStructuresMetaCommand.
fabian-lunarg Jan 6, 2025
4490d47
Add missing tracking of AS scratch-buffers, needed for trimming
fabian-lunarg Jan 6, 2025
e25bbf0
Drop instance_buffers_data, cleanup, doc
fabian-lunarg Jan 7, 2025
448f41e
Seperate AS- and scratch shadow-objects, minor improvements
fabian-lunarg Jan 9, 2025
01d19b4
Add VulkanCaptureManager::OverrideCmdCopyAccelerationStructureKHR
fabian-lunarg Jan 13, 2025
1f24751
work on ProcessVulkanAccelerationStructuresWritePropertiesMetaCommand
fabian-lunarg Jan 13, 2025
71260df
Overall progress and cleanup. some open things, but slowly finalizing
fabian-lunarg Jan 14, 2025
2b1bafa
bring back opaque shadergroup-handles, you never know
fabian-lunarg Jan 14, 2025
16e5877
compute-shaders compiled against vulkan1.1 + optimized spirv
fabian-lunarg Jan 14, 2025
e878682
Guard address_replacer.ProcessCmdTraceRays(), only for '-m rebind'
fabian-lunarg Jan 14, 2025
5fc94a5
review comments, cleanup
fabian-lunarg Jan 14, 2025
58a5de0
Extend state-tracking for VkPhysicalDeviceAccelerationStructureProper…
fabian-lunarg Jan 15, 2025
97f2083
Fetch VkPhysicalDeviceAccelerationStructurePropertiesKHR, in case nob…
fabian-lunarg Jan 16, 2025
ec2788e
Consolidate alignment utils in dedicated header
fabian-lunarg Jan 16, 2025
5e0f610
Repeat call to SetRaytracingProperties, if necessary. we might have m…
fabian-lunarg Jan 16, 2025
4c1c7a7
simpler API for SetRaytracingProperties
fabian-lunarg Jan 16, 2025
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
42 changes: 8 additions & 34 deletions framework/decode/vulkan_address_replacer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,8 +512,9 @@ void VulkanAddressReplacer::ProcessCmdBuildAccelerationStructuresKHR(
}
else
Copy link
Contributor

Choose a reason for hiding this comment

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

You can remove the else and just return false;

{
// GFXRECON_LOG_WARNING(
// "ProcessCmdBuildAccelerationStructuresKHR: missing buffer_info->replay_address, remap failed");
// GFXRECON_LOG_WARNING(
// "ProcessCmdBuildAccelerationStructuresKHR: missing buffer_info->replay_address, remap
// failed");
return false;
}
};
Expand All @@ -532,7 +533,6 @@ void VulkanAddressReplacer::ProcessCmdBuildAccelerationStructuresKHR(
address_remap(build_geometry_info.scratchData.deviceAddress);

// check capture/replay acceleration-structure buffer-sizes
if (!_resource_allocator->SupportsOpaqueDeviceAddresses())
{
VkAccelerationStructureBuildSizesInfoKHR build_size_info = {};
build_size_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;
Expand Down Expand Up @@ -594,7 +594,8 @@ void VulkanAddressReplacer::ProcessCmdBuildAccelerationStructuresKHR(
build_size_info.accelerationStructureSize,
scratch_size))
{
// problem creating shadow-AS
GFXRECON_LOG_ERROR("ProcessCmdBuildAccelerationStructuresKHR: creation of shadow "
"acceleration-structure failed");
}
}

Expand Down Expand Up @@ -791,43 +792,16 @@ void VulkanAddressReplacer::ProcessCmdCopyAccelerationStructuresKHR(
swap_acceleration_structure(info->src);
swap_acceleration_structure(info->dst);

VkDeviceSize compact_size = 0;
// GFXRECON_ASSERT(info->dst != VK_NULL_HANDLE);
auto compact_size_it = _as_compact_sizes.find(info->dst);
VkDeviceSize compact_size = 0;
auto compact_size_it = _as_compact_sizes.find(info->dst);
if (compact_size_it != _as_compact_sizes.end())
{
compact_size = compact_size_it->second;

_as_compact_sizes.erase(info->dst);
GFXRECON_LOG_INFO(
"VulkanAddressReplacer::ProcessCmdCopyAccelerationStructuresKHR: found compacted AS-size: %ul",
compact_size);
}
// else
// {
// GFXRECON_LOG_ERROR(
// "VulkanAddressReplacer::ProcessCmdCopyAccelerationStructuresKHR: compacted AS-size unknown");
// }
// auto replace_it = _shadow_as_map.find(info->dst);
// if (replace_it == _shadow_as_map.end())
// {
// if (info->dst != VK_NULL_HANDLE)
// {
// auto as_info = address_tracker.GetAccelerationStructureByHandle(info->dst);
// GFXRECON_ASSERT(as_info != nullptr);
//
// acceleration_structure_asset_t& new_dst = _shadow_as_map[info->dst];
// uint32_t fake_as_buffer_size = 5 * (1 << 20);
//
// if (create_acceleration_asset(new_dst, as_info->type, fake_as_buffer_size, 0))
// {
// swap_acceleration_structure(info->dst);
// }
// }
// else
// {
// GFXRECON_ASSERT(info->dst != VK_NULL_HANDLE);
// }
// }
}
}

Expand Down
5 changes: 2 additions & 3 deletions framework/decode/vulkan_rebind_allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,13 @@ VkResult VulkanRebindAllocator::CreateBuffer(const VkBufferCreateInfo* create

if ((create_info != nullptr) && (buffer != nullptr) && (allocator_data != nullptr))
{
auto aligned_size = [](uint32_t size, uint32_t alignment) -> uint32_t
{
auto aligned_size = [](uint32_t size, uint32_t alignment) -> uint32_t {
Copy link
Contributor

Choose a reason for hiding this comment

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

There's a similar function in vulkan_address_replacer.cpp. How about moving this in a common header under the graphics namespace?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I chose util/alignment_utils.h and consolidated the alignment and divup helpers there

return (size + alignment - 1) & ~(alignment - 1);
};

auto modified_info = *create_info;
modified_info.size = aligned_size(create_info->size, min_buffer_alignment_);
result = functions_.create_buffer(device_, &modified_info, nullptr, buffer);
result = functions_.create_buffer(device_, &modified_info, nullptr, buffer);

if (result >= 0)
{
Expand Down
206 changes: 166 additions & 40 deletions framework/decode/vulkan_replay_consumer_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7791,7 +7791,7 @@ void VulkanReplayConsumerBase::OverrideCmdBuildAccelerationStructuresKHR(
VkAccelerationStructureBuildGeometryInfoKHR* build_geometry_infos = pInfos->GetPointer();
VkAccelerationStructureBuildRangeInfoKHR** build_range_infos = ppBuildRangeInfos->GetPointer();

// if (!device_info->allocator->SupportsOpaqueDeviceAddresses())
if (!device_info->allocator->SupportsOpaqueDeviceAddresses())
{
auto& address_tracker = GetDeviceAddressTracker(device_info);
auto& address_replacer = GetDeviceAddressReplacer(device_info);
Expand Down Expand Up @@ -7892,38 +7892,157 @@ VkResult VulkanReplayConsumerBase::OverrideCreateRayTracingPipelinesKHR(
&pPipelines->GetPointer()[createInfoCount]);
}

if (omitted_pipeline_cache_data_)
// NOTE: as of early 2025, rayTracingPipelineShaderGroupHandleCaptureReplay is not widely supported.
// e.g. newest nvidia desktop-drivers do not support this feature
if (device_info->property_feature_info.feature_rayTracingPipelineShaderGroupHandleCaptureReplay)
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to make sure this was enabled at vkCreateDevice time? Or does the device_info already do it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

device_info has it all. the feature might have been available during capture, but still missing during replay (e.g. seeing that for rayTracingPipelineShaderGroupHandleCaptureReplay between nvidia(no) <-> radv(yes))

for replay, we do checks in gfxrecon::graphics::VulkanDeviceUtil figuring out if to enable the feature or not.
the information for replay is pulled from VkPhysicalDeviceRayTracingPipelineFeaturesKHR via a vkGetPhysicalDeviceFeatures2 call. active when available both during capture & replay.
some of that logic needed to be touched in this PR (and it might not be the end of story yet).

{
AllowCompileDuringPipelineCreation(createInfoCount,
const_cast<VkRayTracingPipelineCreateInfoKHR*>(in_pCreateInfos));
}
// Modify pipeline create infos with capture replay flag and data.
std::vector<VkRayTracingPipelineCreateInfoKHR> modified_create_infos;
std::vector<std::vector<VkRayTracingShaderGroupCreateInfoKHR>> modified_pgroups;
modified_create_infos.reserve(createInfoCount);
modified_pgroups.resize(createInfoCount);
for (uint32_t create_info_i = 0; create_info_i < createInfoCount; ++create_info_i)
{
format::HandleId pipeline_capture_id = (*pPipelines[create_info_i].GetPointer());

VkPipeline* created_pipelines = nullptr;
// Enable capture replay flag.
modified_create_infos.push_back(in_pCreateInfos[create_info_i]);
modified_create_infos[create_info_i].flags |=
VK_PIPELINE_CREATE_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR;

if (deferred_operation_info)
{
created_pipelines = deferred_operation_info->replayPipelines.data();
uint32_t group_info_count = in_pCreateInfos[create_info_i].groupCount;
bool has_data = (device_info->shader_group_handles.find(pipeline_capture_id) !=
device_info->shader_group_handles.end());

if (has_data)
{
assert(device_info->shader_group_handles.at(pipeline_capture_id).size() ==
(device_info->property_feature_info.property_shaderGroupHandleCaptureReplaySize *
group_info_count));
}
else
{
GFXRECON_LOG_WARNING("Missing shader group handle data in for ray tracing pipeline (ID = %" PRIu64 ").",
pipeline_capture_id);
}

// Set pShaderGroupCaptureReplayHandle in shader group create infos.
std::vector<VkRayTracingShaderGroupCreateInfoKHR>& modified_group_infos = modified_pgroups[create_info_i];
modified_group_infos.reserve(group_info_count);

for (uint32_t group_info_i = 0; group_info_i < group_info_count; ++group_info_i)
{
modified_group_infos.push_back(in_pCreateInfos[create_info_i].pGroups[group_info_i]);

if (has_data)
{
uint32_t byte_offset =
device_info->property_feature_info.property_shaderGroupHandleCaptureReplaySize * group_info_i;
modified_group_infos[group_info_i].pShaderGroupCaptureReplayHandle =
device_info->shader_group_handles.at(pipeline_capture_id).data() + byte_offset;
}
else
{
modified_group_infos[group_info_i].pShaderGroupCaptureReplayHandle = nullptr;
}
}

// Use modified shader group infos.
modified_create_infos[create_info_i].pGroups = modified_group_infos.data();
}

if (omitted_pipeline_cache_data_)
{
AllowCompileDuringPipelineCreation(createInfoCount, modified_create_infos.data());
}

VkPipeline* created_pipelines = nullptr;

if (deferred_operation_info)
{
created_pipelines = deferred_operation_info->replayPipelines.data();
}
else
{
created_pipelines = out_pPipelines;
}

result = GetDeviceTable(device)->CreateRayTracingPipelinesKHR(device,
in_deferredOperation,
overridePipelineCache,
createInfoCount,
modified_create_infos.data(),
in_pAllocator,
created_pipelines);

if ((result == VK_SUCCESS) || (result == VK_OPERATION_NOT_DEFERRED_KHR) ||
(result == VK_PIPELINE_COMPILE_REQUIRED_EXT))
{
// The above return values mean the command is not deferred and driver will finish all workload in current
// thread. Therefore the created pipelines can be read and copied to out_pPipelines which will be
// referenced later.
//
// Note:
// Some pipelines might actually fail creation if the return value is VK_PIPELINE_COMPILE_REQUIRED_EXT.
// These failed pipelines will generate VK_NULL_HANDLE.
//
// If the return value is VK_OPERATION_DEFERRED_KHR, it means the command is deferred, and thus pipeline
// creation is not finished. Subsequent handling will be done by
// vkDeferredOperationJoinKHR/vkGetDeferredOperationResultKHR after pipeline creation is finished.

if (deferred_operation_info)
{
memcpy(out_pPipelines, created_pipelines, createInfoCount * sizeof(VkPipeline));

// Eventhough vkCreateRayTracingPipelinesKHR was called with a valid deferred operation object, the
// driver may opt to not defer the command. In this case, set pending_state flag to false to skip
// vkDeferredOperationJoinKHR handling.
deferred_operation_info->pending_state = false;
}
}

if (deferred_operation_info)
{
deferred_operation_info->record_modified_create_infos = std::move(modified_create_infos);
deferred_operation_info->record_modified_pgroups = std::move(modified_pgroups);
}
}
else
{
created_pipelines = out_pPipelines;
}
if (omitted_pipeline_cache_data_)
{
AllowCompileDuringPipelineCreation(createInfoCount,
const_cast<VkRayTracingPipelineCreateInfoKHR*>(in_pCreateInfos));
}

result = GetDeviceTable(device)->CreateRayTracingPipelinesKHR(device,
in_deferredOperation,
overridePipelineCache,
createInfoCount,
in_pCreateInfos,
in_pAllocator,
created_pipelines);
VkPipeline* created_pipelines = nullptr;

if ((result == VK_SUCCESS) || (result == VK_OPERATION_NOT_DEFERRED_KHR) ||
(result == VK_PIPELINE_COMPILE_REQUIRED_EXT))
{
if (deferred_operation_info)
{
memcpy(out_pPipelines, created_pipelines, createInfoCount * sizeof(VkPipeline));
deferred_operation_info->pending_state = false;
created_pipelines = deferred_operation_info->replayPipelines.data();
}
else
{
created_pipelines = out_pPipelines;
}

result = GetDeviceTable(device)->CreateRayTracingPipelinesKHR(device,
in_deferredOperation,
overridePipelineCache,
createInfoCount,
in_pCreateInfos,
in_pAllocator,
created_pipelines);

if ((result == VK_SUCCESS) || (result == VK_OPERATION_NOT_DEFERRED_KHR) ||
(result == VK_PIPELINE_COMPILE_REQUIRED_EXT))
{

if (deferred_operation_info)
{
memcpy(out_pPipelines, created_pipelines, createInfoCount * sizeof(VkPipeline));
deferred_operation_info->pending_state = false;
}
}
}

Expand Down Expand Up @@ -9537,12 +9656,15 @@ void VulkanReplayConsumerBase::ProcessCopyVulkanAccelerationStructuresMetaComman
VulkanDeviceInfo* device_info = GetObjectInfoTable().GetVkDeviceInfo(device);
GFXRECON_ASSERT(device_info != nullptr);

MapStructArrayHandles(copy_infos->GetMetaStructPointer(), copy_infos->GetLength(), GetObjectInfoTable());
if (!device_info->allocator->SupportsOpaqueDeviceAddresses())
{
MapStructArrayHandles(copy_infos->GetMetaStructPointer(), copy_infos->GetLength(), GetObjectInfoTable());

const auto& address_tracker = GetDeviceAddressTracker(device_info);
auto& address_replacer = GetDeviceAddressReplacer(device_info);
address_replacer.ProcessCopyVulkanAccelerationStructuresMetaCommand(
copy_infos->GetLength(), copy_infos->GetPointer(), address_tracker);
const auto& address_tracker = GetDeviceAddressTracker(device_info);
auto& address_replacer = GetDeviceAddressReplacer(device_info);
address_replacer.ProcessCopyVulkanAccelerationStructuresMetaCommand(
copy_infos->GetLength(), copy_infos->GetPointer(), address_tracker);
}
}
}

Expand All @@ -9557,16 +9679,17 @@ void VulkanReplayConsumerBase::ProcessBuildVulkanAccelerationStructuresMetaComma
VulkanDeviceInfo* device_info = GetObjectInfoTable().GetVkDeviceInfo(device);
GFXRECON_ASSERT(device_info != nullptr);

MapStructArrayHandles(pInfos->GetMetaStructPointer(), pInfos->GetLength(), GetObjectInfoTable());
if (!device_info->allocator->SupportsOpaqueDeviceAddresses())
{
MapStructArrayHandles(pInfos->GetMetaStructPointer(), pInfos->GetLength(), GetObjectInfoTable());

VkAccelerationStructureBuildGeometryInfoKHR* build_geometry_infos = pInfos->GetPointer();
VkAccelerationStructureBuildRangeInfoKHR** range_infos = ppRangeInfos->GetPointer();
VkAccelerationStructureBuildGeometryInfoKHR* build_geometry_infos = pInfos->GetPointer();
VkAccelerationStructureBuildRangeInfoKHR** range_infos = ppRangeInfos->GetPointer();

GetDeviceAddressReplacer(device_info)
.ProcessBuildVulkanAccelerationStructuresMetaCommand(info_count,
pInfos->GetPointer(),
ppRangeInfos->GetPointer(),
GetDeviceAddressTracker(device_info));
GetDeviceAddressReplacer(device_info)
.ProcessBuildVulkanAccelerationStructuresMetaCommand(
info_count, pInfos->GetPointer(), ppRangeInfos->GetPointer(), GetDeviceAddressTracker(device_info));
}
}
}

Expand All @@ -9578,11 +9701,14 @@ void VulkanReplayConsumerBase::ProcessVulkanAccelerationStructuresWritePropertie
VulkanDeviceInfo* device_info = GetObjectInfoTable().GetVkDeviceInfo(device_id);
GFXRECON_ASSERT(device_info != nullptr);

VkAccelerationStructureKHR acceleration_structure = MapHandle<VulkanAccelerationStructureKHRInfo>(
acceleration_structure_id, &VulkanObjectInfoTable::GetVkAccelerationStructureKHRInfo);
if (!device_info->allocator->SupportsOpaqueDeviceAddresses())
{
VkAccelerationStructureKHR acceleration_structure = MapHandle<VulkanAccelerationStructureKHRInfo>(
acceleration_structure_id, &VulkanObjectInfoTable::GetVkAccelerationStructureKHRInfo);

GetDeviceAddressReplacer(device_info)
.ProcessVulkanAccelerationStructuresWritePropertiesMetaCommand(query_type, acceleration_structure);
GetDeviceAddressReplacer(device_info)
.ProcessVulkanAccelerationStructuresWritePropertiesMetaCommand(query_type, acceleration_structure);
}
}
}

Expand Down
6 changes: 3 additions & 3 deletions framework/encode/vulkan_state_tracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2028,8 +2028,8 @@ void gfxrecon::encode::VulkanStateTracker::DestroyState(vulkan_wrappers::BufferW
if (it != (*command)->input_buffers.end())
{
vulkan_wrappers::AccelerationStructureKHRWrapper::ASInputBuffer& buffer = it->second;
buffer.destroyed = true;
auto [resource_util, created] = resource_utils_.try_emplace(
buffer.destroyed = true;
auto [resource_util, created] = resource_utils_.try_emplace(
buffer.bind_device->handle,
graphics::VulkanResourcesUtil(buffer.bind_device->handle,
buffer.bind_device->physical_device->handle,
Expand Down Expand Up @@ -2852,7 +2852,7 @@ void VulkanStateTracker::TrackMappedAssetsWrites(format::HandleId memory_id)

for (const auto& entry : memories_page_status)
{
// assert(entry.second.status_tracker.HasActiveWriteBlock());
assert(entry.second.status_tracker.HasActiveWriteBlock());

const util::PageStatusTracker& page_status = entry.second.status_tracker;

Expand Down
1 change: 1 addition & 0 deletions framework/graphics/test/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
///////////////////////////////////////////////////////////////////////////////

#define CATCH_CONFIG_MAIN
#include <numeric>
#include <catch2/catch.hpp>

#include "graphics/vulkan_shader_group_handle.h"
Expand Down
Loading