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

gfxrecon-replay: Use infinite timeout for 3 Vulkan api calls #1239

Merged
merged 5 commits into from
Aug 30, 2023
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: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ __pycache__/
.vscode/
*.db
*.pyc

1 change: 0 additions & 1 deletion framework/decode/vulkan_captured_swapchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,6 @@ void VulkanCapturedSwapchain::ProcessSetSwapchainImageStateCommand(
const VulkanObjectInfoTable& object_info_table,
SwapchainImageTracker& swapchain_image_tracker)
{

VkDevice device = device_info->handle;
VkSwapchainKHR swapchain = swapchain_info->handle;

Expand Down
23 changes: 4 additions & 19 deletions framework/decode/vulkan_object_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,13 +266,16 @@ struct DeviceInfo : public VulkanObjectInfo<VkDevice>
graphics::VulkanDevicePropertyFeatureInfo property_feature_info;

std::unordered_map<uint32_t, VkDeviceQueueCreateFlags> queue_family_creation_flags;
std::vector<bool> queue_family_index_enabled;

std::vector<VkPhysicalDevice> replay_device_group;
};

struct QueueInfo : public VulkanObjectInfo<VkQueue>
{
std::unordered_map<uint32_t, size_t> array_counts;
uint32_t family_index;
uint32_t queue_index;
};

struct SemaphoreInfo : public VulkanObjectInfo<VkSemaphore>
Expand Down Expand Up @@ -401,31 +404,13 @@ struct SwapchainKHRInfo : public VulkanObjectInfo<VkSwapchainKHR>

// When replay is restricted to a specific surface, a dummy swapchain is created for the omitted surfaces, requiring
// backing images.
uint32_t replay_image_count{ 0 };
std::vector<ImageInfo> image_infos;
VkSwapchainCreateFlagsKHR image_flags{ 0 };
VkFormat image_format{ VK_FORMAT_UNDEFINED };
uint32_t image_array_layers{ 0 };
VkImageUsageFlags image_usage{ 0 };
VkSharingMode image_sharing_mode{ VK_SHARING_MODE_EXCLUSIVE };

// TODO: These values are used by the virtual swapchain. They should be replaced with an opaque handle, similar to
// DeviceMemoryInfo::allocator_data, which is really a pointer to a struct that contains the virtual swapchain's
// internal info. The memory for the struct referenced by the opaque handle would be managed by the virtual
// swapchain class, similar to the way that the VulkanRebindAllocator works.
struct VirtualImage
{
VkDeviceMemory memory{ VK_NULL_HANDLE };
VkImage image{ VK_NULL_HANDLE };
VulkanResourceAllocator::MemoryData memory_allocator_data{ 0 };
VulkanResourceAllocator::ResourceData resource_allocator_data{ 0 };
};
uint32_t replay_image_count{ 0 };
std::vector<VirtualImage> virtual_images; // Images created by replay, returned in place of the swapchain images.
std::vector<VkImage> swapchain_images; // The real swapchain images.
VkQueue blit_queue{ VK_NULL_HANDLE };
VkCommandPool blit_command_pool{ VK_NULL_HANDLE };
std::vector<VkCommandBuffer> blit_command_buffers;
std::vector<VkSemaphore> blit_semaphores;
};

struct ValidationCacheEXTInfo : public VulkanObjectInfo<VkValidationCacheEXT>
Expand Down
162 changes: 158 additions & 4 deletions framework/decode/vulkan_replay_consumer_base.cpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@

#include "generated/generated_vulkan_enum_to_string.h"

#include <algorithm>
#include <cstdint>
#include <limits>
#include <numeric>
#include <unordered_set>
#include <future>

