win-capture: Make Vulkan frame data local to queue

Prevents multiple queues in the same family from racing on frame data.

Removal of vk_family_data also fixes broken capacity calculation. Two
queue families can share the same index if one is "protected-capable"
and the other isn't.
This commit is contained in:
jpark37 2020-07-26 13:31:16 -07:00
parent e6896d79e3
commit 04b9b9fea3

View File

@ -59,6 +59,9 @@ struct vk_queue_data {
uint32_t fam_idx;
bool supports_transfer;
struct vk_frame_data *frames;
uint32_t frame_index;
uint32_t frame_count;
};
struct vk_frame_data {
@ -68,12 +71,6 @@ struct vk_frame_data {
bool cmd_buffer_busy;
};
struct vk_family_data {
struct vk_frame_data *frames;
uint32_t frame_index;
uint32_t frame_count;
};
struct vk_surf_data {
struct vk_obj_node node;
@ -103,8 +100,6 @@ struct vk_data {
struct vk_obj_list queues;
struct vk_family_data *families;
uint32_t family_capacity;
VkExternalMemoryProperties external_mem_props;
struct vk_inst_data *inst_data;
@ -272,6 +267,9 @@ static struct vk_queue_data *add_queue_data(struct vk_data *data, VkQueue queue,
add_obj_data(&data->queues, (uint64_t)queue, queue_data);
queue_data->fam_idx = fam_idx;
queue_data->supports_transfer = supports_transfer;
queue_data->frames = NULL;
queue_data->frame_index = 0;
queue_data->frame_count = 0;
return queue_data;
}
@ -378,12 +376,12 @@ static void vk_shtex_clear_fence(const struct vk_data *data,
}
static void vk_shtex_wait_until_pool_idle(struct vk_data *data,
struct vk_family_data *family_data)
struct vk_queue_data *queue_data)
{
for (uint32_t frame_idx = 0; frame_idx < family_data->frame_count;
for (uint32_t frame_idx = 0; frame_idx < queue_data->frame_count;
frame_idx++) {
struct vk_frame_data *frame_data =
&family_data->frames[frame_idx];
&queue_data->frames[frame_idx];
if (frame_data->cmd_pool != VK_NULL_HANDLE)
vk_shtex_clear_fence(data, frame_data);
}
@ -391,10 +389,15 @@ static void vk_shtex_wait_until_pool_idle(struct vk_data *data,
static void vk_shtex_wait_until_idle(struct vk_data *data)
{
for (uint32_t fam_idx = 0; fam_idx < data->family_capacity; fam_idx++) {
struct vk_family_data *family_data = &data->families[fam_idx];
vk_shtex_wait_until_pool_idle(data, family_data);
struct vk_queue_data *queue_data = queue_walk_begin(data);
while (queue_data) {
vk_shtex_wait_until_pool_idle(data, queue_data);
queue_data = queue_walk_next(queue_data);
}
queue_walk_end(data);
}
static void vk_shtex_free(struct vk_data *data)
@ -880,31 +883,30 @@ static bool vk_shtex_init(struct vk_data *data, HWND window,
return true;
}
static void vk_shtex_create_family_objects(struct vk_data *data,
uint32_t fam_idx,
uint32_t image_count)
static void vk_shtex_create_frame_objects(struct vk_data *data,
struct vk_queue_data *queue_data,
uint32_t image_count)
{
struct vk_family_data *family_data = &data->families[fam_idx];
family_data->frames =
queue_data->frames =
vk_alloc(data->ac, image_count * sizeof(struct vk_frame_data),
_Alignof(struct vk_frame_data),
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
memset(family_data->frames, 0,
memset(queue_data->frames, 0,
image_count * sizeof(struct vk_frame_data));
family_data->frame_index = 0;
family_data->frame_count = image_count;
queue_data->frame_index = 0;
queue_data->frame_count = image_count;
VkDevice device = data->device;
for (uint32_t image_index = 0; image_index < image_count;
image_index++) {
struct vk_frame_data *frame_data =
&family_data->frames[image_index];
&queue_data->frames[image_index];
VkCommandPoolCreateInfo cpci;
cpci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
cpci.pNext = NULL;
cpci.flags = 0;
cpci.queueFamilyIndex = fam_idx;
cpci.queueFamilyIndex = queue_data->fam_idx;
VkResult res = data->funcs.CreateCommandPool(
device, &cpci, data->ac, &frame_data->cmd_pool);
@ -946,15 +948,15 @@ static void vk_shtex_destroy_fence(struct vk_data *data, bool *cmd_buffer_busy,
*fence = VK_NULL_HANDLE;
}
static void vk_shtex_destroy_family_objects(struct vk_data *data,
struct vk_family_data *family_data)
static void vk_shtex_destroy_frame_objects(struct vk_data *data,
struct vk_queue_data *queue_data)
{
VkDevice device = data->device;
for (uint32_t frame_idx = 0; frame_idx < family_data->frame_count;
for (uint32_t frame_idx = 0; frame_idx < queue_data->frame_count;
frame_idx++) {
struct vk_frame_data *frame_data =
&family_data->frames[frame_idx];
&queue_data->frames[frame_idx];
bool *cmd_buffer_busy = &frame_data->cmd_buffer_busy;
VkFence *fence = &frame_data->fence;
vk_shtex_destroy_fence(data, cmd_buffer_busy, fence);
@ -964,9 +966,9 @@ static void vk_shtex_destroy_family_objects(struct vk_data *data,
frame_data->cmd_pool = VK_NULL_HANDLE;
}
vk_free(data->ac, family_data->frames);
family_data->frames = NULL;
family_data->frame_count = 0;
vk_free(data->ac, queue_data->frames);
queue_data->frames = NULL;
queue_data->frame_count = 0;
}
static void vk_shtex_capture(struct vk_data *data,
@ -995,17 +997,16 @@ static void vk_shtex_capture(struct vk_data *data,
struct vk_queue_data *queue_data = get_queue_data(data, queue);
uint32_t fam_idx = queue_data->fam_idx;
struct vk_family_data *family_data = &data->families[fam_idx];
const uint32_t image_count = swap->image_count;
if (family_data->frame_count < image_count) {
if (family_data->frame_count > 0)
vk_shtex_destroy_family_objects(data, family_data);
vk_shtex_create_family_objects(data, fam_idx, image_count);
if (queue_data->frame_count < image_count) {
if (queue_data->frame_count > 0)
vk_shtex_destroy_frame_objects(data, queue_data);
vk_shtex_create_frame_objects(data, queue_data, image_count);
}
const uint32_t frame_index = family_data->frame_index;
struct vk_frame_data *frame_data = &family_data->frames[frame_index];
family_data->frame_index = (frame_index + 1) % family_data->frame_count;
const uint32_t frame_index = queue_data->frame_index;
struct vk_frame_data *frame_data = &queue_data->frames[frame_index];
queue_data->frame_index = (frame_index + 1) % queue_data->frame_count;
vk_shtex_clear_fence(data, frame_data);
VkDevice device = data->device;
@ -1585,17 +1586,6 @@ static VkResult VKAPI_CALL OBS_CreateDevice(VkPhysicalDevice phy_device,
data->ac = &data->ac_storage;
}
uint32_t totol_queue_count = 0;
uint32_t family_capacity = 1;
for (uint32_t i = 0, count = info->queueCreateInfoCount; i < count;
++i) {
const VkDeviceQueueCreateInfo *queue_info =
&info->pQueueCreateInfos[i];
totol_queue_count += queue_info->queueCount;
family_capacity =
max(family_capacity, queue_info->queueFamilyIndex + 1);
}
uint32_t queue_family_property_count = 0;
ifuncs->GetPhysicalDeviceQueueFamilyProperties(
phy_device, &queue_family_property_count, NULL);
@ -1629,14 +1619,6 @@ static VkResult VKAPI_CALL OBS_CreateDevice(VkPhysicalDevice phy_device,
_freea(queue_family_properties);
data->families =
vk_alloc(ac, family_capacity * sizeof(struct vk_family_data),
_Alignof(struct vk_family_data),
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
memset(data->families, 0,
family_capacity * sizeof(struct vk_family_data));
data->family_capacity = family_capacity;
init_obj_list(&data->swaps);
data->valid = true;
@ -1651,18 +1633,17 @@ static void VKAPI_CALL OBS_DestroyDevice(VkDevice device,
struct vk_data *data = remove_device_data(device);
if (data->valid) {
for (uint32_t fam_idx = 0; fam_idx < data->family_capacity;
fam_idx++) {
struct vk_family_data *family_data =
&data->families[fam_idx];
vk_shtex_destroy_family_objects(data, family_data);
struct vk_queue_data *queue_data = queue_walk_begin(data);
while (queue_data) {
vk_shtex_destroy_frame_objects(data, queue_data);
queue_data = queue_walk_next(queue_data);
}
remove_free_queue_all(data, ac);
queue_walk_end(data);
vk_free(ac, data->families);
data->families = NULL;
data->family_capacity = 0;
remove_free_queue_all(data, ac);
}
PFN_vkDestroyDevice destroy_device = data->funcs.DestroyDevice;