Add a new extension VK_EXT_queue_global_priority, which allows the
caller to elevate a queue's priority above all other queues in the
system.

This extension aims to provide a mechanism for compositors to have
achieve a guaranteed quality of service, even when the hardware may be
loaded by a game or application.
---
 docs/specs/VK_EXT_queue_global_priority.txt   | 97 +++++++++++++++++++++++++++
 include/vulkan/vk_ext_queue_global_priority.h | 72 ++++++++++++++++++++
 src/amd/vulkan/radv_device.c                  | 31 ++++++++-
 src/amd/vulkan/radv_private.h                 | 12 ++++
 src/amd/vulkan/radv_radeon_winsys.h           |  8 ++-
 src/amd/vulkan/winsys/amdgpu/radv_amdgpu_cs.c | 20 +++++-
 6 files changed, 234 insertions(+), 6 deletions(-)
 create mode 100644 docs/specs/VK_EXT_queue_global_priority.txt
 create mode 100644 include/vulkan/vk_ext_queue_global_priority.h

diff --git a/docs/specs/VK_EXT_queue_global_priority.txt 
b/docs/specs/VK_EXT_queue_global_priority.txt
new file mode 100644
index 0000000..9a6a712
--- /dev/null
+++ b/docs/specs/VK_EXT_queue_global_priority.txt
@@ -0,0 +1,97 @@
+Name Strings
+
+    VK_EXT_queue_global_priority
+
+Extension Type
+
+    Queue Extension
+
+Registered Extension Number
+
+    Draft
+
+Status
+
+    Draft
+
+Version
+
+    0 (Early Draft)
+
+Last Modified Date
+
+    See git log.
+
+IP Status
+
+    No known IP claims.
+
+Dependencies
+
+    This extension is written against the Vulkan 1.0.32 specification [1].
+
+Contributors
+
+    Andres Rodriguez, Valve Software <andr...@valvesoftware.com>
+    Pierre-Loup Griffais, Valve Software <pgriff...@valvesoftware.com>
+
+Contact
+
+    Andres Rodriguez, Valve Software <andr...@valvesoftware.com>
+
+Overview
+
+    In Vulkan 1.0.32 users can specify device-scope queue priorities. In
+       some cases it may be useful to extend this concept to a system-wide 
scope.
+
+       This extension provides a mechanism for caller's to set their 
system-wide
+    priority. The default queue priority is VK_QUEUE_GLOBAL_PRIORITY_NORMAL.
+
+       TODO: privileges required for priority escalation and note about system
+    resource starvation.
+
+New Object Types
+
+    VkQueueGlobalPriorityEXT
+               VK_STRUCTURE_TYPE_QUEUE_GLOBAL_PRIORITY_EXT
+
+New Enum Constants
+
+       None
+
+New Enums
+
+       VkQueueGlobalPriority
+               VK_QUEUE_GLOBAL_PRIORITY_HIGH
+               VK_QUEUE_GLOBAL_PRIORITY_NORMAL
+
+New Structs
+
+       typedef struct VkQueueGlobalPriorityEXT {
+               VkStructureType                         sType;
+               void*                                   pNext;
+               VkQueueGlobalPriority                   priority;
+       } VkQueueGlobalPriorityEXT;
+
+New Functions
+
+    None
+
+Description
+
+    TODO
+
+Issues
+
+       TODO
+
+References
+
+    [1]: https://github.com/KhronosGroup/Vulkan-Docs/tree/v1.0-core-20161025
+
+Version History
+
+    See git log for full history.
+
+    - Revision 1, 2017-01-01 (Andres Rodriguez)
+        - Initial draft
diff --git a/include/vulkan/vk_ext_queue_global_priority.h 
b/include/vulkan/vk_ext_queue_global_priority.h
new file mode 100644
index 0000000..01c7329
--- /dev/null
+++ b/include/vulkan/vk_ext_queue_global_priority.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017 Valve Software
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef VK_EXT_QUEUE_GLOBAL_PRIORITY_H_
+#define VK_EXT_QUEUE_GLOBAL_PRIORITY_H_
+
+#include "vulkan.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Draft spec lives at <docs/specs/VK_EXT_queue_global_prioruity.txt>.
+ *
+ * TODO: Discuss with everyone who cares.
+ * TODO: Get a proper VkStructureType
+ * TODO: Finish spec
+ */
+#define VK_EXT_queue_global_priority
+#define VK_EXT_queue_global_priotiry_SPEC_VERSION 0 /* experimental */
+#define VK_EXT_queue_global_priority_EXTENSION_NAME 
"VK_EXT_queue_global_priority"
+
+/** System-wide queue priority
+ *
+ *  High priority queues may starve queues in other processes
+ */
+typedef enum VkQueueGlobalPriority {
+    VK_QUEUE_GLOBAL_PRIORITY_HIGH = 1,
+    VK_QUEUE_GLOBAL_PRIORITY_NORMAL = 2,
+    VK_QUEUE_GLOBAL_PRIORITY_BEGIN_RANGE = VK_QUEUE_GLOBAL_PRIORITY_HIGH,
+    VK_QUEUE_GLOBAL_PRIORITY_END_RANGE = VK_QUEUE_GLOBAL_PRIORITY_NORMAL,
+    VK_QUEUE_GLOBAL_PRIORITY_RANGE_SIZE = (VK_QUEUE_GLOBAL_PRIORITY_HIGH - 
VK_QUEUE_GLOBAL_PRIORITY_NORMAL + 1),
+    VK_QUEUE_GLOBAL_PRIORITY_MAX_ENUM = 0x7FFFFFFF
+} VkQueueGlobalPriority;
+
+/* Extends VkDeviceQueueCreateInfo.
+ *
+ * Used to set the global priority for the allocated queue
+ */
+typedef struct VkQueueGlobalPriorityEXT {
+    VkStructureType                         sType;
+    void*                                   pNext;
+    VkQueueGlobalPriority                   priority;
+} VkQueueGlobalPriorityEXT;
+
+#define VK_STRUCTURE_TYPE_QUEUE_GLOBAL_PRIORITY_EXT (VkStructureType)1000120001
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c
index d9f9a2b..9880a5d 100644
--- a/src/amd/vulkan/radv_device.c
+++ b/src/amd/vulkan/radv_device.c
@@ -651,16 +651,41 @@ void radv_GetPhysicalDeviceMemoryProperties(
        };
 }
 
