HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
gfx_device_vulkan_impl.hpp
1// Copyright Take Vos 2019-2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "gfx_device_vulkan.hpp"
8#include "gfx_system_vulkan.hpp"
9#include "gfx_surface_vulkan.hpp"
10#include "../file/file.hpp"
11#include "../utility/utility.hpp"
12#include "../macros.hpp"
13#include <span>
14
15
16namespace hi::inline v1 {
17
18inline gfx_device::gfx_device(vk::PhysicalDevice physicalDevice) :
19 physicalIntrinsic(std::move(physicalDevice))
20{
21 auto result = physicalIntrinsic.getProperties2KHR<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceIDProperties>(
22 vulkan_loader());
23
24 auto resultDeviceProperties2 = result.get<vk::PhysicalDeviceProperties2>();
25 auto resultDeviceIDProperties = result.get<vk::PhysicalDeviceIDProperties>();
26
27 requiredExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
28 requiredExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
29 requiredExtensions.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME);
30 // requiredExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
31 requiredExtensions.push_back(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME);
32 requiredExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
33
34 deviceID = resultDeviceProperties2.properties.deviceID;
35 vendorID = resultDeviceProperties2.properties.vendorID;
36 deviceName = std::string(resultDeviceProperties2.properties.deviceName.data());
37 deviceUUID = uuid::from_big_endian(resultDeviceIDProperties.deviceUUID);
38
39 physicalProperties = physicalIntrinsic.getProperties();
40
41 initialize_device();
42}
43
44inline int gfx_device::score(vk::SurfaceKHR surface) const
45{
46 hi_axiom(gfx_system_mutex.recurse_lock_count());
47
48 auto total_score = 0;
49
50 hi_log_info("Scoring device: {}", string());
51 if (not hasRequiredFeatures(physicalIntrinsic, gfx_system::global().requiredFeatures)) {
52 hi_log_info(" - Does not have the required features.");
53 return -1;
54 }
55
56 if (not meetsRequiredLimits(physicalIntrinsic, gfx_system::global().requiredLimits)) {
57 hi_log_info(" - Does not meet the required limits.");
58 return -1;
59 }
60
61 if (!hasRequiredExtensions(physicalIntrinsic, requiredExtensions)) {
62 hi_log_info(" - Does not have the required extensions.");
63 return -1;
64 }
65
66 bool device_has_graphics = false;
67 bool device_has_present = false;
68 bool device_has_compute = false;
69 bool device_shares_graphics_and_present = false;
70 for (hilet& queue : _queues) {
71 hilet has_present = to_bool(physicalIntrinsic.getSurfaceSupportKHR(queue.family_queue_index, surface));
72 hilet has_graphics = to_bool(queue.flags & vk::QueueFlagBits::eGraphics);
73 hilet has_compute = to_bool(queue.flags & vk::QueueFlagBits::eCompute);
74
75 device_has_graphics |= has_graphics;
76 device_has_present |= has_present;
77 device_has_compute |= has_compute;
78 if (has_present and has_graphics) {
79 device_shares_graphics_and_present = true;
80 }
81 }
82
83 if (not device_has_graphics) {
84 hi_log_info(" - Does not have a graphics queue.");
85 return -1;
86 }
87
88 if (not device_has_present) {
89 hi_log_info(" - Does not have a present queue.");
90 return -1;
91 }
92
93 if (device_has_compute) {
94 hi_log_info(" - Device has compute queue.");
95 total_score += 1;
96 }
97
98 if (device_shares_graphics_and_present) {
99 hi_log_info(" - Device shares graphics and present on same queue.");
100 total_score += 10;
101 }
102
103 hi_log_info(" - Surface formats:");
104 int surface_format_score = 0;
105 [[maybe_unused]] auto surface_format = get_surface_format(surface, &surface_format_score);
106 if (surface_format_score <= 0) {
107 hi_log_info(" - Does not have a suitable surface format.");
108 return -1;
109 }
110 total_score += surface_format_score;
111
112 hi_log_info(" - Present modes:");
113 int present_mode_score = 0;
114 [[maybe_unused]] auto present_mode = get_present_mode(surface, &present_mode_score);
115 if (present_mode_score <= 0) {
116 hi_log_info(" - Does not have a suitable present mode.");
117 return -1;
118 }
119 total_score += present_mode_score;
120
121 // Give score based on the performance of the device.
122 auto device_type_score = 0;
123 hilet properties = physicalIntrinsic.getProperties();
124 switch (properties.deviceType) {
125 case vk::PhysicalDeviceType::eCpu:
126 device_type_score = 1;
127 break;
128 case vk::PhysicalDeviceType::eOther:
129 device_type_score = 1;
130 break;
131 case vk::PhysicalDeviceType::eVirtualGpu:
132 device_type_score = 2;
133 break;
134 case vk::PhysicalDeviceType::eIntegratedGpu:
135 device_type_score = 3;
136 break;
137 case vk::PhysicalDeviceType::eDiscreteGpu:
138 device_type_score = 4;
139 break;
140 }
141 hi_log_info(" - device-type={}, score={}", vk::to_string(properties.deviceType), device_type_score);
142 total_score += device_type_score;
143
144 hi_log_info(" - total score {}", total_score);
145 return total_score;
146}
147
148inline void gfx_device::initialize_device()
149{
150 hilet device_queue_create_infos = make_device_queue_create_infos();
151
152 hilet available_device_features = physicalIntrinsic.getFeatures();
153
154 // Enable optional features.
155 device_features = gfx_system::global().requiredFeatures;
156 device_features.setDualSrcBlend(available_device_features.dualSrcBlend);
157 device_features.setShaderSampledImageArrayDynamicIndexing(VK_TRUE);
158 auto physical_device_features = vk::PhysicalDeviceFeatures2{device_features};
159
160 auto device_descriptor_indexing_features = vk::PhysicalDeviceDescriptorIndexingFeatures{};
161 device_descriptor_indexing_features.setPNext(&physical_device_features);
162 device_descriptor_indexing_features.setShaderSampledImageArrayNonUniformIndexing(VK_TRUE);
163
164 auto device_create_info = vk::DeviceCreateInfo{
165 vk::DeviceCreateFlags(),
166 narrow_cast<uint32_t>(device_queue_create_infos.size()),
167 device_queue_create_infos.data(),
168 0,
169 nullptr,
170 narrow_cast<uint32_t>(requiredExtensions.size()),
171 requiredExtensions.data(),
172 nullptr};
173 device_create_info.setPNext(&device_descriptor_indexing_features);
174
175 intrinsic = physicalIntrinsic.createDevice(device_create_info);
176
177 VmaAllocatorCreateInfo allocatorCreateInfo = {};
178 allocatorCreateInfo.physicalDevice = physicalIntrinsic;
179 allocatorCreateInfo.device = intrinsic;
180 allocatorCreateInfo.instance = vulkan_instance();
181 vmaCreateAllocator(&allocatorCreateInfo, &allocator);
182
183 VmaAllocationCreateInfo lazyAllocationInfo = {};
184 lazyAllocationInfo.flags = VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT;
185 lazyAllocationInfo.pUserData = const_cast<char *>("lazy transient image check");
186 lazyAllocationInfo.usage = VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED;
187 uint32_t typeIndexOut = 0;
188 supportsLazyTransientImages =
189 vmaFindMemoryTypeIndex(allocator, 0, &lazyAllocationInfo, &typeIndexOut) != VK_ERROR_FEATURE_NOT_PRESENT;
190
191 if (supportsLazyTransientImages) {
192 lazyMemoryUsage = VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED;
193 transientImageUsageFlags = vk::ImageUsageFlagBits::eTransientAttachment;
194 }
195
196 initialize_queues(device_queue_create_infos);
197 initialize_quad_index_buffer();
198
199 box_pipeline = std::make_unique<gfx_pipeline_box::device_shared>(*this);
200 image_pipeline = std::make_unique<gfx_pipeline_image::device_shared>(*this);
201 SDF_pipeline = std::make_unique<gfx_pipeline_SDF::device_shared>(*this);
202 alpha_pipeline = std::make_unique<gfx_pipeline_alpha::device_shared>(*this);
203 tone_mapper_pipeline = std::make_unique<gfx_pipeline_tone_mapper::device_shared>(*this);
204}
205
206inline void gfx_device::setDebugUtilsObjectNameEXT(vk::DebugUtilsObjectNameInfoEXT const& name_info) const
207{
208#ifndef NDEBUG
209 hi_axiom(gfx_system_mutex.recurse_lock_count());
210 return intrinsic.setDebugUtilsObjectNameEXT(name_info, vulkan_loader());
211#endif
212}
213
214inline void gfx_device::cmdBeginDebugUtilsLabelEXT(vk::CommandBuffer buffer, vk::DebugUtilsLabelEXT const& create_info) const
215{
216#ifndef NDEBUG
217 buffer.beginDebugUtilsLabelEXT(create_info, vulkan_loader());
218#endif
219}
220
221inline void gfx_device::cmdEndDebugUtilsLabelEXT(vk::CommandBuffer buffer) const
222{
223#ifndef NDEBUG
224 buffer.endDebugUtilsLabelEXT(vulkan_loader());
225#endif
226}
227
228} // namespace hi::inline v1
Defines the file class.
STL namespace.
DOXYGEN BUG.
Definition algorithm.hpp:16
unfair_recursive_mutex gfx_system_mutex
Global mutex for GUI elements, like gfx_system, gfx_device, Windows and Widgets.
Definition gfx_system_globals.hpp:18
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
T move(T... args)