This extension allows the caller to change a queue's system wide priority. This is useful for applications with specific latency constraints. Signed-off-by: Andres Rodriguez <andresx7@gmail.com> Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>tags/17.3-branchpoint
@@ -832,16 +832,40 @@ void radv_GetPhysicalDeviceMemoryProperties2KHR( | |||
&pMemoryProperties->memoryProperties); | |||
} | |||
static enum radeon_ctx_priority | |||
radv_get_queue_global_priority(const VkDeviceQueueGlobalPriorityCreateInfoEXT *pObj) | |||
{ | |||
/* Default to MEDIUM when a specific global priority isn't requested */ | |||
if (!pObj) | |||
return RADEON_CTX_PRIORITY_MEDIUM; | |||
switch(pObj->globalPriority) { | |||
case VK_QUEUE_GLOBAL_PRIORITY_REALTIME: | |||
return RADEON_CTX_PRIORITY_REALTIME; | |||
case VK_QUEUE_GLOBAL_PRIORITY_HIGH: | |||
return RADEON_CTX_PRIORITY_HIGH; | |||
case VK_QUEUE_GLOBAL_PRIORITY_MEDIUM: | |||
return RADEON_CTX_PRIORITY_MEDIUM; | |||
case VK_QUEUE_GLOBAL_PRIORITY_LOW: | |||
return RADEON_CTX_PRIORITY_LOW; | |||
default: | |||
unreachable("Illegal global priority value"); | |||
return RADEON_CTX_PRIORITY_INVALID; | |||
} | |||
} | |||
static int | |||
radv_queue_init(struct radv_device *device, struct radv_queue *queue, | |||
int queue_family_index, int idx) | |||
int queue_family_index, int idx, | |||
const VkDeviceQueueGlobalPriorityCreateInfoEXT *global_priority) | |||
{ | |||
queue->_loader_data.loaderMagic = ICD_LOADER_MAGIC; | |||
queue->device = device; | |||
queue->queue_family_index = queue_family_index; | |||
queue->queue_idx = idx; | |||
queue->priority = radv_get_queue_global_priority(global_priority); | |||
queue->hw_ctx = device->ws->ctx_create(device->ws); | |||
queue->hw_ctx = device->ws->ctx_create(device->ws, queue->priority); | |||
if (!queue->hw_ctx) | |||
return VK_ERROR_OUT_OF_HOST_MEMORY; | |||
@@ -962,6 +986,8 @@ VkResult radv_CreateDevice( | |||
for (unsigned i = 0; i < pCreateInfo->queueCreateInfoCount; i++) { | |||
const VkDeviceQueueCreateInfo *queue_create = &pCreateInfo->pQueueCreateInfos[i]; | |||
uint32_t qfi = queue_create->queueFamilyIndex; | |||
const VkDeviceQueueGlobalPriorityCreateInfoEXT *global_priority = | |||
vk_find_struct_const(queue_create->pNext, DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT); | |||
device->queues[qfi] = vk_alloc(&device->alloc, | |||
queue_create->queueCount * sizeof(struct radv_queue), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); | |||
@@ -975,7 +1001,7 @@ VkResult radv_CreateDevice( | |||
device->queue_count[qfi] = queue_create->queueCount; | |||
for (unsigned q = 0; q < queue_create->queueCount; q++) { | |||
result = radv_queue_init(device, &device->queues[qfi][q], qfi, q); | |||
result = radv_queue_init(device, &device->queues[qfi][q], qfi, q, global_priority); | |||
if (result != VK_SUCCESS) | |||
goto fail; | |||
} |
@@ -487,6 +487,7 @@ struct radv_queue { | |||
VK_LOADER_DATA _loader_data; | |||
struct radv_device * device; | |||
struct radeon_winsys_ctx *hw_ctx; | |||
enum radeon_ctx_priority priority; | |||
int queue_family_index; | |||
int queue_idx; | |||
@@ -70,6 +70,14 @@ enum ring_type { | |||
RING_LAST, | |||
}; | |||
enum radeon_ctx_priority { | |||
RADEON_CTX_PRIORITY_INVALID = -1, | |||
RADEON_CTX_PRIORITY_LOW = 0, | |||
RADEON_CTX_PRIORITY_MEDIUM, | |||
RADEON_CTX_PRIORITY_HIGH, | |||
RADEON_CTX_PRIORITY_REALTIME, | |||
}; | |||
struct radeon_winsys_cs { | |||
unsigned cdw; /* Number of used dwords. */ | |||
unsigned max_dw; /* Maximum number of dwords. */ | |||
@@ -188,7 +196,8 @@ struct radeon_winsys { | |||
void (*buffer_virtual_bind)(struct radeon_winsys_bo *parent, | |||
uint64_t offset, uint64_t size, | |||
struct radeon_winsys_bo *bo, uint64_t bo_offset); | |||
struct radeon_winsys_ctx *(*ctx_create)(struct radeon_winsys *ws); | |||
struct radeon_winsys_ctx *(*ctx_create)(struct radeon_winsys *ws, | |||
enum radeon_ctx_priority priority); | |||
void (*ctx_destroy)(struct radeon_winsys_ctx *ctx); | |||
bool (*ctx_wait_idle)(struct radeon_winsys_ctx *ctx, |
@@ -951,7 +951,6 @@ static int radv_amdgpu_winsys_cs_submit(struct radeon_winsys_ctx *_ctx, | |||
return ret; | |||
} | |||
static void *radv_amdgpu_winsys_get_cpu_addr(void *_cs, uint64_t addr) | |||
{ | |||
struct radv_amdgpu_cs *cs = (struct radv_amdgpu_cs *)_cs; | |||
@@ -1002,17 +1001,36 @@ static void radv_amdgpu_winsys_cs_dump(struct radeon_winsys_cs *_cs, | |||
cs->ws->info.chip_class, radv_amdgpu_winsys_get_cpu_addr, cs); | |||
} | |||
static struct radeon_winsys_ctx *radv_amdgpu_ctx_create(struct radeon_winsys *_ws) | |||
static uint32_t radv_to_amdgpu_priority(enum radeon_ctx_priority radv_priority) | |||
{ | |||
switch (radv_priority) { | |||
case RADEON_CTX_PRIORITY_REALTIME: | |||
return AMDGPU_CTX_PRIORITY_VERY_HIGH; | |||
case RADEON_CTX_PRIORITY_HIGH: | |||
return AMDGPU_CTX_PRIORITY_HIGH; | |||
case RADEON_CTX_PRIORITY_MEDIUM: | |||
return AMDGPU_CTX_PRIORITY_NORMAL; | |||
case RADEON_CTX_PRIORITY_LOW: | |||
return AMDGPU_CTX_PRIORITY_LOW; | |||
default: | |||
unreachable("Invalid context priority"); | |||
} | |||
} | |||
static struct radeon_winsys_ctx *radv_amdgpu_ctx_create(struct radeon_winsys *_ws, | |||
enum radeon_ctx_priority priority) | |||
{ | |||
struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws); | |||
struct radv_amdgpu_ctx *ctx = CALLOC_STRUCT(radv_amdgpu_ctx); | |||
uint32_t amdgpu_priority = radv_to_amdgpu_priority(priority); | |||
int r; | |||
if (!ctx) | |||
return NULL; | |||
r = amdgpu_cs_ctx_create(ws->dev, &ctx->ctx); | |||
r = amdgpu_cs_ctx_create2(ws->dev, amdgpu_priority, &ctx->ctx); | |||
if (r) { | |||
fprintf(stderr, "amdgpu: radv_amdgpu_cs_ctx_create failed. (%i)\n", r); | |||
fprintf(stderr, "amdgpu: radv_amdgpu_cs_ctx_create2 failed. (%i)\n", r); | |||
goto error_create; | |||
} | |||
ctx->ws = ws; |