+static enum ctx_priority
+radv_get_queue_global_priority(VkQueueGlobalPriorityEXT *pObj)
+{
+       switch(pObj->priority) {
+       case VK_QUEUE_GLOBAL_PRIORITY_HIGH:
+               return CTX_PRIORITY_HIGH;
+       default:
+               return CTX_PRIORITY_NORMAL;
+       }
+}
+
 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 VkDeviceQueueCreateInfo 
*create_info)
 {
        queue->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
        queue->device = device;
        queue->queue_family_index = queue_family_index;
        queue->queue_idx = idx;
+       queue->priority = CTX_PRIORITY_NORMAL;
+
+       radv_foreach_ext_obj(create_info, next_obj) {
+               switch (next_obj->sType) {
+               case VK_STRUCTURE_TYPE_QUEUE_GLOBAL_PRIORITY_EXT:
+                       queue->priority = radv_get_queue_global_priority(
+                                                                       
(VkQueueGlobalPriorityEXT*)next_obj);
+                       break;
+               default:
+                       radv_finishme("Unsupported queue extension 
VkStructureType %d\n",
+                                                       next_obj->sType);
+                       break;
+               }
+       }
 
-       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;
 
@@ -731,7 +756,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, queue_create);
                        if (result != VK_SUCCESS)
                                goto fail;
                }
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
index d316f71..d79ef3a 100644
--- a/src/amd/vulkan/radv_private.h
+++ b/src/amd/vulkan/radv_private.h
@@ -66,6 +66,7 @@ typedef uint32_t xcb_window_t;
 
 #include <vulkan/vulkan.h>
 #include <vulkan/vulkan_intel.h>
