-
-
Notifications
You must be signed in to change notification settings - Fork 584
/
Copy pathvulkan_impl_command_queue.cpp
171 lines (137 loc) · 5.57 KB
/
vulkan_impl_command_queue.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
* Copyright (C) 2021 Patrick Mours
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "vulkan_impl_device.hpp"
#include "vulkan_impl_command_queue.hpp"
#include "dll_log.hpp"
#include <algorithm> // std::find
#define vk _device_impl->_dispatch_table
reshade::vulkan::command_queue_impl::command_queue_impl(device_impl *device, uint32_t queue_family_index, const VkQueueFamilyProperties &queue_family, VkQueue queue) :
api_object_impl(queue),
_device_impl(device),
_queue_family_props(queue_family)
{
// Register queue to device (no need to lock, since all command queues are created single threaded in 'vkCreateDevice')
_device_impl->_queues.push_back(this);
// Only create an immediate command list for graphics queues (since the implemented commands do not work on other queue types)
if ((queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
{
_immediate_cmd_list = new command_list_immediate_impl(device, queue_family_index, queue);
// Ensure the immediate command list was initialized successfully, otherwise disable it
if (_immediate_cmd_list->_orig == VK_NULL_HANDLE)
{
log::message(log::level::error, "Failed to create immediate command list for queue %p!", _orig);
delete _immediate_cmd_list;
_immediate_cmd_list = nullptr;
}
}
}
reshade::vulkan::command_queue_impl::~command_queue_impl()
{
delete _immediate_cmd_list;
// Unregister queue from device
_device_impl->_queues.erase(std::find(_device_impl->_queues.begin(), _device_impl->_queues.end(), this));
}
reshade::api::device *reshade::vulkan::command_queue_impl::get_device()
{
return _device_impl;
}
reshade::api::command_queue_type reshade::vulkan::command_queue_impl::get_type() const
{
static_assert(
api::command_queue_type::graphics == VK_QUEUE_GRAPHICS_BIT &&
api::command_queue_type::compute == VK_QUEUE_COMPUTE_BIT &&
api::command_queue_type::copy == VK_QUEUE_TRANSFER_BIT);
return static_cast<api::command_queue_type>(_queue_family_props.queueFlags);
}
void reshade::vulkan::command_queue_impl::wait_idle() const
{
flush_immediate_command_list();
vk.QueueWaitIdle(_orig);
}
void reshade::vulkan::command_queue_impl::flush_immediate_command_list() const
{
VkSubmitInfo submit_info { VK_STRUCTURE_TYPE_SUBMIT_INFO };
if (_immediate_cmd_list != nullptr)
_immediate_cmd_list->flush(submit_info);
}
void reshade::vulkan::command_queue_impl::flush_immediate_command_list(VkSubmitInfo &semaphore_info) const
{
if (_immediate_cmd_list != nullptr)
_immediate_cmd_list->flush(semaphore_info);
}
void reshade::vulkan::command_queue_impl::begin_debug_event(const char *label, const float color[4])
{
assert(label != nullptr);
if (vk.QueueBeginDebugUtilsLabelEXT == nullptr)
return;
VkDebugUtilsLabelEXT label_info { VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT };
label_info.pLabelName = label;
// The optional color value is ignored if all elements are set to zero
if (color != nullptr)
{
label_info.color[0] = color[0];
label_info.color[1] = color[1];
label_info.color[2] = color[2];
label_info.color[3] = color[3];
}
vk.QueueBeginDebugUtilsLabelEXT(_orig, &label_info);
}
void reshade::vulkan::command_queue_impl::end_debug_event()
{
if (vk.QueueEndDebugUtilsLabelEXT == nullptr)
return;
vk.QueueEndDebugUtilsLabelEXT(_orig);
}
void reshade::vulkan::command_queue_impl::insert_debug_marker(const char *label, const float color[4])
{
assert(label != nullptr);
if (vk.QueueInsertDebugUtilsLabelEXT == nullptr)
return;
VkDebugUtilsLabelEXT label_info { VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT };
label_info.pLabelName = label;
if (color != nullptr)
{
label_info.color[0] = color[0];
label_info.color[1] = color[1];
label_info.color[2] = color[2];
label_info.color[3] = color[3];
}
vk.QueueInsertDebugUtilsLabelEXT(_orig, &label_info);
}
bool reshade::vulkan::command_queue_impl::wait(api::fence fence, uint64_t value)
{
const VkSemaphore wait_semaphore = (VkSemaphore)fence.handle;
const VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
VkTimelineSemaphoreSubmitInfo wait_semaphore_info { VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO };
wait_semaphore_info.waitSemaphoreValueCount = 1;
wait_semaphore_info.pWaitSemaphoreValues = &value;
VkSubmitInfo submit_info { VK_STRUCTURE_TYPE_SUBMIT_INFO, &wait_semaphore_info };
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &wait_semaphore;
submit_info.pWaitDstStageMask = &wait_stage;
return vk.QueueSubmit(_orig, 1, &submit_info, VK_NULL_HANDLE) == VK_SUCCESS;
}
bool reshade::vulkan::command_queue_impl::signal(api::fence fence, uint64_t value)
{
const VkSemaphore signal_semaphore = (VkSemaphore)fence.handle;
VkTimelineSemaphoreSubmitInfo signal_semaphore_info { VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO };
signal_semaphore_info.signalSemaphoreValueCount = 1;
signal_semaphore_info.pSignalSemaphoreValues = &value;
VkSubmitInfo submit_info { VK_STRUCTURE_TYPE_SUBMIT_INFO, &signal_semaphore_info };
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &signal_semaphore;
flush_immediate_command_list(submit_info);
if (submit_info.signalSemaphoreCount == 0)
return true; // Already submitted by the flush
return vk.QueueSubmit(_orig, 1, &submit_info, VK_NULL_HANDLE) == VK_SUCCESS;
}
uint64_t reshade::vulkan::command_queue_impl::get_timestamp_frequency() const
{
if (_queue_family_props.timestampValidBits == 0)
return 0;
VkPhysicalDeviceProperties device_props = {};
_device_impl->_instance_dispatch_table.GetPhysicalDeviceProperties(_device_impl->_physical_device, &device_props);
return static_cast<uint64_t>(1000000000ull / device_props.limits.timestampPeriod);
}