Path: blob/master/drivers/vulkan/rendering_device_driver_vulkan.cpp
9903 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#define PRINT_NATIVE_COMMANDS 05152/*****************/53/**** GENERIC ****/54/*****************/5556#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)57static const uint32_t BREADCRUMB_BUFFER_ENTRIES = 512u;58#endif5960static const VkFormat RD_TO_VK_FORMAT[RDD::DATA_FORMAT_MAX] = {61VK_FORMAT_R4G4_UNORM_PACK8,62VK_FORMAT_R4G4B4A4_UNORM_PACK16,63VK_FORMAT_B4G4R4A4_UNORM_PACK16,64VK_FORMAT_R5G6B5_UNORM_PACK16,65VK_FORMAT_B5G6R5_UNORM_PACK16,66VK_FORMAT_R5G5B5A1_UNORM_PACK16,67VK_FORMAT_B5G5R5A1_UNORM_PACK16,68VK_FORMAT_A1R5G5B5_UNORM_PACK16,69VK_FORMAT_R8_UNORM,70VK_FORMAT_R8_SNORM,71VK_FORMAT_R8_USCALED,72VK_FORMAT_R8_SSCALED,73VK_FORMAT_R8_UINT,74VK_FORMAT_R8_SINT,75VK_FORMAT_R8_SRGB,76VK_FORMAT_R8G8_UNORM,77VK_FORMAT_R8G8_SNORM,78VK_FORMAT_R8G8_USCALED,79VK_FORMAT_R8G8_SSCALED,80VK_FORMAT_R8G8_UINT,81VK_FORMAT_R8G8_SINT,82VK_FORMAT_R8G8_SRGB,83VK_FORMAT_R8G8B8_UNORM,84VK_FORMAT_R8G8B8_SNORM,85VK_FORMAT_R8G8B8_USCALED,86VK_FORMAT_R8G8B8_SSCALED,87VK_FORMAT_R8G8B8_UINT,88VK_FORMAT_R8G8B8_SINT,89VK_FORMAT_R8G8B8_SRGB,90VK_FORMAT_B8G8R8_UNORM,91VK_FORMAT_B8G8R8_SNORM,92VK_FORMAT_B8G8R8_USCALED,93VK_FORMAT_B8G8R8_SSCALED,94VK_FORMAT_B8G8R8_UINT,95VK_FORMAT_B8G8R8_SINT,96VK_FORMAT_B8G8R8_SRGB,97VK_FORMAT_R8G8B8A8_UNORM,98VK_FORMAT_R8G8B8A8_SNORM,99VK_FORMAT_R8G8B8A8_USCALED,100VK_FORMAT_R8G8B8A8_SSCALED,101VK_FORMAT_R8G8B8A8_UINT,102VK_FORMAT_R8G8B8A8_SINT,103VK_FORMAT_R8G8B8A8_SRGB,104VK_FORMAT_B8G8R8A8_UNORM,105VK_FORMAT_B8G8R8A8_SNORM,106VK_FORMAT_B8G8R8A8_USCALED,107VK_FORMAT_B8G8R8A8_SSCALED,108VK_FORMAT_B8G8R8A8_UINT,109VK_FORMAT_B8G8R8A8_SINT,110VK_FORMAT_B8G8R8A8_SRGB,111VK_FORMAT_A8B8G8R8_UNORM_PACK32,112VK_FORMAT_A8B8G8R8_SNORM_PACK32,113VK_FORMAT_A8B8G8R8_USCALED_PACK32,114VK_FORMAT_A8B8G8R8_SSCALED_PACK32,115VK_FORMAT_A8B8G8R8_UINT_PACK32,116VK_FORMAT_A8B8G8R8_SINT_PACK32,117VK_FORMAT_A8B8G8R8_SRGB_PACK32,118VK_FORMAT_A2R10G10B10_UNORM_PACK32,119VK_FORMAT_A2R10G10B10_SNORM_PACK32,120VK_FORMAT_A2R10G10B10_USCALED_PACK32,121VK_FORMAT_A2R10G10B10_SSCALED_PACK32,122VK_FORMAT_A2R10G10B10_UINT_PACK32,123VK_FORMAT_A2R10G10B10_SINT_PACK32,124VK_FORMAT_A2B10G10R10_UNORM_PACK32,125VK_FORMAT_A2B10G10R10_SNORM_PACK32,126VK_FORMAT_A2B10G10R10_USCALED_PACK32,127VK_FORMAT_A2B10G10R10_SSCALED_PACK32,128VK_FORMAT_A2B10G10R10_UINT_PACK32,129VK_FORMAT_A2B10G10R10_SINT_PACK32,130VK_FORMAT_R16_UNORM,131VK_FORMAT_R16_SNORM,132VK_FORMAT_R16_USCALED,133VK_FORMAT_R16_SSCALED,134VK_FORMAT_R16_UINT,135VK_FORMAT_R16_SINT,136VK_FORMAT_R16_SFLOAT,137VK_FORMAT_R16G16_UNORM,138VK_FORMAT_R16G16_SNORM,139VK_FORMAT_R16G16_USCALED,140VK_FORMAT_R16G16_SSCALED,141VK_FORMAT_R16G16_UINT,142VK_FORMAT_R16G16_SINT,143VK_FORMAT_R16G16_SFLOAT,144VK_FORMAT_R16G16B16_UNORM,145VK_FORMAT_R16G16B16_SNORM,146VK_FORMAT_R16G16B16_USCALED,147VK_FORMAT_R16G16B16_SSCALED,148VK_FORMAT_R16G16B16_UINT,149VK_FORMAT_R16G16B16_SINT,150VK_FORMAT_R16G16B16_SFLOAT,151VK_FORMAT_R16G16B16A16_UNORM,152VK_FORMAT_R16G16B16A16_SNORM,153VK_FORMAT_R16G16B16A16_USCALED,154VK_FORMAT_R16G16B16A16_SSCALED,155VK_FORMAT_R16G16B16A16_UINT,156VK_FORMAT_R16G16B16A16_SINT,157VK_FORMAT_R16G16B16A16_SFLOAT,158VK_FORMAT_R32_UINT,159VK_FORMAT_R32_SINT,160VK_FORMAT_R32_SFLOAT,161VK_FORMAT_R32G32_UINT,162VK_FORMAT_R32G32_SINT,163VK_FORMAT_R32G32_SFLOAT,164VK_FORMAT_R32G32B32_UINT,165VK_FORMAT_R32G32B32_SINT,166VK_FORMAT_R32G32B32_SFLOAT,167VK_FORMAT_R32G32B32A32_UINT,168VK_FORMAT_R32G32B32A32_SINT,169VK_FORMAT_R32G32B32A32_SFLOAT,170VK_FORMAT_R64_UINT,171VK_FORMAT_R64_SINT,172VK_FORMAT_R64_SFLOAT,173VK_FORMAT_R64G64_UINT,174VK_FORMAT_R64G64_SINT,175VK_FORMAT_R64G64_SFLOAT,176VK_FORMAT_R64G64B64_UINT,177VK_FORMAT_R64G64B64_SINT,178VK_FORMAT_R64G64B64_SFLOAT,179VK_FORMAT_R64G64B64A64_UINT,180VK_FORMAT_R64G64B64A64_SINT,181VK_FORMAT_R64G64B64A64_SFLOAT,182VK_FORMAT_B10G11R11_UFLOAT_PACK32,183VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,184VK_FORMAT_D16_UNORM,185VK_FORMAT_X8_D24_UNORM_PACK32,186VK_FORMAT_D32_SFLOAT,187VK_FORMAT_S8_UINT,188VK_FORMAT_D16_UNORM_S8_UINT,189VK_FORMAT_D24_UNORM_S8_UINT,190VK_FORMAT_D32_SFLOAT_S8_UINT,191VK_FORMAT_BC1_RGB_UNORM_BLOCK,192VK_FORMAT_BC1_RGB_SRGB_BLOCK,193VK_FORMAT_BC1_RGBA_UNORM_BLOCK,194VK_FORMAT_BC1_RGBA_SRGB_BLOCK,195VK_FORMAT_BC2_UNORM_BLOCK,196VK_FORMAT_BC2_SRGB_BLOCK,197VK_FORMAT_BC3_UNORM_BLOCK,198VK_FORMAT_BC3_SRGB_BLOCK,199VK_FORMAT_BC4_UNORM_BLOCK,200VK_FORMAT_BC4_SNORM_BLOCK,201VK_FORMAT_BC5_UNORM_BLOCK,202VK_FORMAT_BC5_SNORM_BLOCK,203VK_FORMAT_BC6H_UFLOAT_BLOCK,204VK_FORMAT_BC6H_SFLOAT_BLOCK,205VK_FORMAT_BC7_UNORM_BLOCK,206VK_FORMAT_BC7_SRGB_BLOCK,207VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,208VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,209VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,210VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,211VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,212VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,213VK_FORMAT_EAC_R11_UNORM_BLOCK,214VK_FORMAT_EAC_R11_SNORM_BLOCK,215VK_FORMAT_EAC_R11G11_UNORM_BLOCK,216VK_FORMAT_EAC_R11G11_SNORM_BLOCK,217VK_FORMAT_ASTC_4x4_UNORM_BLOCK,218VK_FORMAT_ASTC_4x4_SRGB_BLOCK,219VK_FORMAT_ASTC_5x4_UNORM_BLOCK,220VK_FORMAT_ASTC_5x4_SRGB_BLOCK,221VK_FORMAT_ASTC_5x5_UNORM_BLOCK,222VK_FORMAT_ASTC_5x5_SRGB_BLOCK,223VK_FORMAT_ASTC_6x5_UNORM_BLOCK,224VK_FORMAT_ASTC_6x5_SRGB_BLOCK,225VK_FORMAT_ASTC_6x6_UNORM_BLOCK,226VK_FORMAT_ASTC_6x6_SRGB_BLOCK,227VK_FORMAT_ASTC_8x5_UNORM_BLOCK,228VK_FORMAT_ASTC_8x5_SRGB_BLOCK,229VK_FORMAT_ASTC_8x6_UNORM_BLOCK,230VK_FORMAT_ASTC_8x6_SRGB_BLOCK,231VK_FORMAT_ASTC_8x8_UNORM_BLOCK,232VK_FORMAT_ASTC_8x8_SRGB_BLOCK,233VK_FORMAT_ASTC_10x5_UNORM_BLOCK,234VK_FORMAT_ASTC_10x5_SRGB_BLOCK,235VK_FORMAT_ASTC_10x6_UNORM_BLOCK,236VK_FORMAT_ASTC_10x6_SRGB_BLOCK,237VK_FORMAT_ASTC_10x8_UNORM_BLOCK,238VK_FORMAT_ASTC_10x8_SRGB_BLOCK,239VK_FORMAT_ASTC_10x10_UNORM_BLOCK,240VK_FORMAT_ASTC_10x10_SRGB_BLOCK,241VK_FORMAT_ASTC_12x10_UNORM_BLOCK,242VK_FORMAT_ASTC_12x10_SRGB_BLOCK,243VK_FORMAT_ASTC_12x12_UNORM_BLOCK,244VK_FORMAT_ASTC_12x12_SRGB_BLOCK,245VK_FORMAT_G8B8G8R8_422_UNORM,246VK_FORMAT_B8G8R8G8_422_UNORM,247VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,248VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,249VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,250VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,251VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,252VK_FORMAT_R10X6_UNORM_PACK16,253VK_FORMAT_R10X6G10X6_UNORM_2PACK16,254VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,255VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,256VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,257VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,258VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,259VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,260VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,261VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,262VK_FORMAT_R12X4_UNORM_PACK16,263VK_FORMAT_R12X4G12X4_UNORM_2PACK16,264VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,265VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,266VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,267VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,268VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,269VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,270VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,271VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,272VK_FORMAT_G16B16G16R16_422_UNORM,273VK_FORMAT_B16G16R16G16_422_UNORM,274VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,275VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,276VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,277VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,278VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,279VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK,280VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK,281VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK,282VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK,283VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK,284VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK,285VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK,286VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK,287VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK,288VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK,289VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK,290VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK,291VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK,292VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK,293};294295static VkImageLayout RD_TO_VK_LAYOUT[RDD::TEXTURE_LAYOUT_MAX] = {296VK_IMAGE_LAYOUT_UNDEFINED, // TEXTURE_LAYOUT_UNDEFINED297VK_IMAGE_LAYOUT_GENERAL, // TEXTURE_LAYOUT_GENERAL298VK_IMAGE_LAYOUT_GENERAL, // TEXTURE_LAYOUT_STORAGE_OPTIMAL299VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL300VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL301VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, // TEXTURE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL302VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL303VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // TEXTURE_LAYOUT_COPY_SRC_OPTIMAL304VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // TEXTURE_LAYOUT_COPY_DST_OPTIMAL305VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // TEXTURE_LAYOUT_RESOLVE_SRC_OPTIMAL306VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // TEXTURE_LAYOUT_RESOLVE_DST_OPTIMAL307VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, // TEXTURE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL308VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT, // TEXTURE_LAYOUT_FRAGMENT_DENSITY_MAP_ATTACHMENT_OPTIMAL309};310311static VkPipelineStageFlags _rd_to_vk_pipeline_stages(BitField<RDD::PipelineStageBits> p_stages) {312VkPipelineStageFlags vk_flags = 0;313if (p_stages.has_flag(RDD::PIPELINE_STAGE_COPY_BIT) || p_stages.has_flag(RDD::PIPELINE_STAGE_RESOLVE_BIT)) {314// Transfer has been split into copy and resolve bits. Clear them and merge them into one bit.315vk_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;316p_stages.clear_flag(RDD::PIPELINE_STAGE_COPY_BIT);317p_stages.clear_flag(RDD::PIPELINE_STAGE_RESOLVE_BIT);318}319320if (p_stages.has_flag(RDD::PIPELINE_STAGE_CLEAR_STORAGE_BIT)) {321// Vulkan should never use this as API_TRAIT_CLEAR_RESOURCES_WITH_VIEWS is not specified.322// Therefore, storage is never cleared with an explicit command.323p_stages.clear_flag(RDD::PIPELINE_STAGE_CLEAR_STORAGE_BIT);324}325326// The rest of the flags have compatible numeric values with Vulkan.327return VkPipelineStageFlags(p_stages) | vk_flags;328}329330static VkAccessFlags _rd_to_vk_access_flags(BitField<RDD::BarrierAccessBits> p_access) {331VkAccessFlags vk_flags = 0;332if (p_access.has_flag(RDD::BARRIER_ACCESS_COPY_READ_BIT) || p_access.has_flag(RDD::BARRIER_ACCESS_RESOLVE_READ_BIT)) {333vk_flags |= VK_ACCESS_TRANSFER_READ_BIT;334p_access.clear_flag(RDD::BARRIER_ACCESS_COPY_READ_BIT);335p_access.clear_flag(RDD::BARRIER_ACCESS_RESOLVE_READ_BIT);336}337338if (p_access.has_flag(RDD::BARRIER_ACCESS_COPY_WRITE_BIT) || p_access.has_flag(RDD::BARRIER_ACCESS_RESOLVE_WRITE_BIT)) {339vk_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;340p_access.clear_flag(RDD::BARRIER_ACCESS_COPY_WRITE_BIT);341p_access.clear_flag(RDD::BARRIER_ACCESS_RESOLVE_WRITE_BIT);342}343344if (p_access.has_flag(RDD::BARRIER_ACCESS_STORAGE_CLEAR_BIT)) {345// Vulkan should never use this as API_TRAIT_CLEAR_RESOURCES_WITH_VIEWS is not specified.346// Therefore, storage is never cleared with an explicit command.347p_access.clear_flag(RDD::BARRIER_ACCESS_STORAGE_CLEAR_BIT);348}349350// The rest of the flags have compatible numeric values with Vulkan.351return VkAccessFlags(p_access) | vk_flags;352}353354// RDD::CompareOperator == VkCompareOp.355static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_NEVER, VK_COMPARE_OP_NEVER));356static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_LESS, VK_COMPARE_OP_LESS));357static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_EQUAL, VK_COMPARE_OP_EQUAL));358static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL));359static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_GREATER, VK_COMPARE_OP_GREATER));360static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NOT_EQUAL));361static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL));362static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_ALWAYS, VK_COMPARE_OP_ALWAYS));363364static_assert(ARRAYS_COMPATIBLE_FIELDWISE(Rect2i, VkRect2D));365366uint32_t RenderingDeviceDriverVulkan::SubgroupCapabilities::supported_stages_flags_rd() const {367uint32_t flags = 0;368369if (supported_stages & VK_SHADER_STAGE_VERTEX_BIT) {370flags += SHADER_STAGE_VERTEX_BIT;371}372if (supported_stages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) {373flags += SHADER_STAGE_TESSELATION_CONTROL_BIT;374}375if (supported_stages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) {376flags += SHADER_STAGE_TESSELATION_EVALUATION_BIT;377}378if (supported_stages & VK_SHADER_STAGE_GEOMETRY_BIT) {379// FIXME: Add shader stage geometry bit.380}381if (supported_stages & VK_SHADER_STAGE_FRAGMENT_BIT) {382flags += SHADER_STAGE_FRAGMENT_BIT;383}384if (supported_stages & VK_SHADER_STAGE_COMPUTE_BIT) {385flags += SHADER_STAGE_COMPUTE_BIT;386}387388return flags;389}390391String RenderingDeviceDriverVulkan::SubgroupCapabilities::supported_stages_desc() const {392String res;393394if (supported_stages & VK_SHADER_STAGE_VERTEX_BIT) {395res += ", STAGE_VERTEX";396}397if (supported_stages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) {398res += ", STAGE_TESSELLATION_CONTROL";399}400if (supported_stages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) {401res += ", STAGE_TESSELLATION_EVALUATION";402}403if (supported_stages & VK_SHADER_STAGE_GEOMETRY_BIT) {404res += ", STAGE_GEOMETRY";405}406if (supported_stages & VK_SHADER_STAGE_FRAGMENT_BIT) {407res += ", STAGE_FRAGMENT";408}409if (supported_stages & VK_SHADER_STAGE_COMPUTE_BIT) {410res += ", STAGE_COMPUTE";411}412413// These are not defined on Android GRMBL.414if (supported_stages & 0x00000100 /* VK_SHADER_STAGE_RAYGEN_BIT_KHR */) {415res += ", STAGE_RAYGEN_KHR";416}417if (supported_stages & 0x00000200 /* VK_SHADER_STAGE_ANY_HIT_BIT_KHR */) {418res += ", STAGE_ANY_HIT_KHR";419}420if (supported_stages & 0x00000400 /* VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR */) {421res += ", STAGE_CLOSEST_HIT_KHR";422}423if (supported_stages & 0x00000800 /* VK_SHADER_STAGE_MISS_BIT_KHR */) {424res += ", STAGE_MISS_KHR";425}426if (supported_stages & 0x00001000 /* VK_SHADER_STAGE_INTERSECTION_BIT_KHR */) {427res += ", STAGE_INTERSECTION_KHR";428}429if (supported_stages & 0x00002000 /* VK_SHADER_STAGE_CALLABLE_BIT_KHR */) {430res += ", STAGE_CALLABLE_KHR";431}432if (supported_stages & 0x00000040 /* VK_SHADER_STAGE_TASK_BIT_NV */) {433res += ", STAGE_TASK_NV";434}435if (supported_stages & 0x00000080 /* VK_SHADER_STAGE_MESH_BIT_NV */) {436res += ", STAGE_MESH_NV";437}438439return res.substr(2); // Remove first ", ".440}441442uint32_t RenderingDeviceDriverVulkan::SubgroupCapabilities::supported_operations_flags_rd() const {443uint32_t flags = 0;444445if (supported_operations & VK_SUBGROUP_FEATURE_BASIC_BIT) {446flags += SUBGROUP_BASIC_BIT;447}448if (supported_operations & VK_SUBGROUP_FEATURE_VOTE_BIT) {449flags += SUBGROUP_VOTE_BIT;450}451if (supported_operations & VK_SUBGROUP_FEATURE_ARITHMETIC_BIT) {452flags += SUBGROUP_ARITHMETIC_BIT;453}454if (supported_operations & VK_SUBGROUP_FEATURE_BALLOT_BIT) {455flags += SUBGROUP_BALLOT_BIT;456}457if (supported_operations & VK_SUBGROUP_FEATURE_SHUFFLE_BIT) {458flags += SUBGROUP_SHUFFLE_BIT;459}460if (supported_operations & VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT) {461flags += SUBGROUP_SHUFFLE_RELATIVE_BIT;462}463if (supported_operations & VK_SUBGROUP_FEATURE_CLUSTERED_BIT) {464flags += SUBGROUP_CLUSTERED_BIT;465}466if (supported_operations & VK_SUBGROUP_FEATURE_QUAD_BIT) {467flags += SUBGROUP_QUAD_BIT;468}469470return flags;471}472473String RenderingDeviceDriverVulkan::SubgroupCapabilities::supported_operations_desc() const {474String res;475476if (supported_operations & VK_SUBGROUP_FEATURE_BASIC_BIT) {477res += ", FEATURE_BASIC";478}479if (supported_operations & VK_SUBGROUP_FEATURE_VOTE_BIT) {480res += ", FEATURE_VOTE";481}482if (supported_operations & VK_SUBGROUP_FEATURE_ARITHMETIC_BIT) {483res += ", FEATURE_ARITHMETIC";484}485if (supported_operations & VK_SUBGROUP_FEATURE_BALLOT_BIT) {486res += ", FEATURE_BALLOT";487}488if (supported_operations & VK_SUBGROUP_FEATURE_SHUFFLE_BIT) {489res += ", FEATURE_SHUFFLE";490}491if (supported_operations & VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT) {492res += ", FEATURE_SHUFFLE_RELATIVE";493}494if (supported_operations & VK_SUBGROUP_FEATURE_CLUSTERED_BIT) {495res += ", FEATURE_CLUSTERED";496}497if (supported_operations & VK_SUBGROUP_FEATURE_QUAD_BIT) {498res += ", FEATURE_QUAD";499}500if (supported_operations & VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV) {501res += ", FEATURE_PARTITIONED_NV";502}503504return res.substr(2); // Remove first ", ".505}506507/*****************/508/**** GENERIC ****/509/*****************/510511void RenderingDeviceDriverVulkan::_register_requested_device_extension(const CharString &p_extension_name, bool p_required) {512ERR_FAIL_COND(requested_device_extensions.has(p_extension_name));513requested_device_extensions[p_extension_name] = p_required;514}515516Error RenderingDeviceDriverVulkan::_initialize_device_extensions() {517enabled_device_extension_names.clear();518519_register_requested_device_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME, true);520_register_requested_device_extension(VK_KHR_MULTIVIEW_EXTENSION_NAME, false);521_register_requested_device_extension(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, false);522_register_requested_device_extension(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME, false);523_register_requested_device_extension(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, false);524_register_requested_device_extension(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, false);525_register_requested_device_extension(VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME, false);526_register_requested_device_extension(VK_KHR_16BIT_STORAGE_EXTENSION_NAME, false);527_register_requested_device_extension(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME, false);528_register_requested_device_extension(VK_KHR_MAINTENANCE_2_EXTENSION_NAME, false);529_register_requested_device_extension(VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME, false);530_register_requested_device_extension(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, false);531_register_requested_device_extension(VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME, false);532_register_requested_device_extension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, false);533_register_requested_device_extension(VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME, false);534_register_requested_device_extension(VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME, false);535536// We don't actually use this extension, but some runtime components on some platforms537// can and will fill the validation layers with useless info otherwise if not enabled.538_register_requested_device_extension(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, false);539540if (Engine::get_singleton()->is_generate_spirv_debug_info_enabled()) {541_register_requested_device_extension(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME, true);542}543544#if defined(VK_TRACK_DEVICE_MEMORY)545if (Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {546_register_requested_device_extension(VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME, false);547}548#endif549_register_requested_device_extension(VK_EXT_DEVICE_FAULT_EXTENSION_NAME, false);550551{552// Debug marker extensions.553// Should be last element in the array.554#ifdef DEV_ENABLED555bool want_debug_markers = true;556#else557bool want_debug_markers = OS::get_singleton()->is_stdout_verbose();558#endif559if (want_debug_markers) {560_register_requested_device_extension(VK_EXT_DEBUG_MARKER_EXTENSION_NAME, false);561}562}563564uint32_t device_extension_count = 0;565VkResult err = vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &device_extension_count, nullptr);566ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);567ERR_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?");568569TightLocalVector<VkExtensionProperties> device_extensions;570device_extensions.resize(device_extension_count);571err = vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &device_extension_count, device_extensions.ptr());572ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);573574#if defined(SWAPPY_FRAME_PACING_ENABLED)575if (swappy_frame_pacer_enable) {576char **swappy_required_extensions;577uint32_t swappy_required_extensions_count = 0;578// Determine number of extensions required by Swappy frame pacer.579SwappyVk_determineDeviceExtensions(physical_device, device_extension_count, device_extensions.ptr(), &swappy_required_extensions_count, nullptr);580581if (swappy_required_extensions_count < device_extension_count) {582// Determine the actual extensions.583swappy_required_extensions = (char **)malloc(swappy_required_extensions_count * sizeof(char *));584char *pRequiredExtensionsData = (char *)malloc(swappy_required_extensions_count * (VK_MAX_EXTENSION_NAME_SIZE + 1));585for (uint32_t i = 0; i < swappy_required_extensions_count; i++) {586swappy_required_extensions[i] = &pRequiredExtensionsData[i * (VK_MAX_EXTENSION_NAME_SIZE + 1)];587}588SwappyVk_determineDeviceExtensions(physical_device, device_extension_count,589device_extensions.ptr(), &swappy_required_extensions_count, swappy_required_extensions);590591// Enable extensions requested by Swappy.592for (uint32_t i = 0; i < swappy_required_extensions_count; i++) {593CharString extension_name(swappy_required_extensions[i]);594if (requested_device_extensions.has(extension_name)) {595enabled_device_extension_names.insert(extension_name);596}597}598599free(pRequiredExtensionsData);600free(swappy_required_extensions);601}602}603#endif604605#ifdef DEV_ENABLED606for (uint32_t i = 0; i < device_extension_count; i++) {607print_verbose(String("VULKAN: Found device extension ") + String::utf8(device_extensions[i].extensionName));608}609#endif610611// Enable all extensions that are supported and requested.612for (uint32_t i = 0; i < device_extension_count; i++) {613CharString extension_name(device_extensions[i].extensionName);614if (requested_device_extensions.has(extension_name)) {615enabled_device_extension_names.insert(extension_name);616}617}618619// Now check our requested extensions.620for (KeyValue<CharString, bool> &requested_extension : requested_device_extensions) {621if (!enabled_device_extension_names.has(requested_extension.key)) {622if (requested_extension.value) {623ERR_FAIL_V_MSG(ERR_BUG, String("Required extension ") + String::utf8(requested_extension.key) + String(" not found."));624} else {625print_verbose(String("Optional extension ") + String::utf8(requested_extension.key) + String(" not found"));626}627}628}629630return OK;631}632633Error RenderingDeviceDriverVulkan::_check_device_features() {634vkGetPhysicalDeviceFeatures(physical_device, &physical_device_features);635636// Check for required features.637if (!physical_device_features.imageCubeArray || !physical_device_features.independentBlend) {638String 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);639if (!physical_device_features.imageCubeArray) {640error_string += "- No support for image cube arrays.\n";641}642if (!physical_device_features.independentBlend) {643error_string += "- No support for independentBlend.\n";644}645error_string += "\nThis is usually a hardware limitation, so updating graphics drivers won't help in most cases.";646647#if defined(ANDROID_ENABLED) || defined(IOS_ENABLED)648// Android/iOS platform ports currently don't exit themselves when this method returns `ERR_CANT_CREATE`.649OS::get_singleton()->alert(error_string + "\nClick OK to exit (black screen will be visible).");650#else651OS::get_singleton()->alert(error_string + "\nClick OK to exit.");652#endif653654return ERR_CANT_CREATE;655}656657// Opt-in to the features we actually need/use. These can be changed in the future.658// We do this for multiple reasons:659//660// 1. Certain features (like sparse* stuff) cause unnecessary internal driver allocations.661// 2. Others like shaderStorageImageMultisample are a huge red flag662// (MSAA + Storage is rarely needed).663// 3. Most features when turned off aren't actually off (we just promise the driver not to use them)664// and it is validation what will complain. This allows us to target a minimum baseline.665//666// TODO: Allow the user to override these settings (i.e. turn off more stuff) using profiles667// so they can target a broad range of HW. For example Mali HW does not have668// shaderClipDistance/shaderCullDistance; thus validation would complain if such feature is used;669// allowing them to fix the problem without even owning Mali HW to test on.670//671// The excluded features are:672// - robustBufferAccess (can hamper performance on some hardware)673// - occlusionQueryPrecise674// - pipelineStatisticsQuery675// - shaderStorageImageMultisample (unsupported by Intel Arc, prevents from using MSAA storage accidentally)676// - shaderResourceResidency677// - sparseBinding (we don't use sparse features and enabling them cause extra internal allocations inside the Vulkan driver we don't need)678// - sparseResidencyBuffer679// - sparseResidencyImage2D680// - sparseResidencyImage3D681// - sparseResidency2Samples682// - sparseResidency4Samples683// - sparseResidency8Samples684// - sparseResidency16Samples685// - sparseResidencyAliased686// - inheritedQueries687688#define VK_DEVICEFEATURE_ENABLE_IF(x) \689if (physical_device_features.x) { \690requested_device_features.x = physical_device_features.x; \691} else \692((void)0)693694requested_device_features = {};695VK_DEVICEFEATURE_ENABLE_IF(fullDrawIndexUint32);696VK_DEVICEFEATURE_ENABLE_IF(imageCubeArray);697VK_DEVICEFEATURE_ENABLE_IF(independentBlend);698VK_DEVICEFEATURE_ENABLE_IF(geometryShader);699VK_DEVICEFEATURE_ENABLE_IF(tessellationShader);700VK_DEVICEFEATURE_ENABLE_IF(sampleRateShading);701VK_DEVICEFEATURE_ENABLE_IF(dualSrcBlend);702VK_DEVICEFEATURE_ENABLE_IF(logicOp);703VK_DEVICEFEATURE_ENABLE_IF(multiDrawIndirect);704VK_DEVICEFEATURE_ENABLE_IF(drawIndirectFirstInstance);705VK_DEVICEFEATURE_ENABLE_IF(depthClamp);706VK_DEVICEFEATURE_ENABLE_IF(depthBiasClamp);707VK_DEVICEFEATURE_ENABLE_IF(fillModeNonSolid);708VK_DEVICEFEATURE_ENABLE_IF(depthBounds);709VK_DEVICEFEATURE_ENABLE_IF(wideLines);710VK_DEVICEFEATURE_ENABLE_IF(largePoints);711VK_DEVICEFEATURE_ENABLE_IF(alphaToOne);712VK_DEVICEFEATURE_ENABLE_IF(multiViewport);713VK_DEVICEFEATURE_ENABLE_IF(samplerAnisotropy);714VK_DEVICEFEATURE_ENABLE_IF(textureCompressionETC2);715VK_DEVICEFEATURE_ENABLE_IF(textureCompressionASTC_LDR);716VK_DEVICEFEATURE_ENABLE_IF(textureCompressionBC);717VK_DEVICEFEATURE_ENABLE_IF(vertexPipelineStoresAndAtomics);718VK_DEVICEFEATURE_ENABLE_IF(fragmentStoresAndAtomics);719VK_DEVICEFEATURE_ENABLE_IF(shaderTessellationAndGeometryPointSize);720VK_DEVICEFEATURE_ENABLE_IF(shaderImageGatherExtended);721VK_DEVICEFEATURE_ENABLE_IF(shaderStorageImageExtendedFormats);722VK_DEVICEFEATURE_ENABLE_IF(shaderStorageImageReadWithoutFormat);723VK_DEVICEFEATURE_ENABLE_IF(shaderStorageImageWriteWithoutFormat);724VK_DEVICEFEATURE_ENABLE_IF(shaderUniformBufferArrayDynamicIndexing);725VK_DEVICEFEATURE_ENABLE_IF(shaderSampledImageArrayDynamicIndexing);726VK_DEVICEFEATURE_ENABLE_IF(shaderStorageBufferArrayDynamicIndexing);727VK_DEVICEFEATURE_ENABLE_IF(shaderStorageImageArrayDynamicIndexing);728VK_DEVICEFEATURE_ENABLE_IF(shaderClipDistance);729VK_DEVICEFEATURE_ENABLE_IF(shaderCullDistance);730VK_DEVICEFEATURE_ENABLE_IF(shaderFloat64);731VK_DEVICEFEATURE_ENABLE_IF(shaderInt64);732VK_DEVICEFEATURE_ENABLE_IF(shaderInt16);733VK_DEVICEFEATURE_ENABLE_IF(shaderResourceMinLod);734VK_DEVICEFEATURE_ENABLE_IF(variableMultisampleRate);735736return OK;737}738739Error RenderingDeviceDriverVulkan::_check_device_capabilities() {740// Fill device family and version.741device_capabilities.device_family = DEVICE_VULKAN;742device_capabilities.version_major = VK_API_VERSION_MAJOR(physical_device_properties.apiVersion);743device_capabilities.version_minor = VK_API_VERSION_MINOR(physical_device_properties.apiVersion);744745// References:746// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_KHR_multiview.html747// https://www.khronos.org/blog/vulkan-subgroup-tutorial748const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get();749if (functions.GetPhysicalDeviceFeatures2 != nullptr) {750// We must check that the corresponding extension is present before assuming a feature as enabled.751// See also: https://github.com/godotengine/godot/issues/65409752753void *next_features = nullptr;754VkPhysicalDeviceVulkan12Features device_features_vk_1_2 = {};755VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = {};756VkPhysicalDeviceBufferDeviceAddressFeaturesKHR buffer_device_address_features = {};757VkPhysicalDeviceVulkanMemoryModelFeaturesKHR vulkan_memory_model_features = {};758VkPhysicalDeviceFragmentShadingRateFeaturesKHR fsr_features = {};759VkPhysicalDeviceFragmentDensityMapFeaturesEXT fdm_features = {};760VkPhysicalDevice16BitStorageFeaturesKHR storage_feature = {};761VkPhysicalDeviceMultiviewFeatures multiview_features = {};762VkPhysicalDevicePipelineCreationCacheControlFeatures pipeline_cache_control_features = {};763764const bool use_1_2_features = physical_device_properties.apiVersion >= VK_API_VERSION_1_2;765if (use_1_2_features) {766device_features_vk_1_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;767device_features_vk_1_2.pNext = next_features;768next_features = &device_features_vk_1_2;769} else {770if (enabled_device_extension_names.has(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) {771shader_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR;772shader_features.pNext = next_features;773next_features = &shader_features;774}775if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {776buffer_device_address_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR;777buffer_device_address_features.pNext = next_features;778next_features = &buffer_device_address_features;779}780if (enabled_device_extension_names.has(VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME)) {781vulkan_memory_model_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR;782vulkan_memory_model_features.pNext = next_features;783next_features = &vulkan_memory_model_features;784}785}786787if (enabled_device_extension_names.has(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) {788fsr_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR;789fsr_features.pNext = next_features;790next_features = &fsr_features;791}792793if (enabled_device_extension_names.has(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME)) {794fdm_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT;795fdm_features.pNext = next_features;796next_features = &fdm_features;797}798799if (enabled_device_extension_names.has(VK_KHR_16BIT_STORAGE_EXTENSION_NAME)) {800storage_feature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR;801storage_feature.pNext = next_features;802next_features = &storage_feature;803}804805if (enabled_device_extension_names.has(VK_KHR_MULTIVIEW_EXTENSION_NAME)) {806multiview_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;807multiview_features.pNext = next_features;808next_features = &multiview_features;809}810811if (enabled_device_extension_names.has(VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME)) {812pipeline_cache_control_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES;813pipeline_cache_control_features.pNext = next_features;814next_features = &pipeline_cache_control_features;815}816817VkPhysicalDeviceFeatures2 device_features_2 = {};818device_features_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;819device_features_2.pNext = next_features;820functions.GetPhysicalDeviceFeatures2(physical_device, &device_features_2);821822if (use_1_2_features) {823#ifdef MACOS_ENABLED824ERR_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.");825#endif826if (enabled_device_extension_names.has(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) {827shader_capabilities.shader_float16_is_supported = device_features_vk_1_2.shaderFloat16;828shader_capabilities.shader_int8_is_supported = device_features_vk_1_2.shaderInt8;829}830if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {831buffer_device_address_support = device_features_vk_1_2.bufferDeviceAddress;832}833if (enabled_device_extension_names.has(VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME)) {834vulkan_memory_model_support = device_features_vk_1_2.vulkanMemoryModel;835vulkan_memory_model_device_scope_support = device_features_vk_1_2.vulkanMemoryModelDeviceScope;836}837} else {838if (enabled_device_extension_names.has(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) {839shader_capabilities.shader_float16_is_supported = shader_features.shaderFloat16;840shader_capabilities.shader_int8_is_supported = shader_features.shaderInt8;841}842if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {843buffer_device_address_support = buffer_device_address_features.bufferDeviceAddress;844}845if (enabled_device_extension_names.has(VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME)) {846vulkan_memory_model_support = vulkan_memory_model_features.vulkanMemoryModel;847vulkan_memory_model_device_scope_support = vulkan_memory_model_features.vulkanMemoryModelDeviceScope;848}849}850851if (enabled_device_extension_names.has(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) {852fsr_capabilities.pipeline_supported = fsr_features.pipelineFragmentShadingRate;853fsr_capabilities.primitive_supported = fsr_features.primitiveFragmentShadingRate;854fsr_capabilities.attachment_supported = fsr_features.attachmentFragmentShadingRate;855}856857if (enabled_device_extension_names.has(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME)) {858fdm_capabilities.attachment_supported = fdm_features.fragmentDensityMap;859fdm_capabilities.dynamic_attachment_supported = fdm_features.fragmentDensityMapDynamic;860fdm_capabilities.non_subsampled_images_supported = fdm_features.fragmentDensityMapNonSubsampledImages;861}862863// Multiple VRS techniques can't co-exist during the existence of one device, so we must864// choose one at creation time and only report one of them as available.865_choose_vrs_capabilities();866867if (enabled_device_extension_names.has(VK_KHR_MULTIVIEW_EXTENSION_NAME)) {868multiview_capabilities.is_supported = multiview_features.multiview;869multiview_capabilities.geometry_shader_is_supported = multiview_features.multiviewGeometryShader;870multiview_capabilities.tessellation_shader_is_supported = multiview_features.multiviewTessellationShader;871}872873if (enabled_device_extension_names.has(VK_KHR_16BIT_STORAGE_EXTENSION_NAME)) {874storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported = storage_feature.storageBuffer16BitAccess;875storage_buffer_capabilities.uniform_and_storage_buffer_16_bit_access_is_supported = storage_feature.uniformAndStorageBuffer16BitAccess;876storage_buffer_capabilities.storage_push_constant_16_is_supported = storage_feature.storagePushConstant16;877storage_buffer_capabilities.storage_input_output_16 = storage_feature.storageInputOutput16;878}879880if (enabled_device_extension_names.has(VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME)) {881pipeline_cache_control_support = pipeline_cache_control_features.pipelineCreationCacheControl;882}883884if (enabled_device_extension_names.has(VK_EXT_DEVICE_FAULT_EXTENSION_NAME)) {885device_fault_support = true;886}887#if defined(VK_TRACK_DEVICE_MEMORY)888if (enabled_device_extension_names.has(VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME)) {889device_memory_report_support = true;890}891#endif892}893894if (functions.GetPhysicalDeviceProperties2 != nullptr) {895void *next_properties = nullptr;896VkPhysicalDeviceFragmentShadingRatePropertiesKHR fsr_properties = {};897VkPhysicalDeviceFragmentDensityMapPropertiesEXT fdm_properties = {};898VkPhysicalDeviceMultiviewProperties multiview_properties = {};899VkPhysicalDeviceSubgroupProperties subgroup_properties = {};900VkPhysicalDeviceSubgroupSizeControlProperties subgroup_size_control_properties = {};901VkPhysicalDeviceProperties2 physical_device_properties_2 = {};902903const bool use_1_1_properties = physical_device_properties.apiVersion >= VK_API_VERSION_1_1;904if (use_1_1_properties) {905subgroup_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;906subgroup_properties.pNext = next_properties;907next_properties = &subgroup_properties;908909subgroup_capabilities.size_control_is_supported = enabled_device_extension_names.has(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME);910if (subgroup_capabilities.size_control_is_supported) {911subgroup_size_control_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES;912subgroup_size_control_properties.pNext = next_properties;913next_properties = &subgroup_size_control_properties;914}915}916917if (multiview_capabilities.is_supported) {918multiview_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES;919multiview_properties.pNext = next_properties;920next_properties = &multiview_properties;921}922923if (fsr_capabilities.attachment_supported) {924fsr_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR;925fsr_properties.pNext = next_properties;926next_properties = &fsr_properties;927}928929if (fdm_capabilities.attachment_supported) {930fdm_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT;931fdm_properties.pNext = next_properties;932next_properties = &fdm_properties;933}934935physical_device_properties_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;936physical_device_properties_2.pNext = next_properties;937functions.GetPhysicalDeviceProperties2(physical_device, &physical_device_properties_2);938939subgroup_capabilities.size = subgroup_properties.subgroupSize;940subgroup_capabilities.min_size = subgroup_properties.subgroupSize;941subgroup_capabilities.max_size = subgroup_properties.subgroupSize;942subgroup_capabilities.supported_stages = subgroup_properties.supportedStages;943subgroup_capabilities.supported_operations = subgroup_properties.supportedOperations;944945// Note: quadOperationsInAllStages will be true if:946// - supportedStages has VK_SHADER_STAGE_ALL_GRAPHICS + VK_SHADER_STAGE_COMPUTE_BIT.947// - supportedOperations has VK_SUBGROUP_FEATURE_QUAD_BIT.948subgroup_capabilities.quad_operations_in_all_stages = subgroup_properties.quadOperationsInAllStages;949950if (subgroup_capabilities.size_control_is_supported && (subgroup_size_control_properties.requiredSubgroupSizeStages & VK_SHADER_STAGE_COMPUTE_BIT)) {951subgroup_capabilities.min_size = subgroup_size_control_properties.minSubgroupSize;952subgroup_capabilities.max_size = subgroup_size_control_properties.maxSubgroupSize;953}954955if (fsr_capabilities.pipeline_supported || fsr_capabilities.primitive_supported || fsr_capabilities.attachment_supported) {956print_verbose("- Vulkan Fragment Shading Rate supported:");957if (fsr_capabilities.pipeline_supported) {958print_verbose(" Pipeline fragment shading rate");959}960if (fsr_capabilities.primitive_supported) {961print_verbose(" Primitive fragment shading rate");962}963if (fsr_capabilities.attachment_supported) {964// TODO: Expose these somehow to the end user.965fsr_capabilities.min_texel_size.x = fsr_properties.minFragmentShadingRateAttachmentTexelSize.width;966fsr_capabilities.min_texel_size.y = fsr_properties.minFragmentShadingRateAttachmentTexelSize.height;967fsr_capabilities.max_texel_size.x = fsr_properties.maxFragmentShadingRateAttachmentTexelSize.width;968fsr_capabilities.max_texel_size.y = fsr_properties.maxFragmentShadingRateAttachmentTexelSize.height;969fsr_capabilities.max_fragment_size.x = fsr_properties.maxFragmentSize.width; // either 4 or 8970fsr_capabilities.max_fragment_size.y = fsr_properties.maxFragmentSize.height; // generally the same as width971972print_verbose(String(" Attachment fragment shading rate") +973String(", min texel size: (") + itos(fsr_capabilities.min_texel_size.x) + String(", ") + itos(fsr_capabilities.min_texel_size.y) + String(")") +974String(", max texel size: (") + itos(fsr_capabilities.max_texel_size.x) + String(", ") + itos(fsr_capabilities.max_texel_size.y) + String(")") +975String(", max fragment size: (") + itos(fsr_capabilities.max_fragment_size.x) + String(", ") + itos(fsr_capabilities.max_fragment_size.y) + String(")"));976}977978} else {979print_verbose("- Vulkan Variable Rate Shading not supported");980}981982if (fdm_capabilities.attachment_supported || fdm_capabilities.dynamic_attachment_supported || fdm_capabilities.non_subsampled_images_supported) {983print_verbose("- Vulkan Fragment Density Map supported");984985fdm_capabilities.min_texel_size.x = fdm_properties.minFragmentDensityTexelSize.width;986fdm_capabilities.min_texel_size.y = fdm_properties.minFragmentDensityTexelSize.height;987fdm_capabilities.max_texel_size.x = fdm_properties.maxFragmentDensityTexelSize.width;988fdm_capabilities.max_texel_size.y = fdm_properties.maxFragmentDensityTexelSize.height;989fdm_capabilities.invocations_supported = fdm_properties.fragmentDensityInvocations;990991if (fdm_capabilities.dynamic_attachment_supported) {992print_verbose(" - dynamic fragment density map supported");993}994995if (fdm_capabilities.non_subsampled_images_supported) {996print_verbose(" - non-subsampled images supported");997}998} else {999print_verbose("- Vulkan Fragment Density Map not supported");1000}10011002if (multiview_capabilities.is_supported) {1003multiview_capabilities.max_view_count = multiview_properties.maxMultiviewViewCount;1004multiview_capabilities.max_instance_count = multiview_properties.maxMultiviewInstanceIndex;10051006print_verbose("- Vulkan multiview supported:");1007print_verbose(" max view count: " + itos(multiview_capabilities.max_view_count));1008print_verbose(" max instances: " + itos(multiview_capabilities.max_instance_count));1009} else {1010print_verbose("- Vulkan multiview not supported");1011}10121013print_verbose("- Vulkan subgroup:");1014print_verbose(" size: " + itos(subgroup_capabilities.size));1015print_verbose(" min size: " + itos(subgroup_capabilities.min_size));1016print_verbose(" max size: " + itos(subgroup_capabilities.max_size));1017print_verbose(" stages: " + subgroup_capabilities.supported_stages_desc());1018print_verbose(" supported ops: " + subgroup_capabilities.supported_operations_desc());1019if (subgroup_capabilities.quad_operations_in_all_stages) {1020print_verbose(" quad operations in all stages");1021}1022}10231024return OK;1025}10261027void RenderingDeviceDriverVulkan::_choose_vrs_capabilities() {1028bool prefer_fdm_on_qualcomm = physical_device_properties.vendorID == RenderingContextDriver::Vendor::VENDOR_QUALCOMM;1029if (fdm_capabilities.attachment_supported && (!fsr_capabilities.attachment_supported || prefer_fdm_on_qualcomm)) {1030// If available, we prefer using fragment density maps on Qualcomm as they adjust tile distribution when using1031// this technique. Performance as a result is higher than when using fragment shading rate.1032fsr_capabilities = FragmentShadingRateCapabilities();1033} else if (fsr_capabilities.attachment_supported) {1034// Disable any possibility of fragment density maps being used.1035fdm_capabilities = FragmentDensityMapCapabilities();1036} else {1037// Do not report or enable any VRS capabilities if attachment is not supported.1038fsr_capabilities = FragmentShadingRateCapabilities();1039fdm_capabilities = FragmentDensityMapCapabilities();1040}1041}10421043Error RenderingDeviceDriverVulkan::_add_queue_create_info(LocalVector<VkDeviceQueueCreateInfo> &r_queue_create_info) {1044uint32_t queue_family_count = queue_family_properties.size();1045queue_families.resize(queue_family_count);10461047VkQueueFlags queue_flags_mask = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT;1048const uint32_t max_queue_count_per_family = 1;1049static const float queue_priorities[max_queue_count_per_family] = {};1050for (uint32_t i = 0; i < queue_family_count; i++) {1051if ((queue_family_properties[i].queueFlags & queue_flags_mask) == 0) {1052// We ignore creating queues in families that don't support any of the operations we require.1053continue;1054}10551056VkDeviceQueueCreateInfo create_info = {};1057create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;1058create_info.queueFamilyIndex = i;1059create_info.queueCount = MIN(queue_family_properties[i].queueCount, max_queue_count_per_family);1060create_info.pQueuePriorities = queue_priorities;1061r_queue_create_info.push_back(create_info);10621063// Prepare the vectors where the queues will be filled out.1064queue_families[i].resize(create_info.queueCount);1065}10661067return OK;1068}10691070Error RenderingDeviceDriverVulkan::_initialize_device(const LocalVector<VkDeviceQueueCreateInfo> &p_queue_create_info) {1071TightLocalVector<const char *> enabled_extension_names;1072enabled_extension_names.reserve(enabled_device_extension_names.size());1073for (const CharString &extension_name : enabled_device_extension_names) {1074enabled_extension_names.push_back(extension_name.ptr());1075}10761077void *create_info_next = nullptr;1078VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = {};1079shader_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR;1080shader_features.pNext = create_info_next;1081shader_features.shaderFloat16 = shader_capabilities.shader_float16_is_supported;1082shader_features.shaderInt8 = shader_capabilities.shader_int8_is_supported;1083create_info_next = &shader_features;10841085VkPhysicalDeviceBufferDeviceAddressFeaturesKHR buffer_device_address_features = {};1086if (buffer_device_address_support) {1087buffer_device_address_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR;1088buffer_device_address_features.pNext = create_info_next;1089buffer_device_address_features.bufferDeviceAddress = buffer_device_address_support;1090create_info_next = &buffer_device_address_features;1091}10921093VkPhysicalDeviceVulkanMemoryModelFeaturesKHR vulkan_memory_model_features = {};1094if (vulkan_memory_model_support && vulkan_memory_model_device_scope_support) {1095vulkan_memory_model_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR;1096vulkan_memory_model_features.pNext = create_info_next;1097vulkan_memory_model_features.vulkanMemoryModel = vulkan_memory_model_support;1098vulkan_memory_model_features.vulkanMemoryModelDeviceScope = vulkan_memory_model_device_scope_support;1099create_info_next = &vulkan_memory_model_features;1100}11011102VkPhysicalDeviceFragmentShadingRateFeaturesKHR fsr_features = {};1103if (fsr_capabilities.pipeline_supported || fsr_capabilities.primitive_supported || fsr_capabilities.attachment_supported) {1104fsr_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR;1105fsr_features.pNext = create_info_next;1106fsr_features.pipelineFragmentShadingRate = fsr_capabilities.pipeline_supported;1107fsr_features.primitiveFragmentShadingRate = fsr_capabilities.primitive_supported;1108fsr_features.attachmentFragmentShadingRate = fsr_capabilities.attachment_supported;1109create_info_next = &fsr_features;1110}11111112VkPhysicalDeviceFragmentDensityMapFeaturesEXT fdm_features = {};1113if (fdm_capabilities.attachment_supported || fdm_capabilities.dynamic_attachment_supported || fdm_capabilities.non_subsampled_images_supported) {1114fdm_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT;1115fdm_features.pNext = create_info_next;1116fdm_features.fragmentDensityMap = fdm_capabilities.attachment_supported;1117fdm_features.fragmentDensityMapDynamic = fdm_capabilities.dynamic_attachment_supported;1118fdm_features.fragmentDensityMapNonSubsampledImages = fdm_capabilities.non_subsampled_images_supported;1119create_info_next = &fdm_features;1120}11211122VkPhysicalDevicePipelineCreationCacheControlFeatures pipeline_cache_control_features = {};1123if (pipeline_cache_control_support) {1124pipeline_cache_control_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES;1125pipeline_cache_control_features.pNext = create_info_next;1126pipeline_cache_control_features.pipelineCreationCacheControl = pipeline_cache_control_support;1127create_info_next = &pipeline_cache_control_features;1128}11291130VkPhysicalDeviceFaultFeaturesEXT device_fault_features = {};1131if (device_fault_support) {1132device_fault_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT;1133device_fault_features.pNext = create_info_next;1134create_info_next = &device_fault_features;1135}11361137#if defined(VK_TRACK_DEVICE_MEMORY)1138VkDeviceDeviceMemoryReportCreateInfoEXT memory_report_info = {};1139if (device_memory_report_support) {1140memory_report_info.sType = VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT;1141memory_report_info.pfnUserCallback = RenderingContextDriverVulkan::memory_report_callback;1142memory_report_info.pNext = create_info_next;1143memory_report_info.flags = 0;1144memory_report_info.pUserData = this;11451146create_info_next = &memory_report_info;1147}1148#endif11491150VkPhysicalDeviceVulkan11Features vulkan_1_1_features = {};1151VkPhysicalDevice16BitStorageFeaturesKHR storage_features = {};1152VkPhysicalDeviceMultiviewFeatures multiview_features = {};1153const bool enable_1_2_features = physical_device_properties.apiVersion >= VK_API_VERSION_1_2;1154if (enable_1_2_features) {1155// In Vulkan 1.2 and newer we use a newer struct to enable various features.1156vulkan_1_1_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;1157vulkan_1_1_features.pNext = create_info_next;1158vulkan_1_1_features.storageBuffer16BitAccess = storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported;1159vulkan_1_1_features.uniformAndStorageBuffer16BitAccess = storage_buffer_capabilities.uniform_and_storage_buffer_16_bit_access_is_supported;1160vulkan_1_1_features.storagePushConstant16 = storage_buffer_capabilities.storage_push_constant_16_is_supported;1161vulkan_1_1_features.storageInputOutput16 = storage_buffer_capabilities.storage_input_output_16;1162vulkan_1_1_features.multiview = multiview_capabilities.is_supported;1163vulkan_1_1_features.multiviewGeometryShader = multiview_capabilities.geometry_shader_is_supported;1164vulkan_1_1_features.multiviewTessellationShader = multiview_capabilities.tessellation_shader_is_supported;1165vulkan_1_1_features.variablePointersStorageBuffer = 0;1166vulkan_1_1_features.variablePointers = 0;1167vulkan_1_1_features.protectedMemory = 0;1168vulkan_1_1_features.samplerYcbcrConversion = 0;1169vulkan_1_1_features.shaderDrawParameters = 0;1170create_info_next = &vulkan_1_1_features;1171} else {1172// On Vulkan 1.0 and 1.1 we use our older structs to initialize these features.1173storage_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR;1174storage_features.pNext = create_info_next;1175storage_features.storageBuffer16BitAccess = storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported;1176storage_features.uniformAndStorageBuffer16BitAccess = storage_buffer_capabilities.uniform_and_storage_buffer_16_bit_access_is_supported;1177storage_features.storagePushConstant16 = storage_buffer_capabilities.storage_push_constant_16_is_supported;1178storage_features.storageInputOutput16 = storage_buffer_capabilities.storage_input_output_16;1179create_info_next = &storage_features;11801181const bool enable_1_1_features = physical_device_properties.apiVersion >= VK_API_VERSION_1_1;1182if (enable_1_1_features) {1183multiview_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;1184multiview_features.pNext = create_info_next;1185multiview_features.multiview = multiview_capabilities.is_supported;1186multiview_features.multiviewGeometryShader = multiview_capabilities.geometry_shader_is_supported;1187multiview_features.multiviewTessellationShader = multiview_capabilities.tessellation_shader_is_supported;1188create_info_next = &multiview_features;1189}1190}11911192VkDeviceCreateInfo create_info = {};1193create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;1194create_info.pNext = create_info_next;1195create_info.queueCreateInfoCount = p_queue_create_info.size();1196create_info.pQueueCreateInfos = p_queue_create_info.ptr();1197create_info.enabledExtensionCount = enabled_extension_names.size();1198create_info.ppEnabledExtensionNames = enabled_extension_names.ptr();1199create_info.pEnabledFeatures = &requested_device_features;12001201if (VulkanHooks::get_singleton() != nullptr) {1202bool device_created = VulkanHooks::get_singleton()->create_vulkan_device(&create_info, &vk_device);1203ERR_FAIL_COND_V(!device_created, ERR_CANT_CREATE);1204} else {1205VkResult err = vkCreateDevice(physical_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DEVICE), &vk_device);1206ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);1207}12081209for (uint32_t i = 0; i < queue_families.size(); i++) {1210for (uint32_t j = 0; j < queue_families[i].size(); j++) {1211vkGetDeviceQueue(vk_device, i, j, &queue_families[i][j].queue);1212}1213}12141215const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get();1216if (functions.GetDeviceProcAddr != nullptr) {1217device_functions.CreateSwapchainKHR = PFN_vkCreateSwapchainKHR(functions.GetDeviceProcAddr(vk_device, "vkCreateSwapchainKHR"));1218device_functions.DestroySwapchainKHR = PFN_vkDestroySwapchainKHR(functions.GetDeviceProcAddr(vk_device, "vkDestroySwapchainKHR"));1219device_functions.GetSwapchainImagesKHR = PFN_vkGetSwapchainImagesKHR(functions.GetDeviceProcAddr(vk_device, "vkGetSwapchainImagesKHR"));1220device_functions.AcquireNextImageKHR = PFN_vkAcquireNextImageKHR(functions.GetDeviceProcAddr(vk_device, "vkAcquireNextImageKHR"));1221device_functions.QueuePresentKHR = PFN_vkQueuePresentKHR(functions.GetDeviceProcAddr(vk_device, "vkQueuePresentKHR"));12221223if (enabled_device_extension_names.has(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME)) {1224device_functions.CreateRenderPass2KHR = PFN_vkCreateRenderPass2KHR(functions.GetDeviceProcAddr(vk_device, "vkCreateRenderPass2KHR"));1225device_functions.EndRenderPass2KHR = PFN_vkCmdEndRenderPass2KHR(functions.GetDeviceProcAddr(vk_device, "vkCmdEndRenderPass2KHR"));1226}12271228// Debug marker extensions.1229if (enabled_device_extension_names.has(VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) {1230device_functions.CmdDebugMarkerBeginEXT = (PFN_vkCmdDebugMarkerBeginEXT)functions.GetDeviceProcAddr(vk_device, "vkCmdDebugMarkerBeginEXT");1231device_functions.CmdDebugMarkerEndEXT = (PFN_vkCmdDebugMarkerEndEXT)functions.GetDeviceProcAddr(vk_device, "vkCmdDebugMarkerEndEXT");1232device_functions.CmdDebugMarkerInsertEXT = (PFN_vkCmdDebugMarkerInsertEXT)functions.GetDeviceProcAddr(vk_device, "vkCmdDebugMarkerInsertEXT");1233device_functions.DebugMarkerSetObjectNameEXT = (PFN_vkDebugMarkerSetObjectNameEXT)functions.GetDeviceProcAddr(vk_device, "vkDebugMarkerSetObjectNameEXT");1234}12351236// Debug device fault extension.1237if (device_fault_support) {1238device_functions.GetDeviceFaultInfoEXT = (PFN_vkGetDeviceFaultInfoEXT)functions.GetDeviceProcAddr(vk_device, "vkGetDeviceFaultInfoEXT");1239}1240}12411242return OK;1243}12441245Error RenderingDeviceDriverVulkan::_initialize_allocator() {1246VmaAllocatorCreateInfo allocator_info = {};1247allocator_info.physicalDevice = physical_device;1248allocator_info.device = vk_device;1249allocator_info.instance = context_driver->instance_get();1250const bool use_1_3_features = physical_device_properties.apiVersion >= VK_API_VERSION_1_3;1251if (use_1_3_features) {1252allocator_info.flags |= VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT;1253}1254if (buffer_device_address_support) {1255allocator_info.flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;1256}1257VkResult err = vmaCreateAllocator(&allocator_info, &allocator);1258ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, "vmaCreateAllocator failed with error " + itos(err) + ".");12591260return OK;1261}12621263Error RenderingDeviceDriverVulkan::_initialize_pipeline_cache() {1264pipelines_cache.buffer.resize(sizeof(PipelineCacheHeader));1265PipelineCacheHeader *header = (PipelineCacheHeader *)(pipelines_cache.buffer.ptrw());1266*header = {};1267header->magic = 868 + VK_PIPELINE_CACHE_HEADER_VERSION_ONE;1268header->device_id = physical_device_properties.deviceID;1269header->vendor_id = physical_device_properties.vendorID;1270header->driver_version = physical_device_properties.driverVersion;1271memcpy(header->uuid, physical_device_properties.pipelineCacheUUID, VK_UUID_SIZE);1272header->driver_abi = sizeof(void *);12731274pipeline_cache_id = String::hex_encode_buffer(physical_device_properties.pipelineCacheUUID, VK_UUID_SIZE);1275pipeline_cache_id += "-driver-" + itos(physical_device_properties.driverVersion);12761277return OK;1278}12791280static void _convert_subpass_attachments(const VkAttachmentReference2 *p_attachment_references_2, uint32_t p_attachment_references_count, TightLocalVector<VkAttachmentReference> &r_attachment_references) {1281r_attachment_references.resize(p_attachment_references_count);1282for (uint32_t i = 0; i < p_attachment_references_count; i++) {1283// Ignore sType, pNext and aspectMask (which is currently unused).1284r_attachment_references[i].attachment = p_attachment_references_2[i].attachment;1285r_attachment_references[i].layout = p_attachment_references_2[i].layout;1286}1287}12881289VkResult RenderingDeviceDriverVulkan::_create_render_pass(VkDevice p_device, const VkRenderPassCreateInfo2 *p_create_info, const VkAllocationCallbacks *p_allocator, VkRenderPass *p_render_pass) {1290if (device_functions.CreateRenderPass2KHR != nullptr) {1291return device_functions.CreateRenderPass2KHR(p_device, p_create_info, p_allocator, p_render_pass);1292} else {1293// Compatibility fallback with regular create render pass but by converting the inputs from the newer version to the older one.1294TightLocalVector<VkAttachmentDescription> attachments;1295attachments.resize(p_create_info->attachmentCount);1296for (uint32_t i = 0; i < p_create_info->attachmentCount; i++) {1297// Ignores sType and pNext from the attachment.1298const VkAttachmentDescription2 &src = p_create_info->pAttachments[i];1299VkAttachmentDescription &dst = attachments[i];1300dst.flags = src.flags;1301dst.format = src.format;1302dst.samples = src.samples;1303dst.loadOp = src.loadOp;1304dst.storeOp = src.storeOp;1305dst.stencilLoadOp = src.stencilLoadOp;1306dst.stencilStoreOp = src.stencilStoreOp;1307dst.initialLayout = src.initialLayout;1308dst.finalLayout = src.finalLayout;1309}13101311const uint32_t attachment_vectors_per_subpass = 4;1312TightLocalVector<TightLocalVector<VkAttachmentReference>> subpasses_attachments;1313TightLocalVector<VkSubpassDescription> subpasses;1314subpasses_attachments.resize(p_create_info->subpassCount * attachment_vectors_per_subpass);1315subpasses.resize(p_create_info->subpassCount);13161317for (uint32_t i = 0; i < p_create_info->subpassCount; i++) {1318const uint32_t vector_base_index = i * attachment_vectors_per_subpass;1319const uint32_t input_attachments_index = vector_base_index + 0;1320const uint32_t color_attachments_index = vector_base_index + 1;1321const uint32_t resolve_attachments_index = vector_base_index + 2;1322const uint32_t depth_attachment_index = vector_base_index + 3;1323_convert_subpass_attachments(p_create_info->pSubpasses[i].pInputAttachments, p_create_info->pSubpasses[i].inputAttachmentCount, subpasses_attachments[input_attachments_index]);1324_convert_subpass_attachments(p_create_info->pSubpasses[i].pColorAttachments, p_create_info->pSubpasses[i].colorAttachmentCount, subpasses_attachments[color_attachments_index]);1325_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]);1326_convert_subpass_attachments(p_create_info->pSubpasses[i].pDepthStencilAttachment, (p_create_info->pSubpasses[i].pDepthStencilAttachment != nullptr) ? 1 : 0, subpasses_attachments[depth_attachment_index]);13271328// Ignores sType and pNext from the subpass.1329const VkSubpassDescription2 &src_subpass = p_create_info->pSubpasses[i];1330VkSubpassDescription &dst_subpass = subpasses[i];1331dst_subpass.flags = src_subpass.flags;1332dst_subpass.pipelineBindPoint = src_subpass.pipelineBindPoint;1333dst_subpass.inputAttachmentCount = src_subpass.inputAttachmentCount;1334dst_subpass.pInputAttachments = subpasses_attachments[input_attachments_index].ptr();1335dst_subpass.colorAttachmentCount = src_subpass.colorAttachmentCount;1336dst_subpass.pColorAttachments = subpasses_attachments[color_attachments_index].ptr();1337dst_subpass.pResolveAttachments = subpasses_attachments[resolve_attachments_index].ptr();1338dst_subpass.pDepthStencilAttachment = subpasses_attachments[depth_attachment_index].ptr();1339dst_subpass.preserveAttachmentCount = src_subpass.preserveAttachmentCount;1340dst_subpass.pPreserveAttachments = src_subpass.pPreserveAttachments;1341}13421343TightLocalVector<VkSubpassDependency> dependencies;1344dependencies.resize(p_create_info->dependencyCount);13451346for (uint32_t i = 0; i < p_create_info->dependencyCount; i++) {1347// Ignores sType and pNext from the dependency, and viewMask which is currently unused.1348const VkSubpassDependency2 &src_dependency = p_create_info->pDependencies[i];1349VkSubpassDependency &dst_dependency = dependencies[i];1350dst_dependency.srcSubpass = src_dependency.srcSubpass;1351dst_dependency.dstSubpass = src_dependency.dstSubpass;1352dst_dependency.srcStageMask = src_dependency.srcStageMask;1353dst_dependency.dstStageMask = src_dependency.dstStageMask;1354dst_dependency.srcAccessMask = src_dependency.srcAccessMask;1355dst_dependency.dstAccessMask = src_dependency.dstAccessMask;1356dst_dependency.dependencyFlags = src_dependency.dependencyFlags;1357}13581359VkRenderPassCreateInfo create_info = {};1360create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;1361create_info.pNext = p_create_info->pNext;1362create_info.flags = p_create_info->flags;1363create_info.attachmentCount = attachments.size();1364create_info.pAttachments = attachments.ptr();1365create_info.subpassCount = subpasses.size();1366create_info.pSubpasses = subpasses.ptr();1367create_info.dependencyCount = dependencies.size();1368create_info.pDependencies = dependencies.ptr();1369return vkCreateRenderPass(vk_device, &create_info, p_allocator, p_render_pass);1370}1371}13721373bool RenderingDeviceDriverVulkan::_release_image_semaphore(CommandQueue *p_command_queue, uint32_t p_semaphore_index, bool p_release_on_swap_chain) {1374SwapChain *swap_chain = p_command_queue->image_semaphores_swap_chains[p_semaphore_index];1375if (swap_chain != nullptr) {1376// Clear the swap chain from the command queue's vector.1377p_command_queue->image_semaphores_swap_chains[p_semaphore_index] = nullptr;13781379if (p_release_on_swap_chain) {1380// Remove the acquired semaphore from the swap chain's vectors.1381for (uint32_t i = 0; i < swap_chain->command_queues_acquired.size(); i++) {1382if (swap_chain->command_queues_acquired[i] == p_command_queue && swap_chain->command_queues_acquired_semaphores[i] == p_semaphore_index) {1383swap_chain->command_queues_acquired.remove_at(i);1384swap_chain->command_queues_acquired_semaphores.remove_at(i);1385break;1386}1387}1388}13891390return true;1391}13921393return false;1394}13951396bool RenderingDeviceDriverVulkan::_recreate_image_semaphore(CommandQueue *p_command_queue, uint32_t p_semaphore_index, bool p_release_on_swap_chain) {1397_release_image_semaphore(p_command_queue, p_semaphore_index, p_release_on_swap_chain);13981399VkSemaphore semaphore;1400VkSemaphoreCreateInfo create_info = {};1401create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;1402VkResult err = vkCreateSemaphore(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE), &semaphore);1403ERR_FAIL_COND_V(err != VK_SUCCESS, false);14041405// Indicate the semaphore is free again and destroy the previous one before storing the new one.1406vkDestroySemaphore(vk_device, p_command_queue->image_semaphores[p_semaphore_index], VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE));14071408p_command_queue->image_semaphores[p_semaphore_index] = semaphore;1409p_command_queue->free_image_semaphores.push_back(p_semaphore_index);14101411return true;1412}1413// Debug marker extensions.1414VkDebugReportObjectTypeEXT RenderingDeviceDriverVulkan::_convert_to_debug_report_objectType(VkObjectType p_object_type) {1415switch (p_object_type) {1416case VK_OBJECT_TYPE_UNKNOWN:1417return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;1418case VK_OBJECT_TYPE_INSTANCE:1419return VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;1420case VK_OBJECT_TYPE_PHYSICAL_DEVICE:1421return VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT;1422case VK_OBJECT_TYPE_DEVICE:1423return VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT;1424case VK_OBJECT_TYPE_QUEUE:1425return VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT;1426case VK_OBJECT_TYPE_SEMAPHORE:1427return VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT;1428case VK_OBJECT_TYPE_COMMAND_BUFFER:1429return VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT;1430case VK_OBJECT_TYPE_FENCE:1431return VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT;1432case VK_OBJECT_TYPE_DEVICE_MEMORY:1433return VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT;1434case VK_OBJECT_TYPE_BUFFER:1435return VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT;1436case VK_OBJECT_TYPE_IMAGE:1437return VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT;1438case VK_OBJECT_TYPE_EVENT:1439return VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT;1440case VK_OBJECT_TYPE_QUERY_POOL:1441return VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT;1442case VK_OBJECT_TYPE_BUFFER_VIEW:1443return VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT;1444case VK_OBJECT_TYPE_IMAGE_VIEW:1445return VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT;1446case VK_OBJECT_TYPE_SHADER_MODULE:1447return VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT;1448case VK_OBJECT_TYPE_PIPELINE_CACHE:1449return VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT;1450case VK_OBJECT_TYPE_PIPELINE_LAYOUT:1451return VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT;1452case VK_OBJECT_TYPE_RENDER_PASS:1453return VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT;1454case VK_OBJECT_TYPE_PIPELINE:1455return VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT;1456case VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT:1457return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT;1458case VK_OBJECT_TYPE_SAMPLER:1459return VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT;1460case VK_OBJECT_TYPE_DESCRIPTOR_POOL:1461return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT;1462case VK_OBJECT_TYPE_DESCRIPTOR_SET:1463return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT;1464case VK_OBJECT_TYPE_FRAMEBUFFER:1465return VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT;1466case VK_OBJECT_TYPE_COMMAND_POOL:1467return VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT;1468case VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION:1469return VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT;1470case VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE:1471return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT;1472case VK_OBJECT_TYPE_SURFACE_KHR:1473return VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT;1474case VK_OBJECT_TYPE_SWAPCHAIN_KHR:1475return VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT;1476case VK_OBJECT_TYPE_DISPLAY_KHR:1477return VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT;1478case VK_OBJECT_TYPE_DISPLAY_MODE_KHR:1479return VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT;1480case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT:1481return VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT;1482case VK_OBJECT_TYPE_CU_MODULE_NVX:1483return VK_DEBUG_REPORT_OBJECT_TYPE_CU_MODULE_NVX_EXT;1484case VK_OBJECT_TYPE_CU_FUNCTION_NVX:1485return VK_DEBUG_REPORT_OBJECT_TYPE_CU_FUNCTION_NVX_EXT;1486case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR:1487return VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT;1488case VK_OBJECT_TYPE_VALIDATION_CACHE_EXT:1489return VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT;1490case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV:1491return VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT;1492default:1493break;1494}14951496return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;1497}14981499void RenderingDeviceDriverVulkan::_set_object_name(VkObjectType p_object_type, uint64_t p_object_handle, String p_object_name) {1500const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get();1501if (functions.SetDebugUtilsObjectNameEXT != nullptr) {1502CharString obj_data = p_object_name.utf8();1503VkDebugUtilsObjectNameInfoEXT name_info;1504name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;1505name_info.pNext = nullptr;1506name_info.objectType = p_object_type;1507name_info.objectHandle = p_object_handle;1508name_info.pObjectName = obj_data.get_data();1509functions.SetDebugUtilsObjectNameEXT(vk_device, &name_info);1510} else if (functions.DebugMarkerSetObjectNameEXT != nullptr) {1511// Debug marker extensions.1512CharString obj_data = p_object_name.utf8();1513VkDebugMarkerObjectNameInfoEXT name_info;1514name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;1515name_info.pNext = nullptr;1516name_info.objectType = _convert_to_debug_report_objectType(p_object_type);1517name_info.object = p_object_handle;1518name_info.pObjectName = obj_data.get_data();1519functions.DebugMarkerSetObjectNameEXT(vk_device, &name_info);1520}1521}15221523Error RenderingDeviceDriverVulkan::initialize(uint32_t p_device_index, uint32_t p_frame_count) {1524context_device = context_driver->device_get(p_device_index);1525physical_device = context_driver->physical_device_get(p_device_index);1526vkGetPhysicalDeviceProperties(physical_device, &physical_device_properties);15271528// Workaround a driver bug on Adreno 730 GPUs that keeps leaking memory on each call to vkResetDescriptorPool.1529// Which eventually run out of memory. In such case we should not be using linear allocated pools1530// Bug introduced in driver 512.597.0 and fixed in 512.671.0.1531// Confirmed by Qualcomm.1532if (linear_descriptor_pools_enabled) {1533const uint32_t reset_descriptor_pool_broken_driver_begin = VK_MAKE_VERSION(512u, 597u, 0u);1534const uint32_t reset_descriptor_pool_fixed_driver_begin = VK_MAKE_VERSION(512u, 671u, 0u);1535linear_descriptor_pools_enabled = physical_device_properties.driverVersion < reset_descriptor_pool_broken_driver_begin || physical_device_properties.driverVersion > reset_descriptor_pool_fixed_driver_begin;1536}1537frame_count = p_frame_count;15381539// Copy the queue family properties the context already retrieved.1540uint32_t queue_family_count = context_driver->queue_family_get_count(p_device_index);1541queue_family_properties.resize(queue_family_count);1542for (uint32_t i = 0; i < queue_family_count; i++) {1543queue_family_properties[i] = context_driver->queue_family_get(p_device_index, i);1544}15451546Error err = _initialize_device_extensions();1547ERR_FAIL_COND_V(err != OK, err);15481549err = _check_device_features();1550ERR_FAIL_COND_V(err != OK, err);15511552err = _check_device_capabilities();1553ERR_FAIL_COND_V(err != OK, err);15541555LocalVector<VkDeviceQueueCreateInfo> queue_create_info;1556err = _add_queue_create_info(queue_create_info);1557ERR_FAIL_COND_V(err != OK, err);15581559err = _initialize_device(queue_create_info);1560ERR_FAIL_COND_V(err != OK, err);15611562err = _initialize_allocator();1563ERR_FAIL_COND_V(err != OK, err);15641565err = _initialize_pipeline_cache();1566ERR_FAIL_COND_V(err != OK, err);15671568max_descriptor_sets_per_pool = GLOBAL_GET("rendering/rendering_device/vulkan/max_descriptors_per_pool");15691570#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)1571breadcrumb_buffer = buffer_create(2u * sizeof(uint32_t) * BREADCRUMB_BUFFER_ENTRIES, BufferUsageBits::BUFFER_USAGE_TRANSFER_TO_BIT, MemoryAllocationType::MEMORY_ALLOCATION_TYPE_CPU);1572#endif15731574#if defined(SWAPPY_FRAME_PACING_ENABLED)1575swappy_frame_pacer_enable = GLOBAL_GET("display/window/frame_pacing/android/enable_frame_pacing");1576swappy_mode = GLOBAL_GET("display/window/frame_pacing/android/swappy_mode");15771578if (VulkanHooks::get_singleton() != nullptr) {1579// Hooks control device creation & possibly presentation1580// (e.g. OpenXR) thus it's too risky to use Swappy.1581swappy_frame_pacer_enable = false;1582OS::get_singleton()->print("VulkanHooks detected (e.g. OpenXR): Force-disabling Swappy Frame Pacing.\n");1583}1584#endif15851586shader_container_format.set_debug_info_enabled(Engine::get_singleton()->is_generate_spirv_debug_info_enabled());15871588return OK;1589}15901591/****************/1592/**** MEMORY ****/1593/****************/15941595static const uint32_t SMALL_ALLOCATION_MAX_SIZE = 4096;15961597VmaPool RenderingDeviceDriverVulkan::_find_or_create_small_allocs_pool(uint32_t p_mem_type_index) {1598if (small_allocs_pools.has(p_mem_type_index)) {1599return small_allocs_pools[p_mem_type_index];1600}16011602print_verbose("Creating VMA small objects pool for memory type index " + itos(p_mem_type_index));16031604VmaPoolCreateInfo pci = {};1605pci.memoryTypeIndex = p_mem_type_index;1606pci.flags = 0;1607pci.blockSize = 0;1608pci.minBlockCount = 0;1609pci.maxBlockCount = SIZE_MAX;1610pci.priority = 0.5f;1611pci.minAllocationAlignment = 0;1612pci.pMemoryAllocateNext = nullptr;1613VmaPool pool = VK_NULL_HANDLE;1614VkResult res = vmaCreatePool(allocator, &pci, &pool);1615small_allocs_pools[p_mem_type_index] = pool; // Don't try to create it again if failed the first time.1616ERR_FAIL_COND_V_MSG(res, pool, "vmaCreatePool failed with error " + itos(res) + ".");16171618return pool;1619}16201621/*****************/1622/**** BUFFERS ****/1623/*****************/16241625// RDD::BufferUsageBits == VkBufferUsageFlagBits.1626static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_TRANSFER_FROM_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT));1627static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_TRANSFER_TO_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT));1628static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_TEXEL_BIT, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT));1629static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_UNIFORM_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT));1630static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_STORAGE_BIT, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));1631static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_INDEX_BIT, VK_BUFFER_USAGE_INDEX_BUFFER_BIT));1632static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_VERTEX_BIT, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));1633static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_INDIRECT_BIT, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT));1634static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT));16351636RDD::BufferID RenderingDeviceDriverVulkan::buffer_create(uint64_t p_size, BitField<BufferUsageBits> p_usage, MemoryAllocationType p_allocation_type) {1637VkBufferCreateInfo create_info = {};1638create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;1639create_info.size = p_size;1640create_info.usage = p_usage;1641create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;16421643VmaMemoryUsage vma_usage = VMA_MEMORY_USAGE_UNKNOWN;1644uint32_t vma_flags_to_remove = 0;16451646VmaAllocationCreateInfo alloc_create_info = {};1647switch (p_allocation_type) {1648case MEMORY_ALLOCATION_TYPE_CPU: {1649bool is_src = p_usage.has_flag(BUFFER_USAGE_TRANSFER_FROM_BIT);1650bool is_dst = p_usage.has_flag(BUFFER_USAGE_TRANSFER_TO_BIT);1651if (is_src && !is_dst) {1652// Looks like a staging buffer: CPU maps, writes sequentially, then GPU copies to VRAM.1653alloc_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;1654alloc_create_info.preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;1655vma_flags_to_remove |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;1656}1657if (is_dst && !is_src) {1658// Looks like a readback buffer: GPU copies from VRAM, then CPU maps and reads.1659alloc_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;1660alloc_create_info.preferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;1661vma_flags_to_remove |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;1662}1663vma_usage = VMA_MEMORY_USAGE_AUTO_PREFER_HOST;1664alloc_create_info.requiredFlags = (VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);1665} break;1666case MEMORY_ALLOCATION_TYPE_GPU: {1667vma_usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;1668if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {1669// We must set it right now or else vmaFindMemoryTypeIndexForBufferInfo will use wrong parameters.1670alloc_create_info.usage = vma_usage;1671}1672alloc_create_info.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;1673if (p_size <= SMALL_ALLOCATION_MAX_SIZE) {1674uint32_t mem_type_index = 0;1675vmaFindMemoryTypeIndexForBufferInfo(allocator, &create_info, &alloc_create_info, &mem_type_index);1676alloc_create_info.pool = _find_or_create_small_allocs_pool(mem_type_index);1677}1678} break;1679}16801681VkBuffer vk_buffer = VK_NULL_HANDLE;1682VmaAllocation allocation = nullptr;1683VmaAllocationInfo alloc_info = {};16841685if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {1686alloc_create_info.preferredFlags &= ~vma_flags_to_remove;1687alloc_create_info.usage = vma_usage;1688VkResult err = vmaCreateBuffer(allocator, &create_info, &alloc_create_info, &vk_buffer, &allocation, &alloc_info);1689ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't create buffer of size: " + itos(p_size) + ", error " + itos(err) + ".");1690} else {1691VkResult err = vkCreateBuffer(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER), &vk_buffer);1692ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't create buffer of size: " + itos(p_size) + ", error " + itos(err) + ".");1693err = vmaAllocateMemoryForBuffer(allocator, vk_buffer, &alloc_create_info, &allocation, &alloc_info);1694ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't allocate memory for buffer of size: " + itos(p_size) + ", error " + itos(err) + ".");1695err = vmaBindBufferMemory2(allocator, allocation, 0, vk_buffer, nullptr);1696ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't bind memory to buffer of size: " + itos(p_size) + ", error " + itos(err) + ".");1697}16981699// Bookkeep.1700BufferInfo *buf_info = VersatileResource::allocate<BufferInfo>(resources_allocator);1701buf_info->vk_buffer = vk_buffer;1702buf_info->allocation.handle = allocation;1703buf_info->allocation.size = alloc_info.size;1704buf_info->size = p_size;17051706return BufferID(buf_info);1707}17081709bool RenderingDeviceDriverVulkan::buffer_set_texel_format(BufferID p_buffer, DataFormat p_format) {1710BufferInfo *buf_info = (BufferInfo *)p_buffer.id;17111712DEV_ASSERT(!buf_info->vk_view);17131714VkBufferViewCreateInfo view_create_info = {};1715view_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;1716view_create_info.buffer = buf_info->vk_buffer;1717view_create_info.format = RD_TO_VK_FORMAT[p_format];1718view_create_info.range = buf_info->allocation.size;17191720VkResult res = vkCreateBufferView(vk_device, &view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER_VIEW), &buf_info->vk_view);1721ERR_FAIL_COND_V_MSG(res, false, "Unable to create buffer view, error " + itos(res) + ".");17221723return true;1724}17251726void RenderingDeviceDriverVulkan::buffer_free(BufferID p_buffer) {1727BufferInfo *buf_info = (BufferInfo *)p_buffer.id;1728if (buf_info->vk_view) {1729vkDestroyBufferView(vk_device, buf_info->vk_view, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER_VIEW));1730}17311732if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {1733vmaDestroyBuffer(allocator, buf_info->vk_buffer, buf_info->allocation.handle);1734} else {1735vkDestroyBuffer(vk_device, buf_info->vk_buffer, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER));1736vmaFreeMemory(allocator, buf_info->allocation.handle);1737}17381739VersatileResource::free(resources_allocator, buf_info);1740}17411742uint64_t RenderingDeviceDriverVulkan::buffer_get_allocation_size(BufferID p_buffer) {1743const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;1744return buf_info->allocation.size;1745}17461747uint8_t *RenderingDeviceDriverVulkan::buffer_map(BufferID p_buffer) {1748const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;1749void *data_ptr = nullptr;1750VkResult err = vmaMapMemory(allocator, buf_info->allocation.handle, &data_ptr);1751ERR_FAIL_COND_V_MSG(err, nullptr, "vmaMapMemory failed with error " + itos(err) + ".");1752return (uint8_t *)data_ptr;1753}17541755void RenderingDeviceDriverVulkan::buffer_unmap(BufferID p_buffer) {1756const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;1757vmaUnmapMemory(allocator, buf_info->allocation.handle);1758}17591760uint64_t RenderingDeviceDriverVulkan::buffer_get_device_address(BufferID p_buffer) {1761const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;1762VkBufferDeviceAddressInfo address_info = {};1763address_info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;1764address_info.pNext = nullptr;1765address_info.buffer = buf_info->vk_buffer;1766return vkGetBufferDeviceAddress(vk_device, &address_info);1767}17681769/*****************/1770/**** TEXTURE ****/1771/*****************/17721773static const VkImageType RD_TEX_TYPE_TO_VK_IMG_TYPE[RDD::TEXTURE_TYPE_MAX] = {1774VK_IMAGE_TYPE_1D,1775VK_IMAGE_TYPE_2D,1776VK_IMAGE_TYPE_3D,1777VK_IMAGE_TYPE_2D,1778VK_IMAGE_TYPE_1D,1779VK_IMAGE_TYPE_2D,1780VK_IMAGE_TYPE_2D,1781};17821783static const VkSampleCountFlagBits RD_TO_VK_SAMPLE_COUNT[RDD::TEXTURE_SAMPLES_MAX] = {1784VK_SAMPLE_COUNT_1_BIT,1785VK_SAMPLE_COUNT_2_BIT,1786VK_SAMPLE_COUNT_4_BIT,1787VK_SAMPLE_COUNT_8_BIT,1788VK_SAMPLE_COUNT_16_BIT,1789VK_SAMPLE_COUNT_32_BIT,1790VK_SAMPLE_COUNT_64_BIT,1791};17921793// RDD::TextureType == VkImageViewType.1794static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_TYPE_1D, VK_IMAGE_VIEW_TYPE_1D));1795static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_TYPE_2D, VK_IMAGE_VIEW_TYPE_2D));1796static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_TYPE_3D, VK_IMAGE_VIEW_TYPE_3D));1797static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_TYPE_CUBE, VK_IMAGE_VIEW_TYPE_CUBE));1798static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_TYPE_1D_ARRAY, VK_IMAGE_VIEW_TYPE_1D_ARRAY));1799static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_TYPE_2D_ARRAY, VK_IMAGE_VIEW_TYPE_2D_ARRAY));1800static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_TYPE_CUBE_ARRAY, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY));18011802// RDD::TextureSwizzle == VkComponentSwizzle.1803static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY));1804static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO));1805static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ONE));1806static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R));1807static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_G, VK_COMPONENT_SWIZZLE_G));1808static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_B, VK_COMPONENT_SWIZZLE_B));1809static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_A, VK_COMPONENT_SWIZZLE_A));18101811// RDD::TextureAspectBits == VkImageAspectFlagBits.1812static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT));1813static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_ASPECT_DEPTH_BIT, VK_IMAGE_ASPECT_DEPTH_BIT));1814static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_ASPECT_STENCIL_BIT, VK_IMAGE_ASPECT_STENCIL_BIT));18151816VkSampleCountFlagBits RenderingDeviceDriverVulkan::_ensure_supported_sample_count(TextureSamples p_requested_sample_count) {1817VkSampleCountFlags sample_count_flags = (physical_device_properties.limits.framebufferColorSampleCounts & physical_device_properties.limits.framebufferDepthSampleCounts);18181819if ((sample_count_flags & RD_TO_VK_SAMPLE_COUNT[p_requested_sample_count])) {1820// The requested sample count is supported.1821return RD_TO_VK_SAMPLE_COUNT[p_requested_sample_count];1822} else {1823// Find the closest lower supported sample count.1824VkSampleCountFlagBits sample_count = RD_TO_VK_SAMPLE_COUNT[p_requested_sample_count];1825while (sample_count > VK_SAMPLE_COUNT_1_BIT) {1826if (sample_count_flags & sample_count) {1827return sample_count;1828}1829sample_count = (VkSampleCountFlagBits)(sample_count >> 1);1830}1831}1832return VK_SAMPLE_COUNT_1_BIT;1833}18341835RDD::TextureID RenderingDeviceDriverVulkan::texture_create(const TextureFormat &p_format, const TextureView &p_view) {1836VkImageCreateInfo create_info = {};1837create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;18381839if (p_format.shareable_formats.size()) {1840create_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;18411842if (enabled_device_extension_names.has(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME)) {1843VkFormat *vk_allowed_formats = ALLOCA_ARRAY(VkFormat, p_format.shareable_formats.size());1844for (int i = 0; i < p_format.shareable_formats.size(); i++) {1845vk_allowed_formats[i] = RD_TO_VK_FORMAT[p_format.shareable_formats[i]];1846}18471848VkImageFormatListCreateInfoKHR *format_list_create_info = ALLOCA_SINGLE(VkImageFormatListCreateInfoKHR);1849*format_list_create_info = {};1850format_list_create_info->sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR;1851format_list_create_info->viewFormatCount = p_format.shareable_formats.size();1852format_list_create_info->pViewFormats = vk_allowed_formats;18531854create_info.pNext = format_list_create_info;1855}1856}18571858if (p_format.texture_type == TEXTURE_TYPE_CUBE || p_format.texture_type == TEXTURE_TYPE_CUBE_ARRAY) {1859create_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;1860}1861/*if (p_format.texture_type == TEXTURE_TYPE_2D || p_format.texture_type == TEXTURE_TYPE_2D_ARRAY) {1862create_info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;1863}*/18641865create_info.imageType = RD_TEX_TYPE_TO_VK_IMG_TYPE[p_format.texture_type];18661867create_info.format = RD_TO_VK_FORMAT[p_format.format];18681869create_info.extent.width = p_format.width;1870create_info.extent.height = p_format.height;1871create_info.extent.depth = p_format.depth;18721873create_info.mipLevels = p_format.mipmaps;1874create_info.arrayLayers = p_format.array_layers;18751876create_info.samples = _ensure_supported_sample_count(p_format.samples);1877create_info.tiling = (p_format.usage_bits & TEXTURE_USAGE_CPU_READ_BIT) ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;18781879// Usage.1880if ((p_format.usage_bits & TEXTURE_USAGE_SAMPLING_BIT)) {1881create_info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;1882}1883if ((p_format.usage_bits & TEXTURE_USAGE_STORAGE_BIT)) {1884create_info.usage |= VK_IMAGE_USAGE_STORAGE_BIT;1885}1886if ((p_format.usage_bits & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) {1887create_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;1888}1889if ((p_format.usage_bits & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {1890create_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;1891}1892if ((p_format.usage_bits & TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)) {1893create_info.usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;1894}1895if ((p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) && (p_format.usage_bits & TEXTURE_USAGE_VRS_FRAGMENT_SHADING_RATE_BIT)) {1896create_info.usage |= VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;1897}1898if ((p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) && (p_format.usage_bits & TEXTURE_USAGE_VRS_FRAGMENT_DENSITY_MAP_BIT)) {1899create_info.usage |= VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT;1900}1901if ((p_format.usage_bits & TEXTURE_USAGE_CAN_UPDATE_BIT)) {1902create_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;1903}1904if ((p_format.usage_bits & TEXTURE_USAGE_CAN_COPY_FROM_BIT)) {1905create_info.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;1906}1907if ((p_format.usage_bits & TEXTURE_USAGE_CAN_COPY_TO_BIT)) {1908create_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;1909}19101911create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;1912create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;19131914// Allocate memory.19151916uint32_t width = 0, height = 0;1917uint32_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);19181919VmaAllocationCreateInfo alloc_create_info = {};1920alloc_create_info.flags = (p_format.usage_bits & TEXTURE_USAGE_CPU_READ_BIT) ? VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT : 0;19211922if (p_format.usage_bits & TEXTURE_USAGE_TRANSIENT_BIT) {1923uint32_t memory_type_index = 0;1924VmaAllocationCreateInfo lazy_memory_requirements = alloc_create_info;1925lazy_memory_requirements.usage = VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED;1926VkResult result = vmaFindMemoryTypeIndex(allocator, UINT32_MAX, &lazy_memory_requirements, &memory_type_index);1927if (VK_SUCCESS == result) {1928alloc_create_info = lazy_memory_requirements;1929create_info.usage |= VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;1930// VUID-VkImageCreateInfo-usage-00963 :1931// If usage includes VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,1932// then bits other than VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,1933// and VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT must not be set.1934create_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);1935} else {1936alloc_create_info.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;1937}1938} else {1939alloc_create_info.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;1940}19411942if (image_size <= SMALL_ALLOCATION_MAX_SIZE) {1943uint32_t mem_type_index = 0;1944vmaFindMemoryTypeIndexForImageInfo(allocator, &create_info, &alloc_create_info, &mem_type_index);1945alloc_create_info.pool = _find_or_create_small_allocs_pool(mem_type_index);1946}19471948// Create.19491950VkImage vk_image = VK_NULL_HANDLE;1951VmaAllocation allocation = nullptr;1952VmaAllocationInfo alloc_info = {};19531954if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {1955alloc_create_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;1956VkResult err = vmaCreateImage(allocator, &create_info, &alloc_create_info, &vk_image, &allocation, &alloc_info);1957ERR_FAIL_COND_V_MSG(err, TextureID(), "vmaCreateImage failed with error " + itos(err) + ".");1958} else {1959VkResult err = vkCreateImage(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE), &vk_image);1960ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImage failed with error " + itos(err) + ".");1961err = vmaAllocateMemoryForImage(allocator, vk_image, &alloc_create_info, &allocation, &alloc_info);1962ERR_FAIL_COND_V_MSG(err, TextureID(), "Can't allocate memory for image, error: " + itos(err) + ".");1963err = vmaBindImageMemory2(allocator, allocation, 0, vk_image, nullptr);1964ERR_FAIL_COND_V_MSG(err, TextureID(), "Can't bind memory to image, error: " + itos(err) + ".");1965}19661967// Create view.19681969VkImageViewCreateInfo image_view_create_info = {};1970image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;1971image_view_create_info.image = vk_image;1972image_view_create_info.viewType = (VkImageViewType)p_format.texture_type;1973image_view_create_info.format = RD_TO_VK_FORMAT[p_view.format];1974image_view_create_info.components.r = (VkComponentSwizzle)p_view.swizzle_r;1975image_view_create_info.components.g = (VkComponentSwizzle)p_view.swizzle_g;1976image_view_create_info.components.b = (VkComponentSwizzle)p_view.swizzle_b;1977image_view_create_info.components.a = (VkComponentSwizzle)p_view.swizzle_a;1978image_view_create_info.subresourceRange.levelCount = create_info.mipLevels;1979image_view_create_info.subresourceRange.layerCount = create_info.arrayLayers;1980if ((p_format.usage_bits & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {1981image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;1982} else {1983image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;1984}19851986VkImageViewASTCDecodeModeEXT decode_mode;1987if (enabled_device_extension_names.has(VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME)) {1988if (image_view_create_info.format >= VK_FORMAT_ASTC_4x4_UNORM_BLOCK && image_view_create_info.format <= VK_FORMAT_ASTC_12x12_SRGB_BLOCK) {1989decode_mode.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT;1990decode_mode.pNext = nullptr;1991decode_mode.decodeMode = VK_FORMAT_R8G8B8A8_UNORM;1992image_view_create_info.pNext = &decode_mode;1993}1994}19951996VkImageView vk_image_view = VK_NULL_HANDLE;1997VkResult err = vkCreateImageView(vk_device, &image_view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &vk_image_view);1998if (err) {1999if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {2000vmaDestroyImage(allocator, vk_image, allocation);2001} else {2002vkDestroyImage(vk_device, vk_image, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE));2003vmaFreeMemory(allocator, allocation);2004}20052006ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImageView failed with error " + itos(err) + ".");2007}20082009// Bookkeep.20102011TextureInfo *tex_info = VersatileResource::allocate<TextureInfo>(resources_allocator);2012tex_info->vk_image = vk_image;2013tex_info->vk_view = vk_image_view;2014tex_info->rd_format = p_format.format;2015tex_info->vk_create_info = create_info;2016tex_info->vk_view_create_info = image_view_create_info;2017tex_info->allocation.handle = allocation;2018#ifdef DEBUG_ENABLED2019tex_info->transient = (p_format.usage_bits & TEXTURE_USAGE_TRANSIENT_BIT) != 0;2020#endif2021vmaGetAllocationInfo(allocator, tex_info->allocation.handle, &tex_info->allocation.info);20222023#if PRINT_NATIVE_COMMANDS2024print_line(vformat("vkCreateImageView: 0x%uX for 0x%uX", uint64_t(vk_image_view), uint64_t(vk_image)));2025#endif20262027return TextureID(tex_info);2028}20292030RDD::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) {2031VkImage vk_image = (VkImage)p_native_texture;20322033// We only need to create a view into the already existing natively-provided texture.20342035VkImageViewCreateInfo image_view_create_info = {};2036image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;2037image_view_create_info.image = vk_image;2038image_view_create_info.viewType = (VkImageViewType)p_type;2039image_view_create_info.format = RD_TO_VK_FORMAT[p_format];2040image_view_create_info.components.r = VK_COMPONENT_SWIZZLE_R;2041image_view_create_info.components.g = VK_COMPONENT_SWIZZLE_G;2042image_view_create_info.components.b = VK_COMPONENT_SWIZZLE_B;2043image_view_create_info.components.a = VK_COMPONENT_SWIZZLE_A;2044image_view_create_info.subresourceRange.baseMipLevel = 0;2045image_view_create_info.subresourceRange.levelCount = p_mipmaps;2046image_view_create_info.subresourceRange.layerCount = p_array_layers;2047image_view_create_info.subresourceRange.aspectMask = p_depth_stencil ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;20482049VkImageView vk_image_view = VK_NULL_HANDLE;2050VkResult err = vkCreateImageView(vk_device, &image_view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &vk_image_view);2051if (err) {2052ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImageView failed with error " + itos(err) + ".");2053}20542055// Bookkeep.20562057TextureInfo *tex_info = VersatileResource::allocate<TextureInfo>(resources_allocator);2058tex_info->vk_view = vk_image_view;2059tex_info->rd_format = p_format;2060tex_info->vk_view_create_info = image_view_create_info;2061#ifdef DEBUG_ENABLED2062tex_info->created_from_extension = true;2063#endif2064return TextureID(tex_info);2065}20662067RDD::TextureID RenderingDeviceDriverVulkan::texture_create_shared(TextureID p_original_texture, const TextureView &p_view) {2068const TextureInfo *owner_tex_info = (const TextureInfo *)p_original_texture.id;2069#ifdef DEBUG_ENABLED2070ERR_FAIL_COND_V(!owner_tex_info->allocation.handle && !owner_tex_info->created_from_extension, TextureID());2071#endif2072VkImageViewCreateInfo image_view_create_info = owner_tex_info->vk_view_create_info;2073image_view_create_info.format = RD_TO_VK_FORMAT[p_view.format];2074image_view_create_info.components.r = (VkComponentSwizzle)p_view.swizzle_r;2075image_view_create_info.components.g = (VkComponentSwizzle)p_view.swizzle_g;2076image_view_create_info.components.b = (VkComponentSwizzle)p_view.swizzle_b;2077image_view_create_info.components.a = (VkComponentSwizzle)p_view.swizzle_a;20782079if (enabled_device_extension_names.has(VK_KHR_MAINTENANCE_2_EXTENSION_NAME)) {2080// May need to make VK_KHR_maintenance2 mandatory and thus has Vulkan 1.1 be our minimum supported version2081// if we require setting this information. Vulkan 1.0 may simply not care.2082if (image_view_create_info.format != owner_tex_info->vk_view_create_info.format) {2083VkImageViewUsageCreateInfo *usage_info = ALLOCA_SINGLE(VkImageViewUsageCreateInfo);2084*usage_info = {};2085usage_info->sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO;2086usage_info->usage = owner_tex_info->vk_create_info.usage;20872088// Certain features may not be available for the format of the view.2089{2090VkFormatProperties properties = {};2091vkGetPhysicalDeviceFormatProperties(physical_device, RD_TO_VK_FORMAT[p_view.format], &properties);2092const VkFormatFeatureFlags &supported_flags = owner_tex_info->vk_create_info.tiling == VK_IMAGE_TILING_LINEAR ? properties.linearTilingFeatures : properties.optimalTilingFeatures;2093if ((usage_info->usage & VK_IMAGE_USAGE_STORAGE_BIT) && !(supported_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {2094usage_info->usage &= ~uint32_t(VK_IMAGE_USAGE_STORAGE_BIT);2095}2096if ((usage_info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) && !(supported_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {2097usage_info->usage &= ~uint32_t(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);2098}2099}21002101image_view_create_info.pNext = usage_info;2102}2103}21042105VkImageView new_vk_image_view = VK_NULL_HANDLE;2106VkResult err = vkCreateImageView(vk_device, &image_view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &new_vk_image_view);2107ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImageView failed with error " + itos(err) + ".");21082109// Bookkeep.21102111TextureInfo *tex_info = VersatileResource::allocate<TextureInfo>(resources_allocator);2112*tex_info = *owner_tex_info;2113tex_info->vk_view = new_vk_image_view;2114tex_info->vk_view_create_info = image_view_create_info;2115tex_info->allocation = {};21162117#if PRINT_NATIVE_COMMANDS2118print_line(vformat("vkCreateImageView: 0x%uX for 0x%uX", uint64_t(new_vk_image_view), uint64_t(owner_tex_info->vk_view_create_info.image)));2119#endif21202121return TextureID(tex_info);2122}21232124RDD::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) {2125const TextureInfo *owner_tex_info = (const TextureInfo *)p_original_texture.id;2126#ifdef DEBUG_ENABLED2127ERR_FAIL_COND_V(!owner_tex_info->allocation.handle && !owner_tex_info->created_from_extension, TextureID());2128#endif21292130VkImageViewCreateInfo image_view_create_info = owner_tex_info->vk_view_create_info;2131switch (p_slice_type) {2132case TEXTURE_SLICE_2D: {2133image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;2134} break;2135case TEXTURE_SLICE_3D: {2136image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_3D;2137} break;2138case TEXTURE_SLICE_CUBEMAP: {2139image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_CUBE;2140} break;2141case TEXTURE_SLICE_2D_ARRAY: {2142image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;2143} break;2144default: {2145return TextureID(nullptr);2146}2147}2148image_view_create_info.format = RD_TO_VK_FORMAT[p_view.format];2149image_view_create_info.components.r = (VkComponentSwizzle)p_view.swizzle_r;2150image_view_create_info.components.g = (VkComponentSwizzle)p_view.swizzle_g;2151image_view_create_info.components.b = (VkComponentSwizzle)p_view.swizzle_b;2152image_view_create_info.components.a = (VkComponentSwizzle)p_view.swizzle_a;2153image_view_create_info.subresourceRange.baseMipLevel = p_mipmap;2154image_view_create_info.subresourceRange.levelCount = p_mipmaps;2155image_view_create_info.subresourceRange.baseArrayLayer = p_layer;2156image_view_create_info.subresourceRange.layerCount = p_layers;21572158VkImageView new_vk_image_view = VK_NULL_HANDLE;2159VkResult err = vkCreateImageView(vk_device, &image_view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &new_vk_image_view);2160ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImageView failed with error " + itos(err) + ".");21612162// Bookkeep.21632164TextureInfo *tex_info = VersatileResource::allocate<TextureInfo>(resources_allocator);2165*tex_info = *owner_tex_info;2166tex_info->vk_view = new_vk_image_view;2167tex_info->vk_view_create_info = image_view_create_info;2168tex_info->allocation = {};21692170#if PRINT_NATIVE_COMMANDS2171print_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));2172#endif21732174return TextureID(tex_info);2175}21762177void RenderingDeviceDriverVulkan::texture_free(TextureID p_texture) {2178TextureInfo *tex_info = (TextureInfo *)p_texture.id;2179vkDestroyImageView(vk_device, tex_info->vk_view, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW));2180if (tex_info->allocation.handle) {2181if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {2182vmaDestroyImage(allocator, tex_info->vk_view_create_info.image, tex_info->allocation.handle);2183} else {2184vkDestroyImage(vk_device, tex_info->vk_image, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER));2185vmaFreeMemory(allocator, tex_info->allocation.handle);2186}2187}2188VersatileResource::free(resources_allocator, tex_info);2189}21902191uint64_t RenderingDeviceDriverVulkan::texture_get_allocation_size(TextureID p_texture) {2192const TextureInfo *tex_info = (const TextureInfo *)p_texture.id;2193return tex_info->allocation.info.size;2194}21952196void RenderingDeviceDriverVulkan::texture_get_copyable_layout(TextureID p_texture, const TextureSubresource &p_subresource, TextureCopyableLayout *r_layout) {2197const TextureInfo *tex_info = (const TextureInfo *)p_texture.id;21982199*r_layout = {};22002201if (tex_info->vk_create_info.tiling == VK_IMAGE_TILING_LINEAR) {2202VkImageSubresource vk_subres = {};2203vk_subres.aspectMask = (VkImageAspectFlags)(1 << p_subresource.aspect);2204vk_subres.arrayLayer = p_subresource.layer;2205vk_subres.mipLevel = p_subresource.mipmap;22062207VkSubresourceLayout vk_layout = {};2208vkGetImageSubresourceLayout(vk_device, tex_info->vk_view_create_info.image, &vk_subres, &vk_layout);22092210r_layout->offset = vk_layout.offset;2211r_layout->size = vk_layout.size;2212r_layout->row_pitch = vk_layout.rowPitch;2213r_layout->depth_pitch = vk_layout.depthPitch;2214r_layout->layer_pitch = vk_layout.arrayPitch;2215} else {2216// Tight.2217uint32_t w = tex_info->vk_create_info.extent.width;2218uint32_t h = tex_info->vk_create_info.extent.height;2219uint32_t d = tex_info->vk_create_info.extent.depth;2220if (p_subresource.mipmap > 0) {2221r_layout->offset = get_image_format_required_size(tex_info->rd_format, w, h, d, p_subresource.mipmap);2222}2223for (uint32_t i = 0; i < p_subresource.mipmap; i++) {2224w = MAX(1u, w >> 1);2225h = MAX(1u, h >> 1);2226d = MAX(1u, d >> 1);2227}2228uint32_t bw = 0, bh = 0;2229get_compressed_image_format_block_dimensions(tex_info->rd_format, bw, bh);2230uint32_t sbw = 0, sbh = 0;2231r_layout->size = get_image_format_required_size(tex_info->rd_format, w, h, d, 1, &sbw, &sbh);2232r_layout->row_pitch = r_layout->size / ((sbh / bh) * d);2233r_layout->depth_pitch = r_layout->size / d;2234r_layout->layer_pitch = r_layout->size / tex_info->vk_create_info.arrayLayers;2235}2236}22372238uint8_t *RenderingDeviceDriverVulkan::texture_map(TextureID p_texture, const TextureSubresource &p_subresource) {2239const TextureInfo *tex_info = (const TextureInfo *)p_texture.id;22402241VkImageSubresource vk_subres = {};2242vk_subres.aspectMask = (VkImageAspectFlags)(1 << p_subresource.aspect);2243vk_subres.arrayLayer = p_subresource.layer;2244vk_subres.mipLevel = p_subresource.mipmap;22452246VkSubresourceLayout vk_layout = {};2247vkGetImageSubresourceLayout(vk_device, tex_info->vk_view_create_info.image, &vk_subres, &vk_layout);22482249void *data_ptr = nullptr;2250VkResult err = vkMapMemory(2251vk_device,2252tex_info->allocation.info.deviceMemory,2253tex_info->allocation.info.offset + vk_layout.offset,2254vk_layout.size,22550,2256&data_ptr);22572258vmaMapMemory(allocator, tex_info->allocation.handle, &data_ptr);2259ERR_FAIL_COND_V_MSG(err, nullptr, "vkMapMemory failed with error " + itos(err) + ".");2260return (uint8_t *)data_ptr;2261}22622263void RenderingDeviceDriverVulkan::texture_unmap(TextureID p_texture) {2264const TextureInfo *tex_info = (const TextureInfo *)p_texture.id;2265vmaUnmapMemory(allocator, tex_info->allocation.handle);2266}22672268BitField<RDD::TextureUsageBits> RenderingDeviceDriverVulkan::texture_get_usages_supported_by_format(DataFormat p_format, bool p_cpu_readable) {2269if (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)) {2270// Formats that were introduced later with extensions must not reach vkGetPhysicalDeviceFormatProperties if the extension isn't available. This means it's not supported.2271return 0;2272}2273VkFormatProperties properties = {};2274vkGetPhysicalDeviceFormatProperties(physical_device, RD_TO_VK_FORMAT[p_format], &properties);22752276const VkFormatFeatureFlags &flags = p_cpu_readable ? properties.linearTilingFeatures : properties.optimalTilingFeatures;22772278// Everything supported by default makes an all-or-nothing check easier for the caller.2279BitField<RDD::TextureUsageBits> supported = INT64_MAX;22802281if (!(flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {2282supported.clear_flag(TEXTURE_USAGE_SAMPLING_BIT);2283}2284if (!(flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {2285supported.clear_flag(TEXTURE_USAGE_COLOR_ATTACHMENT_BIT);2286}2287if (!(flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {2288supported.clear_flag(TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);2289}2290if (!(flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {2291supported.clear_flag(TEXTURE_USAGE_STORAGE_BIT);2292}2293if (!(flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)) {2294supported.clear_flag(TEXTURE_USAGE_STORAGE_ATOMIC_BIT);2295}2296if (p_format != DATA_FORMAT_R8_UINT && p_format != DATA_FORMAT_R8G8_UNORM) {2297supported.clear_flag(TEXTURE_USAGE_VRS_ATTACHMENT_BIT);2298}22992300return supported;2301}23022303bool RenderingDeviceDriverVulkan::texture_can_make_shared_with_format(TextureID p_texture, DataFormat p_format, bool &r_raw_reinterpretation) {2304r_raw_reinterpretation = false;2305return true;2306}23072308/*****************/2309/**** SAMPLER ****/2310/*****************/23112312// RDD::SamplerRepeatMode == VkSamplerAddressMode.2313static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_REPEAT_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT));2314static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT));2315static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE));2316static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_REPEAT_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER));2317static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_REPEAT_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE));23182319// RDD::SamplerBorderColor == VkBorderColor.2320static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK));2321static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_BORDER_COLOR_INT_TRANSPARENT_BLACK, VK_BORDER_COLOR_INT_TRANSPARENT_BLACK));2322static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_BORDER_COLOR_FLOAT_OPAQUE_BLACK, VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK));2323static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_BORDER_COLOR_INT_OPAQUE_BLACK, VK_BORDER_COLOR_INT_OPAQUE_BLACK));2324static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_BORDER_COLOR_FLOAT_OPAQUE_WHITE, VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE));2325static_assert(ENUM_MEMBERS_EQUAL(RDD::SAMPLER_BORDER_COLOR_INT_OPAQUE_WHITE, VK_BORDER_COLOR_INT_OPAQUE_WHITE));23262327RDD::SamplerID RenderingDeviceDriverVulkan::sampler_create(const SamplerState &p_state) {2328VkSamplerCreateInfo sampler_create_info = {};2329sampler_create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;2330sampler_create_info.pNext = nullptr;2331sampler_create_info.flags = 0;2332sampler_create_info.magFilter = p_state.mag_filter == SAMPLER_FILTER_LINEAR ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;2333sampler_create_info.minFilter = p_state.min_filter == SAMPLER_FILTER_LINEAR ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;2334sampler_create_info.mipmapMode = p_state.mip_filter == SAMPLER_FILTER_LINEAR ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST;2335sampler_create_info.addressModeU = (VkSamplerAddressMode)p_state.repeat_u;2336sampler_create_info.addressModeV = (VkSamplerAddressMode)p_state.repeat_v;2337sampler_create_info.addressModeW = (VkSamplerAddressMode)p_state.repeat_w;2338sampler_create_info.mipLodBias = p_state.lod_bias;2339sampler_create_info.anisotropyEnable = p_state.use_anisotropy && (physical_device_features.samplerAnisotropy == VK_TRUE);2340sampler_create_info.maxAnisotropy = p_state.anisotropy_max;2341sampler_create_info.compareEnable = p_state.enable_compare;2342sampler_create_info.compareOp = (VkCompareOp)p_state.compare_op;2343sampler_create_info.minLod = p_state.min_lod;2344sampler_create_info.maxLod = p_state.max_lod;2345sampler_create_info.borderColor = (VkBorderColor)p_state.border_color;2346sampler_create_info.unnormalizedCoordinates = p_state.unnormalized_uvw;23472348VkSampler vk_sampler = VK_NULL_HANDLE;2349VkResult res = vkCreateSampler(vk_device, &sampler_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SAMPLER), &vk_sampler);2350ERR_FAIL_COND_V_MSG(res, SamplerID(), "vkCreateSampler failed with error " + itos(res) + ".");23512352return SamplerID(vk_sampler);2353}23542355void RenderingDeviceDriverVulkan::sampler_free(SamplerID p_sampler) {2356vkDestroySampler(vk_device, (VkSampler)p_sampler.id, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SAMPLER));2357}23582359bool RenderingDeviceDriverVulkan::sampler_is_format_supported_for_filter(DataFormat p_format, SamplerFilter p_filter) {2360switch (p_filter) {2361case SAMPLER_FILTER_NEAREST: {2362return true;2363}2364case SAMPLER_FILTER_LINEAR: {2365VkFormatProperties properties = {};2366vkGetPhysicalDeviceFormatProperties(physical_device, RD_TO_VK_FORMAT[p_format], &properties);2367return (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT);2368}2369}2370return false;2371}23722373/**********************/2374/**** VERTEX ARRAY ****/2375/**********************/23762377RDD::VertexFormatID RenderingDeviceDriverVulkan::vertex_format_create(VectorView<VertexAttribute> p_vertex_attribs) {2378// Pre-bookkeep.2379VertexFormatInfo *vf_info = VersatileResource::allocate<VertexFormatInfo>(resources_allocator);23802381vf_info->vk_bindings.resize(p_vertex_attribs.size());2382vf_info->vk_attributes.resize(p_vertex_attribs.size());2383for (uint32_t i = 0; i < p_vertex_attribs.size(); i++) {2384vf_info->vk_bindings[i] = {};2385vf_info->vk_bindings[i].binding = i;2386vf_info->vk_bindings[i].stride = p_vertex_attribs[i].stride;2387vf_info->vk_bindings[i].inputRate = p_vertex_attribs[i].frequency == VERTEX_FREQUENCY_INSTANCE ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;2388vf_info->vk_attributes[i] = {};2389vf_info->vk_attributes[i].binding = i;2390vf_info->vk_attributes[i].location = p_vertex_attribs[i].location;2391vf_info->vk_attributes[i].format = RD_TO_VK_FORMAT[p_vertex_attribs[i].format];2392vf_info->vk_attributes[i].offset = p_vertex_attribs[i].offset;2393}23942395vf_info->vk_create_info = {};2396vf_info->vk_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;2397vf_info->vk_create_info.vertexBindingDescriptionCount = vf_info->vk_bindings.size();2398vf_info->vk_create_info.pVertexBindingDescriptions = vf_info->vk_bindings.ptr();2399vf_info->vk_create_info.vertexAttributeDescriptionCount = vf_info->vk_attributes.size();2400vf_info->vk_create_info.pVertexAttributeDescriptions = vf_info->vk_attributes.ptr();24012402return VertexFormatID(vf_info);2403}24042405void RenderingDeviceDriverVulkan::vertex_format_free(VertexFormatID p_vertex_format) {2406VertexFormatInfo *vf_info = (VertexFormatInfo *)p_vertex_format.id;2407VersatileResource::free(resources_allocator, vf_info);2408}24092410/******************/2411/**** BARRIERS ****/2412/******************/24132414// RDD::PipelineStageBits == VkPipelineStageFlagBits.2415static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT));2416static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT));2417static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT));2418static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT));2419static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT));2420static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT));2421static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_GEOMETRY_SHADER_BIT, VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT));2422static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT));2423static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT));2424static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT));2425static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT));2426static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT));2427static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT));2428static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT));2429static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT));2430static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR));2431static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT, VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT));24322433// RDD::BarrierAccessBits == VkAccessFlagBits.2434static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_INDIRECT_COMMAND_READ_BIT, VK_ACCESS_INDIRECT_COMMAND_READ_BIT));2435static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_INDEX_READ_BIT, VK_ACCESS_INDEX_READ_BIT));2436static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT));2437static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_UNIFORM_READ_BIT, VK_ACCESS_UNIFORM_READ_BIT));2438static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_INPUT_ATTACHMENT_READ_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT));2439static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_READ_BIT));2440static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT));2441static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT));2442static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT));2443static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT));2444static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT));2445static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_HOST_READ_BIT, VK_ACCESS_HOST_READ_BIT));2446static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_HOST_WRITE_BIT, VK_ACCESS_HOST_WRITE_BIT));2447static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_MEMORY_READ_BIT, VK_ACCESS_MEMORY_READ_BIT));2448static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_MEMORY_WRITE_BIT, VK_ACCESS_MEMORY_WRITE_BIT));2449static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT, VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR));2450static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_FRAGMENT_DENSITY_MAP_ATTACHMENT_READ_BIT, VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT));24512452void RenderingDeviceDriverVulkan::command_pipeline_barrier(2453CommandBufferID p_cmd_buffer,2454BitField<PipelineStageBits> p_src_stages,2455BitField<PipelineStageBits> p_dst_stages,2456VectorView<MemoryBarrier> p_memory_barriers,2457VectorView<BufferBarrier> p_buffer_barriers,2458VectorView<TextureBarrier> p_texture_barriers) {2459VkMemoryBarrier *vk_memory_barriers = ALLOCA_ARRAY(VkMemoryBarrier, p_memory_barriers.size());2460for (uint32_t i = 0; i < p_memory_barriers.size(); i++) {2461vk_memory_barriers[i] = {};2462vk_memory_barriers[i].sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;2463vk_memory_barriers[i].srcAccessMask = _rd_to_vk_access_flags(p_memory_barriers[i].src_access);2464vk_memory_barriers[i].dstAccessMask = _rd_to_vk_access_flags(p_memory_barriers[i].dst_access);2465}24662467VkBufferMemoryBarrier *vk_buffer_barriers = ALLOCA_ARRAY(VkBufferMemoryBarrier, p_buffer_barriers.size());2468for (uint32_t i = 0; i < p_buffer_barriers.size(); i++) {2469vk_buffer_barriers[i] = {};2470vk_buffer_barriers[i].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;2471vk_buffer_barriers[i].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;2472vk_buffer_barriers[i].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;2473vk_buffer_barriers[i].srcAccessMask = _rd_to_vk_access_flags(p_buffer_barriers[i].src_access);2474vk_buffer_barriers[i].dstAccessMask = _rd_to_vk_access_flags(p_buffer_barriers[i].dst_access);2475vk_buffer_barriers[i].buffer = ((const BufferInfo *)p_buffer_barriers[i].buffer.id)->vk_buffer;2476vk_buffer_barriers[i].offset = p_buffer_barriers[i].offset;2477vk_buffer_barriers[i].size = p_buffer_barriers[i].size;2478}24792480VkImageMemoryBarrier *vk_image_barriers = ALLOCA_ARRAY(VkImageMemoryBarrier, p_texture_barriers.size());2481for (uint32_t i = 0; i < p_texture_barriers.size(); i++) {2482const TextureInfo *tex_info = (const TextureInfo *)p_texture_barriers[i].texture.id;2483vk_image_barriers[i] = {};2484vk_image_barriers[i].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;2485vk_image_barriers[i].srcAccessMask = _rd_to_vk_access_flags(p_texture_barriers[i].src_access);2486vk_image_barriers[i].dstAccessMask = _rd_to_vk_access_flags(p_texture_barriers[i].dst_access);2487vk_image_barriers[i].oldLayout = RD_TO_VK_LAYOUT[p_texture_barriers[i].prev_layout];2488vk_image_barriers[i].newLayout = RD_TO_VK_LAYOUT[p_texture_barriers[i].next_layout];2489vk_image_barriers[i].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;2490vk_image_barriers[i].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;2491vk_image_barriers[i].image = tex_info->vk_view_create_info.image;2492vk_image_barriers[i].subresourceRange.aspectMask = (VkImageAspectFlags)p_texture_barriers[i].subresources.aspect;2493vk_image_barriers[i].subresourceRange.baseMipLevel = p_texture_barriers[i].subresources.base_mipmap;2494vk_image_barriers[i].subresourceRange.levelCount = p_texture_barriers[i].subresources.mipmap_count;2495vk_image_barriers[i].subresourceRange.baseArrayLayer = p_texture_barriers[i].subresources.base_layer;2496vk_image_barriers[i].subresourceRange.layerCount = p_texture_barriers[i].subresources.layer_count;2497}24982499#if PRINT_NATIVE_COMMANDS2500print_line(vformat("vkCmdPipelineBarrier MEMORY %d BUFFER %d TEXTURE %d", p_memory_barriers.size(), p_buffer_barriers.size(), p_texture_barriers.size()));2501for (uint32_t i = 0; i < p_memory_barriers.size(); i++) {2502print_line(vformat(" VkMemoryBarrier #%d src 0x%uX dst 0x%uX", i, vk_memory_barriers[i].srcAccessMask, vk_memory_barriers[i].dstAccessMask));2503}25042505for (uint32_t i = 0; i < p_buffer_barriers.size(); i++) {2506print_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)));2507}25082509for (uint32_t i = 0; i < p_texture_barriers.size(); i++) {2510print_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,2511uint64_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,2512vk_image_barriers[i].subresourceRange.baseArrayLayer, vk_image_barriers[i].subresourceRange.layerCount));2513}2514#endif25152516const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;2517vkCmdPipelineBarrier(2518command_buffer->vk_command_buffer,2519_rd_to_vk_pipeline_stages(p_src_stages),2520_rd_to_vk_pipeline_stages(p_dst_stages),25210,2522p_memory_barriers.size(), vk_memory_barriers,2523p_buffer_barriers.size(), vk_buffer_barriers,2524p_texture_barriers.size(), vk_image_barriers);2525}25262527/****************/2528/**** FENCES ****/2529/****************/25302531RDD::FenceID RenderingDeviceDriverVulkan::fence_create() {2532VkFence vk_fence = VK_NULL_HANDLE;2533VkFenceCreateInfo create_info = {};2534create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;2535VkResult err = vkCreateFence(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FENCE), &vk_fence);2536ERR_FAIL_COND_V(err != VK_SUCCESS, FenceID());25372538Fence *fence = memnew(Fence);2539fence->vk_fence = vk_fence;2540fence->queue_signaled_from = nullptr;2541return FenceID(fence);2542}25432544Error RenderingDeviceDriverVulkan::fence_wait(FenceID p_fence) {2545Fence *fence = (Fence *)(p_fence.id);2546VkResult fence_status = vkGetFenceStatus(vk_device, fence->vk_fence);2547if (fence_status == VK_NOT_READY) {2548VkResult err = vkWaitForFences(vk_device, 1, &fence->vk_fence, VK_TRUE, UINT64_MAX);2549ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED);2550}25512552VkResult err = vkResetFences(vk_device, 1, &fence->vk_fence);2553ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED);25542555if (fence->queue_signaled_from != nullptr) {2556// Release all semaphores that the command queue associated to the fence waited on the last time it was submitted.2557LocalVector<Pair<Fence *, uint32_t>> &pairs = fence->queue_signaled_from->image_semaphores_for_fences;2558uint32_t i = 0;2559while (i < pairs.size()) {2560if (pairs[i].first == fence) {2561_release_image_semaphore(fence->queue_signaled_from, pairs[i].second, true);2562fence->queue_signaled_from->free_image_semaphores.push_back(pairs[i].second);2563pairs.remove_at(i);2564} else {2565i++;2566}2567}25682569fence->queue_signaled_from = nullptr;2570}25712572return OK;2573}25742575void RenderingDeviceDriverVulkan::fence_free(FenceID p_fence) {2576Fence *fence = (Fence *)(p_fence.id);2577vkDestroyFence(vk_device, fence->vk_fence, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FENCE));2578memdelete(fence);2579}25802581/********************/2582/**** SEMAPHORES ****/2583/********************/25842585RDD::SemaphoreID RenderingDeviceDriverVulkan::semaphore_create() {2586VkSemaphore semaphore = VK_NULL_HANDLE;2587VkSemaphoreCreateInfo create_info = {};2588create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;2589VkResult err = vkCreateSemaphore(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE), &semaphore);2590ERR_FAIL_COND_V(err != VK_SUCCESS, SemaphoreID());25912592return SemaphoreID(semaphore);2593}25942595void RenderingDeviceDriverVulkan::semaphore_free(SemaphoreID p_semaphore) {2596vkDestroySemaphore(vk_device, VkSemaphore(p_semaphore.id), VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE));2597}25982599/******************/2600/**** COMMANDS ****/2601/******************/26022603// ----- QUEUE FAMILY -----26042605RDD::CommandQueueFamilyID RenderingDeviceDriverVulkan::command_queue_family_get(BitField<CommandQueueFamilyBits> p_cmd_queue_family_bits, RenderingContextDriver::SurfaceID p_surface) {2606// Pick the queue with the least amount of bits that can fulfill the requirements.2607VkQueueFlags picked_queue_flags = VK_QUEUE_FLAG_BITS_MAX_ENUM;2608uint32_t picked_family_index = UINT_MAX;2609for (uint32_t i = 0; i < queue_family_properties.size(); i++) {2610if (queue_families[i].is_empty()) {2611// Ignore empty queue families.2612continue;2613}26142615if (p_surface != 0 && !context_driver->queue_family_supports_present(physical_device, i, p_surface)) {2616// Present is not an actual bit but something that must be queried manually.2617continue;2618}26192620// Preferring a queue with less bits will get us closer to getting a queue that performs better for our requirements.2621// For example, dedicated compute and transfer queues are usually indicated as such.2622const VkQueueFlags option_queue_flags = queue_family_properties[i].queueFlags;2623const bool includes_all_bits = p_cmd_queue_family_bits.get_shared(option_queue_flags) == p_cmd_queue_family_bits;2624const bool prefer_less_bits = option_queue_flags < picked_queue_flags;2625if (includes_all_bits && prefer_less_bits) {2626picked_family_index = i;2627picked_queue_flags = option_queue_flags;2628}2629}26302631if (picked_family_index >= queue_family_properties.size()) {2632return CommandQueueFamilyID();2633}26342635// Since 0 is a valid index and we use 0 as the error case, we make the index start from 1 instead.2636return CommandQueueFamilyID(picked_family_index + 1);2637}26382639// ----- QUEUE -----26402641RDD::CommandQueueID RenderingDeviceDriverVulkan::command_queue_create(CommandQueueFamilyID p_cmd_queue_family, bool p_identify_as_main_queue) {2642DEV_ASSERT(p_cmd_queue_family.id != 0);26432644// Make a virtual queue on top of a real queue. Use the queue from the family with the least amount of virtual queues created.2645uint32_t family_index = p_cmd_queue_family.id - 1;2646TightLocalVector<Queue> &queue_family = queue_families[family_index];2647uint32_t picked_queue_index = UINT_MAX;2648uint32_t picked_virtual_count = UINT_MAX;2649for (uint32_t i = 0; i < queue_family.size(); i++) {2650if (queue_family[i].virtual_count < picked_virtual_count) {2651picked_queue_index = i;2652picked_virtual_count = queue_family[i].virtual_count;2653}2654}26552656ERR_FAIL_COND_V_MSG(picked_queue_index >= queue_family.size(), CommandQueueID(), "A queue in the picked family could not be found.");26572658#if defined(SWAPPY_FRAME_PACING_ENABLED)2659if (swappy_frame_pacer_enable) {2660VkQueue selected_queue;2661vkGetDeviceQueue(vk_device, family_index, picked_queue_index, &selected_queue);2662SwappyVk_setQueueFamilyIndex(vk_device, selected_queue, family_index);2663}2664#endif26652666// Create the virtual queue.2667CommandQueue *command_queue = memnew(CommandQueue);2668command_queue->queue_family = family_index;2669command_queue->queue_index = picked_queue_index;2670queue_family[picked_queue_index].virtual_count++;26712672// If is was identified as the main queue and a hook is active, indicate it as such to the hook.2673if (p_identify_as_main_queue && (VulkanHooks::get_singleton() != nullptr)) {2674VulkanHooks::get_singleton()->set_direct_queue_family_and_index(family_index, picked_queue_index);2675}26762677return CommandQueueID(command_queue);2678}26792680Error 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) {2681DEV_ASSERT(p_cmd_queue.id != 0);26822683VkResult err;2684CommandQueue *command_queue = (CommandQueue *)(p_cmd_queue.id);2685Queue &device_queue = queue_families[command_queue->queue_family][command_queue->queue_index];2686Fence *fence = (Fence *)(p_cmd_fence.id);2687VkFence vk_fence = (fence != nullptr) ? fence->vk_fence : VK_NULL_HANDLE;26882689thread_local LocalVector<VkSemaphore> wait_semaphores;2690thread_local LocalVector<VkPipelineStageFlags> wait_semaphores_stages;2691wait_semaphores.clear();2692wait_semaphores_stages.clear();26932694if (!command_queue->pending_semaphores_for_execute.is_empty()) {2695for (uint32_t i = 0; i < command_queue->pending_semaphores_for_execute.size(); i++) {2696VkSemaphore wait_semaphore = command_queue->image_semaphores[command_queue->pending_semaphores_for_execute[i]];2697wait_semaphores.push_back(wait_semaphore);2698wait_semaphores_stages.push_back(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);2699}27002701command_queue->pending_semaphores_for_execute.clear();2702}27032704for (uint32_t i = 0; i < p_wait_semaphores.size(); i++) {2705// FIXME: Allow specifying the stage mask in more detail.2706wait_semaphores.push_back(VkSemaphore(p_wait_semaphores[i].id));2707wait_semaphores_stages.push_back(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);2708}27092710if (p_cmd_buffers.size() > 0) {2711thread_local LocalVector<VkCommandBuffer> command_buffers;2712thread_local LocalVector<VkSemaphore> present_semaphores;2713thread_local LocalVector<VkSemaphore> signal_semaphores;2714command_buffers.clear();2715present_semaphores.clear();2716signal_semaphores.clear();27172718for (uint32_t i = 0; i < p_cmd_buffers.size(); i++) {2719const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)(p_cmd_buffers[i].id);2720command_buffers.push_back(command_buffer->vk_command_buffer);2721}27222723for (uint32_t i = 0; i < p_cmd_semaphores.size(); i++) {2724signal_semaphores.push_back(VkSemaphore(p_cmd_semaphores[i].id));2725}27262727for (uint32_t i = 0; i < p_swap_chains.size(); i++) {2728const SwapChain *swap_chain = (const SwapChain *)(p_swap_chains[i].id);2729VkSemaphore semaphore = swap_chain->present_semaphores[swap_chain->image_index];2730present_semaphores.push_back(semaphore);2731signal_semaphores.push_back(semaphore);2732}27332734VkSubmitInfo submit_info = {};2735submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;2736submit_info.waitSemaphoreCount = wait_semaphores.size();2737submit_info.pWaitSemaphores = wait_semaphores.ptr();2738submit_info.pWaitDstStageMask = wait_semaphores_stages.ptr();2739submit_info.commandBufferCount = command_buffers.size();2740submit_info.pCommandBuffers = command_buffers.ptr();2741submit_info.signalSemaphoreCount = signal_semaphores.size();2742submit_info.pSignalSemaphores = signal_semaphores.ptr();27432744device_queue.submit_mutex.lock();2745err = vkQueueSubmit(device_queue.queue, 1, &submit_info, vk_fence);2746device_queue.submit_mutex.unlock();27472748if (err == VK_ERROR_DEVICE_LOST) {2749print_lost_device_info();2750CRASH_NOW_MSG("Vulkan device was lost.");2751}2752ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED);27532754if (fence != nullptr && !command_queue->pending_semaphores_for_fence.is_empty()) {2755fence->queue_signaled_from = command_queue;27562757// Indicate to the fence that it should release the semaphores that were waited on this submission the next time the fence is waited on.2758for (uint32_t i = 0; i < command_queue->pending_semaphores_for_fence.size(); i++) {2759command_queue->image_semaphores_for_fences.push_back({ fence, command_queue->pending_semaphores_for_fence[i] });2760}27612762command_queue->pending_semaphores_for_fence.clear();2763}27642765if (!present_semaphores.is_empty()) {2766// If command buffers were executed, swap chains must wait on the present semaphore used by the command queue.2767wait_semaphores = present_semaphores;2768}2769}27702771if (p_swap_chains.size() > 0) {2772thread_local LocalVector<VkSwapchainKHR> swapchains;2773thread_local LocalVector<uint32_t> image_indices;2774thread_local LocalVector<VkResult> results;2775swapchains.clear();2776image_indices.clear();27772778for (uint32_t i = 0; i < p_swap_chains.size(); i++) {2779SwapChain *swap_chain = (SwapChain *)(p_swap_chains[i].id);2780swapchains.push_back(swap_chain->vk_swapchain);2781DEV_ASSERT(swap_chain->image_index < swap_chain->images.size());2782image_indices.push_back(swap_chain->image_index);2783}27842785results.resize(swapchains.size());27862787VkPresentInfoKHR present_info = {};2788present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;2789present_info.waitSemaphoreCount = wait_semaphores.size();2790present_info.pWaitSemaphores = wait_semaphores.ptr();2791present_info.swapchainCount = swapchains.size();2792present_info.pSwapchains = swapchains.ptr();2793present_info.pImageIndices = image_indices.ptr();2794present_info.pResults = results.ptr();27952796device_queue.submit_mutex.lock();2797#if defined(SWAPPY_FRAME_PACING_ENABLED)2798if (swappy_frame_pacer_enable) {2799err = SwappyVk_queuePresent(device_queue.queue, &present_info);2800} else {2801err = device_functions.QueuePresentKHR(device_queue.queue, &present_info);2802}2803#else2804err = device_functions.QueuePresentKHR(device_queue.queue, &present_info);2805#endif28062807device_queue.submit_mutex.unlock();28082809// 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.2810bool any_result_is_out_of_date = false;2811for (uint32_t i = 0; i < p_swap_chains.size(); i++) {2812SwapChain *swap_chain = (SwapChain *)(p_swap_chains[i].id);2813swap_chain->image_index = UINT_MAX;2814if (results[i] == VK_ERROR_OUT_OF_DATE_KHR) {2815context_driver->surface_set_needs_resize(swap_chain->surface, true);2816any_result_is_out_of_date = true;2817}2818}28192820if (any_result_is_out_of_date || err == VK_ERROR_OUT_OF_DATE_KHR) {2821// It is possible for presentation to fail with out of date while acquire might've succeeded previously. This case2822// will be considered a silent failure as it can be triggered easily by resizing a window in the OS natively.2823return FAILED;2824}28252826// Handling VK_SUBOPTIMAL_KHR the same as VK_SUCCESS is completely intentional.2827//2828// Godot does not currently support native rotation in Android when creating the swap chain. It intentionally uses2829// VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR instead of the current transform bits available in the surface capabilities.2830// Choosing the transform that leads to optimal presentation leads to distortion that makes the application unusable,2831// as the rotation of all the content is not handled at the moment.2832//2833// VK_SUBOPTIMAL_KHR is accepted as a successful case even if it's not the most efficient solution to work around this2834// problem. This behavior should not be changed unless the swap chain recreation uses the current transform bits, as2835// it'll lead to very low performance in Android by entering an endless loop where it'll always resize the swap chain2836// every frame.28372838ERR_FAIL_COND_V_MSG(2839err != VK_SUCCESS && err != VK_SUBOPTIMAL_KHR,2840FAILED,2841"QueuePresentKHR failed with error: " + get_vulkan_result(err));2842}28432844return OK;2845}28462847void RenderingDeviceDriverVulkan::command_queue_free(CommandQueueID p_cmd_queue) {2848DEV_ASSERT(p_cmd_queue);28492850CommandQueue *command_queue = (CommandQueue *)(p_cmd_queue.id);28512852// Erase all the semaphores used for image acquisition.2853for (VkSemaphore semaphore : command_queue->image_semaphores) {2854vkDestroySemaphore(vk_device, semaphore, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE));2855}28562857// Retrieve the queue family corresponding to the virtual queue.2858DEV_ASSERT(command_queue->queue_family < queue_families.size());2859TightLocalVector<Queue> &queue_family = queue_families[command_queue->queue_family];28602861// Decrease the virtual queue count.2862DEV_ASSERT(command_queue->queue_index < queue_family.size());2863DEV_ASSERT(queue_family[command_queue->queue_index].virtual_count > 0);2864queue_family[command_queue->queue_index].virtual_count--;28652866// Destroy the virtual queue structure.2867memdelete(command_queue);2868}28692870// ----- POOL -----28712872RDD::CommandPoolID RenderingDeviceDriverVulkan::command_pool_create(CommandQueueFamilyID p_cmd_queue_family, CommandBufferType p_cmd_buffer_type) {2873DEV_ASSERT(p_cmd_queue_family.id != 0);28742875uint32_t family_index = p_cmd_queue_family.id - 1;2876VkCommandPoolCreateInfo cmd_pool_info = {};2877cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;2878cmd_pool_info.queueFamilyIndex = family_index;28792880if (!command_pool_reset_enabled) {2881cmd_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;2882}28832884VkCommandPool vk_command_pool = VK_NULL_HANDLE;2885VkResult res = vkCreateCommandPool(vk_device, &cmd_pool_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_COMMAND_POOL), &vk_command_pool);2886ERR_FAIL_COND_V_MSG(res, CommandPoolID(), "vkCreateCommandPool failed with error " + itos(res) + ".");28872888CommandPool *command_pool = memnew(CommandPool);2889command_pool->vk_command_pool = vk_command_pool;2890command_pool->buffer_type = p_cmd_buffer_type;2891return CommandPoolID(command_pool);2892}28932894bool RenderingDeviceDriverVulkan::command_pool_reset(CommandPoolID p_cmd_pool) {2895DEV_ASSERT(p_cmd_pool);28962897CommandPool *command_pool = (CommandPool *)(p_cmd_pool.id);2898VkResult err = vkResetCommandPool(vk_device, command_pool->vk_command_pool, 0);2899ERR_FAIL_COND_V_MSG(err, false, "vkResetCommandPool failed with error " + itos(err) + ".");29002901return true;2902}29032904void RenderingDeviceDriverVulkan::command_pool_free(CommandPoolID p_cmd_pool) {2905DEV_ASSERT(p_cmd_pool);29062907CommandPool *command_pool = (CommandPool *)(p_cmd_pool.id);2908for (CommandBufferInfo *command_buffer : command_pool->command_buffers_created) {2909VersatileResource::free(resources_allocator, command_buffer);2910}29112912vkDestroyCommandPool(vk_device, command_pool->vk_command_pool, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_COMMAND_POOL));2913memdelete(command_pool);2914}29152916// ----- BUFFER -----29172918RDD::CommandBufferID RenderingDeviceDriverVulkan::command_buffer_create(CommandPoolID p_cmd_pool) {2919DEV_ASSERT(p_cmd_pool);29202921CommandPool *command_pool = (CommandPool *)(p_cmd_pool.id);2922VkCommandBufferAllocateInfo cmd_buf_info = {};2923cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;2924cmd_buf_info.commandPool = command_pool->vk_command_pool;2925cmd_buf_info.commandBufferCount = 1;29262927if (command_pool->buffer_type == COMMAND_BUFFER_TYPE_SECONDARY) {2928cmd_buf_info.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;2929} else {2930cmd_buf_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;2931}29322933VkCommandBuffer vk_command_buffer = VK_NULL_HANDLE;2934VkResult err = vkAllocateCommandBuffers(vk_device, &cmd_buf_info, &vk_command_buffer);2935ERR_FAIL_COND_V_MSG(err, CommandBufferID(), "vkAllocateCommandBuffers failed with error " + itos(err) + ".");29362937CommandBufferInfo *command_buffer = VersatileResource::allocate<CommandBufferInfo>(resources_allocator);2938command_buffer->vk_command_buffer = vk_command_buffer;2939command_pool->command_buffers_created.push_back(command_buffer);2940return CommandBufferID(command_buffer);2941}29422943bool RenderingDeviceDriverVulkan::command_buffer_begin(CommandBufferID p_cmd_buffer) {2944CommandBufferInfo *command_buffer = (CommandBufferInfo *)(p_cmd_buffer.id);29452946VkCommandBufferBeginInfo cmd_buf_begin_info = {};2947cmd_buf_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;2948cmd_buf_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;29492950VkResult err = vkBeginCommandBuffer(command_buffer->vk_command_buffer, &cmd_buf_begin_info);2951ERR_FAIL_COND_V_MSG(err, false, "vkBeginCommandBuffer failed with error " + itos(err) + ".");29522953return true;2954}29552956bool RenderingDeviceDriverVulkan::command_buffer_begin_secondary(CommandBufferID p_cmd_buffer, RenderPassID p_render_pass, uint32_t p_subpass, FramebufferID p_framebuffer) {2957Framebuffer *framebuffer = (Framebuffer *)(p_framebuffer.id);2958RenderPassInfo *render_pass = (RenderPassInfo *)(p_render_pass.id);2959CommandBufferInfo *command_buffer = (CommandBufferInfo *)(p_cmd_buffer.id);29602961VkCommandBufferInheritanceInfo inheritance_info = {};2962inheritance_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;2963inheritance_info.renderPass = render_pass->vk_render_pass;2964inheritance_info.subpass = p_subpass;2965inheritance_info.framebuffer = framebuffer->vk_framebuffer;29662967VkCommandBufferBeginInfo cmd_buf_begin_info = {};2968cmd_buf_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;2969cmd_buf_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;2970cmd_buf_begin_info.pInheritanceInfo = &inheritance_info;29712972VkResult err = vkBeginCommandBuffer(command_buffer->vk_command_buffer, &cmd_buf_begin_info);2973ERR_FAIL_COND_V_MSG(err, false, "vkBeginCommandBuffer failed with error " + itos(err) + ".");29742975return true;2976}29772978void RenderingDeviceDriverVulkan::command_buffer_end(CommandBufferID p_cmd_buffer) {2979CommandBufferInfo *command_buffer = (CommandBufferInfo *)(p_cmd_buffer.id);2980vkEndCommandBuffer(command_buffer->vk_command_buffer);2981}29822983void RenderingDeviceDriverVulkan::command_buffer_execute_secondary(CommandBufferID p_cmd_buffer, VectorView<CommandBufferID> p_secondary_cmd_buffers) {2984thread_local LocalVector<VkCommandBuffer> secondary_command_buffers;2985CommandBufferInfo *command_buffer = (CommandBufferInfo *)(p_cmd_buffer.id);2986secondary_command_buffers.resize(p_secondary_cmd_buffers.size());2987for (uint32_t i = 0; i < p_secondary_cmd_buffers.size(); i++) {2988CommandBufferInfo *secondary_command_buffer = (CommandBufferInfo *)(p_secondary_cmd_buffers[i].id);2989secondary_command_buffers[i] = secondary_command_buffer->vk_command_buffer;2990}29912992vkCmdExecuteCommands(command_buffer->vk_command_buffer, p_secondary_cmd_buffers.size(), secondary_command_buffers.ptr());2993}29942995/********************/2996/**** SWAP CHAIN ****/2997/********************/29982999void RenderingDeviceDriverVulkan::_swap_chain_release(SwapChain *swap_chain) {3000// Destroy views and framebuffers associated to the swapchain's images.3001for (FramebufferID framebuffer : swap_chain->framebuffers) {3002framebuffer_free(framebuffer);3003}30043005for (VkImageView view : swap_chain->image_views) {3006vkDestroyImageView(vk_device, view, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW));3007}30083009swap_chain->image_index = UINT_MAX;3010swap_chain->images.clear();3011swap_chain->image_views.clear();3012swap_chain->framebuffers.clear();30133014if (swap_chain->vk_swapchain != VK_NULL_HANDLE) {3015#if defined(SWAPPY_FRAME_PACING_ENABLED)3016if (swappy_frame_pacer_enable) {3017// Swappy has a bug where the ANativeWindow will be leaked if we call3018// SwappyVk_destroySwapchain, so we must release it by hand.3019SwappyVk_setWindow(vk_device, swap_chain->vk_swapchain, nullptr);3020SwappyVk_destroySwapchain(vk_device, swap_chain->vk_swapchain);3021}3022#endif3023device_functions.DestroySwapchainKHR(vk_device, swap_chain->vk_swapchain, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SWAPCHAIN_KHR));3024swap_chain->vk_swapchain = VK_NULL_HANDLE;3025}30263027for (uint32_t i = 0; i < swap_chain->command_queues_acquired.size(); i++) {3028_recreate_image_semaphore(swap_chain->command_queues_acquired[i], swap_chain->command_queues_acquired_semaphores[i], false);3029}30303031swap_chain->command_queues_acquired.clear();3032swap_chain->command_queues_acquired_semaphores.clear();30333034for (VkSemaphore semaphore : swap_chain->present_semaphores) {3035vkDestroySemaphore(vk_device, semaphore, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE));3036}30373038swap_chain->present_semaphores.clear();3039}30403041RenderingDeviceDriver::SwapChainID RenderingDeviceDriverVulkan::swap_chain_create(RenderingContextDriver::SurfaceID p_surface) {3042DEV_ASSERT(p_surface != 0);30433044RenderingContextDriverVulkan::Surface *surface = (RenderingContextDriverVulkan::Surface *)(p_surface);3045const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get();30463047// Retrieve the formats supported by the surface.3048uint32_t format_count = 0;3049VkResult err = functions.GetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface->vk_surface, &format_count, nullptr);3050ERR_FAIL_COND_V(err != VK_SUCCESS, SwapChainID());30513052TightLocalVector<VkSurfaceFormatKHR> formats;3053formats.resize(format_count);3054err = functions.GetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface->vk_surface, &format_count, formats.ptr());3055ERR_FAIL_COND_V(err != VK_SUCCESS, SwapChainID());30563057VkFormat format = VK_FORMAT_UNDEFINED;3058VkColorSpaceKHR color_space = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;3059if (format_count == 1 && formats[0].format == VK_FORMAT_UNDEFINED) {3060// If the format list includes just one entry of VK_FORMAT_UNDEFINED, the surface has no preferred format.3061format = VK_FORMAT_B8G8R8A8_UNORM;3062color_space = formats[0].colorSpace;3063} else if (format_count > 0) {3064// Use one of the supported formats, prefer B8G8R8A8_UNORM.3065const VkFormat preferred_format = VK_FORMAT_B8G8R8A8_UNORM;3066const VkFormat second_format = VK_FORMAT_R8G8B8A8_UNORM;3067for (uint32_t i = 0; i < format_count; i++) {3068if (formats[i].format == preferred_format || formats[i].format == second_format) {3069format = formats[i].format;3070if (formats[i].format == preferred_format) {3071// This is the preferred format, stop searching.3072break;3073}3074}3075}3076}30773078// No formats are supported.3079ERR_FAIL_COND_V_MSG(format == VK_FORMAT_UNDEFINED, SwapChainID(), "Surface did not return any valid formats.");30803081// Create the render pass for the chosen format.3082VkAttachmentDescription2KHR attachment = {};3083attachment.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR;3084attachment.format = format;3085attachment.samples = VK_SAMPLE_COUNT_1_BIT;3086attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;3087attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;3088attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;3089attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;3090attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;3091attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;30923093VkAttachmentReference2KHR color_reference = {};3094color_reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;3095color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;30963097VkSubpassDescription2KHR subpass = {};3098subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR;3099subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;3100subpass.colorAttachmentCount = 1;3101subpass.pColorAttachments = &color_reference;31023103VkRenderPassCreateInfo2KHR pass_info = {};3104pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR;3105pass_info.attachmentCount = 1;3106pass_info.pAttachments = &attachment;3107pass_info.subpassCount = 1;3108pass_info.pSubpasses = &subpass;31093110VkRenderPass vk_render_pass = VK_NULL_HANDLE;3111err = _create_render_pass(vk_device, &pass_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_RENDER_PASS), &vk_render_pass);3112ERR_FAIL_COND_V(err != VK_SUCCESS, SwapChainID());31133114RenderPassInfo *render_pass_info = VersatileResource::allocate<RenderPassInfo>(resources_allocator);3115render_pass_info->vk_render_pass = vk_render_pass;31163117SwapChain *swap_chain = memnew(SwapChain);3118swap_chain->surface = p_surface;3119swap_chain->format = format;3120swap_chain->color_space = color_space;3121swap_chain->render_pass = RenderPassID(render_pass_info);3122return SwapChainID(swap_chain);3123}31243125Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, uint32_t p_desired_framebuffer_count) {3126DEV_ASSERT(p_cmd_queue.id != 0);3127DEV_ASSERT(p_swap_chain.id != 0);31283129CommandQueue *command_queue = (CommandQueue *)(p_cmd_queue.id);3130SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);31313132// Release all current contents of the swap chain.3133_swap_chain_release(swap_chain);31343135// Validate if the command queue being used supports creating the swap chain for this surface.3136const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get();3137if (!context_driver->queue_family_supports_present(physical_device, command_queue->queue_family, swap_chain->surface)) {3138ERR_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"3139"previous errors & try launching with --gpu-validation.");3140}31413142// Retrieve the surface's capabilities.3143RenderingContextDriverVulkan::Surface *surface = (RenderingContextDriverVulkan::Surface *)(swap_chain->surface);3144VkSurfaceCapabilitiesKHR surface_capabilities = {};3145VkResult err = functions.GetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface->vk_surface, &surface_capabilities);3146ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);31473148// No swapchain yet, this is the first time we're creating it.3149if (!swap_chain->vk_swapchain) {3150if (surface_capabilities.currentExtent.width == 0xFFFFFFFF) {3151// The current extent is currently undefined, so the current surface width and height will be clamped to the surface's capabilities.3152// We make sure to overwrite surface_capabilities.currentExtent.width so that the same check further below3153// does not set extent.width = CLAMP( surface->width, ... ) on the first run of this function, because3154// that'd be potentially unswapped.3155surface_capabilities.currentExtent.width = CLAMP(surface->width, surface_capabilities.minImageExtent.width, surface_capabilities.maxImageExtent.width);3156surface_capabilities.currentExtent.height = CLAMP(surface->height, surface_capabilities.minImageExtent.height, surface_capabilities.maxImageExtent.height);3157}31583159// We must SWAP() only once otherwise we'll keep ping-ponging between3160// the right and wrong resolutions after multiple calls to swap_chain_resize().3161if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR ||3162surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {3163// Swap to get identity width and height.3164SWAP(surface_capabilities.currentExtent.width, surface_capabilities.currentExtent.height);3165}3166}31673168VkExtent2D extent;3169if (surface_capabilities.currentExtent.width == 0xFFFFFFFF) {3170// The current extent is currently undefined, so the current surface width and height will be clamped to the surface's capabilities.3171// 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.3172extent.width = CLAMP(surface->width, surface_capabilities.minImageExtent.width, surface_capabilities.maxImageExtent.width);3173extent.height = CLAMP(surface->height, surface_capabilities.minImageExtent.height, surface_capabilities.maxImageExtent.height);3174} else {3175// Grab the dimensions from the current extent.3176extent = surface_capabilities.currentExtent;3177surface->width = extent.width;3178surface->height = extent.height;3179}31803181if (surface->width == 0 || surface->height == 0) {3182// The surface doesn't have valid dimensions, so we can't create a swap chain.3183return ERR_SKIP;3184}31853186// Find what present modes are supported.3187TightLocalVector<VkPresentModeKHR> present_modes;3188uint32_t present_modes_count = 0;3189err = functions.GetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface->vk_surface, &present_modes_count, nullptr);3190ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);31913192present_modes.resize(present_modes_count);3193err = functions.GetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface->vk_surface, &present_modes_count, present_modes.ptr());3194ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);31953196// Choose the present mode based on the display server setting.3197VkPresentModeKHR present_mode = VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR;3198String present_mode_name = "Enabled";3199switch (surface->vsync_mode) {3200case DisplayServer::VSYNC_MAILBOX:3201present_mode = VK_PRESENT_MODE_MAILBOX_KHR;3202present_mode_name = "Mailbox";3203break;3204case DisplayServer::VSYNC_ADAPTIVE:3205present_mode = VK_PRESENT_MODE_FIFO_RELAXED_KHR;3206present_mode_name = "Adaptive";3207break;3208case DisplayServer::VSYNC_ENABLED:3209present_mode = VK_PRESENT_MODE_FIFO_KHR;3210present_mode_name = "Enabled";3211break;3212case DisplayServer::VSYNC_DISABLED:3213present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;3214present_mode_name = "Disabled";3215break;3216}32173218bool present_mode_available = present_modes.has(present_mode);3219if (!present_mode_available) {3220// Present mode is not available, fall back to FIFO which is guaranteed to be supported.3221WARN_PRINT(vformat("The requested V-Sync mode %s is not available. Falling back to V-Sync mode Enabled.", present_mode_name));3222surface->vsync_mode = DisplayServer::VSYNC_ENABLED;3223present_mode = VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR;3224}32253226// Clamp the desired image count to the surface's capabilities.3227uint32_t desired_swapchain_images = MAX(p_desired_framebuffer_count, surface_capabilities.minImageCount);3228if (surface_capabilities.maxImageCount > 0) {3229// 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.3230desired_swapchain_images = MIN(desired_swapchain_images, surface_capabilities.maxImageCount);3231}32323233// Refer to the comment in command_queue_present() for more details.3234VkSurfaceTransformFlagBitsKHR surface_transform_bits = surface_capabilities.currentTransform;32353236VkCompositeAlphaFlagBitsKHR composite_alpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;3237if (OS::get_singleton()->is_layered_allowed() || !(surface_capabilities.supportedCompositeAlpha & composite_alpha)) {3238// Find a supported composite alpha mode - one of these is guaranteed to be set.3239VkCompositeAlphaFlagBitsKHR composite_alpha_flags[4] = {3240VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,3241VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR,3242VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,3243VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR3244};32453246for (uint32_t i = 0; i < ARRAY_SIZE(composite_alpha_flags); i++) {3247if (surface_capabilities.supportedCompositeAlpha & composite_alpha_flags[i]) {3248composite_alpha = composite_alpha_flags[i];3249break;3250}3251}3252has_comp_alpha[(uint64_t)p_cmd_queue.id] = (composite_alpha != VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR);3253}32543255VkSwapchainCreateInfoKHR swap_create_info = {};3256swap_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;3257swap_create_info.surface = surface->vk_surface;3258swap_create_info.minImageCount = desired_swapchain_images;3259swap_create_info.imageFormat = swap_chain->format;3260swap_create_info.imageColorSpace = swap_chain->color_space;3261swap_create_info.imageExtent = extent;3262swap_create_info.imageArrayLayers = 1;3263swap_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;3264swap_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;3265swap_create_info.preTransform = surface_transform_bits;3266switch (swap_create_info.preTransform) {3267case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:3268swap_chain->pre_transform_rotation_degrees = 0;3269break;3270case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:3271swap_chain->pre_transform_rotation_degrees = 90;3272break;3273case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:3274swap_chain->pre_transform_rotation_degrees = 180;3275break;3276case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:3277swap_chain->pre_transform_rotation_degrees = 270;3278break;3279default:3280WARN_PRINT("Unexpected swap_create_info.preTransform = " + itos(swap_create_info.preTransform) + ".");3281swap_chain->pre_transform_rotation_degrees = 0;3282break;3283}3284swap_create_info.compositeAlpha = composite_alpha;3285swap_create_info.presentMode = present_mode;3286swap_create_info.clipped = true;3287err = device_functions.CreateSwapchainKHR(vk_device, &swap_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SWAPCHAIN_KHR), &swap_chain->vk_swapchain);3288ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);32893290#if defined(SWAPPY_FRAME_PACING_ENABLED)3291if (swappy_frame_pacer_enable) {3292SwappyVk_initAndGetRefreshCycleDuration(get_jni_env(), static_cast<OS_Android *>(OS::get_singleton())->get_godot_java()->get_activity(), physical_device,3293vk_device, swap_chain->vk_swapchain, &swap_chain->refresh_duration);3294SwappyVk_setWindow(vk_device, swap_chain->vk_swapchain, static_cast<OS_Android *>(OS::get_singleton())->get_native_window());3295SwappyVk_setSwapIntervalNS(vk_device, swap_chain->vk_swapchain, swap_chain->refresh_duration);32963297enum SwappyModes {3298PIPELINE_FORCED_ON,3299AUTO_FPS_PIPELINE_FORCED_ON,3300AUTO_FPS_AUTO_PIPELINE,3301};33023303switch (swappy_mode) {3304case PIPELINE_FORCED_ON:3305SwappyVk_setAutoSwapInterval(true);3306SwappyVk_setAutoPipelineMode(true);3307break;3308case AUTO_FPS_PIPELINE_FORCED_ON:3309SwappyVk_setAutoSwapInterval(true);3310SwappyVk_setAutoPipelineMode(false);3311break;3312case AUTO_FPS_AUTO_PIPELINE:3313SwappyVk_setAutoSwapInterval(false);3314SwappyVk_setAutoPipelineMode(false);3315break;3316}3317}3318#endif33193320uint32_t image_count = 0;3321err = device_functions.GetSwapchainImagesKHR(vk_device, swap_chain->vk_swapchain, &image_count, nullptr);3322ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);33233324swap_chain->images.resize(image_count);3325err = device_functions.GetSwapchainImagesKHR(vk_device, swap_chain->vk_swapchain, &image_count, swap_chain->images.ptr());3326ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);33273328VkImageViewCreateInfo view_create_info = {};3329view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;3330view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;3331view_create_info.format = swap_chain->format;3332view_create_info.components.r = VK_COMPONENT_SWIZZLE_R;3333view_create_info.components.g = VK_COMPONENT_SWIZZLE_G;3334view_create_info.components.b = VK_COMPONENT_SWIZZLE_B;3335view_create_info.components.a = VK_COMPONENT_SWIZZLE_A;3336view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;3337view_create_info.subresourceRange.levelCount = 1;3338view_create_info.subresourceRange.layerCount = 1;33393340swap_chain->image_views.reserve(image_count);33413342VkImageView image_view;3343for (uint32_t i = 0; i < image_count; i++) {3344view_create_info.image = swap_chain->images[i];3345err = vkCreateImageView(vk_device, &view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &image_view);3346ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);33473348swap_chain->image_views.push_back(image_view);3349}33503351swap_chain->framebuffers.reserve(image_count);33523353const RenderPassInfo *render_pass = (const RenderPassInfo *)(swap_chain->render_pass.id);3354VkFramebufferCreateInfo fb_create_info = {};3355fb_create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;3356fb_create_info.renderPass = render_pass->vk_render_pass;3357fb_create_info.attachmentCount = 1;3358fb_create_info.width = surface->width;3359fb_create_info.height = surface->height;3360fb_create_info.layers = 1;33613362VkFramebuffer vk_framebuffer;3363for (uint32_t i = 0; i < image_count; i++) {3364fb_create_info.pAttachments = &swap_chain->image_views[i];3365err = vkCreateFramebuffer(vk_device, &fb_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER), &vk_framebuffer);3366ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);33673368Framebuffer *framebuffer = memnew(Framebuffer);3369framebuffer->vk_framebuffer = vk_framebuffer;3370framebuffer->swap_chain_image = swap_chain->images[i];3371framebuffer->swap_chain_image_subresource_range = view_create_info.subresourceRange;3372swap_chain->framebuffers.push_back(RDD::FramebufferID(framebuffer));3373}33743375VkSemaphore vk_semaphore = VK_NULL_HANDLE;3376for (uint32_t i = 0; i < image_count; i++) {3377VkSemaphoreCreateInfo create_info = {};3378create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;33793380err = vkCreateSemaphore(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE), &vk_semaphore);3381ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED);33823383swap_chain->present_semaphores.push_back(vk_semaphore);3384}33853386// Once everything's been created correctly, indicate the surface no longer needs to be resized.3387context_driver->surface_set_needs_resize(swap_chain->surface, false);33883389return OK;3390}33913392RDD::FramebufferID RenderingDeviceDriverVulkan::swap_chain_acquire_framebuffer(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, bool &r_resize_required) {3393DEV_ASSERT(p_cmd_queue);3394DEV_ASSERT(p_swap_chain);33953396CommandQueue *command_queue = (CommandQueue *)(p_cmd_queue.id);3397SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);3398if ((swap_chain->vk_swapchain == VK_NULL_HANDLE) || context_driver->surface_get_needs_resize(swap_chain->surface)) {3399// The surface does not have a valid swap chain or it indicates it requires a resize.3400r_resize_required = true;3401return FramebufferID();3402}34033404VkResult err;3405VkSemaphore semaphore = VK_NULL_HANDLE;3406uint32_t semaphore_index = 0;3407if (command_queue->free_image_semaphores.is_empty()) {3408// Add a new semaphore if none are free.3409VkSemaphoreCreateInfo create_info = {};3410create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;3411err = vkCreateSemaphore(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE), &semaphore);3412ERR_FAIL_COND_V(err != VK_SUCCESS, FramebufferID());34133414semaphore_index = command_queue->image_semaphores.size();3415command_queue->image_semaphores.push_back(semaphore);3416command_queue->image_semaphores_swap_chains.push_back(swap_chain);3417} else {3418// Pick a free semaphore.3419uint32_t free_index = command_queue->free_image_semaphores.size() - 1;3420semaphore_index = command_queue->free_image_semaphores[free_index];3421command_queue->image_semaphores_swap_chains[semaphore_index] = swap_chain;3422command_queue->free_image_semaphores.remove_at(free_index);3423semaphore = command_queue->image_semaphores[semaphore_index];3424}34253426// Store in the swap chain the acquired semaphore.3427swap_chain->command_queues_acquired.push_back(command_queue);3428swap_chain->command_queues_acquired_semaphores.push_back(semaphore_index);34293430err = device_functions.AcquireNextImageKHR(vk_device, swap_chain->vk_swapchain, UINT64_MAX, semaphore, VK_NULL_HANDLE, &swap_chain->image_index);3431if (err == VK_ERROR_OUT_OF_DATE_KHR) {3432// Out of date leaves the semaphore in a signaled state that will never finish, so it's necessary to recreate it.3433bool semaphore_recreated = _recreate_image_semaphore(command_queue, semaphore_index, true);3434ERR_FAIL_COND_V(!semaphore_recreated, FramebufferID());34353436// Swap chain is out of date and must be recreated.3437r_resize_required = true;3438return FramebufferID();3439} else if (err != VK_SUCCESS && err != VK_SUBOPTIMAL_KHR) {3440// Swap chain failed to present but the reason is unknown.3441// Refer to the comment in command_queue_present() as to why VK_SUBOPTIMAL_KHR is handled the same as VK_SUCCESS.3442return FramebufferID();3443}34443445// Indicate the command queue should wait on these semaphores on the next submission and that it should3446// indicate they're free again on the next fence.3447command_queue->pending_semaphores_for_execute.push_back(semaphore_index);3448command_queue->pending_semaphores_for_fence.push_back(semaphore_index);34493450// Return the corresponding framebuffer to the new current image.3451FramebufferID framebuffer_id = swap_chain->framebuffers[swap_chain->image_index];3452Framebuffer *framebuffer = (Framebuffer *)(framebuffer_id.id);3453framebuffer->swap_chain_acquired = true;3454return framebuffer_id;3455}34563457RDD::RenderPassID RenderingDeviceDriverVulkan::swap_chain_get_render_pass(SwapChainID p_swap_chain) {3458DEV_ASSERT(p_swap_chain.id != 0);34593460SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);3461return swap_chain->render_pass;3462}34633464int RenderingDeviceDriverVulkan::swap_chain_get_pre_rotation_degrees(SwapChainID p_swap_chain) {3465DEV_ASSERT(p_swap_chain.id != 0);34663467SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);3468return swap_chain->pre_transform_rotation_degrees;3469}34703471RDD::DataFormat RenderingDeviceDriverVulkan::swap_chain_get_format(SwapChainID p_swap_chain) {3472DEV_ASSERT(p_swap_chain.id != 0);34733474SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);3475switch (swap_chain->format) {3476case VK_FORMAT_B8G8R8A8_UNORM:3477return DATA_FORMAT_B8G8R8A8_UNORM;3478case VK_FORMAT_R8G8B8A8_UNORM:3479return DATA_FORMAT_R8G8B8A8_UNORM;3480default:3481DEV_ASSERT(false && "Unknown swap chain format.");3482return DATA_FORMAT_MAX;3483}3484}34853486void RenderingDeviceDriverVulkan::swap_chain_set_max_fps(SwapChainID p_swap_chain, int p_max_fps) {3487DEV_ASSERT(p_swap_chain.id != 0);34883489#ifdef SWAPPY_FRAME_PACING_ENABLED3490if (!swappy_frame_pacer_enable) {3491return;3492}34933494SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);3495if (swap_chain->vk_swapchain != VK_NULL_HANDLE) {3496const uint64_t max_time = p_max_fps > 0 ? uint64_t((1000.0 * 1000.0 * 1000.0) / p_max_fps) : 0;3497SwappyVk_setSwapIntervalNS(vk_device, swap_chain->vk_swapchain, MAX(swap_chain->refresh_duration, max_time));3498}3499#endif3500}35013502void RenderingDeviceDriverVulkan::swap_chain_free(SwapChainID p_swap_chain) {3503DEV_ASSERT(p_swap_chain.id != 0);35043505SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);3506_swap_chain_release(swap_chain);35073508if (swap_chain->render_pass) {3509render_pass_free(swap_chain->render_pass);3510}35113512memdelete(swap_chain);3513}35143515/*********************/3516/**** FRAMEBUFFER ****/3517/*********************/35183519RDD::FramebufferID RenderingDeviceDriverVulkan::framebuffer_create(RenderPassID p_render_pass, VectorView<TextureID> p_attachments, uint32_t p_width, uint32_t p_height) {3520RenderPassInfo *render_pass = (RenderPassInfo *)(p_render_pass.id);35213522uint32_t fragment_density_map_offsets_layers = 0;3523VkImageView *vk_img_views = ALLOCA_ARRAY(VkImageView, p_attachments.size());3524for (uint32_t i = 0; i < p_attachments.size(); i++) {3525const TextureInfo *texture = (const TextureInfo *)p_attachments[i].id;3526vk_img_views[i] = texture->vk_view;35273528if (render_pass->uses_fragment_density_map_offsets && (texture->vk_create_info.usage & VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT)) {3529// If the render pass uses the FDM and the usage fits, we store the amount of layers to use it later on the render pass's end.3530fragment_density_map_offsets_layers = texture->vk_create_info.arrayLayers;3531}3532}35333534VkFramebufferCreateInfo framebuffer_create_info = {};3535framebuffer_create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;3536framebuffer_create_info.renderPass = render_pass->vk_render_pass;3537framebuffer_create_info.attachmentCount = p_attachments.size();3538framebuffer_create_info.pAttachments = vk_img_views;3539framebuffer_create_info.width = p_width;3540framebuffer_create_info.height = p_height;3541framebuffer_create_info.layers = 1;35423543VkFramebuffer vk_framebuffer = VK_NULL_HANDLE;3544VkResult err = vkCreateFramebuffer(vk_device, &framebuffer_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER), &vk_framebuffer);3545ERR_FAIL_COND_V_MSG(err, FramebufferID(), "vkCreateFramebuffer failed with error " + itos(err) + ".");35463547#if PRINT_NATIVE_COMMANDS3548print_line(vformat("vkCreateFramebuffer 0x%uX with %d attachments", uint64_t(vk_framebuffer), p_attachments.size()));3549for (uint32_t i = 0; i < p_attachments.size(); i++) {3550const TextureInfo *attachment_info = (const TextureInfo *)p_attachments[i].id;3551print_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)));3552}3553#endif35543555Framebuffer *framebuffer = memnew(Framebuffer);3556framebuffer->vk_framebuffer = vk_framebuffer;3557framebuffer->fragment_density_map_offsets_layers = fragment_density_map_offsets_layers;3558return FramebufferID(framebuffer);3559}35603561void RenderingDeviceDriverVulkan::framebuffer_free(FramebufferID p_framebuffer) {3562Framebuffer *framebuffer = (Framebuffer *)(p_framebuffer.id);3563vkDestroyFramebuffer(vk_device, framebuffer->vk_framebuffer, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER));3564memdelete(framebuffer);3565}35663567/****************/3568/**** SHADER ****/3569/****************/35703571static VkShaderStageFlagBits RD_STAGE_TO_VK_SHADER_STAGE_BITS[RDD::SHADER_STAGE_MAX] = {3572VK_SHADER_STAGE_VERTEX_BIT,3573VK_SHADER_STAGE_FRAGMENT_BIT,3574VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,3575VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,3576VK_SHADER_STAGE_COMPUTE_BIT,3577};35783579RDD::ShaderID RenderingDeviceDriverVulkan::shader_create_from_container(const Ref<RenderingShaderContainer> &p_shader_container, const Vector<ImmutableSampler> &p_immutable_samplers) {3580ShaderReflection shader_refl = p_shader_container->get_shader_reflection();3581ShaderInfo shader_info;3582for (uint32_t i = 0; i < SHADER_STAGE_MAX; i++) {3583if (shader_refl.push_constant_stages.has_flag((ShaderStage)(1 << i))) {3584shader_info.vk_push_constant_stages |= RD_STAGE_TO_VK_SHADER_STAGE_BITS[i];3585}3586}35873588// Set bindings.3589Vector<Vector<VkDescriptorSetLayoutBinding>> vk_set_bindings;3590vk_set_bindings.resize(shader_refl.uniform_sets.size());3591for (uint32_t i = 0; i < shader_refl.uniform_sets.size(); i++) {3592for (uint32_t j = 0; j < shader_refl.uniform_sets[i].size(); j++) {3593const ShaderUniform &uniform = shader_refl.uniform_sets[i][j];3594VkDescriptorSetLayoutBinding layout_binding = {};3595layout_binding.binding = uniform.binding;3596layout_binding.descriptorCount = 1;3597for (uint32_t k = 0; k < SHADER_STAGE_MAX; k++) {3598if ((uniform.stages.has_flag(ShaderStage(1U << k)))) {3599layout_binding.stageFlags |= RD_STAGE_TO_VK_SHADER_STAGE_BITS[k];3600}3601}36023603switch (uniform.type) {3604case UNIFORM_TYPE_SAMPLER: {3605layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;3606layout_binding.descriptorCount = uniform.length;3607// Immutable samplers: here they get set in the layoutbinding, given that they will not be changed later.3608int immutable_bind_index = -1;3609if (immutable_samplers_enabled && p_immutable_samplers.size() > 0) {3610for (int k = 0; k < p_immutable_samplers.size(); k++) {3611if (p_immutable_samplers[k].binding == layout_binding.binding) {3612immutable_bind_index = k;3613break;3614}3615}3616if (immutable_bind_index >= 0) {3617layout_binding.pImmutableSamplers = (VkSampler *)&p_immutable_samplers[immutable_bind_index].ids[0].id;3618}3619}3620} break;3621case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE: {3622layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;3623layout_binding.descriptorCount = uniform.length;3624} break;3625case UNIFORM_TYPE_TEXTURE: {3626layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;3627layout_binding.descriptorCount = uniform.length;3628} break;3629case UNIFORM_TYPE_IMAGE: {3630layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;3631layout_binding.descriptorCount = uniform.length;3632} break;3633case UNIFORM_TYPE_TEXTURE_BUFFER: {3634layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;3635layout_binding.descriptorCount = uniform.length;3636} break;3637case UNIFORM_TYPE_IMAGE_BUFFER: {3638layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;3639} break;3640case UNIFORM_TYPE_UNIFORM_BUFFER: {3641layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;3642} break;3643case UNIFORM_TYPE_STORAGE_BUFFER: {3644layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;3645} break;3646case UNIFORM_TYPE_INPUT_ATTACHMENT: {3647layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;3648} break;3649default: {3650DEV_ASSERT(false);3651}3652}36533654vk_set_bindings.write[i].push_back(layout_binding);3655}3656}36573658// Modules.3659VkResult res;3660String error_text;3661Vector<uint8_t> decompressed_code;3662Vector<uint8_t> decoded_spirv;3663VkShaderModule vk_module;3664for (int i = 0; i < shader_refl.stages_vector.size(); i++) {3665const RenderingShaderContainer::Shader &shader = p_shader_container->shaders[i];3666bool requires_decompression = (shader.code_decompressed_size > 0);3667if (requires_decompression) {3668decompressed_code.resize(shader.code_decompressed_size);3669bool 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());3670if (!decompressed) {3671error_text = vformat("Failed to decompress code on shader stage %s.", String(SHADER_STAGE_NAMES[shader_refl.stages_vector[i]]));3672break;3673}3674}36753676const uint8_t *smolv_input = requires_decompression ? decompressed_code.ptr() : shader.code_compressed_bytes.ptr();3677uint32_t smolv_input_size = requires_decompression ? decompressed_code.size() : shader.code_compressed_bytes.size();3678if (shader.code_compression_flags & RenderingShaderContainerVulkan::COMPRESSION_FLAG_SMOLV) {3679decoded_spirv.resize(smolv::GetDecodedBufferSize(smolv_input, smolv_input_size));3680if (decoded_spirv.is_empty()) {3681error_text = vformat("Malformed smolv input on shader stage %s.", String(SHADER_STAGE_NAMES[shader_refl.stages_vector[i]]));3682break;3683}36843685if (!smolv::Decode(smolv_input, smolv_input_size, decoded_spirv.ptrw(), decoded_spirv.size())) {3686error_text = vformat("Malformed smolv input on shader stage %s.", String(SHADER_STAGE_NAMES[shader_refl.stages_vector[i]]));3687break;3688}3689} else {3690decoded_spirv.resize(smolv_input_size);3691memcpy(decoded_spirv.ptrw(), smolv_input, decoded_spirv.size());3692}36933694VkShaderModuleCreateInfo shader_module_create_info = {};3695shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;3696shader_module_create_info.codeSize = decoded_spirv.size();3697shader_module_create_info.pCode = (const uint32_t *)(decoded_spirv.ptr());36983699res = vkCreateShaderModule(vk_device, &shader_module_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SHADER_MODULE), &vk_module);3700if (res != VK_SUCCESS) {3701error_text = vformat("Error (%d) creating module for shader stage %s.", res, String(SHADER_STAGE_NAMES[shader_refl.stages_vector[i]]));3702break;3703}37043705VkPipelineShaderStageCreateInfo create_info = {};3706create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;3707create_info.stage = RD_STAGE_TO_VK_SHADER_STAGE_BITS[shader_refl.stages_vector[i]];3708create_info.module = vk_module;3709create_info.pName = "main";3710shader_info.vk_stages_create_info.push_back(create_info);3711}37123713// Descriptor sets.3714if (error_text.is_empty()) {3715for (uint32_t i = 0; i < shader_refl.uniform_sets.size(); i++) {3716// Empty ones are fine if they were not used according to spec (binding count will be 0).3717VkDescriptorSetLayoutCreateInfo layout_create_info = {};3718layout_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;3719layout_create_info.bindingCount = vk_set_bindings[i].size();3720layout_create_info.pBindings = vk_set_bindings[i].ptr();37213722VkDescriptorSetLayout layout = VK_NULL_HANDLE;3723res = vkCreateDescriptorSetLayout(vk_device, &layout_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT), &layout);3724if (res) {3725error_text = vformat("Error (%d) creating descriptor set layout for set %d.", res, i);3726break;3727}37283729shader_info.vk_descriptor_set_layouts.push_back(layout);3730}3731}37323733if (error_text.is_empty()) {3734// Pipeline layout.3735VkPipelineLayoutCreateInfo pipeline_layout_create_info = {};3736pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;3737pipeline_layout_create_info.setLayoutCount = shader_info.vk_descriptor_set_layouts.size();3738pipeline_layout_create_info.pSetLayouts = shader_info.vk_descriptor_set_layouts.ptr();37393740if (shader_refl.push_constant_size > 0) {3741VkPushConstantRange *push_constant_range = ALLOCA_SINGLE(VkPushConstantRange);3742*push_constant_range = {};3743push_constant_range->stageFlags = shader_info.vk_push_constant_stages;3744push_constant_range->size = shader_refl.push_constant_size;3745pipeline_layout_create_info.pushConstantRangeCount = 1;3746pipeline_layout_create_info.pPushConstantRanges = push_constant_range;3747}37483749res = vkCreatePipelineLayout(vk_device, &pipeline_layout_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE_LAYOUT), &shader_info.vk_pipeline_layout);3750if (res != VK_SUCCESS) {3751error_text = vformat("Error (%d) creating pipeline layout.", res);3752}3753}37543755if (!error_text.is_empty()) {3756// Clean up if failed.3757for (uint32_t i = 0; i < shader_info.vk_stages_create_info.size(); i++) {3758vkDestroyShaderModule(vk_device, shader_info.vk_stages_create_info[i].module, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SHADER_MODULE));3759}3760for (uint32_t i = 0; i < shader_info.vk_descriptor_set_layouts.size(); i++) {3761vkDestroyDescriptorSetLayout(vk_device, shader_info.vk_descriptor_set_layouts[i], VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT));3762}37633764ERR_FAIL_V_MSG(ShaderID(), error_text);3765}37663767// Bookkeep.3768ShaderInfo *shader_info_ptr = VersatileResource::allocate<ShaderInfo>(resources_allocator);3769*shader_info_ptr = shader_info;3770return ShaderID(shader_info_ptr);3771}37723773void RenderingDeviceDriverVulkan::shader_free(ShaderID p_shader) {3774ShaderInfo *shader_info = (ShaderInfo *)p_shader.id;37753776for (uint32_t i = 0; i < shader_info->vk_descriptor_set_layouts.size(); i++) {3777vkDestroyDescriptorSetLayout(vk_device, shader_info->vk_descriptor_set_layouts[i], VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT));3778}37793780vkDestroyPipelineLayout(vk_device, shader_info->vk_pipeline_layout, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE_LAYOUT));37813782shader_destroy_modules(p_shader);37833784VersatileResource::free(resources_allocator, shader_info);3785}37863787void RenderingDeviceDriverVulkan::shader_destroy_modules(ShaderID p_shader) {3788ShaderInfo *si = (ShaderInfo *)p_shader.id;37893790for (uint32_t i = 0; i < si->vk_stages_create_info.size(); i++) {3791if (si->vk_stages_create_info[i].module) {3792vkDestroyShaderModule(vk_device, si->vk_stages_create_info[i].module,3793VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SHADER_MODULE));3794si->vk_stages_create_info[i].module = VK_NULL_HANDLE;3795}3796}3797si->vk_stages_create_info.clear();3798}37993800/*********************/3801/**** UNIFORM SET ****/3802/*********************/3803VkDescriptorPool RenderingDeviceDriverVulkan::_descriptor_set_pool_find_or_create(const DescriptorSetPoolKey &p_key, DescriptorSetPools::Iterator *r_pool_sets_it, int p_linear_pool_index) {3804bool linear_pool = p_linear_pool_index >= 0;3805DescriptorSetPools::Iterator pool_sets_it = linear_pool ? linear_descriptor_set_pools[p_linear_pool_index].find(p_key) : descriptor_set_pools.find(p_key);38063807if (pool_sets_it) {3808for (KeyValue<VkDescriptorPool, uint32_t> &E : pool_sets_it->value) {3809if (E.value < max_descriptor_sets_per_pool) {3810*r_pool_sets_it = pool_sets_it;3811return E.key;3812}3813}3814}38153816// Create a new one.38173818// Here comes more vulkan API strangeness.3819VkDescriptorPoolSize *vk_sizes = ALLOCA_ARRAY(VkDescriptorPoolSize, UNIFORM_TYPE_MAX);3820uint32_t vk_sizes_count = 0;3821{3822VkDescriptorPoolSize *curr_vk_size = vk_sizes;3823if (p_key.uniform_type[UNIFORM_TYPE_SAMPLER]) {3824*curr_vk_size = {};3825curr_vk_size->type = VK_DESCRIPTOR_TYPE_SAMPLER;3826curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_SAMPLER] * max_descriptor_sets_per_pool;3827curr_vk_size++;3828vk_sizes_count++;3829}3830if (p_key.uniform_type[UNIFORM_TYPE_SAMPLER_WITH_TEXTURE]) {3831*curr_vk_size = {};3832curr_vk_size->type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;3833curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_SAMPLER_WITH_TEXTURE] * max_descriptor_sets_per_pool;3834curr_vk_size++;3835vk_sizes_count++;3836}3837if (p_key.uniform_type[UNIFORM_TYPE_TEXTURE]) {3838*curr_vk_size = {};3839curr_vk_size->type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;3840curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_TEXTURE] * max_descriptor_sets_per_pool;3841curr_vk_size++;3842vk_sizes_count++;3843}3844if (p_key.uniform_type[UNIFORM_TYPE_IMAGE]) {3845*curr_vk_size = {};3846curr_vk_size->type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;3847curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_IMAGE] * max_descriptor_sets_per_pool;3848curr_vk_size++;3849vk_sizes_count++;3850}3851if (p_key.uniform_type[UNIFORM_TYPE_TEXTURE_BUFFER] || p_key.uniform_type[UNIFORM_TYPE_SAMPLER_WITH_TEXTURE_BUFFER]) {3852*curr_vk_size = {};3853curr_vk_size->type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;3854curr_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;3855curr_vk_size++;3856vk_sizes_count++;3857}3858if (p_key.uniform_type[UNIFORM_TYPE_IMAGE_BUFFER]) {3859*curr_vk_size = {};3860curr_vk_size->type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;3861curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_IMAGE_BUFFER] * max_descriptor_sets_per_pool;3862curr_vk_size++;3863vk_sizes_count++;3864}3865if (p_key.uniform_type[UNIFORM_TYPE_UNIFORM_BUFFER]) {3866*curr_vk_size = {};3867curr_vk_size->type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;3868curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_UNIFORM_BUFFER] * max_descriptor_sets_per_pool;3869curr_vk_size++;3870vk_sizes_count++;3871}3872if (p_key.uniform_type[UNIFORM_TYPE_STORAGE_BUFFER]) {3873*curr_vk_size = {};3874curr_vk_size->type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;3875curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_STORAGE_BUFFER] * max_descriptor_sets_per_pool;3876curr_vk_size++;3877vk_sizes_count++;3878}3879if (p_key.uniform_type[UNIFORM_TYPE_INPUT_ATTACHMENT]) {3880*curr_vk_size = {};3881curr_vk_size->type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;3882curr_vk_size->descriptorCount = p_key.uniform_type[UNIFORM_TYPE_INPUT_ATTACHMENT] * max_descriptor_sets_per_pool;3883curr_vk_size++;3884vk_sizes_count++;3885}3886DEV_ASSERT(vk_sizes_count <= UNIFORM_TYPE_MAX);3887}38883889VkDescriptorPoolCreateInfo descriptor_set_pool_create_info = {};3890descriptor_set_pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;3891if (linear_descriptor_pools_enabled && linear_pool) {3892descriptor_set_pool_create_info.flags = 0;3893} else {3894descriptor_set_pool_create_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; // Can't think how somebody may NOT need this flag.3895}3896descriptor_set_pool_create_info.maxSets = max_descriptor_sets_per_pool;3897descriptor_set_pool_create_info.poolSizeCount = vk_sizes_count;3898descriptor_set_pool_create_info.pPoolSizes = vk_sizes;38993900VkDescriptorPool vk_pool = VK_NULL_HANDLE;3901VkResult res = vkCreateDescriptorPool(vk_device, &descriptor_set_pool_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DESCRIPTOR_POOL), &vk_pool);3902if (res) {3903ERR_FAIL_COND_V_MSG(res, VK_NULL_HANDLE, "vkCreateDescriptorPool failed with error " + itos(res) + ".");3904}39053906// Bookkeep.39073908if (!pool_sets_it) {3909if (linear_pool) {3910pool_sets_it = linear_descriptor_set_pools[p_linear_pool_index].insert(p_key, HashMap<VkDescriptorPool, uint32_t>());3911} else {3912pool_sets_it = descriptor_set_pools.insert(p_key, HashMap<VkDescriptorPool, uint32_t>());3913}3914}3915HashMap<VkDescriptorPool, uint32_t> &pool_rcs = pool_sets_it->value;3916pool_rcs.insert(vk_pool, 0);3917*r_pool_sets_it = pool_sets_it;3918return vk_pool;3919}39203921void RenderingDeviceDriverVulkan::_descriptor_set_pool_unreference(DescriptorSetPools::Iterator p_pool_sets_it, VkDescriptorPool p_vk_descriptor_pool, int p_linear_pool_index) {3922HashMap<VkDescriptorPool, uint32_t>::Iterator pool_rcs_it = p_pool_sets_it->value.find(p_vk_descriptor_pool);3923pool_rcs_it->value--;3924if (pool_rcs_it->value == 0) {3925vkDestroyDescriptorPool(vk_device, p_vk_descriptor_pool, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DESCRIPTOR_POOL));3926p_pool_sets_it->value.erase(p_vk_descriptor_pool);3927if (p_pool_sets_it->value.is_empty()) {3928if (linear_descriptor_pools_enabled && p_linear_pool_index >= 0) {3929linear_descriptor_set_pools[p_linear_pool_index].remove(p_pool_sets_it);3930} else {3931descriptor_set_pools.remove(p_pool_sets_it);3932}3933}3934}3935}39363937RDD::UniformSetID RenderingDeviceDriverVulkan::uniform_set_create(VectorView<BoundUniform> p_uniforms, ShaderID p_shader, uint32_t p_set_index, int p_linear_pool_index) {3938if (!linear_descriptor_pools_enabled) {3939p_linear_pool_index = -1;3940}3941DescriptorSetPoolKey pool_key;3942// Immutable samplers will be skipped so we need to track the number of vk_writes used.3943VkWriteDescriptorSet *vk_writes = ALLOCA_ARRAY(VkWriteDescriptorSet, p_uniforms.size());3944uint32_t writes_amount = 0;3945for (uint32_t i = 0; i < p_uniforms.size(); i++) {3946const BoundUniform &uniform = p_uniforms[i];39473948vk_writes[writes_amount] = {};3949vk_writes[writes_amount].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;39503951uint32_t num_descriptors = 1;39523953switch (uniform.type) {3954case UNIFORM_TYPE_SAMPLER: {3955if (uniform.immutable_sampler && immutable_samplers_enabled) {3956continue; // Skipping immutable samplers.3957}3958num_descriptors = uniform.ids.size();3959VkDescriptorImageInfo *vk_img_infos = ALLOCA_ARRAY(VkDescriptorImageInfo, num_descriptors);39603961for (uint32_t j = 0; j < num_descriptors; j++) {3962vk_img_infos[j] = {};3963vk_img_infos[j].sampler = (VkSampler)uniform.ids[j].id;3964vk_img_infos[j].imageView = VK_NULL_HANDLE;3965vk_img_infos[j].imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;3966}39673968vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;3969vk_writes[writes_amount].pImageInfo = vk_img_infos;3970} break;3971case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE: {3972num_descriptors = uniform.ids.size() / 2;3973VkDescriptorImageInfo *vk_img_infos = ALLOCA_ARRAY(VkDescriptorImageInfo, num_descriptors);39743975for (uint32_t j = 0; j < num_descriptors; j++) {3976#ifdef DEBUG_ENABLED3977if (((const TextureInfo *)uniform.ids[j * 2 + 1].id)->transient) {3978ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT texture must not be used for sampling in a shader.");3979}3980#endif3981vk_img_infos[j] = {};3982vk_img_infos[j].sampler = (VkSampler)uniform.ids[j * 2 + 0].id;3983vk_img_infos[j].imageView = ((const TextureInfo *)uniform.ids[j * 2 + 1].id)->vk_view;3984vk_img_infos[j].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;3985}39863987vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;3988vk_writes[writes_amount].pImageInfo = vk_img_infos;3989} break;3990case UNIFORM_TYPE_TEXTURE: {3991num_descriptors = uniform.ids.size();3992VkDescriptorImageInfo *vk_img_infos = ALLOCA_ARRAY(VkDescriptorImageInfo, num_descriptors);39933994for (uint32_t j = 0; j < num_descriptors; j++) {3995#ifdef DEBUG_ENABLED3996if (((const TextureInfo *)uniform.ids[j].id)->transient) {3997ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT texture must not be used for sampling in a shader.");3998}3999#endif4000vk_img_infos[j] = {};4001vk_img_infos[j].imageView = ((const TextureInfo *)uniform.ids[j].id)->vk_view;4002vk_img_infos[j].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;4003}40044005vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;4006vk_writes[writes_amount].pImageInfo = vk_img_infos;4007} break;4008case UNIFORM_TYPE_IMAGE: {4009num_descriptors = uniform.ids.size();4010VkDescriptorImageInfo *vk_img_infos = ALLOCA_ARRAY(VkDescriptorImageInfo, num_descriptors);40114012for (uint32_t j = 0; j < num_descriptors; j++) {4013#ifdef DEBUG_ENABLED4014if (((const TextureInfo *)uniform.ids[j].id)->transient) {4015ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT texture must not be used for sampling in a shader.");4016}4017#endif4018vk_img_infos[j] = {};4019vk_img_infos[j].imageView = ((const TextureInfo *)uniform.ids[j].id)->vk_view;4020vk_img_infos[j].imageLayout = VK_IMAGE_LAYOUT_GENERAL;4021}40224023vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;4024vk_writes[writes_amount].pImageInfo = vk_img_infos;4025} break;4026case UNIFORM_TYPE_TEXTURE_BUFFER: {4027num_descriptors = uniform.ids.size();4028VkDescriptorBufferInfo *vk_buf_infos = ALLOCA_ARRAY(VkDescriptorBufferInfo, num_descriptors);4029VkBufferView *vk_buf_views = ALLOCA_ARRAY(VkBufferView, num_descriptors);40304031for (uint32_t j = 0; j < num_descriptors; j++) {4032const BufferInfo *buf_info = (const BufferInfo *)uniform.ids[j].id;4033vk_buf_infos[j] = {};4034vk_buf_infos[j].buffer = buf_info->vk_buffer;4035vk_buf_infos[j].range = buf_info->size;40364037vk_buf_views[j] = buf_info->vk_view;4038}40394040vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;4041vk_writes[writes_amount].pBufferInfo = vk_buf_infos;4042vk_writes[writes_amount].pTexelBufferView = vk_buf_views;4043} break;4044case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE_BUFFER: {4045num_descriptors = uniform.ids.size() / 2;4046VkDescriptorImageInfo *vk_img_infos = ALLOCA_ARRAY(VkDescriptorImageInfo, num_descriptors);4047VkDescriptorBufferInfo *vk_buf_infos = ALLOCA_ARRAY(VkDescriptorBufferInfo, num_descriptors);4048VkBufferView *vk_buf_views = ALLOCA_ARRAY(VkBufferView, num_descriptors);40494050for (uint32_t j = 0; j < num_descriptors; j++) {4051vk_img_infos[j] = {};4052vk_img_infos[j].sampler = (VkSampler)uniform.ids[j * 2 + 0].id;40534054const BufferInfo *buf_info = (const BufferInfo *)uniform.ids[j * 2 + 1].id;4055vk_buf_infos[j] = {};4056vk_buf_infos[j].buffer = buf_info->vk_buffer;4057vk_buf_infos[j].range = buf_info->size;40584059vk_buf_views[j] = buf_info->vk_view;4060}40614062vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;4063vk_writes[writes_amount].pImageInfo = vk_img_infos;4064vk_writes[writes_amount].pBufferInfo = vk_buf_infos;4065vk_writes[writes_amount].pTexelBufferView = vk_buf_views;4066} break;4067case UNIFORM_TYPE_IMAGE_BUFFER: {4068CRASH_NOW_MSG("Unimplemented!"); // TODO.4069} break;4070case UNIFORM_TYPE_UNIFORM_BUFFER: {4071const BufferInfo *buf_info = (const BufferInfo *)uniform.ids[0].id;4072VkDescriptorBufferInfo *vk_buf_info = ALLOCA_SINGLE(VkDescriptorBufferInfo);4073*vk_buf_info = {};4074vk_buf_info->buffer = buf_info->vk_buffer;4075vk_buf_info->range = buf_info->size;40764077vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;4078vk_writes[writes_amount].pBufferInfo = vk_buf_info;4079} break;4080case UNIFORM_TYPE_STORAGE_BUFFER: {4081const BufferInfo *buf_info = (const BufferInfo *)uniform.ids[0].id;4082VkDescriptorBufferInfo *vk_buf_info = ALLOCA_SINGLE(VkDescriptorBufferInfo);4083*vk_buf_info = {};4084vk_buf_info->buffer = buf_info->vk_buffer;4085vk_buf_info->range = buf_info->size;40864087vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;4088vk_writes[writes_amount].pBufferInfo = vk_buf_info;4089} break;4090case UNIFORM_TYPE_INPUT_ATTACHMENT: {4091num_descriptors = uniform.ids.size();4092VkDescriptorImageInfo *vk_img_infos = ALLOCA_ARRAY(VkDescriptorImageInfo, num_descriptors);40934094for (uint32_t j = 0; j < uniform.ids.size(); j++) {4095vk_img_infos[j] = {};4096vk_img_infos[j].imageView = ((const TextureInfo *)uniform.ids[j].id)->vk_view;4097vk_img_infos[j].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;4098}40994100vk_writes[writes_amount].descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;4101vk_writes[writes_amount].pImageInfo = vk_img_infos;4102} break;4103default: {4104DEV_ASSERT(false);4105}4106}41074108vk_writes[writes_amount].dstBinding = uniform.binding;4109vk_writes[writes_amount].descriptorCount = num_descriptors;41104111ERR_FAIL_COND_V_MSG(pool_key.uniform_type[uniform.type] == MAX_UNIFORM_POOL_ELEMENT, UniformSetID(),4112"Uniform set reached the limit of bindings for the same type (" + itos(MAX_UNIFORM_POOL_ELEMENT) + ").");4113pool_key.uniform_type[uniform.type] += num_descriptors;4114writes_amount++;4115}41164117// Need a descriptor pool.4118DescriptorSetPools::Iterator pool_sets_it;4119VkDescriptorPool vk_pool = _descriptor_set_pool_find_or_create(pool_key, &pool_sets_it, p_linear_pool_index);4120DEV_ASSERT(vk_pool);4121pool_sets_it->value[vk_pool]++;41224123VkDescriptorSetAllocateInfo descriptor_set_allocate_info = {};4124descriptor_set_allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;4125descriptor_set_allocate_info.descriptorPool = vk_pool;4126descriptor_set_allocate_info.descriptorSetCount = 1;4127const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;4128descriptor_set_allocate_info.pSetLayouts = &shader_info->vk_descriptor_set_layouts[p_set_index];41294130VkDescriptorSet vk_descriptor_set = VK_NULL_HANDLE;41314132VkResult res = vkAllocateDescriptorSets(vk_device, &descriptor_set_allocate_info, &vk_descriptor_set);4133if (res) {4134_descriptor_set_pool_unreference(pool_sets_it, vk_pool, p_linear_pool_index);4135ERR_FAIL_V_MSG(UniformSetID(), "Cannot allocate descriptor sets, error " + itos(res) + ".");4136}41374138for (uint32_t i = 0; i < writes_amount; i++) {4139vk_writes[i].dstSet = vk_descriptor_set;4140}4141vkUpdateDescriptorSets(vk_device, writes_amount, vk_writes, 0, nullptr);41424143// Bookkeep.41444145UniformSetInfo *usi = VersatileResource::allocate<UniformSetInfo>(resources_allocator);4146usi->vk_descriptor_set = vk_descriptor_set;4147if (p_linear_pool_index >= 0) {4148usi->vk_linear_descriptor_pool = vk_pool;4149} else {4150usi->vk_descriptor_pool = vk_pool;4151}4152usi->pool_sets_it = pool_sets_it;41534154return UniformSetID(usi);4155}41564157void RenderingDeviceDriverVulkan::uniform_set_free(UniformSetID p_uniform_set) {4158UniformSetInfo *usi = (UniformSetInfo *)p_uniform_set.id;41594160if (usi->vk_linear_descriptor_pool) {4161// Nothing to do. All sets are freed at once using vkResetDescriptorPool.4162//4163// We can NOT decrease the reference count (i.e. call _descriptor_set_pool_unreference())4164// because the pool is linear (i.e. the freed set can't be recycled) and further calls to4165// _descriptor_set_pool_find_or_create() need usi->pool_sets_it->value to stay so that we can4166// tell if the pool has ran out of space and we need to create a new pool.4167} else {4168vkFreeDescriptorSets(vk_device, usi->vk_descriptor_pool, 1, &usi->vk_descriptor_set);4169_descriptor_set_pool_unreference(usi->pool_sets_it, usi->vk_descriptor_pool, -1);4170}41714172VersatileResource::free(resources_allocator, usi);4173}41744175bool RenderingDeviceDriverVulkan::uniform_sets_have_linear_pools() const {4176return true;4177}41784179void RenderingDeviceDriverVulkan::linear_uniform_set_pools_reset(int p_linear_pool_index) {4180if (linear_descriptor_pools_enabled) {4181DescriptorSetPools &pools_to_reset = linear_descriptor_set_pools[p_linear_pool_index];4182DescriptorSetPools::Iterator curr_pool = pools_to_reset.begin();41834184while (curr_pool != pools_to_reset.end()) {4185HashMap<VkDescriptorPool, uint32_t>::Iterator curr_pair = curr_pool->value.begin();4186while (curr_pair != curr_pool->value.end()) {4187vkResetDescriptorPool(vk_device, curr_pair->key, 0);4188curr_pair->value = 0;4189++curr_pair;4190}4191++curr_pool;4192}4193}4194}41954196// ----- COMMANDS -----41974198void RenderingDeviceDriverVulkan::command_uniform_set_prepare_for_use(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index) {4199}42004201/******************/4202/**** TRANSFER ****/4203/******************/42044205static_assert(ARRAYS_COMPATIBLE_FIELDWISE(RDD::BufferCopyRegion, VkBufferCopy));42064207static void _texture_subresource_range_to_vk(const RDD::TextureSubresourceRange &p_subresources, VkImageSubresourceRange *r_vk_subreources) {4208*r_vk_subreources = {};4209r_vk_subreources->aspectMask = (VkImageAspectFlags)p_subresources.aspect;4210r_vk_subreources->baseMipLevel = p_subresources.base_mipmap;4211r_vk_subreources->levelCount = p_subresources.mipmap_count;4212r_vk_subreources->baseArrayLayer = p_subresources.base_layer;4213r_vk_subreources->layerCount = p_subresources.layer_count;4214}42154216static void _texture_subresource_layers_to_vk(const RDD::TextureSubresourceLayers &p_subresources, VkImageSubresourceLayers *r_vk_subreources) {4217*r_vk_subreources = {};4218r_vk_subreources->aspectMask = (VkImageAspectFlags)p_subresources.aspect;4219r_vk_subreources->mipLevel = p_subresources.mipmap;4220r_vk_subreources->baseArrayLayer = p_subresources.base_layer;4221r_vk_subreources->layerCount = p_subresources.layer_count;4222}42234224static void _buffer_texture_copy_region_to_vk(const RDD::BufferTextureCopyRegion &p_copy_region, VkBufferImageCopy *r_vk_copy_region) {4225*r_vk_copy_region = {};4226r_vk_copy_region->bufferOffset = p_copy_region.buffer_offset;4227_texture_subresource_layers_to_vk(p_copy_region.texture_subresources, &r_vk_copy_region->imageSubresource);4228r_vk_copy_region->imageOffset.x = p_copy_region.texture_offset.x;4229r_vk_copy_region->imageOffset.y = p_copy_region.texture_offset.y;4230r_vk_copy_region->imageOffset.z = p_copy_region.texture_offset.z;4231r_vk_copy_region->imageExtent.width = p_copy_region.texture_region_size.x;4232r_vk_copy_region->imageExtent.height = p_copy_region.texture_region_size.y;4233r_vk_copy_region->imageExtent.depth = p_copy_region.texture_region_size.z;4234}42354236static void _texture_copy_region_to_vk(const RDD::TextureCopyRegion &p_copy_region, VkImageCopy *r_vk_copy_region) {4237*r_vk_copy_region = {};4238_texture_subresource_layers_to_vk(p_copy_region.src_subresources, &r_vk_copy_region->srcSubresource);4239r_vk_copy_region->srcOffset.x = p_copy_region.src_offset.x;4240r_vk_copy_region->srcOffset.y = p_copy_region.src_offset.y;4241r_vk_copy_region->srcOffset.z = p_copy_region.src_offset.z;4242_texture_subresource_layers_to_vk(p_copy_region.dst_subresources, &r_vk_copy_region->dstSubresource);4243r_vk_copy_region->dstOffset.x = p_copy_region.dst_offset.x;4244r_vk_copy_region->dstOffset.y = p_copy_region.dst_offset.y;4245r_vk_copy_region->dstOffset.z = p_copy_region.dst_offset.z;4246r_vk_copy_region->extent.width = p_copy_region.size.x;4247r_vk_copy_region->extent.height = p_copy_region.size.y;4248r_vk_copy_region->extent.depth = p_copy_region.size.z;4249}42504251void RenderingDeviceDriverVulkan::command_clear_buffer(CommandBufferID p_cmd_buffer, BufferID p_buffer, uint64_t p_offset, uint64_t p_size) {4252const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4253const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;4254vkCmdFillBuffer(command_buffer->vk_command_buffer, buf_info->vk_buffer, p_offset, p_size, 0);4255}42564257void RenderingDeviceDriverVulkan::command_copy_buffer(CommandBufferID p_cmd_buffer, BufferID p_src_buffer, BufferID p_dst_buffer, VectorView<BufferCopyRegion> p_regions) {4258const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4259const BufferInfo *src_buf_info = (const BufferInfo *)p_src_buffer.id;4260const BufferInfo *dst_buf_info = (const BufferInfo *)p_dst_buffer.id;4261vkCmdCopyBuffer(command_buffer->vk_command_buffer, src_buf_info->vk_buffer, dst_buf_info->vk_buffer, p_regions.size(), (const VkBufferCopy *)p_regions.ptr());4262}42634264void 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) {4265VkImageCopy *vk_copy_regions = ALLOCA_ARRAY(VkImageCopy, p_regions.size());4266for (uint32_t i = 0; i < p_regions.size(); i++) {4267_texture_copy_region_to_vk(p_regions[i], &vk_copy_regions[i]);4268}42694270const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4271const TextureInfo *src_tex_info = (const TextureInfo *)p_src_texture.id;4272const TextureInfo *dst_tex_info = (const TextureInfo *)p_dst_texture.id;42734274#ifdef DEBUG_ENABLED4275if (src_tex_info->transient) {4276ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT p_src_texture must not be used in command_copy_texture.");4277}4278if (dst_tex_info->transient) {4279ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT p_dst_texture must not be used in command_copy_texture.");4280}4281#endif42824283vkCmdCopyImage(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);4284}42854286void 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) {4287const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4288const TextureInfo *src_tex_info = (const TextureInfo *)p_src_texture.id;4289const TextureInfo *dst_tex_info = (const TextureInfo *)p_dst_texture.id;42904291VkImageResolve vk_resolve = {};4292vk_resolve.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;4293vk_resolve.srcSubresource.mipLevel = p_src_mipmap;4294vk_resolve.srcSubresource.baseArrayLayer = p_src_layer;4295vk_resolve.srcSubresource.layerCount = 1;4296vk_resolve.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;4297vk_resolve.dstSubresource.mipLevel = p_dst_mipmap;4298vk_resolve.dstSubresource.baseArrayLayer = p_dst_layer;4299vk_resolve.dstSubresource.layerCount = 1;4300vk_resolve.extent.width = MAX(1u, src_tex_info->vk_create_info.extent.width >> p_src_mipmap);4301vk_resolve.extent.height = MAX(1u, src_tex_info->vk_create_info.extent.height >> p_src_mipmap);4302vk_resolve.extent.depth = MAX(1u, src_tex_info->vk_create_info.extent.depth >> p_src_mipmap);43034304#ifdef DEBUG_ENABLED4305if (src_tex_info->transient) {4306ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT p_src_texture must not be used in command_resolve_texture. Use a resolve store action pass instead.");4307}4308if (dst_tex_info->transient) {4309ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT p_dst_texture must not be used in command_resolve_texture.");4310}4311#endif43124313vkCmdResolveImage(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);4314}43154316void RenderingDeviceDriverVulkan::command_clear_color_texture(CommandBufferID p_cmd_buffer, TextureID p_texture, TextureLayout p_texture_layout, const Color &p_color, const TextureSubresourceRange &p_subresources) {4317VkClearColorValue vk_color = {};4318memcpy(&vk_color.float32, p_color.components, sizeof(VkClearColorValue::float32));43194320VkImageSubresourceRange vk_subresources = {};4321_texture_subresource_range_to_vk(p_subresources, &vk_subresources);43224323const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4324const TextureInfo *tex_info = (const TextureInfo *)p_texture.id;4325#ifdef DEBUG_ENABLED4326if (tex_info->transient) {4327ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT p_texture must not be used in command_clear_color_texture. Use a clear store action pass instead.");4328}4329#endif4330vkCmdClearColorImage(command_buffer->vk_command_buffer, tex_info->vk_view_create_info.image, RD_TO_VK_LAYOUT[p_texture_layout], &vk_color, 1, &vk_subresources);4331}43324333void 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) {4334VkBufferImageCopy *vk_copy_regions = ALLOCA_ARRAY(VkBufferImageCopy, p_regions.size());4335for (uint32_t i = 0; i < p_regions.size(); i++) {4336_buffer_texture_copy_region_to_vk(p_regions[i], &vk_copy_regions[i]);4337}43384339const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4340const BufferInfo *buf_info = (const BufferInfo *)p_src_buffer.id;4341const TextureInfo *tex_info = (const TextureInfo *)p_dst_texture.id;4342#ifdef DEBUG_ENABLED4343if (tex_info->transient) {4344ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT p_dst_texture must not be used in command_copy_buffer_to_texture.");4345}4346#endif4347vkCmdCopyBufferToImage(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);4348}43494350void 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) {4351VkBufferImageCopy *vk_copy_regions = ALLOCA_ARRAY(VkBufferImageCopy, p_regions.size());4352for (uint32_t i = 0; i < p_regions.size(); i++) {4353_buffer_texture_copy_region_to_vk(p_regions[i], &vk_copy_regions[i]);4354}43554356const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4357const TextureInfo *tex_info = (const TextureInfo *)p_src_texture.id;4358const BufferInfo *buf_info = (const BufferInfo *)p_dst_buffer.id;4359#ifdef DEBUG_ENABLED4360if (tex_info->transient) {4361ERR_PRINT("TEXTURE_USAGE_TRANSIENT_BIT p_src_texture must not be used in command_copy_texture_to_buffer.");4362}4363#endif4364vkCmdCopyImageToBuffer(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);4365}43664367/******************/4368/**** PIPELINE ****/4369/******************/43704371void RenderingDeviceDriverVulkan::pipeline_free(PipelineID p_pipeline) {4372vkDestroyPipeline(vk_device, (VkPipeline)p_pipeline.id, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE));4373}43744375// ----- BINDING -----43764377void RenderingDeviceDriverVulkan::command_bind_push_constants(CommandBufferID p_cmd_buffer, ShaderID p_shader, uint32_t p_dst_first_index, VectorView<uint32_t> p_data) {4378const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4379const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;4380vkCmdPushConstants(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());4381}43824383// ----- CACHE -----43844385int RenderingDeviceDriverVulkan::caching_instance_count = 0;43864387bool RenderingDeviceDriverVulkan::pipeline_cache_create(const Vector<uint8_t> &p_data) {4388if (caching_instance_count) {4389WARN_PRINT("There's already a RenderingDeviceDriverVulkan instance doing PSO caching. Only one can at the same time. This one won't.");4390return false;4391}4392caching_instance_count++;43934394pipelines_cache.current_size = 0;4395pipelines_cache.buffer.resize(sizeof(PipelineCacheHeader));43964397// Parse.4398{4399if (p_data.is_empty()) {4400// No pre-existing cache, just create it.4401} else if (p_data.size() <= (int)sizeof(PipelineCacheHeader)) {4402print_verbose("Invalid/corrupt Vulkan pipelines cache. Existing shader pipeline cache will be ignored, which may result in stuttering during gameplay.");4403} else {4404const PipelineCacheHeader *loaded_header = reinterpret_cast<const PipelineCacheHeader *>(p_data.ptr());4405if (loaded_header->magic != 868 + VK_PIPELINE_CACHE_HEADER_VERSION_ONE) {4406print_verbose("Invalid Vulkan pipelines cache magic number. Existing shader pipeline cache will be ignored, which may result in stuttering during gameplay.");4407} else {4408const uint8_t *loaded_buffer_start = p_data.ptr() + sizeof(PipelineCacheHeader);4409uint32_t loaded_buffer_size = p_data.size() - sizeof(PipelineCacheHeader);4410const PipelineCacheHeader *current_header = (PipelineCacheHeader *)pipelines_cache.buffer.ptr();4411if (loaded_header->data_hash != hash_murmur3_buffer(loaded_buffer_start, loaded_buffer_size) ||4412loaded_header->data_size != loaded_buffer_size ||4413loaded_header->vendor_id != current_header->vendor_id ||4414loaded_header->device_id != current_header->device_id ||4415loaded_header->driver_version != current_header->driver_version ||4416memcmp(loaded_header->uuid, current_header->uuid, VK_UUID_SIZE) != 0 ||4417loaded_header->driver_abi != current_header->driver_abi) {4418print_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.");4419} else {4420pipelines_cache.current_size = loaded_buffer_size;4421pipelines_cache.buffer = p_data;4422}4423}4424}4425}44264427// Create.4428{4429VkPipelineCacheCreateInfo cache_info = {};4430cache_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;4431cache_info.initialDataSize = pipelines_cache.buffer.size() - sizeof(PipelineCacheHeader);4432cache_info.pInitialData = pipelines_cache.buffer.ptr() + sizeof(PipelineCacheHeader);44334434VkResult err = vkCreatePipelineCache(vk_device, &cache_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE_CACHE), &pipelines_cache.vk_cache);4435if (err != VK_SUCCESS) {4436WARN_PRINT("vkCreatePipelinecache failed with error " + itos(err) + ".");4437return false;4438}4439}44404441return true;4442}44434444void RenderingDeviceDriverVulkan::pipeline_cache_free() {4445DEV_ASSERT(pipelines_cache.vk_cache);44464447vkDestroyPipelineCache(vk_device, pipelines_cache.vk_cache, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE_CACHE));4448pipelines_cache.vk_cache = VK_NULL_HANDLE;44494450DEV_ASSERT(caching_instance_count > 0);4451caching_instance_count--;4452}44534454size_t RenderingDeviceDriverVulkan::pipeline_cache_query_size() {4455DEV_ASSERT(pipelines_cache.vk_cache);44564457// FIXME:4458// We're letting the cache grow unboundedly. We may want to set at limit and see if implementations use LRU or the like.4459// If we do, we won't be able to assume any longer that the cache is dirty if, and only if, it has grown.4460VkResult err = vkGetPipelineCacheData(vk_device, pipelines_cache.vk_cache, &pipelines_cache.current_size, nullptr);4461ERR_FAIL_COND_V_MSG(err, 0, "vkGetPipelineCacheData failed with error " + itos(err) + ".");44624463return pipelines_cache.current_size;4464}44654466Vector<uint8_t> RenderingDeviceDriverVulkan::pipeline_cache_serialize() {4467DEV_ASSERT(pipelines_cache.vk_cache);44684469pipelines_cache.buffer.resize(pipelines_cache.current_size + sizeof(PipelineCacheHeader));44704471VkResult err = vkGetPipelineCacheData(vk_device, pipelines_cache.vk_cache, &pipelines_cache.current_size, pipelines_cache.buffer.ptrw() + sizeof(PipelineCacheHeader));4472ERR_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).44734474// The real buffer size may now be bigger than the updated current_size.4475// We take into account the new size but keep the buffer resized in a worst-case fashion.44764477PipelineCacheHeader *header = (PipelineCacheHeader *)pipelines_cache.buffer.ptrw();4478header->data_size = pipelines_cache.current_size;4479header->data_hash = hash_murmur3_buffer(pipelines_cache.buffer.ptr() + sizeof(PipelineCacheHeader), pipelines_cache.current_size);44804481return pipelines_cache.buffer;4482}44834484/*******************/4485/**** RENDERING ****/4486/*******************/44874488// ----- SUBPASS -----44894490// RDD::AttachmentLoadOp == VkAttachmentLoadOp.4491static_assert(ENUM_MEMBERS_EQUAL(RDD::ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_LOAD));4492static_assert(ENUM_MEMBERS_EQUAL(RDD::ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_CLEAR));4493static_assert(ENUM_MEMBERS_EQUAL(RDD::ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_DONT_CARE));44944495// RDD::AttachmentStoreOp == VkAttachmentStoreOp.4496static_assert(ENUM_MEMBERS_EQUAL(RDD::ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_STORE_OP_STORE));4497static_assert(ENUM_MEMBERS_EQUAL(RDD::ATTACHMENT_STORE_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE));44984499// Assuming Vulkan and RDD's are backed by uint32_t in:4500// - VkSubpassDescription2::pPreserveAttachments and RDD::Subpass::preserve_attachments.4501// - VkRenderPassCreateInfo2KHR::pCorrelatedViewMasks and p_view_correlation_mask.45024503static void _attachment_reference_to_vk(const RDD::AttachmentReference &p_attachment_reference, VkAttachmentReference2KHR *r_vk_attachment_reference) {4504*r_vk_attachment_reference = {};4505r_vk_attachment_reference->sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;4506r_vk_attachment_reference->attachment = p_attachment_reference.attachment;4507r_vk_attachment_reference->layout = RD_TO_VK_LAYOUT[p_attachment_reference.layout];4508r_vk_attachment_reference->aspectMask = (VkImageAspectFlags)p_attachment_reference.aspect;4509}45104511RDD::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) {4512// These are only used if we use multiview but we need to define them in scope.4513const uint32_t view_mask = (1 << p_view_count) - 1;4514const uint32_t correlation_mask = (1 << p_view_count) - 1;45154516VkAttachmentDescription2KHR *vk_attachments = ALLOCA_ARRAY(VkAttachmentDescription2KHR, p_attachments.size());4517for (uint32_t i = 0; i < p_attachments.size(); i++) {4518vk_attachments[i] = {};4519vk_attachments[i].sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR;4520vk_attachments[i].format = RD_TO_VK_FORMAT[p_attachments[i].format];4521vk_attachments[i].samples = _ensure_supported_sample_count(p_attachments[i].samples);4522vk_attachments[i].loadOp = (VkAttachmentLoadOp)p_attachments[i].load_op;4523vk_attachments[i].storeOp = (VkAttachmentStoreOp)p_attachments[i].store_op;4524vk_attachments[i].stencilLoadOp = (VkAttachmentLoadOp)p_attachments[i].stencil_load_op;4525vk_attachments[i].stencilStoreOp = (VkAttachmentStoreOp)p_attachments[i].stencil_store_op;4526vk_attachments[i].initialLayout = RD_TO_VK_LAYOUT[p_attachments[i].initial_layout];4527vk_attachments[i].finalLayout = RD_TO_VK_LAYOUT[p_attachments[i].final_layout];4528}45294530VkSubpassDescription2KHR *vk_subpasses = ALLOCA_ARRAY(VkSubpassDescription2KHR, p_subpasses.size());4531for (uint32_t i = 0; i < p_subpasses.size(); i++) {4532VkAttachmentReference2KHR *vk_subpass_input_attachments = ALLOCA_ARRAY(VkAttachmentReference2KHR, p_subpasses[i].input_references.size());4533for (uint32_t j = 0; j < p_subpasses[i].input_references.size(); j++) {4534_attachment_reference_to_vk(p_subpasses[i].input_references[j], &vk_subpass_input_attachments[j]);4535}45364537VkAttachmentReference2KHR *vk_subpass_color_attachments = ALLOCA_ARRAY(VkAttachmentReference2KHR, p_subpasses[i].color_references.size());4538for (uint32_t j = 0; j < p_subpasses[i].color_references.size(); j++) {4539_attachment_reference_to_vk(p_subpasses[i].color_references[j], &vk_subpass_color_attachments[j]);4540}45414542VkAttachmentReference2KHR *vk_subpass_resolve_attachments = ALLOCA_ARRAY(VkAttachmentReference2KHR, p_subpasses[i].resolve_references.size());4543for (uint32_t j = 0; j < p_subpasses[i].resolve_references.size(); j++) {4544_attachment_reference_to_vk(p_subpasses[i].resolve_references[j], &vk_subpass_resolve_attachments[j]);4545}45464547VkAttachmentReference2KHR *vk_subpass_depth_stencil_attachment = nullptr;4548if (p_subpasses[i].depth_stencil_reference.attachment != AttachmentReference::UNUSED) {4549vk_subpass_depth_stencil_attachment = ALLOCA_SINGLE(VkAttachmentReference2KHR);4550_attachment_reference_to_vk(p_subpasses[i].depth_stencil_reference, vk_subpass_depth_stencil_attachment);4551}45524553vk_subpasses[i] = {};4554vk_subpasses[i].sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR;4555vk_subpasses[i].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;4556vk_subpasses[i].viewMask = p_view_count == 1 ? 0 : view_mask;4557vk_subpasses[i].inputAttachmentCount = p_subpasses[i].input_references.size();4558vk_subpasses[i].pInputAttachments = vk_subpass_input_attachments;4559vk_subpasses[i].colorAttachmentCount = p_subpasses[i].color_references.size();4560vk_subpasses[i].pColorAttachments = vk_subpass_color_attachments;4561vk_subpasses[i].pResolveAttachments = vk_subpass_resolve_attachments;4562vk_subpasses[i].pDepthStencilAttachment = vk_subpass_depth_stencil_attachment;4563vk_subpasses[i].preserveAttachmentCount = p_subpasses[i].preserve_attachments.size();4564vk_subpasses[i].pPreserveAttachments = p_subpasses[i].preserve_attachments.ptr();45654566// Fragment shading rate.4567if (fsr_capabilities.attachment_supported && p_subpasses[i].fragment_shading_rate_reference.attachment != AttachmentReference::UNUSED) {4568VkAttachmentReference2KHR *vk_subpass_fsr_attachment = ALLOCA_SINGLE(VkAttachmentReference2KHR);4569*vk_subpass_fsr_attachment = {};4570vk_subpass_fsr_attachment->sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;4571vk_subpass_fsr_attachment->attachment = p_subpasses[i].fragment_shading_rate_reference.attachment;4572vk_subpass_fsr_attachment->layout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;45734574VkFragmentShadingRateAttachmentInfoKHR *vk_fsr_info = ALLOCA_SINGLE(VkFragmentShadingRateAttachmentInfoKHR);4575*vk_fsr_info = {};4576vk_fsr_info->sType = VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR;4577vk_fsr_info->pFragmentShadingRateAttachment = vk_subpass_fsr_attachment;4578vk_fsr_info->shadingRateAttachmentTexelSize.width = p_subpasses[i].fragment_shading_rate_texel_size.x;4579vk_fsr_info->shadingRateAttachmentTexelSize.height = p_subpasses[i].fragment_shading_rate_texel_size.y;45804581vk_subpasses[i].pNext = vk_fsr_info;4582}4583}45844585VkSubpassDependency2KHR *vk_subpass_dependencies = ALLOCA_ARRAY(VkSubpassDependency2KHR, p_subpass_dependencies.size());4586for (uint32_t i = 0; i < p_subpass_dependencies.size(); i++) {4587vk_subpass_dependencies[i] = {};4588vk_subpass_dependencies[i].sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2;4589vk_subpass_dependencies[i].srcSubpass = p_subpass_dependencies[i].src_subpass;4590vk_subpass_dependencies[i].dstSubpass = p_subpass_dependencies[i].dst_subpass;4591vk_subpass_dependencies[i].srcStageMask = _rd_to_vk_pipeline_stages(p_subpass_dependencies[i].src_stages);4592vk_subpass_dependencies[i].dstStageMask = _rd_to_vk_pipeline_stages(p_subpass_dependencies[i].dst_stages);4593vk_subpass_dependencies[i].srcAccessMask = _rd_to_vk_access_flags(p_subpass_dependencies[i].src_access);4594vk_subpass_dependencies[i].dstAccessMask = _rd_to_vk_access_flags(p_subpass_dependencies[i].dst_access);4595}45964597VkRenderPassCreateInfo2KHR create_info = {};4598create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR;4599create_info.attachmentCount = p_attachments.size();4600create_info.pAttachments = vk_attachments;4601create_info.subpassCount = p_subpasses.size();4602create_info.pSubpasses = vk_subpasses;4603create_info.dependencyCount = p_subpass_dependencies.size();4604create_info.pDependencies = vk_subpass_dependencies;4605create_info.correlatedViewMaskCount = p_view_count == 1 ? 0 : 1;4606create_info.pCorrelatedViewMasks = p_view_count == 1 ? nullptr : &correlation_mask;46074608// Multiview.4609if (p_view_count > 1 && device_functions.CreateRenderPass2KHR == nullptr) {4610// This is only required when not using vkCreateRenderPass2.4611// We add it if vkCreateRenderPass2KHR is not supported,4612// resulting this in being passed to our vkCreateRenderPass fallback.46134614uint32_t *vk_view_masks = ALLOCA_ARRAY(uint32_t, p_subpasses.size());4615for (uint32_t i = 0; i < p_subpasses.size(); i++) {4616vk_view_masks[i] = view_mask;4617}46184619VkRenderPassMultiviewCreateInfo *multiview_create_info = ALLOCA_SINGLE(VkRenderPassMultiviewCreateInfo);4620*multiview_create_info = {};4621multiview_create_info->sType = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;4622multiview_create_info->subpassCount = p_subpasses.size();4623multiview_create_info->pViewMasks = vk_view_masks;4624multiview_create_info->correlationMaskCount = 1;4625multiview_create_info->pCorrelationMasks = &correlation_mask;46264627create_info.pNext = multiview_create_info;4628}46294630// Fragment density map.4631bool uses_fragment_density_map = fdm_capabilities.attachment_supported && p_fragment_density_map_attachment.attachment != AttachmentReference::UNUSED;4632if (uses_fragment_density_map) {4633VkRenderPassFragmentDensityMapCreateInfoEXT *vk_fdm_info = ALLOCA_SINGLE(VkRenderPassFragmentDensityMapCreateInfoEXT);4634vk_fdm_info->sType = VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT;4635vk_fdm_info->fragmentDensityMapAttachment.attachment = p_fragment_density_map_attachment.attachment;4636vk_fdm_info->fragmentDensityMapAttachment.layout = RD_TO_VK_LAYOUT[p_fragment_density_map_attachment.layout];4637vk_fdm_info->pNext = create_info.pNext;4638create_info.pNext = vk_fdm_info;4639}46404641VkRenderPass vk_render_pass = VK_NULL_HANDLE;4642VkResult res = _create_render_pass(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_RENDER_PASS), &vk_render_pass);4643ERR_FAIL_COND_V_MSG(res, RenderPassID(), "vkCreateRenderPass2KHR failed with error " + itos(res) + ".");46444645RenderPassInfo *render_pass = VersatileResource::allocate<RenderPassInfo>(resources_allocator);4646render_pass->vk_render_pass = vk_render_pass;4647return RenderPassID(render_pass);4648}46494650void RenderingDeviceDriverVulkan::render_pass_free(RenderPassID p_render_pass) {4651RenderPassInfo *render_pass = (RenderPassInfo *)(p_render_pass.id);4652vkDestroyRenderPass(vk_device, render_pass->vk_render_pass, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_RENDER_PASS));4653VersatileResource::free<RenderPassInfo>(resources_allocator, render_pass);4654}46554656// ----- COMMANDS -----46574658static_assert(ARRAYS_COMPATIBLE_FIELDWISE(RDD::RenderPassClearValue, VkClearValue));46594660void 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) {4661CommandBufferInfo *command_buffer = (CommandBufferInfo *)(p_cmd_buffer.id);4662RenderPassInfo *render_pass = (RenderPassInfo *)(p_render_pass.id);4663Framebuffer *framebuffer = (Framebuffer *)(p_framebuffer.id);46644665if (framebuffer->swap_chain_acquired) {4666// Insert a barrier to wait for the acquisition of the framebuffer before the render pass begins.4667VkImageMemoryBarrier image_barrier = {};4668image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;4669image_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;4670image_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;4671image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;4672image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;4673image_barrier.image = framebuffer->swap_chain_image;4674image_barrier.subresourceRange = framebuffer->swap_chain_image_subresource_range;4675vkCmdPipelineBarrier(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);4676framebuffer->swap_chain_acquired = false;4677}46784679VkRenderPassBeginInfo render_pass_begin = {};4680render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;4681render_pass_begin.renderPass = render_pass->vk_render_pass;4682render_pass_begin.framebuffer = framebuffer->vk_framebuffer;46834684render_pass_begin.renderArea.offset.x = p_rect.position.x;4685render_pass_begin.renderArea.offset.y = p_rect.position.y;4686render_pass_begin.renderArea.extent.width = p_rect.size.x;4687render_pass_begin.renderArea.extent.height = p_rect.size.y;46884689render_pass_begin.clearValueCount = p_clear_values.size();4690render_pass_begin.pClearValues = (const VkClearValue *)p_clear_values.ptr();46914692VkSubpassContents vk_subpass_contents = p_cmd_buffer_type == COMMAND_BUFFER_TYPE_PRIMARY ? VK_SUBPASS_CONTENTS_INLINE : VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;4693vkCmdBeginRenderPass(command_buffer->vk_command_buffer, &render_pass_begin, vk_subpass_contents);46944695command_buffer->active_framebuffer = framebuffer;4696command_buffer->active_render_pass = render_pass;46974698#if PRINT_NATIVE_COMMANDS4699print_line(vformat("vkCmdBeginRenderPass Pass 0x%uX Framebuffer 0x%uX", p_render_pass.id, p_framebuffer.id));4700#endif4701}47024703void RenderingDeviceDriverVulkan::command_end_render_pass(CommandBufferID p_cmd_buffer) {4704CommandBufferInfo *command_buffer = (CommandBufferInfo *)(p_cmd_buffer.id);4705DEV_ASSERT(command_buffer->active_framebuffer != nullptr && "A framebuffer must be active.");4706DEV_ASSERT(command_buffer->active_render_pass != nullptr && "A render pass must be active.");47074708vkCmdEndRenderPass(command_buffer->vk_command_buffer);47094710command_buffer->active_render_pass = nullptr;4711command_buffer->active_framebuffer = nullptr;47124713#if PRINT_NATIVE_COMMANDS4714print_line("vkCmdEndRenderPass");4715#endif4716}47174718void RenderingDeviceDriverVulkan::command_next_render_subpass(CommandBufferID p_cmd_buffer, CommandBufferType p_cmd_buffer_type) {4719const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4720VkSubpassContents vk_subpass_contents = p_cmd_buffer_type == COMMAND_BUFFER_TYPE_PRIMARY ? VK_SUBPASS_CONTENTS_INLINE : VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;4721vkCmdNextSubpass(command_buffer->vk_command_buffer, vk_subpass_contents);4722}47234724void RenderingDeviceDriverVulkan::command_render_set_viewport(CommandBufferID p_cmd_buffer, VectorView<Rect2i> p_viewports) {4725const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4726VkViewport *vk_viewports = ALLOCA_ARRAY(VkViewport, p_viewports.size());4727for (uint32_t i = 0; i < p_viewports.size(); i++) {4728vk_viewports[i] = {};4729vk_viewports[i].x = p_viewports[i].position.x;4730vk_viewports[i].y = p_viewports[i].position.y;4731vk_viewports[i].width = p_viewports[i].size.x;4732vk_viewports[i].height = p_viewports[i].size.y;4733vk_viewports[i].minDepth = 0.0f;4734vk_viewports[i].maxDepth = 1.0f;4735}4736vkCmdSetViewport(command_buffer->vk_command_buffer, 0, p_viewports.size(), vk_viewports);4737}47384739void RenderingDeviceDriverVulkan::command_render_set_scissor(CommandBufferID p_cmd_buffer, VectorView<Rect2i> p_scissors) {4740const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4741vkCmdSetScissor(command_buffer->vk_command_buffer, 0, p_scissors.size(), (VkRect2D *)p_scissors.ptr());4742}47434744void RenderingDeviceDriverVulkan::command_render_clear_attachments(CommandBufferID p_cmd_buffer, VectorView<AttachmentClear> p_attachment_clears, VectorView<Rect2i> p_rects) {4745const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;47464747VkClearAttachment *vk_clears = ALLOCA_ARRAY(VkClearAttachment, p_attachment_clears.size());4748for (uint32_t i = 0; i < p_attachment_clears.size(); i++) {4749vk_clears[i] = {};4750memcpy(&vk_clears[i].clearValue, &p_attachment_clears[i].value, sizeof(VkClearValue));4751vk_clears[i].colorAttachment = p_attachment_clears[i].color_attachment;4752vk_clears[i].aspectMask = p_attachment_clears[i].aspect;4753}47544755VkClearRect *vk_rects = ALLOCA_ARRAY(VkClearRect, p_rects.size());4756for (uint32_t i = 0; i < p_rects.size(); i++) {4757vk_rects[i] = {};4758vk_rects[i].rect.offset.x = p_rects[i].position.x;4759vk_rects[i].rect.offset.y = p_rects[i].position.y;4760vk_rects[i].rect.extent.width = p_rects[i].size.x;4761vk_rects[i].rect.extent.height = p_rects[i].size.y;4762vk_rects[i].baseArrayLayer = 0;4763vk_rects[i].layerCount = 1;4764}47654766vkCmdClearAttachments(command_buffer->vk_command_buffer, p_attachment_clears.size(), vk_clears, p_rects.size(), vk_rects);4767}47684769void RenderingDeviceDriverVulkan::command_bind_render_pipeline(CommandBufferID p_cmd_buffer, PipelineID p_pipeline) {4770const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4771vkCmdBindPipeline(command_buffer->vk_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, (VkPipeline)p_pipeline.id);4772}47734774void RenderingDeviceDriverVulkan::command_bind_render_uniform_set(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index) {4775const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4776const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;4777const UniformSetInfo *usi = (const UniformSetInfo *)p_uniform_set.id;4778vkCmdBindDescriptorSets(command_buffer->vk_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, shader_info->vk_pipeline_layout, p_set_index, 1, &usi->vk_descriptor_set, 0, nullptr);4779}47804781void 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) {4782if (p_set_count == 0) {4783return;4784}47854786thread_local LocalVector<VkDescriptorSet> sets;4787sets.clear();4788sets.resize(p_set_count);47894790for (uint32_t i = 0; i < p_set_count; i++) {4791sets[i] = ((const UniformSetInfo *)p_uniform_sets[i].id)->vk_descriptor_set;4792}47934794const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4795const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;4796vkCmdBindDescriptorSets(command_buffer->vk_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, shader_info->vk_pipeline_layout, p_first_set_index, p_set_count, &sets[0], 0, nullptr);4797}47984799void 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) {4800const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4801vkCmdDraw(command_buffer->vk_command_buffer, p_vertex_count, p_instance_count, p_base_vertex, p_first_instance);4802}48034804void 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) {4805const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4806vkCmdDrawIndexed(command_buffer->vk_command_buffer, p_index_count, p_instance_count, p_first_index, p_vertex_offset, p_first_instance);4807}48084809void 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) {4810const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4811const BufferInfo *buf_info = (const BufferInfo *)p_indirect_buffer.id;4812vkCmdDrawIndexedIndirect(command_buffer->vk_command_buffer, buf_info->vk_buffer, p_offset, p_draw_count, p_stride);4813}48144815void 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) {4816const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4817const BufferInfo *indirect_buf_info = (const BufferInfo *)p_indirect_buffer.id;4818const BufferInfo *count_buf_info = (const BufferInfo *)p_count_buffer.id;4819vkCmdDrawIndexedIndirectCount(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);4820}48214822void 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) {4823const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4824const BufferInfo *buf_info = (const BufferInfo *)p_indirect_buffer.id;4825vkCmdDrawIndirect(command_buffer->vk_command_buffer, buf_info->vk_buffer, p_offset, p_draw_count, p_stride);4826}48274828void 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) {4829const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4830const BufferInfo *indirect_buf_info = (const BufferInfo *)p_indirect_buffer.id;4831const BufferInfo *count_buf_info = (const BufferInfo *)p_count_buffer.id;4832vkCmdDrawIndirectCount(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);4833}48344835void RenderingDeviceDriverVulkan::command_render_bind_vertex_buffers(CommandBufferID p_cmd_buffer, uint32_t p_binding_count, const BufferID *p_buffers, const uint64_t *p_offsets) {4836const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;48374838VkBuffer *vk_buffers = ALLOCA_ARRAY(VkBuffer, p_binding_count);4839for (uint32_t i = 0; i < p_binding_count; i++) {4840vk_buffers[i] = ((const BufferInfo *)p_buffers[i].id)->vk_buffer;4841}4842vkCmdBindVertexBuffers(command_buffer->vk_command_buffer, 0, p_binding_count, vk_buffers, p_offsets);4843}48444845void RenderingDeviceDriverVulkan::command_render_bind_index_buffer(CommandBufferID p_cmd_buffer, BufferID p_buffer, IndexBufferFormat p_format, uint64_t p_offset) {4846const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4847const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;4848vkCmdBindIndexBuffer(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);4849}48504851void RenderingDeviceDriverVulkan::command_render_set_blend_constants(CommandBufferID p_cmd_buffer, const Color &p_constants) {4852const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4853vkCmdSetBlendConstants(command_buffer->vk_command_buffer, p_constants.components);4854}48554856void RenderingDeviceDriverVulkan::command_render_set_line_width(CommandBufferID p_cmd_buffer, float p_width) {4857const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;4858vkCmdSetLineWidth(command_buffer->vk_command_buffer, p_width);4859}48604861// ----- PIPELINE -----48624863static const VkPrimitiveTopology RD_TO_VK_PRIMITIVE[RDD::RENDER_PRIMITIVE_MAX] = {4864VK_PRIMITIVE_TOPOLOGY_POINT_LIST,4865VK_PRIMITIVE_TOPOLOGY_LINE_LIST,4866VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,4867VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,4868VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,4869VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,4870VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,4871VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,4872VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,4873VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,4874VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,4875};48764877// RDD::PolygonCullMode == VkCullModeFlagBits.4878static_assert(ENUM_MEMBERS_EQUAL(RDD::POLYGON_CULL_DISABLED, VK_CULL_MODE_NONE));4879static_assert(ENUM_MEMBERS_EQUAL(RDD::POLYGON_CULL_FRONT, VK_CULL_MODE_FRONT_BIT));4880static_assert(ENUM_MEMBERS_EQUAL(RDD::POLYGON_CULL_BACK, VK_CULL_MODE_BACK_BIT));48814882// RDD::StencilOperation == VkStencilOp.4883static_assert(ENUM_MEMBERS_EQUAL(RDD::STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP));4884static_assert(ENUM_MEMBERS_EQUAL(RDD::STENCIL_OP_ZERO, VK_STENCIL_OP_ZERO));4885static_assert(ENUM_MEMBERS_EQUAL(RDD::STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE));4886static_assert(ENUM_MEMBERS_EQUAL(RDD::STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP));4887static_assert(ENUM_MEMBERS_EQUAL(RDD::STENCIL_OP_DECREMENT_AND_CLAMP, VK_STENCIL_OP_DECREMENT_AND_CLAMP));4888static_assert(ENUM_MEMBERS_EQUAL(RDD::STENCIL_OP_INVERT, VK_STENCIL_OP_INVERT));4889static_assert(ENUM_MEMBERS_EQUAL(RDD::STENCIL_OP_INCREMENT_AND_WRAP, VK_STENCIL_OP_INCREMENT_AND_WRAP));4890static_assert(ENUM_MEMBERS_EQUAL(RDD::STENCIL_OP_DECREMENT_AND_WRAP, VK_STENCIL_OP_DECREMENT_AND_WRAP));48914892// RDD::LogicOperation == VkLogicOp.4893static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_CLEAR, VK_LOGIC_OP_CLEAR));4894static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_AND, VK_LOGIC_OP_AND));4895static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_AND_REVERSE, VK_LOGIC_OP_AND_REVERSE));4896static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_COPY, VK_LOGIC_OP_COPY));4897static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_AND_INVERTED, VK_LOGIC_OP_AND_INVERTED));4898static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_NO_OP, VK_LOGIC_OP_NO_OP));4899static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_XOR, VK_LOGIC_OP_XOR));4900static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_OR, VK_LOGIC_OP_OR));4901static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_NOR, VK_LOGIC_OP_NOR));4902static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_EQUIVALENT, VK_LOGIC_OP_EQUIVALENT));4903static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_INVERT, VK_LOGIC_OP_INVERT));4904static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_OR_REVERSE, VK_LOGIC_OP_OR_REVERSE));4905static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_COPY_INVERTED, VK_LOGIC_OP_COPY_INVERTED));4906static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_OR_INVERTED, VK_LOGIC_OP_OR_INVERTED));4907static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_NAND, VK_LOGIC_OP_NAND));4908static_assert(ENUM_MEMBERS_EQUAL(RDD::LOGIC_OP_SET, VK_LOGIC_OP_SET));49094910// RDD::BlendFactor == VkBlendFactor.4911static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ZERO));4912static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ONE));4913static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_SRC_COLOR, VK_BLEND_FACTOR_SRC_COLOR));4914static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR));4915static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_DST_COLOR, VK_BLEND_FACTOR_DST_COLOR));4916static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE_MINUS_DST_COLOR, VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR));4917static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_SRC_ALPHA));4918static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA));4919static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_DST_ALPHA, VK_BLEND_FACTOR_DST_ALPHA));4920static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE_MINUS_DST_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA));4921static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_CONSTANT_COLOR, VK_BLEND_FACTOR_CONSTANT_COLOR));4922static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR));4923static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_CONSTANT_ALPHA, VK_BLEND_FACTOR_CONSTANT_ALPHA));4924static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA));4925static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_SRC_ALPHA_SATURATE, VK_BLEND_FACTOR_SRC_ALPHA_SATURATE));4926static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_SRC1_COLOR, VK_BLEND_FACTOR_SRC1_COLOR));4927static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE_MINUS_SRC1_COLOR, VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR));4928static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_SRC1_ALPHA, VK_BLEND_FACTOR_SRC1_ALPHA));4929static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA));49304931// RDD::BlendOperation == VkBlendOp.4932static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_OP_ADD, VK_BLEND_OP_ADD));4933static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_OP_SUBTRACT, VK_BLEND_OP_SUBTRACT));4934static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_OP_REVERSE_SUBTRACT, VK_BLEND_OP_REVERSE_SUBTRACT));4935static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_OP_MINIMUM, VK_BLEND_OP_MIN));4936static_assert(ENUM_MEMBERS_EQUAL(RDD::BLEND_OP_MAXIMUM, VK_BLEND_OP_MAX));49374938RDD::PipelineID RenderingDeviceDriverVulkan::render_pipeline_create(4939ShaderID p_shader,4940VertexFormatID p_vertex_format,4941RenderPrimitive p_render_primitive,4942PipelineRasterizationState p_rasterization_state,4943PipelineMultisampleState p_multisample_state,4944PipelineDepthStencilState p_depth_stencil_state,4945PipelineColorBlendState p_blend_state,4946VectorView<int32_t> p_color_attachments,4947BitField<PipelineDynamicStateFlags> p_dynamic_state,4948RenderPassID p_render_pass,4949uint32_t p_render_subpass,4950VectorView<PipelineSpecializationConstant> p_specialization_constants) {4951// Vertex.4952const VkPipelineVertexInputStateCreateInfo *vertex_input_state_create_info = nullptr;4953if (p_vertex_format.id) {4954const VertexFormatInfo *vf_info = (const VertexFormatInfo *)p_vertex_format.id;4955vertex_input_state_create_info = &vf_info->vk_create_info;4956} else {4957VkPipelineVertexInputStateCreateInfo *null_vertex_input_state = ALLOCA_SINGLE(VkPipelineVertexInputStateCreateInfo);4958*null_vertex_input_state = {};4959null_vertex_input_state->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;4960vertex_input_state_create_info = null_vertex_input_state;4961}49624963// Input assembly.4964VkPipelineInputAssemblyStateCreateInfo input_assembly_create_info = {};4965input_assembly_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;4966input_assembly_create_info.topology = RD_TO_VK_PRIMITIVE[p_render_primitive];4967input_assembly_create_info.primitiveRestartEnable = (p_render_primitive == RENDER_PRIMITIVE_TRIANGLE_STRIPS_WITH_RESTART_INDEX);49684969// Tessellation.4970VkPipelineTessellationStateCreateInfo tessellation_create_info = {};4971tessellation_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;4972ERR_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());4973tessellation_create_info.patchControlPoints = p_rasterization_state.patch_control_points;49744975// Viewport.4976VkPipelineViewportStateCreateInfo viewport_state_create_info = {};4977viewport_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;4978viewport_state_create_info.viewportCount = 1; // If VR extensions are supported at some point, this will have to be customizable in the framebuffer format.4979viewport_state_create_info.scissorCount = 1;49804981// Rasterization.4982VkPipelineRasterizationStateCreateInfo rasterization_state_create_info = {};4983rasterization_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;4984rasterization_state_create_info.depthClampEnable = p_rasterization_state.enable_depth_clamp;4985rasterization_state_create_info.rasterizerDiscardEnable = p_rasterization_state.discard_primitives;4986rasterization_state_create_info.polygonMode = p_rasterization_state.wireframe ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL;4987rasterization_state_create_info.cullMode = (PolygonCullMode)p_rasterization_state.cull_mode;4988rasterization_state_create_info.frontFace = (p_rasterization_state.front_face == POLYGON_FRONT_FACE_CLOCKWISE ? VK_FRONT_FACE_CLOCKWISE : VK_FRONT_FACE_COUNTER_CLOCKWISE);4989rasterization_state_create_info.depthBiasEnable = p_rasterization_state.depth_bias_enabled;4990rasterization_state_create_info.depthBiasConstantFactor = p_rasterization_state.depth_bias_constant_factor;4991rasterization_state_create_info.depthBiasClamp = p_rasterization_state.depth_bias_clamp;4992rasterization_state_create_info.depthBiasSlopeFactor = p_rasterization_state.depth_bias_slope_factor;4993rasterization_state_create_info.lineWidth = p_rasterization_state.line_width;49944995// Multisample.4996VkPipelineMultisampleStateCreateInfo multisample_state_create_info = {};4997multisample_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;4998multisample_state_create_info.rasterizationSamples = _ensure_supported_sample_count(p_multisample_state.sample_count);4999multisample_state_create_info.sampleShadingEnable = p_multisample_state.enable_sample_shading;5000multisample_state_create_info.minSampleShading = p_multisample_state.min_sample_shading;5001if (p_multisample_state.sample_mask.size()) {5002static_assert(ARRAYS_COMPATIBLE(uint32_t, VkSampleMask));5003multisample_state_create_info.pSampleMask = p_multisample_state.sample_mask.ptr();5004} else {5005multisample_state_create_info.pSampleMask = nullptr;5006}5007multisample_state_create_info.alphaToCoverageEnable = p_multisample_state.enable_alpha_to_coverage;5008multisample_state_create_info.alphaToOneEnable = p_multisample_state.enable_alpha_to_one;50095010// Depth stencil.50115012VkPipelineDepthStencilStateCreateInfo depth_stencil_state_create_info = {};5013depth_stencil_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;5014depth_stencil_state_create_info.depthTestEnable = p_depth_stencil_state.enable_depth_test;5015depth_stencil_state_create_info.depthWriteEnable = p_depth_stencil_state.enable_depth_write;5016depth_stencil_state_create_info.depthCompareOp = (VkCompareOp)p_depth_stencil_state.depth_compare_operator;5017depth_stencil_state_create_info.depthBoundsTestEnable = p_depth_stencil_state.enable_depth_range;5018depth_stencil_state_create_info.stencilTestEnable = p_depth_stencil_state.enable_stencil;50195020depth_stencil_state_create_info.front.failOp = (VkStencilOp)p_depth_stencil_state.front_op.fail;5021depth_stencil_state_create_info.front.passOp = (VkStencilOp)p_depth_stencil_state.front_op.pass;5022depth_stencil_state_create_info.front.depthFailOp = (VkStencilOp)p_depth_stencil_state.front_op.depth_fail;5023depth_stencil_state_create_info.front.compareOp = (VkCompareOp)p_depth_stencil_state.front_op.compare;5024depth_stencil_state_create_info.front.compareMask = p_depth_stencil_state.front_op.compare_mask;5025depth_stencil_state_create_info.front.writeMask = p_depth_stencil_state.front_op.write_mask;5026depth_stencil_state_create_info.front.reference = p_depth_stencil_state.front_op.reference;50275028depth_stencil_state_create_info.back.failOp = (VkStencilOp)p_depth_stencil_state.back_op.fail;5029depth_stencil_state_create_info.back.passOp = (VkStencilOp)p_depth_stencil_state.back_op.pass;5030depth_stencil_state_create_info.back.depthFailOp = (VkStencilOp)p_depth_stencil_state.back_op.depth_fail;5031depth_stencil_state_create_info.back.compareOp = (VkCompareOp)p_depth_stencil_state.back_op.compare;5032depth_stencil_state_create_info.back.compareMask = p_depth_stencil_state.back_op.compare_mask;5033depth_stencil_state_create_info.back.writeMask = p_depth_stencil_state.back_op.write_mask;5034depth_stencil_state_create_info.back.reference = p_depth_stencil_state.back_op.reference;50355036depth_stencil_state_create_info.minDepthBounds = p_depth_stencil_state.depth_range_min;5037depth_stencil_state_create_info.maxDepthBounds = p_depth_stencil_state.depth_range_max;50385039// Blend state.50405041VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = {};5042color_blend_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;5043color_blend_state_create_info.logicOpEnable = p_blend_state.enable_logic_op;5044color_blend_state_create_info.logicOp = (VkLogicOp)p_blend_state.logic_op;50455046VkPipelineColorBlendAttachmentState *vk_attachment_states = ALLOCA_ARRAY(VkPipelineColorBlendAttachmentState, p_color_attachments.size());5047{5048for (uint32_t i = 0; i < p_color_attachments.size(); i++) {5049vk_attachment_states[i] = {};5050if (p_color_attachments[i] != ATTACHMENT_UNUSED) {5051vk_attachment_states[i].blendEnable = p_blend_state.attachments[i].enable_blend;50525053vk_attachment_states[i].srcColorBlendFactor = (VkBlendFactor)p_blend_state.attachments[i].src_color_blend_factor;5054vk_attachment_states[i].dstColorBlendFactor = (VkBlendFactor)p_blend_state.attachments[i].dst_color_blend_factor;5055vk_attachment_states[i].colorBlendOp = (VkBlendOp)p_blend_state.attachments[i].color_blend_op;50565057vk_attachment_states[i].srcAlphaBlendFactor = (VkBlendFactor)p_blend_state.attachments[i].src_alpha_blend_factor;5058vk_attachment_states[i].dstAlphaBlendFactor = (VkBlendFactor)p_blend_state.attachments[i].dst_alpha_blend_factor;5059vk_attachment_states[i].alphaBlendOp = (VkBlendOp)p_blend_state.attachments[i].alpha_blend_op;50605061if (p_blend_state.attachments[i].write_r) {5062vk_attachment_states[i].colorWriteMask |= VK_COLOR_COMPONENT_R_BIT;5063}5064if (p_blend_state.attachments[i].write_g) {5065vk_attachment_states[i].colorWriteMask |= VK_COLOR_COMPONENT_G_BIT;5066}5067if (p_blend_state.attachments[i].write_b) {5068vk_attachment_states[i].colorWriteMask |= VK_COLOR_COMPONENT_B_BIT;5069}5070if (p_blend_state.attachments[i].write_a) {5071vk_attachment_states[i].colorWriteMask |= VK_COLOR_COMPONENT_A_BIT;5072}5073}5074}5075}5076color_blend_state_create_info.attachmentCount = p_color_attachments.size();5077color_blend_state_create_info.pAttachments = vk_attachment_states;50785079color_blend_state_create_info.blendConstants[0] = p_blend_state.blend_constant.r;5080color_blend_state_create_info.blendConstants[1] = p_blend_state.blend_constant.g;5081color_blend_state_create_info.blendConstants[2] = p_blend_state.blend_constant.b;5082color_blend_state_create_info.blendConstants[3] = p_blend_state.blend_constant.a;50835084// Dynamic state.50855086VkPipelineDynamicStateCreateInfo dynamic_state_create_info = {};5087dynamic_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;50885089static const uint32_t MAX_DYN_STATE_COUNT = 9;5090VkDynamicState *vk_dynamic_states = ALLOCA_ARRAY(VkDynamicState, MAX_DYN_STATE_COUNT);5091uint32_t vk_dynamic_states_count = 0;50925093vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_VIEWPORT; // Viewport and scissor are always dynamic.5094vk_dynamic_states_count++;5095vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_SCISSOR;5096vk_dynamic_states_count++;5097if (p_dynamic_state.has_flag(DYNAMIC_STATE_LINE_WIDTH)) {5098vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_LINE_WIDTH;5099vk_dynamic_states_count++;5100}5101if (p_dynamic_state.has_flag(DYNAMIC_STATE_DEPTH_BIAS)) {5102vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_DEPTH_BIAS;5103vk_dynamic_states_count++;5104}5105if (p_dynamic_state.has_flag(DYNAMIC_STATE_BLEND_CONSTANTS)) {5106vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_BLEND_CONSTANTS;5107vk_dynamic_states_count++;5108}5109if (p_dynamic_state.has_flag(DYNAMIC_STATE_DEPTH_BOUNDS)) {5110vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_DEPTH_BOUNDS;5111vk_dynamic_states_count++;5112}5113if (p_dynamic_state.has_flag(DYNAMIC_STATE_STENCIL_COMPARE_MASK)) {5114vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK;5115vk_dynamic_states_count++;5116}5117if (p_dynamic_state.has_flag(DYNAMIC_STATE_STENCIL_WRITE_MASK)) {5118vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_STENCIL_WRITE_MASK;5119vk_dynamic_states_count++;5120}5121if (p_dynamic_state.has_flag(DYNAMIC_STATE_STENCIL_REFERENCE)) {5122vk_dynamic_states[vk_dynamic_states_count] = VK_DYNAMIC_STATE_STENCIL_REFERENCE;5123vk_dynamic_states_count++;5124}5125DEV_ASSERT(vk_dynamic_states_count <= MAX_DYN_STATE_COUNT);51265127dynamic_state_create_info.dynamicStateCount = vk_dynamic_states_count;5128dynamic_state_create_info.pDynamicStates = vk_dynamic_states;51295130void *graphics_pipeline_nextptr = nullptr;51315132if (fsr_capabilities.attachment_supported) {5133// Fragment shading rate.5134// If FSR is used, this defines how the different FSR types are combined.5135// combinerOps[0] decides how we use the output of pipeline and primitive (drawcall) FSR.5136// combinerOps[1] decides how we use the output of combinerOps[0] and our attachment FSR.51375138VkPipelineFragmentShadingRateStateCreateInfoKHR *fsr_create_info = ALLOCA_SINGLE(VkPipelineFragmentShadingRateStateCreateInfoKHR);5139*fsr_create_info = {};5140fsr_create_info->sType = VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR;5141fsr_create_info->fragmentSize = { 4, 4 };5142fsr_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.5143fsr_create_info->combinerOps[1] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR; // Always use the outcome of attachment FSR if enabled.51445145graphics_pipeline_nextptr = fsr_create_info;5146}51475148// Finally, pipeline create info.51495150const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;51515152VkGraphicsPipelineCreateInfo pipeline_create_info = {};51535154pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;5155pipeline_create_info.pNext = graphics_pipeline_nextptr;5156pipeline_create_info.stageCount = shader_info->vk_stages_create_info.size();51575158ERR_FAIL_COND_V_MSG(pipeline_create_info.stageCount == 0, PipelineID(),5159"Cannot create pipeline without shader module, please make sure shader modules are destroyed only after all associated pipelines are created.");5160VkPipelineShaderStageCreateInfo *vk_pipeline_stages = ALLOCA_ARRAY(VkPipelineShaderStageCreateInfo, shader_info->vk_stages_create_info.size());51615162for (uint32_t i = 0; i < shader_info->vk_stages_create_info.size(); i++) {5163vk_pipeline_stages[i] = shader_info->vk_stages_create_info[i];51645165if (p_specialization_constants.size()) {5166VkSpecializationMapEntry *specialization_map_entries = ALLOCA_ARRAY(VkSpecializationMapEntry, p_specialization_constants.size());5167for (uint32_t j = 0; j < p_specialization_constants.size(); j++) {5168specialization_map_entries[j] = {};5169specialization_map_entries[j].constantID = p_specialization_constants[j].constant_id;5170specialization_map_entries[j].offset = (const char *)&p_specialization_constants[j].int_value - (const char *)p_specialization_constants.ptr();5171specialization_map_entries[j].size = sizeof(uint32_t);5172}51735174VkSpecializationInfo *specialization_info = ALLOCA_SINGLE(VkSpecializationInfo);5175*specialization_info = {};5176specialization_info->dataSize = p_specialization_constants.size() * sizeof(PipelineSpecializationConstant);5177specialization_info->pData = p_specialization_constants.ptr();5178specialization_info->mapEntryCount = p_specialization_constants.size();5179specialization_info->pMapEntries = specialization_map_entries;51805181vk_pipeline_stages[i].pSpecializationInfo = specialization_info;5182}5183}51845185const RenderPassInfo *render_pass = (const RenderPassInfo *)(p_render_pass.id);5186pipeline_create_info.pStages = vk_pipeline_stages;5187pipeline_create_info.pVertexInputState = vertex_input_state_create_info;5188pipeline_create_info.pInputAssemblyState = &input_assembly_create_info;5189pipeline_create_info.pTessellationState = &tessellation_create_info;5190pipeline_create_info.pViewportState = &viewport_state_create_info;5191pipeline_create_info.pRasterizationState = &rasterization_state_create_info;5192pipeline_create_info.pMultisampleState = &multisample_state_create_info;5193pipeline_create_info.pDepthStencilState = &depth_stencil_state_create_info;5194pipeline_create_info.pColorBlendState = &color_blend_state_create_info;5195pipeline_create_info.pDynamicState = &dynamic_state_create_info;5196pipeline_create_info.layout = shader_info->vk_pipeline_layout;5197pipeline_create_info.renderPass = render_pass->vk_render_pass;5198pipeline_create_info.subpass = p_render_subpass;51995200// ---52015202VkPipeline vk_pipeline = VK_NULL_HANDLE;5203VkResult err = vkCreateGraphicsPipelines(vk_device, pipelines_cache.vk_cache, 1, &pipeline_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE), &vk_pipeline);5204ERR_FAIL_COND_V_MSG(err, PipelineID(), "vkCreateGraphicsPipelines failed with error " + itos(err) + ".");52055206return PipelineID(vk_pipeline);5207}52085209/*****************/5210/**** COMPUTE ****/5211/*****************/52125213// ----- COMMANDS -----52145215void RenderingDeviceDriverVulkan::command_bind_compute_pipeline(CommandBufferID p_cmd_buffer, PipelineID p_pipeline) {5216const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5217vkCmdBindPipeline(command_buffer->vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, (VkPipeline)p_pipeline.id);5218}52195220void RenderingDeviceDriverVulkan::command_bind_compute_uniform_set(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index) {5221const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5222const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;5223const UniformSetInfo *usi = (const UniformSetInfo *)p_uniform_set.id;5224vkCmdBindDescriptorSets(command_buffer->vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, shader_info->vk_pipeline_layout, p_set_index, 1, &usi->vk_descriptor_set, 0, nullptr);5225}52265227void 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) {5228if (p_set_count == 0) {5229return;5230}52315232thread_local LocalVector<VkDescriptorSet> sets;5233sets.clear();5234sets.resize(p_set_count);52355236for (uint32_t i = 0; i < p_set_count; i++) {5237sets[i] = ((const UniformSetInfo *)p_uniform_sets[i].id)->vk_descriptor_set;5238}52395240const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5241const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;5242vkCmdBindDescriptorSets(command_buffer->vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, shader_info->vk_pipeline_layout, p_first_set_index, p_set_count, &sets[0], 0, nullptr);5243}52445245void RenderingDeviceDriverVulkan::command_compute_dispatch(CommandBufferID p_cmd_buffer, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups) {5246const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5247vkCmdDispatch(command_buffer->vk_command_buffer, p_x_groups, p_y_groups, p_z_groups);5248}52495250void RenderingDeviceDriverVulkan::command_compute_dispatch_indirect(CommandBufferID p_cmd_buffer, BufferID p_indirect_buffer, uint64_t p_offset) {5251const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5252const BufferInfo *buf_info = (const BufferInfo *)p_indirect_buffer.id;5253vkCmdDispatchIndirect(command_buffer->vk_command_buffer, buf_info->vk_buffer, p_offset);5254}52555256// ----- PIPELINE -----52575258RDD::PipelineID RenderingDeviceDriverVulkan::compute_pipeline_create(ShaderID p_shader, VectorView<PipelineSpecializationConstant> p_specialization_constants) {5259const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;52605261VkComputePipelineCreateInfo pipeline_create_info = {};5262pipeline_create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;5263pipeline_create_info.stage = shader_info->vk_stages_create_info[0];5264pipeline_create_info.layout = shader_info->vk_pipeline_layout;52655266if (p_specialization_constants.size()) {5267VkSpecializationMapEntry *specialization_map_entries = ALLOCA_ARRAY(VkSpecializationMapEntry, p_specialization_constants.size());5268for (uint32_t i = 0; i < p_specialization_constants.size(); i++) {5269specialization_map_entries[i] = {};5270specialization_map_entries[i].constantID = p_specialization_constants[i].constant_id;5271specialization_map_entries[i].offset = (const char *)&p_specialization_constants[i].int_value - (const char *)p_specialization_constants.ptr();5272specialization_map_entries[i].size = sizeof(uint32_t);5273}52745275VkSpecializationInfo *specialization_info = ALLOCA_SINGLE(VkSpecializationInfo);5276*specialization_info = {};5277specialization_info->dataSize = p_specialization_constants.size() * sizeof(PipelineSpecializationConstant);5278specialization_info->pData = p_specialization_constants.ptr();5279specialization_info->mapEntryCount = p_specialization_constants.size();5280specialization_info->pMapEntries = specialization_map_entries;52815282pipeline_create_info.stage.pSpecializationInfo = specialization_info;5283}52845285VkPipeline vk_pipeline = VK_NULL_HANDLE;5286VkResult err = vkCreateComputePipelines(vk_device, pipelines_cache.vk_cache, 1, &pipeline_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE), &vk_pipeline);5287ERR_FAIL_COND_V_MSG(err, PipelineID(), "vkCreateComputePipelines failed with error " + itos(err) + ".");52885289return PipelineID(vk_pipeline);5290}52915292/*****************/5293/**** QUERIES ****/5294/*****************/52955296// ----- TIMESTAMP -----52975298RDD::QueryPoolID RenderingDeviceDriverVulkan::timestamp_query_pool_create(uint32_t p_query_count) {5299VkQueryPoolCreateInfo query_pool_create_info = {};5300query_pool_create_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;5301query_pool_create_info.queryType = VK_QUERY_TYPE_TIMESTAMP;5302query_pool_create_info.queryCount = p_query_count;53035304VkQueryPool vk_query_pool = VK_NULL_HANDLE;5305vkCreateQueryPool(vk_device, &query_pool_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_QUERY_POOL), &vk_query_pool);5306return RDD::QueryPoolID(vk_query_pool);5307}53085309void RenderingDeviceDriverVulkan::timestamp_query_pool_free(QueryPoolID p_pool_id) {5310vkDestroyQueryPool(vk_device, (VkQueryPool)p_pool_id.id, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_QUERY_POOL));5311}53125313void RenderingDeviceDriverVulkan::timestamp_query_pool_get_results(QueryPoolID p_pool_id, uint32_t p_query_count, uint64_t *r_results) {5314vkGetQueryPoolResults(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);5315}53165317uint64_t RenderingDeviceDriverVulkan::timestamp_query_result_to_time(uint64_t p_result) {5318// This sucks because timestampPeriod multiplier is a float, while the timestamp is 64 bits nanosecs.5319// So, in cases like nvidia which give you enormous numbers and 1 as multiplier, multiplying is next to impossible.5320// Need to do 128 bits fixed point multiplication to get the right value.53215322auto mult64to128 = [](uint64_t u, uint64_t v, uint64_t &h, uint64_t &l) {5323uint64_t u1 = (u & 0xffffffff);5324uint64_t v1 = (v & 0xffffffff);5325uint64_t t = (u1 * v1);5326uint64_t w3 = (t & 0xffffffff);5327uint64_t k = (t >> 32);53285329u >>= 32;5330t = (u * v1) + k;5331k = (t & 0xffffffff);5332uint64_t w1 = (t >> 32);53335334v >>= 32;5335t = (u1 * v) + k;5336k = (t >> 32);53375338h = (u * v) + w1 + k;5339l = (t << 32) + w3;5340};53415342uint64_t shift_bits = 16;5343uint64_t h = 0, l = 0;5344mult64to128(p_result, uint64_t(double(physical_device_properties.limits.timestampPeriod) * double(1 << shift_bits)), h, l);5345l >>= shift_bits;5346l |= h << (64 - shift_bits);53475348return l;5349}53505351void RenderingDeviceDriverVulkan::command_timestamp_query_pool_reset(CommandBufferID p_cmd_buffer, QueryPoolID p_pool_id, uint32_t p_query_count) {5352const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5353vkCmdResetQueryPool(command_buffer->vk_command_buffer, (VkQueryPool)p_pool_id.id, 0, p_query_count);5354}53555356void RenderingDeviceDriverVulkan::command_timestamp_write(CommandBufferID p_cmd_buffer, QueryPoolID p_pool_id, uint32_t p_index) {5357const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5358vkCmdWriteTimestamp(command_buffer->vk_command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, (VkQueryPool)p_pool_id.id, p_index);5359}53605361/****************/5362/**** LABELS ****/5363/****************/53645365void RenderingDeviceDriverVulkan::command_begin_label(CommandBufferID p_cmd_buffer, const char *p_label_name, const Color &p_color) {5366const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5367const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get();5368if (!functions.CmdBeginDebugUtilsLabelEXT) {5369if (functions.CmdDebugMarkerBeginEXT) {5370// Debug marker extensions.5371VkDebugMarkerMarkerInfoEXT marker;5372marker.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;5373marker.pNext = nullptr;5374marker.pMarkerName = p_label_name;5375marker.color[0] = p_color[0];5376marker.color[1] = p_color[1];5377marker.color[2] = p_color[2];5378marker.color[3] = p_color[3];5379functions.CmdDebugMarkerBeginEXT(command_buffer->vk_command_buffer, &marker);5380}5381return;5382}5383VkDebugUtilsLabelEXT label;5384label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;5385label.pNext = nullptr;5386label.pLabelName = p_label_name;5387label.color[0] = p_color[0];5388label.color[1] = p_color[1];5389label.color[2] = p_color[2];5390label.color[3] = p_color[3];5391functions.CmdBeginDebugUtilsLabelEXT(command_buffer->vk_command_buffer, &label);5392}53935394void RenderingDeviceDriverVulkan::command_end_label(CommandBufferID p_cmd_buffer) {5395const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5396const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get();5397if (!functions.CmdEndDebugUtilsLabelEXT) {5398if (functions.CmdDebugMarkerEndEXT) {5399// Debug marker extensions.5400functions.CmdDebugMarkerEndEXT(command_buffer->vk_command_buffer);5401}5402return;5403}5404functions.CmdEndDebugUtilsLabelEXT(command_buffer->vk_command_buffer);5405}54065407/****************/5408/**** DEBUG *****/5409/****************/5410void RenderingDeviceDriverVulkan::command_insert_breadcrumb(CommandBufferID p_cmd_buffer, uint32_t p_data) {5411#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)5412if (p_data == BreadcrumbMarker::NONE) {5413return;5414}54155416const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id;5417if (Engine::get_singleton()->is_accurate_breadcrumbs_enabled()) {5418// Force a full barrier so commands are not executed in parallel.5419// This will mean that the last breadcrumb to see was actually the5420// last (group of) command to be executed (hence, the one causing the crash).5421VkMemoryBarrier memoryBarrier;5422memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;5423memoryBarrier.pNext = nullptr;5424memoryBarrier.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT |5425VK_ACCESS_INDEX_READ_BIT |5426VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |5427VK_ACCESS_UNIFORM_READ_BIT |5428VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |5429VK_ACCESS_SHADER_READ_BIT |5430VK_ACCESS_SHADER_WRITE_BIT |5431VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |5432VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |5433VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |5434VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |5435VK_ACCESS_TRANSFER_READ_BIT |5436VK_ACCESS_TRANSFER_WRITE_BIT |5437VK_ACCESS_HOST_READ_BIT |5438VK_ACCESS_HOST_WRITE_BIT;5439memoryBarrier.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT |5440VK_ACCESS_INDEX_READ_BIT |5441VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |5442VK_ACCESS_UNIFORM_READ_BIT |5443VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |5444VK_ACCESS_SHADER_READ_BIT |5445VK_ACCESS_SHADER_WRITE_BIT |5446VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |5447VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |5448VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |5449VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |5450VK_ACCESS_TRANSFER_READ_BIT |5451VK_ACCESS_TRANSFER_WRITE_BIT |5452VK_ACCESS_HOST_READ_BIT |5453VK_ACCESS_HOST_WRITE_BIT;54545455vkCmdPipelineBarrier(5456command_buffer->vk_command_buffer,5457VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,5458VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,54590, 1u, &memoryBarrier, 0u, nullptr, 0u, nullptr);5460}54615462// We write to a circular buffer. If you're getting barrier sync errors here,5463// increase the value of BREADCRUMB_BUFFER_ENTRIES.5464vkCmdFillBuffer(command_buffer->vk_command_buffer, ((BufferInfo *)breadcrumb_buffer.id)->vk_buffer, breadcrumb_offset, sizeof(uint32_t), breadcrumb_id++);5465vkCmdFillBuffer(command_buffer->vk_command_buffer, ((BufferInfo *)breadcrumb_buffer.id)->vk_buffer, breadcrumb_offset + sizeof(uint32_t), sizeof(uint32_t), p_data);5466breadcrumb_offset += sizeof(uint32_t) * 2u;5467if (breadcrumb_offset >= BREADCRUMB_BUFFER_ENTRIES * sizeof(uint32_t) * 2u) {5468breadcrumb_offset = 0u;5469}5470#endif5471}54725473void RenderingDeviceDriverVulkan::on_device_lost() const {5474if (device_functions.GetDeviceFaultInfoEXT == nullptr) {5475_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "VK_EXT_device_fault not available.");5476return;5477}54785479VkDeviceFaultCountsEXT fault_counts = {};5480fault_counts.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT;5481VkResult vkres = device_functions.GetDeviceFaultInfoEXT(vk_device, &fault_counts, nullptr);54825483if (vkres != VK_SUCCESS) {5484_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "vkGetDeviceFaultInfoEXT returned " + itos(vkres) + " when getting fault count, skipping VK_EXT_device_fault report...");5485return;5486}54875488String err_msg;5489VkDeviceFaultInfoEXT fault_info = {};5490fault_info.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT;5491fault_info.pVendorInfos = fault_counts.vendorInfoCount5492? (VkDeviceFaultVendorInfoEXT *)memalloc(fault_counts.vendorInfoCount * sizeof(VkDeviceFaultVendorInfoEXT))5493: nullptr;5494fault_info.pAddressInfos =5495fault_counts.addressInfoCount5496? (VkDeviceFaultAddressInfoEXT *)memalloc(fault_counts.addressInfoCount * sizeof(VkDeviceFaultAddressInfoEXT))5497: nullptr;5498fault_counts.vendorBinarySize = 0;5499vkres = device_functions.GetDeviceFaultInfoEXT(vk_device, &fault_counts, &fault_info);5500if (vkres != VK_SUCCESS) {5501_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "vkGetDeviceFaultInfoEXT returned " + itos(vkres) + " when getting fault info, skipping VK_EXT_device_fault report...");5502} else {5503err_msg += "** Report from VK_EXT_device_fault **";5504err_msg += "\nDescription: " + String(fault_info.description);5505err_msg += "\nVendor infos:";5506for (uint32_t vd = 0; vd < fault_counts.vendorInfoCount; ++vd) {5507const VkDeviceFaultVendorInfoEXT *vendor_info = &fault_info.pVendorInfos[vd];5508err_msg += "\nInfo " + itos(vd);5509err_msg += "\n Description: " + String(vendor_info->description);5510err_msg += "\n Fault code : " + itos(vendor_info->vendorFaultCode);5511err_msg += "\n Fault data : " + itos(vendor_info->vendorFaultData);5512}55135514static constexpr const char *addressTypeNames[] = {5515"NONE",5516"READ_INVALID",5517"WRITE_INVALID",5518"EXECUTE_INVALID",5519"INSTRUCTION_POINTER_UNKNOWN",5520"INSTRUCTION_POINTER_INVALID",5521"INSTRUCTION_POINTER_FAULT",5522};5523err_msg += "\nAddresses info:";5524for (uint32_t ad = 0; ad < fault_counts.addressInfoCount; ++ad) {5525const VkDeviceFaultAddressInfoEXT *addr_info = &fault_info.pAddressInfos[ad];5526// From https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkDeviceFaultAddressInfoEXT.html5527const VkDeviceAddress lower = (addr_info->reportedAddress & ~(addr_info->addressPrecision - 1));5528const VkDeviceAddress upper = (addr_info->reportedAddress | (addr_info->addressPrecision - 1));5529err_msg += "\nInfo " + itos(ad);5530err_msg += "\n Type : " + String(addressTypeNames[addr_info->addressType]);5531err_msg += "\n Reported address: " + itos(addr_info->reportedAddress);5532err_msg += "\n Lower address : " + itos(lower);5533err_msg += "\n Upper address : " + itos(upper);5534err_msg += "\n Precision : " + itos(addr_info->addressPrecision);5535}5536}55375538_err_print_error(FUNCTION_STR, __FILE__, __LINE__, err_msg);55395540if (fault_info.pVendorInfos) {5541memfree(fault_info.pVendorInfos);5542}5543if (fault_info.pAddressInfos) {5544memfree(fault_info.pAddressInfos);5545}55465547_err_print_error(FUNCTION_STR, __FILE__, __LINE__, context_driver->get_driver_and_device_memory_report());5548}55495550void RenderingDeviceDriverVulkan::print_lost_device_info() {5551#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)5552{5553String error_msg = "Printing last known breadcrumbs in reverse order (last executed first).";5554if (!Engine::get_singleton()->is_accurate_breadcrumbs_enabled()) {5555error_msg += "\nSome of them might be inaccurate. Try running with --accurate-breadcrumbs for precise information.";5556}5557_err_print_error(FUNCTION_STR, __FILE__, __LINE__, error_msg);5558}55595560uint8_t *breadcrumb_ptr = nullptr;5561VkResult map_result = VK_SUCCESS;55625563vmaFlushAllocation(allocator, ((BufferInfo *)breadcrumb_buffer.id)->allocation.handle, 0, BREADCRUMB_BUFFER_ENTRIES * sizeof(uint32_t) * 2u);5564vmaInvalidateAllocation(allocator, ((BufferInfo *)breadcrumb_buffer.id)->allocation.handle, 0, BREADCRUMB_BUFFER_ENTRIES * sizeof(uint32_t) * 2u);5565{5566void *ptr = nullptr;5567map_result = vmaMapMemory(allocator, ((BufferInfo *)breadcrumb_buffer.id)->allocation.handle, &ptr);5568breadcrumb_ptr = reinterpret_cast<uint8_t *>(ptr);5569}55705571if (breadcrumb_ptr && map_result == VK_SUCCESS) {5572uint32_t last_breadcrumb_offset = 0;5573{5574_err_print_error_asap("Searching last breadcrumb. We've sent up to ID: " + itos(breadcrumb_id - 1u));55755576// Scan the whole buffer to find the offset with the highest ID.5577// That means that was the last one to be written.5578//5579// We use "breadcrumb_id - id" to account for wraparound.5580// e.g. breadcrumb_id = 2 and id = 4294967294; then 2 - 4294967294 = 4.5581// The one with the smallest difference is the closest to breadcrumb_id, which means it's5582// the last written command.5583uint32_t biggest_id = 0u;5584uint32_t smallest_id_diff = std::numeric_limits<uint32_t>::max();5585const uint32_t *breadcrumb_ptr32 = reinterpret_cast<const uint32_t *>(breadcrumb_ptr);5586for (size_t i = 0u; i < BREADCRUMB_BUFFER_ENTRIES; ++i) {5587const uint32_t id = breadcrumb_ptr32[i * 2u];5588const uint32_t id_diff = breadcrumb_id - id;5589if (id_diff < smallest_id_diff) {5590biggest_id = i;5591smallest_id_diff = id_diff;5592}5593}55945595_err_print_error_asap("Last breadcrumb ID found: " + itos(breadcrumb_ptr32[biggest_id * 2u]));55965597last_breadcrumb_offset = biggest_id * sizeof(uint32_t) * 2u;5598}55995600const size_t entries_to_print = 8u; // Note: The value is arbitrary.5601for (size_t i = 0u; i < entries_to_print; ++i) {5602const uint32_t last_breadcrumb = *reinterpret_cast<uint32_t *>(breadcrumb_ptr + last_breadcrumb_offset + sizeof(uint32_t));5603const uint32_t phase = last_breadcrumb & uint32_t(~((1 << 16) - 1));5604const uint32_t user_data = last_breadcrumb & ((1 << 16) - 1);5605String error_msg = "Last known breadcrumb: ";56065607switch (phase) {5608case BreadcrumbMarker::ALPHA_PASS:5609error_msg += "ALPHA_PASS";5610break;5611case BreadcrumbMarker::BLIT_PASS:5612error_msg += "BLIT_PASS";5613break;5614case BreadcrumbMarker::DEBUG_PASS:5615error_msg += "DEBUG_PASS";5616break;5617case BreadcrumbMarker::LIGHTMAPPER_PASS:5618error_msg += "LIGHTMAPPER_PASS";5619break;5620case BreadcrumbMarker::OPAQUE_PASS:5621error_msg += "OPAQUE_PASS";5622break;5623case BreadcrumbMarker::POST_PROCESSING_PASS:5624error_msg += "POST_PROCESSING_PASS";5625break;5626case BreadcrumbMarker::REFLECTION_PROBES:5627error_msg += "REFLECTION_PROBES";5628break;5629case BreadcrumbMarker::SHADOW_PASS_CUBE:5630error_msg += "SHADOW_PASS_CUBE";5631break;5632case BreadcrumbMarker::SHADOW_PASS_DIRECTIONAL:5633error_msg += "SHADOW_PASS_DIRECTIONAL";5634break;5635case BreadcrumbMarker::SKY_PASS:5636error_msg += "SKY_PASS";5637break;5638case BreadcrumbMarker::TRANSPARENT_PASS:5639error_msg += "TRANSPARENT_PASS";5640break;5641case BreadcrumbMarker::UI_PASS:5642error_msg += "UI_PASS";5643break;5644default:5645error_msg += "UNKNOWN_BREADCRUMB(" + itos((uint32_t)phase) + ')';5646break;5647}56485649if (user_data != 0) {5650error_msg += " | User data: " + itos(user_data);5651}56525653_err_print_error_asap(error_msg);56545655if (last_breadcrumb_offset == 0u) {5656// Decrement last_breadcrumb_idx, wrapping underflow.5657last_breadcrumb_offset = BREADCRUMB_BUFFER_ENTRIES * sizeof(uint32_t) * 2u;5658}5659last_breadcrumb_offset -= sizeof(uint32_t) * 2u;5660}56615662vmaUnmapMemory(allocator, ((BufferInfo *)breadcrumb_buffer.id)->allocation.handle);5663breadcrumb_ptr = nullptr;5664} else {5665_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Couldn't map breadcrumb buffer. VkResult = " + itos(map_result));5666}5667#endif5668on_device_lost();5669}56705671inline String RenderingDeviceDriverVulkan::get_vulkan_result(VkResult err) {5672#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)5673if (err == VK_ERROR_OUT_OF_HOST_MEMORY) {5674return "VK_ERROR_OUT_OF_HOST_MEMORY";5675} else if (err == VK_ERROR_OUT_OF_DEVICE_MEMORY) {5676return "VK_ERROR_OUT_OF_DEVICE_MEMORY";5677} else if (err == VK_ERROR_DEVICE_LOST) {5678return "VK_ERROR_DEVICE_LOST";5679} else if (err == VK_ERROR_SURFACE_LOST_KHR) {5680return "VK_ERROR_SURFACE_LOST_KHR";5681} else if (err == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT) {5682return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT";5683}5684#endif5685return itos(err);5686}56875688/********************/5689/**** SUBMISSION ****/5690/********************/56915692void RenderingDeviceDriverVulkan::begin_segment(uint32_t p_frame_index, uint32_t p_frames_drawn) {5693// Per-frame segments are not required in Vulkan.5694}56955696void RenderingDeviceDriverVulkan::end_segment() {5697// Per-frame segments are not required in Vulkan.5698}56995700/**************/5701/**** MISC ****/5702/**************/57035704void RenderingDeviceDriverVulkan::set_object_name(ObjectType p_type, ID p_driver_id, const String &p_name) {5705switch (p_type) {5706case OBJECT_TYPE_TEXTURE: {5707const TextureInfo *tex_info = (const TextureInfo *)p_driver_id.id;5708if (tex_info->allocation.handle) {5709_set_object_name(VK_OBJECT_TYPE_IMAGE, (uint64_t)tex_info->vk_view_create_info.image, p_name);5710}5711_set_object_name(VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)tex_info->vk_view, p_name + " View");5712} break;5713case OBJECT_TYPE_SAMPLER: {5714_set_object_name(VK_OBJECT_TYPE_SAMPLER, p_driver_id.id, p_name);5715} break;5716case OBJECT_TYPE_BUFFER: {5717const BufferInfo *buf_info = (const BufferInfo *)p_driver_id.id;5718_set_object_name(VK_OBJECT_TYPE_BUFFER, (uint64_t)buf_info->vk_buffer, p_name);5719if (buf_info->vk_view) {5720_set_object_name(VK_OBJECT_TYPE_BUFFER_VIEW, (uint64_t)buf_info->vk_view, p_name + " View");5721}5722} break;5723case OBJECT_TYPE_SHADER: {5724const ShaderInfo *shader_info = (const ShaderInfo *)p_driver_id.id;5725for (uint32_t i = 0; i < shader_info->vk_descriptor_set_layouts.size(); i++) {5726_set_object_name(VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)shader_info->vk_descriptor_set_layouts[i], p_name);5727}5728_set_object_name(VK_OBJECT_TYPE_PIPELINE_LAYOUT, (uint64_t)shader_info->vk_pipeline_layout, p_name + " Pipeline Layout");5729} break;5730case OBJECT_TYPE_UNIFORM_SET: {5731const UniformSetInfo *usi = (const UniformSetInfo *)p_driver_id.id;5732_set_object_name(VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)usi->vk_descriptor_set, p_name);5733} break;5734case OBJECT_TYPE_PIPELINE: {5735_set_object_name(VK_OBJECT_TYPE_PIPELINE, (uint64_t)p_driver_id.id, p_name);5736} break;5737default: {5738DEV_ASSERT(false);5739}5740}5741}57425743uint64_t RenderingDeviceDriverVulkan::get_resource_native_handle(DriverResource p_type, ID p_driver_id) {5744switch (p_type) {5745case DRIVER_RESOURCE_LOGICAL_DEVICE: {5746return (uint64_t)vk_device;5747}5748case DRIVER_RESOURCE_PHYSICAL_DEVICE: {5749return (uint64_t)physical_device;5750}5751case DRIVER_RESOURCE_TOPMOST_OBJECT: {5752return (uint64_t)context_driver->instance_get();5753}5754case DRIVER_RESOURCE_COMMAND_QUEUE: {5755const CommandQueue *queue_info = (const CommandQueue *)p_driver_id.id;5756return (uint64_t)queue_families[queue_info->queue_family][queue_info->queue_index].queue;5757}5758case DRIVER_RESOURCE_QUEUE_FAMILY: {5759return uint32_t(p_driver_id.id) - 1;5760}5761case DRIVER_RESOURCE_TEXTURE: {5762const TextureInfo *tex_info = (const TextureInfo *)p_driver_id.id;5763return (uint64_t)tex_info->vk_view_create_info.image;5764}5765case DRIVER_RESOURCE_TEXTURE_VIEW: {5766const TextureInfo *tex_info = (const TextureInfo *)p_driver_id.id;5767return (uint64_t)tex_info->vk_view;5768}5769case DRIVER_RESOURCE_TEXTURE_DATA_FORMAT: {5770const TextureInfo *tex_info = (const TextureInfo *)p_driver_id.id;5771return (uint64_t)tex_info->vk_view_create_info.format;5772}5773case DRIVER_RESOURCE_SAMPLER:5774case DRIVER_RESOURCE_UNIFORM_SET:5775case DRIVER_RESOURCE_BUFFER:5776case DRIVER_RESOURCE_COMPUTE_PIPELINE:5777case DRIVER_RESOURCE_RENDER_PIPELINE: {5778return p_driver_id.id;5779}5780default: {5781return 0;5782}5783}5784}57855786uint64_t RenderingDeviceDriverVulkan::get_total_memory_used() {5787VmaTotalStatistics stats = {};5788vmaCalculateStatistics(allocator, &stats);5789return stats.total.statistics.allocationBytes;5790}57915792uint64_t RenderingDeviceDriverVulkan::get_lazily_memory_used() {5793return vmaCalculateLazilyAllocatedBytes(allocator);5794}57955796uint64_t RenderingDeviceDriverVulkan::limit_get(Limit p_limit) {5797const VkPhysicalDeviceLimits &limits = physical_device_properties.limits;5798uint64_t safe_unbounded = ((uint64_t)1 << 30);5799switch (p_limit) {5800case LIMIT_MAX_BOUND_UNIFORM_SETS:5801return limits.maxBoundDescriptorSets;5802case LIMIT_MAX_FRAMEBUFFER_COLOR_ATTACHMENTS:5803return limits.maxColorAttachments;5804case LIMIT_MAX_TEXTURES_PER_UNIFORM_SET:5805return limits.maxDescriptorSetSampledImages;5806case LIMIT_MAX_SAMPLERS_PER_UNIFORM_SET:5807return limits.maxDescriptorSetSamplers;5808case LIMIT_MAX_STORAGE_BUFFERS_PER_UNIFORM_SET:5809return limits.maxDescriptorSetStorageBuffers;5810case LIMIT_MAX_STORAGE_IMAGES_PER_UNIFORM_SET:5811return limits.maxDescriptorSetStorageImages;5812case LIMIT_MAX_UNIFORM_BUFFERS_PER_UNIFORM_SET:5813return limits.maxDescriptorSetUniformBuffers;5814case LIMIT_MAX_DRAW_INDEXED_INDEX:5815return limits.maxDrawIndexedIndexValue;5816case LIMIT_MAX_FRAMEBUFFER_HEIGHT:5817return limits.maxFramebufferHeight;5818case LIMIT_MAX_FRAMEBUFFER_WIDTH:5819return limits.maxFramebufferWidth;5820case LIMIT_MAX_TEXTURE_ARRAY_LAYERS:5821return limits.maxImageArrayLayers;5822case LIMIT_MAX_TEXTURE_SIZE_1D:5823return limits.maxImageDimension1D;5824case LIMIT_MAX_TEXTURE_SIZE_2D:5825return limits.maxImageDimension2D;5826case LIMIT_MAX_TEXTURE_SIZE_3D:5827return limits.maxImageDimension3D;5828case LIMIT_MAX_TEXTURE_SIZE_CUBE:5829return limits.maxImageDimensionCube;5830case LIMIT_MAX_TEXTURES_PER_SHADER_STAGE:5831return limits.maxPerStageDescriptorSampledImages;5832case LIMIT_MAX_SAMPLERS_PER_SHADER_STAGE:5833return limits.maxPerStageDescriptorSamplers;5834case LIMIT_MAX_STORAGE_BUFFERS_PER_SHADER_STAGE:5835return limits.maxPerStageDescriptorStorageBuffers;5836case LIMIT_MAX_STORAGE_IMAGES_PER_SHADER_STAGE:5837return limits.maxPerStageDescriptorStorageImages;5838case LIMIT_MAX_UNIFORM_BUFFERS_PER_SHADER_STAGE:5839return limits.maxPerStageDescriptorUniformBuffers;5840case LIMIT_MAX_PUSH_CONSTANT_SIZE:5841return limits.maxPushConstantsSize;5842case LIMIT_MAX_UNIFORM_BUFFER_SIZE:5843return limits.maxUniformBufferRange;5844case LIMIT_MAX_VERTEX_INPUT_ATTRIBUTE_OFFSET:5845return limits.maxVertexInputAttributeOffset;5846case LIMIT_MAX_VERTEX_INPUT_ATTRIBUTES:5847return limits.maxVertexInputAttributes;5848case LIMIT_MAX_VERTEX_INPUT_BINDINGS:5849return limits.maxVertexInputBindings;5850case LIMIT_MAX_VERTEX_INPUT_BINDING_STRIDE:5851return limits.maxVertexInputBindingStride;5852case LIMIT_MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT:5853return limits.minUniformBufferOffsetAlignment;5854case LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X:5855return limits.maxComputeWorkGroupCount[0];5856case LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Y:5857return limits.maxComputeWorkGroupCount[1];5858case LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Z:5859return limits.maxComputeWorkGroupCount[2];5860case LIMIT_MAX_COMPUTE_WORKGROUP_INVOCATIONS:5861return limits.maxComputeWorkGroupInvocations;5862case LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_X:5863return limits.maxComputeWorkGroupSize[0];5864case LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Y:5865return limits.maxComputeWorkGroupSize[1];5866case LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z:5867return limits.maxComputeWorkGroupSize[2];5868case LIMIT_MAX_COMPUTE_SHARED_MEMORY_SIZE:5869return limits.maxComputeSharedMemorySize;5870case LIMIT_MAX_VIEWPORT_DIMENSIONS_X:5871return limits.maxViewportDimensions[0];5872case LIMIT_MAX_VIEWPORT_DIMENSIONS_Y:5873return limits.maxViewportDimensions[1];5874case LIMIT_SUBGROUP_SIZE:5875return subgroup_capabilities.size;5876case LIMIT_SUBGROUP_MIN_SIZE:5877return subgroup_capabilities.min_size;5878case LIMIT_SUBGROUP_MAX_SIZE:5879return subgroup_capabilities.max_size;5880case LIMIT_SUBGROUP_IN_SHADERS:5881return subgroup_capabilities.supported_stages_flags_rd();5882case LIMIT_SUBGROUP_OPERATIONS:5883return subgroup_capabilities.supported_operations_flags_rd();5884case LIMIT_MAX_SHADER_VARYINGS:5885// The Vulkan spec states that built in varyings like gl_FragCoord should count against this, but in5886// practice, that doesn't seem to be the case. The validation layers don't even complain.5887return MIN(limits.maxVertexOutputComponents / 4, limits.maxFragmentInputComponents / 4);5888default: {5889#ifdef DEV_ENABLED5890WARN_PRINT("Returning maximum value for unknown limit " + itos(p_limit) + ".");5891#endif5892return safe_unbounded;5893}5894}5895}58965897uint64_t RenderingDeviceDriverVulkan::api_trait_get(ApiTrait p_trait) {5898switch (p_trait) {5899case API_TRAIT_TEXTURE_TRANSFER_ALIGNMENT:5900return (uint64_t)MAX((uint64_t)16, physical_device_properties.limits.optimalBufferCopyOffsetAlignment);5901case API_TRAIT_SHADER_CHANGE_INVALIDATION:5902return (uint64_t)SHADER_CHANGE_INVALIDATION_INCOMPATIBLE_SETS_PLUS_CASCADE;5903default:5904return RenderingDeviceDriver::api_trait_get(p_trait);5905}5906}59075908bool RenderingDeviceDriverVulkan::has_feature(Features p_feature) {5909switch (p_feature) {5910case SUPPORTS_HALF_FLOAT:5911return shader_capabilities.shader_float16_is_supported && physical_device_features.shaderInt16 && storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported;5912case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:5913return true;5914case SUPPORTS_BUFFER_DEVICE_ADDRESS:5915return buffer_device_address_support;5916case SUPPORTS_IMAGE_ATOMIC_32_BIT:5917#if (defined(MACOS_ENABLED) || defined(APPLE_EMBEDDED_ENABLED))5918// MoltenVK has previously had issues with 32-bit atomics on images.5919return false;5920#else5921return true;5922#endif5923case SUPPORTS_VULKAN_MEMORY_MODEL:5924return vulkan_memory_model_support && vulkan_memory_model_device_scope_support;5925default:5926return false;5927}5928}59295930const RDD::MultiviewCapabilities &RenderingDeviceDriverVulkan::get_multiview_capabilities() {5931return multiview_capabilities;5932}59335934const RDD::FragmentShadingRateCapabilities &RenderingDeviceDriverVulkan::get_fragment_shading_rate_capabilities() {5935return fsr_capabilities;5936}59375938const RDD::FragmentDensityMapCapabilities &RenderingDeviceDriverVulkan::get_fragment_density_map_capabilities() {5939return fdm_capabilities;5940}59415942String RenderingDeviceDriverVulkan::get_api_name() const {5943return "Vulkan";5944}59455946String RenderingDeviceDriverVulkan::get_api_version() const {5947uint32_t api_version = physical_device_properties.apiVersion;5948return vformat("%d.%d.%d", VK_API_VERSION_MAJOR(api_version), VK_API_VERSION_MINOR(api_version), VK_API_VERSION_PATCH(api_version));5949}59505951String RenderingDeviceDriverVulkan::get_pipeline_cache_uuid() const {5952return pipeline_cache_id;5953}59545955const RDD::Capabilities &RenderingDeviceDriverVulkan::get_capabilities() const {5956return device_capabilities;5957}59585959const RenderingShaderContainerFormat &RenderingDeviceDriverVulkan::get_shader_container_format() const {5960return shader_container_format;5961}59625963bool RenderingDeviceDriverVulkan::is_composite_alpha_supported(CommandQueueID p_queue) const {5964if (has_comp_alpha.has((uint64_t)p_queue.id)) {5965return has_comp_alpha[(uint64_t)p_queue.id];5966}5967return false;5968}59695970/******************/59715972RenderingDeviceDriverVulkan::RenderingDeviceDriverVulkan(RenderingContextDriverVulkan *p_context_driver) {5973DEV_ASSERT(p_context_driver != nullptr);59745975context_driver = p_context_driver;5976max_descriptor_sets_per_pool = GLOBAL_GET("rendering/rendering_device/vulkan/max_descriptors_per_pool");5977}59785979RenderingDeviceDriverVulkan::~RenderingDeviceDriverVulkan() {5980#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)5981buffer_free(breadcrumb_buffer);5982#endif59835984while (small_allocs_pools.size()) {5985HashMap<uint32_t, VmaPool>::Iterator E = small_allocs_pools.begin();5986vmaDestroyPool(allocator, E->value);5987small_allocs_pools.remove(E);5988}5989vmaDestroyAllocator(allocator);59905991// Destroy linearly allocated descriptor pools.5992for (KeyValue<int, DescriptorSetPools> &pool_map : linear_descriptor_set_pools) {5993for (KeyValue<DescriptorSetPoolKey, HashMap<VkDescriptorPool, uint32_t>> pools : pool_map.value) {5994for (KeyValue<VkDescriptorPool, uint32_t> descriptor_pool : pools.value) {5995vkDestroyDescriptorPool(vk_device, descriptor_pool.key, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DESCRIPTOR_POOL));5996}5997}5998}59996000if (vk_device != VK_NULL_HANDLE) {6001vkDestroyDevice(vk_device, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DEVICE));6002}6003}600460056006