diff options
Diffstat (limited to 'src/video_core/vulkan_common/vulkan_device.h')
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_device.h | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index d8524f6575..5f75bcc18e 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -6,7 +6,10 @@ #pragma once +#include <array> #include <atomic> +#include <cstdlib> +#include <mutex> #include <optional> #include <set> #include <span> @@ -20,6 +23,7 @@ #include "video_core/vulkan_common/vulkan_wrapper.h" VK_DEFINE_HANDLE(VmaAllocator) +VK_DEFINE_HANDLE(VmaPool) // Define all features which may be used by the implementation here. // Vulkan version in the macro describes the minimum version required for feature availability. @@ -65,6 +69,7 @@ VK_DEFINE_HANDLE(VmaAllocator) FEATURE(EXT, 4444Formats, 4444_FORMATS, format_a4b4g4r4) \ FEATURE(EXT, IndexTypeUint8, INDEX_TYPE_UINT8, index_type_uint8) \ FEATURE(EXT, LineRasterization, LINE_RASTERIZATION, line_rasterization) \ + FEATURE(EXT, MeshShader, MESH_SHADER, mesh_shader) \ FEATURE(EXT, PrimitiveTopologyListRestart, PRIMITIVE_TOPOLOGY_LIST_RESTART, \ primitive_topology_list_restart) \ FEATURE(EXT, ProvokingVertex, PROVOKING_VERTEX, provoking_vertex) \ @@ -263,6 +268,17 @@ public: return allocator; } + /// Allocations kept out of the default blocks, which then hold images only: churned buffers + /// and long-lived sparse pages left holes the texture cache's collector couldn't drain. + enum class SeparatePool : u32 { + SparsePages, + DeviceBuffers, + }; + static constexpr VkDeviceSize SeparatePoolBlockSize = 16ULL << 20; + + /// The pool of that kind for a memory type, created on first use (null if that failed). + VmaPool GetSeparatePool(SeparatePool kind, u32 memory_type) const; + /// Returns the logical device. const vk::Device& GetLogical() const { return logical; @@ -326,6 +342,28 @@ public: return IsSparseBindingSupported() && features.features.sparseResidencyImage2D; } + /// Whether a sparse image may bind the same memory to several of its blocks. + bool IsSparseResidencyAliasedSupported() const { + return IsSparseResidencyImage2DSupported() && features.features.sparseResidencyAliased; + } + + /// Whether images with no memory bound may be sampled and used as attachments. AMD's drivers + /// fault on it (the GPU hangs shortly after the first such draw), so large images there are + /// backed normally. RADV is counted in until someone shows it doesn't need it. + /// EDEN_NX2_SPARSE_UNBACKED=1 allows unbound images on any driver, =0 on none. + bool CanUseUnbackedSparseImages() const { + static const char forced = [] { + const char* value = std::getenv("EDEN_NX2_SPARSE_UNBACKED"); + return value == nullptr ? '\0' : value[0]; + }(); + if (forced == '0' || forced == '1') { + return forced == '1'; + } + const VkDriverIdKHR id = GetDriverID(); + return id != VK_DRIVER_ID_AMD_PROPRIETARY && id != VK_DRIVER_ID_AMD_OPEN_SOURCE && + id != VK_DRIVER_ID_MESA_RADV; + } + /// Returns true for tile-based deferred renderers. bool IsTiler() const { switch (GetDriverID()) { @@ -610,6 +648,12 @@ FN_MAX_LIMIT_LIST return extensions.shader_quad_control && features.shader_quad_control.shaderQuadControl; } + /// Returns true if the device supports task and mesh shaders (VK_EXT_mesh_shader). + bool IsExtMeshShaderSupported() const { + return extensions.mesh_shader && features.mesh_shader.taskShader && + features.mesh_shader.meshShader; + } + /// Returns true if the device supports VK_KHR_image_format_list. bool IsKhrImageFormatListSupported() const { return extensions.image_format_list || instance_version >= VK_API_VERSION_1_2; @@ -928,6 +972,11 @@ FN_MAX_LIMIT_LIST return 0x00010300U; } + /// Returns true for an integrated GPU (its device-local memory is system memory). + bool IsIntegrated() const { + return is_integrated; + } + /// Returns true when a known debugging tool is attached. bool HasDebuggingToolAttached() const { return has_renderdoc || has_nsight_graphics || has_radeon_gpu_profiler; @@ -970,9 +1019,15 @@ FN_MAX_LIMIT_LIST /// The driver's current memory budget for this process (VK_EXT_memory_budget), in /// GetDeviceMemoryUsage() terms: the usage at which the main device-local heap reaches its - /// budget. 0 without the extension. + /// budget. 0 without the extension. The unused part of the allocator's blocks is not + /// subtracted: see GetDeviceMemorySlack(). u64 GetDeviceMemoryBudget() const; + /// Memory the allocator holds from the driver in the main device-local heap but has no + /// allocation in (the unused part of its blocks). GetDeviceMemoryUsage() does not count it, + /// yet the driver does: with the heap at its budget it is not available to new images. + u64 GetDeviceMemorySlack() const; + u32 GetSetsPerPool() const { return sets_per_pool; } @@ -1106,6 +1161,12 @@ FN_MAX_LIMIT_LIST return properties.driver.driverID == VK_DRIVER_ID_MOLTENVK; } + /// The multiple vertex input binding strides must be. Metal needs 4 bytes, which MoltenVK + /// reports as minVertexInputBindingStrideAlignment through VK_KHR_portability_subset. + u32 GetMinVertexInputBindingStrideAlignment() const noexcept { + return IsMoltenVK() ? 4 : 1; + } + NvidiaArchitecture GetNvidiaArch() const noexcept { return nvidia_arch; } @@ -1156,6 +1217,8 @@ private: private: VkInstance instance; ///< Vulkan instance. VmaAllocator allocator{}; ///< VMA allocator. + mutable std::mutex separate_pools_mutex; + mutable std::array<std::array<VmaPool, VK_MAX_MEMORY_TYPES>, 2> separate_pools{}; vk::DeviceDispatch dld; ///< Device function pointers. vk::PhysicalDevice physical; ///< Physical device. vk::Device logical; ///< Logical device. |
