Skip to content

Commit 0d6adc3

Browse files
committed
Virtual swapchain: restore captured swapchain-image layouts on trim state load
- implement ProcessSetSwapchainImageStateCommand (was empty stub) - transition virtual images UNDEFINED -> captured layout in one injected submit - skip UNDEFINED entries and unrecognized image IDs - fixes VUID-vkCmdDraw-None-09600 on first use after trim load
1 parent d40a227 commit 0d6adc3

2 files changed

Lines changed: 138 additions & 7 deletions

File tree

framework/decode/vulkan_virtual_swapchain.cpp

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,6 +1145,138 @@ VkResult VulkanVirtualSwapchain::QueuePresentKHR(VkResult
11451145
return func(queue, &modified_present_info);
11461146
}
11471147

1148+
void VulkanVirtualSwapchain::ProcessSetSwapchainImageStateCommand(
1149+
const VulkanDeviceInfo* device_info,
1150+
VulkanSwapchainKHRInfo* swapchain_info,
1151+
uint32_t last_presented_image,
1152+
const std::vector<format::SwapchainImageStateInfo>& image_infos,
1153+
const CommonObjectInfoTable& object_info_table,
1154+
SwapchainImageTracker& swapchain_image_tracker)
1155+
{
1156+
GFXRECON_UNREFERENCED_PARAMETER(last_presented_image);
1157+
GFXRECON_UNREFERENCED_PARAMETER(swapchain_image_tracker);
1158+
1159+
GFXRECON_ASSERT(device_table_ != nullptr);
1160+
1161+
VkDevice device = device_info->handle;
1162+
uint32_t queue_family_index = swapchain_info->queue_family_indices[0];
1163+
1164+
VkQueue transition_queue = GetDeviceQueue(device_table_, device_info, queue_family_index, 0);
1165+
if (transition_queue == VK_NULL_HANDLE)
1166+
{
1167+
GFXRECON_LOG_WARNING("Failed image layout restore for VkSwapchainKHR object (ID = %" PRIu64
1168+
"), could not get device queue %u",
1169+
swapchain_info->capture_id,
1170+
queue_family_index);
1171+
return;
1172+
}
1173+
1174+
// trim-state setup has already run, so mark as injected from here
1175+
util::MarkInjectedCommandsHelper mark_injected_commands_helper;
1176+
1177+
VkCommandPool transition_pool = VK_NULL_HANDLE;
1178+
VkCommandBuffer transition_command = VK_NULL_HANDLE;
1179+
1180+
VkCommandPoolCreateInfo pool_create_info = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
1181+
pool_create_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
1182+
pool_create_info.queueFamilyIndex = queue_family_index;
1183+
1184+
VkResult result = device_table_->CreateCommandPool(device, &pool_create_info, nullptr, &transition_pool);
1185+
1186+
if (result == VK_SUCCESS)
1187+
{
1188+
VkCommandBufferAllocateInfo allocate_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
1189+
allocate_info.commandPool = transition_pool;
1190+
allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
1191+
allocate_info.commandBufferCount = 1;
1192+
1193+
result = device_table_->AllocateCommandBuffers(device, &allocate_info, &transition_command);
1194+
}
1195+
1196+
if (result == VK_SUCCESS)
1197+
{
1198+
VkCommandBufferBeginInfo begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
1199+
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1200+
result = device_table_->BeginCommandBuffer(transition_command, &begin_info);
1201+
}
1202+
1203+
if (result == VK_SUCCESS)
1204+
{
1205+
// Transition the virtual images to their captured layouts. They are plain images, so no acquire is
1206+
// required; the real swapchain images are transitioned separately on first acquire.
1207+
VkImageMemoryBarrier image_barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
1208+
image_barrier.srcAccessMask = VK_ACCESS_NONE;
1209+
image_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
1210+
image_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1211+
image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1212+
image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1213+
image_barrier.subresourceRange.baseMipLevel = 0;
1214+
image_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
1215+
image_barrier.subresourceRange.baseArrayLayer = 0;
1216+
image_barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
1217+
1218+
uint32_t barrier_count = 0;
1219+
1220+
for (const auto& entry : image_infos)
1221+
{
1222+
const VulkanImageInfo* image_info = object_info_table.GetVkImageInfo(entry.image_id);
1223+
if (image_info == nullptr)
1224+
{
1225+
GFXRECON_LOG_WARNING("Skipping layout restore for unrecognized VkImage object (ID = %" PRIu64 ")",
1226+
entry.image_id);
1227+
continue;
1228+
}
1229+
1230+
auto image_layout = static_cast<VkImageLayout>(entry.image_layout);
1231+
if (image_layout == VK_IMAGE_LAYOUT_UNDEFINED)
1232+
{
1233+
continue;
1234+
}
1235+
1236+
image_barrier.newLayout = image_layout;
1237+
image_barrier.image = image_info->handle;
1238+
image_barrier.subresourceRange.aspectMask = graphics::GetFormatAspects(image_info->format);
1239+
1240+
device_table_->CmdPipelineBarrier(transition_command,
1241+
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1242+
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
1243+
0,
1244+
0,
1245+
nullptr,
1246+
0,
1247+
nullptr,
1248+
1,
1249+
&image_barrier);
1250+
++barrier_count;
1251+
}
1252+
result = device_table_->EndCommandBuffer(transition_command);
1253+
1254+
if (result == VK_SUCCESS && barrier_count > 0)
1255+
{
1256+
VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
1257+
submit_info.commandBufferCount = 1;
1258+
submit_info.pCommandBuffers = &transition_command;
1259+
result = device_table_->QueueSubmit(transition_queue, 1, &submit_info, VK_NULL_HANDLE);
1260+
1261+
if (result == VK_SUCCESS)
1262+
{
1263+
result = device_table_->QueueWaitIdle(transition_queue);
1264+
}
1265+
}
1266+
}
1267+
1268+
if (result != VK_SUCCESS)
1269+
{
1270+
GFXRECON_LOG_WARNING("Failed image layout restore for VkSwapchainKHR object (ID = %" PRIu64 ")",
1271+
swapchain_info->capture_id);
1272+
}
1273+
1274+
if (transition_pool != VK_NULL_HANDLE)
1275+
{
1276+
device_table_->DestroyCommandPool(device, transition_pool, nullptr);
1277+
}
1278+
}
1279+
11481280
VkResult VulkanVirtualSwapchain::CreateRenderPass(VkResult original_result,
11491281
PFN_vkCreateRenderPass func,
11501282
const VulkanDeviceInfo* device_info,

framework/decode/vulkan_virtual_swapchain.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,12 @@ class VulkanVirtualSwapchain : public VulkanSwapchain
121121
application::Application* application,
122122
const std::optional<std::array<float, 2>>& scale) override;
123123

124-
virtual void ProcessSetSwapchainImageStateCommand(const VulkanDeviceInfo* device_info,
125-
VulkanSwapchainKHRInfo* swapchain_info,
126-
uint32_t last_presented_image,
127-
const std::vector<format::SwapchainImageStateInfo>& image_info,
128-
const CommonObjectInfoTable& object_info_table,
129-
SwapchainImageTracker& swapchain_image_tracker) override
130-
{}
124+
void ProcessSetSwapchainImageStateCommand(const VulkanDeviceInfo* device_info,
125+
VulkanSwapchainKHRInfo* swapchain_info,
126+
uint32_t last_presented_image,
127+
const std::vector<format::SwapchainImageStateInfo>& image_infos,
128+
const CommonObjectInfoTable& object_info_table,
129+
SwapchainImageTracker& swapchain_image_tracker) override;
131130

132131
protected:
133132
// Structure necessary to track the necessary information related to the virtual swapchain images

0 commit comments

Comments
 (0)