1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2021 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#ifndef VK_QUEUE_H 25bf215546Sopenharmony_ci#define VK_QUEUE_H 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "vk_device.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "c11/threads.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci#include "util/list.h" 32bf215546Sopenharmony_ci#include "util/u_dynarray.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#ifdef __cplusplus 35bf215546Sopenharmony_ciextern "C" { 36bf215546Sopenharmony_ci#endif 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_cistruct vk_command_buffer; 39bf215546Sopenharmony_cistruct vk_queue_submit; 40bf215546Sopenharmony_cistruct vk_sync; 41bf215546Sopenharmony_cistruct vk_sync_wait; 42bf215546Sopenharmony_cistruct vk_sync_signal; 43bf215546Sopenharmony_cistruct vk_sync_timeline_point; 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_cistruct vk_queue { 46bf215546Sopenharmony_ci struct vk_object_base base; 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci /* Link in vk_device::queues */ 49bf215546Sopenharmony_ci struct list_head link; 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci /* VkDeviceQueueCreateInfo::flags */ 52bf215546Sopenharmony_ci VkDeviceQueueCreateFlags flags; 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci /* VkDeviceQueueCreateInfo::queueFamilyIndex */ 55bf215546Sopenharmony_ci uint32_t queue_family_index; 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci /* Which queue this is within the queue family */ 58bf215546Sopenharmony_ci uint32_t index_in_family; 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci /** Driver queue submit hook 61bf215546Sopenharmony_ci * 62bf215546Sopenharmony_ci * When using the common implementation of vkQueueSubmit(), this function 63bf215546Sopenharmony_ci * is called to do the final submit to the kernel driver after all 64bf215546Sopenharmony_ci * semaphore dependencies have been resolved. Depending on the timeline 65bf215546Sopenharmony_ci * mode and application usage, this function may be called directly from 66bf215546Sopenharmony_ci * the client thread on which vkQueueSubmit was called or from a runtime- 67bf215546Sopenharmony_ci * managed submit thread. We do, however, guarantee that as long as the 68bf215546Sopenharmony_ci * client follows the Vulkan threading rules, this function will never be 69bf215546Sopenharmony_ci * called by the runtime concurrently on the same queue. 70bf215546Sopenharmony_ci */ 71bf215546Sopenharmony_ci VkResult (*driver_submit)(struct vk_queue *queue, 72bf215546Sopenharmony_ci struct vk_queue_submit *submit); 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci struct { 75bf215546Sopenharmony_ci /** Current submit mode 76bf215546Sopenharmony_ci * 77bf215546Sopenharmony_ci * This represents the exact current submit mode for this specific queue 78bf215546Sopenharmony_ci * which may be different from `vk_device::submit_mode`. In particular, 79bf215546Sopenharmony_ci * this will never be `VK_QUEUE_SUBMIT_MODE_THREADED_ON_DEMAND`. 80bf215546Sopenharmony_ci * Instead, when the device submit mode is 81bf215546Sopenharmony_ci * `VK_QUEUE_SUBMIT_MODE_THREADED_ON_DEMAND`, the queue submit mode 82bf215546Sopenharmony_ci * will be one of `VK_QUEUE_SUBMIT_MODE_THREADED` or 83bf215546Sopenharmony_ci * `VK_QUEUE_SUBMIT_MODE_IMMEDIATE` depending on whether or not a submit 84bf215546Sopenharmony_ci * thread is currently running for this queue. If the device submit 85bf215546Sopenharmony_ci * mode is `VK_QUEUE_SUBMIT_MODE_DEFERRED`, every queue in the device 86bf215546Sopenharmony_ci * will use `VK_QUEUE_SUBMIT_MODE_DEFERRED` because the deferred submit 87bf215546Sopenharmony_ci * model depends on regular flushing instead of independent threads. 88bf215546Sopenharmony_ci */ 89bf215546Sopenharmony_ci enum vk_queue_submit_mode mode; 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci mtx_t mutex; 92bf215546Sopenharmony_ci cnd_t push; 93bf215546Sopenharmony_ci cnd_t pop; 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci struct list_head submits; 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci bool thread_run; 98bf215546Sopenharmony_ci thrd_t thread; 99bf215546Sopenharmony_ci } submit; 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci struct { 102bf215546Sopenharmony_ci /* Only set once atomically by the queue */ 103bf215546Sopenharmony_ci int lost; 104bf215546Sopenharmony_ci int error_line; 105bf215546Sopenharmony_ci const char *error_file; 106bf215546Sopenharmony_ci char error_msg[80]; 107bf215546Sopenharmony_ci } _lost; 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci /** 110bf215546Sopenharmony_ci * VK_EXT_debug_utils 111bf215546Sopenharmony_ci * 112bf215546Sopenharmony_ci * The next two fields represent debug labels storage. 113bf215546Sopenharmony_ci * 114bf215546Sopenharmony_ci * VK_EXT_debug_utils spec requires that upon triggering a debug message 115bf215546Sopenharmony_ci * with a queue attached to it, all "active" labels will also be provided 116bf215546Sopenharmony_ci * to the callback. The spec describes two distinct ways of attaching a 117bf215546Sopenharmony_ci * debug label to the queue: opening a label region and inserting a single 118bf215546Sopenharmony_ci * label. 119bf215546Sopenharmony_ci * 120bf215546Sopenharmony_ci * Label region is active between the corresponding `*BeginDebugUtilsLabel` 121bf215546Sopenharmony_ci * and `*EndDebugUtilsLabel` calls. The spec doesn't mention any limits on 122bf215546Sopenharmony_ci * nestedness of label regions. This implementation assumes that there 123bf215546Sopenharmony_ci * aren't any. 124bf215546Sopenharmony_ci * 125bf215546Sopenharmony_ci * The spec, however, doesn't explain the lifetime of a label submitted by 126bf215546Sopenharmony_ci * an `*InsertDebugUtilsLabel` call. The LunarG whitepaper [1] (pp 12-15) 127bf215546Sopenharmony_ci * provides a more detailed explanation along with some examples. According 128bf215546Sopenharmony_ci * to those, such label remains active until the next `*DebugUtilsLabel` 129bf215546Sopenharmony_ci * call. This means that there can be no more than one such label at a 130bf215546Sopenharmony_ci * time. 131bf215546Sopenharmony_ci * 132bf215546Sopenharmony_ci * \c labels contains all active labels at this point in order of submission 133bf215546Sopenharmony_ci * \c region_begin denotes whether the most recent label opens a new region 134bf215546Sopenharmony_ci * If \t labels is empty \t region_begin must be true. 135bf215546Sopenharmony_ci * 136bf215546Sopenharmony_ci * Anytime we modify labels, we first check for \c region_begin. If it's 137bf215546Sopenharmony_ci * false, it means that the most recent label was submitted by 138bf215546Sopenharmony_ci * `*InsertDebugUtilsLabel` and we need to remove it before doing anything 139bf215546Sopenharmony_ci * else. 140bf215546Sopenharmony_ci * 141bf215546Sopenharmony_ci * See the discussion here: 142bf215546Sopenharmony_ci * https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10318#note_1061317 143bf215546Sopenharmony_ci * 144bf215546Sopenharmony_ci * [1] https://www.lunarg.com/wp-content/uploads/2018/05/Vulkan-Debug-Utils_05_18_v1.pdf 145bf215546Sopenharmony_ci */ 146bf215546Sopenharmony_ci struct util_dynarray labels; 147bf215546Sopenharmony_ci bool region_begin; 148bf215546Sopenharmony_ci}; 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ciVK_DEFINE_HANDLE_CASTS(vk_queue, base, VkQueue, VK_OBJECT_TYPE_QUEUE) 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ciVkResult MUST_CHECK 153bf215546Sopenharmony_civk_queue_init(struct vk_queue *queue, struct vk_device *device, 154bf215546Sopenharmony_ci const VkDeviceQueueCreateInfo *pCreateInfo, 155bf215546Sopenharmony_ci uint32_t index_in_family); 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_civoid 158bf215546Sopenharmony_civk_queue_finish(struct vk_queue *queue); 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_cistatic inline bool 161bf215546Sopenharmony_civk_queue_is_empty(struct vk_queue *queue) 162bf215546Sopenharmony_ci{ 163bf215546Sopenharmony_ci return list_is_empty(&queue->submit.submits); 164bf215546Sopenharmony_ci} 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci/** Enables threaded submit on this queue 167bf215546Sopenharmony_ci * 168bf215546Sopenharmony_ci * This should be called by the driver if it wants to be able to block inside 169bf215546Sopenharmony_ci * `vk_queue::driver_submit`. Once this function has been called, the queue 170bf215546Sopenharmony_ci * will always use a submit thread for all submissions. You must have called 171bf215546Sopenharmony_ci * vk_device_enabled_threaded_submit() before calling this function. 172bf215546Sopenharmony_ci */ 173bf215546Sopenharmony_ciVkResult vk_queue_enable_submit_thread(struct vk_queue *queue); 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ciVkResult vk_queue_flush(struct vk_queue *queue, uint32_t *submit_count_out); 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ciVkResult vk_queue_wait_before_present(struct vk_queue *queue, 178bf215546Sopenharmony_ci const VkPresentInfoKHR *pPresentInfo); 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ciVkResult PRINTFLIKE(4, 5) 181bf215546Sopenharmony_ci_vk_queue_set_lost(struct vk_queue *queue, 182bf215546Sopenharmony_ci const char *file, int line, 183bf215546Sopenharmony_ci const char *msg, ...); 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci#define vk_queue_set_lost(queue, ...) \ 186bf215546Sopenharmony_ci _vk_queue_set_lost(queue, __FILE__, __LINE__, __VA_ARGS__) 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_cistatic inline bool 189bf215546Sopenharmony_civk_queue_is_lost(struct vk_queue *queue) 190bf215546Sopenharmony_ci{ 191bf215546Sopenharmony_ci return queue->_lost.lost; 192bf215546Sopenharmony_ci} 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci#define vk_foreach_queue(queue, device) \ 195bf215546Sopenharmony_ci list_for_each_entry(struct vk_queue, queue, &(device)->queues, link) 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci#define vk_foreach_queue_safe(queue, device) \ 198bf215546Sopenharmony_ci list_for_each_entry_safe(struct vk_queue, queue, &(device)->queues, link) 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_cistruct vk_queue_submit { 201bf215546Sopenharmony_ci struct list_head link; 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci uint32_t wait_count; 204bf215546Sopenharmony_ci uint32_t command_buffer_count; 205bf215546Sopenharmony_ci uint32_t signal_count; 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci uint32_t buffer_bind_count; 208bf215546Sopenharmony_ci uint32_t image_opaque_bind_count; 209bf215546Sopenharmony_ci uint32_t image_bind_count; 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci struct vk_sync_wait *waits; 212bf215546Sopenharmony_ci struct vk_command_buffer **command_buffers; 213bf215546Sopenharmony_ci struct vk_sync_signal *signals; 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci VkSparseBufferMemoryBindInfo *buffer_binds; 216bf215546Sopenharmony_ci VkSparseImageOpaqueMemoryBindInfo *image_opaque_binds; 217bf215546Sopenharmony_ci VkSparseImageMemoryBindInfo *image_binds; 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci uint32_t perf_pass_index; 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci /* Used internally; should be ignored by drivers */ 222bf215546Sopenharmony_ci struct vk_sync **_wait_temps; 223bf215546Sopenharmony_ci struct vk_sync *_mem_signal_temp; 224bf215546Sopenharmony_ci struct vk_sync_timeline_point **_wait_points; 225bf215546Sopenharmony_ci struct vk_sync_timeline_point **_signal_points; 226bf215546Sopenharmony_ci}; 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci#ifdef __cplusplus 229bf215546Sopenharmony_ci} 230bf215546Sopenharmony_ci#endif 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci#endif /* VK_QUEUE_H */ 233