Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
vkDevice.cpp
Go to the documentation of this file.
1
2
3#include "Headers/vkDevice.h"
4
6
7namespace Divide
8{
9 VKDevice::VKDevice( vkb::Instance& instance, VkSurfaceKHR targetSurface )
10 {
11 VkPhysicalDeviceExtendedDynamicState3FeaturesEXT vk13EXTfeatures{};
12 vk13EXTfeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT;
13 vk13EXTfeatures.extendedDynamicState3ColorBlendEnable = true;
14 vk13EXTfeatures.extendedDynamicState3ColorBlendEquation = true;
15 vk13EXTfeatures.extendedDynamicState3ColorWriteMask = true;
16
17 VkPhysicalDeviceVulkan13Features vk13features{};
18 vk13features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
19 vk13features.pNext = &vk13EXTfeatures;
20
21 vk13features.synchronization2 = true;
22 vk13features.dynamicRendering = true;
23 vk13features.maintenance4 = true;
24 VkPhysicalDeviceVulkan12Features vk12features{};
25 vk12features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
26 vk12features.samplerMirrorClampToEdge = true;
27 vk12features.timelineSemaphore = true;
28 vk12features.descriptorBindingPartiallyBound = true;
29 vk12features.descriptorBindingUniformBufferUpdateAfterBind = true;
30 vk12features.descriptorBindingSampledImageUpdateAfterBind = true;
31 vk12features.descriptorBindingStorageImageUpdateAfterBind = true;
32 vk12features.descriptorBindingStorageBufferUpdateAfterBind = true;
33 vk12features.descriptorBindingUpdateUnusedWhilePending = true;
34 vk12features.shaderSampledImageArrayNonUniformIndexing = true;
35 vk12features.runtimeDescriptorArray = true;
36 vk12features.descriptorBindingVariableDescriptorCount = true;
37 VkPhysicalDeviceVulkan11Features vk11features{};
38 vk11features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
39 vk11features.shaderDrawParameters = true;
40 VkPhysicalDeviceFeatures vk10features{};
41 vk10features.independentBlend = true;
42 vk10features.imageCubeArray = true;
43 vk10features.geometryShader = true;
44 vk10features.tessellationShader = true;
45 vk10features.multiDrawIndirect = true;
46 vk10features.drawIndirectFirstInstance = true; //???
47 vk10features.depthClamp = true;
48 vk10features.depthBiasClamp = true;
49 vk10features.fillModeNonSolid = true;
50 vk10features.depthBounds = true;
51 vk10features.samplerAnisotropy = true;
52 vk10features.sampleRateShading = true;
53 //vk10features.textureCompressionETC2 = true;
54 vk10features.textureCompressionBC = true;
55 vk10features.shaderClipDistance = true;
56 vk10features.shaderCullDistance = true;
57
58 vkb::PhysicalDeviceSelector selector{ instance };
59 auto physicalDeviceSelection = selector.set_minimum_version( 1, Config::MINIMUM_VULKAN_MINOR_VERSION )
60 //.set_desired_version(1, Config::DESIRED_VULKAN_MINOR_VERSION)
61 .set_surface( targetSurface )
62 .prefer_gpu_device_type( vkb::PreferredDeviceType::discrete )
63 .add_required_extension( VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME )
64 .set_required_features( vk10features )
65 .set_required_features_11( vk11features )
66 .set_required_features_12( vk12features )
67 .set_required_features_13( vk13features )
68 .select();
69
70 if ( !physicalDeviceSelection )
71 {
72 Console::errorfn( LOCALE_STR( "ERROR_VK_INIT" ), physicalDeviceSelection.error().message().c_str() );
73 }
74 else
75 {
76 _physicalDevice = physicalDeviceSelection.value();
77 _physicalDevice.enable_extensions_if_present(
78 {
79 VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME,
80 VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME,
81 VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME
82 }
83 );
84
85 //create the final Vulkan device
86 vkb::DeviceBuilder deviceBuilder{ _physicalDevice };
87 auto vkbDevice = deviceBuilder.build();
88 if ( !vkbDevice )
89 {
90 Console::errorfn( LOCALE_STR( "ERROR_VK_INIT" ), vkbDevice.error().message().c_str() );
91 return;
92 }
93
94 for ( const auto& extension : _physicalDevice.get_extensions() )
95 {
96 if ( extension == VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME )
97 {
98 supportsDynamicExtension3(true);
99 }
100 else if ( extension == VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME )
101 {
102 supportsPushDescriptors(true);
103 }
104 else if ( extension == VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME )
105 {
106 supportsDescriptorBuffers(true);
107 }
108 }
109
110 // Get the VkDevice handle used in the rest of a Vulkan application
111 _device = vkbDevice.value();
112
113 const auto presentIndex = _device.get_queue_index(vkb::QueueType::present);
114 if (presentIndex )
115 {
116 _presentQueueIndex = presentIndex.value();
117
118 for ( U8 t = 0u; t < to_base( QueueType::COUNT ); ++t )
119 {
120 _queues[t] = getQueueInternal( static_cast<QueueType>(t), true);
121 }
122 }
123 else
124 {
125 Console::errorfn( LOCALE_STR( "ERROR_VK_INIT" ), presentIndex.error().message().c_str() );
126 }
127
128 }
129 }
130
132 {
133 for ( VKQueue& queue : _queues )
134 {
135 if ( queue._pool != VK_NULL_HANDLE )
136 {
137 vkDestroyCommandPool( getVKDevice(), queue._pool, nullptr );
138 }
139 }
140
141 if ( _device.device != VK_NULL_HANDLE )
142 {
143 vkb::destroy_device( _device );
144 }
145 }
146
148 {
149 return _presentQueueIndex;
150 }
151
152 VKQueue VKDevice::getQueue( QueueType type ) const noexcept
153 {
154 return _queues[to_base(type)];
155 }
156
157 VKQueue VKDevice::getQueueInternal( const QueueType type, bool dedicated ) const noexcept
158 {
160
161 constexpr const char* QueueName[] = { "Graphics", "Compute", "Transfer" };
162 constexpr vkb::QueueType VKBQueueType[] = {vkb::QueueType::graphics, vkb::QueueType::compute, vkb::QueueType::transfer};
163
164 VKQueue ret{};
165
166 if ( getDevice() == nullptr )
167 {
168 Console::errorfn( LOCALE_STR( "ERROR_VK_INIT" ), "VKDevice::getQueueInternal error: no valid device found!");
169 return ret;
170 }
171
172 if ( type != QueueType::COMPUTE && type != QueueType::TRANSFER )
173 {
174 dedicated = false;
175 }
176
177 const vkb::QueueType vkbType = VKBQueueType[to_base(type)];
178
179 // Dumb way of doing this, but VkBootstrap's Result& operator=(Result&& result) is missing a return statement and causes a compilation error
180 const auto index = dedicated ? _device.get_dedicated_queue_index( vkbType ) : _device.get_queue_index( vkbType );
181 if ( !index )
182 {
183 if ( dedicated )
184 {
185 Console::warnfn( LOCALE_STR( "WARN_VK_DEDICATED_QUEUE" ), QueueName[to_base(type)], index.error().message().c_str() );
186 }
187 else
188 {
189 Console::errorfn( LOCALE_STR( "ERROR_VK_DEDICATED_QUEUE" ), QueueName[to_base( type )], index.error().message().c_str() );
190 }
191
192 return dedicated ? getQueueInternal(type, false) : ret;
193 }
194
195 ret._index = index.value();
196 ret._type = type;
197 ret._pool = createCommandPool( ret._index, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT );
198 vkGetDeviceQueue( _device.device, ret._index, 0u, &ret._queue );
199
200 return ret;
201 }
202
203 VkDevice VKDevice::getVKDevice() const noexcept
204 {
205 return _device.device;
206 }
207
208 VkPhysicalDevice VKDevice::getVKPhysicalDevice() const noexcept
209 {
210 return _physicalDevice.physical_device;
211 }
212
213 const vkb::Device& VKDevice::getDevice() const noexcept
214 {
215 return _device;
216 }
217
218 const vkb::PhysicalDevice& VKDevice::getPhysicalDevice() const noexcept
219 {
220 return _physicalDevice;
221 }
222
223 VkCommandPool VKDevice::createCommandPool( const uint32_t queueFamilyIndex, const VkCommandPoolCreateFlags createFlags ) const
224 {
226
227 VkCommandPoolCreateInfo cmdPoolInfo = vk::commandPoolCreateInfo();
228 cmdPoolInfo.queueFamilyIndex = queueFamilyIndex;
229 cmdPoolInfo.flags = createFlags;
230 VkCommandPool cmdPool;
231 VK_CHECK( vkCreateCommandPool( getVKDevice(), &cmdPoolInfo, nullptr, &cmdPool ) );
232 return cmdPool;
233 }
234
235 void VKDevice::submitToQueue( const QueueType queue, const VkSubmitInfo& submitInfo, VkFence& fence ) const
236 {
238
239 // Submit command buffer to the queue and execute it.
240 // "fence" will now block until the graphic commands finish execution
241 LockGuard<Mutex> w_lock( _queueLocks[to_base( queue )] );
242 VK_CHECK( vkQueueSubmit( _queues[to_base( queue )]._queue, 1, &submitInfo, fence ) );
243 }
244
245 VkResult VKDevice::queuePresent( const QueueType queue, const VkPresentInfoKHR& presentInfo ) const
246 {
248
249 LockGuard<Mutex> w_lock( _queueLocks[to_base( queue )] );
250 return vkQueuePresentKHR( _queues[to_base( queue )]._queue, &presentInfo );
251 }
252
253}; //namespace Divide
#define LOCALE_STR(X)
Definition: Localization.h:91
#define PROFILE_SCOPE_AUTO(CATEGORY)
Definition: Profiler.h:87
U32 _presentQueueIndex
Definition: vkDevice.h:69
const vkb::PhysicalDevice & getPhysicalDevice() const noexcept
Definition: vkDevice.cpp:218
VkCommandPool createCommandPool(uint32_t queueFamilyIndex, VkCommandPoolCreateFlags createFlags=VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT) const
Definition: vkDevice.cpp:223
std::array< Mutex, to_base(QueueType::COUNT)> _queueLocks
Definition: vkDevice.h:72
U32 getPresentQueueIndex() const noexcept
Definition: vkDevice.cpp:147
std::array< VKQueue, to_base(QueueType::COUNT) > _queues
Definition: vkDevice.h:71
void submitToQueue(QueueType queue, const VkSubmitInfo &submitInfo, VkFence &fence) const
Definition: vkDevice.cpp:235
VkPhysicalDevice getVKPhysicalDevice() const noexcept
Definition: vkDevice.cpp:208
VKDevice(vkb::Instance &instance, VkSurfaceKHR targetSurface)
Definition: vkDevice.cpp:9
VKQueue getQueue(QueueType type) const noexcept
Definition: vkDevice.cpp:152
const vkb::Device & getDevice() const noexcept
Definition: vkDevice.cpp:213
VKQueue getQueueInternal(QueueType type, bool dedicated) const noexcept
Definition: vkDevice.cpp:157
vkb::PhysicalDevice _physicalDevice
Definition: vkDevice.h:68
vkb::Device _device
Definition: vkDevice.h:67
VkResult queuePresent(QueueType queue, const VkPresentInfoKHR &presentInfo) const
Definition: vkDevice.cpp:245
VkDevice getVKDevice() const noexcept
Definition: vkDevice.cpp:203
constexpr unsigned char MINIMUM_VULKAN_MINOR_VERSION
Definition: config.h:93
constexpr Optick::Category::Type Graphics
Definition: Profiler.h:60
VkCommandPoolCreateInfo commandPoolCreateInfo()
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
std::lock_guard< mutex > LockGuard
Definition: SharedMutex.h:55
uint8_t U8
uint32_t U32
constexpr auto to_base(const Type value) -> Type
static NO_INLINE void errorfn(const char *format, T &&... args)
static NO_INLINE void warnfn(const char *format, T &&... args)
#define VK_CHECK(x)
Definition: vkResources.h:327