radv: Implement VK_EXT_global_priority
authorAndres Rodriguez <andresx7@gmail.com>
Fri, 20 Oct 2017 22:02:14 +0000 (18:02 -0400)
committerBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Fri, 20 Oct 2017 23:01:44 +0000 (01:01 +0200)
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>
src/amd/vulkan/radv_device.c
src/amd/vulkan/radv_private.h
src/amd/vulkan/radv_radeon_winsys.h
src/amd/vulkan/winsys/amdgpu/radv_amdgpu_cs.c

index ab7e97b8ba1e4d7291b0fe243b1b9a06f4c29567..307d5579573c2445527cfcd589cadee165c1cdb9 100644 (file)
@@ -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;
                }
index a149f72e61235166c742be233f5bd28ad396dfd2..47a068b5597cb48be57019135c4cb7492330f5ff 100644 (file)
@@ -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;
 
index 52b55c38e697c72d77e42a3ef8854364b4338a3c..328b8a19cc5414cc900fccecb688fb9e5a329ced 100644 (file)
@@ -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,
index 53d428681cd8890b79e242fd01fd205eda370ab4..46e5b7670331b640af0a76b87e9fc59ac8378bde 100644 (file)
@@ -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;