Expand Down Expand Up @@ -2145,12 +2147,12 @@ void VulkanReplayConsumerBase::WriteScreenshots(const Decoded_VkPresentInfoKHR*
// If both copy_scale and copy_width are provided, use copy_scale.
const uint32_t screenshot_width =
options_.screenshot_scale
? (options_.screenshot_scale * swapchain_info->width)
? static_cast<uint32_t>(options_.screenshot_scale * swapchain_info->width)
: (options_.screenshot_width ? options_.screenshot_width : swapchain_info->width);

const uint32_t screenshot_height =
options_.screenshot_scale
? (options_.screenshot_scale * swapchain_info->height)
? static_cast<uint32_t>(options_.screenshot_scale * swapchain_info->height)
: (options_.screenshot_height ? options_.screenshot_height : swapchain_info->height);

screenshot_handler_->WriteImage(filename_prefix,
Expand Down Expand Up @@ -2222,12 +2224,12 @@ bool VulkanReplayConsumerBase::CheckCommandBufferInfoForFrameBoundary(const Comm
// If both copy_scale and copy_width are provided, use copy_scale.
const uint32_t screenshot_width =
options_.screenshot_scale
? (options_.screenshot_scale * image_info->extent.width)
? static_cast<uint32_t>(options_.screenshot_scale * image_info->extent.width)
: (options_.screenshot_width ? options_.screenshot_width : image_info->extent.width);

const uint32_t screenshot_height =
options_.screenshot_scale
? (options_.screenshot_scale * image_info->extent.height)
? static_cast<uint32_t>(options_.screenshot_scale * image_info->extent.height)
: (options_.screenshot_height ? options_.screenshot_height : image_info->extent.height);

screenshot_handler_->WriteImage(filename_prefix,
Expand Down Expand Up @@ -2664,13 +2666,27 @@ VulkanReplayConsumerBase::OverrideCreateDevice(VkResult original_resu
// Track state of physical device properties and features at device creation
device_info->property_feature_info = property_feature_info;

// Keep track of what queue families this device is planning on using. This information is
// very important if we end up using the VulkanVirtualSwapchain path.
auto max = [](uint32_t current_max, const VkDeviceQueueCreateInfo& dqci) {
return std::max(current_max, dqci.queueFamilyIndex);
};
uint32_t max_queue_family =
std::accumulate(modified_create_info.pQueueCreateInfos,
modified_create_info.pQueueCreateInfos + modified_create_info.queueCreateInfoCount,
0,
max);
device_info->queue_family_index_enabled.clear();
device_info->queue_family_index_enabled.resize(max_queue_family + 1, false);

for (uint32_t q = 0; q < modified_create_info.queueCreateInfoCount; ++q)
{
const VkDeviceQueueCreateInfo* queue_create_info = &modified_create_info.pQueueCreateInfos[q];
assert(device_info->queue_family_creation_flags.find(queue_create_info->queueFamilyIndex) ==
device_info->queue_family_creation_flags.end());
device_info->queue_family_creation_flags[queue_create_info->queueFamilyIndex] =
queue_create_info->flags;
device_info->queue_family_index_enabled[queue_create_info->queueFamilyIndex] = true;
}
}

Expand Down Expand Up @@ -2907,6 +2923,52 @@ VkResult VulkanReplayConsumerBase::OverrideEnumeratePhysicalDeviceGroups(
return result;
}

void VulkanReplayConsumerBase::OverrideGetDeviceQueue(PFN_vkGetDeviceQueue func,
DeviceInfo* device_info,
uint32_t queueFamilyIndex,
uint32_t queueIndex,
HandlePointerDecoder<VkQueue>* pQueue)
{
VkDevice device = device_info->handle;
if (!pQueue->IsNull())
{
pQueue->SetHandleLength(1);
}
VkQueue* out_pQueue = pQueue->GetHandlePointer();

func(device, queueFamilyIndex, queueIndex, out_pQueue);

// Add tracking for which VkQueue objects are associated with what queue family and index.
// This is necessary for the virtual swapchain to determine which command buffer to use when
// Bliting the images on the Presenting Queue.
auto queue_info = reinterpret_cast<QueueInfo*>(pQueue->GetConsumerData(0));
queue_info->family_index = queueFamilyIndex;
queue_info->queue_index = queueIndex;
}

void VulkanReplayConsumerBase::OverrideGetDeviceQueue2(PFN_vkGetDeviceQueue2 func,
DeviceInfo* device_info,
StructPointerDecoder<Decoded_VkDeviceQueueInfo2>* pQueueInfo,
HandlePointerDecoder<VkQueue>* pQueue)
{
VkDevice device = device_info->handle;
const VkDeviceQueueInfo2* in_pQueueInfo = pQueueInfo->GetPointer();
if (!pQueue->IsNull())
{
pQueue->SetHandleLength(1);
}
VkQueue* out_pQueue = pQueue->GetHandlePointer();

func(device, in_pQueueInfo, out_pQueue);

// Add tracking for which VkQueue objects are associated with what queue family and index.
// This is necessary for the virtual swapchain to determine which command buffer to use when
// Bliting the images on the Presenting Queue.
auto queue_info = reinterpret_cast<QueueInfo*>(pQueue->GetConsumerData(0));
queue_info->family_index = in_pQueueInfo->queueFamilyIndex;
queue_info->queue_index = in_pQueueInfo->queueIndex;
}

void VulkanReplayConsumerBase::OverrideGetPhysicalDeviceProperties(
PFN_vkGetPhysicalDeviceProperties func,
PhysicalDeviceInfo* physical_device_info,
Expand Down Expand Up @@ -5294,9 +5356,13 @@ VkResult VulkanReplayConsumerBase::OverrideAcquireNextImageKHR(PFN_vkAcquireNext
// If expected result is VK_TIMEOUT, try to get a timeout by using a timeout of 0.
// If expected result is anything else, use the passed in timeout value.
if (original_result == VK_SUCCESS)
{
timeout = std::numeric_limits<uint64_t>::max();
}
else if (original_result == VK_TIMEOUT)
{
timeout = 0;
}
result = swapchain_->AcquireNextImageKHR(
func, device_info, swapchain_info, timeout, semaphore_info, fence_info, captured_index, replay_index);

Expand Down Expand Up @@ -5412,9 +5478,13 @@ VkResult VulkanReplayConsumerBase::OverrideAcquireNextImage2KHR(
// If expected result is anything else, use the passed in timeout value.
VkAcquireNextImageInfoKHR modified_acquire_info = *replay_acquire_info;
if (original_result == VK_SUCCESS)
{
modified_acquire_info.timeout = std::numeric_limits<uint64_t>::max();
}
else if (original_result == VK_TIMEOUT)
{
modified_acquire_info.timeout = 0;
}
result = swapchain_->AcquireNextImage2KHR(
func, device_info, swapchain_info, &modified_acquire_info, captured_index, replay_index);

Expand Down Expand Up @@ -6641,6 +6711,90 @@ VkResult VulkanReplayConsumerBase::OverrideGetPhysicalDeviceToolProperties(
}
}

VkResult
VulkanReplayConsumerBase::OverrideWaitSemaphores(PFN_vkWaitSemaphores func,
VkResult original_result,
const DeviceInfo* device_info,
const StructPointerDecoder<Decoded_VkSemaphoreWaitInfo>* pInfo,
uint64_t timeout)
{
assert((device_info != nullptr) && (pInfo != nullptr) && !pInfo->IsNull() && (pInfo->GetPointer() != nullptr));
VkDevice device = device_info->handle;
const VkSemaphoreWaitInfo* wait_info = pInfo->GetPointer();
VkResult result;

// If expected result is VK_SUCCESS, ensure that vkWaitSemaphores waits until semaphores
// are available by using a timeout of UINT64_MAX.
// If expected result is VK_TIMEOUT, try to get a timeout by using a timeout of 0.
// If expected result is anything else, use the passed in timeout value.
if (original_result == VK_SUCCESS)
MarkY-LunarG marked this conversation as resolved.
Show resolved Hide resolved
{
timeout = std::numeric_limits<uint64_t>::max();
}
else if (original_result == VK_TIMEOUT)
{
timeout = 0;
MarkY-LunarG marked this conversation as resolved.
Show resolved Hide resolved
}
result = func(device, wait_info, timeout);
return result;
}

VkResult VulkanReplayConsumerBase::OverrideAcquireProfilingLockKHR(
PFN_vkAcquireProfilingLockKHR func,
VkResult original_result,
const DeviceInfo* device_info,
const StructPointerDecoder<Decoded_VkAcquireProfilingLockInfoKHR>* pInfo)
{
assert((device_info != nullptr) && (pInfo != nullptr) && !pInfo->IsNull() && (pInfo->GetPointer() != nullptr));
VkDevice device = device_info->handle;
const VkAcquireProfilingLockInfoKHR* acquire_info = pInfo->GetPointer();
VkResult result;

// If expected result is VK_SUCCESS, ensure that vkAcquireProfilingLockKHR waits for locks
// using a timeout of UINT64_MAX.
// If expected result is VK_TIMEOUT, try to get a timeout by using a timeout of 0.
// If expected result is anything else, use the passed in timeout value.
VkAcquireProfilingLockInfoKHR modified_acquire_info = *acquire_info;
if (original_result == VK_SUCCESS)
{
modified_acquire_info.timeout = std::numeric_limits<uint64_t>::max();
}
else if (original_result == VK_TIMEOUT)
{
modified_acquire_info.timeout = 0;
}
result = func(device, &modified_acquire_info);
return result;
}

VkResult VulkanReplayConsumerBase::OverrideWaitForPresentKHR(PFN_vkWaitForPresentKHR func,
VkResult original_result,
const DeviceInfo* device_info,
SwapchainKHRInfo* swapchain_info,
uint64_t presentid,
uint64_t timeout)
{
assert((device_info != nullptr) && (swapchain_info != nullptr));
VkDevice device = device_info->handle;
VkSwapchainKHR swapchain = swapchain_info->handle;
VkResult result;

// If expected result is VK_SUCCESS, ensure that vkWaitForPresent waits for present by
// using a timeout of UINT64_MAX.
// If expected result is VK_TIMEOUT, try to get a timeout by using a timeout of 0.
// If expected result is anything else, use the passed in timeout value.
if (original_result == VK_SUCCESS)
{
timeout = std::numeric_limits<uint64_t>::max();
}
else if (original_result == VK_TIMEOUT)
{
timeout = 0;
}
result = func(device, swapchain, presentid, timeout);
return result;
}

void VulkanReplayConsumerBase::MapDescriptorUpdateTemplateHandles(
const DescriptorUpdateTemplateInfo* update_template_info, DescriptorUpdateTemplateDecoder* decoder)
{
Expand Down
Loading