diff options
Diffstat (limited to 'drivers/vulkan')
| -rw-r--r-- | drivers/vulkan/rendering_device_vulkan.cpp | 98 | ||||
| -rw-r--r-- | drivers/vulkan/rendering_device_vulkan.h | 9 | ||||
| -rw-r--r-- | drivers/vulkan/vulkan_context.cpp | 350 | ||||
| -rw-r--r-- | drivers/vulkan/vulkan_context.h | 23 |
4 files changed, 280 insertions, 200 deletions
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 4cae051302..ba623eb298 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -387,14 +387,6 @@ const VkFormat RenderingDeviceVulkan::vulkan_formats[RenderingDevice::DATA_FORMA VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, - VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, - VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, - VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG, - VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG, - VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG, - VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG, - VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG, - VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG, }; const char *RenderingDeviceVulkan::named_formats[RenderingDevice::DATA_FORMAT_MAX] = { @@ -616,14 +608,6 @@ const char *RenderingDeviceVulkan::named_formats[RenderingDevice::DATA_FORMAT_MA "G16_B16_R16_3Plane_422_Unorm", "G16_B16R16_2Plane_422_Unorm", "G16_B16_R16_3Plane_444_Unorm", - "Pvrtc1_2Bpp_Unorm_Block_Img", - "Pvrtc1_4Bpp_Unorm_Block_Img", - "Pvrtc2_2Bpp_Unorm_Block_Img", - "Pvrtc2_4Bpp_Unorm_Block_Img", - "Pvrtc1_2Bpp_Srgb_Block_Img", - "Pvrtc1_4Bpp_Srgb_Block_Img", - "Pvrtc2_2Bpp_Srgb_Block_Img", - "Pvrtc2_4Bpp_Srgb_Block_Img" }; int RenderingDeviceVulkan::get_format_vertex_size(DataFormat p_format) { @@ -970,15 +954,6 @@ uint32_t RenderingDeviceVulkan::get_image_format_pixel_size(DataFormat p_format) case DATA_FORMAT_G16_B16R16_2PLANE_422_UNORM: case DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM: return 8; - case DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG: - case DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG: - case DATA_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG: - case DATA_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG: - case DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG: - case DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG: - case DATA_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG: - case DATA_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG: - return 1; default: { ERR_PRINT("Format not handled, bug"); } @@ -1048,20 +1023,6 @@ void RenderingDeviceVulkan::get_compressed_image_format_block_dimensions(DataFor r_w = 4; r_h = 4; return; - case DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG: - case DATA_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG: - case DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG: - case DATA_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG: - r_w = 4; - r_h = 4; - return; - case DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG: - case DATA_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG: - case DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG: - case DATA_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG: - r_w = 8; - r_h = 4; - return; default: { r_w = 1; r_h = 1; @@ -1138,15 +1099,6 @@ uint32_t RenderingDeviceVulkan::get_compressed_image_format_block_byte_size(Data case DATA_FORMAT_ASTC_12x12_UNORM_BLOCK: case DATA_FORMAT_ASTC_12x12_SRGB_BLOCK: return 8; //wrong - case DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG: - case DATA_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG: - case DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG: - case DATA_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG: - case DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG: - case DATA_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG: - case DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG: - case DATA_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG: - return 8; //what varies is resolution default: { } } @@ -1167,16 +1119,7 @@ uint32_t RenderingDeviceVulkan::get_compressed_image_format_pixel_rshift(DataFor case DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: case DATA_FORMAT_EAC_R11_UNORM_BLOCK: case DATA_FORMAT_EAC_R11_SNORM_BLOCK: - case DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG: - case DATA_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG: - case DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG: - case DATA_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG: return 1; - case DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG: //these formats are quarter byte size, so rshift is 1 - case DATA_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG: - case DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG: - case DATA_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG: - return 2; default: { } } @@ -2170,7 +2113,7 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID return id; } -RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type) { +RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps, TextureSliceType p_slice_type) { _THREAD_SAFE_METHOD_ Texture *src_texture = texture_owner.get_or_null(p_with_texture); @@ -2194,6 +2137,7 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p //create view ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, src_texture->mipmaps, RID()); + ERR_FAIL_COND_V(p_mipmap + p_mipmaps > src_texture->mipmaps, RID()); ERR_FAIL_UNSIGNED_INDEX_V(p_layer, src_texture->layers, RID()); int slice_layers = 1; @@ -2206,7 +2150,7 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p Texture texture = *src_texture; get_image_format_required_size(texture.format, texture.width, texture.height, texture.depth, p_mipmap + 1, &texture.width, &texture.height); - texture.mipmaps = 1; + texture.mipmaps = p_mipmaps; texture.layers = slice_layers; texture.base_mipmap = p_mipmap; texture.base_layer = p_layer; @@ -2269,7 +2213,7 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p "Specified layer must be a multiple of 6."); } image_view_create_info.subresourceRange.baseMipLevel = p_mipmap; - image_view_create_info.subresourceRange.levelCount = 1; + image_view_create_info.subresourceRange.levelCount = p_mipmaps; image_view_create_info.subresourceRange.layerCount = slice_layers; image_view_create_info.subresourceRange.baseArrayLayer = p_layer; @@ -2520,7 +2464,7 @@ Error RenderingDeviceVulkan::_texture_update(RID p_texture, uint32_t p_layer, co image_memory_barrier.subresourceRange.baseArrayLayer = p_layer; image_memory_barrier.subresourceRange.layerCount = 1; - vkCmdPipelineBarrier(command_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, barrier_flags, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier); + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, barrier_flags, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier); } if (texture->used_in_frame != frames_drawn) { @@ -4249,7 +4193,7 @@ String RenderingDeviceVulkan::_shader_uniform_debug(RID p_shader, int p_set) { } for (int j = 0; j < shader->sets[i].uniform_info.size(); j++) { const UniformInfo &ui = shader->sets[i].uniform_info[j]; - if (ret != String()) { + if (!ret.is_empty()) { ret += "\n"; } ret += "Set: " + itos(i) + " Binding: " + itos(ui.binding) + " Type: " + shader_uniform_names[ui.type] + " Length: " + itos(ui.length); @@ -7574,6 +7518,9 @@ Error RenderingDeviceVulkan::draw_list_switch_to_next_pass_split(uint32_t p_spli } Error RenderingDeviceVulkan::_draw_list_allocate(const Rect2i &p_viewport, uint32_t p_splits, uint32_t p_subpass) { + // Lock while draw_list is active + _THREAD_SAFE_LOCK_ + if (p_splits == 0) { draw_list = memnew(DrawList); draw_list->command_buffer = frames[frame].draw_command_buffer; @@ -7684,6 +7631,9 @@ void RenderingDeviceVulkan::_draw_list_free(Rect2i *r_last_viewport) { memdelete(draw_list); draw_list = nullptr; } + + // draw_list is no longer active + _THREAD_SAFE_UNLOCK_ } void RenderingDeviceVulkan::draw_list_end(uint32_t p_post_barrier) { @@ -7797,6 +7747,9 @@ RenderingDevice::ComputeListID RenderingDeviceVulkan::compute_list_begin(bool p_ ERR_FAIL_COND_V_MSG(!p_allow_draw_overlap && draw_list != nullptr, INVALID_ID, "Only one draw list can be active at the same time."); ERR_FAIL_COND_V_MSG(compute_list != nullptr, INVALID_ID, "Only one draw/compute list can be active at the same time."); + // Lock while compute_list is active + _THREAD_SAFE_LOCK_ + compute_list = memnew(ComputeList); compute_list->command_buffer = frames[frame].draw_command_buffer; compute_list->state.allow_draw_overlap = p_allow_draw_overlap; @@ -8270,6 +8223,9 @@ void RenderingDeviceVulkan::compute_list_end(uint32_t p_post_barrier) { memdelete(compute_list); compute_list = nullptr; + + // compute_list is no longer active + _THREAD_SAFE_UNLOCK_ } void RenderingDeviceVulkan::barrier(uint32_t p_from, uint32_t p_to) { @@ -8428,11 +8384,11 @@ void RenderingDeviceVulkan::_free_internal(RID p_id) { } else if (uniform_set_owner.owns(p_id)) { UniformSet *uniform_set = uniform_set_owner.get_or_null(p_id); frames[frame].uniform_sets_to_dispose_of.push_back(*uniform_set); + uniform_set_owner.free(p_id); + if (uniform_set->invalidated_callback != nullptr) { - uniform_set->invalidated_callback(p_id, uniform_set->invalidated_callback_userdata); + uniform_set->invalidated_callback(uniform_set->invalidated_callback_userdata); } - - uniform_set_owner.free(p_id); } else if (render_pipeline_owner.owns(p_id)) { RenderPipeline *pipeline = render_pipeline_owner.get_or_null(p_id); frames[frame].render_pipelines_to_dispose_of.push_back(*pipeline); @@ -8525,6 +8481,11 @@ String RenderingDeviceVulkan::get_device_vendor_name() const { String RenderingDeviceVulkan::get_device_name() const { return context->get_device_name(); } + +RenderingDevice::DeviceType RenderingDeviceVulkan::get_device_type() const { + return context->get_device_type(); +} + String RenderingDeviceVulkan::get_device_pipeline_cache_uuid() const { return context->get_device_pipeline_cache_uuid(); } @@ -8822,6 +8783,7 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de // get info about further features VulkanContext::MultiviewCapabilities multiview_capabilies = p_context->get_multiview_capabilities(); device_capabilities.supports_multiview = multiview_capabilies.is_supported && multiview_capabilies.max_view_count > 1; + device_capabilities.supports_fsr_half_float = p_context->get_shader_capabilities().shader_float16_is_supported && p_context->get_storage_buffer_capabilities().storage_buffer_16_bit_access_is_supported; } context = p_context; @@ -8979,7 +8941,7 @@ void RenderingDeviceVulkan::_free_rids(T &p_owner, const char *p_type) { } void RenderingDeviceVulkan::capture_timestamp(const String &p_name) { - ERR_FAIL_COND_MSG(draw_list != nullptr, "Capturing timestamps during draw list creation is not allowed. Offending timestap was: " + p_name); + ERR_FAIL_COND_MSG(draw_list != nullptr, "Capturing timestamps during draw list creation is not allowed. Offending timestamp was: " + p_name); ERR_FAIL_COND(frames[frame].timestamp_count >= max_timestamp_query_elements); //this should be optional for profiling, else it will slow things down diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index cf0b725cfc..f42929ffa4 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -175,7 +175,7 @@ class RenderingDeviceVulkan : public RenderingDevice { // These are temporary buffers on CPU memory that hold // the information until the CPU fetches it and places it // either on GPU buffers, or images (textures). It ensures - // updates are properly synchronized with whathever the + // updates are properly synchronized with whatever the // GPU is doing. // // The logic here is as follows, only 3 of these @@ -1037,7 +1037,7 @@ public: virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector<Vector<uint8_t>> &p_data = Vector<Vector<uint8_t>>()); virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture); - virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type = TEXTURE_SLICE_2D); + virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D); virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL); virtual Vector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer); @@ -1225,6 +1225,7 @@ public: virtual String get_device_vendor_name() const; virtual String get_device_name() const; + virtual RenderingDevice::DeviceType get_device_type() const; virtual String get_device_pipeline_cache_uuid() const; virtual uint64_t get_driver_resource(DriverResource p_resource, RID p_rid = RID(), uint64_t p_index = 0); diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index c178a68236..1aa1bfddc8 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,6 +33,7 @@ #include "core/config/engine.h" #include "core/config/project_settings.h" #include "core/string/ustring.h" +#include "core/templates/local_vector.h" #include "core/version.h" #include "servers/rendering/rendering_device.h" @@ -41,7 +42,6 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <vector> #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #define APP_SHORT_NAME "GodotEngine" @@ -212,7 +212,7 @@ VkBool32 VulkanContext::_check_layers(uint32_t check_count, const char *const *c } Error VulkanContext::_get_preferred_validation_layers(uint32_t *count, const char *const **names) { - static const std::vector<std::vector<const char *>> instance_validation_layers_alt{ + static const LocalVector<LocalVector<const char *>> instance_validation_layers_alt{ // Preferred set of validation layers { "VK_LAYER_KHRONOS_validation" }, @@ -249,10 +249,10 @@ Error VulkanContext::_get_preferred_validation_layers(uint32_t *count, const cha } for (uint32_t i = 0; i < instance_validation_layers_alt.size(); i++) { - if (_check_layers(instance_validation_layers_alt[i].size(), instance_validation_layers_alt[i].data(), instance_layer_count, instance_layers)) { + if (_check_layers(instance_validation_layers_alt[i].size(), instance_validation_layers_alt[i].ptr(), instance_layer_count, instance_layers)) { *count = instance_validation_layers_alt[i].size(); if (names != nullptr) { - *names = instance_validation_layers_alt[i].data(); + *names = instance_validation_layers_alt[i].ptr(); } break; } @@ -273,9 +273,9 @@ Error VulkanContext::_obtain_vulkan_version() { uint32_t api_version; VkResult res = func(&api_version); if (res == VK_SUCCESS) { - vulkan_major = VK_VERSION_MAJOR(api_version); - vulkan_minor = VK_VERSION_MINOR(api_version); - vulkan_patch = VK_VERSION_PATCH(api_version); + vulkan_major = VK_API_VERSION_MAJOR(api_version); + vulkan_minor = VK_API_VERSION_MINOR(api_version); + vulkan_patch = VK_API_VERSION_PATCH(api_version); } else { // according to the documentation this shouldn't fail with anything except a memory allocation error // in which case we're in deep trouble anyway @@ -535,6 +535,24 @@ Error VulkanContext::_check_capabilities() { multiview_capabilities.is_supported = multiview_features.multiview; multiview_capabilities.geometry_shader_is_supported = multiview_features.multiviewGeometryShader; multiview_capabilities.tessellation_shader_is_supported = multiview_features.multiviewTessellationShader; + + VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features; + shader_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR; + shader_features.pNext = nullptr; + + device_features.pNext = &shader_features; + + device_features_func(gpu, &device_features); + shader_capabilities.shader_float16_is_supported = shader_features.shaderFloat16; + + VkPhysicalDevice16BitStorageFeaturesKHR storage_feature; + storage_feature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR; + storage_feature.pNext = nullptr; + + device_features.pNext = &storage_feature; + + device_features_func(gpu, &device_features); + storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported = storage_feature.storageBuffer16BitAccess; } // check extended properties @@ -597,7 +615,7 @@ Error VulkanContext::_check_capabilities() { return OK; } -Error VulkanContext::_create_physical_device() { +Error VulkanContext::_create_instance() { /* obtain version */ _obtain_vulkan_version(); @@ -610,15 +628,13 @@ Error VulkanContext::_create_physical_device() { } CharString cs = ProjectSettings::get_singleton()->get("application/config/name").operator String().utf8(); - String name = "GodotEngine " + String(VERSION_FULL_NAME); - CharString namecs = name.utf8(); const VkApplicationInfo app = { /*sType*/ VK_STRUCTURE_TYPE_APPLICATION_INFO, /*pNext*/ nullptr, /*pApplicationName*/ cs.get_data(), /*applicationVersion*/ 0, - /*pEngineName*/ namecs.get_data(), - /*engineVersion*/ 0, + /*pEngineName*/ VERSION_NAME, + /*engineVersion*/ VK_MAKE_VERSION(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH), /*apiVersion*/ VK_MAKE_VERSION(vulkan_major, vulkan_minor, 0) }; VkInstanceCreateInfo inst_info{}; @@ -662,8 +678,6 @@ Error VulkanContext::_create_physical_device() { inst_info.pNext = &dbg_report_callback_create_info; } - uint32_t gpu_count; - VkResult err = vkCreateInstance(&inst_info, nullptr, &inst); ERR_FAIL_COND_V_MSG(err == VK_ERROR_INCOMPATIBLE_DRIVER, ERR_CANT_CREATE, "Cannot find a compatible Vulkan installable client driver (ICD).\n\n" @@ -684,10 +698,85 @@ Error VulkanContext::_create_physical_device() { volkLoadInstance(inst); #endif + if (enabled_debug_utils) { + // Setup VK_EXT_debug_utils function pointers always (we use them for + // debug labels and names). + CreateDebugUtilsMessengerEXT = + (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(inst, "vkCreateDebugUtilsMessengerEXT"); + DestroyDebugUtilsMessengerEXT = + (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(inst, "vkDestroyDebugUtilsMessengerEXT"); + SubmitDebugUtilsMessageEXT = + (PFN_vkSubmitDebugUtilsMessageEXT)vkGetInstanceProcAddr(inst, "vkSubmitDebugUtilsMessageEXT"); + CmdBeginDebugUtilsLabelEXT = + (PFN_vkCmdBeginDebugUtilsLabelEXT)vkGetInstanceProcAddr(inst, "vkCmdBeginDebugUtilsLabelEXT"); + CmdEndDebugUtilsLabelEXT = + (PFN_vkCmdEndDebugUtilsLabelEXT)vkGetInstanceProcAddr(inst, "vkCmdEndDebugUtilsLabelEXT"); + CmdInsertDebugUtilsLabelEXT = + (PFN_vkCmdInsertDebugUtilsLabelEXT)vkGetInstanceProcAddr(inst, "vkCmdInsertDebugUtilsLabelEXT"); + SetDebugUtilsObjectNameEXT = + (PFN_vkSetDebugUtilsObjectNameEXT)vkGetInstanceProcAddr(inst, "vkSetDebugUtilsObjectNameEXT"); + if (nullptr == CreateDebugUtilsMessengerEXT || nullptr == DestroyDebugUtilsMessengerEXT || + nullptr == SubmitDebugUtilsMessageEXT || nullptr == CmdBeginDebugUtilsLabelEXT || + nullptr == CmdEndDebugUtilsLabelEXT || nullptr == CmdInsertDebugUtilsLabelEXT || + nullptr == SetDebugUtilsObjectNameEXT) { + ERR_FAIL_V_MSG(ERR_CANT_CREATE, + "GetProcAddr: Failed to init VK_EXT_debug_utils\n" + "GetProcAddr: Failure"); + } + + err = CreateDebugUtilsMessengerEXT(inst, &dbg_messenger_create_info, nullptr, &dbg_messenger); + switch (err) { + case VK_SUCCESS: + break; + case VK_ERROR_OUT_OF_HOST_MEMORY: + ERR_FAIL_V_MSG(ERR_CANT_CREATE, + "CreateDebugUtilsMessengerEXT: out of host memory\n" + "CreateDebugUtilsMessengerEXT Failure"); + break; + default: + ERR_FAIL_V_MSG(ERR_CANT_CREATE, + "CreateDebugUtilsMessengerEXT: unknown failure\n" + "CreateDebugUtilsMessengerEXT Failure"); + ERR_FAIL_V(ERR_CANT_CREATE); + break; + } + } else if (enabled_debug_report) { + CreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT"); + DebugReportMessageEXT = (PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr(inst, "vkDebugReportMessageEXT"); + DestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT"); + + if (nullptr == CreateDebugReportCallbackEXT || nullptr == DebugReportMessageEXT || nullptr == DestroyDebugReportCallbackEXT) { + ERR_FAIL_V_MSG(ERR_CANT_CREATE, + "GetProcAddr: Failed to init VK_EXT_debug_report\n" + "GetProcAddr: Failure"); + } + + err = CreateDebugReportCallbackEXT(inst, &dbg_report_callback_create_info, nullptr, &dbg_debug_report); + switch (err) { + case VK_SUCCESS: + break; + case VK_ERROR_OUT_OF_HOST_MEMORY: + ERR_FAIL_V_MSG(ERR_CANT_CREATE, + "CreateDebugReportCallbackEXT: out of host memory\n" + "CreateDebugReportCallbackEXT Failure"); + break; + default: + ERR_FAIL_V_MSG(ERR_CANT_CREATE, + "CreateDebugReportCallbackEXT: unknown failure\n" + "CreateDebugReportCallbackEXT Failure"); + ERR_FAIL_V(ERR_CANT_CREATE); + break; + } + } + + return OK; +} + +Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) { /* Make initial call to query gpu_count, then second call for gpu info*/ - err = vkEnumeratePhysicalDevices(inst, &gpu_count, nullptr); + uint32_t gpu_count = 0; + VkResult err = vkEnumeratePhysicalDevices(inst, &gpu_count, nullptr); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); - ERR_FAIL_COND_V_MSG(gpu_count == 0, ERR_CANT_CREATE, "vkEnumeratePhysicalDevices reported zero accessible devices.\n\n" "Do you have a compatible Vulkan installable client driver (ICD) installed?\n" @@ -700,24 +789,120 @@ Error VulkanContext::_create_physical_device() { ERR_FAIL_V(ERR_CANT_CREATE); } + static const struct { + uint32_t id; + const char *name; + } vendor_names[] = { + { 0x1002, "AMD" }, + { 0x1010, "ImgTec" }, + { 0x106B, "Apple" }, + { 0x10DE, "NVIDIA" }, + { 0x13B5, "ARM" }, + { 0x5143, "Qualcomm" }, + { 0x8086, "Intel" }, + { 0, nullptr }, + }; + // TODO: At least on Linux Laptops integrated GPUs fail with Vulkan in many instances. // The device should really be a preference, but for now choosing a discrete GPU over the // integrated one is better than the default. - // Default to first device - uint32_t device_index = 0; - + int32_t device_index = -1; + int type_selected = -1; + print_verbose("Vulkan devices:"); for (uint32_t i = 0; i < gpu_count; ++i) { VkPhysicalDeviceProperties props; vkGetPhysicalDeviceProperties(physical_devices[i], &props); - if (props.deviceType == VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { - // Prefer discrete GPU. - device_index = i; - break; + bool present_supported = false; + + uint32_t device_queue_family_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &device_queue_family_count, nullptr); + VkQueueFamilyProperties *device_queue_props = (VkQueueFamilyProperties *)malloc(device_queue_family_count * sizeof(VkQueueFamilyProperties)); + vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &device_queue_family_count, device_queue_props); + for (uint32_t j = 0; j < device_queue_family_count; j++) { + VkBool32 supports; + vkGetPhysicalDeviceSurfaceSupportKHR(physical_devices[i], j, p_surface, &supports); + if (supports && ((device_queue_props[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)) { + present_supported = true; + } else { + continue; + } + } + String name = props.deviceName; + String vendor = "Unknown"; + String dev_type; + switch (props.deviceType) { + case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: { + dev_type = "Discrete"; + } break; + case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: { + dev_type = "Integrated"; + } break; + case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: { + dev_type = "Virtual"; + } break; + case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_CPU: { + dev_type = "CPU"; + } break; + default: { + dev_type = "Other"; + } break; } + uint32_t vendor_idx = 0; + while (vendor_names[vendor_idx].name != nullptr) { + if (props.vendorID == vendor_names[vendor_idx].id) { + vendor = vendor_names[vendor_idx].name; + break; + } + vendor_idx++; + } + free(device_queue_props); + print_verbose(" #" + itos(i) + ": " + vendor + " " + name + " - " + (present_supported ? "Supported" : "Unsupported") + ", " + dev_type); + + if (present_supported) { // Select first supported device of preferred type: Discrete > Integrated > Virtual > CPU > Other. + switch (props.deviceType) { + case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: { + if (type_selected < 4) { + type_selected = 4; + device_index = i; + } + } break; + case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: { + if (type_selected < 3) { + type_selected = 3; + device_index = i; + } + } break; + case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: { + if (type_selected < 2) { + type_selected = 2; + device_index = i; + } + } break; + case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_CPU: { + if (type_selected < 1) { + type_selected = 1; + device_index = i; + } + } break; + default: { + if (type_selected < 0) { + type_selected = 0; + device_index = i; + } + } break; + } + } + } + + int32_t user_device_index = Engine::get_singleton()->get_gpu_index(); // Force user selected GPU. + if (user_device_index >= 0 && user_device_index < (int32_t)gpu_count) { + device_index = user_device_index; } + ERR_FAIL_COND_V_MSG(device_index == -1, ERR_CANT_CREATE, "None of Vulkan devices supports both graphics and present queues."); + gpu = physical_devices[device_index]; free(physical_devices); @@ -730,20 +915,8 @@ Error VulkanContext::_create_physical_device() { /* Get identifier properties */ vkGetPhysicalDeviceProperties(gpu, &gpu_props); - static const struct { - uint32_t id; - const char *name; - } vendor_names[] = { - { 0x1002, "AMD" }, - { 0x1010, "ImgTec" }, - { 0x106B, "Apple" }, - { 0x10DE, "NVIDIA" }, - { 0x13B5, "ARM" }, - { 0x5143, "Qualcomm" }, - { 0x8086, "Intel" }, - { 0, nullptr }, - }; device_name = gpu_props.deviceName; + device_type = gpu_props.deviceType; pipeline_cache_id = String::hex_encode_buffer(gpu_props.pipelineCacheUUID, VK_UUID_SIZE); pipeline_cache_id += "-driver-" + itos(gpu_props.driverVersion); { @@ -834,77 +1007,6 @@ Error VulkanContext::_create_physical_device() { " extension.\n\nDo you have a compatible Vulkan installable client driver (ICD) installed?\n" "vkCreateInstance Failure"); - if (enabled_debug_utils) { - // Setup VK_EXT_debug_utils function pointers always (we use them for - // debug labels and names). - CreateDebugUtilsMessengerEXT = - (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(inst, "vkCreateDebugUtilsMessengerEXT"); - DestroyDebugUtilsMessengerEXT = - (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(inst, "vkDestroyDebugUtilsMessengerEXT"); - SubmitDebugUtilsMessageEXT = - (PFN_vkSubmitDebugUtilsMessageEXT)vkGetInstanceProcAddr(inst, "vkSubmitDebugUtilsMessageEXT"); - CmdBeginDebugUtilsLabelEXT = - (PFN_vkCmdBeginDebugUtilsLabelEXT)vkGetInstanceProcAddr(inst, "vkCmdBeginDebugUtilsLabelEXT"); - CmdEndDebugUtilsLabelEXT = - (PFN_vkCmdEndDebugUtilsLabelEXT)vkGetInstanceProcAddr(inst, "vkCmdEndDebugUtilsLabelEXT"); - CmdInsertDebugUtilsLabelEXT = - (PFN_vkCmdInsertDebugUtilsLabelEXT)vkGetInstanceProcAddr(inst, "vkCmdInsertDebugUtilsLabelEXT"); - SetDebugUtilsObjectNameEXT = - (PFN_vkSetDebugUtilsObjectNameEXT)vkGetInstanceProcAddr(inst, "vkSetDebugUtilsObjectNameEXT"); - if (nullptr == CreateDebugUtilsMessengerEXT || nullptr == DestroyDebugUtilsMessengerEXT || - nullptr == SubmitDebugUtilsMessageEXT || nullptr == CmdBeginDebugUtilsLabelEXT || - nullptr == CmdEndDebugUtilsLabelEXT || nullptr == CmdInsertDebugUtilsLabelEXT || - nullptr == SetDebugUtilsObjectNameEXT) { - ERR_FAIL_V_MSG(ERR_CANT_CREATE, - "GetProcAddr: Failed to init VK_EXT_debug_utils\n" - "GetProcAddr: Failure"); - } - - err = CreateDebugUtilsMessengerEXT(inst, &dbg_messenger_create_info, nullptr, &dbg_messenger); - switch (err) { - case VK_SUCCESS: - break; - case VK_ERROR_OUT_OF_HOST_MEMORY: - ERR_FAIL_V_MSG(ERR_CANT_CREATE, - "CreateDebugUtilsMessengerEXT: out of host memory\n" - "CreateDebugUtilsMessengerEXT Failure"); - break; - default: - ERR_FAIL_V_MSG(ERR_CANT_CREATE, - "CreateDebugUtilsMessengerEXT: unknown failure\n" - "CreateDebugUtilsMessengerEXT Failure"); - ERR_FAIL_V(ERR_CANT_CREATE); - break; - } - } else if (enabled_debug_report) { - CreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT"); - DebugReportMessageEXT = (PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr(inst, "vkDebugReportMessageEXT"); - DestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT"); - - if (nullptr == CreateDebugReportCallbackEXT || nullptr == DebugReportMessageEXT || nullptr == DestroyDebugReportCallbackEXT) { - ERR_FAIL_V_MSG(ERR_CANT_CREATE, - "GetProcAddr: Failed to init VK_EXT_debug_report\n" - "GetProcAddr: Failure"); - } - - err = CreateDebugReportCallbackEXT(inst, &dbg_report_callback_create_info, nullptr, &dbg_debug_report); - switch (err) { - case VK_SUCCESS: - break; - case VK_ERROR_OUT_OF_HOST_MEMORY: - ERR_FAIL_V_MSG(ERR_CANT_CREATE, - "CreateDebugReportCallbackEXT: out of host memory\n" - "CreateDebugReportCallbackEXT Failure"); - break; - default: - ERR_FAIL_V_MSG(ERR_CANT_CREATE, - "CreateDebugReportCallbackEXT: unknown failure\n" - "CreateDebugReportCallbackEXT Failure"); - ERR_FAIL_V(ERR_CANT_CREATE); - break; - } - } - /* Call with nullptr data to get count */ vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queue_family_count, nullptr); ERR_FAIL_COND_V(queue_family_count == 0, ERR_CANT_CREATE); @@ -940,6 +1042,7 @@ Error VulkanContext::_create_physical_device() { } } + device_initialized = true; return OK; } @@ -1192,25 +1295,17 @@ bool VulkanContext::_use_validation_layers() { Error VulkanContext::_window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, VkSurfaceKHR p_surface, int p_width, int p_height) { ERR_FAIL_COND_V(windows.has(p_window_id), ERR_INVALID_PARAMETER); + if (!device_initialized) { + Error err = _create_physical_device(p_surface); + ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE); + } + if (!queues_initialized) { // We use a single GPU, but we need a surface to initialize the // queues, so this process must be deferred until a surface // is created. Error err = _initialize_queues(p_surface); ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE); - } else { - // make sure any of the surfaces supports present (validation layer complains if this is not done). - bool any_supports_present = false; - for (uint32_t i = 0; i < queue_family_count; i++) { - VkBool32 supports; - fpGetPhysicalDeviceSurfaceSupportKHR(gpu, i, p_surface, &supports); - if (supports) { - any_supports_present = true; - break; - } - } - - ERR_FAIL_COND_V_MSG(!any_supports_present, ERR_CANT_CREATE, "Surface passed for sub-window creation does not support presenting"); } Window window; @@ -1677,12 +1772,12 @@ Error VulkanContext::initialize() { return FAILED; } #endif - Error err = _create_physical_device(); - if (err) { + + Error err = _create_instance(); + if (err != OK) { return err; } - device_initialized = true; return OK; } @@ -2192,6 +2287,11 @@ String VulkanContext::get_device_vendor_name() const { String VulkanContext::get_device_name() const { return device_name; } + +RenderingDevice::DeviceType VulkanContext::get_device_type() const { + return RenderingDevice::DeviceType(device_type); +} + String VulkanContext::get_device_pipeline_cache_uuid() const { return pipeline_cache_id; } diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h index ae7c697be8..67a675f6c6 100644 --- a/drivers/vulkan/vulkan_context.h +++ b/drivers/vulkan/vulkan_context.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,6 +37,7 @@ #include "core/templates/map.h" #include "core/templates/rid_owner.h" #include "servers/display_server.h" +#include "servers/rendering/rendering_device.h" #ifdef USE_VOLK #include <volk.h> @@ -66,6 +67,14 @@ public: uint32_t max_instance_count; }; + struct ShaderCapabilities { + bool shader_float16_is_supported; + }; + + struct StorageBufferCapabilities { + bool storage_buffer_16_bit_access_is_supported; + }; + private: enum { MAX_EXTENSIONS = 128, @@ -88,9 +97,12 @@ private: uint32_t vulkan_patch = 0; SubgroupCapabilities subgroup_capabilities; MultiviewCapabilities multiview_capabilities; + ShaderCapabilities shader_capabilities; + StorageBufferCapabilities storage_buffer_capabilities; String device_vendor; String device_name; + VkPhysicalDeviceType device_type; String pipeline_cache_id; uint32_t device_api_version = 0; @@ -212,7 +224,9 @@ private: const char *pMessage, void *pUserData); - Error _create_physical_device(); + Error _create_instance(); + + Error _create_physical_device(VkSurfaceKHR p_surface); Error _initialize_queues(VkSurfaceKHR p_surface); @@ -239,6 +253,8 @@ public: uint32_t get_vulkan_minor() const { return vulkan_minor; }; SubgroupCapabilities get_subgroup_capabilities() const { return subgroup_capabilities; }; MultiviewCapabilities get_multiview_capabilities() const { return multiview_capabilities; }; + ShaderCapabilities get_shader_capabilities() const { return shader_capabilities; }; + StorageBufferCapabilities get_storage_buffer_capabilities() const { return storage_buffer_capabilities; }; VkDevice get_device(); VkPhysicalDevice get_physical_device(); @@ -278,6 +294,7 @@ public: String get_device_vendor_name() const; String get_device_name() const; + RenderingDevice::DeviceType get_device_type() const; String get_device_pipeline_cache_uuid() const; void set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_mode); |