Skip to content

Commit

Permalink
vkd3d: Rewrite queue selection logic to consider priorities.
Browse files Browse the repository at this point in the history
Try to avoid scenarios where different prio queues share a physical
queue.

Signed-off-by: Hans-Kristian Arntzen <[email protected]>
  • Loading branch information
HansKristian-Work committed Jan 3, 2025
1 parent ec4d059 commit 53f004b
Showing 1 changed file with 65 additions and 6 deletions.
71 changes: 65 additions & 6 deletions libs/vkd3d/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -2633,23 +2633,82 @@ struct vkd3d_queue_family_info *d3d12_device_get_vkd3d_queue_family(struct d3d12
struct vkd3d_queue *d3d12_device_allocate_vkd3d_queue(struct vkd3d_queue_family_info *queue_family,
struct d3d12_command_queue *command_queue)
{
unsigned int num_available_physical_queues = 0;
struct vkd3d_queue *last_vacant_queue = NULL;
struct vkd3d_queue *queue;
unsigned int i;
bool allow_vacant_queue;
bool is_higher_prio;
unsigned int i, j;
int prio;

prio = command_queue ? command_queue->desc.Priority : D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
is_higher_prio = prio >= D3D12_COMMAND_QUEUE_PRIORITY_HIGH;

for (i = 0; i < queue_family->queue_count; i++)
pthread_mutex_lock(&queue_family->queues[i]->mutex);

for (i = 0; i < queue_family->queue_count; i++)
{
queue = queue_family->queues[i];
if (queue->virtual_queue_count == 0)
{
num_available_physical_queues++;
last_vacant_queue = queue;
}
}

if (num_available_physical_queues != 1)
last_vacant_queue = NULL;

allow_vacant_queue = !last_vacant_queue || is_higher_prio;

/* Select the queue that has the lowest number of virtual queues mapped
* to it, in order to avoid situations where we map multiple queues to
* the same vkd3d queue while others are unused */
queue = queue_family->queues[0];
* the same vkd3d queue while others are unused.
* To avoid staggered submit as much as possible, we should always leave one queue for any higher-prio work. */
queue = NULL;

if (num_available_physical_queues == 0 || is_higher_prio)
{
/* There is nothing left, switch the heuristic such that we match logical queue prios if possible,
* to avoid creating stagger submit scenarios if we can avoid it.
* Also take this path so that all high-prio work can share one queue. We don't want high prio queues
* to monopolize all physical queues if we can help it. */

for (i = 0; i < queue_family->queue_count; i++)
{
struct vkd3d_queue *candidate = queue_family->queues[i];

/* Don't try to alias with internal queues if possible. */
bool same_prio_level = candidate->command_queue_count != 0;

for (j = 0; j < candidate->command_queue_count && same_prio_level; j++)
same_prio_level = candidate->command_queues[j]->desc.Priority == prio;

if (!same_prio_level)
continue;

if (!queue || candidate->virtual_queue_count < queue->virtual_queue_count)
queue = candidate;
}
}

for (i = 1; i < queue_family->queue_count; i++)
if (!queue)
{
if (queue_family->queues[i]->virtual_queue_count < queue->virtual_queue_count)
queue = queue_family->queues[i];
for (i = 0; i < queue_family->queue_count; i++)
{
struct vkd3d_queue *candidate = queue_family->queues[i];
if (candidate->virtual_queue_count == 0 && !allow_vacant_queue)
continue;
if (!queue || candidate->virtual_queue_count < queue->virtual_queue_count)
queue = candidate;
}
}

if (!queue)
queue = last_vacant_queue;

assert(queue);
queue->virtual_queue_count++;

if (command_queue)
Expand Down

0 comments on commit 53f004b

Please sign in to comment.