+#include <vulkan/vk_ext_queue_global_priority.h>
 #include <vulkan/vk_icd.h>
 
 #include "radv_entrypoints.h"
@@ -457,6 +458,7 @@ struct radv_queue {
        VK_LOADER_DATA                              _loader_data;
        struct radv_device *                         device;
        struct radeon_winsys_ctx                    *hw_ctx;
+       enum ctx_priority                            priority;
        int queue_family_index;
        int queue_idx;
 };
@@ -1325,4 +1327,14 @@ RADV_DEFINE_NONDISP_HANDLE_CASTS(radv_shader_module, 
VkShaderModule)
                return (const __VkType *) __radv_obj;                   \
        }
 
+/**
+ * Used to iterate over Vk structs that support extension types
+ *
+ * Iterate over the __obj->pNext list, keeping the current object in __varname
+ */
+#define radv_foreach_ext_obj(__obj, __varname) \
+               /*Note: Any type with sType/pNext works here*/ \
+               for ( VkSubmitInfo *__varname = (VkSubmitInfo*)__obj->pNext;\
+                               __varname != NULL;\
+                               __varname = (VkSubmitInfo*)__varname->pNext)
 #endif /* RADV_PRIVATE_H */
diff --git a/src/amd/vulkan/radv_radeon_winsys.h 
b/src/amd/vulkan/radv_radeon_winsys.h
index 4b738b8..3218c87 100644
--- a/src/amd/vulkan/radv_radeon_winsys.h
+++ b/src/amd/vulkan/radv_radeon_winsys.h
@@ -64,6 +64,11 @@ enum ring_type {
        RING_LAST,
 };
 
+enum ctx_priority {
+       CTX_PRIORITY_HIGH = 0,
+       CTX_PRIORITY_NORMAL
+};
+
 struct radeon_winsys_cs {
        unsigned cdw;  /* Number of used dwords. */
        unsigned max_dw; /* Maximum number of dwords. */
@@ -284,7 +289,8 @@ struct radeon_winsys {
 
        void (*buffer_set_metadata)(struct radeon_winsys_bo *bo,
                                    struct radeon_bo_metadata *md);
-       struct radeon_winsys_ctx *(*ctx_create)(struct radeon_winsys *ws);
+       struct radeon_winsys_ctx *(*ctx_create)(struct radeon_winsys *ws,
+                                                                               
        enum ctx_priority priority);
        void (*ctx_destroy)(struct radeon_winsys_ctx *ctx);
 
        bool (*ctx_wait_idle)(struct radeon_winsys_ctx *ctx,
diff --git a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_cs.c 
b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_cs.c
index b24aa99..585ccf4 100644
--- a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_cs.c
+++ b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_cs.c
@@ -775,15 +775,31 @@ static int radv_amdgpu_winsys_cs_submit(struct 
radeon_winsys_ctx *_ctx,
        return ret;
 }
 
-static struct radeon_winsys_ctx *radv_amdgpu_ctx_create(struct radeon_winsys 
*_ws)
+static uint32_t radv_to_amdgpu_priority(enum ctx_priority priority 
radv_priority)
+{
+       switch (radv_priority) {
+               case AMDGPU_CTX_PRIORITY_HIGH:
+                       return AMDGPU_CTX_PRIORITY_HIGH;
+               case AMDGPU_CTX_PRIORITY_NORMAL:
+                       return AMDGPU_CTX_PRIORITY_NORMAL;
+               default:
+                       radv_loge("Invalid radv priority %d\n, defualting to 
normal", radv_priority);
+                       return AMDGPU_CTX_PRIORITY_NORMAL;
+       }
+}
+
+static struct radeon_winsys_ctx *radv_amdgpu_ctx_create(struct radeon_winsys 
*_ws,
+                                                                               
                                enum 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);
                goto error_create;
-- 
2.9.3

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to