Path: blob/master/drivers/vulkan/rendering_device_driver_vulkan.cpp
20941 views
/**************************************************************************/1/* rendering_device_driver_vulkan.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "rendering_device_driver_vulkan.h"3132#include "core/config/project_settings.h"33#include "core/io/marshalls.h"34#include "vulkan_hooks.h"3536#include "thirdparty/misc/smolv.h"3738#if defined(ANDROID_ENABLED)39#include "platform/android/java_godot_wrapper.h"40#include "platform/android/os_android.h"41#include "platform/android/thread_jandroid.h"42#endif4344#if defined(SWAPPY_FRAME_PACING_ENABLED)45#include "thirdparty/swappy-frame-pacing/swappyVk.h"46#endif4748#define ARRAY_SIZE(a) std_size(a)4950// Disable raytracing support on macOS and iOS due to MoltenVK limitations.51#if !(defined(MACOS_ENABLED) || defined(IOS_ENABLED))52#define VULKAN_RAYTRACING_ENABLED 153#else54#define VULKAN_RAYTRACING_ENABLED 055#endif5657#define PRINT_NATIVE_COMMANDS 05859// Enable the use of re-spirv for optimizing shaders after applying specialization constants.60#define RESPV_ENABLED 16162// Only enable function inlining for re-spirv when dealing with a shader that uses specialization constants.63#define RESPV_ONLY_INLINE_SHADERS_WITH_SPEC_CONSTANTS 16465// Print additional information about every shader optimized with re-spirv.66#define RESPV_VERBOSE 06768// Disable dead code elimination when using re-spirv.69#define RESPV_DONT_REMOVE_DEAD_CODE 07071// Record numerous statistics about pipeline creation such as time and shader sizes. When combined with enabling72// and disabling re-spirv, this can be used to measure its effects.73#define RECORD_PIPELINE_STATISTICS 07475#if RECORD_PIPELINE_STATISTICS76#include "core/io/file_access.h"77#define RECORD_PIPELINE_STATISTICS_PATH "./pipelines.csv"78#endif7980/*****************/81/**** GENERIC ****/82/*****************/8384#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)85static const uint32_t BREADCRUMB_BUFFER_ENTRIES = 512u;86#endif8788static const uint32_t MAX_DYNAMIC_BUFFERS = 8u; // Minimum guaranteed by Vulkan.8990static const VkFormat RD_TO_VK_FORMAT[RDD::DATA_FORMAT_MAX] = {91VK_FORMAT_R4G4_UNORM_PACK8,92VK_FORMAT_R4G4B4A4_UNORM_PACK16,93VK_FORMAT_B4G4R4A4_UNORM_PACK16,94VK_FORMAT_R5G6B5_UNORM_PACK16,95VK_FORMAT_B5G6R5_UNORM_PACK16,96VK_FORMAT_R5G5B5A1_UNORM_PACK16,97VK_FORMAT_B5G5R5A1_UNORM_PACK16,98VK_FORMAT_A1R5G5B5_UNORM_PACK16,99VK_FORMAT_R8_UNORM,100VK_FORMAT_R8_SNORM,101VK_FORMAT_R8_USCALED,102VK_FORMAT_R8_SSCALED,103VK_FORMAT_R8_UINT,104VK_FORMAT_R8_SINT,105VK_FORMAT_R8_SRGB,106VK_FORMAT_R8G8_UNORM,107VK_FORMAT_R8G8_SNORM,108VK_FORMAT_R8G8_USCALED,109VK_FORMAT_R8G8_SSCALED,110VK_FORMAT_R8G8_UINT,111VK_FORMAT_R8G8_SINT,112VK_FORMAT_R8G8_SRGB,113VK_FORMAT_R8G8B8_UNORM,114VK_FORMAT_R8G8B8_SNORM,115VK_FORMAT_R8G8B8_USCALED,116VK_FORMAT_R8G8B8_SSCALED,117VK_FORMAT_R8G8B8_UINT,118VK_FORMAT_R8G8B8_SINT,119VK_FORMAT_R8G8B8_SRGB,120VK_FORMAT_B8G8R8_UNORM,121VK_FORMAT_B8G8R8_SNORM,122VK_FORMAT_B8G8R8_USCALED,123VK_FORMAT_B8G8R8_SSCALED,124VK_FORMAT_B8G8R8_UINT,125VK_FORMAT_B8G8R8_SINT,126VK_FORMAT_B8G8R8_SRGB,127VK_FORMAT_R8G8B8A8_UNORM,128VK_FORMAT_R8G8B8A8_SNORM,129VK_FORMAT_R8G8B8A8_USCALED,130VK_FORMAT_R8G8B8A8_SSCALED,131VK_FORMAT_R8G8B8A8_UINT,132VK_FORMAT_R8G8B8A8_SINT,133VK_FORMAT_R8G8B8A8_SRGB,134VK_FORMAT_B8G8R8A8_UNORM,135VK_FORMAT_B8G8R8A8_SNORM,136VK_FORMAT_B8G8R8A8_USCALED,137VK_FORMAT_B8G8R8A8_SSCALED,138VK_FORMAT_B8G8R8A8_UINT,139VK_FORMAT_B8G8R8A8_SINT,140VK_FORMAT_B8G8R8A8_SRGB,141VK_FORMAT_A8B8G8R8_UNORM_PACK32,142VK_FORMAT_A8B8G8R8_SNORM_PACK32,143VK_FORMAT_A8B8G8R8_USCALED_PACK32,144VK_FORMAT_A8B8G8R8_SSCALED_PACK32,145VK_FORMAT_A8B8G8R8_UINT_PACK32,146VK_FORMAT_A8B8G8R8_SINT_PACK32,147VK_FORMAT_A8B8G8R8_SRGB_PACK32,148VK_FORMAT_A2R10G10B10_UNORM_PACK32,149VK_FORMAT_A2R10G10B10_SNORM_PACK32,150VK_FORMAT_A2R10G10B10_USCALED_PACK32,151VK_FORMAT_A2R10G10B10_SSCALED_PACK32,152VK_FORMAT_A2R10G10B10_UINT_PACK32,153VK_FORMAT_A2R10G10B10_SINT_PACK32,154VK_FORMAT_A2B10G10R10_UNORM_PACK32,155VK_FORMAT_A2B10G10R10_SNORM_PACK32,156VK_FORMAT_A2B10G10R10_USCALED_PACK32,157VK_FORMAT_A2B10G10R10_SSCALED_PACK32,158VK_FORMAT_A2B10G10R10_UINT_PACK32,159VK_FORMAT_A2B10G10R10_SINT_PACK32,160VK_FORMAT_R16_UNORM,161VK_FORMAT_R16_SNORM,162VK_FORMAT_R16_USCALED,163VK_FORMAT_R16_SSCALED,164VK_FORMAT_R16_UINT,165VK_FORMAT_R16_SINT,166VK_FORMAT_R16_SFLOAT,167VK_FORMAT_R16G16_UNORM,168VK_FORMAT_R16G16_SNORM,169VK_FORMAT_R16G16_USCALED,170VK_FORMAT_R16G16_SSCALED,171VK_FORMAT_R16G16_UINT,172VK_FORMAT_R16G16_SINT,173VK_FORMAT_R16G16_SFLOAT,174VK_FORMAT_R16G16B16_UNORM,175VK_FORMAT_R16G16B16_SNORM,176VK_FORMAT_R16G16B16_USCALED,177VK_FORMAT_R16G16B16_SSCALED,178VK_FORMAT_R16G16B16_UINT,179VK_FORMAT_R16G16B16_SINT,180VK_FORMAT_R16G16B16_SFLOAT,181VK_FORMAT_R16G16B16A16_UNORM,182VK_FORMAT_R16G16B16A16_SNORM,183VK_FORMAT_R16G16B16A16_USCALED,184VK_FORMAT_R16G16B16A16_SSCALED,185VK_FORMAT_R16G16B16A16_UINT,186VK_FORMAT_R16G16B16A16_SINT,187VK_FORMAT_R16G16B16A16_SFLOAT,188VK_FORMAT_R32_UINT,189VK_FORMAT_R32_SINT,190VK_FORMAT_R32_SFLOAT,191VK_FORMAT_R32G32_UINT,192VK_FORMAT_R32G32_SINT,193VK_FORMAT_R32G32_SFLOAT,194VK_FORMAT_R32G32B32_UINT,195VK_FORMAT_R32G32B32_SINT,196VK_FORMAT_R32G32B32_SFLOAT,197VK_FORMAT_R32G32B32A32_UINT,198VK_FORMAT_R32G32B32A32_SINT,199VK_FORMAT_R32G32B32A32_SFLOAT,200VK_FORMAT_R64_UINT,201VK_FORMAT_R64_SINT,202VK_FORMAT_R64_SFLOAT,203VK_FORMAT_R64G64_UINT,204VK_FORMAT_R64G64_SINT,205VK_FORMAT_R64G64_SFLOAT,206VK_FORMAT_R64G64B64_UINT,207VK_FORMAT_R64G64B64_SINT,208VK_FORMAT_R64G64B64_SFLOAT,209VK_FORMAT_R64G64B64A64_UINT,210VK_FORMAT_R64G64B64A64_SINT,211VK_FORMAT_R64G64B64A64_SFLOAT,212VK_FORMAT_B10G11R11_UFLOAT_PACK32,213VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,214VK_FORMAT_D16_UNORM,215VK_FORMAT_X8_D24_UNORM_PACK32,216VK_FORMAT_D32_SFLOAT,217VK_FORMAT_S8_UINT,218VK_FORMAT_D16_UNORM_S8_UINT,219VK_FORMAT_D24_UNORM_S8_UINT,220VK_FORMAT_D32_SFLOAT_S8_UINT,221VK_FORMAT_BC1_RGB_UNORM_BLOCK,222VK_FORMAT_BC1_RGB_SRGB_BLOCK,223VK_FORMAT_BC1_RGBA_UNORM_BLOCK,224VK_FORMAT_BC1_RGBA_SRGB_BLOCK,225VK_FORMAT_BC2_UNORM_BLOCK,226VK_FORMAT_BC2_SRGB_BLOCK,227VK_FORMAT_BC3_UNORM_BLOCK,228VK_FORMAT_BC3_SRGB_BLOCK,229VK_FORMAT_BC4_UNORM_BLOCK,230VK_FORMAT_BC4_SNORM_BLOCK,231VK_FORMAT_BC5_UNORM_BLOCK,232VK_FORMAT_BC5_SNORM_BLOCK,233VK_FORMAT_BC6H_UFLOAT_BLOCK,234VK_FORMAT_BC6H_SFLOAT_BLOCK,235VK_FORMAT_BC7_UNORM_BLOCK,236VK_FORMAT_BC7_SRGB_BLOCK,237VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,238VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,239VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,240VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,241VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,242VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,243VK_FORMAT_EAC_R11_UNORM_BLOCK,244VK_FORMAT_EAC_R11_SNORM_BLOCK,245VK_FORMAT_EAC_R11G11_UNORM_BLOCK,246VK_FORMAT_EAC_R11G11_SNORM_BLOCK,247VK_FORMAT_ASTC_4x4_UNORM_BLOCK,248VK_FORMAT_ASTC_4x4_SRGB_BLOCK,249VK_FORMAT_ASTC_5x4_UNORM_BLOCK,250VK_FORMAT_ASTC_5x4_SRGB_BLOCK,251VK_FORMAT_ASTC_5x5_UNORM_BLOCK,252VK_FORMAT_ASTC_5x5_SRGB_BLOCK,253VK_FORMAT_ASTC_6x5_UNORM_BLOCK,254VK_FORMAT_ASTC_6x5_SRGB_BLOCK,255VK_FORMAT_ASTC_6x6_UNORM_BLOCK,256VK_FORMAT_ASTC_6x6_SRGB_BLOCK,257VK_FORMAT_ASTC_8x5_UNORM_BLOCK,258VK_FORMAT_ASTC_8x5_SRGB_BLOCK,259VK_FORMAT_ASTC_8x6_UNORM_BLOCK,260VK_FORMAT_ASTC_8x6_SRGB_BLOCK,261VK_FORMAT_ASTC_8x8_UNORM_BLOCK,262VK_FORMAT_ASTC_8x8_SRGB_BLOCK,263VK_FORMAT_ASTC_10x5_UNORM_BLOCK,264VK_FORMAT_ASTC_10x5_SRGB_BLOCK,265VK_FORMAT_ASTC_10x6_UNORM_BLOCK,266VK_FORMAT_ASTC_10x6_SRGB_BLOCK,267VK_FORMAT_ASTC_10x8_UNORM_BLOCK,268VK_FORMAT_ASTC_10x8_SRGB_BLOCK,269VK_FORMAT_ASTC_10x10_UNORM_BLOCK,270VK_FORMAT_ASTC_10x10_SRGB_BLOCK,271VK_FORMAT_ASTC_12x10_UNORM_BLOCK,272VK_FORMAT_ASTC_12x10_SRGB_BLOCK,273VK_FORMAT_ASTC_12x12_UNORM_BLOCK,274VK_FORMAT_ASTC_12x12_SRGB_BLOCK,275VK_FORMAT_G8B8G8R8_422_UNORM,276VK_FORMAT_B8G8R8G8_422_UNORM,277VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,278VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,279VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,280VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,281VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,282VK_FORMAT_R10X6_UNORM_PACK16,283VK_FORMAT_R10X6G10X6_UNORM_2PACK16,284VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,285VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,286VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,287VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,288VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,289VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,290VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,291VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,292VK_FORMAT_R12X4_UNORM_PACK16,293VK_FORMAT_R12X4G12X4_UNORM_2PACK16,294VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,295VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,296VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,297VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,298VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,299VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,300VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,301VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,302VK_FORMAT_G16B16G16R16_422_UNORM,303VK_FORMAT_B16G16R16G16_422_UNORM,304VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,305VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,306VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,307VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,308VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,309VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK,310VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK,311VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK,312VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK,313VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK,314VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK,315VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK,316VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK,317VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK,318VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK,319VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK,320VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK,321VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK,322VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK,323};324325static VkImageLayout RD_TO_VK_LAYOUT[RDD::TEXTURE_LAYOUT_MAX] = {326VK_IMAGE_LAYOUT_UNDEFINED, // TEXTURE_LAYOUT_UNDEFINED327VK_IMAGE_LAYOUT_GENERAL, // TEXTURE_LAYOUT_GENERAL328VK_IMAGE_LAYOUT_GENERAL, // TEXTURE_LAYOUT_STORAGE_OPTIMAL329VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL330VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL331VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, // TEXTURE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL332VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL333VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // TEXTURE_LAYOUT_COPY_SRC_OPTIMAL334VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // TEXTURE_LAYOUT_COPY_DST_OPTIMAL335VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // TEXTURE_LAYOUT_RESOLVE_SRC_OPTIMAL336VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // TEXTURE_LAYOUT_RESOLVE_DST_OPTIMAL337VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, // TEXTURE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL338VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT, // TEXTURE_LAYOUT_FRAGMENT_DENSITY_MAP_ATTACHMENT_OPTIMAL339};340341static VkPipelineStageFlags _rd_to_vk_pipeline_stages(BitField<RDD::PipelineStageBits> p_stages) {342VkPipelineStageFlags vk_flags = 0;343if (p_stages.has_flag(RDD::PIPELINE_STAGE_COPY_BIT) || p_stages.has_flag(RDD::PIPELINE_STAGE_RESOLVE_BIT)) {344// Transfer has been split into copy and resolve bits. Clear them and merge them into one bit.345vk_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;346p_stages.clear_flag(RDD::PIPELINE_STAGE_COPY_BIT);347p_stages.clear_flag(RDD::PIPELINE_STAGE_RESOLVE_BIT);348}349350if (p_stages.has_flag(RDD::PIPELINE_STAGE_CLEAR_STORAGE_BIT)) {351// Vulkan should never use this as API_TRAIT_CLEAR_RESOURCES_WITH_VIEWS is not specified.352// Therefore, storage is never cleared with an explicit command.353p_stages.clear_flag(RDD::PIPELINE_STAGE_CLEAR_STORAGE_BIT);354}355356// The rest of the flags have compatible numeric values with Vulkan.357return VkPipelineStageFlags(p_stages) | vk_flags;358}359360static VkAccessFlags _rd_to_vk_access_flags(BitField<RDD::BarrierAccessBits> p_access) {361VkAccessFlags vk_flags = 0;362if (p_access.has_flag(RDD::BARRIER_ACCESS_COPY_READ_BIT) || p_access.has_flag(RDD::BARRIER_ACCESS_RESOLVE_READ_BIT)) {363vk_flags |= VK_ACCESS_TRANSFER_READ_BIT;364p_access.clear_flag(RDD::BARRIER_ACCESS_COPY_READ_BIT);365p_access.clear_flag(RDD::BARRIER_ACCESS_RESOLVE_READ_BIT);366}367368if (p_access.has_flag(RDD::BARRIER_ACCESS_COPY_WRITE_BIT) || p_access.has_flag(RDD::BARRIER_ACCESS_RESOLVE_WRITE_BIT)) {369vk_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;370p_access.clear_flag(RDD::BARRIER_ACCESS_COPY_WRITE_BIT);371p_access.clear_flag(RDD::BARRIER_ACCESS_RESOLVE_WRITE_BIT);372}373374if (p_access.has_flag(RDD::BARRIER_ACCESS_STORAGE_CLEAR_BIT)) {375// Vulkan should never use this as API_TRAIT_CLEAR_RESOURCES_WITH_VIEWS is not specified.376// Therefore, storage is never cleared with an explicit command.377p_access.clear_flag(RDD::BARRIER_ACCESS_STORAGE_CLEAR_BIT);378}379380// The rest of the flags have compatible numeric values with Vulkan.381return VkAccessFlags(p_access) | vk_flags;382}383384// RDD::CompareOperator == VkCompareOp.385static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_NEVER, VK_COMPARE_OP_NEVER));386static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_LESS, VK_COMPARE_OP_LESS));387static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_EQUAL, VK_COMPARE_OP_EQUAL));388static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL));389static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_GREATER, VK_COMPARE_OP_GREATER));390static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NOT_EQUAL));391static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL));392static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_ALWAYS, VK_COMPARE_OP_ALWAYS));393394static_assert(ARRAYS_COMPATIBLE_FIELDWISE(Rect2i, VkRect2D));395396uint32_t RenderingDeviceDriverVulkan::SubgroupCapabilities::supported_stages_flags_rd() const {397uint32_t flags = 0;398399if (supported_stages & VK_SHADER_STAGE_VERTEX_BIT) {400flags += SHADER_STAGE_VERTEX_BIT;401}402if (supported_stages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) {403flags += SHADER_STAGE_TESSELATION_CONTROL_BIT;404}405if (supported_stages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) {406flags += SHADER_STAGE_TESSELATION_EVALUATION_BIT;407}408if (supported_stages & VK_SHADER_STAGE_GEOMETRY_BIT) {409// FIXME: Add shader stage geometry bit.410}411if (supported_stages & VK_SHADER_STAGE_FRAGMENT_BIT) {412flags += SHADER_STAGE_FRAGMENT_BIT;413}414if (supported_stages & VK_SHADER_STAGE_COMPUTE_BIT) {415flags += SHADER_STAGE_COMPUTE_BIT;416}417if (supported_stages & VK_SHADER_STAGE_RAYGEN_BIT_KHR) {418flags += SHADER_STAGE_RAYGEN_BIT;419}420if (supported_stages & VK_SHADER_STAGE_ANY_HIT_BIT_KHR) {421flags += SHADER_STAGE_ANY_HIT_BIT;422}423if (supported_stages & VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR) {424flags += SHADER_STAGE_CLOSEST_HIT_BIT;425}426if (supported_stages & VK_SHADER_STAGE_MISS_BIT_KHR) {427flags += SHADER_STAGE_MISS_BIT;428}429if (supported_stages & VK_SHADER_STAGE_INTERSECTION_BIT_KHR) {430flags += SHADER_STAGE_INTERSECTION_BIT;431}432433return flags;434}435436String RenderingDeviceDriverVulkan::SubgroupCapabilities::supported_stages_desc() const {437String res;438439if (supported_stages & VK_SHADER_STAGE_VERTEX_BIT) {440res += ", STAGE_VERTEX";441}442if (supported_stages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) {443res += ", STAGE_TESSELLATION_CONTROL";444}445if (supported_stages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) {446res += ", STAGE_TESSELLATION_EVALUATION";447}448if (supported_stages & VK_SHADER_STAGE_GEOMETRY_BIT) {449res += ", STAGE_GEOMETRY";450}451if (supported_stages & VK_SHADER_STAGE_FRAGMENT_BIT) {452res += ", STAGE_FRAGMENT";453}454if (supported_stages & VK_SHADER_STAGE_COMPUTE_BIT) {455res += ", STAGE_COMPUTE";456}457458// These are not defined on Android GRMBL.459if (supported_stages & 0x00000100 /* VK_SHADER_STAGE_RAYGEN_BIT_KHR */) {460res += ", STAGE_RAYGEN_KHR";461}462if (supported_stages & 0x00000200 /* VK_SHADER_STAGE_ANY_HIT_BIT_KHR */) {463res += ", STAGE_ANY_HIT_KHR";464}465if (supported_stages & 0x00000400 /* VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR */) {466res += ", STAGE_CLOSEST_HIT_KHR";467}468if (supported_stages & 0x00000800 /* VK_SHADER_STAGE_MISS_BIT_KHR */) {469res += ", STAGE_MISS_KHR";470}471if (supported_stages & 0x00001000 /* VK_SHADER_STAGE_INTERSECTION_BIT_KHR */) {472res += ", STAGE_INTERSECTION_KHR";473}474if (supported_stages & 0x00002000 /* VK_SHADER_STAGE_CALLABLE_BIT_KHR */) {475res += ", STAGE_CALLABLE_KHR";476}477if (supported_stages & 0x00000040 /* VK_SHADER_STAGE_TASK_BIT_NV */) {478res += ", STAGE_TASK_NV";479}480if (supported_stages & 0x00000080 /* VK_SHADER_STAGE_MESH_BIT_NV */) {481res += ", STAGE_MESH_NV";482}483484return res.substr(2); // Remove first ", ".485}486487uint32_t RenderingDeviceDriverVulkan::SubgroupCapabilities::supported_operations_flags_rd() const {488uint32_t flags = 0;489490if (supported_operations & VK_SUBGROUP_FEATURE_BASIC_BIT) {491flags += SUBGROUP_BASIC_BIT;492}493if (supported_operations & VK_SUBGROUP_FEATURE_VOTE_BIT) {494flags += SUBGROUP_VOTE_BIT;495}496if (supported_operations & VK_SUBGROUP_FEATURE_ARITHMETIC_BIT) {497flags += SUBGROUP_ARITHMETIC_BIT;498}499if (supported_operations & VK_SUBGROUP_FEATURE_BALLOT_BIT) {500flags += SUBGROUP_BALLOT_BIT;501}502if (supported_operations & VK_SUBGROUP_FEATURE_SHUFFLE_BIT) {503flags += SUBGROUP_SHUFFLE_BIT;504}505if (supported_operations & VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT) {506flags += SUBGROUP_SHUFFLE_RELATIVE_BIT;507}508if (supported_operations & VK_SUBGROUP_FEATURE_CLUSTERED_BIT) {509flags += SUBGROUP_CLUSTERED_BIT;510}511if (supported_operations & VK_SUBGROUP_FEATURE_QUAD_BIT) {512flags += SUBGROUP_QUAD_BIT;513}514515return flags;516}517518String RenderingDeviceDriverVulkan::SubgroupCapabilities::supported_operations_desc() const {519String res;520521if (supported_operations & VK_SUBGROUP_FEATURE_BASIC_BIT) {522res += ", FEATURE_BASIC";523}524if (supported_operations & VK_SUBGROUP_FEATURE_VOTE_BIT) {525res += ", FEATURE_VOTE";526}527if (supported_operations & VK_SUBGROUP_FEATURE_ARITHMETIC_BIT) {528res += ", FEATURE_ARITHMETIC";529}530if (supported_operations & VK_SUBGROUP_FEATURE_BALLOT_BIT) {531res += ", FEATURE_BALLOT";532}533if (supported_operations & VK_SUBGROUP_FEATURE_SHUFFLE_BIT) {534res += ", FEATURE_SHUFFLE";535}536if (supported_operations & VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT) {537res += ", FEATURE_SHUFFLE_RELATIVE";538}539if (supported_operations & VK_SUBGROUP_FEATURE_CLUSTERED_BIT) {540res += ", FEATURE_CLUSTERED";541}542if (supported_operations & VK_SUBGROUP_FEATURE_QUAD_BIT) {543res += ", FEATURE_QUAD";544}545if (supported_operations & VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV) {546res += ", FEATURE_PARTITIONED_NV";547}548549return res.substr(2); // Remove first ", ".550}551552/*****************/553/**** GENERIC ****/554/*****************/555556void RenderingDeviceDriverVulkan::_register_requested_device_extension(const CharString &p_extension_name, bool p_required) {557ERR_FAIL_COND(requested_device_extensions.has(p_extension_name));558requested_device_extensions[p_extension_name] = p_required;559}560561Error RenderingDeviceDriverVulkan::_initialize_device_extensions() {562enabled_device_extension_names.clear();563564_register_requested_device_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME, true);565_register_requested_device_extension(VK_KHR_MULTIVIEW_EXTENSION_NAME, false);566_register_requested_device_extension(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, false);567_register_requested_device_extension(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME, false);568_register_requested_device_extension(VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME, false);569_register_requested_device_extension(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, false);570_register_requested_device_extension(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, false);571_register_requested_device_extension(VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME, false);572_register_requested_device_extension(VK_KHR_16BIT_STORAGE_EXTENSION_NAME, false);573_register_requested_device_extension(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME, false);574_register_requested_device_extension(VK_KHR_MAINTENANCE_2_EXTENSION_NAME, false);575_register_requested_device_extension(VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME, false);576_register_requested_device_extension(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, false);577_register_requested_device_extension(VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME, false);578_register_requested_device_extension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, false);579_register_requested_device_extension(VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME, false);580_register_requested_device_extension(VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME, false);581_register_requested_device_extension(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME, false);582_register_requested_device_extension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, false);583_register_requested_device_extension(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME, false);584_register_requested_device_extension(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, false);585_register_requested_device_extension(VK_NV_RAY_TRACING_VALIDATION_EXTENSION_NAME, false);586_register_requested_device_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME, false);587588// We don't actually use this extension, but some runtime components on some platforms589// can and will fill the validation layers with useless info otherwise if not enabled.590_register_requested_device_extension(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, false);591592if (Engine::get_singleton()->is_generate_spirv_debug_info_enabled()) {593_register_requested_device_extension(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME, true);594}595596#if defined(VK_TRACK_DEVICE_MEMORY)597if (Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {598_register_requested_device_extension(VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME, false);599}600#endif601_register_requested_device_extension(VK_EXT_DEVICE_FAULT_EXTENSION_NAME, false);602603{604// Debug marker extensions.605// Should be last element in the array.606#ifdef DEV_ENABLED607bool want_debug_markers = true;608#else609bool want_debug_markers = OS::get_singleton()->is_stdout_verbose();610#endif611if (want_debug_markers) {612_register_requested_device_extension(VK_EXT_DEBUG_MARKER_EXTENSION_NAME, false);613}614}615616uint32_t device_extension_count = 0;617VkResult err = vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &device_extension_count, nullptr);618ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);619ERR_FAIL_COND_V_MSG(device_extension_count == 0, ERR_CANT_CREATE, "vkEnumerateDeviceExtensionProperties failed to find any extensions\n\nDo you have a compatible Vulkan installable client driver (ICD) installed?");620621TightLocalVector<VkExtensionProperties> device_extensions;622device_extensions.resize(device_extension_count);623err = vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &device_extension_count, device_extensions.ptr());624ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);625626#if defined(SWAPPY_FRAME_PACING_ENABLED)627if (swappy_frame_pacer_enable) {628char **swappy_required_extensions;629uint32_t swappy_required_extensions_count = 0;630// Determine number of extensions required by Swappy frame pacer.631SwappyVk_determineDeviceExtensions(physical_device, device_extension_count, device_extensions.ptr(), &swappy_required_extensions_count, nullptr);632633if (swappy_required_extensions_count < device_extension_count) {634// Determine the actual extensions.635swappy_required_extensions = (char **)malloc(swappy_required_extensions_count * sizeof(char *));636char *pRequiredExtensionsData = (char *)malloc(swappy_required_extensions_count * (VK_MAX_EXTENSION_NAME_SIZE + 1));637for (uint32_t i = 0; i < swappy_required_extensions_count; i++) {638swappy_required_extensions[i] = &pRequiredExtensionsData[i * (VK_MAX_EXTENSION_NAME_SIZE + 1)];639}640SwappyVk_determineDeviceExtensions(physical_device, device_extension_count,641device_extensions.ptr(), &swappy_required_extensions_count, swappy_required_extensions);642643// Enable extensions requested by Swappy.644for (uint32_t i = 0; i < swappy_required_extensions_count; i++) {645CharString extension_name(swappy_required_extensions[i]);646if (requested_device_extensions.has(extension_name)) {647enabled_device_extension_names.insert(extension_name);648}649}650651free(pRequiredExtensionsData);652free(swappy_required_extensions);653}654}655#endif656657#ifdef DEV_ENABLED658for (uint32_t i = 0; i < device_extension_count; i++) {659print_verbose(String("VULKAN: Found device extension ") + String::utf8(device_extensions[i].extensionName));660}661#endif662663// Enable all extensions that are supported and requested.664for (uint32_t i = 0; i < device_extension_count; i++) {665CharString extension_name(device_extensions[i].extensionName);666if (requested_device_extensions.has(extension_name)) {667enabled_device_extension_names.insert(extension_name);668}669}670671// Now check our requested extensions.672for (KeyValue<CharString, bool> &requested_extension : requested_device_extensions) {673if (!enabled_device_extension_names.has(requested_extension.key)) {674if (requested_extension.value) {675ERR_FAIL_V_MSG(ERR_BUG, String("Required extension ") + String::utf8(requested_extension.key) + String(" not found."));676} else {677print_verbose(String("Optional extension ") + String::utf8(requested_extension.key) + String(" not found"));678}679}680}681682return OK;683}684685Error RenderingDeviceDriverVulkan::_check_device_features() {686vkGetPhysicalDeviceFeatures(physical_device, &physical_device_features);687688// Check for required features.689if (!physical_device_features.imageCubeArray || !physical_device_features.independentBlend) {690String error_string = vformat("Your GPU (%s) does not support the following features which are required to use Vulkan-based renderers in Godot:\n\n", context_device.name);691if (!physical_device_features.imageCubeArray) {692error_string += "- No support for image cube arrays.\n";693}694if (!physical_device_features.independentBlend) {695error_string += "- No support for independentBlend.\n";696}697error_string += "\nThis is usually a hardware limitation, so updating graphics drivers won't help in most cases.";698699#if defined(ANDROID_ENABLED) || defined(IOS_ENABLED)700// Android/iOS platform ports currently don't exit themselves when this method returns `ERR_CANT_CREATE`.701OS::get_singleton()->alert(error_string + "\nClick OK to exit (black screen will be visible).");702#else703OS::get_singleton()->alert(error_string + "\nClick OK to exit.");704#endif705706return ERR_CANT_CREATE;707}708709// Opt-in to the features we actually need/use. These can be changed in the future.710// We do this for multiple reasons:711//712// 1. Certain features (like sparse* stuff) cause unnecessary internal driver allocations.713// 2. Others like shaderStorageImageMultisample are a huge red flag714// (MSAA + Storage is rarely needed).715// 3. Most features when turned off aren't actually off (we just promise the driver not to use them)716// and it is validation what will complain. This allows us to target a minimum baseline.717//718// TODO: Allow the user to override these settings (i.e. turn off more stuff) using profiles719// so they can target a broad range of HW. For example Mali HW does not have720// shaderClipDistance/shaderCullDistance; thus validation would complain if such feature is used;721// allowing them to fix the problem without even owning Mali HW to test on.722//723// The excluded features are:724// - robustBufferAccess (can hamper performance on some hardware)725// - occlusionQueryPrecise726// - pipelineStatisticsQuery727// - shaderStorageImageMultisample (unsupported by Intel Arc, prevents from using MSAA storage accidentally)728// - shaderResourceResidency729// - sparseBinding (we don't use sparse features and enabling them cause extra internal allocations inside the Vulkan driver we don't need)730// - sparseResidencyBuffer731// - sparseResidencyImage2D732// - sparseResidencyImage3D733// - sparseResidency2Samples734// - sparseResidency4Samples735// - sparseResidency8Samples736// - sparseResidency16Samples737// - sparseResidencyAliased738// - inheritedQueries739740#define VK_DEVICEFEATURE_ENABLE_IF(x) \741if (physical_device_features.x) { \742requested_device_features.x = physical_device_features.x; \743} else \744((void)0)745746requested_device_features = {};747VK_DEVICEFEATURE_ENABLE_IF(fullDrawIndexUint32);748VK_DEVICEFEATURE_ENABLE_IF(imageCubeArray);749VK_DEVICEFEATURE_ENABLE_IF(independentBlend);750VK_DEVICEFEATURE_ENABLE_IF(geometryShader);751VK_DEVICEFEATURE_ENABLE_IF(tessellationShader);752VK_DEVICEFEATURE_ENABLE_IF(sampleRateShading);753VK_DEVICEFEATURE_ENABLE_IF(dualSrcBlend);754VK_DEVICEFEATURE_ENABLE_IF(logicOp);755VK_DEVICEFEATURE_ENABLE_IF(multiDrawIndirect);756VK_DEVICEFEATURE_ENABLE_IF(drawIndirectFirstInstance);757VK_DEVICEFEATURE_ENABLE_IF(depthClamp);758VK_DEVICEFEATURE_ENABLE_IF(depthBiasClamp);759VK_DEVICEFEATURE_ENABLE_IF(fillModeNonSolid);760VK_DEVICEFEATURE_ENABLE_IF(depthBounds);761VK_DEVICEFEATURE_ENABLE_IF(wideLines);762VK_DEVICEFEATURE_ENABLE_IF(largePoints);763VK_DEVICEFEATURE_ENABLE_IF(alphaToOne);764VK_DEVICEFEATURE_ENABLE_IF(multiViewport);765VK_DEVICEFEATURE_ENABLE_IF(samplerAnisotropy);766VK_DEVICEFEATURE_ENABLE_IF(textureCompressionETC2);767VK_DEVICEFEATURE_ENABLE_IF(textureCompressionASTC_LDR);768VK_DEVICEFEATURE_ENABLE_IF(textureCompressionBC);769VK_DEVICEFEATURE_ENABLE_IF(vertexPipelineStoresAndAtomics);770VK_DEVICEFEATURE_ENABLE_IF(fragmentStoresAndAtomics);771VK_DEVICEFEATURE_ENABLE_IF(shaderTessellationAndGeometryPointSize);772VK_DEVICEFEATURE_ENABLE_IF(shaderImageGatherExtended);773VK_DEVICEFEATURE_ENABLE_IF(shaderStorageImageExtendedFormats);774VK_DEVICEFEATURE_ENABLE_IF(shaderStorageImageReadWithoutFormat);775VK_DEVICEFEATURE_ENABLE_IF(shaderStorageImageWriteWithoutFormat);776VK_DEVICEFEATURE_ENABLE_IF(shaderUniformBufferArrayDynamicIndexing);777VK_DEVICEFEATURE_ENABLE_IF(shaderSampledImageArrayDynamicIndexing);778VK_DEVICEFEATURE_ENABLE_IF(shaderStorageBufferArrayDynamicIndexing);779VK_DEVICEFEATURE_ENABLE_IF(shaderStorageImageArrayDynamicIndexing);780VK_DEVICEFEATURE_ENABLE_IF(shaderClipDistance);781VK_DEVICEFEATURE_ENABLE_IF(shaderCullDistance);782VK_DEVICEFEATURE_ENABLE_IF(shaderFloat64);783VK_DEVICEFEATURE_ENABLE_IF(shaderInt64);784VK_DEVICEFEATURE_ENABLE_IF(shaderInt16);785VK_DEVICEFEATURE_ENABLE_IF(shaderResourceMinLod);786VK_DEVICEFEATURE_ENABLE_IF(variableMultisampleRate);787788return OK;789}790791static uint32_t _align_up(uint32_t size, uint32_t alignment) {792return (size + (alignment - 1)) & ~(alignment - 1);793}794795Error RenderingDeviceDriverVulkan::_check_device_capabilities() {796// Fill device family and version.797device_capabilities.device_family = DEVICE_VULKAN;798device_capabilities.version_major = VK_API_VERSION_MAJOR(physical_device_properties.apiVersion);799device_capabilities.version_minor = VK_API_VERSION_MINOR(physical_device_properties.apiVersion);800801// Cache extension availability we query often.802framebuffer_depth_resolve = enabled_device_extension_names.has(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);803804bool use_fdm_offsets = false;805if (VulkanHooks::get_singleton() != nullptr) {806use_fdm_offsets = VulkanHooks::get_singleton()->use_fragment_density_offsets();807}808809// References:810// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_KHR_multiview.html811// https://www.khronos.org/blog/vulkan-subgroup-tutorial812const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get();813if (functions.GetPhysicalDeviceFeatures2 != nullptr) {814// We must check that the corresponding extension is present before assuming a feature as enabled.815// See also: https://github.com/godotengine/godot/issues/65409816817void *next_features = nullptr;818VkPhysicalDeviceVulkan12Features device_features_vk_1_2 = {};819VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = {};820VkPhysicalDeviceBufferDeviceAddressFeaturesKHR buffer_device_address_features = {};821VkPhysicalDeviceVulkanMemoryModelFeaturesKHR vulkan_memory_model_features = {};822VkPhysicalDeviceFragmentShadingRateFeaturesKHR fsr_features = {};823VkPhysicalDeviceFragmentDensityMapFeaturesEXT fdm_features = {};824VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM fdmo_features_qcom = {};825VkPhysicalDevice16BitStorageFeaturesKHR storage_feature = {};826VkPhysicalDeviceMultiviewFeatures multiview_features = {};827VkPhysicalDevicePipelineCreationCacheControlFeatures pipeline_cache_control_features = {};828VkPhysicalDeviceVulkanMemoryModelFeatures memory_model_features = {};829VkPhysicalDeviceAccelerationStructureFeaturesKHR acceleration_structure_features = {};830VkPhysicalDeviceRayTracingPipelineFeaturesKHR raytracing_pipeline_features = {};831VkPhysicalDeviceSynchronization2FeaturesKHR sync_2_features = {};832VkPhysicalDeviceRayTracingValidationFeaturesNV raytracing_validation_features = {};833834const bool use_1_2_features = physical_device_properties.apiVersion >= VK_API_VERSION_1_2;835if (use_1_2_features) {836device_features_vk_1_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;837device_features_vk_1_2.pNext = next_features;838next_features = &device_features_vk_1_2;839} else {840if (enabled_device_extension_names.has(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) {841shader_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR;842shader_features.pNext = next_features;843next_features = &shader_features;844}845if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {846buffer_device_address_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR;847buffer_device_address_features.pNext = next_features;848next_features = &buffer_device_address_features;849}850if (enabled_device_extension_names.has(VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME)) {851vulkan_memory_model_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR;852vulkan_memory_model_features.pNext = next_features;853next_features = &vulkan_memory_model_features;854}855}856857if (enabled_device_extension_names.has(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) {858fsr_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR;859fsr_features.pNext = next_features;860next_features = &fsr_features;861}862863if (enabled_device_extension_names.has(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME)) {864fdm_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT;865fdm_features.pNext = next_features;866next_features = &fdm_features;867}868869if (use_fdm_offsets && enabled_device_extension_names.has(VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME)) {870fdmo_features_qcom.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM;871fdmo_features_qcom.pNext = next_features;872next_features = &fdmo_features_qcom;873}874875if (enabled_device_extension_names.has(VK_KHR_16BIT_STORAGE_EXTENSION_NAME)) {876storage_feature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR;877storage_feature.pNext = next_features;878next_features = &storage_feature;879}880881if (enabled_device_extension_names.has(VK_KHR_MULTIVIEW_EXTENSION_NAME)) {882multiview_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;883multiview_features.pNext = next_features;884next_features = &multiview_features;885}886887if (enabled_device_extension_names.has(VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME)) {888pipeline_cache_control_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES;889pipeline_cache_control_features.pNext = next_features;890next_features = &pipeline_cache_control_features;891}892893if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {894memory_model_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES;895memory_model_features.pNext = next_features;896next_features = &memory_model_features;897}898899if (enabled_device_extension_names.has(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME)) {900acceleration_structure_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;901acceleration_structure_features.pNext = next_features;902next_features = &acceleration_structure_features;903}904905if (enabled_device_extension_names.has(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME)) {906raytracing_pipeline_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR;907raytracing_pipeline_features.pNext = next_features;908next_features = &raytracing_pipeline_features;909}910911if (enabled_device_extension_names.has(VK_NV_RAY_TRACING_VALIDATION_EXTENSION_NAME)) {912raytracing_validation_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_VALIDATION_FEATURES_NV;913raytracing_validation_features.pNext = next_features;914next_features = &raytracing_validation_features;915}916917if (enabled_device_extension_names.has(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME)) {918sync_2_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES;919sync_2_features.pNext = next_features;920next_features = &sync_2_features;921}922923VkPhysicalDeviceFeatures2 device_features_2 = {};924device_features_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;925device_features_2.pNext = next_features;926functions.GetPhysicalDeviceFeatures2(physical_device, &device_features_2);927928if (use_1_2_features) {929#ifdef MACOS_ENABLED930ERR_FAIL_COND_V_MSG(!device_features_vk_1_2.shaderSampledImageArrayNonUniformIndexing, ERR_CANT_CREATE, "Your GPU doesn't support shaderSampledImageArrayNonUniformIndexing which is required to use the Vulkan-based renderers in Godot.");931#endif932if (enabled_device_extension_names.has(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) {933shader_capabilities.shader_float16_is_supported = device_features_vk_1_2.shaderFloat16;934shader_capabilities.shader_int8_is_supported = device_features_vk_1_2.shaderInt8;935}936if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {937buffer_device_address_support = device_features_vk_1_2.bufferDeviceAddress;938}939if (enabled_device_extension_names.has(VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME)) {940vulkan_memory_model_support = device_features_vk_1_2.vulkanMemoryModel;941vulkan_memory_model_device_scope_support = device_features_vk_1_2.vulkanMemoryModelDeviceScope;942}943} else {944if (enabled_device_extension_names.has(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) {945shader_capabilities.shader_float16_is_supported = shader_features.shaderFloat16;946shader_capabilities.shader_int8_is_supported = shader_features.shaderInt8;947}948if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {949buffer_device_address_support = buffer_device_address_features.bufferDeviceAddress;950}951if (enabled_device_extension_names.has(VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME)) {952vulkan_memory_model_support = vulkan_memory_model_features.vulkanMemoryModel;953vulkan_memory_model_device_scope_support = vulkan_memory_model_features.vulkanMemoryModelDeviceScope;954}955}956957if (enabled_device_extension_names.has(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) {958fsr_capabilities.pipeline_supported = fsr_features.pipelineFragmentShadingRate;959fsr_capabilities.primitive_supported = fsr_features.primitiveFragmentShadingRate;960fsr_capabilities.attachment_supported = fsr_features.attachmentFragmentShadingRate;961}962963if (enabled_device_extension_names.has(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME)) {964fdm_capabilities.attachment_supported = fdm_features.fragmentDensityMap;965fdm_capabilities.dynamic_attachment_supported = fdm_features.fragmentDensityMapDynamic;966fdm_capabilities.non_subsampled_images_supported = fdm_features.fragmentDensityMapNonSubsampledImages;967}968969if (enabled_device_extension_names.has(VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME)) {970fdm_capabilities.offset_supported = fdmo_features_qcom.fragmentDensityMapOffset;971}972973// Multiple VRS techniques can't co-exist during the existence of one device, so we must974// choose one at creation time and only report one of them as available.975_choose_vrs_capabilities();976977if (enabled_device_extension_names.has(VK_KHR_MULTIVIEW_EXTENSION_NAME)) {978multiview_capabilities.is_supported = multiview_features.multiview;979multiview_capabilities.geometry_shader_is_supported = multiview_features.multiviewGeometryShader;980multiview_capabilities.tessellation_shader_is_supported = multiview_features.multiviewTessellationShader;981}982983if (enabled_device_extension_names.has(VK_KHR_16BIT_STORAGE_EXTENSION_NAME)) {984storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported = storage_feature.storageBuffer16BitAccess;985storage_buffer_capabilities.uniform_and_storage_buffer_16_bit_access_is_supported = storage_feature.uniformAndStorageBuffer16BitAccess;986storage_buffer_capabilities.storage_push_constant_16_is_supported = storage_feature.storagePushConstant16;987storage_buffer_capabilities.storage_input_output_16 = storage_feature.storageInputOutput16;988}989990if (enabled_device_extension_names.has(VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME)) {991pipeline_cache_control_support = pipeline_cache_control_features.pipelineCreationCacheControl;992}993994if (enabled_device_extension_names.has(VK_EXT_DEVICE_FAULT_EXTENSION_NAME)) {995device_fault_support = true;996}997#if defined(VK_TRACK_DEVICE_MEMORY)998if (enabled_device_extension_names.has(VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME)) {999device_memory_report_support = true;1000}1001#endif10021003if (enabled_device_extension_names.has(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME)) {1004acceleration_structure_capabilities.acceleration_structure_support = acceleration_structure_features.accelerationStructure;1005}10061007if (enabled_device_extension_names.has(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME)) {1008raytracing_capabilities.raytracing_pipeline_support = raytracing_pipeline_features.rayTracingPipeline;1009raytracing_capabilities.validation = raytracing_validation_features.rayTracingValidation;1010}1011}10121013if (functions.GetPhysicalDeviceProperties2 != nullptr) {1014void *next_properties = nullptr;1015VkPhysicalDeviceFragmentShadingRatePropertiesKHR fsr_properties = {};1016VkPhysicalDeviceFragmentDensityMapPropertiesEXT fdm_properties = {};1017VkPhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM fdmo_properties = {};1018VkPhysicalDeviceMultiviewProperties multiview_properties = {};1019VkPhysicalDeviceSubgroupProperties subgroup_properties = {};1020VkPhysicalDeviceSubgroupSizeControlProperties subgroup_size_control_properties = {};1021VkPhysicalDeviceAccelerationStructurePropertiesKHR acceleration_structure_properties = {};1022VkPhysicalDeviceRayTracingPipelinePropertiesKHR raytracing_properties = {};1023VkPhysicalDeviceProperties2 physical_device_properties_2 = {};10241025const bool use_1_1_properties = physical_device_properties.apiVersion >= VK_API_VERSION_1_1;1026if (use_1_1_properties) {1027subgroup_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;1028subgroup_properties.pNext = next_properties;1029next_properties = &subgroup_properties;10301031subgroup_capabilities.size_control_is_supported = enabled_device_extension_names.has(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME);1032if (subgroup_capabilities.size_control_is_supported) {1033subgroup_size_control_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES;1034subgroup_size_control_properties.pNext = next_properties;1035next_properties = &subgroup_size_control_properties;1036}1037}10381039if (multiview_capabilities.is_supported) {1040multiview_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES;1041multiview_properties.pNext = next_properties;1042next_properties = &multiview_properties;1043}10441045if (fsr_capabilities.attachment_supported) {1046fsr_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR;1047fsr_properties.pNext = next_properties;1048next_properties = &fsr_properties;1049}10501051if (fdm_capabilities.attachment_supported) {1052fdm_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT;1053fdm_properties.pNext = next_properties;1054next_properties = &fdm_properties;1055}10561057if (fdm_capabilities.offset_supported) {1058fdmo_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM;1059fdmo_properties.pNext = next_properties;1060next_properties = &fdmo_properties;1061}10621063if (acceleration_structure_capabilities.acceleration_structure_support) {1064acceleration_structure_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR;1065acceleration_structure_properties.pNext = next_properties;1066next_properties = &acceleration_structure_properties;1067}10681069if (raytracing_capabilities.raytracing_pipeline_support) {1070raytracing_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;1071raytracing_properties.pNext = next_properties;1072next_properties = &raytracing_properties;1073}10741075physical_device_properties_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;1076physical_device_properties_2.pNext = next_properties;1077functions.GetPhysicalDeviceProperties2(physical_device, &physical_device_properties_2);10781079subgroup_capabilities.size = subgroup_properties.subgroupSize;1080subgroup_capabilities.min_size = subgroup_properties.subgroupSize;1081subgroup_capabilities.max_size = subgroup_properties.subgroupSize;1082subgroup_capabilities.supported_stages = subgroup_properties.supportedStages;1083subgroup_capabilities.supported_operations = subgroup_properties.supportedOperations;10841085// Note: quadOperationsInAllStages will be true if:1086// - supportedStages has VK_SHADER_STAGE_ALL_GRAPHICS + VK_SHADER_STAGE_COMPUTE_BIT.1087// - supportedOperations has VK_SUBGROUP_FEATURE_QUAD_BIT.1088subgroup_capabilities.quad_operations_in_all_stages = subgroup_properties.quadOperationsInAllStages;10891090if (subgroup_capabilities.size_control_is_supported && (subgroup_size_control_properties.requiredSubgroupSizeStages & VK_SHADER_STAGE_COMPUTE_BIT)) {1091subgroup_capabilities.min_size = subgroup_size_control_properties.minSubgroupSize;1092subgroup_capabilities.max_size = subgroup_size_control_properties.maxSubgroupSize;1093}10941095if (fsr_capabilities.pipeline_supported || fsr_capabilities.primitive_supported || fsr_capabilities.attachment_supported) {1096print_verbose("- Vulkan Fragment Shading Rate supported:");1097if (fsr_capabilities.pipeline_supported) {1098print_verbose(" Pipeline fragment shading rate");1099}1100if (fsr_capabilities.primitive_supported) {1101print_verbose(" Primitive fragment shading rate");1102}1103if (fsr_capabilities.attachment_supported) {1104// TODO: Expose these somehow to the end user.1105fsr_capabilities.min_texel_size.x = fsr_properties.minFragmentShadingRateAttachmentTexelSize.width;1106fsr_capabilities.min_texel_size.y = fsr_properties.minFragmentShadingRateAttachmentTexelSize.height;1107fsr_capabilities.max_texel_size.x = fsr_properties.maxFragmentShadingRateAttachmentTexelSize.width;1108fsr_capabilities.max_texel_size.y = fsr_properties.maxFragmentShadingRateAttachmentTexelSize.height;1109fsr_capabilities.max_fragment_size.x = fsr_properties.maxFragmentSize.width; // either 4 or 81110fsr_capabilities.max_fragment_size.y = fsr_properties.maxFragmentSize.height; // generally the same as width11111112print_verbose(String(" Attachment fragment shading rate") +1113String(", min texel size: (") + itos(fsr_capabilities.min_texel_size.x) + String(", ") + itos(fsr_capabilities.min_texel_size.y) + String(")") +1114String(", max texel size: (") + itos(fsr_capabilities.max_texel_size.x) + String(", ") + itos(fsr_capabilities.max_texel_size.y) + String(")") +1115String(", max fragment size: (") + itos(fsr_capabilities.max_fragment_size.x) + String(", ") + itos(fsr_capabilities.max_fragment_size.y) + String(")"));1116}11171118} else {1119print_verbose("- Vulkan Variable Rate Shading not supported");1120}11211122if (fdm_capabilities.attachment_supported || fdm_capabilities.dynamic_attachment_supported || fdm_capabilities.non_subsampled_images_supported) {1123fdm_capabilities.min_texel_size.x = fdm_properties.minFragmentDensityTexelSize.width;1124fdm_capabilities.min_texel_size.y = fdm_properties.minFragmentDensityTexelSize.height;1125fdm_capabilities.max_texel_size.x = fdm_properties.maxFragmentDensityTexelSize.width;1126fdm_capabilities.max_texel_size.y = fdm_properties.maxFragmentDensityTexelSize.height;1127fdm_capabilities.invocations_supported = fdm_properties.fragmentDensityInvocations;11281129print_verbose(String("- Vulkan Fragment Density Map supported") +1130String(", min texel size: (") + itos(fdm_capabilities.min_texel_size.x) + String(", ") + itos(fdm_capabilities.min_texel_size.y) + String(")") +1131String(", max texel size: (") + itos(fdm_capabilities.max_texel_size.x) + String(", ") + itos(fdm_capabilities.max_texel_size.y) + String(")"));11321133if (fdm_capabilities.dynamic_attachment_supported) {1134print_verbose(" - dynamic fragment density map supported");1135}11361137if (fdm_capabilities.non_subsampled_images_supported) {1138print_verbose(" - non-subsampled images supported");1139}1140} else {1141print_verbose("- Vulkan Fragment Density Map not supported");1142}11431144if (fdm_capabilities.offset_supported) {1145print_verbose("- Vulkan Fragment Density Map Offset supported");11461147fdm_capabilities.offset_granularity.x = fdmo_properties.fragmentDensityOffsetGranularity.width;1148fdm_capabilities.offset_granularity.y = fdmo_properties.fragmentDensityOffsetGranularity.height;11491150print_verbose(vformat(" Offset granularity: (%d, %d)", fdm_capabilities.offset_granularity.x, fdm_capabilities.offset_granularity.y));1151} else if (use_fdm_offsets) {1152print_verbose("- Vulkan Fragment Density Map Offset not supported");1153}11541155if (multiview_capabilities.is_supported) {1156multiview_capabilities.max_view_count = multiview_properties.maxMultiviewViewCount;1157multiview_capabilities.max_instance_count = multiview_properties.maxMultiviewInstanceIndex;11581159print_verbose("- Vulkan multiview supported:");1160print_verbose(" max view count: " + itos(multiview_capabilities.max_view_count));1161print_verbose(" max instances: " + itos(multiview_capabilities.max_instance_count));1162} else {1163print_verbose("- Vulkan multiview not supported");1164}11651166print_verbose("- Vulkan subgroup:");1167print_verbose(" size: " + itos(subgroup_capabilities.size));1168print_verbose(" min size: " + itos(subgroup_capabilities.min_size));1169print_verbose(" max size: " + itos(subgroup_capabilities.max_size));1170print_verbose(" stages: " + subgroup_capabilities.supported_stages_desc());1171print_verbose(" supported ops: " + subgroup_capabilities.supported_operations_desc());1172if (subgroup_capabilities.quad_operations_in_all_stages) {1173print_verbose(" quad operations in all stages");1174}11751176if (acceleration_structure_capabilities.acceleration_structure_support) {1177print_verbose("- Vulkan Acceleration Structure supported");1178acceleration_structure_capabilities.min_acceleration_structure_scratch_offset_alignment = acceleration_structure_properties.minAccelerationStructureScratchOffsetAlignment;1179print_verbose(" min acceleration structure scratch offset alignment: " + itos(acceleration_structure_capabilities.min_acceleration_structure_scratch_offset_alignment));1180} else {1181print_verbose("- Vulkan Acceleration Structure not supported");1182}11831184if (raytracing_capabilities.raytracing_pipeline_support) {1185raytracing_capabilities.shader_group_handle_size = raytracing_properties.shaderGroupHandleSize;1186raytracing_capabilities.shader_group_handle_alignment = raytracing_properties.shaderGroupHandleAlignment;1187raytracing_capabilities.shader_group_handle_size_aligned = _align_up(raytracing_capabilities.shader_group_handle_size, raytracing_capabilities.shader_group_handle_alignment);1188raytracing_capabilities.shader_group_base_alignment = raytracing_properties.shaderGroupBaseAlignment;11891190print_verbose("- Vulkan Raytracing supported");1191print_verbose(" shader group handle size: " + itos(raytracing_capabilities.shader_group_handle_size));1192print_verbose(" shader group handle alignment: " + itos(raytracing_capabilities.shader_group_handle_alignment));1193print_verbose(" shader group handle size aligned: " + itos(raytracing_capabilities.shader_group_handle_size_aligned));1194print_verbose(" shader group base alignment: " + itos(raytracing_capabilities.shader_group_base_alignment));1195} else {1196print_verbose("- Vulkan Raytracing not supported");1197}1198}11991200return OK;1201}12021203void RenderingDeviceDriverVulkan::_choose_vrs_capabilities() {1204bool prefer_fdm_on_qualcomm = physical_device_properties.vendorID == RenderingContextDriver::Vendor::VENDOR_QUALCOMM;1205if (fdm_capabilities.attachment_supported && (!fsr_capabilities.attachment_supported || prefer_fdm_on_qualcomm)) {1206// If available, we prefer using fragment density maps on Qualcomm as they adjust tile distribution when using1207// this technique. Performance as a result is higher than when using fragment shading rate.1208fsr_capabilities = FragmentShadingRateCapabilities();1209} else if (fsr_capabilities.attachment_supported) {1210// Disable any possibility of fragment density maps being used.1211fdm_capabilities = FragmentDensityMapCapabilities();1212} else {1213// Do not report or enable any VRS capabilities if attachment is not supported.1214fsr_capabilities = FragmentShadingRateCapabilities();1215fdm_capabilities = FragmentDensityMapCapabilities();1216}1217}12181219Error RenderingDeviceDriverVulkan::_add_queue_create_info(LocalVector<VkDeviceQueueCreateInfo> &r_queue_create_info) {1220uint32_t queue_family_count = queue_family_properties.size();1221queue_families.resize(queue_family_count);12221223VkQueueFlags queue_flags_mask = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT;1224const uint32_t max_queue_count_per_family = 1;1225static const float queue_priorities[max_queue_count_per_family] = {};1226for (uint32_t i = 0; i < queue_family_count; i++) {1227if ((queue_family_properties[i].queueFlags & queue_flags_mask) == 0) {1228// We ignore creating queues in families that don't support any of the operations we require.1229continue;1230}12311232VkDeviceQueueCreateInfo create_info = {};1233create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;1234create_info.queueFamilyIndex = i;1235create_info.queueCount = MIN(queue_family_properties[i].queueCount, max_queue_count_per_family);1236create_info.pQueuePriorities = queue_priorities;1237r_queue_create_info.push_back(create_info);12381239// Prepare the vectors where the queues will be filled out.1240queue_families[i].resize(create_info.queueCount);1241}12421243return OK;1244}12451246Error RenderingDeviceDriverVulkan::_initialize_device(const LocalVector<VkDeviceQueueCreateInfo> &p_queue_create_info) {1247TightLocalVector<const char *> enabled_extension_names;1248enabled_extension_names.reserve(enabled_device_extension_names.size());1249for (const CharString &extension_name : enabled_device_extension_names) {1250enabled_extension_names.push_back(extension_name.ptr());1251}12521253void *create_info_next = nullptr;1254VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = {};1255shader_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR;1256shader_features.pNext = create_info_next;1257shader_features.shaderFloat16 = shader_capabilities.shader_float16_is_supported;1258shader_features.shaderInt8 = shader_capabilities.shader_int8_is_supported;1259create_info_next = &shader_features;12601261VkPhysicalDeviceBufferDeviceAddressFeaturesKHR buffer_device_address_features = {};1262if (buffer_device_address_support) {1263buffer_device_address_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR;1264buffer_device_address_features.pNext = create_info_next;1265buffer_device_address_features.bufferDeviceAddress = buffer_device_address_support;1266create_info_next = &buffer_device_address_features;1267}12681269VkPhysicalDeviceVulkanMemoryModelFeaturesKHR vulkan_memory_model_features = {};1270if (vulkan_memory_model_support && vulkan_memory_model_device_scope_support) {1271vulkan_memory_model_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR;1272vulkan_memory_model_features.pNext = create_info_next;1273vulkan_memory_model_features.vulkanMemoryModel = vulkan_memory_model_support;1274vulkan_memory_model_features.vulkanMemoryModelDeviceScope = vulkan_memory_model_device_scope_support;1275create_info_next = &vulkan_memory_model_features;1276}12771278VkPhysicalDeviceFragmentShadingRateFeaturesKHR fsr_features = {};1279if (fsr_capabilities.pipeline_supported || fsr_capabilities.primitive_supported || fsr_capabilities.attachment_supported) {1280fsr_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR;1281fsr_features.pNext = create_info_next;1282fsr_features.pipelineFragmentShadingRate = fsr_capabilities.pipeline_supported;1283fsr_features.primitiveFragmentShadingRate = fsr_capabilities.primitive_supported;1284fsr_features.attachmentFragmentShadingRate = fsr_capabilities.attachment_supported;1285create_info_next = &fsr_features;1286}12871288VkPhysicalDeviceFragmentDensityMapFeaturesEXT fdm_features = {};1289if (fdm_capabilities.attachment_supported || fdm_capabilities.dynamic_attachment_supported || fdm_capabilities.non_subsampled_images_supported) {1290fdm_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT;1291fdm_features.pNext = create_info_next;1292fdm_features.fragmentDensityMap = fdm_capabilities.attachment_supported;1293fdm_features.fragmentDensityMapDynamic = fdm_capabilities.dynamic_attachment_supported;1294fdm_features.fragmentDensityMapNonSubsampledImages = fdm_capabilities.non_subsampled_images_supported;1295create_info_next = &fdm_features;1296}12971298VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM fdm_offset_features = {};1299if (fdm_capabilities.offset_supported) {1300fdm_offset_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM;1301fdm_offset_features.pNext = create_info_next;1302fdm_offset_features.fragmentDensityMapOffset = VK_TRUE;1303create_info_next = &fdm_offset_features;1304}13051306VkPhysicalDevicePipelineCreationCacheControlFeatures pipeline_cache_control_features = {};1307if (pipeline_cache_control_support) {1308pipeline_cache_control_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES;1309pipeline_cache_control_features.pNext = create_info_next;1310pipeline_cache_control_features.pipelineCreationCacheControl = pipeline_cache_control_support;1311create_info_next = &pipeline_cache_control_features;1312}13131314VkPhysicalDeviceFaultFeaturesEXT device_fault_features = {};1315if (device_fault_support) {1316device_fault_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT;1317device_fault_features.pNext = create_info_next;1318create_info_next = &device_fault_features;1319}13201321#if defined(VK_TRACK_DEVICE_MEMORY)1322VkDeviceDeviceMemoryReportCreateInfoEXT memory_report_info = {};1323if (device_memory_report_support) {1324memory_report_info.sType = VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT;1325memory_report_info.pfnUserCallback = RenderingContextDriverVulkan::memory_report_callback;1326memory_report_info.pNext = create_info_next;1327memory_report_info.flags = 0;1328memory_report_info.pUserData = this;13291330create_info_next = &memory_report_info;1331}1332#endif13331334VkPhysicalDeviceAccelerationStructureFeaturesKHR acceleration_structure_features = {};1335if (acceleration_structure_capabilities.acceleration_structure_support) {1336acceleration_structure_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;1337acceleration_structure_features.pNext = create_info_next;1338acceleration_structure_features.accelerationStructure = acceleration_structure_capabilities.acceleration_structure_support;1339create_info_next = &acceleration_structure_features;1340}13411342VkPhysicalDeviceRayTracingPipelineFeaturesKHR raytracing_pipeline_features = {};1343if (raytracing_capabilities.raytracing_pipeline_support) {1344raytracing_pipeline_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR;1345raytracing_pipeline_features.pNext = create_info_next;1346raytracing_pipeline_features.rayTracingPipeline = raytracing_capabilities.raytracing_pipeline_support;1347create_info_next = &raytracing_pipeline_features;1348}13491350VkPhysicalDeviceRayTracingValidationFeaturesNV raytracing_validation_features = {};1351if (raytracing_capabilities.validation) {1352raytracing_validation_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_VALIDATION_FEATURES_NV;1353raytracing_validation_features.pNext = create_info_next;1354raytracing_validation_features.rayTracingValidation = raytracing_capabilities.validation;1355create_info_next = &raytracing_validation_features;1356}13571358VkPhysicalDeviceVulkan11Features vulkan_1_1_features = {};1359VkPhysicalDevice16BitStorageFeaturesKHR storage_features = {};1360VkPhysicalDeviceMultiviewFeatures multiview_features = {};1361const bool enable_1_2_features = physical_device_properties.apiVersion >= VK_API_VERSION_1_2;1362if (enable_1_2_features) {1363// In Vulkan 1.2 and newer we use a newer struct to enable various features.1364vulkan_1_1_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;1365vulkan_1_1_features.pNext = create_info_next;1366vulkan_1_1_features.storageBuffer16BitAccess = storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported;1367vulkan_1_1_features.uniformAndStorageBuffer16BitAccess = storage_buffer_capabilities.uniform_and_storage_buffer_16_bit_access_is_supported;1368vulkan_1_1_features.storagePushConstant16 = storage_buffer_capabilities.storage_push_constant_16_is_supported;1369vulkan_1_1_features.storageInputOutput16 = storage_buffer_capabilities.storage_input_output_16;1370vulkan_1_1_features.multiview = multiview_capabilities.is_supported;1371vulkan_1_1_features.multiviewGeometryShader = multiview_capabilities.geometry_shader_is_supported;1372vulkan_1_1_features.multiviewTessellationShader = multiview_capabilities.tessellation_shader_is_supported;1373vulkan_1_1_features.variablePointersStorageBuffer = 0;1374vulkan_1_1_features.variablePointers = 0;1375vulkan_1_1_features.protectedMemory = 0;1376vulkan_1_1_features.samplerYcbcrConversion = 0;1377vulkan_1_1_features.shaderDrawParameters = 0;1378create_info_next = &vulkan_1_1_features;1379} else {1380// On Vulkan 1.0 and 1.1 we use our older structs to initialize these features.1381storage_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR;1382storage_features.pNext = create_info_next;1383storage_features.storageBuffer16BitAccess = storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported;1384storage_features.uniformAndStorageBuffer16BitAccess = storage_buffer_capabilities.uniform_and_storage_buffer_16_bit_access_is_supported;1385storage_features.storagePushConstant16 = storage_buffer_capabilities.storage_push_constant_16_is_supported;1386storage_features.storageInputOutput16 = storage_buffer_capabilities.storage_input_output_16;1387create_info_next = &storage_features;13881389const bool enable_1_1_features = physical_device_properties.apiVersion >= VK_API_VERSION_1_1;1390if (enable_1_1_features) {1391multiview_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;1392multiview_features.pNext = create_info_next;1393multiview_features.multiview = multiview_capabilities.is_supported;1394multiview_features.multiviewGeometryShader = multiview_capabilities.geometry_shader_is_supported;1395multiview_features.multiviewTessellationShader = multiview_capabilities.tessellation_shader_is_supported;1396create_info_next = &multiview_features;1397}1398}13991400VkDeviceCreateInfo create_info = {};1401create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;1402create_info.pNext = create_info_next;1403create_info.queueCreateInfoCount = p_queue_create_info.size();1404create_info.pQueueCreateInfos = p_queue_create_info.ptr();1405create_info.enabledExtensionCount = enabled_extension_names.size();1406create_info.ppEnabledExtensionNames = enabled_extension_names.ptr();1407create_info.pEnabledFeatures = &requested_device_features;14081409if (VulkanHooks::get_singleton() != nullptr) {1410bool device_created = VulkanHooks::get_singleton()->create_vulkan_device(&create_info, &vk_device);1411ERR_FAIL_COND_V(!device_created, ERR_CANT_CREATE);1412} else {1413VkResult err = vkCreateDevice(physical_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DEVICE), &vk_device);1414ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);1415}14161417for (uint32_t i = 0; i < queue_families.size(); i++) {1418for (uint32_t j = 0; j < queue_families[i].size(); j++) {1419vkGetDeviceQueue(vk_device, i, j, &queue_families[i][j].queue);1420}1421}14221423const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get();1424if (functions.GetDeviceProcAddr != nullptr) {1425device_functions.CreateSwapchainKHR = PFN_vkCreateSwapchainKHR(functions.GetDeviceProcAddr(vk_device, "vkCreateSwapchainKHR"));1426device_functions.DestroySwapchainKHR = PFN_vkDestroySwapchainKHR(functions.GetDeviceProcAddr(vk_device, "vkDestroySwapchainKHR"));1427device_functions.GetSwapchainImagesKHR = PFN_vkGetSwapchainImagesKHR(functions.GetDeviceProcAddr(vk_device, "vkGetSwapchainImagesKHR"));1428device_functions.AcquireNextImageKHR = PFN_vkAcquireNextImageKHR(functions.GetDeviceProcAddr(vk_device, "vkAcquireNextImageKHR"));1429device_functions.QueuePresentKHR = PFN_vkQueuePresentKHR(functions.GetDeviceProcAddr(vk_device, "vkQueuePresentKHR"));14301431if (enabled_device_extension_names.has(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME)) {1432device_functions.CreateRenderPass2KHR = PFN_vkCreateRenderPass2KHR(functions.GetDeviceProcAddr(vk_device, "vkCreateRenderPass2KHR"));1433device_functions.EndRenderPass2KHR = PFN_vkCmdEndRenderPass2KHR(functions.GetDeviceProcAddr(vk_device, "vkCmdEndRenderPass2KHR"));1434}14351436// Debug marker extensions.1437if (enabled_device_extension_names.has(VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) {1438device_functions.CmdDebugMarkerBeginEXT = (PFN_vkCmdDebugMarkerBeginEXT)functions.GetDeviceProcAddr(vk_device, "vkCmdDebugMarkerBeginEXT");1439device_functions.CmdDebugMarkerEndEXT = (PFN_vkCmdDebugMarkerEndEXT)functions.GetDeviceProcAddr(vk_device, "vkCmdDebugMarkerEndEXT");1440device_functions.CmdDebugMarkerInsertEXT = (PFN_vkCmdDebugMarkerInsertEXT)functions.GetDeviceProcAddr(vk_device, "vkCmdDebugMarkerInsertEXT");1441device_functions.DebugMarkerSetObjectNameEXT = (PFN_vkDebugMarkerSetObjectNameEXT)functions.GetDeviceProcAddr(vk_device, "vkDebugMarkerSetObjectNameEXT");1442}14431444// Debug device fault extension.1445if (device_fault_support) {1446device_functions.GetDeviceFaultInfoEXT = (PFN_vkGetDeviceFaultInfoEXT)functions.GetDeviceProcAddr(vk_device, "vkGetDeviceFaultInfoEXT");1447}14481449// Device raytracing extensions.1450if (enabled_device_extension_names.has(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME)) {1451device_functions.CreateAccelerationStructureKHR = PFN_vkCreateAccelerationStructureKHR(functions.GetDeviceProcAddr(vk_device, "vkCreateAccelerationStructureKHR"));1452}14531454if (enabled_device_extension_names.has(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME)) {1455device_functions.CreateRaytracingPipelinesKHR = PFN_vkCreateRayTracingPipelinesKHR(functions.GetDeviceProcAddr(vk_device, "vkCreateRayTracingPipelinesKHR"));1456}1457}14581459return OK;1460}14611462Error RenderingDeviceDriverVulkan::_initialize_allocator() {1463VmaAllocatorCreateInfo allocator_info = {};1464allocator_info.physicalDevice = physical_device;1465allocator_info.device = vk_device;1466allocator_info.instance = context_driver->instance_get();1467const bool use_1_3_features = physical_device_properties.apiVersion >= VK_API_VERSION_1_3;1468if (use_1_3_features) {1469allocator_info.flags |= VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT;1470}1471if (buffer_device_address_support) {1472allocator_info.flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;1473}1474VkResult err = vmaCreateAllocator(&allocator_info, &allocator);1475ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, "vmaCreateAllocator failed with error " + itos(err) + ".");14761477return OK;1478}14791480Error RenderingDeviceDriverVulkan::_initialize_pipeline_cache() {1481pipelines_cache.buffer.resize(sizeof(PipelineCacheHeader));1482PipelineCacheHeader *header = (PipelineCacheHeader *)(pipelines_cache.buffer.ptrw());1483*header = {};1484header->magic = 868 + VK_PIPELINE_CACHE_HEADER_VERSION_ONE;1485header->device_id = physical_device_properties.deviceID;1486header->vendor_id = physical_device_properties.vendorID;1487header->driver_version = physical_device_properties.driverVersion;1488memcpy(header->uuid, physical_device_properties.pipelineCacheUUID, VK_UUID_SIZE);1489header->driver_abi = sizeof(void *);14901491pipeline_cache_id = String::hex_encode_buffer(physical_device_properties.pipelineCacheUUID, VK_UUID_SIZE);1492pipeline_cache_id += "-driver-" + itos(physical_device_properties.driverVersion);14931494return OK;1495}14961497static void _convert_subpass_attachments(const VkAttachmentReference2 *p_attachment_references_2, uint32_t p_attachment_references_count, TightLocalVector<VkAttachmentReference> &r_attachment_references) {1498r_attachment_references.resize(p_attachment_references_count);1499for (uint32_t i = 0; i < p_attachment_references_count; i++) {1500// Ignore sType, pNext and aspectMask (which is currently unused).1501r_attachment_references[i].attachment = p_attachment_references_2[i].attachment;1502r_attachment_references[i].layout = p_attachment_references_2[i].layout;1503}1504}15051506VkResult RenderingDeviceDriverVulkan::_create_render_pass(VkDevice p_device, const VkRenderPassCreateInfo2 *p_create_info, const VkAllocationCallbacks *p_allocator, VkRenderPass *p_render_pass) {1507if (device_functions.CreateRenderPass2KHR != nullptr) {1508return device_functions.CreateRenderPass2KHR(p_device, p_create_info, p_allocator, p_render_pass);1509} else {1510// Compatibility fallback with regular create render pass but by converting the inputs from the newer version to the older one.1511TightLocalVector<VkAttachmentDescription> attachments;1512attachments.resize(p_create_info->attachmentCount);1513for (uint32_t i = 0; i < p_create_info->attachmentCount; i++) {1514// Ignores sType and pNext from the attachment.1515const VkAttachmentDescription2 &src = p_create_info->pAttachments[i];1516VkAttachmentDescription &dst = attachments[i];1517dst.flags = src.flags;1518dst.format = src.format;1519dst.samples = src.samples;1520dst.loadOp = src.loadOp;1521dst.storeOp = src.storeOp;1522dst.stencilLoadOp = src.stencilLoadOp;1523dst.stencilStoreOp = src.stencilStoreOp;1524dst.initialLayout = src.initialLayout;1525dst.finalLayout = src.finalLayout;1526}15271528const uint32_t attachment_vectors_per_subpass = 4;1529TightLocalVector<TightLocalVector<VkAttachmentReference>> subpasses_attachments;1530TightLocalVector<VkSubpassDescription> subpasses;1531subpasses_attachments.resize(p_create_info->subpassCount * attachment_vectors_per_subpass);1532subpasses.resize(p_create_info->subpassCount);15331534for (uint32_t i = 0; i < p_create_info->subpassCount; i++) {1535const uint32_t vector_base_index = i * attachment_vectors_per_subpass;1536const uint32_t input_attachments_index = vector_base_index + 0;1537const uint32_t color_attachments_index = vector_base_index + 1;1538const uint32_t resolve_attachments_index = vector_base_index + 2;1539const uint32_t depth_attachment_index = vector_base_index + 3;1540_convert_subpass_attachments(p_create_info->pSubpasses[i].pInputAttachments, p_create_info->pSubpasses[i].inputAttachmentCount, subpasses_attachments[input_attachments_index]);1541_convert_subpass_attachments(p_create_info->pSubpasses[i].pColorAttachments, p_create_info->pSubpasses[i].colorAttachmentCount, subpasses_attachments[color_attachments_index]);1542_convert_subpass_attachments(p_create_info->pSubpasses[i].pResolveAttachments, (p_create_info->pSubpasses[i].pResolveAttachments != nullptr) ? p_create_info->pSubpasses[i].colorAttachmentCount : 0, subpasses_attachments[resolve_attachments_index]);1543_convert_subpass_attachments(p_create_info->pSubpasses[i].pDepthStencilAttachment, (p_create_info->pSubpasses[i].pDepthStencilAttachment != nullptr) ? 1 : 0, subpasses_attachments[depth_attachment_index]);15441545// Ignores sType and pNext from the subpass.1546const VkSubpassDescription2 &src_subpass = p_create_info->pSubpasses[i];1547VkSubpassDescription &dst_subpass = subpasses[i];1548dst_subpass.flags = src_subpass.flags;1549dst_subpass.pipelineBindPoint = src_subpass.pipelineBindPoint;1550dst_subpass.inputAttachmentCount = src_subpass.inputAttachmentCount;1551dst_subpass.pInputAttachments = subpasses_attachments[input_attachments_index].ptr();1552dst_subpass.colorAttachmentCount = src_subpass.colorAttachmentCount;1553dst_subpass.pColorAttachments = subpasses_attachments[color_attachments_index].ptr();1554dst_subpass.pResolveAttachments = subpasses_attachments[resolve_attachments_index].ptr();1555dst_subpass.pDepthStencilAttachment = subpasses_attachments[depth_attachment_index].ptr();1556dst_subpass.preserveAttachmentCount = src_subpass.preserveAttachmentCount;1557dst_subpass.pPreserveAttachments = src_subpass.pPreserveAttachments;1558}15591560TightLocalVector<VkSubpassDependency> dependencies;1561dependencies.resize(p_create_info->dependencyCount);15621563for (uint32_t i = 0; i < p_create_info->dependencyCount; i++) {1564// Ignores sType and pNext from the dependency, and viewMask which is currently unused.1565const VkSubpassDependency2 &src_dependency = p_create_info->pDependencies[i];1566VkSubpassDependency &dst_dependency = dependencies[i];1567dst_dependency.srcSubpass = src_dependency.srcSubpass;1568dst_dependency.dstSubpass = src_dependency.dstSubpass;1569dst_dependency.srcStageMask = src_dependency.srcStageMask;1570dst_dependency.dstStageMask = src_dependency.dstStageMask;1571dst_dependency.srcAccessMask = src_dependency.srcAccessMask;1572dst_dependency.dstAccessMask = src_dependency.dstAccessMask;1573dst_dependency.dependencyFlags = src_dependency.dependencyFlags;1574}15751576VkRenderPassCreateInfo create_info = {};1577create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;1578create_info.pNext = p_create_info->pNext;1579create_info.flags = p_create_info->flags;1580create_info.attachmentCount = attachments.size();1581create_info.pAttachments = attachments.ptr();1582create_info.subpassCount = subpasses.size();1583create_info.pSubpasses = subpasses.ptr();1584create_info.dependencyCount = dependencies.size();1585create_info.pDependencies = dependencies.ptr();1586return vkCreateRenderPass(vk_device, &create_info, p_allocator, p_render_pass);1587}1588}15891590bool RenderingDeviceDriverVulkan::_release_image_semaphore(CommandQueue *p_command_queue, uint32_t p_semaphore_index, bool p_release_on_swap_chain) {1591SwapChain *swap_chain = p_command_queue->image_semaphores_swap_chains[p_semaphore_index];1592if (swap_chain != nullptr) {1593// Clear the swap chain from the command queue's vector.1594p_command_queue->image_semaphores_swap_chains[p_semaphore_index] = nullptr;15951596if (p_release_on_swap_chain) {1597// Remove the acquired semaphore from the swap chain's vectors.1598for (uint32_t i = 0; i < swap_chain->command_queues_acquired.size(); i++) {1599if (swap_chain->command_queues_acquired[i] == p_command_queue && swap_chain->command_queues_acquired_semaphores[i] == p_semaphore_index) {1600swap_chain->command_queues_acquired.remove_at(i);1601swap_chain->command_queues_acquired_semaphores.remove_at(i);1602break;1603}1604}1605}16061607return true;1608}16091610return false;1611}16121613bool RenderingDeviceDriverVulkan::_recreate_image_semaphore(CommandQueue *p_command_queue, uint32_t p_semaphore_index, bool p_release_on_swap_chain) {1614_release_image_semaphore(p_command_queue, p_semaphore_index, p_release_on_swap_chain);16151616VkSemaphore semaphore;1617VkSemaphoreCreateInfo create_info = {};1618create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;1619VkResult err = vkCreateSemaphore(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE), &semaphore);1620ERR_FAIL_COND_V(err != VK_SUCCESS, false);16211622// Indicate the semaphore is free again and destroy the previous one before storing the new one.1623vkDestroySemaphore(vk_device, p_command_queue->image_semaphores[p_semaphore_index], VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE));16241625p_command_queue->image_semaphores[p_semaphore_index] = semaphore;1626p_command_queue->free_image_semaphores.push_back(p_semaphore_index);16271628return true;1629}1630// Debug marker extensions.1631VkDebugReportObjectTypeEXT RenderingDeviceDriverVulkan::_convert_to_debug_report_objectType(VkObjectType p_object_type) {1632switch (p_object_type) {1633case VK_OBJECT_TYPE_UNKNOWN:1634return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;1635case VK_OBJECT_TYPE_INSTANCE:1636return VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;1637case VK_OBJECT_TYPE_PHYSICAL_DEVICE:1638return VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT;1639case VK_OBJECT_TYPE_DEVICE:1640return VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT;1641case VK_OBJECT_TYPE_QUEUE:1642return VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT;1643case VK_OBJECT_TYPE_SEMAPHORE:1644return VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT;1645case VK_OBJECT_TYPE_COMMAND_BUFFER:1646return VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT;1647case VK_OBJECT_TYPE_FENCE:1648return VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT;1649case VK_OBJECT_TYPE_DEVICE_MEMORY:1650return VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT;1651case VK_OBJECT_TYPE_BUFFER:1652return VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT;1653case VK_OBJECT_TYPE_IMAGE:1654return VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT;1655case VK_OBJECT_TYPE_EVENT:1656return VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT;1657case VK_OBJECT_TYPE_QUERY_POOL:1658return VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT;1659case VK_OBJECT_TYPE_BUFFER_VIEW:1660return VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT;1661case VK_OBJECT_TYPE_IMAGE_VIEW:1662return VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT;1663case VK_OBJECT_TYPE_SHADER_MODULE:1664return VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT;1665case VK_OBJECT_TYPE_PIPELINE_CACHE:1666return VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT;1667case VK_OBJECT_TYPE_PIPELINE_LAYOUT:1668return VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT;1669case VK_OBJECT_TYPE_RENDER_PASS:1670return VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT;1671case VK_OBJECT_TYPE_PIPELINE:1672return VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT;1673case VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT:1674return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT;1675case VK_OBJECT_TYPE_SAMPLER:1676return VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT;1677case VK_OBJECT_TYPE_DESCRIPTOR_POOL:1678return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT;1679case VK_OBJECT_TYPE_DESCRIPTOR_SET:1680return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT;1681case VK_OBJECT_TYPE_FRAMEBUFFER:1682return VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT;1683case VK_OBJECT_TYPE_COMMAND_POOL:1684return VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT;1685case VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION:1686return VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT;1687case VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE:1688return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT;1689case VK_OBJECT_TYPE_SURFACE_KHR:1690return VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT;1691case VK_OBJECT_TYPE_SWAPCHAIN_KHR:1692return VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT;1693case VK_OBJECT_TYPE_DISPLAY_KHR:1694return VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT;1695case VK_OBJECT_TYPE_DISPLAY_MODE_KHR:1696return VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT;1697case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT:1698return VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT;1699case VK_OBJECT_TYPE_CU_MODULE_NVX:1700return VK_DEBUG_REPORT_OBJECT_TYPE_CU_MODULE_NVX_EXT;1701case VK_OBJECT_TYPE_CU_FUNCTION_NVX:1702return VK_DEBUG_REPORT_OBJECT_TYPE_CU_FUNCTION_NVX_EXT;1703case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR:1704return VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT;1705case VK_OBJECT_TYPE_VALIDATION_CACHE_EXT:1706return VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT;1707case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV:1708return VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT;1709default:1710break;1711}17121713return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;1714}17151716void RenderingDeviceDriverVulkan::_set_object_name(VkObjectType p_object_type, uint64_t p_object_handle, String p_object_name) {1717const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get();1718if (functions.SetDebugUtilsObjectNameEXT != nullptr) {1719CharString obj_data = p_object_name.utf8();1720VkDebugUtilsObjectNameInfoEXT name_info;1721name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;1722name_info.pNext = nullptr;1723name_info.objectType = p_object_type;1724name_info.objectHandle = p_object_handle;1725name_info.pObjectName = obj_data.get_data();1726functions.SetDebugUtilsObjectNameEXT(vk_device, &name_info);1727} else if (functions.DebugMarkerSetObjectNameEXT != nullptr) {1728// Debug marker extensions.1729CharString obj_data = p_object_name.utf8();1730VkDebugMarkerObjectNameInfoEXT name_info;1731name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;1732name_info.pNext = nullptr;1733name_info.objectType = _convert_to_debug_report_objectType(p_object_type);1734name_info.object = p_object_handle;1735name_info.pObjectName = obj_data.get_data();1736functions.DebugMarkerSetObjectNameEXT(vk_device, &name_info);1737}1738}17391740Error RenderingDeviceDriverVulkan::initialize(uint32_t p_device_index, uint32_t p_frame_count) {1741context_device = context_driver->device_get(p_device_index);1742physical_device = context_driver->physical_device_get(p_device_index);1743vkGetPhysicalDeviceProperties(physical_device, &physical_device_properties);17441745// Workaround a driver bug on Adreno 730 GPUs that keeps leaking memory on each call to vkResetDescriptorPool.1746// Which eventually run out of memory. In such case we should not be using linear allocated pools1747// Bug introduced in driver 512.597.0 and fixed in 512.671.0.1748// Confirmed by Qualcomm.1749if (linear_descriptor_pools_enabled) {1750const uint32_t reset_descriptor_pool_broken_driver_begin = VK_MAKE_VERSION(512u, 597u, 0u);1751const uint32_t reset_descriptor_pool_fixed_driver_begin = VK_MAKE_VERSION(512u, 671u, 0u);1752linear_descriptor_pools_enabled = physical_device_properties.driverVersion < reset_descriptor_pool_broken_driver_begin || physical_device_properties.driverVersion > reset_descriptor_pool_fixed_driver_begin;1753}17541755// Workaround a driver bug on Adreno 5XX GPUs that causes a crash when1756// there are empty descriptor set layouts placed between non-empty ones.1757adreno_5xx_empty_descriptor_set_layout_workaround =1758physical_device_properties.vendorID == RenderingContextDriver::Vendor::VENDOR_QUALCOMM &&1759physical_device_properties.deviceID >= 0x5000000 &&1760physical_device_properties.deviceID < 0x6000000;17611762frame_count = p_frame_count;17631764// Copy the queue family properties the context already retrieved.1765uint32_t queue_family_count = context_driver->queue_family_get_count(p_device_index);1766queue_family_properties.resize(queue_family_count);1767for (uint32_t i = 0; i < queue_family_count; i++) {1768queue_family_properties[i] = context_driver->queue_family_get(p_device_index, i);1769}17701771Error err = _initialize_device_extensions();1772ERR_FAIL_COND_V(err != OK, err);17731774err = _check_device_features();1775ERR_FAIL_COND_V(err != OK, err);17761777err = _check_device_capabilities();1778ERR_FAIL_COND_V(err != OK, err);17791780LocalVector<VkDeviceQueueCreateInfo> queue_create_info;1781err = _add_queue_create_info(queue_create_info);1782ERR_FAIL_COND_V(err != OK, err);17831784err = _initialize_device(queue_create_info);1785ERR_FAIL_COND_V(err != OK, err);17861787err = _initialize_allocator();1788ERR_FAIL_COND_V(err != OK, err);17891790err = _initialize_pipeline_cache();1791ERR_FAIL_COND_V(err != OK, err);17921793max_descriptor_sets_per_pool = GLOBAL_GET("rendering/rendering_device/vulkan/max_descriptors_per_pool");17941795#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)1796breadcrumb_buffer = buffer_create(2u * sizeof(uint32_t) * BREADCRUMB_BUFFER_ENTRIES, BufferUsageBits::BUFFER_USAGE_TRANSFER_TO_BIT, MemoryAllocationType::MEMORY_ALLOCATION_TYPE_CPU, UINT64_MAX);1797#endif17981799#if defined(SWAPPY_FRAME_PACING_ENABLED)1800swappy_frame_pacer_enable = GLOBAL_GET("display/window/frame_pacing/android/enable_frame_pacing");1801swappy_mode = GLOBAL_GET("display/window/frame_pacing/android/swappy_mode");18021803if (VulkanHooks::get_singleton() != nullptr) {1804// Hooks control device creation & possibly presentation1805// (e.g. OpenXR) thus it's too risky to use Swappy.1806swappy_frame_pacer_enable = false;1807OS::get_singleton()->print("VulkanHooks detected (e.g. OpenXR): Force-disabling Swappy Frame Pacing.\n");1808}1809#endif18101811shader_container_format.set_debug_info_enabled(Engine::get_singleton()->is_generate_spirv_debug_info_enabled());18121813#if RECORD_PIPELINE_STATISTICS1814pipeline_statistics.file_access = FileAccess::open(RECORD_PIPELINE_STATISTICS_PATH, FileAccess::WRITE);1815ERR_FAIL_NULL_V_MSG(pipeline_statistics.file_access, ERR_CANT_CREATE, "Unable to write pipeline statistics file.");18161817pipeline_statistics.file_access->store_csv_line({ "name", "hash", "stage", "spec", "glslang", "re-spirv", "time" });1818pipeline_statistics.file_access->flush();1819#endif18201821return OK;1822}18231824/****************/1825/**** MEMORY ****/1826/****************/18271828static const uint32_t SMALL_ALLOCATION_MAX_SIZE = 4096;18291830VmaPool RenderingDeviceDriverVulkan::_find_or_create_small_allocs_pool(uint32_t p_mem_type_index) {1831if (small_allocs_pools.has(p_mem_type_index)) {1832return small_allocs_pools[p_mem_type_index];1833}18341835print_verbose("Creating VMA small objects pool for memory type index " + itos(p_mem_type_index));18361837VmaPoolCreateInfo pci = {};1838pci.memoryTypeIndex = p_mem_type_index;1839pci.flags = 0;1840pci.blockSize = 0;1841pci.minBlockCount = 0;1842pci.maxBlockCount = SIZE_MAX;1843pci.priority = 0.5f;1844pci.minAllocationAlignment = 0;1845pci.pMemoryAllocateNext = nullptr;1846VmaPool pool = VK_NULL_HANDLE;1847VkResult res = vmaCreatePool(allocator, &pci, &pool);1848small_allocs_pools[p_mem_type_index] = pool; // Don't try to create it again if failed the first time.1849ERR_FAIL_COND_V_MSG(res, pool, "vmaCreatePool failed with error " + itos(res) + ".");18501851return pool;1852}18531854/*****************/1855/**** BUFFERS ****/1856/*****************/18571858// RDD::BufferUsageBits == VkBufferUsageFlagBits.1859static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_TRANSFER_FROM_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT));1860static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_TRANSFER_TO_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT));1861static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_TEXEL_BIT, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT));1862static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_UNIFORM_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT));1863static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_STORAGE_BIT, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));1864static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_INDEX_BIT, VK_BUFFER_USAGE_INDEX_BUFFER_BIT));1865static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_VERTEX_BIT, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));1866static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_INDIRECT_BIT, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT));1867static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT));1868static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR));1869static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR));18701871RDD::BufferID RenderingDeviceDriverVulkan::buffer_create(uint64_t p_size, BitField<BufferUsageBits> p_usage, MemoryAllocationType p_allocation_type, uint64_t p_frames_drawn) {1872uint32_t alignment = 16u; // 16 bytes is reasonable.1873if (p_usage.has_flag(BUFFER_USAGE_UNIFORM_BIT)) {1874// Some GPUs (e.g. NVIDIA) have absurdly high alignments, like 256 bytes.1875alignment = MAX(alignment, physical_device_properties.limits.minUniformBufferOffsetAlignment);1876}1877if (p_usage.has_flag(BUFFER_USAGE_STORAGE_BIT)) {1878// This shouldn't be a problem since it's often <= 16 bytes. But do it just in case.1879alignment = MAX(alignment, physical_device_properties.limits.minStorageBufferOffsetAlignment);1880}1881// Align the size. This is specially important for BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT buffers.1882// For the rest, it should work thanks to VMA taking care of the details. But still align just in case.1883p_size = STEPIFY(p_size, alignment);18841885const size_t original_size = p_size;1886if (p_usage.has_flag(BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT)) {1887p_size = p_size * frame_count;1888}1889VkBufferCreateInfo create_info = {};1890create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;1891create_info.size = p_size;1892create_info.usage = p_usage & ~BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT;1893create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;18941895VmaMemoryUsage vma_usage = VMA_MEMORY_USAGE_UNKNOWN;1896uint32_t vma_flags_to_remove = 0;18971898VmaAllocationCreateInfo alloc_create_info = {};1899switch (p_allocation_type) {1900case MEMORY_ALLOCATION_TYPE_CPU: {1901bool is_src = p_usage.has_flag(BUFFER_USAGE_TRANSFER_FROM_BIT);1902bool is_dst = p_usage.has_flag(BUFFER_USAGE_TRANSFER_TO_BIT);1903if (is_src && !is_dst) {1904// Looks like a staging buffer: CPU maps, writes sequentially, then GPU copies to VRAM.1905alloc_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;1906alloc_create_info.preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;1907vma_flags_to_remove |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;1908}1909if (is_dst && !is_src) {1910// Looks like a readback buffer: GPU copies from VRAM, then CPU maps and reads.1911alloc_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;1912alloc_create_info.preferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;1913vma_flags_to_remove |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;1914}1915vma_usage = VMA_MEMORY_USAGE_AUTO_PREFER_HOST;1916alloc_create_info.requiredFlags = (VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);1917} break;1918case MEMORY_ALLOCATION_TYPE_GPU: {1919vma_usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;1920if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {1921// We must set it right now or else vmaFindMemoryTypeIndexForBufferInfo will use wrong parameters.1922alloc_create_info.usage = vma_usage;1923}1924if (p_usage.has_flag(BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT)) {1925alloc_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;1926}1927alloc_create_info.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;1928if (p_size <= SMALL_ALLOCATION_MAX_SIZE) {1929uint32_t mem_type_index = 0;1930vmaFindMemoryTypeIndexForBufferInfo(allocator, &create_info, &alloc_create_info, &mem_type_index);1931alloc_create_info.pool = _find_or_create_small_allocs_pool(mem_type_index);1932}1933} break;1934}19351936VkBuffer vk_buffer = VK_NULL_HANDLE;1937VmaAllocation allocation = nullptr;1938VmaAllocationInfo alloc_info = {};19391940if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {1941alloc_create_info.preferredFlags &= ~vma_flags_to_remove;1942alloc_create_info.usage = vma_usage;1943VkResult err = vmaCreateBuffer(allocator, &create_info, &alloc_create_info, &vk_buffer, &allocation, &alloc_info);1944ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't create buffer of size: " + itos(p_size) + ", error " + itos(err) + ".");1945} else {1946VkResult err = vkCreateBuffer(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER), &vk_buffer);1947ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't create buffer of size: " + itos(p_size) + ", error " + itos(err) + ".");1948err = vmaAllocateMemoryForBuffer(allocator, vk_buffer, &alloc_create_info, &allocation, &alloc_info);1949ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't allocate memory for buffer of size: " + itos(p_size) + ", error " + itos(err) + ".");1950err = vmaBindBufferMemory2(allocator, allocation, 0, vk_buffer, nullptr);1951ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't bind memory to buffer of size: " + itos(p_size) + ", error " + itos(err) + ".");1952}19531954// Bookkeep.1955BufferInfo *buf_info;1956if (p_usage.has_flag(BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT)) {1957void *persistent_ptr = nullptr;1958VkResult err = vmaMapMemory(allocator, allocation, &persistent_ptr);1959ERR_FAIL_COND_V_MSG(err, BufferID(), "vmaMapMemory failed with error " + itos(err) + ".");19601961BufferDynamicInfo *dyn_buffer = VersatileResource::allocate<BufferDynamicInfo>(resources_allocator);1962buf_info = dyn_buffer;1963#ifdef DEBUG_ENABLED1964dyn_buffer->last_frame_mapped = p_frames_drawn - 1ul;1965#endif1966dyn_buffer->frame_idx = 0u;1967dyn_buffer->persistent_ptr = (uint8_t *)persistent_ptr;1968} else {1969buf_info = VersatileResource::allocate<BufferInfo>(resources_allocator);1970}1971buf_info->vk_buffer = vk_buffer;1972buf_info->allocation.handle = allocation;1973buf_info->allocation.size = alloc_info.size;1974buf_info->size = original_size;19751976return BufferID(buf_info);1977}19781979bool RenderingDeviceDriverVulkan::buffer_set_texel_format(BufferID p_buffer, DataFormat p_format) {1980BufferInfo *buf_info = (BufferInfo *)p_buffer.id;19811982DEV_ASSERT(!buf_info->vk_view);19831984VkBufferViewCreateInfo view_create_info = {};1985view_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;1986view_create_info.buffer = buf_info->vk_buffer;1987view_create_info.format = RD_TO_VK_FORMAT[p_format];1988view_create_info.range = buf_info->allocation.size;19891990VkResult res = vkCreateBufferView(vk_device, &view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER_VIEW), &buf_info->vk_view);1991ERR_FAIL_COND_V_MSG(res, false, "Unable to create buffer view, error " + itos(res) + ".");19921993return true;1994}19951996void RenderingDeviceDriverVulkan::buffer_free(BufferID p_buffer) {1997BufferInfo *buf_info = (BufferInfo *)p_buffer.id;1998if (buf_info->vk_view) {1999vkDestroyBufferView(vk_device, buf_info->vk_view, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER_VIEW));2000}20012002if (buf_info->is_dynamic()) {2003vmaUnmapMemory(allocator, buf_info->allocation.handle);2004}20052006if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {2007vmaDestroyBuffer(allocator, buf_info->vk_buffer, buf_info->allocation.handle);2008} else {2009vkDestroyBuffer(vk_device, buf_info->vk_buffer, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER));2010vmaFreeMemory(allocator, buf_info->allocation.handle);2011}20122013if (buf_info->is_dynamic()) {2014VersatileResource::free(resources_allocator, (BufferDynamicInfo *)buf_info);2015} else {2016VersatileResource::free(resources_allocator, buf_info);2017}2018}20192020uint64_t RenderingDeviceDriverVulkan::buffer_get_allocation_size(BufferID p_buffer) {2021const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;2022return buf_info->allocation.size;2023}20242025uint8_t *RenderingDeviceDriverVulkan::buffer_map(BufferID p_buffer) {2026const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;2027ERR_FAIL_COND_V_MSG(buf_info->is_dynamic(), nullptr, "Buffer must NOT have BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT. Use buffer_persistent_map_advance() instead.");2028void *data_ptr = nullptr;2029VkResult err = vmaMapMemory(allocator, buf_info->allocation.handle, &data_ptr);2030ERR_FAIL_COND_V_MSG(err, nullptr, "vmaMapMemory failed with error " + itos(err) + ".");2031return (uint8_t *)data_ptr;2032}20332034void RenderingDeviceDriverVulkan::buffer_unmap(BufferID p_buffer) {2035const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;2036vmaUnmapMemory(allocator, buf_info->allocation.handle);2037}20382039uint8_t *RenderingDeviceDriverVulkan::buffer_persistent_map_advance(BufferID p_buffer, uint64_t p_frames_drawn) {2040BufferDynamicInfo *buf_info = (BufferDynamicInfo *)p_buffer.id;2041ERR_FAIL_COND_V_MSG(!buf_info->is_dynamic(), nullptr, "Buffer must have BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT. Use buffer_map() instead.");2042#ifdef DEBUG_ENABLED2043ERR_FAIL_COND_V_MSG(buf_info->last_frame_mapped == p_frames_drawn, nullptr, "Buffers with BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT must only be mapped once per frame. Otherwise there could be race conditions with the GPU. Amalgamate all data uploading into one map(), use an extra buffer or remove the bit.");2044buf_info->last_frame_mapped = p_frames_drawn;2045#endif2046buf_info->frame_idx = (buf_info->frame_idx + 1u) % frame_count;2047return buf_info->persistent_ptr + buf_info->frame_idx * buf_info->size;2048}20492050uint64_t RenderingDeviceDriverVulkan::buffer_get_dynamic_offsets(Span<BufferID> p_buffers) {2051uint64_t mask = 0u;2052uint64_t shift = 0u;20532054for (const BufferID &buf : p_buffers) {2055const BufferInfo *buf_info = (const BufferInfo *)buf.id;2056if (!buf_info->is_dynamic()) {2057continue;2058}2059mask |= buf_info->frame_idx << shift;2060// We can encode the frame index in 2 bits since frame_count won't be > 4.2061shift += 2UL;2062}20632064return mask;2065}20662067void RenderingDeviceDriverVulkan::buffer_flush(BufferID p_buffer) {2068BufferDynamicInfo *buf_info = (BufferDynamicInfo *)p_buffer.id;20692070VkMemoryPropertyFlags mem_props_flags;2071vmaGetAllocationMemoryProperties(allocator, buf_info->allocation.handle, &mem_props_flags);20722073const bool needs_flushing = !(mem_props_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);20742075if (needs_flushing) {2076if (buf_info->is_dynamic()) {2077pending_flushes.allocations.push_back(buf_info->allocation.handle);2078pending_flushes.offsets.push_back(buf_info->frame_idx * buf_info->size);2079pending_flushes.sizes.push_back(buf_info->size);2080} else {2081pending_flushes.allocations.push_back(buf_info->allocation.handle);2082pending_flushes.offsets.push_back(0u);2083pending_flushes.sizes.push_back(VK_WHOLE_SIZE);2084}2085}2086}20872088uint64_t RenderingDeviceDriverVulkan::buffer_get_device_address(BufferID p_buffer) {2089const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;2090VkBufferDeviceAddressInfo address_info = {};2091address_info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;2092address_info.pNext = nullptr;2093address_info.buffer = buf_info->vk_buffer;2094return vkGetBufferDeviceAddress(vk_device, &address_info);2095}20962097/*****************/2098/**** TEXTURE ****/2099/*****************/21002101static const VkImageType RD_TEX_TYPE_TO_VK_IMG_TYPE[RDD::TEXTURE_TYPE_MAX] = {2102VK_IMAGE_TYPE_1D,2103VK_IMAGE_TYPE_2D,2104VK_IMAGE_TYPE_3D,2105VK_IMAGE_TYPE_2D,2106VK_IMAGE_TYPE_1D,2107VK_IMAGE_TYPE_2D,2108VK_IMAGE_TYPE_2D,2109};21102111static const VkSampleCountFlagBits RD_TO_VK_SAMPLE_COUNT[RDD::TEXTURE_SAMPLES_MAX] = {2112VK_SAMPLE_COUNT_1_BIT,2113VK_SAMPLE_COUNT_2_BIT,2114VK_SAMPLE_COUNT_4_BIT,2115VK_SAMPLE_COUNT_8_BIT,2116VK_SAMPLE_COUNT_16_BIT,2117VK_SAMPLE_COUNT_32_BIT,2118VK_SAMPLE_COUNT_64_BIT,2119};21202121// RDD::TextureType == VkImageViewType.2122static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_TYPE_1D, VK_IMAGE_VIEW_TYPE_1D));2123static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_TYPE_2D, VK_IMAGE_VIEW_TYPE_2D));2124static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_TYPE_3D, VK_IMAGE_VIEW_TYPE_3D));2125static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_TYPE_CUBE, VK_IMAGE_VIEW_TYPE_CUBE));2126static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_TYPE_1D_ARRAY, VK_IMAGE_VIEW_TYPE_1D_ARRAY));2127static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_TYPE_2D_ARRAY, VK_IMAGE_VIEW_TYPE_2D_ARRAY));2128static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_TYPE_CUBE_ARRAY, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY));21292130// RDD::TextureSwizzle == VkComponentSwizzle.2131static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY));2132static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO));2133static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ONE));2134static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R));2135static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_G, VK_COMPONENT_SWIZZLE_G));2136static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_B, VK_COMPONENT_SWIZZLE_B));2137static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_A, VK_COMPONENT_SWIZZLE_A));21382139// RDD::TextureAspectBits == VkImageAspectFlagBits.2140static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT));2141static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_ASPECT_DEPTH_BIT, VK_IMAGE_ASPECT_DEPTH_BIT));2142static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_ASPECT_STENCIL_BIT, VK_IMAGE_ASPECT_STENCIL_BIT));21432144VkSampleCountFlagBits RenderingDeviceDriverVulkan::_ensure_supported_sample_count(TextureSamples p_requested_sample_count) {2145VkSampleCountFlags sample_count_flags = (physical_device_properties.limits.framebufferColorSampleCounts & physical_device_properties.limits.framebufferDepthSampleCounts);21462147if ((sample_count_flags & RD_TO_VK_SAMPLE_COUNT[p_requested_sample_count])) {2148// The requested sample count is supported.2149return RD_TO_VK_SAMPLE_COUNT[p_requested_sample_count];2150} else {2151// Find the closest lower supported sample count.2152VkSampleCountFlagBits sample_count = RD_TO_VK_SAMPLE_COUNT[p_requested_sample_count];2153while (sample_count > VK_SAMPLE_COUNT_1_BIT) {2154if (sample_count_flags & sample_count) {2155return sample_count;2156}2157sample_count = (VkSampleCountFlagBits)(sample_count >> 1);2158}2159}2160return VK_SAMPLE_COUNT_1_BIT;2161}21622163RDD::TextureID RenderingDeviceDriverVulkan::texture_create(const TextureFormat &p_format, const TextureView &p_view) {2164VkImageCreateInfo create_info = {};2165create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;21662167if (p_format.shareable_formats.size()) {2168create_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;21692170if (enabled_device_extension_names.has(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME)) {2171VkFormat *vk_allowed_formats = ALLOCA_ARRAY(VkFormat, p_format.shareable_formats.size());2172for (int i = 0; i < p_format.shareable_formats.size(); i++) {2173vk_allowed_formats[i] = RD_TO_VK_FORMAT[p_format.shareable_formats[i]];2174}21752176VkImageFormatListCreateInfoKHR *format_list_create_info = ALLOCA_SINGLE(VkImageFormatListCreateInfoKHR);2177*format_list_create_info = {};2178format_list_create_info->sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR;2179format_list_create_info->viewFormatCount = p_format.shareable_formats.size();2180format_list_create_info->pViewFormats = vk_allowed_formats;21812182create_info.pNext = format_list_create_info;2183}2184}21852186if (p_format.texture_type == TEXTURE_TYPE_CUBE || p_format.texture_type == TEXTURE_TYPE_CUBE_ARRAY) {2187create_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;2188}2189/*if (p_format.texture_type == TEXTURE_TYPE_2D || p_format.texture_type == TEXTURE_TYPE_2D_ARRAY) {2190create_info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;2191}*/21922193if (fdm_capabilities.offset_supported && (p_format.usage_bits & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_RESOLVE_ATTACHMENT_BIT | TEXTURE_USAGE_VRS_ATTACHMENT_BIT))) {2194create_info.flags |= VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_QCOM;2195}21962197create_info.imageType = RD_TEX_TYPE_TO_VK_IMG_TYPE[p_format.texture_type];21982199create_info.format = RD_TO_VK_FORMAT[p_format.format];22002201create_info.extent.width = p_format.width;2202create_info.extent.height = p_format.height;2203create_info.extent.depth = p_format.depth;22042205create_info.mipLevels = p_format.mipmaps;2206create_info.arrayLayers = p_format.array_layers;22072208create_info.samples = _ensure_supported_sample_count(p_format.samples);2209create_info.tiling = (p_format.usage_bits & TEXTURE_USAGE_CPU_READ_BIT) ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;22102211// Usage.2212if ((p_format.usage_bits & TEXTURE_USAGE_SAMPLING_BIT)) {2213create_info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;2214}2215if ((p_format.usage_bits & TEXTURE_USAGE_STORAGE_BIT)) {2216create_info.usage |= VK_IMAGE_USAGE_STORAGE_BIT;2217}2218if ((p_format.usage_bits & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) {2219create_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;2220}2221if ((p_format.usage_bits & (TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_RESOLVE_ATTACHMENT_BIT))) {2222create_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;2223}2224if ((p_format.usage_bits & TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)) {2225create_info.usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;2226}2227if ((p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) && (p_format.usage_bits & TEXTURE_USAGE_VRS_FRAGMENT_SHADING_RATE_BIT)) {2228create_info.usage |= VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;2229}2230if ((p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) && (p_format.usage_bits & TEXTURE_USAGE_VRS_FRAGMENT_DENSITY_MAP_BIT)) {2231create_info.usage |= VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT;2232}2233if ((p_format.usage_bits & TEXTURE_USAGE_CAN_UPDATE_BIT)) {2234create_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;2235}2236if ((p_format.usage_bits & TEXTURE_USAGE_CAN_COPY_FROM_BIT)) {2237create_info.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;2238}2239if ((p_format.usage_bits & TEXTURE_USAGE_CAN_COPY_TO_BIT)) {2240create_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;2241}22422243create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;2244create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;22452246// Allocate memory.22472248uint32_t width = 0, height = 0;2249uint32_t image_size = get_image_format_required_size(p_format.format, p_format.width, p_format.height, p_format.depth, p_format.mipmaps, &width, &height);22502251VmaAllocationCreateInfo alloc_create_info = {};2252alloc_create_info.flags = (p_format.usage_bits & TEXTURE_USAGE_CPU_READ_BIT) ? VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT : 0;22532254if (p_format.usage_bits & TEXTURE_USAGE_TRANSIENT_BIT) {2255uint32_t memory_type_index = 0;2256VmaAllocationCreateInfo lazy_memory_requirements = alloc_create_info;2257lazy_memory_requirements.usage = VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED;2258VkResult result = vmaFindMemoryTypeIndex(allocator, UINT32_MAX, &lazy_memory_requirements, &memory_type_index);2259if (VK_SUCCESS == result) {2260alloc_create_info = lazy_memory_requirements;2261create_info.usage |= VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;2262// VUID-VkImageCreateInfo-usage-00963 :2263// If usage includes VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,2264// then bits other than VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,2265// and VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT must not be set.2266create_info.usage &= (VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);2267} else {2268alloc_create_info.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;2269}2270} else if (p_format.usage_bits & TEXTURE_USAGE_CPU_READ_BIT) {2271alloc_create_info.preferredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;2272} else {2273alloc_create_info.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;2274}22752276if (image_size <= SMALL_ALLOCATION_MAX_SIZE) {2277uint32_t mem_type_index = 0;2278vmaFindMemoryTypeIndexForImageInfo(allocator, &create_info, &alloc_create_info, &mem_type_index);2279alloc_create_info.pool = _find_or_create_small_allocs_pool(mem_type_index);2280}22812282// Create.22832284VkImage vk_image = VK_NULL_HANDLE;2285VmaAllocation allocation = nullptr;2286VmaAllocationInfo alloc_info = {};22872288if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {2289alloc_create_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;2290VkResult err = vmaCreateImage(allocator, &create_info, &alloc_create_info, &vk_image, &allocation, &alloc_info);2291ERR_FAIL_COND_V_MSG(err, TextureID(), "vmaCreateImage failed with error " + itos(err) + ".");2292} else {2293VkResult err = vkCreateImage(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE), &vk_image);2294ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImage failed with error " + itos(err) + ".");2295err = vmaAllocateMemoryForImage(allocator, vk_image, &alloc_create_info, &allocation, &alloc_info);2296ERR_FAIL_COND_V_MSG(err, TextureID(), "Can't allocate memory for image, error: " + itos(err) + ".");2297err = vmaBindImageMemory2(allocator, allocation, 0, vk_image, nullptr);2298ERR_FAIL_COND_V_MSG(err, TextureID(), "Can't bind memory to image, error: " + itos(err) + ".");2299}23002301// Create view.23022303VkImageViewCreateInfo image_view_create_info = {};2304image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;2305image_view_create_info.image = vk_image;2306image_view_create_info.viewType = (VkImageViewType)p_format.texture_type;2307image_view_create_info.format = RD_TO_VK_FORMAT[p_view.format];2308image_view_create_info.components.r = (VkComponentSwizzle)p_view.swizzle_r;2309image_view_create_info.components.g = (VkComponentSwizzle)p_view.swizzle_g;2310image_view_create_info.components.b = (VkComponentSwizzle)p_view.swizzle_b;2311image_view_create_info.components.a = (VkComponentSwizzle)p_view.swizzle_a;2312image_view_create_info.subresourceRange.levelCount = create_info.mipLevels;2313image_view_create_info.subresourceRange.layerCount = create_info.arrayLayers;2314if ((p_format.usage_bits & (TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_RESOLVE_ATTACHMENT_BIT))) {2315image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;2316} else {2317image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;2318}23192320VkImageViewASTCDecodeModeEXT decode_mode;2321if (enabled_device_extension_names.has(VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME)) {2322if (image_view_create_info.format >= VK_FORMAT_ASTC_4x4_UNORM_BLOCK && image_view_create_info.format <= VK_FORMAT_ASTC_12x12_SRGB_BLOCK) {2323decode_mode.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT;2324decode_mode.pNext = nullptr;2325decode_mode.decodeMode = VK_FORMAT_R8G8B8A8_UNORM;2326image_view_create_info.pNext = &decode_mode;2327}2328}23292330VkImageView vk_image_view = VK_NULL_HANDLE;2331VkResult err = vkCreateImageView(vk_device, &image_view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &vk_image_view);2332if (err) {2333if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {2334vmaDestroyImage(allocator, vk_image, allocation);2335} else {2336vkDestroyImage(vk_device, vk_image, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE));2337vmaFreeMemory(allocator, allocation);2338}23392340ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImageView failed with error " + itos(err) + ".");2341}23422343// Bookkeep.23442345TextureInfo *tex_info = VersatileResource::allocate<TextureInfo>(resources_allocator);2346tex_info->vk_image = vk_image;2347tex_info->vk_view = vk_image_view;2348tex_info->rd_format = p_format.format;2349tex_info->vk_create_info = create_info;2350tex_info->vk_view_create_info = image_view_create_info;2351tex_info->allocation.handle = allocation;2352#ifdef DEBUG_ENABLED2353tex_info->transient = (p_format.usage_bits & TEXTURE_USAGE_TRANSIENT_BIT) != 0;2354#endif2355vmaGetAllocationInfo(allocator, tex_info->allocation.handle, &tex_info->allocation.info);23562357#if PRINT_NATIVE_COMMANDS2358print_line(vformat("vkCreateImageView: 0x%uX for 0x%uX", uint64_t(vk_image_view), uint64_t(vk_image)));2359#endif23602361return TextureID(tex_info);2362}23632364RDD::TextureID RenderingDeviceDriverVulkan::texture_create_from_extension(uint64_t p_native_texture, TextureType p_type, DataFormat p_format, uint32_t p_array_layers, bool p_depth_stencil, uint32_t p_mipmaps) {2365VkImage vk_image = (VkImage)p_native_texture;23662367// We only need to create a view into the already existing natively-provided texture.23682369VkImageViewCreateInfo image_view_create_info = {};2370image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;2371image_view_create_info.image = vk_image;2372image_view_create_info.viewType = (VkImageViewType)p_type;2373image_view_create_info.format = RD_TO_VK_FORMAT[p_format];2374image_view_create_info.components.r = VK_COMPONENT_SWIZZLE_R;2375image_view_create_info.components.g = VK_COMPONENT_SWIZZLE_G;2376image_view_create_info.components.b = VK_COMPONENT_SWIZZLE_B;2377image_view_create_info.components.a = VK_COMPONENT_SWIZZLE_A;2378image_view_create_info.subresourceRange.baseMipLevel = 0;2379image_view_create_info.subresourceRange.levelCount = p_mipmaps;2380image_view_create_info.subresourceRange.layerCount = p_array_layers;2381image_view_create_info.subresourceRange.aspectMask = p_depth_stencil ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;23822383VkImageView vk_image_view = VK_NULL_HANDLE;2384VkResult err = vkCreateImageView(vk_device, &image_view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &vk_image_view);2385if (err) {2386ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImageView failed with error " + itos(err) + ".");2387}23882389// Bookkeep.23902391TextureInfo *tex_info = VersatileResource::allocate<TextureInfo>(resources_allocator);2392tex_info->vk_view = vk_image_view;2393tex_info->rd_format = p_format;2394tex_info->vk_view_create_info = image_view_create_info;2395#ifdef DEBUG_ENABLED2396tex_info->created_from_extension = true;2397#endif2398return TextureID(tex_info);2399}24002401RDD::TextureID RenderingDeviceDriverVulkan::texture_create_shared(TextureID p_original_texture, const TextureView &p_view) {2402const TextureInfo *owner_tex_info = (const TextureInfo *)p_original_texture.id;2403#ifdef DEBUG_ENABLED2404ERR_FAIL_COND_V(!owner_tex_info->allocation.handle && !owner_tex_info->created_from_extension, TextureID());2405#endif2406VkImageViewCreateInfo image_view_create_info = owner_tex_info->vk_view_create_info;2407image_view_create_info.format = RD_TO_VK_FORMAT[p_view.format];2408image_view_create_info.components.r = (VkComponentSwizzle)p_view.swizzle_r;2409image_view_create_info.components.g = (VkComponentSwizzle)p_view.swizzle_g;2410image_view_create_info.components.b = (VkComponentSwizzle)p_view.swizzle_b;2411image_view_create_info.components.a = (VkComponentSwizzle)p_view.swizzle_a;24122413if (enabled_device_extension_names.has(VK_KHR_MAINTENANCE_2_EXTENSION_NAME)) {2414// May need to make VK_KHR_maintenance2 mandatory and thus has Vulkan 1.1 be our minimum supported version2415// if we require setting this information. Vulkan 1.0 may simply not care.2416if (image_view_create_info.format != owner_tex_info->vk_view_create_info.format) {2417VkImageViewUsageCreateInfo *usage_info = ALLOCA_SINGLE(VkImageViewUsageCreateInfo);2418*usage_info = {};2419usage_info->sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO;2420usage_info->usage = owner_tex_info->vk_create_info.usage;24212422// Certain features may not be available for the format of the view.2423{2424VkFormatProperties properties = {};2425vkGetPhysicalDeviceFormatProperties(physical_device, RD_TO_VK_FORMAT[p_view.format], &properties);2426const VkFormatFeatureFlags &supported_flags = owner_tex_info->vk_create_info.tiling == VK_IMAGE_TILING_LINEAR ? properties.linearTilingFeatures : properties.optimalTilingFeatures;2427if ((usage_info->usage & VK_IMAGE_USAGE_STORAGE_BIT) && !(supported_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {2428usage_info->usage &= ~uint32_t(VK_IMAGE_USAGE_STORAGE_BIT);2429}2430if ((usage_info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) && !(supported_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {2431usage_info->usage &= ~uint32_t(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);2432}2433}24342435image_view_create_info.pNext = usage_info;2436}2437}24382439VkImageView new_vk_image_view = VK_NULL_HANDLE;2440VkResult err = vkCreateImageView(vk_device, &image_view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &new_vk_image_view);2441ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImageView failed with error " + itos(err) + ".");24422443// Bookkeep.24442445TextureInfo *tex_info = VersatileResource::allocate<TextureInfo>(resources_allocator);2446*tex_info = *owner_tex_info;2447tex_info->vk_view = new_vk_image_view;2448tex_info->vk_view_create_info = image_view_create_info;2449tex_info->allocation = {};24502451#if PRINT_NATIVE_COMMANDS2452print_line(vformat("vkCreateImageView: 0x%uX for 0x%uX", uint64_t(new_vk_image_view), uint64_t(owner_tex_info->vk_view_create_info.image)));2453#endif24542455return TextureID(tex_info);2456}24572458RDD::TextureID RenderingDeviceDriverVulkan::texture_create_shared_from_slice(TextureID p_original_texture, const TextureView &p_view, TextureSliceType p_slice_type, uint32_t p_layer, uint32_t p_layers, uint32_t p_mipmap, uint32_t p_mipmaps) {2459const TextureInfo *owner_tex_info = (const TextureInfo *)p_original_texture.id;2460#ifdef DEBUG_ENABLED2461ERR_FAIL_COND_V(!owner_tex_info->allocation.handle && !owner_tex_info->created_from_extension, TextureID());2462#endif24632464VkImageViewCreateInfo image_view_create_info = owner_tex_info->vk_view_create_info;2465switch (p_slice_type) {2466case TEXTURE_SLICE_2D: {2467image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;2468} break;2469case TEXTURE_SLICE_3D: {2470image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_3D;2471} break;2472case TEXTURE_SLICE_CUBEMAP: {2473image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_CUBE;2474} break;2475case TEXTURE_SLICE_2D_ARRAY: {2476image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;2477} break;2478default: {2479return TextureID(nullptr);2480}2481}2482image_view_create_info.format = RD_TO_VK_FORMAT[p_view.format];2483image_view_create_info.components.r = (VkComponentSwizzle)p_view.swizzle_r;2484image_view_create_info.components.g = (VkComponentSwizzle)p_view.swizzle_g;2485image_view_create_info.components.b = (VkComponentSwizzle)p_view.swizzle_b;2486image_view_create_info.components.a = (VkComponentSwizzle)p_view.swizzle_a;2487image_view_create_info.subresourceRange.baseMipLevel = p_mipmap;2488image_view_create_info.subresourceRange.levelCount = p_mipmaps;2489image_view_create_info.subresourceRange.baseArrayLayer = p_layer;2490image_view_create_info.subresourceRange.layerCount = p_layers;24912492VkImageView new_vk_image_view = VK_NULL_HANDLE;2493VkResult err = vkCreateImageView(vk_device, &image_view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &new_vk_image_view);2494ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImageView failed with error " + itos(err) + ".");24952496// Bookkeep.24972498TextureInfo *tex_info = VersatileResource::allocate<TextureInfo>(resources_allocator);2499*tex_info = *owner_tex_info;2500tex_info->vk_view = new_vk_image_view;2501tex_info->vk_view_create_info = image_view_create_info;2502tex_info->allocation = {};25032504#if PRINT_NATIVE_COMMANDS2505print_line(vformat("vkCreateImageView: 0x%uX for 0x%uX (%d %d %d %d)", uint64_t(new_vk_image_view), uint64_t(owner_tex_info->vk_view_create_info.image), p_mipmap, p_mipmaps, p_layer, p_layers));2506#endif25072508return TextureID(tex_info);2509}25102511void RenderingDeviceDriverVulkan::texture_free(TextureID p_texture) {2512TextureInfo *tex_info = (TextureInfo *)p_texture.id;2513vkDestroyImageView(vk_device, tex_info->vk_view, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW));2514if (tex_info->allocation.handle) {2515if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {2516vmaDestroyImage(allocator, tex_info->vk_view_create_info.image, tex_info->allocation.handle);2517} else {2518vkDestroyImage(vk_device, tex_info->vk_image, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER));2519vmaFreeMemory(allocator, tex_info->allocation.handle);2520}2521}2522VersatileResource::free(resources_allocator, tex_info);2523}25242525uint64_t RenderingDeviceDriverVulkan::texture_get_allocation_size(TextureID p_texture) {2526const TextureInfo *tex_info = (const TextureInfo *)p_texture.id;2527return tex_info->allocation.info.size;2528}25292530void RenderingDeviceDriverVulkan::texture_get_copyable_layout(TextureID p_texture, const TextureSubresource &p_subresource, TextureCopyableLayout *r_layout) {2531const TextureInfo *tex_info = (const TextureInfo *)p_texture.id;25322533uint32_t w = MAX(1u, tex_info->vk_create_info.extent.width >> p_subresource.mipmap);2534uint32_t h = MAX(1u, tex_info->vk_create_info.extent.height >> p_subresource.mipmap);2535uint32_t d = MAX(1u, tex_info->vk_create_info.extent.depth >> p_subresource.mipmap);25362537uint32_t bw = 0, bh = 0;2538get_compressed_image_format_block_dimensions(tex_info->rd_format, bw, bh);25392540uint32_t sbw = 0, sbh = 0;2541*r_layout = {};2542r_layout->size = get_image_format_required_size(tex_info->rd_format, w, h, d, 1, &sbw, &sbh);2543r_layout->row_pitch = r_layout->size / ((sbh / bh) * d);2544}25452546Vector<uint8_t> RenderingDeviceDriverVulkan::texture_get_data(TextureID p_texture, uint32_t p_layer) {2547const TextureInfo *tex = (const TextureInfo *)p_texture.id;25482549DataFormat tex_format = tex->rd_format;2550uint32_t tex_width = tex->vk_create_info.extent.width;2551uint32_t tex_height = tex->vk_create_info.extent.height;2552uint32_t tex_depth = tex->vk_create_info.extent.depth;2553uint32_t tex_mipmaps = tex->vk_create_info.mipLevels;25542555uint32_t width, height, depth;2556uint32_t tight_mip_size = get_image_format_required_size(tex_format, tex_width, tex_height, tex_depth, tex_mipmaps, &width, &height, &depth);25572558Vector<uint8_t> image_data;2559image_data.resize(tight_mip_size);25602561uint32_t blockw, blockh;2562get_compressed_image_format_block_dimensions(tex_format, blockw, blockh);2563uint32_t block_size = get_compressed_image_format_block_byte_size(tex_format);2564uint32_t pixel_size = get_image_format_pixel_size(tex_format);25652566void *data_ptr = nullptr;2567VkResult err = vmaMapMemory(allocator, tex->allocation.handle, &data_ptr);2568ERR_FAIL_COND_V_MSG(err, Vector<uint8_t>(), "vmaMapMemory failed with error " + itos(err) + ".");25692570{2571uint8_t *w = image_data.ptrw();25722573uint32_t mipmap_offset = 0;2574for (uint32_t mm_i = 0; mm_i < tex_mipmaps; mm_i++) {2575uint32_t image_total = get_image_format_required_size(tex_format, tex_width, tex_height, tex_depth, mm_i + 1, &width, &height, &depth);25762577uint8_t *write_ptr_mipmap = w + mipmap_offset;2578tight_mip_size = image_total - mipmap_offset;25792580VkImageSubresource vk_subres = {};2581vk_subres.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;2582vk_subres.arrayLayer = p_layer;2583vk_subres.mipLevel = mm_i;25842585VkSubresourceLayout vk_layout = {};2586vkGetImageSubresourceLayout(vk_device, tex->vk_view_create_info.image, &vk_subres, &vk_layout);25872588for (uint32_t z = 0; z < depth; z++) {2589uint8_t *write_ptr = write_ptr_mipmap + z * tight_mip_size / depth;2590const uint8_t *slice_read_ptr = (uint8_t *)data_ptr + vk_layout.offset + z * vk_layout.depthPitch;25912592if (block_size > 1) {2593// Compressed.2594uint32_t line_width = (block_size * (width / blockw));2595for (uint32_t y = 0; y < height / blockh; y++) {2596const uint8_t *rptr = slice_read_ptr + y * vk_layout.rowPitch;2597uint8_t *wptr = write_ptr + y * line_width;25982599memcpy(wptr, rptr, line_width);2600}2601} else {2602// Uncompressed.2603for (uint32_t y = 0; y < height; y++) {2604const uint8_t *rptr = slice_read_ptr + y * vk_layout.rowPitch;2605uint8_t *wptr = write_ptr + y * pixel_size * width;2606memcpy(wptr, rptr, (uint64_t)pixel_size * width);2607}2608}2609}26102611mipmap_offset = image_total;2612}2613}26142615vmaUnmapMemory(allocator, tex->allocation.handle);26162617return image_data;2618}26192620BitField<RDD::TextureUsageBits> RenderingDeviceDriverVulkan::texture_get_usages_supported_by_format(DataFormat p_format, bool p_cpu_readable) {2621if (p_format >= DATA_FORMAT_ASTC_4x4_SFLOAT_BLOCK && p_format <= DATA_FORMAT_ASTC_12x12_SFLOAT_BLOCK && !enabled_device_extension_names.has(VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME)) {2622// Formats that were introduced later with extensions must not reach vkGetPhysicalDeviceFormatProperties if the extension isn't available. This means it's not supported.2623return 0;2624}2625VkFormatProperties properties = {};2626vkGetPhysicalDeviceFormatProperties(physical_device, RD_TO_VK_FORMAT[p_format], &properties);26272628const VkFormatFeatureFlags &flags = p_cpu_readable ? properties.linearTilingFeatures : properties.optimalTilingFeatures;26292630// Everything supported by default makes an all-or-nothing check easier for the caller.2631BitField<RDD::TextureUsageBits> supported = INT64_MAX;26322633if (!(flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {2634supported.clear_flag(TEXTURE_USAGE_SAMPLING_BIT);2635}2636if (!(flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {2637supported.clear_flag(TEXTURE_USAGE_COLOR_ATTACHMENT_BIT);2638}2639if (!(flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {2640supported.clear_flag(TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);2641supported.clear_flag(TEXTURE_USAGE_DEPTH_RESOLVE_ATTACHMENT_BIT);2642}2643if (!(flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {2644supported.clear_flag(TEXTURE_USAGE_STORAGE_BIT);2645}2646if (!(flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)) {2647supported.clear_flag(TEXTURE_USAGE_STORAGE_ATOMIC_BIT);2648}2649if (p_format != DATA_FORMAT_R8_UINT && p_format != DATA_FORMAT_R8G8_UNORM) {2650supported.clear_flag(TEXTURE_USAGE_VRS_ATTACHMENT_BIT);2651}26522653return supported;2654}26552656bool RenderingDeviceDriverVulkan::texture_can_make_shared_with_format(TextureID p_texture, DataFormat p_format, bool &r_raw_reinterpretation) {2657r_raw_reinterpretation = false;2658return true;2659}26602661/*****************/2662/**** SAMPLER ****/2663/*****************/26642665// RDD::SamplerRepeatMode == VkSamplerAddressMode.2666static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_REPEAT_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT));2667static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT));2668static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE));2669static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_REPEAT_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER));2670static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_REPEAT_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE));26712672// RDD::SamplerBorderColor == VkBorderColor.2673static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK));2674static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_BORDER_COLOR_INT_TRANSPARENT_BLACK, VK_BORDER_COLOR_INT_TRANSPARENT_BLACK));2675static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_BORDER_COLOR_FLOAT_OPAQUE_BLACK, VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK));2676static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_BORDER_COLOR_INT_OPAQUE_BLACK, VK_BORDER_COLOR_INT_OPAQUE_BLACK));2677static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_BORDER_COLOR_FLOAT_OPAQUE_WHITE, VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE));2678static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_BORDER_COLOR_INT_OPAQUE_WHITE, VK_BORDER_COLOR_INT_OPAQUE_WHITE));26792680RDD::SamplerID RenderingDeviceDriverVulkan::sampler_create(const SamplerState &p_state) {2681VkSamplerCreateInfo sampler_create_info = {};2682sampler_create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;2683sampler_create_info.pNext = nullptr;2684sampler_create_info.flags = 0;2685sampler_create_info.magFilter = p_state.mag_filter == SAMPLER_FILTER_LINEAR ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;2686sampler_create_info.minFilter = p_state.min_filter == SAMPLER_FILTER_LINEAR ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;2687sampler_create_info.mipmapMode = p_state.mip_filter == SAMPLER_FILTER_LINEAR ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST;2688sampler_create_info.addressModeU = (VkSamplerAddressMode)p_state.repeat_u;2689sampler_create_info.addressModeV = (VkSamplerAddressMode)p_state.repeat_v;2690sampler_create_info.addressModeW = (VkSamplerAddressMode)p_state.repeat_w;2691sampler_create_info.mipLodBias = p_state.lod_bias;2692sampler_create_info.anisotropyEnable = p_state.use_anisotropy && (physical_device_features.samplerAnisotropy == VK_TRUE);2693sampler_create_info.maxAnisotropy = p_state.anisotropy_max;2694sampler_create_info.compareEnable = p_state.enable_compare;2695sampler_create_info.compareOp = (VkCompareOp)p_state.compare_op;2696sampler_create_info.minLod = p_state.min_lod;2697sampler_create_info.maxLod = p_state.max_lod;2698sampler_create_info.borderColor = (VkBorderColor)p_state.border_color;2699sampler_create_info.unnormalizedCoordinates = p_state.unnormalized_uvw;27002701VkSampler vk_sampler = VK_NULL_HANDLE;2702VkResult res = vkCreateSampler(vk_device, &sampler_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SAMPLER), &vk_sampler);2703ERR_FAIL_COND_V_MSG(res, SamplerID(), "vkCreateSampler failed with error " + itos(res) + ".");27042705return SamplerID(vk_sampler);2706}27072708void RenderingDeviceDriverVulkan::sampler_free(SamplerID p_sampler) {2709vkDestroySampler(vk_device, (VkSampler)p_sampler.id, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SAMPLER));2710}27112712bool RenderingDeviceDriverVulkan::sampler_is_format_supported_for_filter(DataFormat p_format, SamplerFilter p_filter) {2713switch (p_filter) {2714case SAMPLER_FILTER_NEAREST: {2715return true;2716}2717case SAMPLER_FILTER_LINEAR: {2718VkFormatProperties properties = {};2719vkGetPhysicalDeviceFormatProperties(physical_device, RD_TO_VK_FORMAT[p_format], &properties);2720return (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT);2721}2722}2723return false;2724}27252726/**********************/2727/**** VERTEX ARRAY ****/2728/**********************/27292730RDD::VertexFormatID RenderingDeviceDriverVulkan::vertex_format_create(Span<VertexAttribute> p_vertex_attribs, const VertexAttributeBindingsMap &p_vertex_bindings) {2731// Pre-bookkeep.2732VertexFormatInfo *vf_info = VersatileResource::allocate<VertexFormatInfo>(resources_allocator);27332734vf_info->vk_bindings.reserve(p_vertex_bindings.size());2735for (const VertexAttributeBindingsMap::KV &E : p_vertex_bindings) {2736const VertexAttributeBinding &binding = E.value;2737VkVertexInputBindingDescription vk_binding = {};2738vk_binding.binding = E.key;2739vk_binding.stride = binding.stride;2740vk_binding.inputRate = binding.frequency == VERTEX_FREQUENCY_INSTANCE ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;2741vf_info->vk_bindings.push_back(vk_binding);2742}2743vf_info->vk_attributes.resize(p_vertex_attribs.size());2744for (uint32_t i = 0; i < p_vertex_attribs.size(); i++) {2745vf_info->vk_attributes[i] = {};2746vf_info->vk_attributes[i].binding = p_vertex_attribs[i].binding;2747vf_info->vk_attributes[i].location = p_vertex_attribs[i].location;2748vf_info->vk_attributes[i].format = RD_TO_VK_FORMAT[p_vertex_attribs[i].format];2749vf_info->vk_attributes[i].offset = p_vertex_attribs[i].offset;2750}27512752vf_info->vk_create_info = {};2753vf_info->vk_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;2754vf_info->vk_create_info.vertexBindingDescriptionCount = vf_info->vk_bindings.size();2755vf_info->vk_create_info.pVertexBindingDescriptions = vf_info->vk_bindings.ptr();2756vf_info->vk_create_info.vertexAttributeDescriptionCount = vf_info->vk_attributes.size();2757vf_info->vk_create_info.pVertexAttributeDescriptions = vf_info->vk_attributes.ptr();27582759return VertexFormatID(vf_info);2760}27612762void RenderingDeviceDriverVulkan::vertex_format_free(VertexFormatID p_vertex_format) {2763VertexFormatInfo *vf_info = (VertexFormatInfo *)p_vertex_format.id;2764VersatileResource::free(resources_allocator, vf_info);2765}27662767/******************/2768/**** BARRIERS ****/2769/******************/27702771// RDD::PipelineStageBits == VkPipelineStageFlagBits.2772static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT));2773static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT));2774static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT));2775static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT));2776static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT));2777static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT));2778static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_GEOMETRY_SHADER_BIT, VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT));2779static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT));2780static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT));2781static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT));2782static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT));2783static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT));2784static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT));2785static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT));2786static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT));2787static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR));2788static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT, VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT));2789static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_RAY_TRACING_SHADER_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR));2790static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR));27912792// RDD::BarrierAccessBits == VkAccessFlagBits.2793static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_INDIRECT_COMMAND_READ_BIT, VK_ACCESS_INDIRECT_COMMAND_READ_BIT));2794static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_INDEX_READ_BIT, VK_ACCESS_INDEX_READ_BIT));2795static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT));2796static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_UNIFORM_READ_BIT, VK_ACCESS_UNIFORM_READ_BIT));2797static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_INPUT_ATTACHMENT_READ_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT));2798static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_READ_BIT));2799static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT));2800static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT));2801static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT));2802static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT));2803static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT));2804static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_HOST_READ_BIT, VK_ACCESS_HOST_READ_BIT));2805static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_HOST_WRITE_BIT, VK_ACCESS_HOST_WRITE_BIT));2806static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_MEMORY_READ_BIT, VK_ACCESS_MEMORY_READ_BIT));2807static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_MEMORY_WRITE_BIT, VK_ACCESS_MEMORY_WRITE_BIT));2808static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT, VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR));2809static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_FRAGMENT_DENSITY_MAP_ATTACHMENT_READ_BIT, VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT));2810static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_ACCELERATION_STRUCTURE_READ_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR));2811static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR));28122813void RenderingDeviceDriverVulkan::command_pipeline_barrier(2814CommandBufferID p_cmd_buffer,2815BitField<PipelineStageBits> p_src_stages,2816BitField<PipelineStageBits> p_dst_stages,2817VectorView<MemoryAccessBarrier> p_memory_barriers,2818VectorView<BufferBarrier> p_buffer_barriers,2819VectorView<TextureBarrier> p_texture_barriers,2820VectorView<AccelerationStructureBarrier> p_acceleration_structure_barriers) {2821VkMemoryBarrier *vk_memory_barriers = ALLOCA_ARRAY(VkMemoryBarrier, p_memory_barriers.size());2822for (uint32_t i = 0; i < p_memory_barriers.size(); i++) {2823vk_memory_barriers[i] = {};2824vk_memory_barriers[i].sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;2825vk_memory_barriers[i].srcAccessMask = _rd_to_vk_access_flags(p_memory_barriers[i].src_access) & ~VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;2826vk_memory_barriers[i].dstAccessMask = _rd_to_vk_access_flags(p_memory_barriers[i].dst_access) & ~VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;2827}28282829VkBufferMemoryBarrier *vk_buffer_barriers = ALLOCA_ARRAY(VkBufferMemoryBarrier, p_buffer_barriers.size());2830for (uint32_t i = 0; i < p_buffer_barriers.size(); i++) {2831vk_buffer_barriers[i] = {};2832vk_buffer_barriers[i].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;2833vk_buffer_barriers[i].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;2834vk_buffer_barriers[i].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;2835vk_buffer_barriers[i].srcAccessMask = _rd_to_vk_access_flags(p_buffer_barriers[i].src_access) & ~VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;2836vk_buffer_barriers[i].dstAccessMask = _rd_to_vk_access_flags(p_buffer_barriers[i].dst_access) & ~VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;2837vk_buffer_barriers[i].buffer = ((const BufferInfo *)p_buffer_barriers[i].buffer.id)->vk_buffer;2838vk_buffer_barriers[i].offset = p_buffer_barriers[i].offset;2839vk_buffer_barriers[i].size = p_buffer_barriers[i].size;2840}28412842VkImageMemoryBarrier *vk_image_barriers = ALLOCA_ARRAY(VkImageMemoryBarrier, p_texture_barriers.size());2843for (uint32_t i = 0; i < p_texture_barriers.size(); i++) {2844const TextureInfo *tex_info = (const TextureInfo *)p_texture_barriers[i].texture.id;2845vk_image_barriers[i] = {};2846vk_image_barriers[i].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;2847vk_image_barriers[i].srcAccessMask = _rd_to_vk_access_flags(p_texture_barriers[i].src_access);2848vk_image_barriers[i].dstAccessMask = _rd_to_vk_access_flags(p_texture_barriers[i].dst_access);2849vk_image_barriers[i].oldLayout = RD_TO_VK_LAYOUT[p_texture_barriers[i].prev_layout];2850vk_image_barriers[i].newLayout = RD_TO_VK_LAYOUT[p_texture_barriers[i].next_layout];2851vk_image_barriers[i].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;2852vk_image_barriers[i].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;2853vk_image_barriers[i].image = tex_info->vk_view_create_info.image;2854vk_image_barriers[i].subresourceRange.aspectMask = (VkImageAspectFlags)p_texture_barriers[i].subresources.aspect;2855vk_image_barriers[i].subresourceRange.baseMipLevel = p_texture_barriers[i].subresources.base_mipmap;2856vk_image_barriers[i].subresourceRange.levelCount = p_texture_barriers[i].subresources.mipmap_count;2857vk_image_barriers[i].subresourceRange.baseArrayLayer = p_texture_barriers[i].subresources.base_layer;2858vk_image_barriers[i].subresourceRange.layerCount = p_texture_barriers[i].subresources.layer_count;2859}28602861VkPipelineStageFlags src_stage_flags = _rd_to_vk_pipeline_stages(p_src_stages);2862VkPipelineStageFlags dst_stage_flags = _rd_to_vk_pipeline_stages(p_dst_stages);2863VkPipelineStageFlags accel_src_stages = src_stage_flags;2864VkPipelineStageFlags accel_dst_stages = dst_stage_flags;28652866VkBufferMemoryBarrier *vk_accel_barriers = ALLOCA_ARRAY(VkBufferMemoryBarrier, p_acceleration_structure_barriers.size());2867for (uint32_t i = 0; i < p_acceleration_structure_barriers.size(); i++) {2868// If the rayQuery feature is not enabled and a memory barrier srcAccessMask includes2869// VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, srcStageMask must not include any of the2870// VK_PIPELINE_STAGE_*_SHADER_BIT stages except VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR2871VkAccessFlags src_access = _rd_to_vk_access_flags(p_acceleration_structure_barriers[i].src_access);2872if ((src_access & VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR) != 0) {2873accel_src_stages &= ~(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);2874}28752876// If the rayQuery feature is not enabled and a memory barrier dstAccessMask includes2877// VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, dstStageMask must not include any of the2878// VK_PIPELINE_STAGE_*_SHADER_BIT stages except VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR2879VkAccessFlags dst_access = _rd_to_vk_access_flags(p_acceleration_structure_barriers[i].dst_access);2880if ((dst_access & VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR) != 0) {2881accel_dst_stages &= ~(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);2882}28832884const AccelerationStructureInfo *accel_info = (const AccelerationStructureInfo *)p_acceleration_structure_barriers[i].acceleration_structure.id;2885vk_accel_barriers[i] = {};2886vk_accel_barriers[i].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;2887vk_accel_barriers[i].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;2888vk_accel_barriers[i].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;2889vk_accel_barriers[i].srcAccessMask = src_access;2890vk_accel_barriers[i].dstAccessMask = dst_access;2891vk_accel_barriers[i].buffer = ((const BufferInfo *)accel_info->buffer.id)->vk_buffer;2892vk_accel_barriers[i].offset = p_acceleration_structure_barriers[i].offset;2893vk_accel_barriers[i].size = p_acceleration_structure_barriers[i].size;2894}28952896#if PRINT_NATIVE_COMMANDS2897print_line(vformat("vkCmdPipelineBarrier MEMORY %d BUFFER %d TEXTURE %d ACCELERATION STRUCTURE %d", p_memory_barriers.size(), p_buffer_barriers.size(), p_texture_barriers.size(), p_acceleration_structure_barriers.size()));2898for (uint32_t i = 0; i < p_memory_barriers.size(); i++) {2899print_line(vformat(" VkMemoryBarrier #%d src 0x%uX dst 0x%uX", i, vk_memory_barriers[i].srcAccessMask, vk_memory_barriers[i].dstAccessMask));2900}29012902for (uint32_t i = 0; i < p_buffer_barriers.size(); i++) {2903print_line(vformat(" VkBufferMemoryBarrier #%d src 0x%uX dst 0x%uX buffer 0x%ux", i, vk_buffer_barriers[i].srcAccessMask, vk_buffer_barriers[i].dstAccessMask, uint64_t(vk_buffer_barriers[i].buffer)));2904}29052906for (uint32_t i = 0; i < p_texture_barriers.size(); i++) {2907print_line(vformat(" VkImageMemoryBarrier #%d src 0x%uX dst 0x%uX image 0x%ux old %d new %d (%d %d %d %d)", i, vk_image_barriers[i].srcAccessMask, vk_image_barriers[i].dstAccessMask,2908uint64_t(vk_image_barriers[i].image), vk_image_barriers[i].oldLayout, vk_image_barriers[i].newLayout, vk_image_barriers[i].subresourceRange.baseMipLevel, vk_image_barriers[i].subresourceRange.levelCount,2909vk_image_barriers[i].subresourceRange.baseArrayLayer, vk_image_barriers[i].subresourceRange.layerCount));2910}29112912for (uint32_t i = 0; i < p_acceleration_structure_barriers.size(); i++) {2913print_line(vformat(" VkBufferMemoryBarrier #%d src 0x%uX dst 0x%uX acceleration structure buffer 0x%ux", i, vk_accel_barriers[i].srcAccessMask, vk_accel_barriers[i].dstAccessMask, uint64_t(vk_accel_barriers[i].buffer)));2914}2915#endif29162917const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;2918vkCmdPipelineBarrier(2919command_buffer->vk_command_buffer,2920src_stage_flags,2921dst_stage_flags,29220,2923p_memory_barriers.size(), vk_memory_barriers,2924p_buffer_barriers.size(), vk_buffer_barriers,2925p_texture_barriers.size(), vk_image_barriers);29262927if (p_acceleration_structure_barriers.size() > 0) {2928vkCmdPipelineBarrier(2929command_buffer->vk_command_buffer,2930accel_src_stages,2931accel_dst_stages,29320,29330, nullptr,2934p_acceleration_structure_barriers.size(), vk_accel_barriers,29350, nullptr);2936}2937}29382939/****************/2940/**** FENCES ****/2941/****************/29422943RDD::FenceID RenderingDeviceDriverVulkan::fence_create() {2944VkFence vk_fence = VK_NULL_HANDLE;2945VkFenceCreateInfo create_info = {};2946create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;2947VkResult err = vkCreateFence(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FENCE), &vk_fence);2948ERR_FAIL_COND_V(err != VK_SUCCESS, FenceID());29492950Fence *fence = memnew(Fence);2951fence->vk_fence = vk_fence;2952fence->queue_signaled_from = nullptr;2953return FenceID(fence);2954}29552956Error RenderingDeviceDriverVulkan::fence_wait(FenceID p_fence) {2957Fence *fence = (Fence *)(p_fence.id);2958VkResult fence_status = vkGetFenceStatus(vk_device, fence->vk_fence);2959if (fence_status == VK_NOT_READY) {2960VkResult err = vkWaitForFences(vk_device, 1, &fence->vk_fence, VK_TRUE, UINT64_MAX);2961ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED);2962}29632964VkResult err = vkResetFences(vk_device, 1, &fence->vk_fence);2965ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED);29662967if (fence->queue_signaled_from != nullptr) {2968// Release all semaphores that the command queue associated to the fence waited on the last time it was submitted.2969LocalVector<Pair<Fence *, uint32_t>> &pairs = fence->queue_signaled_from->image_semaphores_for_fences;2970uint32_t i = 0;2971while (i < pairs.size()) {2972if (pairs[i].first == fence) {2973_release_image_semaphore(fence->queue_signaled_from, pairs[i].second, true);2974fence->queue_signaled_from->free_image_semaphores.push_back(pairs[i].second);2975pairs.remove_at(i);2976} else {2977i++;2978}2979}29802981fence->queue_signaled_from = nullptr;2982}29832984return OK;2985}29862987void RenderingDeviceDriverVulkan::fence_free(FenceID p_fence) {2988Fence *fence = (Fence *)(p_fence.id);2989vkDestroyFence(vk_device, fence->vk_fence, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FENCE));2990memdelete(fence);2991}29922993/********************/2994/**** SEMAPHORES ****/2995/********************/29962997RDD::SemaphoreID RenderingDeviceDriverVulkan::semaphore_create() {2998VkSemaphore semaphore = VK_NULL_HANDLE;2999VkSemaphoreCreateInfo create_info = {};3000create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;3001VkResult err = vkCreateSemaphore(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE), &semaphore);3002ERR_FAIL_COND_V(err != VK_SUCCESS, SemaphoreID());30033004return SemaphoreID(semaphore);3005}30063007void RenderingDeviceDriverVulkan::semaphore_free(SemaphoreID p_semaphore) {3008vkDestroySemaphore(vk_device, VkSemaphore(p_semaphore.id), VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE));3009}30103011/******************/3012/**** COMMANDS ****/3013/******************/30143015// ----- QUEUE FAMILY -----30163017RDD::CommandQueueFamilyID RenderingDeviceDriverVulkan::command_queue_family_get(BitField<CommandQueueFamilyBits> p_cmd_queue_family_bits, RenderingContextDriver::SurfaceID p_surface) {3018// Pick the queue with the least amount of bits that can fulfill the requirements.3019VkQueueFlags picked_queue_flags = VK_QUEUE_FLAG_BITS_MAX_ENUM;3020uint32_t picked_family_index = UINT_MAX;3021for (uint32_t i = 0; i < queue_family_properties.size(); i++) {3022if (queue_families[i].is_empty()) {3023// Ignore empty queue families.3024continue;3025}30263027if (p_surface != 0 && !context_driver->queue_family_supports_present(physical_device, i, p_surface)) {3028// Present is not an actual bit but something that must be queried manually.3029continue;3030}30313032// Preferring a queue with less bits will get us closer to getting a queue that performs better for our requirements.3033// For example, dedicated compute and transfer queues are usually indicated as such.3034const VkQueueFlags option_queue_flags = queue_family_properties[i].queueFlags;3035const bool includes_all_bits = p_cmd_queue_family_bits.get_shared(option_queue_flags) == p_cmd_queue_family_bits;3036const bool prefer_less_bits = option_queue_flags < picked_queue_flags;3037if (includes_all_bits && prefer_less_bits) {3038picked_family_index = i;3039picked_queue_flags = option_queue_flags;3040}3041}30423043if (picked_family_index >= queue_family_properties.size()) {3044return CommandQueueFamilyID();3045}30463047// Since 0 is a valid index and we use 0 as the error case, we make the index start from 1 instead.3048return CommandQueueFamilyID(picked_family_index + 1);3049}30503051// ----- QUEUE -----30523053RDD::CommandQueueID RenderingDeviceDriverVulkan::command_queue_create(CommandQueueFamilyID p_cmd_queue_family, bool p_identify_as_main_queue) {3054DEV_ASSERT(p_cmd_queue_family.id != 0);30553056// Make a virtual queue on top of a real queue. Use the queue from the family with the least amount of virtual queues created.3057uint32_t family_index = p_cmd_queue_family.id - 1;3058TightLocalVector<Queue> &queue_family = queue_families[family_index];3059uint32_t picked_queue_index = UINT_MAX;3060uint32_t picked_virtual_count = UINT_MAX;3061for (uint32_t i = 0; i < queue_family.size(); i++) {3062if (queue_family[i].virtual_count < picked_virtual_count) {3063picked_queue_index = i;3064picked_virtual_count = queue_family[i].virtual_count;3065}3066}30673068ERR_FAIL_COND_V_MSG(picked_queue_index >= queue_family.size(), CommandQueueID(), "A queue in the picked family could not be found.");30693070#if defined(SWAPPY_FRAME_PACING_ENABLED)3071if (swappy_frame_pacer_enable) {3072VkQueue selected_queue;3073vkGetDeviceQueue(vk_device, family_index, picked_queue_index, &selected_queue);3074SwappyVk_setQueueFamilyIndex(vk_device, selected_queue, family_index);3075}3076#endif30773078// Create the virtual queue.3079CommandQueue *command_queue = memnew(CommandQueue);3080command_queue->queue_family = family_index;3081command_queue->queue_index = picked_queue_index;3082queue_family[picked_queue_index].virtual_count++;30833084// If is was identified as the main queue and a hook is active, indicate it as such to the hook.3085if (p_identify_as_main_queue && (VulkanHooks::get_singleton() != nullptr)) {3086VulkanHooks::get_singleton()->set_direct_queue_family_and_index(family_index, picked_queue_index);3087}30883089return CommandQueueID(command_queue);3090}30913092Error RenderingDeviceDriverVulkan::command_queue_execute_and_present(CommandQueueID p_cmd_queue, VectorView<SemaphoreID> p_wait_semaphores, VectorView<CommandBufferID> p_cmd_buffers, VectorView<SemaphoreID> p_cmd_semaphores, FenceID p_cmd_fence, VectorView<SwapChainID> p_swap_chains) {3093DEV_ASSERT(p_cmd_queue.id != 0);30943095VkResult err;3096CommandQueue *command_queue = (CommandQueue *)(p_cmd_queue.id);3097Queue &device_queue = queue_families[command_queue->queue_family][command_queue->queue_index];3098Fence *fence = (Fence *)(p_cmd_fence.id);3099VkFence vk_fence = (fence != nullptr) ? fence->vk_fence : VK_NULL_HANDLE;31003101thread_local LocalVector<VkSemaphore> wait_semaphores;3102thread_local LocalVector<VkPipelineStageFlags> wait_semaphores_stages;3103wait_semaphores.clear();3104wait_semaphores_stages.clear();31053106if (!command_queue->pending_semaphores_for_execute.is_empty()) {3107for (uint32_t i = 0; i < command_queue->pending_semaphores_for_execute.size(); i++) {3108VkSemaphore wait_semaphore = command_queue->image_semaphores[command_queue->pending_semaphores_for_execute[i]];3109wait_semaphores.push_back(wait_semaphore);3110wait_semaphores_stages.push_back(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);3111}31123113command_queue->pending_semaphores_for_execute.clear();3114}31153116for (uint32_t i = 0; i < p_wait_semaphores.size(); i++) {3117// FIXME: Allow specifying the stage mask in more detail.3118wait_semaphores.push_back(VkSemaphore(p_wait_semaphores[i].id));3119wait_semaphores_stages.push_back(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);3120}31213122if (!pending_flushes.allocations.is_empty()) {3123// We must do this now, even if p_cmd_buffers is empty; because afterwards pending_flushes.allocations3124// could become dangling. We cannot delay this call for the next frame(s).3125err = vmaFlushAllocations(allocator, pending_flushes.allocations.size(),3126pending_flushes.allocations.ptr(), pending_flushes.offsets.ptr(),3127pending_flushes.sizes.ptr());3128pending_flushes.allocations.clear();3129pending_flushes.offsets.clear();3130pending_flushes.sizes.clear();3131ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED);3132}31333134if (p_cmd_buffers.size() > 0) {3135thread_local LocalVector<VkCommandBuffer> command_buffers;3136thread_local LocalVector<VkSemaphore> present_semaphores;3137thread_local LocalVector<VkSemaphore> signal_semaphores;3138command_buffers.clear();3139present_semaphores.clear();3140signal_semaphores.clear();31413142for (uint32_t i = 0; i < p_cmd_buffers.size(); i++) {3143const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)(p_cmd_buffers[i].id);3144command_buffers.push_back(command_buffer->vk_command_buffer);3145}31463147for (uint32_t i = 0; i < p_cmd_semaphores.size(); i++) {3148signal_semaphores.push_back(VkSemaphore(p_cmd_semaphores[i].id));3149}31503151for (uint32_t i = 0; i < p_swap_chains.size(); i++) {3152const SwapChain *swap_chain = (const SwapChain *)(p_swap_chains[i].id);3153VkSemaphore semaphore = swap_chain->present_semaphores[swap_chain->image_index];3154present_semaphores.push_back(semaphore);3155signal_semaphores.push_back(semaphore);3156}31573158VkSubmitInfo submit_info = {};3159submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;3160submit_info.waitSemaphoreCount = wait_semaphores.size();3161submit_info.pWaitSemaphores = wait_semaphores.ptr();3162submit_info.pWaitDstStageMask = wait_semaphores_stages.ptr();3163submit_info.commandBufferCount = command_buffers.size();3164submit_info.pCommandBuffers = command_buffers.ptr();3165submit_info.signalSemaphoreCount = signal_semaphores.size();3166submit_info.pSignalSemaphores = signal_semaphores.ptr();31673168device_queue.submit_mutex.lock();3169err = vkQueueSubmit(device_queue.queue, 1, &submit_info, vk_fence);3170device_queue.submit_mutex.unlock();31713172if (err == VK_ERROR_DEVICE_LOST) {3173print_lost_device_info();3174CRASH_NOW_MSG("Vulkan device was lost.");3175}3176ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED);31773178if (fence != nullptr && !command_queue->pending_semaphores_for_fence.is_empty()) {3179fence->queue_signaled_from = command_queue;31803181// Indicate to the fence that it should release the semaphores that were waited on this submission the next time the fence is waited on.3182for (uint32_t i = 0; i < command_queue->pending_semaphores_for_fence.size(); i++) {3183command_queue->image_semaphores_for_fences.push_back({ fence, command_queue->pending_semaphores_for_fence[i] });3184}31853186command_queue->pending_semaphores_for_fence.clear();3187}31883189if (!present_semaphores.is_empty()) {3190// If command buffers were executed, swap chains must wait on the present semaphore used by the command queue.3191wait_semaphores = present_semaphores;3192}3193}31943195if (p_swap_chains.size() > 0) {3196thread_local LocalVector<VkSwapchainKHR> swapchains;3197thread_local LocalVector<uint32_t> image_indices;3198thread_local LocalVector<VkResult> results;3199swapchains.clear();3200image_indices.clear();32013202for (uint32_t i = 0; i < p_swap_chains.size(); i++) {3203SwapChain *swap_chain = (SwapChain *)(p_swap_chains[i].id);3204swapchains.push_back(swap_chain->vk_swapchain);3205DEV_ASSERT(swap_chain->image_index < swap_chain->images.size());3206image_indices.push_back(swap_chain->image_index);3207}32083209results.resize(swapchains.size());32103211VkPresentInfoKHR present_info = {};3212present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;3213present_info.waitSemaphoreCount = wait_semaphores.size();3214present_info.pWaitSemaphores = wait_semaphores.ptr();3215present_info.swapchainCount = swapchains.size();3216present_info.pSwapchains = swapchains.ptr();3217present_info.pImageIndices = image_indices.ptr();3218present_info.pResults = results.ptr();32193220device_queue.submit_mutex.lock();3221#if defined(SWAPPY_FRAME_PACING_ENABLED)3222if (swappy_frame_pacer_enable) {3223err = SwappyVk_queuePresent(device_queue.queue, &present_info);3224} else {3225err = device_functions.QueuePresentKHR(device_queue.queue, &present_info);3226}3227#else3228err = device_functions.QueuePresentKHR(device_queue.queue, &present_info);3229#endif32303231device_queue.submit_mutex.unlock();32323233// Set the index to an invalid value. If any of the swap chains returned out of date, indicate it should be resized the next time it's acquired.3234bool any_result_is_out_of_date = false;3235for (uint32_t i = 0; i < p_swap_chains.size(); i++) {3236SwapChain *swap_chain = (SwapChain *)(p_swap_chains[i].id);3237swap_chain->image_index = UINT_MAX;3238if (results[i] == VK_ERROR_OUT_OF_DATE_KHR) {3239context_driver->surface_set_needs_resize(swap_chain->surface, true);3240any_result_is_out_of_date = true;3241}3242}32433244if (any_result_is_out_of_date || err == VK_ERROR_OUT_OF_DATE_KHR) {3245// It is possible for presentation to fail with out of date while acquire might've succeeded previously. This case3246// will be considered a silent failure as it can be triggered easily by resizing a window in the OS natively.3247return FAILED;3248}32493250// Handling VK_SUBOPTIMAL_KHR the same as VK_SUCCESS is completely intentional.3251//3252// Godot does not currently support native rotation in Android when creating the swap chain. It intentionally uses3253// VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR instead of the current transform bits available in the surface capabilities.3254// Choosing the transform that leads to optimal presentation leads to distortion that makes the application unusable,3255// as the rotation of all the content is not handled at the moment.3256//3257// VK_SUBOPTIMAL_KHR is accepted as a successful case even if it's not the most efficient solution to work around this3258// problem. This behavior should not be changed unless the swap chain recreation uses the current transform bits, as3259// it'll lead to very low performance in Android by entering an endless loop where it'll always resize the swap chain3260// every frame.32613262ERR_FAIL_COND_V_MSG(3263err != VK_SUCCESS && err != VK_SUBOPTIMAL_KHR,3264FAILED,3265"QueuePresentKHR failed with error: " + get_vulkan_result(err));3266}32673268return OK;3269}32703271void RenderingDeviceDriverVulkan::command_queue_free(CommandQueueID p_cmd_queue) {3272DEV_ASSERT(p_cmd_queue);32733274CommandQueue *command_queue = (CommandQueue *)(p_cmd_queue.id);32753276// Erase all the semaphores used for image acquisition.3277for (VkSemaphore semaphore : command_queue->image_semaphores) {3278vkDestroySemaphore(vk_device, semaphore, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE));3279}32803281// Retrieve the queue family corresponding to the virtual queue.3282DEV_ASSERT(command_queue->queue_family < queue_families.size());3283TightLocalVector<Queue> &queue_family = queue_families[command_queue->queue_family];32843285// Decrease the virtual queue count.3286DEV_ASSERT(command_queue->queue_index < queue_family.size());3287DEV_ASSERT(queue_family[command_queue->queue_index].virtual_count > 0);3288queue_family[command_queue->queue_index].virtual_count--;32893290// Destroy the virtual queue structure.3291memdelete(command_queue);3292}32933294// ----- POOL -----32953296RDD::CommandPoolID RenderingDeviceDriverVulkan::command_pool_create(CommandQueueFamilyID p_cmd_queue_family, CommandBufferType p_cmd_buffer_type) {3297DEV_ASSERT(p_cmd_queue_family.id != 0);32983299uint32_t family_index = p_cmd_queue_family.id - 1;3300VkCommandPoolCreateInfo cmd_pool_info = {};3301cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;3302cmd_pool_info.queueFamilyIndex = family_index;33033304if (!command_pool_reset_enabled) {3305cmd_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;3306}33073308VkCommandPool vk_command_pool = VK_NULL_HANDLE;3309VkResult res = vkCreateCommandPool(vk_device, &cmd_pool_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_COMMAND_POOL), &vk_command_pool);3310ERR_FAIL_COND_V_MSG(res, CommandPoolID(), "vkCreateCommandPool failed with error " + itos(res) + ".");33113312CommandPool *command_pool = memnew(CommandPool);3313command_pool->vk_command_pool = vk_command_pool;3314command_pool->buffer_type = p_cmd_buffer_type;3315return CommandPoolID(command_pool);3316}33173318bool RenderingDeviceDriverVulkan::command_pool_reset(CommandPoolID p_cmd_pool) {3319DEV_ASSERT(p_cmd_pool);33203321CommandPool *command_pool = (CommandPool *)(p_cmd_pool.id);3322VkResult err = vkResetCommandPool(vk_device, command_pool->vk_command_pool, 0);3323ERR_FAIL_COND_V_MSG(err, false, "vkResetCommandPool failed with error " + itos(err) + ".");33243325return true;3326}33273328void RenderingDeviceDriverVulkan::command_pool_free(CommandPoolID p_cmd_pool) {3329DEV_ASSERT(p_cmd_pool);33303331CommandPool *command_pool = (CommandPool *)(p_cmd_pool.id);3332for (CommandBufferInfo *command_buffer : command_pool->command_buffers_created) {3333VersatileResource::free(resources_allocator, command_buffer);3334}33353336vkDestroyCommandPool(vk_device, command_pool->vk_command_pool, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_COMMAND_POOL));3337memdelete(command_pool);3338}33393340// ----- BUFFER -----33413342RDD::CommandBufferID RenderingDeviceDriverVulkan::command_buffer_create(CommandPoolID p_cmd_pool) {3343DEV_ASSERT(p_cmd_pool);33443345CommandPool *command_pool = (CommandPool *)(p_cmd_pool.id);3346VkCommandBufferAllocateInfo cmd_buf_info = {};3347cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;3348cmd_buf_info.commandPool = command_pool->vk_command_pool;3349cmd_buf_info.commandBufferCount = 1;33503351if (command_pool->buffer_type == COMMAND_BUFFER_TYPE_SECONDARY) {3352cmd_buf_info.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;3353} else {3354cmd_buf_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;3355}33563357VkCommandBuffer vk_command_buffer = VK_NULL_HANDLE;3358VkResult err = vkAllocateCommandBuffers(vk_device, &cmd_buf_info, &vk_command_buffer);3359ERR_FAIL_COND_V_MSG(err, CommandBufferID(), "vkAllocateCommandBuffers failed with error " + itos(err) + ".");33603361CommandBufferInfo *command_buffer = VersatileResource::allocate<CommandBufferInfo>(resources_allocator);3362command_buffer->vk_command_buffer = vk_command_buffer;3363command_pool->command_buffers_created.push_back(command_buffer);3364return CommandBufferID(command_buffer);3365}33663367bool RenderingDeviceDriverVulkan::command_buffer_begin(CommandBufferID p_cmd_buffer) {3368CommandBufferInfo *command_buffer = (CommandBufferInfo *)(p_cmd_buffer.id);33693370VkCommandBufferBeginInfo cmd_buf_begin_info = {};3371cmd_buf_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;3372cmd_buf_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;33733374VkResult err = vkBeginCommandBuffer(command_buffer->vk_command_buffer, &cmd_buf_begin_info);3375ERR_FAIL_COND_V_MSG(err, false, "vkBeginCommandBuffer failed with error " + itos(err) + ".");33763377return true;3378}33793380bool RenderingDeviceDriverVulkan::command_buffer_begin_secondary(CommandBufferID p_cmd_buffer, RenderPassID p_render_pass, uint32_t p_subpass, FramebufferID p_framebuffer) {3381Framebuffer *framebuffer = (Framebuffer *)(p_framebuffer.id);3382RenderPassInfo *render_pass = (RenderPassInfo *)(p_render_pass.id);3383CommandBufferInfo *command_buffer = (CommandBufferInfo *)(p_cmd_buffer.id);33843385VkCommandBufferInheritanceInfo inheritance_info = {};3386inheritance_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;3387inheritance_info.renderPass = render_pass->vk_render_pass;3388inheritance_info.subpass = p_subpass;3389inheritance_info.framebuffer = framebuffer->vk_framebuffer;33903391VkCommandBufferBeginInfo cmd_buf_begin_info = {};3392cmd_buf_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;3393cmd_buf_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;3394cmd_buf_begin_info.pInheritanceInfo = &inheritance_info;33953396VkResult err = vkBeginCommandBuffer(command_buffer->vk_command_buffer, &cmd_buf_begin_info);3397ERR_FAIL_COND_V_MSG(err, false, "vkBeginCommandBuffer failed with error " + itos(err) + ".");33983399return true;3400}34013402void RenderingDeviceDriverVulkan::command_buffer_end(CommandBufferID p_cmd_buffer) {3403CommandBufferInfo *command_buffer = (CommandBufferInfo *)(p_cmd_buffer.id);3404vkEndCommandBuffer(command_buffer->vk_command_buffer);3405}34063407void RenderingDeviceDriverVulkan::command_buffer_execute_secondary(CommandBufferID p_cmd_buffer, VectorView<CommandBufferID> p_secondary_cmd_buffers) {3408thread_local LocalVector<VkCommandBuffer> secondary_command_buffers;3409CommandBufferInfo *command_buffer = (CommandBufferInfo *)(p_cmd_buffer.id);3410secondary_command_buffers.resize(p_secondary_cmd_buffers.size());3411for (uint32_t i = 0; i < p_secondary_cmd_buffers.size(); i++) {3412CommandBufferInfo *secondary_command_buffer = (CommandBufferInfo *)(p_secondary_cmd_buffers[i].id);3413secondary_command_buffers[i] = secondary_command_buffer->vk_command_buffer;3414}34153416vkCmdExecuteCommands(command_buffer->vk_command_buffer, p_secondary_cmd_buffers.size(), secondary_command_buffers.ptr());3417}34183419/********************/3420/**** SWAP CHAIN ****/3421/********************/34223423void RenderingDeviceDriverVulkan::_swap_chain_release(SwapChain *swap_chain) {3424// Destroy views and framebuffers associated to the swapchain's images.3425for (FramebufferID framebuffer : swap_chain->framebuffers) {3426framebuffer_free(framebuffer);3427}34283429for (VkImageView view : swap_chain->image_views) {3430vkDestroyImageView(vk_device, view, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW));3431}34323433swap_chain->image_index = UINT_MAX;3434swap_chain->images.clear();3435swap_chain->image_views.clear();3436swap_chain->framebuffers.clear();34373438if (swap_chain->vk_swapchain != VK_NULL_HANDLE) {3439#if defined(SWAPPY_FRAME_PACING_ENABLED)3440if (swappy_frame_pacer_enable) {3441// Swappy has a bug where the ANativeWindow will be leaked if we call3442// SwappyVk_destroySwapchain, so we must release it by hand.3443SwappyVk_setWindow(vk_device, swap_chain->vk_swapchain, nullptr);3444SwappyVk_destroySwapchain(vk_device, swap_chain->vk_swapchain);3445}3446#endif3447device_functions.DestroySwapchainKHR(vk_device, swap_chain->vk_swapchain, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SWAPCHAIN_KHR));3448swap_chain->vk_swapchain = VK_NULL_HANDLE;3449}34503451for (uint32_t i = 0; i < swap_chain->command_queues_acquired.size(); i++) {3452_recreate_image_semaphore(swap_chain->command_queues_acquired[i], swap_chain->command_queues_acquired_semaphores[i], false);3453}34543455swap_chain->command_queues_acquired.clear();3456swap_chain->command_queues_acquired_semaphores.clear();34573458for (VkSemaphore semaphore : swap_chain->present_semaphores) {3459vkDestroySemaphore(vk_device, semaphore, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE));3460}34613462swap_chain->present_semaphores.clear();3463}34643465RenderingDeviceDriver::SwapChainID RenderingDeviceDriverVulkan::swap_chain_create(RenderingContextDriver::SurfaceID p_surface) {3466DEV_ASSERT(p_surface != 0);34673468RenderingContextDriverVulkan::Surface *surface = (RenderingContextDriverVulkan::Surface *)(p_surface);3469const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get();34703471// Retrieve the formats supported by the surface.3472uint32_t format_count = 0;3473VkResult err = functions.GetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface->vk_surface, &format_count, nullptr);3474ERR_FAIL_COND_V(err != VK_SUCCESS, SwapChainID());34753476TightLocalVector<VkSurfaceFormatKHR> formats;3477formats.resize(format_count);3478err = functions.GetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface->vk_surface, &format_count, formats.ptr());3479ERR_FAIL_COND_V(err != VK_SUCCESS, SwapChainID());34803481VkFormat format = VK_FORMAT_UNDEFINED;3482VkColorSpaceKHR color_space = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;3483if (format_count == 1 && formats[0].format == VK_FORMAT_UNDEFINED) {3484// If the format list includes just one entry of VK_FORMAT_UNDEFINED, the surface has no preferred format.3485format = VK_FORMAT_B8G8R8A8_UNORM;3486color_space = formats[0].colorSpace;3487} else if (format_count > 0) {3488// Use one of the supported formats, prefer B8G8R8A8_UNORM.3489const VkFormat preferred_format = VK_FORMAT_B8G8R8A8_UNORM;3490const VkFormat second_format = VK_FORMAT_R8G8B8A8_UNORM;3491for (uint32_t i = 0; i < format_count; i++) {3492if (formats[i].format == preferred_format || formats[i].format == second_format) {3493format = formats[i].format;3494if (formats[i].format == preferred_format) {3495// This is the preferred format, stop searching.3496break;3497}3498}3499}3500}35013502// No formats are supported.3503ERR_FAIL_COND_V_MSG(format == VK_FORMAT_UNDEFINED, SwapChainID(), "Surface did not return any valid formats.");35043505// Create the render pass for the chosen format.3506VkAttachmentDescription2KHR attachment = {};3507attachment.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR;3508attachment.format = format;3509attachment.samples = VK_SAMPLE_COUNT_1_BIT;3510attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;3511attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;3512attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;3513attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;3514attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;3515attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;35163517VkAttachmentReference2KHR color_reference = {};3518color_reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;3519color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;35203521VkSubpassDescription2KHR subpass = {};3522subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR;3523subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;3524subpass.colorAttachmentCount = 1;3525subpass.pColorAttachments = &color_reference;35263527VkRenderPassCreateInfo2KHR pass_info = {};3528pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR;3529pass_info.attachmentCount = 1;3530pass_info.pAttachments = &attachment;3531pass_info.subpassCount = 1;3532pass_info.pSubpasses = &subpass;35333534VkRenderPass vk_render_pass = VK_NULL_HANDLE;3535err = _create_render_pass(vk_device, &pass_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_RENDER_PASS), &vk_render_pass);3536ERR_FAIL_COND_V(err != VK_SUCCESS, SwapChainID());35373538RenderPassInfo *render_pass_info = VersatileResource::allocate<RenderPassInfo>(resources_allocator);3539render_pass_info->vk_render_pass = vk_render_pass;35403541SwapChain *swap_chain = memnew(SwapChain);3542swap_chain->surface = p_surface;3543swap_chain->format = format;3544swap_chain->color_space = color_space;3545swap_chain->render_pass = RenderPassID(render_pass_info);3546return SwapChainID(swap_chain);3547}35483549Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, uint32_t p_desired_framebuffer_count) {3550DEV_ASSERT(p_cmd_queue.id != 0);3551DEV_ASSERT(p_swap_chain.id != 0);35523553CommandQueue *command_queue = (CommandQueue *)(p_cmd_queue.id);3554SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);35553556// Release all current contents of the swap chain.3557_swap_chain_release(swap_chain);35583559// Validate if the command queue being used supports creating the swap chain for this surface.3560const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get();3561if (!context_driver->queue_family_supports_present(physical_device, command_queue->queue_family, swap_chain->surface)) {3562ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Surface is not supported by device. Did the GPU go offline? Was the window created on another monitor? Check"3563"previous errors & try launching with --gpu-validation.");3564}35653566// Retrieve the surface's capabilities.3567RenderingContextDriverVulkan::Surface *surface = (RenderingContextDriverVulkan::Surface *)(swap_chain->surface);3568VkSurfaceCapabilitiesKHR surface_capabilities = {};3569VkResult err = functions.GetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface->vk_surface, &surface_capabilities);3570ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);35713572// No swapchain yet, this is the first time we're creating it.3573if (!swap_chain->vk_swapchain) {3574if (surface_capabilities.currentExtent.width == 0xFFFFFFFF) {3575// The current extent is currently undefined, so the current surface width and height will be clamped to the surface's capabilities.3576// We make sure to overwrite surface_capabilities.currentExtent.width so that the same check further below3577// does not set extent.width = CLAMP( surface->width, ... ) on the first run of this function, because3578// that'd be potentially unswapped.3579surface_capabilities.currentExtent.width = CLAMP(surface->width, surface_capabilities.minImageExtent.width, surface_capabilities.maxImageExtent.width);3580surface_capabilities.currentExtent.height = CLAMP(surface->height, surface_capabilities.minImageExtent.height, surface_capabilities.maxImageExtent.height);3581}35823583// We must SWAP() only once otherwise we'll keep ping-ponging between3584// the right and wrong resolutions after multiple calls to swap_chain_resize().3585if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR ||3586surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {3587// Swap to get identity width and height.3588SWAP(surface_capabilities.currentExtent.width, surface_capabilities.currentExtent.height);3589}3590}35913592VkExtent2D extent;3593if (surface_capabilities.currentExtent.width == 0xFFFFFFFF) {3594// The current extent is currently undefined, so the current surface width and height will be clamped to the surface's capabilities.3595// We can only be here on the second call to swap_chain_resize(), by which time surface->width & surface->height should already be swapped if needed.3596extent.width = CLAMP(surface->width, surface_capabilities.minImageExtent.width, surface_capabilities.maxImageExtent.width);3597extent.height = CLAMP(surface->height, surface_capabilities.minImageExtent.height, surface_capabilities.maxImageExtent.height);3598} else {3599// Grab the dimensions from the current extent.3600extent = surface_capabilities.currentExtent;3601surface->width = extent.width;3602surface->height = extent.height;3603}36043605if (surface->width == 0 || surface->height == 0) {3606// The surface doesn't have valid dimensions, so we can't create a swap chain.3607return ERR_SKIP;3608}36093610// Find what present modes are supported.3611TightLocalVector<VkPresentModeKHR> present_modes;3612uint32_t present_modes_count = 0;3613err = functions.GetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface->vk_surface, &present_modes_count, nullptr);3614ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);36153616present_modes.resize(present_modes_count);3617err = functions.GetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface->vk_surface, &present_modes_count, present_modes.ptr());3618ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);36193620// Choose the present mode based on the display server setting.3621VkPresentModeKHR present_mode = VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR;3622String present_mode_name = "Enabled";3623switch (surface->vsync_mode) {3624case DisplayServer::VSYNC_MAILBOX:3625present_mode = VK_PRESENT_MODE_MAILBOX_KHR;3626present_mode_name = "Mailbox";3627break;3628case DisplayServer::VSYNC_ADAPTIVE:3629present_mode = VK_PRESENT_MODE_FIFO_RELAXED_KHR;3630present_mode_name = "Adaptive";3631break;3632case DisplayServer::VSYNC_ENABLED:3633present_mode = VK_PRESENT_MODE_FIFO_KHR;3634present_mode_name = "Enabled";3635break;3636case DisplayServer::VSYNC_DISABLED:3637present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;3638present_mode_name = "Disabled";3639break;3640}36413642bool present_mode_available = present_modes.has(present_mode);3643if (!present_mode_available) {3644// Present mode is not available, fall back to FIFO which is guaranteed to be supported.3645WARN_PRINT(vformat("The requested V-Sync mode %s is not available. Falling back to V-Sync mode Enabled.", present_mode_name));3646surface->vsync_mode = DisplayServer::VSYNC_ENABLED;3647present_mode = VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR;3648}36493650// Clamp the desired image count to the surface's capabilities.3651uint32_t desired_swapchain_images = MAX(p_desired_framebuffer_count, surface_capabilities.minImageCount);3652if (surface_capabilities.maxImageCount > 0) {3653// Only clamp to the max image count if it's defined. A max image count of 0 means there's no upper limit to the amount of images.3654desired_swapchain_images = MIN(desired_swapchain_images, surface_capabilities.maxImageCount);3655}36563657// Refer to the comment in command_queue_present() for more details.3658VkSurfaceTransformFlagBitsKHR surface_transform_bits = surface_capabilities.currentTransform;36593660VkCompositeAlphaFlagBitsKHR composite_alpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;3661if (OS::get_singleton()->is_layered_allowed() || !(surface_capabilities.supportedCompositeAlpha & composite_alpha)) {3662// Find a supported composite alpha mode - one of these is guaranteed to be set.3663VkCompositeAlphaFlagBitsKHR composite_alpha_flags[4] = {3664VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,3665VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR,3666VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,3667VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR3668};36693670for (uint32_t i = 0; i < ARRAY_SIZE(composite_alpha_flags); i++) {3671if (surface_capabilities.supportedCompositeAlpha & composite_alpha_flags[i]) {3672composite_alpha = composite_alpha_flags[i];3673break;3674}3675}3676has_comp_alpha[(uint64_t)p_cmd_queue.id] = (composite_alpha != VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR);3677}36783679VkSwapchainCreateInfoKHR swap_create_info = {};3680swap_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;3681swap_create_info.surface = surface->vk_surface;3682swap_create_info.minImageCount = desired_swapchain_images;3683swap_create_info.imageFormat = swap_chain->format;3684swap_create_info.imageColorSpace = swap_chain->color_space;3685swap_create_info.imageExtent = extent;3686swap_create_info.imageArrayLayers = 1;3687swap_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;3688swap_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;3689swap_create_info.preTransform = surface_transform_bits;3690switch (swap_create_info.preTransform) {3691case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:3692swap_chain->pre_transform_rotation_degrees = 0;3693break;3694case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:3695swap_chain->pre_transform_rotation_degrees = 90;3696break;3697case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:3698swap_chain->pre_transform_rotation_degrees = 180;3699break;3700case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:3701swap_chain->pre_transform_rotation_degrees = 270;3702break;3703default:3704WARN_PRINT("Unexpected swap_create_info.preTransform = " + itos(swap_create_info.preTransform) + ".");3705swap_chain->pre_transform_rotation_degrees = 0;3706break;3707}3708swap_create_info.compositeAlpha = composite_alpha;3709swap_create_info.presentMode = present_mode;3710swap_create_info.clipped = true;3711err = device_functions.CreateSwapchainKHR(vk_device, &swap_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SWAPCHAIN_KHR), &swap_chain->vk_swapchain);3712ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);37133714#if defined(SWAPPY_FRAME_PACING_ENABLED)3715if (swappy_frame_pacer_enable) {3716SwappyVk_initAndGetRefreshCycleDuration(get_jni_env(), static_cast<OS_Android *>(OS::get_singleton())->get_godot_java()->get_activity(), physical_device,3717vk_device, swap_chain->vk_swapchain, &swap_chain->refresh_duration);3718SwappyVk_setWindow(vk_device, swap_chain->vk_swapchain, static_cast<OS_Android *>(OS::get_singleton())->get_native_window());3719SwappyVk_setSwapIntervalNS(vk_device, swap_chain->vk_swapchain, swap_chain->refresh_duration);37203721enum SwappyModes {3722PIPELINE_FORCED_ON,3723AUTO_FPS_PIPELINE_FORCED_ON,3724AUTO_FPS_AUTO_PIPELINE,3725};37263727switch (swappy_mode) {3728case PIPELINE_FORCED_ON:3729SwappyVk_setAutoSwapInterval(true);3730SwappyVk_setAutoPipelineMode(true);3731break;3732case AUTO_FPS_PIPELINE_FORCED_ON:3733SwappyVk_setAutoSwapInterval(true);3734SwappyVk_setAutoPipelineMode(false);3735break;3736case AUTO_FPS_AUTO_PIPELINE:3737SwappyVk_setAutoSwapInterval(false);3738SwappyVk_setAutoPipelineMode(false);3739break;3740}3741}3742#endif37433744uint32_t image_count = 0;3745err = device_functions.GetSwapchainImagesKHR(vk_device, swap_chain->vk_swapchain, &image_count, nullptr);3746ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);37473748swap_chain->images.resize(image_count);3749err = device_functions.GetSwapchainImagesKHR(vk_device, swap_chain->vk_swapchain, &image_count, swap_chain->images.ptr());3750ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);37513752VkImageViewCreateInfo view_create_info = {};3753view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;3754view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;3755view_create_info.format = swap_chain->format;3756view_create_info.components.r = VK_COMPONENT_SWIZZLE_R;3757view_create_info.components.g = VK_COMPONENT_SWIZZLE_G;3758view_create_info.components.b = VK_COMPONENT_SWIZZLE_B;3759view_create_info.components.a = VK_COMPONENT_SWIZZLE_A;3760view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;3761view_create_info.subresourceRange.levelCount = 1;3762view_create_info.subresourceRange.layerCount = 1;37633764swap_chain->image_views.reserve(image_count);37653766VkImageView image_view;3767for (uint32_t i = 0; i < image_count; i++) {3768view_create_info.image = swap_chain->images[i];3769err = vkCreateImageView(vk_device, &view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &image_view);3770ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);37713772swap_chain->image_views.push_back(image_view);3773}37743775swap_chain->framebuffers.reserve(image_count);37763777const RenderPassInfo *render_pass = (const RenderPassInfo *)(swap_chain->render_pass.id);3778VkFramebufferCreateInfo fb_create_info = {};3779fb_create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;3780fb_create_info.renderPass = render_pass->vk_render_pass;3781fb_create_info.attachmentCount = 1;3782fb_create_info.width = surface->width;3783fb_create_info.height = surface->height;3784fb_create_info.layers = 1;37853786VkFramebuffer vk_framebuffer;3787for (uint32_t i = 0; i < image_count; i++) {3788fb_create_info.pAttachments = &swap_chain->image_views[i];3789err = vkCreateFramebuffer(vk_device, &fb_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER), &vk_framebuffer);3790ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);37913792Framebuffer *framebuffer = memnew(Framebuffer);3793framebuffer->vk_framebuffer = vk_framebuffer;3794framebuffer->swap_chain_image = swap_chain->images[i];3795framebuffer->swap_chain_image_subresource_range = view_create_info.subresourceRange;3796swap_chain->framebuffers.push_back(RDD::FramebufferID(framebuffer));3797}37983799VkSemaphore vk_semaphore = VK_NULL_HANDLE;3800for (uint32_t i = 0; i < image_count; i++) {3801VkSemaphoreCreateInfo create_info = {};3802create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;38033804err = vkCreateSemaphore(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE), &vk_semaphore);3805ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED);38063807swap_chain->present_semaphores.push_back(vk_semaphore);3808}38093810// Once everything's been created correctly, indicate the surface no longer needs to be resized.3811context_driver->surface_set_needs_resize(swap_chain->surface, false);38123813return OK;3814}38153816RDD::FramebufferID RenderingDeviceDriverVulkan::swap_chain_acquire_framebuffer(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, bool &r_resize_required) {3817DEV_ASSERT(p_cmd_queue);3818DEV_ASSERT(p_swap_chain);38193820CommandQueue *command_queue = (CommandQueue *)(p_cmd_queue.id);3821SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);3822if ((swap_chain->vk_swapchain == VK_NULL_HANDLE) || context_driver->surface_get_needs_resize(swap_chain->surface)) {3823// The surface does not have a valid swap chain or it indicates it requires a resize.3824r_resize_required = true;3825return FramebufferID();3826}38273828VkResult err;3829VkSemaphore semaphore = VK_NULL_HANDLE;3830uint32_t semaphore_index = 0;3831if (command_queue->free_image_semaphores.is_empty()) {3832// Add a new semaphore if none are free.3833VkSemaphoreCreateInfo create_info = {};3834create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;3835err = vkCreateSemaphore(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE), &semaphore);3836ERR_FAIL_COND_V(err != VK_SUCCESS, FramebufferID());38373838semaphore_index = command_queue->image_semaphores.size();3839command_queue->image_semaphores.push_back(semaphore);3840command_queue->image_semaphores_swap_chains.push_back(swap_chain);3841} else {3842// Pick a free semaphore.3843uint32_t free_index = command_queue->free_image_semaphores.size() - 1;3844semaphore_index = command_queue->free_image_semaphores[free_index];3845command_queue->image_semaphores_swap_chains[semaphore_index] = swap_chain;3846command_queue->free_image_semaphores.remove_at(free_index);3847semaphore = command_queue->image_semaphores[semaphore_index];3848}38493850// Store in the swap chain the acquired semaphore.3851swap_chain->command_queues_acquired.push_back(command_queue);3852swap_chain->command_queues_acquired_semaphores.push_back(semaphore_index);38533854err = device_functions.AcquireNextImageKHR(vk_device, swap_chain->vk_swapchain, UINT64_MAX, semaphore, VK_NULL_HANDLE, &swap_chain->image_index);3855if (err == VK_ERROR_OUT_OF_DATE_KHR) {3856// Out of date leaves the semaphore in a signaled state that will never finish, so it's necessary to recreate it.3857bool semaphore_recreated = _recreate_image_semaphore(command_queue, semaphore_index, true);3858ERR_FAIL_COND_V(!semaphore_recreated, FramebufferID());38593860// Swap chain is out of date and must be recreated.3861r_resize_required = true;3862return FramebufferID();3863} else if (err != VK_SUCCESS && err != VK_SUBOPTIMAL_KHR) {3864// Swap chain failed to present but the reason is unknown.3865// Refer to the comment in command_queue_present() as to why VK_SUBOPTIMAL_KHR is handled the same as VK_SUCCESS.3866return FramebufferID();3867}38683869// Indicate the command queue should wait on these semaphores on the next submission and that it should3870// indicate they're free again on the next fence.3871command_queue->pending_semaphores_for_execute.push_back(semaphore_index);3872command_queue->pending_semaphores_for_fence.push_back(semaphore_index);38733874// Return the corresponding framebuffer to the new current image.3875FramebufferID framebuffer_id = swap_chain->framebuffers[swap_chain->image_index];3876Framebuffer *framebuffer = (Framebuffer *)(framebuffer_id.id);3877framebuffer->swap_chain_acquired = true;3878return framebuffer_id;3879}38803881RDD::RenderPassID RenderingDeviceDriverVulkan::swap_chain_get_render_pass(SwapChainID p_swap_chain) {3882DEV_ASSERT(p_swap_chain.id != 0);38833884SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);3885return swap_chain->render_pass;3886}38873888int RenderingDeviceDriverVulkan::swap_chain_get_pre_rotation_degrees(SwapChainID p_swap_chain) {3889DEV_ASSERT(p_swap_chain.id != 0);38903891SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);3892return swap_chain->pre_transform_rotation_degrees;3893}38943895RDD::DataFormat RenderingDeviceDriverVulkan::swap_chain_get_format(SwapChainID p_swap_chain) {3896DEV_ASSERT(p_swap_chain.id != 0);38973898SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);3899switch (swap_chain->format) {3900case VK_FORMAT_B8G8R8A8_UNORM:3901return DATA_FORMAT_B8G8R8A8_UNORM;3902case VK_FORMAT_R8G8B8A8_UNORM:3903return DATA_FORMAT_R8G8B8A8_UNORM;3904default:3905DEV_ASSERT(false && "Unknown swap chain format.");3906return DATA_FORMAT_MAX;3907}3908}39093910void RenderingDeviceDriverVulkan::swap_chain_set_max_fps(SwapChainID p_swap_chain, int p_max_fps) {3911DEV_ASSERT(p_swap_chain.id != 0);39123913#ifdef SWAPPY_FRAME_PACING_ENABLED3914if (!swappy_frame_pacer_enable) {3915return;3916}39173918SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);3919if (swap_chain->vk_swapchain != VK_NULL_HANDLE) {3920const uint64_t max_time = p_max_fps > 0 ? uint64_t((1000.0 * 1000.0 * 1000.0) / p_max_fps) : 0;3921SwappyVk_setSwapIntervalNS(vk_device, swap_chain->vk_swapchain, MAX(swap_chain->refresh_duration, max_time));3922}3923#endif3924}39253926void RenderingDeviceDriverVulkan::swap_chain_free(SwapChainID p_swap_chain) {3927DEV_ASSERT(p_swap_chain.id != 0);39283929SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);3930_swap_chain_release(swap_chain);39313932if (swap_chain->render_pass) {3933render_pass_free(swap_chain->render_pass);3934}39353936memdelete(swap_chain);3937}39383939/*********************/3940/**** FRAMEBUFFER ****/3941/*********************/39423943RDD::FramebufferID RenderingDeviceDriverVulkan::framebuffer_create(RenderPassID p_render_pass, VectorView<TextureID> p_attachments, uint32_t p_width, uint32_t p_height) {3944RenderPassInfo *render_pass = (RenderPassInfo *)(p_render_pass.id);39453946uint32_t fragment_density_map_offsets_layers = 0;3947VkImageView *vk_img_views = ALLOCA_ARRAY(VkImageView, p_attachments.size());3948for (uint32_t i = 0; i < p_attachments.size(); i++) {3949const TextureInfo *texture = (const TextureInfo *)p_attachments[i].id;3950vk_img_views[i] = texture->vk_view;3951}39523953VkFramebufferCreateInfo framebuffer_create_info = {};3954framebuffer_create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;3955framebuffer_create_info.renderPass = render_pass->vk_render_pass;3956framebuffer_create_info.attachmentCount = p_attachments.size();3957framebuffer_create_info.pAttachments = vk_img_views;3958framebuffer_create_info.width = p_width;3959framebuffer_create_info.height = p_height;3960framebuffer_create_info.layers = 1;39613962VkFramebuffer vk_framebuffer = VK_NULL_HANDLE;3963VkResult err = vkCreateFramebuffer(vk_device, &framebuffer_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER), &vk_framebuffer);3964ERR_FAIL_COND_V_MSG(err, FramebufferID(), "vkCreateFramebuffer failed with error " + itos(err) + ".");39653966#if PRINT_NATIVE_COMMANDS3967print_line(vformat("vkCreateFramebuffer 0x%uX with %d attachments", uint64_t(vk_framebuffer), p_attachments.size()));3968for (uint32_t i = 0; i < p_attachments.size(); i++) {3969const TextureInfo *attachment_info = (const TextureInfo *)p_attachments[i].id;3970print_line(vformat(" Attachment #%d: IMAGE 0x%uX VIEW 0x%uX", i, uint64_t(attachment_info->vk_view_create_info.image), uint64_t(attachment_info->vk_view)));3971}3972#endif39733974Framebuffer *framebuffer = memnew(Framebuffer);3975framebuffer->vk_framebuffer = vk_framebuffer;3976framebuffer->fragment_density_map_offsets_layers = fragment_density_map_offsets_layers;3977return FramebufferID(framebuffer);3978}39793980void RenderingDeviceDriverVulkan::framebuffer_free(FramebufferID p_framebuffer) {3981Framebuffer *framebuffer = (Framebuffer *)(p_framebuffer.id);3982vkDestroyFramebuffer(vk_device, framebuffer->vk_framebuffer, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER));3983memdelete(framebuffer);3984}39853986/****************/3987/**** SHADER ****/3988/****************/39893990static VkShaderStageFlagBits RD_STAGE_TO_VK_SHADER_STAGE_BITS[RDD::SHADER_STAGE_MAX] = {3991VK_SHADER_STAGE_VERTEX_BIT,3992VK_SHADER_STAGE_FRAGMENT_BIT,3993VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,3994VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,3995VK_SHADER_STAGE_COMPUTE_BIT,3996VK_SHADER_STAGE_RAYGEN_BIT_KHR,3997VK_SHADER_STAGE_ANY_HIT_BIT_KHR,3998VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,3999VK_SHADER_STAGE_MISS_BIT_KHR,4000VK_SHADER_STAGE_INTERSECTION_BIT_KHR,4001};40024003RDD::ShaderID RenderingDeviceDriverVulkan::shader_create_from_container(const Ref<RenderingShaderContainer> &p_shader_container, const Vector<ImmutableSampler> &p_immutable_samplers) {4004ShaderReflection shader_refl = p_shader_container->get_shader_reflection();4005ShaderInfo shader_info;4006shader_info.name = p_shader_container->shader_name.get_data();40074008for (uint32_t i = 0; i < SHADER_STAGE_MAX; i++) {4009if (shader_refl.push_constant_stages.has_flag((ShaderStage)(1 << i))) {4010shader_info.vk_push_constant_stages |= RD_STAGE_TO_VK_SHADER_STAGE_BITS[i];4011}4012}40134014// Set bindings.4015Vector<Vector<VkDescriptorSetLayoutBinding>> vk_set_bindings;4016vk_set_bindings.resize(shader_refl.uniform_sets.size());4017for (uint32_t i = 0; i < shader_refl.uniform_sets.size(); i++) {4018for (uint32_t j = 0; j < shader_refl.uniform_sets[i].size(); j++) {4019const ShaderUniform &uniform = shader_refl.uniform_sets[i][j];4020VkDescriptorSetLayoutBinding layout_binding = {};4021layout_binding.binding = uniform.binding;4022layout_binding.descriptorCount = 1;4023for (uint32_t k = 0; k < SHADER_STAGE_MAX; k++) {4024if ((uniform.stages.has_flag(ShaderStage(1U << k)))) {4025layout_binding.stageFlags |= RD_STAGE_TO_VK_SHADER_STAGE_BITS[k];4026}4027}40284029switch (uniform.type) {4030case UNIFORM_TYPE_SAMPLER: {4031layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;4032layout_binding.descriptorCount = uniform.length;4033// Immutable samplers: here they get set in the layoutbinding, given that they will not be changed later.4034int immutable_bind_index = -1;4035if (immutable_samplers_enabled && p_immutable_samplers.size() > 0) {4036for (int k = 0; k < p_immutable_samplers.size(); k++) {4037if (p_immutable_samplers[k].binding == layout_binding.binding) {4038immutable_bind_index = k;4039break;4040}4041}4042if (immutable_bind_index >= 0) {4043layout_binding.pImmutableSamplers = (VkSampler *)&p_immutable_samplers[immutable_bind_index].ids[0].id;4044}4045}4046} break;4047case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE: {4048layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;4049layout_binding.descriptorCount = uniform.length;4050} break;4051case UNIFORM_TYPE_TEXTURE: {4052layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;4053layout_binding.descriptorCount = uniform.length;4054} break;4055case UNIFORM_TYPE_IMAGE: {4056layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;4057layout_binding.descriptorCount = uniform.length;4058} break;4059case UNIFORM_TYPE_TEXTURE_BUFFER: {4060layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;4061layout_binding.descriptorCount = uniform.length;4062} break;4063case UNIFORM_TYPE_IMAGE_BUFFER: {4064layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;4065} break;4066case UNIFORM_TYPE_UNIFORM_BUFFER: {4067layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;4068} break;4069case UNIFORM_TYPE_UNIFORM_BUFFER_DYNAMIC: {4070layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;4071} break;4072case UNIFORM_TYPE_STORAGE_BUFFER: {4073layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;4074} break;4075case UNIFORM_TYPE_STORAGE_BUFFER_DYNAMIC: {4076layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;4077} break;4078case UNIFORM_TYPE_INPUT_ATTACHMENT: {4079layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;4080} break;4081case UNIFORM_TYPE_ACCELERATION_STRUCTURE: {4082layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;4083} break;4084default: {4085DEV_ASSERT(false);4086}4087}40884089vk_set_bindings.write[i].push_back(layout_binding);4090}4091}40924093// Modules.4094VkResult res;4095String error_text;4096Vector<uint8_t> decompressed_code;4097VkShaderModule vk_module;4098PackedByteArray decoded_spirv;4099const bool use_respv = RESPV_ENABLED && !shader_container_format.get_debug_info_enabled();4100const bool store_respv = use_respv && !shader_refl.specialization_constants.is_empty();4101const int64_t stage_count = shader_refl.stages_vector.size();4102shader_info.vk_stages_create_info.reserve(stage_count);4103shader_info.original_stage_size.reserve(stage_count);41044105#if RECORD_PIPELINE_STATISTICS4106shader_info.spirv_stage_bytes.reserve(stage_count);4107#endif41084109if (store_respv) {4110shader_info.respv_stage_shaders.reserve(stage_count);4111}41124113// AnyHit and ClosestHit go in the same group.4114uint32_t hit_group_index = UINT32_MAX;41154116for (int i = 0; i < stage_count; i++) {4117const RenderingShaderContainer::Shader &shader = p_shader_container->shaders[i];4118bool requires_decompression = (shader.code_decompressed_size > 0);4119if (requires_decompression) {4120decompressed_code.resize(shader.code_decompressed_size);4121bool decompressed = p_shader_container->decompress_code(shader.code_compressed_bytes.ptr(), shader.code_compressed_bytes.size(), shader.code_compression_flags, decompressed_code.ptrw(), decompressed_code.size());4122if (!decompressed) {4123error_text = vformat("Failed to decompress code on shader stage %s.", String(SHADER_STAGE_NAMES[shader_refl.stages_vector[i]]));4124break;4125}4126}41274128const uint8_t *smolv_input = requires_decompression ? decompressed_code.ptr() : shader.code_compressed_bytes.ptr();4129uint32_t smolv_input_size = requires_decompression ? decompressed_code.size() : shader.code_compressed_bytes.size();4130if (shader.code_compression_flags & RenderingShaderContainerVulkan::COMPRESSION_FLAG_SMOLV) {4131decoded_spirv.resize(smolv::GetDecodedBufferSize(smolv_input, smolv_input_size));4132if (decoded_spirv.is_empty()) {4133error_text = vformat("Malformed smolv input on shader stage %s.", String(SHADER_STAGE_NAMES[shader_refl.stages_vector[i]]));4134break;4135}41364137if (!smolv::Decode(smolv_input, smolv_input_size, decoded_spirv.ptrw(), decoded_spirv.size())) {4138error_text = vformat("Malformed smolv input on shader stage %s.", String(SHADER_STAGE_NAMES[shader_refl.stages_vector[i]]));4139break;4140}4141} else {4142decoded_spirv.resize(smolv_input_size);4143memcpy(decoded_spirv.ptrw(), smolv_input, decoded_spirv.size());4144}41454146shader_info.original_stage_size.push_back(decoded_spirv.size());41474148if (use_respv) {4149const bool inline_data = store_respv || !RESPV_ONLY_INLINE_SHADERS_WITH_SPEC_CONSTANTS;4150respv::Shader respv_shader(decoded_spirv.ptr(), decoded_spirv.size(), inline_data);4151if (respv_shader.empty()) {4152#if RESPV_VERBOSE4153print_line("re-spirv failed to parse the shader, skipping optimization.");4154#endif4155if (store_respv) {4156shader_info.respv_stage_shaders.push_back(respv::Shader());4157}4158} else if (store_respv) {4159shader_info.respv_stage_shaders.push_back(respv_shader);4160} else {4161std::vector<uint8_t> respv_optimized_data;4162if (respv::Optimizer::run(respv_shader, nullptr, 0, respv_optimized_data)) {4163#if RESPV_VERBOSE4164print_line(vformat("re-spirv transformed the shader from %d bytes to %d bytes.", decoded_spirv.size(), respv_optimized_data.size()));4165#endif4166decoded_spirv.resize(respv_optimized_data.size());4167memcpy(decoded_spirv.ptrw(), respv_optimized_data.data(), respv_optimized_data.size());4168} else {4169#if RESPV_VERBOSE4170print_line("re-spirv failed to optimize the shader.");4171#endif4172}4173}4174}41754176#if RECORD_PIPELINE_STATISTICS4177shader_info.spirv_stage_bytes.push_back(decoded_spirv);4178#endif41794180VkShaderModuleCreateInfo shader_module_create_info = {};4181shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;4182shader_module_create_info.codeSize = decoded_spirv.size();4183shader_module_create_info.pCode = (const uint32_t *)(decoded_spirv.ptr());41844185res = vkCreateShaderModule(vk_device, &shader_module_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SHADER_MODULE), &vk_module);4186if (res != VK_SUCCESS) {4187error_text = vformat("Error (%d) creating module for shader stage %s.", res, String(SHADER_STAGE_NAMES[shader_refl.stages_vector[i]]));4188break;4189}41904191VkPipelineShaderStageCreateInfo create_info = {};4192create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;4193create_info.stage = RD_STAGE_TO_VK_SHADER_STAGE_BITS[shader_refl.stages_vector[i]];4194create_info.module = vk_module;4195create_info.pName = "main";4196shader_info.vk_stages_create_info.push_back(create_info);41974198ShaderStage stage = shader_refl.stages_vector[i];41994200if (stage == ShaderStage::SHADER_STAGE_RAYGEN || stage == ShaderStage::SHADER_STAGE_MISS) {4201VkRayTracingShaderGroupCreateInfoKHR group_info = {};4202group_info.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;4203group_info.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;4204group_info.anyHitShader = VK_SHADER_UNUSED_KHR;4205group_info.closestHitShader = VK_SHADER_UNUSED_KHR;4206group_info.intersectionShader = VK_SHADER_UNUSED_KHR;4207group_info.generalShader = i;42084209shader_info.vk_groups_create_info.push_back(group_info);4210}4211if (stage == ShaderStage::SHADER_STAGE_ANY_HIT || stage == ShaderStage::SHADER_STAGE_CLOSEST_HIT) {4212if (hit_group_index == UINT32_MAX) {4213VkRayTracingShaderGroupCreateInfoKHR group_info = {};4214group_info.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;4215group_info.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;4216group_info.anyHitShader = VK_SHADER_UNUSED_KHR;4217group_info.closestHitShader = VK_SHADER_UNUSED_KHR;4218group_info.intersectionShader = VK_SHADER_UNUSED_KHR;4219group_info.generalShader = VK_SHADER_UNUSED_KHR;42204221hit_group_index = shader_info.vk_groups_create_info.size();4222shader_info.vk_groups_create_info.push_back(group_info);4223}42244225VkRayTracingShaderGroupCreateInfoKHR &group_info = shader_info.vk_groups_create_info[hit_group_index];4226if (stage == ShaderStage::SHADER_STAGE_ANY_HIT) {4227group_info.anyHitShader = i;4228} else if (stage == ShaderStage::SHADER_STAGE_CLOSEST_HIT) {4229group_info.closestHitShader = i;4230}4231}4232if (stage == ShaderStage::SHADER_STAGE_INTERSECTION) {4233VkRayTracingShaderGroupCreateInfoKHR group_info = {};4234group_info.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;4235group_info.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR;4236group_info.anyHitShader = VK_SHADER_UNUSED_KHR;4237group_info.closestHitShader = VK_SHADER_UNUSED_KHR;4238group_info.intersectionShader = i;4239group_info.generalShader = VK_SHADER_UNUSED_KHR;42404241shader_info.vk_groups_create_info.push_back(group_info);4242}4243}42444245// Descriptor sets.4246if (error_text.is_empty()) {4247// For Adreno 5XX driver bug.4248VkDescriptorSetLayoutBinding placeholder_binding = {};4249placeholder_binding.binding = 0;4250placeholder_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;4251placeholder_binding.descriptorCount = 1;4252placeholder_binding.stageFlags = VK_SHADER_STAGE_ALL;42534254for (uint32_t i = 0; i < shader_refl.uniform_sets.size(); i++) {4255// Empty ones are fine if they were not used according to spec (binding count will be 0).4256VkDescriptorSetLayoutCreateInfo layout_create_info = {};4257layout_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;4258layout_create_info.bindingCount = vk_set_bindings[i].size();4259layout_create_info.pBindings = vk_set_bindings[i].ptr();42604261// ...not so fine on Adreno 5XX.4262if (adreno_5xx_empty_descriptor_set_layout_workaround && layout_create_info.bindingCount == 0) {4263layout_create_info.bindingCount = 1;4264layout_create_info.pBindings = &placeholder_binding;4265}42664267VkDescriptorSetLayout layout = VK_NULL_HANDLE;4268res = vkCreateDescriptorSetLayout(vk_device, &layout_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT), &layout);4269if (res) {4270error_text = vformat("Error (%d) creating descriptor set layout for set %d.", res, i);4271break;4272}42734274shader_info.vk_descriptor_set_layouts.push_back(layout);4275}4276}42774278if (error_text.is_empty()) {4279// Pipeline layout.4280VkPipelineLayoutCreateInfo pipeline_layout_create_info = {};4281pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;4282pipeline_layout_create_info.setLayoutCount = shader_info.vk_descriptor_set_layouts.size();4283pipeline_layout_create_info.pSetLayouts = shader_info.vk_descriptor_set_layouts.ptr();42844285if (shader_refl.push_constant_size > 0) {4286VkPushConstantRange *push_constant_range = ALLOCA_SINGLE(VkPushConstantRange);4287*push_constant_range = {};4288push_constant_range->stageFlags = shader_info.vk_push_constant_stages;4289push_constant_range->size = shader_refl.push_constant_size;4290pipeline_layout_create_info.pushConstantRangeCount = 1;4291pipeline_layout_create_info.pPushConstantRanges = push_constant_range;4292}42934294res = vkCreatePipelineLayout(vk_device, &pipeline_layout_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE_LAYOUT), &shader_info.vk_pipeline_layout);4295if (res != VK_SUCCESS) {4296error_text = vformat("Error (%d) creating pipeline layout.", res);4297}4298}42994300if (!error_text.is_empty()) {4301// Clean up if failed.4302for (uint32_t i = 0; i < shader_info.vk_stages_create_info.size(); i++) {4303vkDestroyShaderModule(vk_device, shader_info.vk_stages_create_info[i].module, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SHADER_MODULE));4304}4305for (uint32_t i = 0; i < shader_info.vk_descriptor_set_layouts.size(); i++) {4306vkDestroyDescriptorSetLayout(vk_device, shader_info.vk_descriptor_set_layouts[i], VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT));4307}43084309ERR_FAIL_V_MSG(ShaderID(), error_text);4310}43114312if (shader_refl.pipeline_type == PIPELINE_TYPE_RAYTRACING) {4313// Regions43144315for (ShaderStage stage : shader_refl.stages_vector) {4316switch (stage) {4317case ShaderStage::SHADER_STAGE_RAYGEN:4318shader_info.region_count.raygen_count += 1;4319break;4320case ShaderStage::SHADER_STAGE_ANY_HIT:4321case ShaderStage::SHADER_STAGE_CLOSEST_HIT:4322shader_info.region_count.hit_count += 1;4323break;4324case ShaderStage::SHADER_STAGE_MISS:4325shader_info.region_count.miss_count += 1;4326break;4327default:4328// nothing4329break;4330}4331}43324333shader_info.region_count.group_count = shader_info.region_count.raygen_count + shader_info.region_count.hit_count + shader_info.region_count.miss_count;4334}43354336// Bookkeep.4337ShaderInfo *shader_info_ptr = VersatileResource::allocate<ShaderInfo>(resources_allocator);4338*shader_info_ptr = shader_info;4339return ShaderID(shader_info_ptr);4340}43414342void RenderingDeviceDriverVulkan::shader_free(ShaderID p_shader) {4343ShaderInfo *shader_info = (ShaderInfo *)p_shader.id;43444345for (uint32_t i = 0; i < shader_info->vk_descriptor_set_layouts.size(); i++) {4346vkDestroyDescriptorSetLayout(vk_device, shader_info->vk_descriptor_set_layouts[i], VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT));4347}43484349vkDestroyPipelineLayout(vk_device, shader_info->vk_pipeline_layout, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE_LAYOUT));43504351shader_destroy_modules(p_shader);43524353VersatileResource::free(resources_allocator, shader_info);4354}43554356void RenderingDeviceDriverVulkan::shader_destroy_modules(ShaderID p_shader) {4357ShaderInfo *si = (ShaderInfo *)p_shader.id;43584359for (uint32_t i = 0; i < si->vk_stages_create_info.size(); i++) {4360if (si->vk_stages_create_info[i].module) {4361vkDestroyShaderModule(vk_device, si->vk_stages_create_info[i].module,4362VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SHADER_MODULE));4363si->vk_stages_create_info[i].module = VK_NULL_HANDLE;4364}4365}4366si->vk_stages_create_info.clear();4367}43684369/*********************/4370/**** UNIFORM SET ****/4371/*********************/4372VkDescriptorPool RenderingDeviceDriverVulkan::_descriptor_set_pool_create(const DescriptorSetPoolKey &p_key, bool p_linear_pool) {4373// Here comes more vulkan API strangeness.4374VkDescriptorPoolSize *vk_sizes = ALLOCA_ARRAY(VkDescriptorPoolSize, UNIFORM_TYPE_MAX);4375uint32_t vk_sizes_count = 0;4376{4377VkDescriptorPoolSize *curr_vk_size = vk_sizes;4378if (p_key.uniform_type[UNIFORM_TYPE_SAMPLER]) {4379*curr_vk_size = {};4380curr_vk_size->type = VK_DESCRIPTOR_TYPE_SAMPLER;4381curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_SAMPLER] * max_descriptor_sets_per_pool;4382curr_vk_size++;4383vk_sizes_count++;4384}4385if (p_key.uniform_type[UNIFORM_TYPE_SAMPLER_WITH_TEXTURE]) {4386*curr_vk_size = {};4387curr_vk_size->type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;4388curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_SAMPLER_WITH_TEXTURE] * max_descriptor_sets_per_pool;4389curr_vk_size++;4390vk_sizes_count++;4391}4392if (p_key.uniform_type[UNIFORM_TYPE_TEXTURE]) {4393*curr_vk_size = {};4394curr_vk_size->type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;4395curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_TEXTURE] * max_descriptor_sets_per_pool;4396curr_vk_size++;4397vk_sizes_count++;4398}4399if (p_key.uniform_type[UNIFORM_TYPE_IMAGE]) {4400*curr_vk_size = {};4401curr_vk_size->type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;4402curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_IMAGE] * max_descriptor_sets_per_pool;4403curr_vk_size++;4404vk_sizes_count++;4405}4406if (p_key.uniform_type[UNIFORM_TYPE_TEXTURE_BUFFER] || p_key.uniform_type[UNIFORM_TYPE_SAMPLER_WITH_TEXTURE_BUFFER]) {4407*curr_vk_size = {};4408curr_vk_size->type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;4409curr_vk_size->descriptorCount = (p_key.uniform_type[UNIFORM_TYPE_TEXTURE_BUFFER] + p_key.uniform_type[UNIFORM_TYPE_SAMPLER_WITH_TEXTURE_BUFFER]) * max_descriptor_sets_per_pool;4410curr_vk_size++;4411vk_sizes_count++;4412}4413if (p_key.uniform_type[UNIFORM_TYPE_IMAGE_BUFFER]) {4414*curr_vk_size = {};4415curr_vk_size->type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;4416curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_IMAGE_BUFFER] * max_descriptor_sets_per_pool;4417curr_vk_size++;4418vk_sizes_count++;4419}4420if (p_key.uniform_type[UNIFORM_TYPE_UNIFORM_BUFFER]) {4421*curr_vk_size = {};4422curr_vk_size->type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;4423curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_UNIFORM_BUFFER] * max_descriptor_sets_per_pool;4424curr_vk_size++;4425vk_sizes_count++;4426}4427if (p_key.uniform_type[UNIFORM_TYPE_UNIFORM_BUFFER_DYNAMIC]) {4428*curr_vk_size = {};4429curr_vk_size->type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;4430curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_UNIFORM_BUFFER_DYNAMIC] * max_descriptor_sets_per_pool;4431curr_vk_size++;4432vk_sizes_count++;4433}4434if (p_key.uniform_type[UNIFORM_TYPE_STORAGE_BUFFER]) {4435*curr_vk_size = {};4436curr_vk_size->type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;4437curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_STORAGE_BUFFER] * max_descriptor_sets_per_pool;4438curr_vk_size++;4439vk_sizes_count++;4440}4441if (p_key.uniform_type[UNIFORM_TYPE_STORAGE_BUFFER_DYNAMIC]) {4442*curr_vk_size = {};4443curr_vk_size->type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;4444curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_STORAGE_BUFFER_DYNAMIC] * max_descriptor_sets_per_pool;4445curr_vk_size++;4446vk_sizes_count++;4447}4448if (p_key.uniform_type[UNIFORM_TYPE_INPUT_ATTACHMENT]) {4449*curr_vk_size = {};4450curr_vk_size->type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;4451curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_INPUT_ATTACHMENT] * max_descriptor_sets_per_pool;4452curr_vk_size++;4453vk_sizes_count++;4454}4455if (p_key.uniform_type[UNIFORM_TYPE_ACCELERATION_STRUCTURE]) {4456*curr_vk_size = {};4457curr_vk_size->type = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;4458curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_ACCELERATION_STRUCTURE] * max_descriptor_sets_per_pool;4459curr_vk_size++;4460vk_sizes_count++;4461}4462DEV_ASSERT(vk_sizes_count <= UNIFORM_TYPE_MAX);4463}44644465VkDescriptorPoolCreateInfo descriptor_set_pool_create_info = {};4466descriptor_set_pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;4467if (linear_descriptor_pools_enabled && p_linear_pool) {4468descriptor_set_pool_create_info.flags = 0;4469} else {4470descriptor_set_pool_create_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; // Can't think how somebody may NOT need this flag.4471}4472descriptor_set_pool_create_info.maxSets = max_descriptor_sets_per_pool;4473descriptor_set_pool_create_info.poolSizeCount = vk_sizes_count;4474descriptor_set_pool_create_info.pPoolSizes = vk_sizes;44754476VkDescriptorPool vk_pool = VK_NULL_HANDLE;4477VkResult res = vkCreateDescriptorPool(vk_device, &descriptor_set_pool_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DESCRIPTOR_POOL), &vk_pool);4478if (res) {4479ERR_FAIL_COND_V_MSG(res, VK_NULL_HANDLE, "vkCreateDescriptorPool failed with error " + itos(res) + ".");4480}44814482return vk_pool;4483}44844485void RenderingDeviceDriverVulkan::_descriptor_set_pool_unreference(DescriptorSetPools::Iterator p_pool_sets_it, VkDescriptorPool p_vk_descriptor_pool, int p_linear_pool_index) {4486HashMap<VkDescriptorPool, uint32_t>::Iterator pool_rcs_it = p_pool_sets_it->value.find(p_vk_descriptor_pool);4487pool_rcs_it->value--;4488if (pool_rcs_it->value == 0) {4489vkDestroyDescriptorPool(vk_device, p_vk_descriptor_pool, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DESCRIPTOR_POOL));4490p_pool_sets_it->value.erase(p_vk_descriptor_pool);4491if (p_pool_sets_it->value.is_empty()) {4492if (linear_descriptor_pools_enabled && p_linear_pool_index >= 0) {4493linear_descriptor_set_pools[p_linear_pool_index].remove(p_pool_sets_it);4494} else {4495descriptor_set_pools.remove(p_pool_sets_it);4496}4497}4498}4499}45004501RDD::UniformSetID RenderingDeviceDriverVulkan::uniform_set_create(VectorView<BoundUniform> p_uniforms, ShaderID p_shader, uint32_t p_set_index, int p_linear_pool_index) {4502if (!linear_descriptor_pools_enabled) {4503p_linear_pool_index = -1;4504}4505DescriptorSetPoolKey pool_key;45064507// We first gather dynamic arrays in a local array because TightLocalVector's4508// growth is not efficient when the number of elements is unknown.4509const BufferInfo *dynamic_buffers[MAX_DYNAMIC_BUFFERS];4510uint32_t num_dynamic_buffers = 0u;45114512// Immutable samplers will be skipped so we need to track the number of vk_writes used.4513VkWriteDescriptorSet *vk_writes = ALLOCA_ARRAY(VkWriteDescriptorSet, p_uniforms.size());4514uint32_t writes_amount = 0;4515for (uint32_t i = 0; i < p_uniforms.size(); i++) {4516const BoundUniform &uniform = p_uniforms[i];45174518vk_writes[writes_amount] = {};4519vk_writes[writes_amount].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;45204521bool add_write = true;4522uint32_t num_descriptors = 1;45234524switch (uniform.type) {4525case UNIFORM_TYPE_SAMPLER: {4526num_descriptors = uniform.ids.size();45274528if (uniform.immutable_sampler && immutable_samplers_enabled) {4529add_write = false;4530} else {4531VkDescriptorImageInfo *vk_img_infos = ALLOCA_ARRAY(VkDescriptorImageInfo, num_descriptors);45324533for (uint32_t j = 0; j < num_descriptors; j++) {4534vk_img_infos[j] = {};4535vk_img_infos[j].sampler = (VkSampler)uniform.ids[j].id;4536vk_img_infos[j].imageView = VK_NULL_HANDLE;4537vk_img_infos[j].imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;4538}45394540vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;4541vk_writes[writes_amount].pImageInfo = vk_img_infos;4542}4543} break;4544case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE: {4545num_descriptors = uniform.ids.size() / 2;4546VkDescriptorImageInfo *vk_img_infos = ALLOCA_ARRAY(VkDescriptorImageInfo, num_descriptors);45474548for (uint32_t j = 0; j < num_descriptors; j++) {4549#ifdef DEBUG_ENABLED4550if (((const TextureInfo *)uniform.ids[j * 2 + 1].id)->transient) {4551ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT texture must not be used for sampling in a shader.");4552}4553#endif4554vk_img_infos[j] = {};4555vk_img_infos[j].sampler = (VkSampler)uniform.ids[j * 2 + 0].id;4556vk_img_infos[j].imageView = ((const TextureInfo *)uniform.ids[j * 2 + 1].id)->vk_view;4557vk_img_infos[j].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;4558}45594560vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;4561vk_writes[writes_amount].pImageInfo = vk_img_infos;4562} break;4563case UNIFORM_TYPE_TEXTURE: {4564num_descriptors = uniform.ids.size();4565VkDescriptorImageInfo *vk_img_infos = ALLOCA_ARRAY(VkDescriptorImageInfo, num_descriptors);45664567for (uint32_t j = 0; j < num_descriptors; j++) {4568#ifdef DEBUG_ENABLED4569if (((const TextureInfo *)uniform.ids[j].id)->transient) {4570ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT texture must not be used for sampling in a shader.");4571}4572#endif4573vk_img_infos[j] = {};4574vk_img_infos[j].imageView = ((const TextureInfo *)uniform.ids[j].id)->vk_view;4575vk_img_infos[j].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;4576}45774578vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;4579vk_writes[writes_amount].pImageInfo = vk_img_infos;4580} break;4581case UNIFORM_TYPE_IMAGE: {4582num_descriptors = uniform.ids.size();4583VkDescriptorImageInfo *vk_img_infos = ALLOCA_ARRAY(VkDescriptorImageInfo, num_descriptors);45844585for (uint32_t j = 0; j < num_descriptors; j++) {4586#ifdef DEBUG_ENABLED4587if (((const TextureInfo *)uniform.ids[j].id)->transient) {4588ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT texture must not be used for sampling in a shader.");4589}4590#endif4591vk_img_infos[j] = {};4592vk_img_infos[j].imageView = ((const TextureInfo *)uniform.ids[j].id)->vk_view;4593vk_img_infos[j].imageLayout = VK_IMAGE_LAYOUT_GENERAL;4594}45954596vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;4597vk_writes[writes_amount].pImageInfo = vk_img_infos;4598} break;4599case UNIFORM_TYPE_TEXTURE_BUFFER: {4600num_descriptors = uniform.ids.size();4601VkDescriptorBufferInfo *vk_buf_infos = ALLOCA_ARRAY(VkDescriptorBufferInfo, num_descriptors);4602VkBufferView *vk_buf_views = ALLOCA_ARRAY(VkBufferView, num_descriptors);46034604for (uint32_t j = 0; j < num_descriptors; j++) {4605const BufferInfo *buf_info = (const BufferInfo *)uniform.ids[j].id;4606vk_buf_infos[j] = {};4607vk_buf_infos[j].buffer = buf_info->vk_buffer;4608vk_buf_infos[j].range = buf_info->size;46094610vk_buf_views[j] = buf_info->vk_view;4611}46124613vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;4614vk_writes[writes_amount].pBufferInfo = vk_buf_infos;4615vk_writes[writes_amount].pTexelBufferView = vk_buf_views;4616} break;4617case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE_BUFFER: {4618num_descriptors = uniform.ids.size() / 2;4619VkDescriptorImageInfo *vk_img_infos = ALLOCA_ARRAY(VkDescriptorImageInfo, num_descriptors);4620VkDescriptorBufferInfo *vk_buf_infos = ALLOCA_ARRAY(VkDescriptorBufferInfo, num_descriptors);4621VkBufferView *vk_buf_views = ALLOCA_ARRAY(VkBufferView, num_descriptors);46224623for (uint32_t j = 0; j < num_descriptors; j++) {4624vk_img_infos[j] = {};4625vk_img_infos[j].sampler = (VkSampler)uniform.ids[j * 2 + 0].id;46264627const BufferInfo *buf_info = (const BufferInfo *)uniform.ids[j * 2 + 1].id;4628vk_buf_infos[j] = {};4629vk_buf_infos[j].buffer = buf_info->vk_buffer;4630vk_buf_infos[j].range = buf_info->size;46314632vk_buf_views[j] = buf_info->vk_view;4633}46344635vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;4636vk_writes[writes_amount].pImageInfo = vk_img_infos;4637vk_writes[writes_amount].pBufferInfo = vk_buf_infos;4638vk_writes[writes_amount].pTexelBufferView = vk_buf_views;4639} break;4640case UNIFORM_TYPE_IMAGE_BUFFER: {4641CRASH_NOW_MSG("Unimplemented!"); // TODO.4642} break;4643case UNIFORM_TYPE_UNIFORM_BUFFER: {4644const BufferInfo *buf_info = (const BufferInfo *)uniform.ids[0].id;4645VkDescriptorBufferInfo *vk_buf_info = ALLOCA_SINGLE(VkDescriptorBufferInfo);4646*vk_buf_info = {};4647vk_buf_info->buffer = buf_info->vk_buffer;4648vk_buf_info->range = buf_info->size;46494650ERR_FAIL_COND_V_MSG(buf_info->is_dynamic(), UniformSetID(),4651"Sent a buffer with BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT but binding (" + itos(uniform.binding) + "), set (" + itos(p_set_index) + ") is UNIFORM_TYPE_UNIFORM_BUFFER instead of UNIFORM_TYPE_UNIFORM_BUFFER_DYNAMIC.");46524653vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;4654vk_writes[writes_amount].pBufferInfo = vk_buf_info;4655} break;4656case UNIFORM_TYPE_UNIFORM_BUFFER_DYNAMIC: {4657const BufferInfo *buf_info = (const BufferInfo *)uniform.ids[0].id;4658VkDescriptorBufferInfo *vk_buf_info = ALLOCA_SINGLE(VkDescriptorBufferInfo);4659*vk_buf_info = {};4660vk_buf_info->buffer = buf_info->vk_buffer;4661vk_buf_info->range = buf_info->size;46624663ERR_FAIL_COND_V_MSG(!buf_info->is_dynamic(), UniformSetID(),4664"Sent a buffer without BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT but binding (" + itos(uniform.binding) + "), set (" + itos(p_set_index) + ") is UNIFORM_TYPE_UNIFORM_BUFFER_DYNAMIC instead of UNIFORM_TYPE_UNIFORM_BUFFER.");4665ERR_FAIL_COND_V_MSG(num_dynamic_buffers >= MAX_DYNAMIC_BUFFERS, UniformSetID(),4666"Uniform set exceeded the limit of dynamic/persistent buffers. (" + itos(MAX_DYNAMIC_BUFFERS) + ").");46674668dynamic_buffers[num_dynamic_buffers++] = buf_info;4669vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;4670vk_writes[writes_amount].pBufferInfo = vk_buf_info;4671} break;4672case UNIFORM_TYPE_STORAGE_BUFFER: {4673const BufferInfo *buf_info = (const BufferInfo *)uniform.ids[0].id;4674VkDescriptorBufferInfo *vk_buf_info = ALLOCA_SINGLE(VkDescriptorBufferInfo);4675*vk_buf_info = {};4676vk_buf_info->buffer = buf_info->vk_buffer;4677vk_buf_info->range = buf_info->size;46784679ERR_FAIL_COND_V_MSG(buf_info->is_dynamic(), UniformSetID(),4680"Sent a buffer with BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT but binding (" + itos(uniform.binding) + "), set (" + itos(p_set_index) + ") is UNIFORM_TYPE_STORAGE_BUFFER instead of UNIFORM_TYPE_STORAGE_BUFFER_DYNAMIC.");46814682vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;4683vk_writes[writes_amount].pBufferInfo = vk_buf_info;4684} break;4685case UNIFORM_TYPE_STORAGE_BUFFER_DYNAMIC: {4686const BufferInfo *buf_info = (const BufferInfo *)uniform.ids[0].id;4687VkDescriptorBufferInfo *vk_buf_info = ALLOCA_SINGLE(VkDescriptorBufferInfo);4688*vk_buf_info = {};4689vk_buf_info->buffer = buf_info->vk_buffer;4690vk_buf_info->range = buf_info->size;46914692ERR_FAIL_COND_V_MSG(!buf_info->is_dynamic(), UniformSetID(),4693"Sent a buffer without BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT but binding (" + itos(uniform.binding) + "), set (" + itos(p_set_index) + ") is UNIFORM_TYPE_STORAGE_BUFFER_DYNAMIC instead of UNIFORM_TYPE_STORAGE_BUFFER.");4694ERR_FAIL_COND_V_MSG(num_dynamic_buffers >= MAX_DYNAMIC_BUFFERS, UniformSetID(),4695"Uniform set exceeded the limit of dynamic/persistent buffers. (" + itos(MAX_DYNAMIC_BUFFERS) + ").");46964697dynamic_buffers[num_dynamic_buffers++] = buf_info;4698vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;4699vk_writes[writes_amount].pBufferInfo = vk_buf_info;4700} break;4701case UNIFORM_TYPE_INPUT_ATTACHMENT: {4702num_descriptors = uniform.ids.size();4703VkDescriptorImageInfo *vk_img_infos = ALLOCA_ARRAY(VkDescriptorImageInfo, num_descriptors);47044705for (uint32_t j = 0; j < uniform.ids.size(); j++) {4706vk_img_infos[j] = {};4707vk_img_infos[j].imageView = ((const TextureInfo *)uniform.ids[j].id)->vk_view;4708vk_img_infos[j].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;4709}47104711vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;4712vk_writes[writes_amount].pImageInfo = vk_img_infos;4713} break;4714case UNIFORM_TYPE_ACCELERATION_STRUCTURE: {4715const AccelerationStructureInfo *accel_info = (const AccelerationStructureInfo *)uniform.ids[0].id;4716VkWriteDescriptorSetAccelerationStructureKHR *acceleration_structure_write = ALLOCA_SINGLE(VkWriteDescriptorSetAccelerationStructureKHR);4717*acceleration_structure_write = {};4718acceleration_structure_write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;4719acceleration_structure_write->accelerationStructureCount = 1;4720acceleration_structure_write->pAccelerationStructures = &accel_info->vk_acceleration_structure;47214722vk_writes[i].descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;4723vk_writes[i].pNext = acceleration_structure_write;4724} break;4725default: {4726DEV_ASSERT(false);4727}4728}47294730if (add_write) {4731vk_writes[writes_amount].dstBinding = uniform.binding;4732vk_writes[writes_amount].descriptorCount = num_descriptors;4733writes_amount++;4734}47354736ERR_FAIL_COND_V_MSG(pool_key.uniform_type[uniform.type] == MAX_UNIFORM_POOL_ELEMENT, UniformSetID(), "Uniform set reached the limit of bindings for the same type (" + itos(MAX_UNIFORM_POOL_ELEMENT) + ").");4737pool_key.uniform_type[uniform.type] += num_descriptors;4738}47394740bool linear_pool = p_linear_pool_index >= 0;4741DescriptorSetPools::Iterator pool_sets_it = linear_pool ? linear_descriptor_set_pools[p_linear_pool_index].find(pool_key) : descriptor_set_pools.find(pool_key);4742if (!pool_sets_it) {4743if (linear_pool) {4744pool_sets_it = linear_descriptor_set_pools[p_linear_pool_index].insert(pool_key, HashMap<VkDescriptorPool, uint32_t>());4745} else {4746pool_sets_it = descriptor_set_pools.insert(pool_key, HashMap<VkDescriptorPool, uint32_t>());4747}4748}47494750VkDescriptorSetAllocateInfo descriptor_set_allocate_info = {};4751descriptor_set_allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;4752descriptor_set_allocate_info.descriptorSetCount = 1;4753const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;4754descriptor_set_allocate_info.pSetLayouts = &shader_info->vk_descriptor_set_layouts[p_set_index];47554756VkDescriptorSet vk_descriptor_set = VK_NULL_HANDLE;4757for (KeyValue<VkDescriptorPool, uint32_t> &E : pool_sets_it->value) {4758if (E.value < max_descriptor_sets_per_pool) {4759descriptor_set_allocate_info.descriptorPool = E.key;4760VkResult res = vkAllocateDescriptorSets(vk_device, &descriptor_set_allocate_info, &vk_descriptor_set);47614762// Break early on success.4763if (res == VK_SUCCESS) {4764break;4765}47664767// "Fragmented pool" and "out of memory pool" errors are handled by creating more pools. Any other error is unexpected.4768if (res != VK_ERROR_FRAGMENTED_POOL && res != VK_ERROR_OUT_OF_POOL_MEMORY) {4769ERR_FAIL_V_MSG(UniformSetID(), "Cannot allocate descriptor sets, error " + itos(res) + ".");4770}4771}4772}47734774// Create a new pool when no allocations could be made from the existing pools.4775if (vk_descriptor_set == VK_NULL_HANDLE) {4776descriptor_set_allocate_info.descriptorPool = _descriptor_set_pool_create(pool_key, linear_pool);4777VkResult res = vkAllocateDescriptorSets(vk_device, &descriptor_set_allocate_info, &vk_descriptor_set);47784779// All errors are unexpected at this stage.4780if (res) {4781vkDestroyDescriptorPool(vk_device, descriptor_set_allocate_info.descriptorPool, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DESCRIPTOR_POOL));4782ERR_FAIL_V_MSG(UniformSetID(), "Cannot allocate descriptor sets, error " + itos(res) + ".");4783}4784}47854786DEV_ASSERT(descriptor_set_allocate_info.descriptorPool != VK_NULL_HANDLE && vk_descriptor_set != VK_NULL_HANDLE);4787pool_sets_it->value[descriptor_set_allocate_info.descriptorPool]++;47884789for (uint32_t i = 0; i < writes_amount; i++) {4790vk_writes[i].dstSet = vk_descriptor_set;4791}4792vkUpdateDescriptorSets(vk_device, writes_amount, vk_writes, 0, nullptr);47934794// Bookkeep.47954796UniformSetInfo *usi = VersatileResource::allocate<UniformSetInfo>(resources_allocator);4797usi->vk_descriptor_set = vk_descriptor_set;4798if (p_linear_pool_index >= 0) {4799usi->vk_linear_descriptor_pool = descriptor_set_allocate_info.descriptorPool;4800} else {4801usi->vk_descriptor_pool = descriptor_set_allocate_info.descriptorPool;4802}4803usi->pool_sets_it = pool_sets_it;4804usi->dynamic_buffers.resize(num_dynamic_buffers);4805for (uint32_t i = 0u; i < num_dynamic_buffers; ++i) {4806usi->dynamic_buffers[i] = dynamic_buffers[i];4807}48084809return UniformSetID(usi);4810}48114812void RenderingDeviceDriverVulkan::uniform_set_free(UniformSetID p_uniform_set) {4813UniformSetInfo *usi = (UniformSetInfo *)p_uniform_set.id;48144815if (usi->vk_linear_descriptor_pool) {4816// Nothing to do. All sets are freed at once using vkResetDescriptorPool.4817//4818// We can NOT decrease the reference count (i.e. call _descriptor_set_pool_unreference())4819// because the pool is linear (i.e. the freed set can't be recycled) and further calls to4820// _descriptor_set_pool_find_or_create() need usi->pool_sets_it->value to stay so that we can4821// tell if the pool has ran out of space and we need to create a new pool.4822} else {4823vkFreeDescriptorSets(vk_device, usi->vk_descriptor_pool, 1, &usi->vk_descriptor_set);4824_descriptor_set_pool_unreference(usi->pool_sets_it, usi->vk_descriptor_pool, -1);4825}48264827VersatileResource::free(resources_allocator, usi);4828}48294830bool RenderingDeviceDriverVulkan::uniform_sets_have_linear_pools() const {4831return true;4832}48334834uint32_t RenderingDeviceDriverVulkan::uniform_sets_get_dynamic_offsets(VectorView<UniformSetID> p_uniform_sets, ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count) const {4835uint32_t mask = 0u;4836uint32_t shift = 0u;4837#ifdef DEV_ENABLED4838uint32_t curr_dynamic_offset = 0u;4839#endif48404841for (uint32_t i = 0; i < p_set_count; i++) {4842const UniformSetInfo *usi = (const UniformSetInfo *)p_uniform_sets[i].id;4843// At this point this assert should already have been validated.4844DEV_ASSERT(curr_dynamic_offset + usi->dynamic_buffers.size() <= MAX_DYNAMIC_BUFFERS);48454846for (const BufferInfo *dynamic_buffer : usi->dynamic_buffers) {4847DEV_ASSERT(dynamic_buffer->frame_idx < 16u);4848mask |= dynamic_buffer->frame_idx << shift;4849shift += 4u;4850}4851#ifdef DEV_ENABLED4852curr_dynamic_offset += usi->dynamic_buffers.size();4853#endif4854}48554856return mask;4857}48584859void RenderingDeviceDriverVulkan::linear_uniform_set_pools_reset(int p_linear_pool_index) {4860if (linear_descriptor_pools_enabled) {4861DescriptorSetPools &pools_to_reset = linear_descriptor_set_pools[p_linear_pool_index];4862DescriptorSetPools::Iterator curr_pool = pools_to_reset.begin();48634864while (curr_pool != pools_to_reset.end()) {4865HashMap<VkDescriptorPool, uint32_t>::Iterator curr_pair = curr_pool->value.begin();4866while (curr_pair != curr_pool->value.end()) {4867vkResetDescriptorPool(vk_device, curr_pair->key, 0);4868curr_pair->value = 0;4869++curr_pair;4870}4871++curr_pool;4872}4873}4874}48754876// ----- COMMANDS -----48774878void RenderingDeviceDriverVulkan::command_uniform_set_prepare_for_use(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index) {4879}48804881/******************/4882/**** TRANSFER ****/4883/******************/48844885static_assert(ARRAYS_COMPATIBLE_FIELDWISE(RDD::BufferCopyRegion, VkBufferCopy));48864887static void _texture_subresource_range_to_vk(const RDD::TextureSubresourceRange &p_subresources, VkImageSubresourceRange *r_vk_subreources) {4888*r_vk_subreources = {};4889r_vk_subreources->aspectMask = (VkImageAspectFlags)p_subresources.aspect;4890r_vk_subreources->baseMipLevel = p_subresources.base_mipmap;4891r_vk_subreources->levelCount = p_subresources.mipmap_count;4892r_vk_subreources->baseArrayLayer = p_subresources.base_layer;4893r_vk_subreources->layerCount = p_subresources.layer_count;4894}48954896static void _texture_subresource_layers_to_vk(const RDD::TextureSubresourceLayers &p_subresources, VkImageSubresourceLayers *r_vk_subreources) {4897*r_vk_subreources = {};4898r_vk_subreources->aspectMask = (VkImageAspectFlags)p_subresources.aspect;4899r_vk_subreources->mipLevel = p_subresources.mipmap;4900r_vk_subreources->baseArrayLayer = p_subresources.base_layer;4901r_vk_subreources->layerCount = p_subresources.layer_count;4902}49034904static void _buffer_texture_copy_region_to_vk(const RDD::BufferTextureCopyRegion &p_copy_region, uint32_t p_buffer_row_length, VkBufferImageCopy *r_vk_copy_region) {4905*r_vk_copy_region = {};4906r_vk_copy_region->bufferOffset = p_copy_region.buffer_offset;4907r_vk_copy_region->bufferRowLength = p_buffer_row_length;4908r_vk_copy_region->imageSubresource.aspectMask = (VkImageAspectFlags)(1 << p_copy_region.texture_subresource.aspect);4909r_vk_copy_region->imageSubresource.mipLevel = p_copy_region.texture_subresource.mipmap;4910r_vk_copy_region->imageSubresource.baseArrayLayer = p_copy_region.texture_subresource.layer;4911r_vk_copy_region->imageSubresource.layerCount = 1;4912r_vk_copy_region->imageOffset.x = p_copy_region.texture_offset.x;4913r_vk_copy_region->imageOffset.y = p_copy_region.texture_offset.y;4914r_vk_copy_region->imageOffset.z = p_copy_region.texture_offset.z;4915r_vk_copy_region->imageExtent.width = p_copy_region.texture_region_size.x;4916r_vk_copy_region->imageExtent.height = p_copy_region.texture_region_size.y;4917r_vk_copy_region->imageExtent.depth = p_copy_region.texture_region_size.z;4918}49194920static void _texture_copy_region_to_vk(const RDD::TextureCopyRegion &p_copy_region, VkImageCopy *r_vk_copy_region) {4921*r_vk_copy_region = {};4922_texture_subresource_layers_to_vk(p_copy_region.src_subresources, &r_vk_copy_region->srcSubresource);4923r_vk_copy_region->srcOffset.x = p_copy_region.src_offset.x;4924r_vk_copy_region->srcOffset.y = p_copy_region.src_offset.y;4925r_vk_copy_region->srcOffset.z = p_copy_region.src_offset.z;4926_texture_subresource_layers_to_vk(p_copy_region.dst_subresources, &r_vk_copy_region->dstSubresource);4927r_vk_copy_region->dstOffset.x = p_copy_region.dst_offset.x;4928r_vk_copy_region->dstOffset.y = p_copy_region.dst_offset.y;4929r_vk_copy_region->dstOffset.z = p_copy_region.dst_offset.z;4930r_vk_copy_region->extent.width = p_copy_region.size.x;4931r_vk_copy_region->extent.height = p_copy_region.size.y;4932r_vk_copy_region->extent.depth = p_copy_region.size.z;4933}49344935void RenderingDeviceDriverVulkan::command_clear_buffer(CommandBufferID p_cmd_buffer, BufferID p_buffer, uint64_t p_offset, uint64_t p_size) {4936const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4937const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;4938vkCmdFillBuffer(command_buffer->vk_command_buffer, buf_info->vk_buffer, p_offset, p_size, 0);4939}49404941void RenderingDeviceDriverVulkan::command_copy_buffer(CommandBufferID p_cmd_buffer, BufferID p_src_buffer, BufferID p_dst_buffer, VectorView<BufferCopyRegion> p_regions) {4942const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4943const BufferInfo *src_buf_info = (const BufferInfo *)p_src_buffer.id;4944const BufferInfo *dst_buf_info = (const BufferInfo *)p_dst_buffer.id;4945vkCmdCopyBuffer(command_buffer->vk_command_buffer, src_buf_info->vk_buffer, dst_buf_info->vk_buffer, p_regions.size(), (const VkBufferCopy *)p_regions.ptr());4946}49474948void RenderingDeviceDriverVulkan::command_copy_texture(CommandBufferID p_cmd_buffer, TextureID p_src_texture, TextureLayout p_src_texture_layout, TextureID p_dst_texture, TextureLayout p_dst_texture_layout, VectorView<TextureCopyRegion> p_regions) {4949VkImageCopy *vk_copy_regions = ALLOCA_ARRAY(VkImageCopy, p_regions.size());4950for (uint32_t i = 0; i < p_regions.size(); i++) {4951_texture_copy_region_to_vk(p_regions[i], &vk_copy_regions[i]);4952}49534954const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4955const TextureInfo *src_tex_info = (const TextureInfo *)p_src_texture.id;4956const TextureInfo *dst_tex_info = (const TextureInfo *)p_dst_texture.id;49574958#ifdef DEBUG_ENABLED4959if (src_tex_info->transient) {4960ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT p_src_texture must not be used in command_copy_texture.");4961}4962if (dst_tex_info->transient) {4963ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT p_dst_texture must not be used in command_copy_texture.");4964}4965#endif49664967vkCmdCopyImage(command_buffer->vk_command_buffer, src_tex_info->vk_view_create_info.image, RD_TO_VK_LAYOUT[p_src_texture_layout], dst_tex_info->vk_view_create_info.image, RD_TO_VK_LAYOUT[p_dst_texture_layout], p_regions.size(), vk_copy_regions);4968}49694970void RenderingDeviceDriverVulkan::command_resolve_texture(CommandBufferID p_cmd_buffer, TextureID p_src_texture, TextureLayout p_src_texture_layout, uint32_t p_src_layer, uint32_t p_src_mipmap, TextureID p_dst_texture, TextureLayout p_dst_texture_layout, uint32_t p_dst_layer, uint32_t p_dst_mipmap) {4971const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4972const TextureInfo *src_tex_info = (const TextureInfo *)p_src_texture.id;4973const TextureInfo *dst_tex_info = (const TextureInfo *)p_dst_texture.id;49744975VkImageResolve vk_resolve = {};4976vk_resolve.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;4977vk_resolve.srcSubresource.mipLevel = p_src_mipmap;4978vk_resolve.srcSubresource.baseArrayLayer = p_src_layer;4979vk_resolve.srcSubresource.layerCount = 1;4980vk_resolve.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;4981vk_resolve.dstSubresource.mipLevel = p_dst_mipmap;4982vk_resolve.dstSubresource.baseArrayLayer = p_dst_layer;4983vk_resolve.dstSubresource.layerCount = 1;4984vk_resolve.extent.width = MAX(1u, src_tex_info->vk_create_info.extent.width >> p_src_mipmap);4985vk_resolve.extent.height = MAX(1u, src_tex_info->vk_create_info.extent.height >> p_src_mipmap);4986vk_resolve.extent.depth = MAX(1u, src_tex_info->vk_create_info.extent.depth >> p_src_mipmap);49874988#ifdef DEBUG_ENABLED4989if (src_tex_info->transient) {4990ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT p_src_texture must not be used in command_resolve_texture. Use a resolve store action pass instead.");4991}4992if (dst_tex_info->transient) {4993ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT p_dst_texture must not be used in command_resolve_texture.");4994}4995#endif49964997vkCmdResolveImage(command_buffer->vk_command_buffer, src_tex_info->vk_view_create_info.image, RD_TO_VK_LAYOUT[p_src_texture_layout], dst_tex_info->vk_view_create_info.image, RD_TO_VK_LAYOUT[p_dst_texture_layout], 1, &vk_resolve);4998}49995000void RenderingDeviceDriverVulkan::command_clear_color_texture(CommandBufferID p_cmd_buffer, TextureID p_texture, TextureLayout p_texture_layout, const Color &p_color, const TextureSubresourceRange &p_subresources) {5001VkClearColorValue vk_color = {};5002memcpy(&vk_color.float32, p_color.components, sizeof(VkClearColorValue::float32));50035004VkImageSubresourceRange vk_subresources = {};5005_texture_subresource_range_to_vk(p_subresources, &vk_subresources);50065007const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5008const TextureInfo *tex_info = (const TextureInfo *)p_texture.id;5009#ifdef DEBUG_ENABLED5010if (tex_info->transient) {5011ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT p_texture must not be used in command_clear_color_texture. Use a clear store action pass instead.");5012}5013#endif5014vkCmdClearColorImage(command_buffer->vk_command_buffer, tex_info->vk_view_create_info.image, RD_TO_VK_LAYOUT[p_texture_layout], &vk_color, 1, &vk_subresources);5015}50165017void RenderingDeviceDriverVulkan::command_clear_depth_stencil_texture(CommandBufferID p_cmd_buffer, TextureID p_texture, TextureLayout p_texture_layout, float p_depth, uint8_t p_stencil, const TextureSubresourceRange &p_subresources) {5018VkClearDepthStencilValue vk_depth_stencil = {};5019vk_depth_stencil.depth = p_depth;5020vk_depth_stencil.stencil = p_stencil;50215022VkImageSubresourceRange vk_subresources = {};5023_texture_subresource_range_to_vk(p_subresources, &vk_subresources);50245025const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5026const TextureInfo *tex_info = (const TextureInfo *)p_texture.id;5027#ifdef DEBUG_ENABLED5028if (tex_info->transient) {5029ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT p_texture must not be used in command_clear_depth_stencil_texture. Use a clear store action pass instead.");5030}5031#endif5032vkCmdClearDepthStencilImage(command_buffer->vk_command_buffer, tex_info->vk_view_create_info.image, RD_TO_VK_LAYOUT[p_texture_layout], &vk_depth_stencil, 1, &vk_subresources);5033}50345035void RenderingDeviceDriverVulkan::command_copy_buffer_to_texture(CommandBufferID p_cmd_buffer, BufferID p_src_buffer, TextureID p_dst_texture, TextureLayout p_dst_texture_layout, VectorView<BufferTextureCopyRegion> p_regions) {5036const TextureInfo *tex_info = (const TextureInfo *)p_dst_texture.id;50375038uint32_t pixel_size = get_image_format_pixel_size(tex_info->rd_format);5039uint32_t block_size = get_compressed_image_format_block_byte_size(tex_info->rd_format);5040uint32_t block_w, block_h;5041get_compressed_image_format_block_dimensions(tex_info->rd_format, block_w, block_h);50425043VkBufferImageCopy *vk_copy_regions = ALLOCA_ARRAY(VkBufferImageCopy, p_regions.size());5044for (uint32_t i = 0; i < p_regions.size(); i++) {5045_buffer_texture_copy_region_to_vk(p_regions[i], p_regions[i].row_pitch * block_w / (pixel_size * block_size), &vk_copy_regions[i]);5046}50475048const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5049const BufferInfo *buf_info = (const BufferInfo *)p_src_buffer.id;5050#ifdef DEBUG_ENABLED5051if (tex_info->transient) {5052ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT p_dst_texture must not be used in command_copy_buffer_to_texture.");5053}5054#endif5055vkCmdCopyBufferToImage(command_buffer->vk_command_buffer, buf_info->vk_buffer, tex_info->vk_view_create_info.image, RD_TO_VK_LAYOUT[p_dst_texture_layout], p_regions.size(), vk_copy_regions);5056}50575058void RenderingDeviceDriverVulkan::command_copy_texture_to_buffer(CommandBufferID p_cmd_buffer, TextureID p_src_texture, TextureLayout p_src_texture_layout, BufferID p_dst_buffer, VectorView<BufferTextureCopyRegion> p_regions) {5059const TextureInfo *tex_info = (const TextureInfo *)p_src_texture.id;50605061uint32_t pixel_size = get_image_format_pixel_size(tex_info->rd_format);5062uint32_t block_size = get_compressed_image_format_block_byte_size(tex_info->rd_format);5063uint32_t block_w, block_h;5064get_compressed_image_format_block_dimensions(tex_info->rd_format, block_w, block_h);50655066VkBufferImageCopy *vk_copy_regions = ALLOCA_ARRAY(VkBufferImageCopy, p_regions.size());5067for (uint32_t i = 0; i < p_regions.size(); i++) {5068_buffer_texture_copy_region_to_vk(p_regions[i], p_regions[i].row_pitch * block_w / (pixel_size * block_size), &vk_copy_regions[i]);5069}50705071const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5072const BufferInfo *buf_info = (const BufferInfo *)p_dst_buffer.id;5073#ifdef DEBUG_ENABLED5074if (tex_info->transient) {5075ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT p_src_texture must not be used in command_copy_texture_to_buffer.");5076}5077#endif5078vkCmdCopyImageToBuffer(command_buffer->vk_command_buffer, tex_info->vk_view_create_info.image, RD_TO_VK_LAYOUT[p_src_texture_layout], buf_info->vk_buffer, p_regions.size(), vk_copy_regions);5079}50805081/******************/5082/**** PIPELINE ****/5083/******************/50845085void RenderingDeviceDriverVulkan::pipeline_free(PipelineID p_pipeline) {5086vkDestroyPipeline(vk_device, (VkPipeline)p_pipeline.id, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE));5087}50885089// ----- BINDING -----50905091void RenderingDeviceDriverVulkan::command_bind_push_constants(CommandBufferID p_cmd_buffer, ShaderID p_shader, uint32_t p_dst_first_index, VectorView<uint32_t> p_data) {5092const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5093const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;5094vkCmdPushConstants(command_buffer->vk_command_buffer, shader_info->vk_pipeline_layout, shader_info->vk_push_constant_stages, p_dst_first_index * sizeof(uint32_t), p_data.size() * sizeof(uint32_t), p_data.ptr());5095}50965097// ----- CACHE -----50985099int RenderingDeviceDriverVulkan::caching_instance_count = 0;51005101bool RenderingDeviceDriverVulkan::pipeline_cache_create(const Vector<uint8_t> &p_data) {5102if (caching_instance_count) {5103WARN_PRINT("There's already a RenderingDeviceDriverVulkan instance doing PSO caching. Only one can at the same time. This one won't.");5104return false;5105}5106caching_instance_count++;51075108pipelines_cache.current_size = 0;5109pipelines_cache.buffer.resize(sizeof(PipelineCacheHeader));51105111// Parse.5112{5113if (p_data.is_empty()) {5114// No pre-existing cache, just create it.5115} else if (p_data.size() <= (int)sizeof(PipelineCacheHeader)) {5116print_verbose("Invalid/corrupt Vulkan pipelines cache. Existing shader pipeline cache will be ignored, which may result in stuttering during gameplay.");5117} else {5118const PipelineCacheHeader *loaded_header = reinterpret_cast<const PipelineCacheHeader *>(p_data.ptr());5119if (loaded_header->magic != 868 + VK_PIPELINE_CACHE_HEADER_VERSION_ONE) {5120print_verbose("Invalid Vulkan pipelines cache magic number. Existing shader pipeline cache will be ignored, which may result in stuttering during gameplay.");5121} else {5122const uint8_t *loaded_buffer_start = p_data.ptr() + sizeof(PipelineCacheHeader);5123uint32_t loaded_buffer_size = p_data.size() - sizeof(PipelineCacheHeader);5124const PipelineCacheHeader *current_header = (PipelineCacheHeader *)pipelines_cache.buffer.ptr();5125if (loaded_header->data_hash != hash_murmur3_buffer(loaded_buffer_start, loaded_buffer_size) ||5126loaded_header->data_size != loaded_buffer_size ||5127loaded_header->vendor_id != current_header->vendor_id ||5128loaded_header->device_id != current_header->device_id ||5129loaded_header->driver_version != current_header->driver_version ||5130memcmp(loaded_header->uuid, current_header->uuid, VK_UUID_SIZE) != 0 ||5131loaded_header->driver_abi != current_header->driver_abi) {5132print_verbose("Invalid Vulkan pipelines cache header. This may be due to an engine change, GPU change or graphics driver version change. Existing shader pipeline cache will be ignored, which may result in stuttering during gameplay.");5133} else {5134pipelines_cache.current_size = loaded_buffer_size;5135pipelines_cache.buffer = p_data;5136}5137}5138}5139}51405141// Create.5142{5143VkPipelineCacheCreateInfo cache_info = {};5144cache_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;5145cache_info.initialDataSize = pipelines_cache.buffer.size() - sizeof(PipelineCacheHeader);5146cache_info.pInitialData = pipelines_cache.buffer.ptr() + sizeof(PipelineCacheHeader);51475148VkResult err = vkCreatePipelineCache(vk_device, &cache_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE_CACHE), &pipelines_cache.vk_cache);5149if (err != VK_SUCCESS) {5150WARN_PRINT("vkCreatePipelinecache failed with error " + itos(err) + ".");5151return false;5152}5153}51545155return true;5156}51575158void RenderingDeviceDriverVulkan::pipeline_cache_free() {5159DEV_ASSERT(pipelines_cache.vk_cache);51605161vkDestroyPipelineCache(vk_device, pipelines_cache.vk_cache, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE_CACHE));5162pipelines_cache.vk_cache = VK_NULL_HANDLE;51635164DEV_ASSERT(caching_instance_count > 0);5165caching_instance_count--;5166}51675168size_t RenderingDeviceDriverVulkan::pipeline_cache_query_size() {5169DEV_ASSERT(pipelines_cache.vk_cache);51705171// FIXME:5172// We're letting the cache grow unboundedly. We may want to set at limit and see if implementations use LRU or the like.5173// If we do, we won't be able to assume any longer that the cache is dirty if, and only if, it has grown.5174VkResult err = vkGetPipelineCacheData(vk_device, pipelines_cache.vk_cache, &pipelines_cache.current_size, nullptr);5175ERR_FAIL_COND_V_MSG(err, 0, "vkGetPipelineCacheData failed with error " + itos(err) + ".");51765177return pipelines_cache.current_size;5178}51795180Vector<uint8_t> RenderingDeviceDriverVulkan::pipeline_cache_serialize() {5181DEV_ASSERT(pipelines_cache.vk_cache);51825183pipelines_cache.buffer.resize(pipelines_cache.current_size + sizeof(PipelineCacheHeader));51845185VkResult err = vkGetPipelineCacheData(vk_device, pipelines_cache.vk_cache, &pipelines_cache.current_size, pipelines_cache.buffer.ptrw() + sizeof(PipelineCacheHeader));5186ERR_FAIL_COND_V(err != VK_SUCCESS && err != VK_INCOMPLETE, Vector<uint8_t>()); // Incomplete is OK because the cache may have grown since the size was queried (unless when exiting).51875188// The real buffer size may now be bigger than the updated current_size.5189// We take into account the new size but keep the buffer resized in a worst-case fashion.51905191PipelineCacheHeader *header = (PipelineCacheHeader *)pipelines_cache.buffer.ptrw();5192header->data_size = pipelines_cache.current_size;5193header->data_hash = hash_murmur3_buffer(pipelines_cache.buffer.ptr() + sizeof(PipelineCacheHeader), pipelines_cache.current_size);51945195return pipelines_cache.buffer;5196}51975198/*******************/5199/**** RENDERING ****/5200/*******************/52015202// ----- SUBPASS -----52035204// RDD::AttachmentLoadOp == VkAttachmentLoadOp.5205static_assert(ENUM_MEMBERS_EQUAL(RDD::ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_LOAD));5206static_assert(ENUM_MEMBERS_EQUAL(RDD::ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_CLEAR));5207static_assert(ENUM_MEMBERS_EQUAL(RDD::ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_DONT_CARE));52085209// RDD::AttachmentStoreOp == VkAttachmentStoreOp.5210static_assert(ENUM_MEMBERS_EQUAL(RDD::ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_STORE_OP_STORE));5211static_assert(ENUM_MEMBERS_EQUAL(RDD::ATTACHMENT_STORE_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE));52125213// Assuming Vulkan and RDD's are backed by uint32_t in:5214// - VkSubpassDescription2::pPreserveAttachments and RDD::Subpass::preserve_attachments.5215// - VkRenderPassCreateInfo2KHR::pCorrelatedViewMasks and p_view_correlation_mask.52165217static void _attachment_reference_to_vk(const RDD::AttachmentReference &p_attachment_reference, VkAttachmentReference2KHR *r_vk_attachment_reference) {5218*r_vk_attachment_reference = {};5219r_vk_attachment_reference->sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;5220r_vk_attachment_reference->attachment = p_attachment_reference.attachment;5221r_vk_attachment_reference->layout = RD_TO_VK_LAYOUT[p_attachment_reference.layout];5222r_vk_attachment_reference->aspectMask = (VkImageAspectFlags)p_attachment_reference.aspect;5223}52245225RDD::RenderPassID RenderingDeviceDriverVulkan::render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count, AttachmentReference p_fragment_density_map_attachment) {5226// These are only used if we use multiview but we need to define them in scope.5227const uint32_t view_mask = (1 << p_view_count) - 1;5228const uint32_t correlation_mask = (1 << p_view_count) - 1;52295230VkAttachmentDescription2KHR *vk_attachments = ALLOCA_ARRAY(VkAttachmentDescription2KHR, p_attachments.size());5231for (uint32_t i = 0; i < p_attachments.size(); i++) {5232vk_attachments[i] = {};5233vk_attachments[i].sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR;5234vk_attachments[i].format = RD_TO_VK_FORMAT[p_attachments[i].format];5235vk_attachments[i].samples = _ensure_supported_sample_count(p_attachments[i].samples);5236vk_attachments[i].loadOp = (VkAttachmentLoadOp)p_attachments[i].load_op;5237vk_attachments[i].storeOp = (VkAttachmentStoreOp)p_attachments[i].store_op;5238vk_attachments[i].stencilLoadOp = (VkAttachmentLoadOp)p_attachments[i].stencil_load_op;5239vk_attachments[i].stencilStoreOp = (VkAttachmentStoreOp)p_attachments[i].stencil_store_op;5240vk_attachments[i].initialLayout = RD_TO_VK_LAYOUT[p_attachments[i].initial_layout];5241vk_attachments[i].finalLayout = RD_TO_VK_LAYOUT[p_attachments[i].final_layout];5242}52435244VkSubpassDescription2KHR *vk_subpasses = ALLOCA_ARRAY(VkSubpassDescription2KHR, p_subpasses.size());5245for (uint32_t i = 0; i < p_subpasses.size(); i++) {5246VkAttachmentReference2KHR *vk_subpass_input_attachments = ALLOCA_ARRAY(VkAttachmentReference2KHR, p_subpasses[i].input_references.size());5247for (uint32_t j = 0; j < p_subpasses[i].input_references.size(); j++) {5248_attachment_reference_to_vk(p_subpasses[i].input_references[j], &vk_subpass_input_attachments[j]);5249}52505251VkAttachmentReference2KHR *vk_subpass_color_attachments = ALLOCA_ARRAY(VkAttachmentReference2KHR, p_subpasses[i].color_references.size());5252for (uint32_t j = 0; j < p_subpasses[i].color_references.size(); j++) {5253_attachment_reference_to_vk(p_subpasses[i].color_references[j], &vk_subpass_color_attachments[j]);5254}52555256VkAttachmentReference2KHR *vk_subpass_resolve_attachments = ALLOCA_ARRAY(VkAttachmentReference2KHR, p_subpasses[i].resolve_references.size());5257for (uint32_t j = 0; j < p_subpasses[i].resolve_references.size(); j++) {5258_attachment_reference_to_vk(p_subpasses[i].resolve_references[j], &vk_subpass_resolve_attachments[j]);5259}52605261VkAttachmentReference2KHR *vk_subpass_depth_stencil_attachment = nullptr;5262if (p_subpasses[i].depth_stencil_reference.attachment != AttachmentReference::UNUSED) {5263vk_subpass_depth_stencil_attachment = ALLOCA_SINGLE(VkAttachmentReference2KHR);5264_attachment_reference_to_vk(p_subpasses[i].depth_stencil_reference, vk_subpass_depth_stencil_attachment);5265}52665267vk_subpasses[i] = {};5268vk_subpasses[i].sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR;5269vk_subpasses[i].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;5270vk_subpasses[i].viewMask = p_view_count == 1 ? 0 : view_mask;5271vk_subpasses[i].inputAttachmentCount = p_subpasses[i].input_references.size();5272vk_subpasses[i].pInputAttachments = vk_subpass_input_attachments;5273vk_subpasses[i].colorAttachmentCount = p_subpasses[i].color_references.size();5274vk_subpasses[i].pColorAttachments = vk_subpass_color_attachments;5275vk_subpasses[i].pResolveAttachments = vk_subpass_resolve_attachments;5276vk_subpasses[i].pDepthStencilAttachment = vk_subpass_depth_stencil_attachment;5277vk_subpasses[i].preserveAttachmentCount = p_subpasses[i].preserve_attachments.size();5278vk_subpasses[i].pPreserveAttachments = p_subpasses[i].preserve_attachments.ptr();52795280// Fragment shading rate.5281if (fsr_capabilities.attachment_supported && p_subpasses[i].fragment_shading_rate_reference.attachment != AttachmentReference::UNUSED) {5282VkAttachmentReference2KHR *vk_subpass_fsr_attachment = ALLOCA_SINGLE(VkAttachmentReference2KHR);5283*vk_subpass_fsr_attachment = {};5284vk_subpass_fsr_attachment->sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;5285vk_subpass_fsr_attachment->attachment = p_subpasses[i].fragment_shading_rate_reference.attachment;5286vk_subpass_fsr_attachment->layout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;52875288VkFragmentShadingRateAttachmentInfoKHR *vk_fsr_info = ALLOCA_SINGLE(VkFragmentShadingRateAttachmentInfoKHR);5289*vk_fsr_info = {};5290vk_fsr_info->sType = VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR;5291vk_fsr_info->pNext = vk_subpasses[i].pNext;5292vk_fsr_info->pFragmentShadingRateAttachment = vk_subpass_fsr_attachment;5293vk_fsr_info->shadingRateAttachmentTexelSize.width = p_subpasses[i].fragment_shading_rate_texel_size.x;5294vk_fsr_info->shadingRateAttachmentTexelSize.height = p_subpasses[i].fragment_shading_rate_texel_size.y;52955296vk_subpasses[i].pNext = vk_fsr_info;5297}52985299// Depth resolve.5300if (framebuffer_depth_resolve && p_subpasses[i].depth_resolve_reference.attachment != AttachmentReference::UNUSED) {5301VkAttachmentReference2KHR *vk_subpass_depth_resolve_attachment = ALLOCA_SINGLE(VkAttachmentReference2KHR);5302*vk_subpass_depth_resolve_attachment = {};5303vk_subpass_depth_resolve_attachment->sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;5304vk_subpass_depth_resolve_attachment->attachment = p_subpasses[i].depth_resolve_reference.attachment;5305vk_subpass_depth_resolve_attachment->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;53065307VkSubpassDescriptionDepthStencilResolveKHR *vk_depth_resolve_info = ALLOCA_SINGLE(VkSubpassDescriptionDepthStencilResolveKHR);5308*vk_depth_resolve_info = {};5309vk_depth_resolve_info->sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE;5310vk_depth_resolve_info->pNext = vk_subpasses[i].pNext;5311vk_depth_resolve_info->depthResolveMode = VK_RESOLVE_MODE_MAX_BIT_KHR;5312vk_depth_resolve_info->stencilResolveMode = VK_RESOLVE_MODE_NONE_KHR; // we don't resolve our stencil (for now)5313vk_depth_resolve_info->pDepthStencilResolveAttachment = vk_subpass_depth_resolve_attachment;53145315vk_subpasses[i].pNext = vk_depth_resolve_info;5316}5317}53185319VkSubpassDependency2KHR *vk_subpass_dependencies = ALLOCA_ARRAY(VkSubpassDependency2KHR, p_subpass_dependencies.size());5320for (uint32_t i = 0; i < p_subpass_dependencies.size(); i++) {5321vk_subpass_dependencies[i] = {};5322vk_subpass_dependencies[i].sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2;5323vk_subpass_dependencies[i].srcSubpass = p_subpass_dependencies[i].src_subpass;5324vk_subpass_dependencies[i].dstSubpass = p_subpass_dependencies[i].dst_subpass;5325vk_subpass_dependencies[i].srcStageMask = _rd_to_vk_pipeline_stages(p_subpass_dependencies[i].src_stages);5326vk_subpass_dependencies[i].dstStageMask = _rd_to_vk_pipeline_stages(p_subpass_dependencies[i].dst_stages);5327vk_subpass_dependencies[i].srcAccessMask = _rd_to_vk_access_flags(p_subpass_dependencies[i].src_access);5328vk_subpass_dependencies[i].dstAccessMask = _rd_to_vk_access_flags(p_subpass_dependencies[i].dst_access);5329}53305331VkRenderPassCreateInfo2KHR create_info = {};5332create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR;5333create_info.attachmentCount = p_attachments.size();5334create_info.pAttachments = vk_attachments;5335create_info.subpassCount = p_subpasses.size();5336create_info.pSubpasses = vk_subpasses;5337create_info.dependencyCount = p_subpass_dependencies.size();5338create_info.pDependencies = vk_subpass_dependencies;5339create_info.correlatedViewMaskCount = p_view_count == 1 ? 0 : 1;5340create_info.pCorrelatedViewMasks = p_view_count == 1 ? nullptr : &correlation_mask;53415342// Multiview.5343if (p_view_count > 1 && device_functions.CreateRenderPass2KHR == nullptr) {5344// This is only required when not using vkCreateRenderPass2.5345// We add it if vkCreateRenderPass2KHR is not supported,5346// resulting this in being passed to our vkCreateRenderPass fallback.53475348uint32_t *vk_view_masks = ALLOCA_ARRAY(uint32_t, p_subpasses.size());5349for (uint32_t i = 0; i < p_subpasses.size(); i++) {5350vk_view_masks[i] = view_mask;5351}53525353VkRenderPassMultiviewCreateInfo *multiview_create_info = ALLOCA_SINGLE(VkRenderPassMultiviewCreateInfo);5354*multiview_create_info = {};5355multiview_create_info->sType = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;5356multiview_create_info->subpassCount = p_subpasses.size();5357multiview_create_info->pViewMasks = vk_view_masks;5358multiview_create_info->correlationMaskCount = 1;5359multiview_create_info->pCorrelationMasks = &correlation_mask;53605361create_info.pNext = multiview_create_info;5362}53635364// Fragment density map.5365bool uses_fragment_density_map = fdm_capabilities.attachment_supported && p_fragment_density_map_attachment.attachment != AttachmentReference::UNUSED;5366if (uses_fragment_density_map) {5367VkRenderPassFragmentDensityMapCreateInfoEXT *vk_fdm_info = ALLOCA_SINGLE(VkRenderPassFragmentDensityMapCreateInfoEXT);5368vk_fdm_info->sType = VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT;5369vk_fdm_info->fragmentDensityMapAttachment.attachment = p_fragment_density_map_attachment.attachment;5370vk_fdm_info->fragmentDensityMapAttachment.layout = RD_TO_VK_LAYOUT[p_fragment_density_map_attachment.layout];5371vk_fdm_info->pNext = create_info.pNext;5372create_info.pNext = vk_fdm_info;5373}53745375VkRenderPass vk_render_pass = VK_NULL_HANDLE;5376VkResult res = _create_render_pass(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_RENDER_PASS), &vk_render_pass);5377ERR_FAIL_COND_V_MSG(res, RenderPassID(), "vkCreateRenderPass2KHR failed with error " + itos(res) + ".");53785379RenderPassInfo *render_pass = VersatileResource::allocate<RenderPassInfo>(resources_allocator);5380render_pass->vk_render_pass = vk_render_pass;5381render_pass->uses_fragment_density_map = uses_fragment_density_map;5382return RenderPassID(render_pass);5383}53845385void RenderingDeviceDriverVulkan::render_pass_free(RenderPassID p_render_pass) {5386RenderPassInfo *render_pass = (RenderPassInfo *)(p_render_pass.id);5387vkDestroyRenderPass(vk_device, render_pass->vk_render_pass, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_RENDER_PASS));5388VersatileResource::free<RenderPassInfo>(resources_allocator, render_pass);5389}53905391// ----- COMMANDS -----53925393static_assert(ARRAYS_COMPATIBLE_FIELDWISE(RDD::RenderPassClearValue, VkClearValue));53945395void RenderingDeviceDriverVulkan::command_begin_render_pass(CommandBufferID p_cmd_buffer, RenderPassID p_render_pass, FramebufferID p_framebuffer, CommandBufferType p_cmd_buffer_type, const Rect2i &p_rect, VectorView<RenderPassClearValue> p_clear_values) {5396CommandBufferInfo *command_buffer = (CommandBufferInfo *)(p_cmd_buffer.id);5397RenderPassInfo *render_pass = (RenderPassInfo *)(p_render_pass.id);5398Framebuffer *framebuffer = (Framebuffer *)(p_framebuffer.id);53995400if (framebuffer->swap_chain_acquired) {5401// Insert a barrier to wait for the acquisition of the framebuffer before the render pass begins.5402VkImageMemoryBarrier image_barrier = {};5403image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;5404image_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;5405image_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;5406image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;5407image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;5408image_barrier.image = framebuffer->swap_chain_image;5409image_barrier.subresourceRange = framebuffer->swap_chain_image_subresource_range;5410vkCmdPipelineBarrier(command_buffer->vk_command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_barrier);5411framebuffer->swap_chain_acquired = false;5412}54135414VkRenderPassBeginInfo render_pass_begin = {};5415render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;5416render_pass_begin.renderPass = render_pass->vk_render_pass;5417render_pass_begin.framebuffer = framebuffer->vk_framebuffer;54185419render_pass_begin.renderArea.offset.x = p_rect.position.x;5420render_pass_begin.renderArea.offset.y = p_rect.position.y;5421render_pass_begin.renderArea.extent.width = p_rect.size.x;5422render_pass_begin.renderArea.extent.height = p_rect.size.y;54235424render_pass_begin.clearValueCount = p_clear_values.size();5425render_pass_begin.pClearValues = (const VkClearValue *)p_clear_values.ptr();54265427VkSubpassContents vk_subpass_contents = p_cmd_buffer_type == COMMAND_BUFFER_TYPE_PRIMARY ? VK_SUBPASS_CONTENTS_INLINE : VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;5428vkCmdBeginRenderPass(command_buffer->vk_command_buffer, &render_pass_begin, vk_subpass_contents);54295430command_buffer->active_framebuffer = framebuffer;5431command_buffer->active_render_pass = render_pass;54325433#if PRINT_NATIVE_COMMANDS5434print_line(vformat("vkCmdBeginRenderPass Pass 0x%uX Framebuffer 0x%uX", p_render_pass.id, p_framebuffer.id));5435#endif5436}54375438void RenderingDeviceDriverVulkan::command_end_render_pass(CommandBufferID p_cmd_buffer) {5439CommandBufferInfo *command_buffer = (CommandBufferInfo *)(p_cmd_buffer.id);5440DEV_ASSERT(command_buffer->active_framebuffer != nullptr && "A framebuffer must be active.");5441DEV_ASSERT(command_buffer->active_render_pass != nullptr && "A render pass must be active.");54425443if (device_functions.EndRenderPass2KHR != nullptr && fdm_capabilities.offset_supported && command_buffer->active_render_pass->uses_fragment_density_map) {5444LocalVector<VkOffset2D> fragment_density_offsets;5445if (VulkanHooks::get_singleton() != nullptr) {5446VulkanHooks::get_singleton()->get_fragment_density_offsets(fragment_density_offsets, fdm_capabilities.offset_granularity);5447}5448if (fragment_density_offsets.size() > 0) {5449VkSubpassFragmentDensityMapOffsetEndInfoQCOM offset_info = {};5450offset_info.sType = VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM;5451offset_info.pFragmentDensityOffsets = fragment_density_offsets.ptr();5452offset_info.fragmentDensityOffsetCount = fragment_density_offsets.size();54535454VkSubpassEndInfo subpass_end_info = {};5455subpass_end_info.sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO;5456subpass_end_info.pNext = &offset_info;54575458device_functions.EndRenderPass2KHR(command_buffer->vk_command_buffer, &subpass_end_info);5459} else {5460vkCmdEndRenderPass(command_buffer->vk_command_buffer);5461}5462} else {5463vkCmdEndRenderPass(command_buffer->vk_command_buffer);5464}54655466command_buffer->active_render_pass = nullptr;5467command_buffer->active_framebuffer = nullptr;54685469#if PRINT_NATIVE_COMMANDS5470print_line("vkCmdEndRenderPass");5471#endif5472}54735474void RenderingDeviceDriverVulkan::command_next_render_subpass(CommandBufferID p_cmd_buffer, CommandBufferType p_cmd_buffer_type) {5475const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5476VkSubpassContents vk_subpass_contents = p_cmd_buffer_type == COMMAND_BUFFER_TYPE_PRIMARY ? VK_SUBPASS_CONTENTS_INLINE : VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;5477vkCmdNextSubpass(command_buffer->vk_command_buffer, vk_subpass_contents);5478}54795480void RenderingDeviceDriverVulkan::command_render_set_viewport(CommandBufferID p_cmd_buffer, VectorView<Rect2i> p_viewports) {5481const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5482VkViewport *vk_viewports = ALLOCA_ARRAY(VkViewport, p_viewports.size());5483for (uint32_t i = 0; i < p_viewports.size(); i++) {5484vk_viewports[i] = {};5485vk_viewports[i].x = p_viewports[i].position.x;5486vk_viewports[i].y = p_viewports[i].position.y;5487vk_viewports[i].width = p_viewports[i].size.x;5488vk_viewports[i].height = p_viewports[i].size.y;5489vk_viewports[i].minDepth = 0.0f;5490vk_viewports[i].maxDepth = 1.0f;5491}5492vkCmdSetViewport(command_buffer->vk_command_buffer, 0, p_viewports.size(), vk_viewports);5493}54945495void RenderingDeviceDriverVulkan::command_render_set_scissor(CommandBufferID p_cmd_buffer, VectorView<Rect2i> p_scissors) {5496const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5497vkCmdSetScissor(command_buffer->vk_command_buffer, 0, p_scissors.size(), (VkRect2D *)p_scissors.ptr());5498}54995500void RenderingDeviceDriverVulkan::command_render_clear_attachments(CommandBufferID p_cmd_buffer, VectorView<AttachmentClear> p_attachment_clears, VectorView<Rect2i> p_rects) {5501const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;55025503VkClearAttachment *vk_clears = ALLOCA_ARRAY(VkClearAttachment, p_attachment_clears.size());5504for (uint32_t i = 0; i < p_attachment_clears.size(); i++) {5505vk_clears[i] = {};5506memcpy(&vk_clears[i].clearValue, &p_attachment_clears[i].value, sizeof(VkClearValue));5507vk_clears[i].colorAttachment = p_attachment_clears[i].color_attachment;5508vk_clears[i].aspectMask = p_attachment_clears[i].aspect;5509}55105511VkClearRect *vk_rects = ALLOCA_ARRAY(VkClearRect, p_rects.size());5512for (uint32_t i = 0; i < p_rects.size(); i++) {5513vk_rects[i] = {};5514vk_rects[i].rect.offset.x = p_rects[i].position.x;5515vk_rects[i].rect.offset.y = p_rects[i].position.y;5516vk_rects[i].rect.extent.width = p_rects[i].size.x;5517vk_rects[i].rect.extent.height = p_rects[i].size.y;5518vk_rects[i].baseArrayLayer = 0;5519vk_rects[i].layerCount = 1;5520}55215522vkCmdClearAttachments(command_buffer->vk_command_buffer, p_attachment_clears.size(), vk_clears, p_rects.size(), vk_rects);5523}55245525void RenderingDeviceDriverVulkan::command_bind_render_pipeline(CommandBufferID p_cmd_buffer, PipelineID p_pipeline) {5526const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5527vkCmdBindPipeline(command_buffer->vk_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, (VkPipeline)p_pipeline.id);5528}55295530void RenderingDeviceDriverVulkan::command_bind_render_uniform_sets(CommandBufferID p_cmd_buffer, VectorView<UniformSetID> p_uniform_sets, ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count, uint32_t p_dynamic_offsets) {5531if (p_set_count == 0) {5532return;5533}55345535thread_local LocalVector<VkDescriptorSet> sets;5536sets.clear();5537sets.resize(p_set_count);55385539uint32_t dynamic_offsets[MAX_DYNAMIC_BUFFERS];5540uint32_t shift = 0u;5541uint32_t curr_dynamic_offset = 0u;55425543for (uint32_t i = 0; i < p_set_count; i++) {5544const UniformSetInfo *usi = (const UniformSetInfo *)p_uniform_sets[i].id;55455546sets[i] = usi->vk_descriptor_set;55475548// At this point this assert should already have been validated.5549DEV_ASSERT(curr_dynamic_offset + usi->dynamic_buffers.size() <= MAX_DYNAMIC_BUFFERS);55505551const uint32_t dynamic_offset_count = usi->dynamic_buffers.size();5552for (uint32_t j = 0u; j < dynamic_offset_count; ++j) {5553const uint32_t frame_idx = (p_dynamic_offsets >> shift) & 0xFu;5554shift += 4u;5555dynamic_offsets[curr_dynamic_offset++] = uint32_t(frame_idx * usi->dynamic_buffers[j]->size);5556}5557}55585559const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5560const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;5561vkCmdBindDescriptorSets(command_buffer->vk_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, shader_info->vk_pipeline_layout, p_first_set_index, p_set_count, &sets[0], curr_dynamic_offset, dynamic_offsets);5562}55635564void RenderingDeviceDriverVulkan::command_render_draw(CommandBufferID p_cmd_buffer, uint32_t p_vertex_count, uint32_t p_instance_count, uint32_t p_base_vertex, uint32_t p_first_instance) {5565const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5566vkCmdDraw(command_buffer->vk_command_buffer, p_vertex_count, p_instance_count, p_base_vertex, p_first_instance);5567}55685569void RenderingDeviceDriverVulkan::command_render_draw_indexed(CommandBufferID p_cmd_buffer, uint32_t p_index_count, uint32_t p_instance_count, uint32_t p_first_index, int32_t p_vertex_offset, uint32_t p_first_instance) {5570const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5571vkCmdDrawIndexed(command_buffer->vk_command_buffer, p_index_count, p_instance_count, p_first_index, p_vertex_offset, p_first_instance);5572}55735574void RenderingDeviceDriverVulkan::command_render_draw_indexed_indirect(CommandBufferID p_cmd_buffer, BufferID p_indirect_buffer, uint64_t p_offset, uint32_t p_draw_count, uint32_t p_stride) {5575const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5576const BufferInfo *buf_info = (const BufferInfo *)p_indirect_buffer.id;5577vkCmdDrawIndexedIndirect(command_buffer->vk_command_buffer, buf_info->vk_buffer, p_offset, p_draw_count, p_stride);5578}55795580void RenderingDeviceDriverVulkan::command_render_draw_indexed_indirect_count(CommandBufferID p_cmd_buffer, BufferID p_indirect_buffer, uint64_t p_offset, BufferID p_count_buffer, uint64_t p_count_buffer_offset, uint32_t p_max_draw_count, uint32_t p_stride) {5581const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5582const BufferInfo *indirect_buf_info = (const BufferInfo *)p_indirect_buffer.id;5583const BufferInfo *count_buf_info = (const BufferInfo *)p_count_buffer.id;5584vkCmdDrawIndexedIndirectCount(command_buffer->vk_command_buffer, indirect_buf_info->vk_buffer, p_offset, count_buf_info->vk_buffer, p_count_buffer_offset, p_max_draw_count, p_stride);5585}55865587void RenderingDeviceDriverVulkan::command_render_draw_indirect(CommandBufferID p_cmd_buffer, BufferID p_indirect_buffer, uint64_t p_offset, uint32_t p_draw_count, uint32_t p_stride) {5588const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5589const BufferInfo *buf_info = (const BufferInfo *)p_indirect_buffer.id;5590vkCmdDrawIndirect(command_buffer->vk_command_buffer, buf_info->vk_buffer, p_offset, p_draw_count, p_stride);5591}55925593void RenderingDeviceDriverVulkan::command_render_draw_indirect_count(CommandBufferID p_cmd_buffer, BufferID p_indirect_buffer, uint64_t p_offset, BufferID p_count_buffer, uint64_t p_count_buffer_offset, uint32_t p_max_draw_count, uint32_t p_stride) {5594const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5595const BufferInfo *indirect_buf_info = (const BufferInfo *)p_indirect_buffer.id;5596const BufferInfo *count_buf_info = (const BufferInfo *)p_count_buffer.id;5597vkCmdDrawIndirectCount(command_buffer->vk_command_buffer, indirect_buf_info->vk_buffer, p_offset, count_buf_info->vk_buffer, p_count_buffer_offset, p_max_draw_count, p_stride);5598}55995600void RenderingDeviceDriverVulkan::command_render_bind_vertex_buffers(CommandBufferID p_cmd_buffer, uint32_t p_binding_count, const BufferID *p_buffers, const uint64_t *p_offsets, uint64_t p_dynamic_offsets) {5601const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5602VkBuffer *vk_buffers = ALLOCA_ARRAY(VkBuffer, p_binding_count);5603uint64_t *vk_offsets = ALLOCA_ARRAY(uint64_t, p_binding_count);5604for (uint32_t i = 0; i < p_binding_count; i++) {5605const BufferInfo *buf_info = (const BufferInfo *)p_buffers[i].id;5606uint64_t offset = p_offsets[i];5607if (buf_info->is_dynamic()) {5608uint64_t frame_idx = p_dynamic_offsets & 0x3; // Assuming max 4 frames.5609p_dynamic_offsets >>= 2;5610offset += frame_idx * buf_info->size;5611}5612vk_buffers[i] = ((const BufferInfo *)p_buffers[i].id)->vk_buffer;5613vk_offsets[i] = offset;5614}5615vkCmdBindVertexBuffers(command_buffer->vk_command_buffer, 0, p_binding_count, vk_buffers, vk_offsets);5616}56175618void RenderingDeviceDriverVulkan::command_render_bind_index_buffer(CommandBufferID p_cmd_buffer, BufferID p_buffer, IndexBufferFormat p_format, uint64_t p_offset) {5619const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5620const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;5621vkCmdBindIndexBuffer(command_buffer->vk_command_buffer, buf_info->vk_buffer, p_offset, p_format == INDEX_BUFFER_FORMAT_UINT16 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32);5622}56235624void RenderingDeviceDriverVulkan::command_render_set_blend_constants(CommandBufferID p_cmd_buffer, const Color &p_constants) {5625const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5626vkCmdSetBlendConstants(command_buffer->vk_command_buffer, p_constants.components);5627}56285629void RenderingDeviceDriverVulkan::command_render_set_line_width(CommandBufferID p_cmd_buffer, float p_width) {5630const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5631vkCmdSetLineWidth(command_buffer->vk_command_buffer, p_width);5632}56335634// ----- PIPELINE -----56355636static const VkPrimitiveTopology RD_TO_VK_PRIMITIVE[RDD::RENDER_PRIMITIVE_MAX] = {5637VK_PRIMITIVE_TOPOLOGY_POINT_LIST,5638VK_PRIMITIVE_TOPOLOGY_LINE_LIST,5639VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,5640VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,5641VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,5642VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,5643VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,5644VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,5645VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,5646VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,5647VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,5648};56495650// RDD::PolygonCullMode == VkCullModeFlagBits.5651static_assert(ENUM_MEMBERS_EQUAL(RDD::POLYGON_CULL_DISABLED, VK_CULL_MODE_NONE));5652static_assert(ENUM_MEMBERS_EQUAL(RDD::POLYGON_CULL_FRONT, VK_CULL_MODE_FRONT_BIT));5653static_assert(ENUM_MEMBERS_EQUAL(RDD::POLYGON_CULL_BACK, VK_CULL_MODE_BACK_BIT));56545655// RDD::StencilOperation == VkStencilOp.5656static_assert(ENUM_MEMBERS_EQUAL(RDD::STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP));5657static_assert(ENUM_MEMBERS_EQUAL(RDD::STENCIL_OP_ZERO, VK_STENCIL_OP_ZERO));5658static_assert(ENUM_MEMBERS_EQUAL(RDD::STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE));5659static_assert(ENUM_MEMBERS_EQUAL(RDD::STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP));5660static_assert(ENUM_MEMBERS_EQUAL(RDD::STENCIL_OP_DECREMENT_AND_CLAMP, VK_STENCIL_OP_DECREMENT_AND_CLAMP));5661static_assert(ENUM_MEMBERS_EQUAL(RDD::STENCIL_OP_INVERT, VK_STENCIL_OP_INVERT));5662static_assert(ENUM_MEMBERS_EQUAL(RDD::STENCIL_OP_INCREMENT_AND_WRAP, VK_STENCIL_OP_INCREMENT_AND_WRAP));5663static_assert(ENUM_MEMBERS_EQUAL(RDD::STENCIL_OP_DECREMENT_AND_WRAP, VK_STENCIL_OP_DECREMENT_AND_WRAP));56645665// RDD::LogicOperation == VkLogicOp.5666static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_CLEAR, VK_LOGIC_OP_CLEAR));5667static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_AND, VK_LOGIC_OP_AND));5668static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_AND_REVERSE, VK_LOGIC_OP_AND_REVERSE));5669static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_COPY, VK_LOGIC_OP_COPY));5670static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_AND_INVERTED, VK_LOGIC_OP_AND_INVERTED));5671static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_NO_OP, VK_LOGIC_OP_NO_OP));5672static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_XOR, VK_LOGIC_OP_XOR));5673static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_OR, VK_LOGIC_OP_OR));5674static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_NOR, VK_LOGIC_OP_NOR));5675static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_EQUIVALENT, VK_LOGIC_OP_EQUIVALENT));5676static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_INVERT, VK_LOGIC_OP_INVERT));5677static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_OR_REVERSE, VK_LOGIC_OP_OR_REVERSE));5678static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_COPY_INVERTED, VK_LOGIC_OP_COPY_INVERTED));5679static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_OR_INVERTED, VK_LOGIC_OP_OR_INVERTED));5680static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_NAND, VK_LOGIC_OP_NAND));5681static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_SET, VK_LOGIC_OP_SET));56825683// RDD::BlendFactor == VkBlendFactor.5684static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ZERO));5685static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ONE));5686static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_SRC_COLOR, VK_BLEND_FACTOR_SRC_COLOR));5687static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR));5688static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_DST_COLOR, VK_BLEND_FACTOR_DST_COLOR));5689static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE_MINUS_DST_COLOR, VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR));5690static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_SRC_ALPHA));5691static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA));5692static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_DST_ALPHA, VK_BLEND_FACTOR_DST_ALPHA));5693static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE_MINUS_DST_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA));5694static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_CONSTANT_COLOR, VK_BLEND_FACTOR_CONSTANT_COLOR));5695static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR));5696static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_CONSTANT_ALPHA, VK_BLEND_FACTOR_CONSTANT_ALPHA));5697static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA));5698static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_SRC_ALPHA_SATURATE, VK_BLEND_FACTOR_SRC_ALPHA_SATURATE));5699static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_SRC1_COLOR, VK_BLEND_FACTOR_SRC1_COLOR));5700static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE_MINUS_SRC1_COLOR, VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR));5701static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_SRC1_ALPHA, VK_BLEND_FACTOR_SRC1_ALPHA));5702static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA));57035704// RDD::BlendOperation == VkBlendOp.5705static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_OP_ADD, VK_BLEND_OP_ADD));5706static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_OP_SUBTRACT, VK_BLEND_OP_SUBTRACT));5707static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_OP_REVERSE_SUBTRACT, VK_BLEND_OP_REVERSE_SUBTRACT));5708static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_OP_MINIMUM, VK_BLEND_OP_MIN));5709static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_OP_MAXIMUM, VK_BLEND_OP_MAX));57105711RDD::PipelineID RenderingDeviceDriverVulkan::render_pipeline_create(5712ShaderID p_shader,5713VertexFormatID p_vertex_format,5714RenderPrimitive p_render_primitive,5715PipelineRasterizationState p_rasterization_state,5716PipelineMultisampleState p_multisample_state,5717PipelineDepthStencilState p_depth_stencil_state,5718PipelineColorBlendState p_blend_state,5719VectorView<int32_t> p_color_attachments,5720BitField<PipelineDynamicStateFlags> p_dynamic_state,5721RenderPassID p_render_pass,5722uint32_t p_render_subpass,5723VectorView<PipelineSpecializationConstant> p_specialization_constants) {5724// Vertex.5725const VkPipelineVertexInputStateCreateInfo *vertex_input_state_create_info = nullptr;5726if (p_vertex_format.id) {5727const VertexFormatInfo *vf_info = (const VertexFormatInfo *)p_vertex_format.id;5728vertex_input_state_create_info = &vf_info->vk_create_info;5729} else {5730VkPipelineVertexInputStateCreateInfo *null_vertex_input_state = ALLOCA_SINGLE(VkPipelineVertexInputStateCreateInfo);5731*null_vertex_input_state = {};5732null_vertex_input_state->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;5733vertex_input_state_create_info = null_vertex_input_state;5734}57355736// Input assembly.5737VkPipelineInputAssemblyStateCreateInfo input_assembly_create_info = {};5738input_assembly_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;5739input_assembly_create_info.topology = RD_TO_VK_PRIMITIVE[p_render_primitive];5740input_assembly_create_info.primitiveRestartEnable = (p_render_primitive == RENDER_PRIMITIVE_TRIANGLE_STRIPS_WITH_RESTART_INDEX);57415742// Tessellation.5743VkPipelineTessellationStateCreateInfo tessellation_create_info = {};5744tessellation_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;5745ERR_FAIL_COND_V(physical_device_properties.limits.maxTessellationPatchSize > 0 && (p_rasterization_state.patch_control_points < 1 || p_rasterization_state.patch_control_points > physical_device_properties.limits.maxTessellationPatchSize), PipelineID());5746tessellation_create_info.patchControlPoints = p_rasterization_state.patch_control_points;57475748// Viewport.5749VkPipelineViewportStateCreateInfo viewport_state_create_info = {};5750viewport_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;5751viewport_state_create_info.viewportCount = 1; // If VR extensions are supported at some point, this will have to be customizable in the framebuffer format.5752viewport_state_create_info.scissorCount = 1;57535754// Rasterization.5755VkPipelineRasterizationStateCreateInfo rasterization_state_create_info = {};5756rasterization_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;5757rasterization_state_create_info.depthClampEnable = p_rasterization_state.enable_depth_clamp;5758rasterization_state_create_info.rasterizerDiscardEnable = p_rasterization_state.discard_primitives;5759rasterization_state_create_info.polygonMode = p_rasterization_state.wireframe ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL;5760rasterization_state_create_info.cullMode = (PolygonCullMode)p_rasterization_state.cull_mode;5761rasterization_state_create_info.frontFace = (p_rasterization_state.front_face == POLYGON_FRONT_FACE_CLOCKWISE ? VK_FRONT_FACE_CLOCKWISE : VK_FRONT_FACE_COUNTER_CLOCKWISE);5762rasterization_state_create_info.depthBiasEnable = p_rasterization_state.depth_bias_enabled;5763rasterization_state_create_info.depthBiasConstantFactor = p_rasterization_state.depth_bias_constant_factor;5764rasterization_state_create_info.depthBiasClamp = p_rasterization_state.depth_bias_clamp;5765rasterization_state_create_info.depthBiasSlopeFactor = p_rasterization_state.depth_bias_slope_factor;5766rasterization_state_create_info.lineWidth = p_rasterization_state.line_width;57675768// Multisample.5769VkPipelineMultisampleStateCreateInfo multisample_state_create_info = {};5770multisample_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;5771multisample_state_create_info.rasterizationSamples = _ensure_supported_sample_count(p_multisample_state.sample_count);5772multisample_state_create_info.sampleShadingEnable = p_multisample_state.enable_sample_shading;5773multisample_state_create_info.minSampleShading = p_multisample_state.min_sample_shading;5774if (p_multisample_state.sample_mask.size()) {5775static_assert(ARRAYS_COMPATIBLE(uint32_t, VkSampleMask));5776multisample_state_create_info.pSampleMask = p_multisample_state.sample_mask.ptr();5777} else {5778multisample_state_create_info.pSampleMask = nullptr;5779}5780multisample_state_create_info.alphaToCoverageEnable = p_multisample_state.enable_alpha_to_coverage;5781multisample_state_create_info.alphaToOneEnable = p_multisample_state.enable_alpha_to_one;57825783// Depth stencil.57845785VkPipelineDepthStencilStateCreateInfo depth_stencil_state_create_info = {};5786depth_stencil_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;5787depth_stencil_state_create_info.depthTestEnable = p_depth_stencil_state.enable_depth_test;5788depth_stencil_state_create_info.depthWriteEnable = p_depth_stencil_state.enable_depth_write;5789depth_stencil_state_create_info.depthCompareOp = (VkCompareOp)p_depth_stencil_state.depth_compare_operator;5790depth_stencil_state_create_info.depthBoundsTestEnable = p_depth_stencil_state.enable_depth_range;5791depth_stencil_state_create_info.stencilTestEnable = p_depth_stencil_state.enable_stencil;57925793depth_stencil_state_create_info.front.failOp = (VkStencilOp)p_depth_stencil_state.front_op.fail;5794depth_stencil_state_create_info.front.passOp = (VkStencilOp)p_depth_stencil_state.front_op.pass;5795depth_stencil_state_create_info.front.depthFailOp = (VkStencilOp)p_depth_stencil_state.front_op.depth_fail;5796depth_stencil_state_create_info.front.compareOp = (VkCompareOp)p_depth_stencil_state.front_op.compare;5797depth_stencil_state_create_info.front.compareMask = p_depth_stencil_state.front_op.compare_mask;5798depth_stencil_state_create_info.front.writeMask = p_depth_stencil_state.front_op.write_mask;5799depth_stencil_state_create_info.front.reference = p_depth_stencil_state.front_op.reference;58005801depth_stencil_state_create_info.back.failOp = (VkStencilOp)p_depth_stencil_state.back_op.fail;5802depth_stencil_state_create_info.back.passOp = (VkStencilOp)p_depth_stencil_state.back_op.pass;5803depth_stencil_state_create_info.back.depthFailOp = (VkStencilOp)p_depth_stencil_state.back_op.depth_fail;5804depth_stencil_state_create_info.back.compareOp = (VkCompareOp)p_depth_stencil_state.back_op.compare;5805depth_stencil_state_create_info.back.compareMask = p_depth_stencil_state.back_op.compare_mask;5806depth_stencil_state_create_info.back.writeMask = p_depth_stencil_state.back_op.write_mask;5807depth_stencil_state_create_info.back.reference = p_depth_stencil_state.back_op.reference;58085809depth_stencil_state_create_info.minDepthBounds = p_depth_stencil_state.depth_range_min;5810depth_stencil_state_create_info.maxDepthBounds = p_depth_stencil_state.depth_range_max;58115812// Blend state.58135814VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = {};5815color_blend_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;5816color_blend_state_create_info.logicOpEnable = p_blend_state.enable_logic_op;5817color_blend_state_create_info.logicOp = (VkLogicOp)p_blend_state.logic_op;58185819VkPipelineColorBlendAttachmentState *vk_attachment_states = ALLOCA_ARRAY(VkPipelineColorBlendAttachmentState, p_color_attachments.size());5820{5821for (uint32_t i = 0; i < p_color_attachments.size(); i++) {5822vk_attachment_states[i] = {};5823if (p_color_attachments[i] != ATTACHMENT_UNUSED) {5824vk_attachment_states[i].blendEnable = p_blend_state.attachments[i].enable_blend;58255826vk_attachment_states[i].srcColorBlendFactor = (VkBlendFactor)p_blend_state.attachments[i].src_color_blend_factor;5827vk_attachment_states[i].dstColorBlendFactor = (VkBlendFactor)p_blend_state.attachments[i].dst_color_blend_factor;5828vk_attachment_states[i].colorBlendOp = (VkBlendOp)p_blend_state.attachments[i].color_blend_op;58295830vk_attachment_states[i].srcAlphaBlendFactor = (VkBlendFactor)p_blend_state.attachments[i].src_alpha_blend_factor;5831vk_attachment_states[i].dstAlphaBlendFactor = (VkBlendFactor)p_blend_state.attachments[i].dst_alpha_blend_factor;5832vk_attachment_states[i].alphaBlendOp = (VkBlendOp)p_blend_state.attachments[i].alpha_blend_op;58335834if (p_blend_state.attachments[i].write_r) {5835vk_attachment_states[i].colorWriteMask |= VK_COLOR_COMPONENT_R_BIT;5836}5837if (p_blend_state.attachments[i].write_g) {5838vk_attachment_states[i].colorWriteMask |= VK_COLOR_COMPONENT_G_BIT;5839}5840if (p_blend_state.attachments[i].write_b) {5841vk_attachment_states[i].colorWriteMask |= VK_COLOR_COMPONENT_B_BIT;5842}5843if (p_blend_state.attachments[i].write_a) {5844vk_attachment_states[i].colorWriteMask |= VK_COLOR_COMPONENT_A_BIT;5845}5846}5847}5848}5849color_blend_state_create_info.attachmentCount = p_color_attachments.size();5850color_blend_state_create_info.pAttachments = vk_attachment_states;58515852color_blend_state_create_info.blendConstants[0] = p_blend_state.blend_constant.r;5853color_blend_state_create_info.blendConstants[1] = p_blend_state.blend_constant.g;5854color_blend_state_create_info.blendConstants[2] = p_blend_state.blend_constant.b;5855color_blend_state_create_info.blendConstants[3] = p_blend_state.blend_constant.a;58565857// Dynamic state.58585859VkPipelineDynamicStateCreateInfo dynamic_state_create_info = {};5860dynamic_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;58615862static const uint32_t MAX_DYN_STATE_COUNT = 9;5863VkDynamicState *vk_dynamic_states = ALLOCA_ARRAY(VkDynamicState, MAX_DYN_STATE_COUNT);5864uint32_t vk_dynamic_states_count = 0;58655866vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_VIEWPORT; // Viewport and scissor are always dynamic.5867vk_dynamic_states_count++;5868vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_SCISSOR;5869vk_dynamic_states_count++;5870if (p_dynamic_state.has_flag(DYNAMIC_STATE_LINE_WIDTH)) {5871vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_LINE_WIDTH;5872vk_dynamic_states_count++;5873}5874if (p_dynamic_state.has_flag(DYNAMIC_STATE_DEPTH_BIAS)) {5875vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_DEPTH_BIAS;5876vk_dynamic_states_count++;5877}5878if (p_dynamic_state.has_flag(DYNAMIC_STATE_BLEND_CONSTANTS)) {5879vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_BLEND_CONSTANTS;5880vk_dynamic_states_count++;5881}5882if (p_dynamic_state.has_flag(DYNAMIC_STATE_DEPTH_BOUNDS)) {5883vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_DEPTH_BOUNDS;5884vk_dynamic_states_count++;5885}5886if (p_dynamic_state.has_flag(DYNAMIC_STATE_STENCIL_COMPARE_MASK)) {5887vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK;5888vk_dynamic_states_count++;5889}5890if (p_dynamic_state.has_flag(DYNAMIC_STATE_STENCIL_WRITE_MASK)) {5891vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_STENCIL_WRITE_MASK;5892vk_dynamic_states_count++;5893}5894if (p_dynamic_state.has_flag(DYNAMIC_STATE_STENCIL_REFERENCE)) {5895vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_STENCIL_REFERENCE;5896vk_dynamic_states_count++;5897}5898DEV_ASSERT(vk_dynamic_states_count <= MAX_DYN_STATE_COUNT);58995900dynamic_state_create_info.dynamicStateCount = vk_dynamic_states_count;5901dynamic_state_create_info.pDynamicStates = vk_dynamic_states;59025903void *graphics_pipeline_nextptr = nullptr;59045905if (fsr_capabilities.attachment_supported) {5906// Fragment shading rate.5907// If FSR is used, this defines how the different FSR types are combined.5908// combinerOps[0] decides how we use the output of pipeline and primitive (drawcall) FSR.5909// combinerOps[1] decides how we use the output of combinerOps[0] and our attachment FSR.59105911VkPipelineFragmentShadingRateStateCreateInfoKHR *fsr_create_info = ALLOCA_SINGLE(VkPipelineFragmentShadingRateStateCreateInfoKHR);5912*fsr_create_info = {};5913fsr_create_info->sType = VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR;5914fsr_create_info->fragmentSize = { 4, 4 };5915fsr_create_info->combinerOps[0] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR; // We don't use pipeline/primitive FSR so this really doesn't matter.5916fsr_create_info->combinerOps[1] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR; // Always use the outcome of attachment FSR if enabled.59175918graphics_pipeline_nextptr = fsr_create_info;5919}59205921// Finally, pipeline create info.59225923const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;59245925VkGraphicsPipelineCreateInfo pipeline_create_info = {};59265927pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;5928pipeline_create_info.pNext = graphics_pipeline_nextptr;5929pipeline_create_info.stageCount = shader_info->vk_stages_create_info.size();59305931ERR_FAIL_COND_V_MSG(pipeline_create_info.stageCount == 0, PipelineID(),5932"Cannot create pipeline without shader module, please make sure shader modules are destroyed only after all associated pipelines are created.");5933VkPipelineShaderStageCreateInfo *vk_pipeline_stages = ALLOCA_ARRAY(VkPipelineShaderStageCreateInfo, shader_info->vk_stages_create_info.size());59345935thread_local std::vector<uint8_t> respv_optimized_data;5936thread_local LocalVector<respv::SpecConstant> respv_spec_constants;5937thread_local LocalVector<VkShaderModule> respv_shader_modules;5938thread_local LocalVector<VkSpecializationMapEntry> specialization_entries;59395940#if RECORD_PIPELINE_STATISTICS5941thread_local LocalVector<uint64_t> respv_run_time;5942thread_local LocalVector<uint64_t> respv_size;5943uint32_t stage_count = shader_info->vk_stages_create_info.size();5944respv_run_time.clear();5945respv_size.clear();5946respv_run_time.resize_initialized(stage_count);5947respv_size.resize_initialized(stage_count);5948#endif59495950respv_shader_modules.clear();5951specialization_entries.clear();59525953for (uint32_t i = 0; i < shader_info->vk_stages_create_info.size(); i++) {5954vk_pipeline_stages[i] = shader_info->vk_stages_create_info[i];59555956if (p_specialization_constants.size()) {5957bool use_pipeline_spec_constants = true;5958if ((i < shader_info->respv_stage_shaders.size()) && !shader_info->respv_stage_shaders[i].empty()) {5959#if RECORD_PIPELINE_STATISTICS5960uint64_t respv_start_time = OS::get_singleton()->get_ticks_usec();5961#endif5962// Attempt to optimize the shader using re-spirv before relying on the driver.5963respv_spec_constants.resize(p_specialization_constants.size());5964for (uint32_t j = 0; j < p_specialization_constants.size(); j++) {5965respv_spec_constants[j].specId = p_specialization_constants[j].constant_id;5966respv_spec_constants[j].values.resize(1);5967respv_spec_constants[j].values[0] = p_specialization_constants[j].int_value;5968}59695970respv::Options respv_options;5971#if RESPV_DONT_REMOVE_DEAD_CODE5972respv_options.removeDeadCode = false;5973#endif5974if (respv::Optimizer::run(shader_info->respv_stage_shaders[i], respv_spec_constants.ptr(), respv_spec_constants.size(), respv_optimized_data, respv_options)) {5975#if RESPV_VERBOSE5976String spec_constants;5977for (uint32_t j = 0; j < p_specialization_constants.size(); j++) {5978spec_constants += vformat("%d: %d", p_specialization_constants[j].constant_id, p_specialization_constants[j].int_value);5979if (j < p_specialization_constants.size() - 1) {5980spec_constants += ", ";5981}5982}59835984print_line(vformat("re-spirv transformed the shader from %d bytes to %d bytes with constants %s (%d).", shader_info->respv_stage_shaders[i].inlinedSpirvWords.size() * sizeof(uint32_t), respv_optimized_data.size(), spec_constants, p_shader.id));5985#endif59865987// Create the shader module with the optimized output.5988VkShaderModule shader_module = VK_NULL_HANDLE;5989VkShaderModuleCreateInfo shader_module_create_info = {};5990shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;5991shader_module_create_info.pCode = (const uint32_t *)(respv_optimized_data.data());5992shader_module_create_info.codeSize = respv_optimized_data.size();5993VkResult err = vkCreateShaderModule(vk_device, &shader_module_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SHADER_MODULE), &shader_module);5994if (err == VK_SUCCESS) {5995// Replace the module used in the creation info.5996vk_pipeline_stages[i].module = shader_module;5997respv_shader_modules.push_back(shader_module);5998use_pipeline_spec_constants = false;5999}60006001#if RECORD_PIPELINE_STATISTICS6002respv_run_time[i] = OS::get_singleton()->get_ticks_usec() - respv_start_time;6003respv_size[i] = respv_optimized_data.size();6004#endif6005} else {6006#if RESPV_VERBOSE6007print_line("re-spirv failed to optimize the shader.");6008#endif6009}6010}60116012if (use_pipeline_spec_constants) {6013// Use specialization constants through the driver.6014if (specialization_entries.is_empty()) {6015specialization_entries.resize(p_specialization_constants.size());6016for (uint32_t j = 0; j < p_specialization_constants.size(); j++) {6017specialization_entries[j] = {};6018specialization_entries[j].constantID = p_specialization_constants[j].constant_id;6019specialization_entries[j].offset = (const char *)&p_specialization_constants[j].int_value - (const char *)p_specialization_constants.ptr();6020specialization_entries[j].size = sizeof(uint32_t);6021}6022}60236024VkSpecializationInfo *specialization_info = ALLOCA_SINGLE(VkSpecializationInfo);6025*specialization_info = {};6026specialization_info->dataSize = p_specialization_constants.size() * sizeof(PipelineSpecializationConstant);6027specialization_info->pData = p_specialization_constants.ptr();6028specialization_info->mapEntryCount = specialization_entries.size();6029specialization_info->pMapEntries = specialization_entries.ptr();60306031vk_pipeline_stages[i].pSpecializationInfo = specialization_info;6032}6033}6034}60356036const RenderPassInfo *render_pass = (const RenderPassInfo *)(p_render_pass.id);6037pipeline_create_info.pStages = vk_pipeline_stages;6038pipeline_create_info.pVertexInputState = vertex_input_state_create_info;6039pipeline_create_info.pInputAssemblyState = &input_assembly_create_info;6040pipeline_create_info.pTessellationState = &tessellation_create_info;6041pipeline_create_info.pViewportState = &viewport_state_create_info;6042pipeline_create_info.pRasterizationState = &rasterization_state_create_info;6043pipeline_create_info.pMultisampleState = &multisample_state_create_info;6044pipeline_create_info.pDepthStencilState = &depth_stencil_state_create_info;6045pipeline_create_info.pColorBlendState = &color_blend_state_create_info;6046pipeline_create_info.pDynamicState = &dynamic_state_create_info;6047pipeline_create_info.layout = shader_info->vk_pipeline_layout;6048pipeline_create_info.renderPass = render_pass->vk_render_pass;6049pipeline_create_info.subpass = p_render_subpass;60506051#if RECORD_PIPELINE_STATISTICS6052uint64_t pipeline_start_time = OS::get_singleton()->get_ticks_usec();6053#endif60546055VkPipeline vk_pipeline = VK_NULL_HANDLE;6056VkResult err = vkCreateGraphicsPipelines(vk_device, pipelines_cache.vk_cache, 1, &pipeline_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE), &vk_pipeline);6057ERR_FAIL_COND_V_MSG(err, PipelineID(), "vkCreateGraphicsPipelines failed with error " + itos(err) + ".");60586059#if RECORD_PIPELINE_STATISTICS6060{6061MutexLock lock(pipeline_statistics.file_access_mutex);6062uint64_t pipeline_creation_time = OS::get_singleton()->get_ticks_usec() - pipeline_start_time;6063for (uint32_t i = 0; i < shader_info->vk_stages_create_info.size(); i++) {6064PackedStringArray csv_array = {6065shader_info->name,6066String::num_uint64(hash_murmur3_buffer(shader_info->spirv_stage_bytes[i].ptr(), shader_info->spirv_stage_bytes[i].size())),6067String::num_uint64(i),6068String::num_uint64(respv_size[i] > 0),6069String::num_uint64(shader_info->original_stage_size[i]),6070String::num_uint64(respv_size[i] > 0 ? respv_size[i] : shader_info->spirv_stage_bytes[i].size()),6071String::num_uint64(respv_run_time[i] + pipeline_creation_time)6072};60736074pipeline_statistics.file_access->store_csv_line(csv_array);6075}60766077pipeline_statistics.file_access->flush();6078}6079#endif60806081// Destroy any modules created temporarily by re-spirv.6082for (VkShaderModule vk_module : respv_shader_modules) {6083vkDestroyShaderModule(vk_device, vk_module, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SHADER_MODULE));6084}60856086return PipelineID(vk_pipeline);6087}60886089/********************/6090/**** RAYTRACING ****/6091/********************/60926093// RDD::AccelerationStructureGeometryBits == VkGeometryFlagsKHR.6094static_assert(ENUM_MEMBERS_EQUAL(RDD::ACCELERATION_STRUCTURE_GEOMETRY_OPAQUE, VK_GEOMETRY_OPAQUE_BIT_KHR));6095static_assert(ENUM_MEMBERS_EQUAL(RDD::ACCELERATION_STRUCTURE_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION, VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR));60966097RDD::AccelerationStructureID RenderingDeviceDriverVulkan::blas_create(BufferID p_vertex_buffer, uint64_t p_vertex_offset, VertexFormatID p_vertex_format, uint32_t p_vertex_count, uint32_t p_position_attribute_location, BufferID p_index_buffer, IndexBufferFormat p_index_format, uint64_t p_index_offset_bytes, uint32_t p_index_count, BitField<AccelerationStructureGeometryBits> p_geometry_bits) {6098#if VULKAN_RAYTRACING_ENABLED6099const VertexFormatInfo *vf_info = (const VertexFormatInfo *)p_vertex_format.id;61006101const VkVertexInputAttributeDescription *position_attribute = nullptr;6102for (const VkVertexInputAttributeDescription &attribute : vf_info->vk_attributes) {6103if (attribute.location == p_position_attribute_location) {6104position_attribute = &attribute;6105break;6106}6107}6108ERR_FAIL_NULL_V_MSG(position_attribute, AccelerationStructureID(), "BLAS position attribute location is missing from the vertex format.");61096110uint32_t position_binding_index = position_attribute->binding;6111if (position_binding_index == UINT32_MAX) {6112position_binding_index = p_position_attribute_location;6113}61146115const VkVertexInputBindingDescription *position_binding = nullptr;6116for (const VkVertexInputBindingDescription &binding : vf_info->vk_bindings) {6117if (binding.binding == position_binding_index) {6118position_binding = &binding;6119break;6120}6121}6122ERR_FAIL_NULL_V_MSG(position_binding, AccelerationStructureID(), "BLAS position attribute binding is missing from the vertex format.");61236124VkDeviceSize buffer_offset = position_attribute->offset;61256126VkDeviceAddress vertex_address = buffer_get_device_address(p_vertex_buffer) + buffer_offset;6127VkDeviceAddress index_address = buffer_get_device_address(p_index_buffer) + p_index_offset_bytes;61286129VkDeviceSize vertex_stride = position_binding->stride;6130VkFormat vertex_format = position_attribute->format;6131uint32_t max_vertex = p_vertex_count ? p_vertex_count - 1 : 0;61326133AccelerationStructureInfo *accel_info = VersatileResource::allocate<AccelerationStructureInfo>(resources_allocator);61346135accel_info->geometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;6136accel_info->geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;6137accel_info->geometry.flags = p_geometry_bits;61386139accel_info->geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;6140accel_info->geometry.geometry.triangles.vertexFormat = vertex_format;6141accel_info->geometry.geometry.triangles.vertexData.deviceAddress = vertex_address;6142accel_info->geometry.geometry.triangles.vertexStride = vertex_stride;6143accel_info->geometry.geometry.triangles.indexType = p_index_format == INDEX_BUFFER_FORMAT_UINT16 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32;6144accel_info->geometry.geometry.triangles.indexData.deviceAddress = index_address;6145accel_info->geometry.geometry.triangles.transformData.deviceAddress = 0;6146// Number of vertices in vertexData minus one, aka max vertex index.6147accel_info->geometry.geometry.triangles.maxVertex = max_vertex;61486149// Info for building BLAS.6150uint32_t primitive_count = p_vertex_count / 3;6151if (p_index_buffer) {6152primitive_count = p_index_count / 3;6153}6154// The vertex offset is expressed in bytes.6155uint32_t first_vertex = p_vertex_offset / vertex_stride;6156accel_info->range_info.firstVertex = first_vertex;6157accel_info->range_info.primitiveCount = primitive_count;6158accel_info->range_info.primitiveOffset = 0;6159accel_info->range_info.transformOffset = 0;6160uint32_t max_primitive_count = accel_info->range_info.primitiveCount;61616162accel_info->build_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;6163accel_info->build_info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;6164accel_info->build_info.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;6165accel_info->build_info.pGeometries = &accel_info->geometry;6166accel_info->build_info.geometryCount = 1;6167accel_info->build_info.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;61686169VkAccelerationStructureBuildSizesInfoKHR size_info = {};6170size_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;61716172vkGetAccelerationStructureBuildSizesKHR(vk_device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &accel_info->build_info, &max_primitive_count, &size_info);6173_acceleration_structure_create(VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, size_info, accel_info);61746175return AccelerationStructureID(accel_info);6176#else6177return AccelerationStructureID();6178#endif6179}61806181#if VULKAN_RAYTRACING_ENABLED6182static _FORCE_INLINE_ void _store_transform_transposed_3x4(const Transform3D &p_mtx, VkTransformMatrixKHR &r_mtx) {6183r_mtx.matrix[0][0] = p_mtx.basis.rows[0][0];6184r_mtx.matrix[0][1] = p_mtx.basis.rows[0][1];6185r_mtx.matrix[0][2] = p_mtx.basis.rows[0][2];6186r_mtx.matrix[0][3] = p_mtx.origin.x;6187r_mtx.matrix[1][0] = p_mtx.basis.rows[1][0];6188r_mtx.matrix[1][1] = p_mtx.basis.rows[1][1];6189r_mtx.matrix[1][2] = p_mtx.basis.rows[1][2];6190r_mtx.matrix[1][3] = p_mtx.origin.y;6191r_mtx.matrix[2][0] = p_mtx.basis.rows[2][0];6192r_mtx.matrix[2][1] = p_mtx.basis.rows[2][1];6193r_mtx.matrix[2][2] = p_mtx.basis.rows[2][2];6194r_mtx.matrix[2][3] = p_mtx.origin.z;6195}6196#endif61976198uint32_t RenderingDeviceDriverVulkan::tlas_instances_buffer_get_size_bytes(uint32_t p_instance_count) {6199#if VULKAN_RAYTRACING_ENABLED6200return p_instance_count * sizeof(VkAccelerationStructureInstanceKHR);6201#else6202return 0;6203#endif6204}62056206void RenderingDeviceDriverVulkan::tlas_instances_buffer_fill(BufferID p_instances_buffer, VectorView<AccelerationStructureID> p_blases, VectorView<Transform3D> p_transforms) {6207#if VULKAN_RAYTRACING_ENABLED6208uint32_t blases_count = p_blases.size();6209ERR_FAIL_COND_MSG(blases_count != p_transforms.size(), "Blases and transforms vectors must have the same size.");6210ERR_FAIL_COND(blases_count == 0);62116212LocalVector<VkAccelerationStructureInstanceKHR> instances;6213instances.resize(blases_count);62146215for (uint32_t i = 0; i < blases_count; ++i) {6216const AccelerationStructureID &blas = p_blases[i];6217AccelerationStructureInfo *blas_info = (AccelerationStructureInfo *)blas.id;62186219VkAccelerationStructureInstanceKHR &instance = instances[i];6220_store_transform_transposed_3x4(p_transforms[i], instance.transform);6221instance.instanceCustomIndex = i;6222instance.mask = 0xFF;6223instance.accelerationStructureReference = buffer_get_device_address(blas_info->buffer);6224instance.instanceShaderBindingTableRecordOffset = 0;6225instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;6226}62276228uint8_t *data_ptr = buffer_map(p_instances_buffer);6229ERR_FAIL_NULL(data_ptr);6230uint32_t instances_size = blases_count * sizeof(instances[0]);6231memcpy(data_ptr, instances.ptr(), instances_size);6232buffer_unmap(p_instances_buffer);6233#endif6234}62356236RDD::AccelerationStructureID RenderingDeviceDriverVulkan::tlas_create(BufferID p_instances_buffer) {6237#if VULKAN_RAYTRACING_ENABLED6238ERR_FAIL_COND_V(p_instances_buffer == BufferID(), AccelerationStructureID());62396240AccelerationStructureInfo *accel_info = VersatileResource::allocate<AccelerationStructureInfo>(resources_allocator);62416242accel_info->geometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;6243accel_info->geometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;6244accel_info->geometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR;6245accel_info->geometry.geometry.instances.data.deviceAddress = buffer_get_device_address(p_instances_buffer);62466247accel_info->build_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;6248accel_info->build_info.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;6249accel_info->build_info.geometryCount = 1;6250accel_info->build_info.pGeometries = &accel_info->geometry;6251accel_info->build_info.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;6252accel_info->build_info.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;62536254uint32_t instance_count = buffer_get_allocation_size(p_instances_buffer) / sizeof(VkAccelerationStructureInstanceKHR);6255VkAccelerationStructureBuildSizesInfoKHR size_info = {};6256size_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;6257vkGetAccelerationStructureBuildSizesKHR(vk_device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &accel_info->build_info, &instance_count, &size_info);6258accel_info->range_info.primitiveCount = instance_count;62596260_acceleration_structure_create(VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, size_info, accel_info);6261return AccelerationStructureID(accel_info);6262#else6263return AccelerationStructureID();6264#endif6265}62666267#if VULKAN_RAYTRACING_ENABLED6268static VkDeviceAddress _align_up_address(VkDeviceAddress address, VkDeviceAddress alignment) {6269return (address + (alignment - 1)) & ~(alignment - 1);6270}6271#endif62726273void RenderingDeviceDriverVulkan::_acceleration_structure_create(VkAccelerationStructureTypeKHR p_type, VkAccelerationStructureBuildSizesInfoKHR p_size_info, AccelerationStructureInfo *r_accel_info) {6274#if VULKAN_RAYTRACING_ENABLED6275RDD::BufferID buffer = buffer_create(p_size_info.accelerationStructureSize, RDD::BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT | RDD::BUFFER_USAGE_STORAGE_BIT | RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT, RDD::MEMORY_ALLOCATION_TYPE_GPU, UINT64_MAX);6276r_accel_info->buffer = buffer;62776278// Scratch address must be a multiple of minAccelerationStructureScratchOffsetAlignment.6279r_accel_info->scratch_alignment = acceleration_structure_capabilities.min_acceleration_structure_scratch_offset_alignment;6280r_accel_info->scratch_size = p_size_info.buildScratchSize + r_accel_info->scratch_alignment;62816282VkAccelerationStructureCreateInfoKHR accel_create_info = {};6283accel_create_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;6284accel_create_info.type = p_type;6285accel_create_info.size = p_size_info.accelerationStructureSize;6286accel_create_info.buffer = ((const BufferInfo *)buffer.id)->vk_buffer;6287VkResult err = vkCreateAccelerationStructureKHR(vk_device, &accel_create_info, nullptr, &r_accel_info->vk_acceleration_structure);6288ERR_FAIL_COND_MSG(err, "vkCreateAccelerationStructureKHR failed with error " + itos(err) + ".");6289r_accel_info->build_info.dstAccelerationStructure = r_accel_info->vk_acceleration_structure;6290#endif6291}62926293void RenderingDeviceDriverVulkan::acceleration_structure_free(AccelerationStructureID p_acceleration_structure) {6294#if VULKAN_RAYTRACING_ENABLED6295AccelerationStructureInfo *accel_info = (AccelerationStructureInfo *)p_acceleration_structure.id;6296ERR_FAIL_NULL_MSG(accel_info, "Acceleration structure input parameter is not valid.");6297if (accel_info->instances_buffer) {6298buffer_free(accel_info->instances_buffer);6299}6300if (accel_info->buffer) {6301buffer_free(accel_info->buffer);6302}6303if (accel_info->vk_acceleration_structure) {6304vkDestroyAccelerationStructureKHR(vk_device, accel_info->vk_acceleration_structure, nullptr);6305}6306VersatileResource::free(resources_allocator, accel_info);6307#endif6308}63096310uint32_t RenderingDeviceDriverVulkan::acceleration_structure_get_scratch_size_bytes(AccelerationStructureID p_acceleration_structure) {6311AccelerationStructureInfo *accel_info = (AccelerationStructureInfo *)p_acceleration_structure.id;6312ERR_FAIL_NULL_V_MSG(accel_info, 0, "Acceleration structure input parameter is not valid.");6313return accel_info->scratch_size;6314}63156316// ----- COMMANDS -----63176318void RenderingDeviceDriverVulkan::command_build_acceleration_structure(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer) {6319#if VULKAN_RAYTRACING_ENABLED6320const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;6321AccelerationStructureInfo *accel_info = (AccelerationStructureInfo *)p_acceleration_structure.id;63226323VkAccelerationStructureBuildGeometryInfoKHR *build_info = &accel_info->build_info;6324VkDeviceAddress scratch_address = buffer_get_device_address(p_scratch_buffer);6325build_info->scratchData.deviceAddress = _align_up_address(scratch_address, accel_info->scratch_alignment);63266327const VkAccelerationStructureBuildRangeInfoKHR *range_info_ptr = &accel_info->range_info;63286329vkCmdBuildAccelerationStructuresKHR(command_buffer->vk_command_buffer, 1, build_info, &range_info_ptr);6330#endif6331}63326333void RenderingDeviceDriverVulkan::command_bind_raytracing_pipeline(CommandBufferID p_cmd_buffer, RaytracingPipelineID p_pipeline) {6334const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;6335bound_raytracing_pipeline_id = p_pipeline;6336const RaytracingPipelineInfo *rpi = (const RaytracingPipelineInfo *)p_pipeline.id;6337vkCmdBindPipeline(command_buffer->vk_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, rpi->vk_pipeline);6338}63396340void RenderingDeviceDriverVulkan::command_bind_raytracing_uniform_set(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index) {6341const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;6342const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;6343const UniformSetInfo *usi = (const UniformSetInfo *)p_uniform_set.id;6344vkCmdBindDescriptorSets(command_buffer->vk_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, shader_info->vk_pipeline_layout, p_set_index, 1, &usi->vk_descriptor_set, 0, nullptr);6345}63466347void RenderingDeviceDriverVulkan::command_trace_rays(CommandBufferID p_cmd_buffer, uint32_t p_width, uint32_t p_height) {6348#if VULKAN_RAYTRACING_ENABLED6349const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;6350ERR_FAIL_COND_MSG(bound_raytracing_pipeline_id == RaytracingPipelineID(), "A raytracing pipeline must have been bound with `command_bind_raytracing_pipeline()`.");6351const RaytracingPipelineInfo *rpi = (const RaytracingPipelineInfo *)bound_raytracing_pipeline_id.id;6352vkCmdTraceRaysKHR(command_buffer->vk_command_buffer, &rpi->regions.raygen, &rpi->regions.miss, &rpi->regions.hit, &rpi->regions.call, p_width, p_height, 1);6353#endif6354}63556356// --- PIPELINE ---63576358RDD::RaytracingPipelineID RenderingDeviceDriverVulkan::raytracing_pipeline_create(ShaderID p_shader, VectorView<PipelineSpecializationConstant> p_specialization_constants) {6359#if VULKAN_RAYTRACING_ENABLED6360const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;63616362VkRayTracingPipelineCreateInfoKHR pipeline_create_info = {};6363pipeline_create_info.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR;63646365// Stages.6366pipeline_create_info.stageCount = shader_info->vk_stages_create_info.size();63676368VkPipelineShaderStageCreateInfo *vk_pipeline_stages = ALLOCA_ARRAY(VkPipelineShaderStageCreateInfo, pipeline_create_info.stageCount);63696370for (uint32_t i = 0; i < pipeline_create_info.stageCount; i++) {6371vk_pipeline_stages[i] = shader_info->vk_stages_create_info[i];63726373if (p_specialization_constants.size()) {6374VkSpecializationMapEntry *specialization_map_entries = ALLOCA_ARRAY(VkSpecializationMapEntry, p_specialization_constants.size());6375for (uint32_t j = 0; j < p_specialization_constants.size(); j++) {6376specialization_map_entries[j] = {};6377specialization_map_entries[j].constantID = p_specialization_constants[j].constant_id;6378specialization_map_entries[j].offset = (const char *)&p_specialization_constants[j].int_value - (const char *)p_specialization_constants.ptr();6379specialization_map_entries[j].size = sizeof(uint32_t);6380}63816382VkSpecializationInfo *specialization_info = ALLOCA_SINGLE(VkSpecializationInfo);6383*specialization_info = {};6384specialization_info->dataSize = p_specialization_constants.size() * sizeof(PipelineSpecializationConstant);6385specialization_info->pData = p_specialization_constants.ptr();6386specialization_info->mapEntryCount = p_specialization_constants.size();6387specialization_info->pMapEntries = specialization_map_entries;63886389vk_pipeline_stages[i].pSpecializationInfo = specialization_info;6390}6391}63926393// Groups.6394pipeline_create_info.groupCount = pipeline_create_info.stageCount;6395VkRayTracingShaderGroupCreateInfoKHR *vk_pipeline_groups = ALLOCA_ARRAY(VkRayTracingShaderGroupCreateInfoKHR, pipeline_create_info.groupCount);6396for (uint32_t i = 0; i < pipeline_create_info.stageCount; i++) {6397vk_pipeline_groups[i] = shader_info->vk_groups_create_info[i];6398}63996400// Pipeline.6401pipeline_create_info.layout = shader_info->vk_pipeline_layout;6402pipeline_create_info.pStages = vk_pipeline_stages;6403pipeline_create_info.pGroups = vk_pipeline_groups;6404pipeline_create_info.maxPipelineRayRecursionDepth = 1;64056406RaytracingPipelineInfo *rpi = VersatileResource::allocate<RaytracingPipelineInfo>(resources_allocator);64076408VkResult err = vkCreateRayTracingPipelinesKHR(vk_device, VK_NULL_HANDLE, pipelines_cache.vk_cache, 1, &pipeline_create_info, nullptr, &rpi->vk_pipeline);6409ERR_FAIL_COND_V_MSG(err, RaytracingPipelineID(), "vkCreateRayTracingPipelinesKHR failed with error " + itos(err) + ".");64106411RaytracingPipelineID raytracing_pipeline = RaytracingPipelineID(rpi);6412err = _raytracing_pipeline_stb_create(raytracing_pipeline, p_shader);6413ERR_FAIL_COND_V_MSG(err, RaytracingPipelineID(), "_raytracing_pipeline_stb_create failed with error " + itos(err) + ".");64146415return raytracing_pipeline;6416#else6417return RaytracingPipelineID();6418#endif6419}64206421VkResult RenderingDeviceDriverVulkan::_raytracing_pipeline_stb_create(RaytracingPipelineID p_pipeline, ShaderID p_shader) {6422#if VULKAN_RAYTRACING_ENABLED6423RaytracingPipelineInfo *rpi = (RaytracingPipelineInfo *)p_pipeline.id;6424const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;64256426// Shader group handles.6427uint32_t handle_size_aligned = raytracing_capabilities.shader_group_handle_size_aligned;6428uint32_t base_alignment = raytracing_capabilities.shader_group_base_alignment;64296430rpi->regions.raygen.stride = _align_up(handle_size_aligned * shader_info->region_count.raygen_count, base_alignment);6431rpi->regions.raygen.size = rpi->regions.raygen.stride; // odd but ok.64326433rpi->regions.hit.stride = handle_size_aligned;6434rpi->regions.hit.size = _align_up(handle_size_aligned * shader_info->region_count.hit_count, base_alignment);64356436rpi->regions.miss.stride = handle_size_aligned;6437rpi->regions.miss.size = _align_up(handle_size_aligned * shader_info->region_count.miss_count, base_alignment);64386439rpi->regions.call.stride = 0;6440rpi->regions.call.size = 0;64416442// Shader binding table.6443uint32_t sbt_size = rpi->regions.raygen.size + rpi->regions.hit.size + rpi->regions.miss.size + rpi->regions.call.size;6444rpi->sbt_buffer = buffer_create(sbt_size, BUFFER_USAGE_TRANSFER_FROM_BIT | BUFFER_USAGE_DEVICE_ADDRESS_BIT | BUFFER_USAGE_SHADER_BINDING_TABLE_BIT, MEMORY_ALLOCATION_TYPE_CPU, UINT64_MAX);64456446// Update regions addresses.6447rpi->regions.raygen.deviceAddress = buffer_get_device_address(rpi->sbt_buffer);6448rpi->regions.hit.deviceAddress = rpi->regions.raygen.deviceAddress + rpi->regions.raygen.size;6449rpi->regions.miss.deviceAddress = rpi->regions.hit.deviceAddress + rpi->regions.hit.size;6450rpi->regions.call.deviceAddress = 0;64516452// Update shader binding table buffer.6453uint32_t handle_size = raytracing_capabilities.shader_group_handle_size;6454uint32_t handles_size = shader_info->region_count.group_count * handle_size;6455LocalVector<uint8_t> handles_data;6456handles_data.resize(handles_size);6457uint8_t *handles_ptr = handles_data.ptr();64586459VkResult err = vkGetRayTracingShaderGroupHandlesKHR(vk_device, rpi->vk_pipeline, 0, shader_info->region_count.group_count, handles_size, handles_ptr);6460ERR_FAIL_COND_V_MSG(err, err, "vkGetRayTracingShaderGroupHandlesKHR failed with error " + itos(err) + ".");64616462uint8_t *sbt_ptr = buffer_map(rpi->sbt_buffer);6463uint8_t *sbt_data = sbt_ptr;6464uint32_t handle_index = 0;64656466// Raygen.6467memcpy(sbt_data, handles_ptr + handle_index * handle_size, handle_size);6468++handle_index;64696470// Hit.6471sbt_data = sbt_ptr + rpi->regions.raygen.size;6472for (uint32_t i = 0; i < shader_info->region_count.hit_count; ++i) {6473memcpy(sbt_data, handles_ptr + handle_index * handle_size, handle_size);6474sbt_data += rpi->regions.hit.stride;6475++handle_index;6476}64776478// Miss.6479sbt_data = sbt_ptr + rpi->regions.raygen.size + rpi->regions.hit.size;6480for (uint32_t i = 0; i < shader_info->region_count.miss_count; ++i) {6481memcpy(sbt_data, handles_ptr + handle_index * handle_size, handle_size);6482sbt_data += rpi->regions.miss.stride;6483++handle_index;6484}64856486buffer_unmap(rpi->sbt_buffer);64876488return err;6489#else6490return VK_ERROR_UNKNOWN;6491#endif6492}64936494void RenderingDeviceDriverVulkan::raytracing_pipeline_free(RaytracingPipelineID p_pipeline) {6495const RaytracingPipelineInfo *rpi = (const RaytracingPipelineInfo *)p_pipeline.id;6496vkDestroyPipeline(vk_device, rpi->vk_pipeline, nullptr);6497if (rpi->sbt_buffer) {6498buffer_free(rpi->sbt_buffer);6499}6500VersatileResource::free(resources_allocator, rpi);6501}65026503/*****************/6504/**** COMPUTE ****/6505/*****************/65066507// ----- COMMANDS -----65086509void RenderingDeviceDriverVulkan::command_bind_compute_pipeline(CommandBufferID p_cmd_buffer, PipelineID p_pipeline) {6510const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;6511vkCmdBindPipeline(command_buffer->vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, (VkPipeline)p_pipeline.id);6512}65136514void RenderingDeviceDriverVulkan::command_bind_compute_uniform_sets(CommandBufferID p_cmd_buffer, VectorView<UniformSetID> p_uniform_sets, ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count, uint32_t p_dynamic_offsets) {6515if (p_set_count == 0) {6516return;6517}65186519thread_local LocalVector<VkDescriptorSet> sets;6520sets.clear();6521sets.resize(p_set_count);65226523uint32_t dynamic_offsets[MAX_DYNAMIC_BUFFERS];6524uint32_t shift = 0u;6525uint32_t curr_dynamic_offset = 0u;65266527for (uint32_t i = 0; i < p_set_count; i++) {6528const UniformSetInfo *usi = (const UniformSetInfo *)p_uniform_sets[i].id;65296530sets[i] = usi->vk_descriptor_set;65316532// At this point this assert should already have been validated.6533DEV_ASSERT(curr_dynamic_offset + usi->dynamic_buffers.size() <= MAX_DYNAMIC_BUFFERS);65346535const uint32_t dynamic_offset_count = usi->dynamic_buffers.size();6536for (uint32_t j = 0u; j < dynamic_offset_count; ++j) {6537const uint32_t frame_idx = (p_dynamic_offsets >> shift) & 0xFu;6538shift += 4u;6539dynamic_offsets[curr_dynamic_offset++] = uint32_t(frame_idx * usi->dynamic_buffers[j]->size);6540}6541}65426543const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;6544const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;6545vkCmdBindDescriptorSets(command_buffer->vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, shader_info->vk_pipeline_layout, p_first_set_index, p_set_count, &sets[0], curr_dynamic_offset, dynamic_offsets);6546}65476548void RenderingDeviceDriverVulkan::command_compute_dispatch(CommandBufferID p_cmd_buffer, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups) {6549const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;6550vkCmdDispatch(command_buffer->vk_command_buffer, p_x_groups, p_y_groups, p_z_groups);6551}65526553void RenderingDeviceDriverVulkan::command_compute_dispatch_indirect(CommandBufferID p_cmd_buffer, BufferID p_indirect_buffer, uint64_t p_offset) {6554const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;6555const BufferInfo *buf_info = (const BufferInfo *)p_indirect_buffer.id;6556vkCmdDispatchIndirect(command_buffer->vk_command_buffer, buf_info->vk_buffer, p_offset);6557}65586559// ----- PIPELINE -----65606561RDD::PipelineID RenderingDeviceDriverVulkan::compute_pipeline_create(ShaderID p_shader, VectorView<PipelineSpecializationConstant> p_specialization_constants) {6562const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;65636564VkComputePipelineCreateInfo pipeline_create_info = {};6565pipeline_create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;6566pipeline_create_info.stage = shader_info->vk_stages_create_info[0];6567pipeline_create_info.layout = shader_info->vk_pipeline_layout;65686569if (p_specialization_constants.size()) {6570VkSpecializationMapEntry *specialization_map_entries = ALLOCA_ARRAY(VkSpecializationMapEntry, p_specialization_constants.size());6571for (uint32_t i = 0; i < p_specialization_constants.size(); i++) {6572specialization_map_entries[i] = {};6573specialization_map_entries[i].constantID = p_specialization_constants[i].constant_id;6574specialization_map_entries[i].offset = (const char *)&p_specialization_constants[i].int_value - (const char *)p_specialization_constants.ptr();6575specialization_map_entries[i].size = sizeof(uint32_t);6576}65776578VkSpecializationInfo *specialization_info = ALLOCA_SINGLE(VkSpecializationInfo);6579*specialization_info = {};6580specialization_info->dataSize = p_specialization_constants.size() * sizeof(PipelineSpecializationConstant);6581specialization_info->pData = p_specialization_constants.ptr();6582specialization_info->mapEntryCount = p_specialization_constants.size();6583specialization_info->pMapEntries = specialization_map_entries;65846585pipeline_create_info.stage.pSpecializationInfo = specialization_info;6586}65876588VkPipeline vk_pipeline = VK_NULL_HANDLE;6589VkResult err = vkCreateComputePipelines(vk_device, pipelines_cache.vk_cache, 1, &pipeline_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE), &vk_pipeline);6590ERR_FAIL_COND_V_MSG(err, PipelineID(), "vkCreateComputePipelines failed with error " + itos(err) + ".");65916592return PipelineID(vk_pipeline);6593}65946595/*****************/6596/**** QUERIES ****/6597/*****************/65986599// ----- TIMESTAMP -----66006601RDD::QueryPoolID RenderingDeviceDriverVulkan::timestamp_query_pool_create(uint32_t p_query_count) {6602VkQueryPoolCreateInfo query_pool_create_info = {};6603query_pool_create_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;6604query_pool_create_info.queryType = VK_QUERY_TYPE_TIMESTAMP;6605query_pool_create_info.queryCount = p_query_count;66066607VkQueryPool vk_query_pool = VK_NULL_HANDLE;6608vkCreateQueryPool(vk_device, &query_pool_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_QUERY_POOL), &vk_query_pool);6609return RDD::QueryPoolID(vk_query_pool);6610}66116612void RenderingDeviceDriverVulkan::timestamp_query_pool_free(QueryPoolID p_pool_id) {6613vkDestroyQueryPool(vk_device, (VkQueryPool)p_pool_id.id, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_QUERY_POOL));6614}66156616void RenderingDeviceDriverVulkan::timestamp_query_pool_get_results(QueryPoolID p_pool_id, uint32_t p_query_count, uint64_t *r_results) {6617vkGetQueryPoolResults(vk_device, (VkQueryPool)p_pool_id.id, 0, p_query_count, sizeof(uint64_t) * p_query_count, r_results, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT);6618}66196620uint64_t RenderingDeviceDriverVulkan::timestamp_query_result_to_time(uint64_t p_result) {6621// This sucks because timestampPeriod multiplier is a float, while the timestamp is 64 bits nanosecs.6622// So, in cases like nvidia which give you enormous numbers and 1 as multiplier, multiplying is next to impossible.6623// Need to do 128 bits fixed point multiplication to get the right value.66246625auto mult64to128 = [](uint64_t u, uint64_t v, uint64_t &h, uint64_t &l) {6626uint64_t u1 = (u & 0xffffffff);6627uint64_t v1 = (v & 0xffffffff);6628uint64_t t = (u1 * v1);6629uint64_t w3 = (t & 0xffffffff);6630uint64_t k = (t >> 32);66316632u >>= 32;6633t = (u * v1) + k;6634k = (t & 0xffffffff);6635uint64_t w1 = (t >> 32);66366637v >>= 32;6638t = (u1 * v) + k;6639k = (t >> 32);66406641h = (u * v) + w1 + k;6642l = (t << 32) + w3;6643};66446645uint64_t shift_bits = 16;6646uint64_t h = 0, l = 0;6647mult64to128(p_result, uint64_t(double(physical_device_properties.limits.timestampPeriod) * double(1 << shift_bits)), h, l);6648l >>= shift_bits;6649l |= h << (64 - shift_bits);66506651return l;6652}66536654void RenderingDeviceDriverVulkan::command_timestamp_query_pool_reset(CommandBufferID p_cmd_buffer, QueryPoolID p_pool_id, uint32_t p_query_count) {6655const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;6656vkCmdResetQueryPool(command_buffer->vk_command_buffer, (VkQueryPool)p_pool_id.id, 0, p_query_count);6657}66586659void RenderingDeviceDriverVulkan::command_timestamp_write(CommandBufferID p_cmd_buffer, QueryPoolID p_pool_id, uint32_t p_index) {6660const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;6661vkCmdWriteTimestamp(command_buffer->vk_command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, (VkQueryPool)p_pool_id.id, p_index);6662}66636664/****************/6665/**** LABELS ****/6666/****************/66676668void RenderingDeviceDriverVulkan::command_begin_label(CommandBufferID p_cmd_buffer, const char *p_label_name, const Color &p_color) {6669const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;6670const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get();6671if (!functions.CmdBeginDebugUtilsLabelEXT) {6672if (functions.CmdDebugMarkerBeginEXT) {6673// Debug marker extensions.6674VkDebugMarkerMarkerInfoEXT marker;6675marker.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;6676marker.pNext = nullptr;6677marker.pMarkerName = p_label_name;6678marker.color[0] = p_color[0];6679marker.color[1] = p_color[1];6680marker.color[2] = p_color[2];6681marker.color[3] = p_color[3];6682functions.CmdDebugMarkerBeginEXT(command_buffer->vk_command_buffer, &marker);6683}6684return;6685}6686VkDebugUtilsLabelEXT label;6687label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;6688label.pNext = nullptr;6689label.pLabelName = p_label_name;6690label.color[0] = p_color[0];6691label.color[1] = p_color[1];6692label.color[2] = p_color[2];6693label.color[3] = p_color[3];6694functions.CmdBeginDebugUtilsLabelEXT(command_buffer->vk_command_buffer, &label);6695}66966697void RenderingDeviceDriverVulkan::command_end_label(CommandBufferID p_cmd_buffer) {6698const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;6699const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get();6700if (!functions.CmdEndDebugUtilsLabelEXT) {6701if (functions.CmdDebugMarkerEndEXT) {6702// Debug marker extensions.6703functions.CmdDebugMarkerEndEXT(command_buffer->vk_command_buffer);6704}6705return;6706}6707functions.CmdEndDebugUtilsLabelEXT(command_buffer->vk_command_buffer);6708}67096710/****************/6711/**** DEBUG *****/6712/****************/6713void RenderingDeviceDriverVulkan::command_insert_breadcrumb(CommandBufferID p_cmd_buffer, uint32_t p_data) {6714#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)6715if (p_data == BreadcrumbMarker::NONE) {6716return;6717}67186719const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;6720if (Engine::get_singleton()->is_accurate_breadcrumbs_enabled()) {6721// Force a full barrier so commands are not executed in parallel.6722// This will mean that the last breadcrumb to see was actually the6723// last (group of) command to be executed (hence, the one causing the crash).6724VkMemoryBarrier memoryBarrier;6725memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;6726memoryBarrier.pNext = nullptr;6727memoryBarrier.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT |6728VK_ACCESS_INDEX_READ_BIT |6729VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |6730VK_ACCESS_UNIFORM_READ_BIT |6731VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |6732VK_ACCESS_SHADER_READ_BIT |6733VK_ACCESS_SHADER_WRITE_BIT |6734VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |6735VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |6736VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |6737VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |6738VK_ACCESS_TRANSFER_READ_BIT |6739VK_ACCESS_TRANSFER_WRITE_BIT |6740VK_ACCESS_HOST_READ_BIT |6741VK_ACCESS_HOST_WRITE_BIT;6742memoryBarrier.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT |6743VK_ACCESS_INDEX_READ_BIT |6744VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |6745VK_ACCESS_UNIFORM_READ_BIT |6746VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |6747VK_ACCESS_SHADER_READ_BIT |6748VK_ACCESS_SHADER_WRITE_BIT |6749VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |6750VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |6751VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |6752VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |6753VK_ACCESS_TRANSFER_READ_BIT |6754VK_ACCESS_TRANSFER_WRITE_BIT |6755VK_ACCESS_HOST_READ_BIT |6756VK_ACCESS_HOST_WRITE_BIT;67576758vkCmdPipelineBarrier(6759command_buffer->vk_command_buffer,6760VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,6761VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,67620, 1u, &memoryBarrier, 0u, nullptr, 0u, nullptr);6763}67646765// We write to a circular buffer. If you're getting barrier sync errors here,6766// increase the value of BREADCRUMB_BUFFER_ENTRIES.6767vkCmdFillBuffer(command_buffer->vk_command_buffer, ((BufferInfo *)breadcrumb_buffer.id)->vk_buffer, breadcrumb_offset, sizeof(uint32_t), breadcrumb_id++);6768vkCmdFillBuffer(command_buffer->vk_command_buffer, ((BufferInfo *)breadcrumb_buffer.id)->vk_buffer, breadcrumb_offset + sizeof(uint32_t), sizeof(uint32_t), p_data);6769breadcrumb_offset += sizeof(uint32_t) * 2u;6770if (breadcrumb_offset >= BREADCRUMB_BUFFER_ENTRIES * sizeof(uint32_t) * 2u) {6771breadcrumb_offset = 0u;6772}6773#endif6774}67756776void RenderingDeviceDriverVulkan::on_device_lost() const {6777if (device_functions.GetDeviceFaultInfoEXT == nullptr) {6778_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "VK_EXT_device_fault not available.");6779return;6780}67816782VkDeviceFaultCountsEXT fault_counts = {};6783fault_counts.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT;6784VkResult vkres = device_functions.GetDeviceFaultInfoEXT(vk_device, &fault_counts, nullptr);67856786if (vkres != VK_SUCCESS) {6787_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "vkGetDeviceFaultInfoEXT returned " + itos(vkres) + " when getting fault count, skipping VK_EXT_device_fault report...");6788return;6789}67906791String err_msg;6792VkDeviceFaultInfoEXT fault_info = {};6793fault_info.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT;6794fault_info.pVendorInfos = fault_counts.vendorInfoCount6795? (VkDeviceFaultVendorInfoEXT *)memalloc(fault_counts.vendorInfoCount * sizeof(VkDeviceFaultVendorInfoEXT))6796: nullptr;6797fault_info.pAddressInfos =6798fault_counts.addressInfoCount6799? (VkDeviceFaultAddressInfoEXT *)memalloc(fault_counts.addressInfoCount * sizeof(VkDeviceFaultAddressInfoEXT))6800: nullptr;6801fault_counts.vendorBinarySize = 0;6802vkres = device_functions.GetDeviceFaultInfoEXT(vk_device, &fault_counts, &fault_info);6803if (vkres != VK_SUCCESS) {6804_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "vkGetDeviceFaultInfoEXT returned " + itos(vkres) + " when getting fault info, skipping VK_EXT_device_fault report...");6805} else {6806err_msg += "** Report from VK_EXT_device_fault **";6807err_msg += "\nDescription: " + String(fault_info.description);6808err_msg += "\nVendor infos:";6809for (uint32_t vd = 0; vd < fault_counts.vendorInfoCount; ++vd) {6810const VkDeviceFaultVendorInfoEXT *vendor_info = &fault_info.pVendorInfos[vd];6811err_msg += "\nInfo " + itos(vd);6812err_msg += "\n Description: " + String(vendor_info->description);6813err_msg += "\n Fault code : " + itos(vendor_info->vendorFaultCode);6814err_msg += "\n Fault data : " + itos(vendor_info->vendorFaultData);6815}68166817static constexpr const char *addressTypeNames[] = {6818"NONE",6819"READ_INVALID",6820"WRITE_INVALID",6821"EXECUTE_INVALID",6822"INSTRUCTION_POINTER_UNKNOWN",6823"INSTRUCTION_POINTER_INVALID",6824"INSTRUCTION_POINTER_FAULT",6825};6826err_msg += "\nAddresses info:";6827for (uint32_t ad = 0; ad < fault_counts.addressInfoCount; ++ad) {6828const VkDeviceFaultAddressInfoEXT *addr_info = &fault_info.pAddressInfos[ad];6829// From https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkDeviceFaultAddressInfoEXT.html6830const VkDeviceAddress lower = (addr_info->reportedAddress & ~(addr_info->addressPrecision - 1));6831const VkDeviceAddress upper = (addr_info->reportedAddress | (addr_info->addressPrecision - 1));6832err_msg += "\nInfo " + itos(ad);6833err_msg += "\n Type : " + String(addressTypeNames[addr_info->addressType]);6834err_msg += "\n Reported address: " + itos(addr_info->reportedAddress);6835err_msg += "\n Lower address : " + itos(lower);6836err_msg += "\n Upper address : " + itos(upper);6837err_msg += "\n Precision : " + itos(addr_info->addressPrecision);6838}6839}68406841_err_print_error(FUNCTION_STR, __FILE__, __LINE__, err_msg);68426843if (fault_info.pVendorInfos) {6844memfree(fault_info.pVendorInfos);6845}6846if (fault_info.pAddressInfos) {6847memfree(fault_info.pAddressInfos);6848}68496850_err_print_error(FUNCTION_STR, __FILE__, __LINE__, context_driver->get_driver_and_device_memory_report());6851}68526853void RenderingDeviceDriverVulkan::print_lost_device_info() {6854#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)6855{6856String error_msg = "Printing last known breadcrumbs in reverse order (last executed first).";6857if (!Engine::get_singleton()->is_accurate_breadcrumbs_enabled()) {6858error_msg += "\nSome of them might be inaccurate. Try running with --accurate-breadcrumbs for precise information.";6859}6860_err_print_error(FUNCTION_STR, __FILE__, __LINE__, error_msg);6861}68626863uint8_t *breadcrumb_ptr = nullptr;6864VkResult map_result = VK_SUCCESS;68656866vmaFlushAllocation(allocator, ((BufferInfo *)breadcrumb_buffer.id)->allocation.handle, 0, BREADCRUMB_BUFFER_ENTRIES * sizeof(uint32_t) * 2u);6867vmaInvalidateAllocation(allocator, ((BufferInfo *)breadcrumb_buffer.id)->allocation.handle, 0, BREADCRUMB_BUFFER_ENTRIES * sizeof(uint32_t) * 2u);6868{6869void *ptr = nullptr;6870map_result = vmaMapMemory(allocator, ((BufferInfo *)breadcrumb_buffer.id)->allocation.handle, &ptr);6871breadcrumb_ptr = reinterpret_cast<uint8_t *>(ptr);6872}68736874if (breadcrumb_ptr && map_result == VK_SUCCESS) {6875uint32_t last_breadcrumb_offset = 0;6876{6877_err_print_error_asap("Searching last breadcrumb. We've sent up to ID: " + itos(breadcrumb_id - 1u));68786879// Scan the whole buffer to find the offset with the highest ID.6880// That means that was the last one to be written.6881//6882// We use "breadcrumb_id - id" to account for wraparound.6883// e.g. breadcrumb_id = 2 and id = 4294967294; then 2 - 4294967294 = 4.6884// The one with the smallest difference is the closest to breadcrumb_id, which means it's6885// the last written command.6886uint32_t biggest_id = 0u;6887uint32_t smallest_id_diff = std::numeric_limits<uint32_t>::max();6888const uint32_t *breadcrumb_ptr32 = reinterpret_cast<const uint32_t *>(breadcrumb_ptr);6889for (size_t i = 0u; i < BREADCRUMB_BUFFER_ENTRIES; ++i) {6890const uint32_t id = breadcrumb_ptr32[i * 2u];6891const uint32_t id_diff = breadcrumb_id - id;6892if (id_diff < smallest_id_diff) {6893biggest_id = i;6894smallest_id_diff = id_diff;6895}6896}68976898_err_print_error_asap("Last breadcrumb ID found: " + itos(breadcrumb_ptr32[biggest_id * 2u]));68996900last_breadcrumb_offset = biggest_id * sizeof(uint32_t) * 2u;6901}69026903const size_t entries_to_print = 8u; // Note: The value is arbitrary.6904for (size_t i = 0u; i < entries_to_print; ++i) {6905const uint32_t last_breadcrumb = *reinterpret_cast<uint32_t *>(breadcrumb_ptr + last_breadcrumb_offset + sizeof(uint32_t));6906const uint32_t phase = last_breadcrumb & uint32_t(~((1 << 16) - 1));6907const uint32_t user_data = last_breadcrumb & ((1 << 16) - 1);6908String error_msg = "Last known breadcrumb: ";69096910switch (phase) {6911case BreadcrumbMarker::ALPHA_PASS:6912error_msg += "ALPHA_PASS";6913break;6914case BreadcrumbMarker::BLIT_PASS:6915error_msg += "BLIT_PASS";6916break;6917case BreadcrumbMarker::DEBUG_PASS:6918error_msg += "DEBUG_PASS";6919break;6920case BreadcrumbMarker::LIGHTMAPPER_PASS:6921error_msg += "LIGHTMAPPER_PASS";6922break;6923case BreadcrumbMarker::OPAQUE_PASS:6924error_msg += "OPAQUE_PASS";6925break;6926case BreadcrumbMarker::POST_PROCESSING_PASS:6927error_msg += "POST_PROCESSING_PASS";6928break;6929case BreadcrumbMarker::REFLECTION_PROBES:6930error_msg += "REFLECTION_PROBES";6931break;6932case BreadcrumbMarker::SHADOW_PASS_CUBE:6933error_msg += "SHADOW_PASS_CUBE";6934break;6935case BreadcrumbMarker::SHADOW_PASS_DIRECTIONAL:6936error_msg += "SHADOW_PASS_DIRECTIONAL";6937break;6938case BreadcrumbMarker::SKY_PASS:6939error_msg += "SKY_PASS";6940break;6941case BreadcrumbMarker::TRANSPARENT_PASS:6942error_msg += "TRANSPARENT_PASS";6943break;6944case BreadcrumbMarker::UI_PASS:6945error_msg += "UI_PASS";6946break;6947default:6948error_msg += "UNKNOWN_BREADCRUMB(" + itos((uint32_t)phase) + ')';6949break;6950}69516952if (user_data != 0) {6953error_msg += " | User data: " + itos(user_data);6954}69556956_err_print_error_asap(error_msg);69576958if (last_breadcrumb_offset == 0u) {6959// Decrement last_breadcrumb_idx, wrapping underflow.6960last_breadcrumb_offset = BREADCRUMB_BUFFER_ENTRIES * sizeof(uint32_t) * 2u;6961}6962last_breadcrumb_offset -= sizeof(uint32_t) * 2u;6963}69646965vmaUnmapMemory(allocator, ((BufferInfo *)breadcrumb_buffer.id)->allocation.handle);6966breadcrumb_ptr = nullptr;6967} else {6968_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Couldn't map breadcrumb buffer. VkResult = " + itos(map_result));6969}6970#endif6971on_device_lost();6972}69736974inline String RenderingDeviceDriverVulkan::get_vulkan_result(VkResult err) {6975#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)6976if (err == VK_ERROR_OUT_OF_HOST_MEMORY) {6977return "VK_ERROR_OUT_OF_HOST_MEMORY";6978} else if (err == VK_ERROR_OUT_OF_DEVICE_MEMORY) {6979return "VK_ERROR_OUT_OF_DEVICE_MEMORY";6980} else if (err == VK_ERROR_DEVICE_LOST) {6981return "VK_ERROR_DEVICE_LOST";6982} else if (err == VK_ERROR_SURFACE_LOST_KHR) {6983return "VK_ERROR_SURFACE_LOST_KHR";6984} else if (err == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT) {6985return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT";6986}6987#endif6988return itos(err);6989}69906991/********************/6992/**** SUBMISSION ****/6993/********************/69946995void RenderingDeviceDriverVulkan::begin_segment(uint32_t p_frame_index, uint32_t p_frames_drawn) {6996// Per-frame segments are not required in Vulkan.6997}69986999void RenderingDeviceDriverVulkan::end_segment() {7000// Per-frame segments are not required in Vulkan.7001}70027003/**************/7004/**** MISC ****/7005/**************/70067007void RenderingDeviceDriverVulkan::set_object_name(ObjectType p_type, ID p_driver_id, const String &p_name) {7008switch (p_type) {7009case OBJECT_TYPE_TEXTURE: {7010const TextureInfo *tex_info = (const TextureInfo *)p_driver_id.id;7011if (tex_info->allocation.handle) {7012_set_object_name(VK_OBJECT_TYPE_IMAGE, (uint64_t)tex_info->vk_view_create_info.image, p_name);7013}7014_set_object_name(VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)tex_info->vk_view, p_name + " View");7015} break;7016case OBJECT_TYPE_SAMPLER: {7017_set_object_name(VK_OBJECT_TYPE_SAMPLER, p_driver_id.id, p_name);7018} break;7019case OBJECT_TYPE_BUFFER: {7020const BufferInfo *buf_info = (const BufferInfo *)p_driver_id.id;7021_set_object_name(VK_OBJECT_TYPE_BUFFER, (uint64_t)buf_info->vk_buffer, p_name);7022if (buf_info->vk_view) {7023_set_object_name(VK_OBJECT_TYPE_BUFFER_VIEW, (uint64_t)buf_info->vk_view, p_name + " View");7024}7025} break;7026case OBJECT_TYPE_SHADER: {7027const ShaderInfo *shader_info = (const ShaderInfo *)p_driver_id.id;7028for (uint32_t i = 0; i < shader_info->vk_descriptor_set_layouts.size(); i++) {7029_set_object_name(VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)shader_info->vk_descriptor_set_layouts[i], p_name);7030}7031_set_object_name(VK_OBJECT_TYPE_PIPELINE_LAYOUT, (uint64_t)shader_info->vk_pipeline_layout, p_name + " Pipeline Layout");7032} break;7033case OBJECT_TYPE_UNIFORM_SET: {7034const UniformSetInfo *usi = (const UniformSetInfo *)p_driver_id.id;7035_set_object_name(VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)usi->vk_descriptor_set, p_name);7036} break;7037case OBJECT_TYPE_PIPELINE: {7038_set_object_name(VK_OBJECT_TYPE_PIPELINE, (uint64_t)p_driver_id.id, p_name);7039} break;7040case OBJECT_TYPE_ACCELERATION_STRUCTURE: {7041const AccelerationStructureInfo *asi = (const AccelerationStructureInfo *)p_driver_id.id;7042_set_object_name(VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR, (uint64_t)asi->vk_acceleration_structure, p_name);7043} break;7044case OBJECT_TYPE_RAYTRACING_PIPELINE: {7045const RaytracingPipelineInfo *rpi = (const RaytracingPipelineInfo *)p_driver_id.id;7046_set_object_name(VK_OBJECT_TYPE_PIPELINE, (uint64_t)rpi->vk_pipeline, p_name);7047} break;7048default: {7049DEV_ASSERT(false);7050}7051}7052}70537054uint64_t RenderingDeviceDriverVulkan::get_resource_native_handle(DriverResource p_type, ID p_driver_id) {7055switch (p_type) {7056case DRIVER_RESOURCE_LOGICAL_DEVICE: {7057return (uint64_t)vk_device;7058}7059case DRIVER_RESOURCE_PHYSICAL_DEVICE: {7060return (uint64_t)physical_device;7061}7062case DRIVER_RESOURCE_TOPMOST_OBJECT: {7063return (uint64_t)context_driver->instance_get();7064}7065case DRIVER_RESOURCE_COMMAND_QUEUE: {7066const CommandQueue *queue_info = (const CommandQueue *)p_driver_id.id;7067return (uint64_t)queue_families[queue_info->queue_family][queue_info->queue_index].queue;7068}7069case DRIVER_RESOURCE_QUEUE_FAMILY: {7070return uint32_t(p_driver_id.id) - 1;7071}7072case DRIVER_RESOURCE_TEXTURE: {7073const TextureInfo *tex_info = (const TextureInfo *)p_driver_id.id;7074return (uint64_t)tex_info->vk_view_create_info.image;7075}7076case DRIVER_RESOURCE_TEXTURE_VIEW: {7077const TextureInfo *tex_info = (const TextureInfo *)p_driver_id.id;7078return (uint64_t)tex_info->vk_view;7079}7080case DRIVER_RESOURCE_TEXTURE_DATA_FORMAT: {7081const TextureInfo *tex_info = (const TextureInfo *)p_driver_id.id;7082return (uint64_t)tex_info->vk_view_create_info.format;7083}7084case DRIVER_RESOURCE_SAMPLER:7085case DRIVER_RESOURCE_UNIFORM_SET:7086case DRIVER_RESOURCE_BUFFER:7087case DRIVER_RESOURCE_COMPUTE_PIPELINE:7088case DRIVER_RESOURCE_RENDER_PIPELINE: {7089return p_driver_id.id;7090}7091default: {7092return 0;7093}7094}7095}70967097uint64_t RenderingDeviceDriverVulkan::get_total_memory_used() {7098VmaTotalStatistics stats = {};7099vmaCalculateStatistics(allocator, &stats);7100return stats.total.statistics.allocationBytes;7101}71027103uint64_t RenderingDeviceDriverVulkan::get_lazily_memory_used() {7104return vmaCalculateLazilyAllocatedBytes(allocator);7105}71067107uint64_t RenderingDeviceDriverVulkan::limit_get(Limit p_limit) {7108const VkPhysicalDeviceLimits &limits = physical_device_properties.limits;7109uint64_t safe_unbounded = ((uint64_t)1 << 30);7110switch (p_limit) {7111case LIMIT_MAX_BOUND_UNIFORM_SETS:7112return limits.maxBoundDescriptorSets;7113case LIMIT_MAX_FRAMEBUFFER_COLOR_ATTACHMENTS:7114return limits.maxColorAttachments;7115case LIMIT_MAX_TEXTURES_PER_UNIFORM_SET:7116return limits.maxDescriptorSetSampledImages;7117case LIMIT_MAX_SAMPLERS_PER_UNIFORM_SET:7118return limits.maxDescriptorSetSamplers;7119case LIMIT_MAX_STORAGE_BUFFERS_PER_UNIFORM_SET:7120return limits.maxDescriptorSetStorageBuffers;7121case LIMIT_MAX_STORAGE_IMAGES_PER_UNIFORM_SET:7122return limits.maxDescriptorSetStorageImages;7123case LIMIT_MAX_UNIFORM_BUFFERS_PER_UNIFORM_SET:7124return limits.maxDescriptorSetUniformBuffers;7125case LIMIT_MAX_DRAW_INDEXED_INDEX:7126return limits.maxDrawIndexedIndexValue;7127case LIMIT_MAX_FRAMEBUFFER_HEIGHT:7128return limits.maxFramebufferHeight;7129case LIMIT_MAX_FRAMEBUFFER_WIDTH:7130return limits.maxFramebufferWidth;7131case LIMIT_MAX_TEXTURE_ARRAY_LAYERS:7132return limits.maxImageArrayLayers;7133case LIMIT_MAX_TEXTURE_SIZE_1D:7134return limits.maxImageDimension1D;7135case LIMIT_MAX_TEXTURE_SIZE_2D:7136return limits.maxImageDimension2D;7137case LIMIT_MAX_TEXTURE_SIZE_3D:7138return limits.maxImageDimension3D;7139case LIMIT_MAX_TEXTURE_SIZE_CUBE:7140return limits.maxImageDimensionCube;7141case LIMIT_MAX_TEXTURES_PER_SHADER_STAGE:7142return limits.maxPerStageDescriptorSampledImages;7143case LIMIT_MAX_SAMPLERS_PER_SHADER_STAGE:7144return limits.maxPerStageDescriptorSamplers;7145case LIMIT_MAX_STORAGE_BUFFERS_PER_SHADER_STAGE:7146return limits.maxPerStageDescriptorStorageBuffers;7147case LIMIT_MAX_STORAGE_IMAGES_PER_SHADER_STAGE:7148return limits.maxPerStageDescriptorStorageImages;7149case LIMIT_MAX_UNIFORM_BUFFERS_PER_SHADER_STAGE:7150return limits.maxPerStageDescriptorUniformBuffers;7151case LIMIT_MAX_PUSH_CONSTANT_SIZE:7152return limits.maxPushConstantsSize;7153case LIMIT_MAX_UNIFORM_BUFFER_SIZE:7154return limits.maxUniformBufferRange;7155case LIMIT_MAX_VERTEX_INPUT_ATTRIBUTE_OFFSET:7156return limits.maxVertexInputAttributeOffset;7157case LIMIT_MAX_VERTEX_INPUT_ATTRIBUTES:7158return limits.maxVertexInputAttributes;7159case LIMIT_MAX_VERTEX_INPUT_BINDINGS:7160return limits.maxVertexInputBindings;7161case LIMIT_MAX_VERTEX_INPUT_BINDING_STRIDE:7162return limits.maxVertexInputBindingStride;7163case LIMIT_MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT:7164return limits.minUniformBufferOffsetAlignment;7165case LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X:7166return limits.maxComputeWorkGroupCount[0];7167case LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Y:7168return limits.maxComputeWorkGroupCount[1];7169case LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Z:7170return limits.maxComputeWorkGroupCount[2];7171case LIMIT_MAX_COMPUTE_WORKGROUP_INVOCATIONS:7172return limits.maxComputeWorkGroupInvocations;7173case LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_X:7174return limits.maxComputeWorkGroupSize[0];7175case LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Y:7176return limits.maxComputeWorkGroupSize[1];7177case LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z:7178return limits.maxComputeWorkGroupSize[2];7179case LIMIT_MAX_COMPUTE_SHARED_MEMORY_SIZE:7180return limits.maxComputeSharedMemorySize;7181case LIMIT_MAX_VIEWPORT_DIMENSIONS_X:7182return limits.maxViewportDimensions[0];7183case LIMIT_MAX_VIEWPORT_DIMENSIONS_Y:7184return limits.maxViewportDimensions[1];7185case LIMIT_SUBGROUP_SIZE:7186return subgroup_capabilities.size;7187case LIMIT_SUBGROUP_MIN_SIZE:7188return subgroup_capabilities.min_size;7189case LIMIT_SUBGROUP_MAX_SIZE:7190return subgroup_capabilities.max_size;7191case LIMIT_SUBGROUP_IN_SHADERS:7192return subgroup_capabilities.supported_stages_flags_rd();7193case LIMIT_SUBGROUP_OPERATIONS:7194return subgroup_capabilities.supported_operations_flags_rd();7195case LIMIT_MAX_SHADER_VARYINGS:7196// The Vulkan spec states that built in varyings like gl_FragCoord should count against this, but in7197// practice, that doesn't seem to be the case. The validation layers don't even complain.7198return MIN(limits.maxVertexOutputComponents / 4, limits.maxFragmentInputComponents / 4);7199default: {7200#ifdef DEV_ENABLED7201WARN_PRINT("Returning maximum value for unknown limit " + itos(p_limit) + ".");7202#endif7203return safe_unbounded;7204}7205}7206}72077208uint64_t RenderingDeviceDriverVulkan::api_trait_get(ApiTrait p_trait) {7209switch (p_trait) {7210case API_TRAIT_TEXTURE_TRANSFER_ALIGNMENT:7211return (uint64_t)MAX((uint64_t)16, physical_device_properties.limits.optimalBufferCopyOffsetAlignment);7212case API_TRAIT_SHADER_CHANGE_INVALIDATION:7213return (uint64_t)SHADER_CHANGE_INVALIDATION_INCOMPATIBLE_SETS_PLUS_CASCADE;7214default:7215return RenderingDeviceDriver::api_trait_get(p_trait);7216}7217}72187219bool RenderingDeviceDriverVulkan::has_feature(Features p_feature) {7220switch (p_feature) {7221case SUPPORTS_HALF_FLOAT:7222return shader_capabilities.shader_float16_is_supported && physical_device_features.shaderInt16 && storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported;7223case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:7224return true;7225case SUPPORTS_BUFFER_DEVICE_ADDRESS:7226return buffer_device_address_support;7227case SUPPORTS_IMAGE_ATOMIC_32_BIT:7228#if (defined(MACOS_ENABLED) || defined(APPLE_EMBEDDED_ENABLED))7229// MoltenVK has previously had issues with 32-bit atomics on images.7230return false;7231#else7232return true;7233#endif7234case SUPPORTS_VULKAN_MEMORY_MODEL:7235return vulkan_memory_model_support && vulkan_memory_model_device_scope_support;7236case SUPPORTS_FRAMEBUFFER_DEPTH_RESOLVE:7237return framebuffer_depth_resolve;7238case SUPPORTS_POINT_SIZE:7239return true;7240case SUPPORTS_RAY_QUERY:7241return acceleration_structure_capabilities.acceleration_structure_support && ray_query_support;7242case SUPPORTS_RAYTRACING_PIPELINE:7243return acceleration_structure_capabilities.acceleration_structure_support && raytracing_capabilities.raytracing_pipeline_support;7244default:7245return false;7246}7247}72487249const RDD::MultiviewCapabilities &RenderingDeviceDriverVulkan::get_multiview_capabilities() {7250return multiview_capabilities;7251}72527253const RDD::FragmentShadingRateCapabilities &RenderingDeviceDriverVulkan::get_fragment_shading_rate_capabilities() {7254return fsr_capabilities;7255}72567257const RDD::FragmentDensityMapCapabilities &RenderingDeviceDriverVulkan::get_fragment_density_map_capabilities() {7258return fdm_capabilities;7259}72607261String RenderingDeviceDriverVulkan::get_api_name() const {7262return "Vulkan";7263}72647265String RenderingDeviceDriverVulkan::get_api_version() const {7266uint32_t api_version = physical_device_properties.apiVersion;7267return vformat("%d.%d.%d", VK_API_VERSION_MAJOR(api_version), VK_API_VERSION_MINOR(api_version), VK_API_VERSION_PATCH(api_version));7268}72697270String RenderingDeviceDriverVulkan::get_pipeline_cache_uuid() const {7271return pipeline_cache_id;7272}72737274const RDD::Capabilities &RenderingDeviceDriverVulkan::get_capabilities() const {7275return device_capabilities;7276}72777278const RenderingShaderContainerFormat &RenderingDeviceDriverVulkan::get_shader_container_format() const {7279return shader_container_format;7280}72817282bool RenderingDeviceDriverVulkan::is_composite_alpha_supported(CommandQueueID p_queue) const {7283if (has_comp_alpha.has((uint64_t)p_queue.id)) {7284return has_comp_alpha[(uint64_t)p_queue.id];7285}7286return false;7287}72887289/******************/72907291RenderingDeviceDriverVulkan::RenderingDeviceDriverVulkan(RenderingContextDriverVulkan *p_context_driver) {7292DEV_ASSERT(p_context_driver != nullptr);72937294context_driver = p_context_driver;7295max_descriptor_sets_per_pool = GLOBAL_GET("rendering/rendering_device/vulkan/max_descriptors_per_pool");7296}72977298RenderingDeviceDriverVulkan::~RenderingDeviceDriverVulkan() {7299#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)7300if (breadcrumb_buffer != BufferID()) {7301buffer_free(breadcrumb_buffer);7302}7303#endif73047305while (small_allocs_pools.size()) {7306HashMap<uint32_t, VmaPool>::Iterator E = small_allocs_pools.begin();7307vmaDestroyPool(allocator, E->value);7308small_allocs_pools.remove(E);7309}7310vmaDestroyAllocator(allocator);73117312// Destroy linearly allocated descriptor pools.7313for (KeyValue<int, DescriptorSetPools> &pool_map : linear_descriptor_set_pools) {7314for (KeyValue<DescriptorSetPoolKey, HashMap<VkDescriptorPool, uint32_t>> pools : pool_map.value) {7315for (KeyValue<VkDescriptorPool, uint32_t> descriptor_pool : pools.value) {7316vkDestroyDescriptorPool(vk_device, descriptor_pool.key, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DESCRIPTOR_POOL));7317}7318}7319}73207321if (vk_device != VK_NULL_HANDLE) {7322vkDestroyDevice(vk_device, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DEVICE));7323}7324}732573267327