1 /* Copyright (c) 2017-2020 Hans-Kristian Arntzen 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining 4 * a copy of this software and associated documentation files (the 5 * "Software"), to deal in the Software without restriction, including 6 * without limitation the rights to use, copy, modify, merge, publish, 7 * distribute, sublicense, and/or sell copies of the Software, and to 8 * permit persons to whom the Software is furnished to do so, subject to 9 * the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be 12 * included in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23 #pragma once 24 25 #include "vulkan_headers.hpp" 26 #include "logging.hpp" 27 #include <memory> 28 #include <functional> 29 30 namespace Vulkan 31 { 32 struct DeviceFeatures 33 { 34 bool supports_physical_device_properties2 = false; 35 bool supports_external = false; 36 bool supports_dedicated = false; 37 bool supports_image_format_list = false; 38 bool supports_debug_marker = false; 39 bool supports_debug_utils = false; 40 bool supports_mirror_clamp_to_edge = false; 41 bool supports_google_display_timing = false; 42 bool supports_nv_device_diagnostic_checkpoints = false; 43 bool supports_vulkan_11_instance = false; 44 bool supports_vulkan_11_device = false; 45 bool supports_external_memory_host = false; 46 bool supports_surface_capabilities2 = false; 47 bool supports_full_screen_exclusive = false; 48 bool supports_update_template = false; 49 bool supports_maintenance_1 = false; 50 bool supports_maintenance_2 = false; 51 bool supports_maintenance_3 = false; 52 bool supports_descriptor_indexing = false; 53 bool supports_conservative_rasterization = false; 54 bool supports_bind_memory2 = false; 55 bool supports_get_memory_requirements2 = false; 56 bool supports_draw_indirect_count = false; 57 bool supports_draw_parameters = false; 58 bool supports_driver_properties = false; 59 bool supports_calibrated_timestamps = false; 60 VkPhysicalDeviceSubgroupProperties subgroup_properties = {}; 61 VkPhysicalDevice8BitStorageFeaturesKHR storage_8bit_features = {}; 62 VkPhysicalDevice16BitStorageFeaturesKHR storage_16bit_features = {}; 63 VkPhysicalDeviceFloat16Int8FeaturesKHR float16_int8_features = {}; 64 VkPhysicalDeviceFeatures enabled_features = {}; 65 VkPhysicalDeviceExternalMemoryHostPropertiesEXT host_memory_properties = {}; 66 VkPhysicalDeviceMultiviewFeaturesKHR multiview_features = {}; 67 VkPhysicalDeviceImagelessFramebufferFeaturesKHR imageless_features = {}; 68 VkPhysicalDeviceSubgroupSizeControlFeaturesEXT subgroup_size_control_features = {}; 69 VkPhysicalDeviceSubgroupSizeControlPropertiesEXT subgroup_size_control_properties = {}; 70 VkPhysicalDeviceComputeShaderDerivativesFeaturesNV compute_shader_derivative_features = {}; 71 VkPhysicalDeviceHostQueryResetFeaturesEXT host_query_reset_features = {}; 72 VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT demote_to_helper_invocation_features = {}; 73 VkPhysicalDeviceScalarBlockLayoutFeaturesEXT scalar_block_features = {}; 74 VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR ubo_std430_features = {}; 75 VkPhysicalDeviceTimelineSemaphoreFeaturesKHR timeline_semaphore_features = {}; 76 VkPhysicalDeviceDescriptorIndexingFeaturesEXT descriptor_indexing_features = {}; 77 VkPhysicalDeviceDescriptorIndexingPropertiesEXT descriptor_indexing_properties = {}; 78 VkPhysicalDeviceConservativeRasterizationPropertiesEXT conservative_rasterization_properties = {}; 79 VkPhysicalDevicePerformanceQueryFeaturesKHR performance_query_features = {}; 80 VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR sampler_ycbcr_conversion_features = {}; 81 VkPhysicalDeviceDriverPropertiesKHR driver_properties = {}; 82 }; 83 84 enum VendorID 85 { 86 VENDOR_ID_AMD = 0x1002, 87 VENDOR_ID_NVIDIA = 0x10de, 88 VENDOR_ID_INTEL = 0x8086, 89 VENDOR_ID_ARM = 0x13b5, 90 VENDOR_ID_QCOM = 0x5143 91 }; 92 93 enum ContextCreationFlagBits 94 { 95 CONTEXT_CREATION_DISABLE_BINDLESS_BIT = 1 << 0 96 }; 97 using ContextCreationFlags = uint32_t; 98 99 class Context 100 { 101 public: 102 bool init_instance_and_device(const char **instance_ext, uint32_t instance_ext_count, const char **device_ext, uint32_t device_ext_count, 103 ContextCreationFlags flags = 0); 104 bool init_from_instance_and_device(VkInstance instance, VkPhysicalDevice gpu, VkDevice device, VkQueue queue, uint32_t queue_family); 105 bool init_device_from_instance(VkInstance instance, VkPhysicalDevice gpu, VkSurfaceKHR surface, const char **required_device_extensions, 106 unsigned num_required_device_extensions, const char **required_device_layers, 107 unsigned num_required_device_layers, const VkPhysicalDeviceFeatures *required_features, 108 ContextCreationFlags flags = 0); 109 110 Context() = default; 111 Context(const Context &) = delete; 112 void operator=(const Context &) = delete; 113 static bool init_loader(PFN_vkGetInstanceProcAddr addr); 114 115 ~Context(); 116 get_instance() const117 VkInstance get_instance() const 118 { 119 return instance; 120 } 121 get_gpu() const122 VkPhysicalDevice get_gpu() const 123 { 124 return gpu; 125 } 126 get_device() const127 VkDevice get_device() const 128 { 129 return device; 130 } 131 get_graphics_queue() const132 VkQueue get_graphics_queue() const 133 { 134 return graphics_queue; 135 } 136 get_compute_queue() const137 VkQueue get_compute_queue() const 138 { 139 return compute_queue; 140 } 141 get_transfer_queue() const142 VkQueue get_transfer_queue() const 143 { 144 return transfer_queue; 145 } 146 get_gpu_props() const147 const VkPhysicalDeviceProperties &get_gpu_props() const 148 { 149 return gpu_props; 150 } 151 get_mem_props() const152 const VkPhysicalDeviceMemoryProperties &get_mem_props() const 153 { 154 return mem_props; 155 } 156 get_graphics_queue_family() const157 uint32_t get_graphics_queue_family() const 158 { 159 return graphics_queue_family; 160 } 161 get_compute_queue_family() const162 uint32_t get_compute_queue_family() const 163 { 164 return compute_queue_family; 165 } 166 get_transfer_queue_family() const167 uint32_t get_transfer_queue_family() const 168 { 169 return transfer_queue_family; 170 } 171 get_timestamp_valid_bits() const172 uint32_t get_timestamp_valid_bits() const 173 { 174 return timestamp_valid_bits; 175 } 176 release_instance()177 void release_instance() 178 { 179 owned_instance = false; 180 } 181 release_device()182 void release_device() 183 { 184 owned_device = false; 185 } 186 get_enabled_device_features() const187 const DeviceFeatures &get_enabled_device_features() const 188 { 189 return ext; 190 } 191 192 static const VkApplicationInfo &get_application_info(bool supports_vulkan_11); 193 194 void notify_validation_error(const char *msg); 195 void set_notification_callback(std::function<void (const char *)> func); 196 set_num_thread_indices(unsigned indices)197 void set_num_thread_indices(unsigned indices) 198 { 199 num_thread_indices = indices; 200 } 201 get_num_thread_indices() const202 unsigned get_num_thread_indices() const 203 { 204 return num_thread_indices; 205 } 206 get_device_table() const207 const VolkDeviceTable &get_device_table() const 208 { 209 return device_table; 210 } 211 212 private: 213 VkDevice device = VK_NULL_HANDLE; 214 VkInstance instance = VK_NULL_HANDLE; 215 VkPhysicalDevice gpu = VK_NULL_HANDLE; 216 VolkDeviceTable device_table = {}; 217 218 VkPhysicalDeviceProperties gpu_props = {}; 219 VkPhysicalDeviceMemoryProperties mem_props = {}; 220 221 VkQueue graphics_queue = VK_NULL_HANDLE; 222 VkQueue compute_queue = VK_NULL_HANDLE; 223 VkQueue transfer_queue = VK_NULL_HANDLE; 224 uint32_t graphics_queue_family = VK_QUEUE_FAMILY_IGNORED; 225 uint32_t compute_queue_family = VK_QUEUE_FAMILY_IGNORED; 226 uint32_t transfer_queue_family = VK_QUEUE_FAMILY_IGNORED; 227 uint32_t timestamp_valid_bits = 0; 228 unsigned num_thread_indices = 1; 229 230 bool create_instance(const char **instance_ext, uint32_t instance_ext_count); 231 bool create_device(VkPhysicalDevice gpu, VkSurfaceKHR surface, const char **required_device_extensions, 232 unsigned num_required_device_extensions, const char **required_device_layers, 233 unsigned num_required_device_layers, const VkPhysicalDeviceFeatures *required_features, 234 ContextCreationFlags flags); 235 236 bool owned_instance = false; 237 bool owned_device = false; 238 DeviceFeatures ext; 239 240 #ifdef VULKAN_DEBUG 241 VkDebugReportCallbackEXT debug_callback = VK_NULL_HANDLE; 242 VkDebugUtilsMessengerEXT debug_messenger = VK_NULL_HANDLE; 243 #endif 244 std::function<void (const char *)> message_callback; 245 246 void destroy(); 247 void check_descriptor_indexing_features(); 248 bool force_no_validation = false; 249 }; 250 } 251