1 // Copyright 2016 Dolphin Emulator Project 2 // Licensed under GPLv2+ 3 // Refer to the license.txt file included. 4 5 #pragma once 6 7 #include <memory> 8 #include <optional> 9 #include <string> 10 #include <vector> 11 12 #include "Common/CommonTypes.h" 13 #include "Common/WindowSystemInfo.h" 14 #include "VideoBackends/Vulkan/Constants.h" 15 #include "VideoCommon/VideoConfig.h" 16 17 namespace Vulkan 18 { 19 class VulkanContext 20 { 21 public: 22 VulkanContext(VkInstance instance, VkPhysicalDevice physical_device); 23 ~VulkanContext(); 24 25 // Determines if the Vulkan validation layer is available on the system. 26 static bool CheckValidationLayerAvailablility(); 27 28 // Helper method to create a Vulkan instance. 29 static VkInstance CreateVulkanInstance(WindowSystemType wstype, bool enable_debug_report, 30 bool enable_validation_layer); 31 32 // Returns a list of Vulkan-compatible GPUs. 33 using GPUList = std::vector<VkPhysicalDevice>; 34 static GPUList EnumerateGPUs(VkInstance instance); 35 36 // Populates backend/video config. 37 // These are public so that the backend info can be populated without creating a context. 38 static void PopulateBackendInfo(VideoConfig* config); 39 static void PopulateBackendInfoAdapters(VideoConfig* config, const GPUList& gpu_list); 40 static void PopulateBackendInfoFeatures(VideoConfig* config, VkPhysicalDevice gpu, 41 const VkPhysicalDeviceProperties& properties, 42 const VkPhysicalDeviceFeatures& features); 43 static void PopulateBackendInfoMultisampleModes(VideoConfig* config, VkPhysicalDevice gpu, 44 const VkPhysicalDeviceProperties& properties); 45 46 // Creates a Vulkan device context. 47 // This assumes that PopulateBackendInfo and PopulateBackendInfoAdapters has already 48 // been called for the specified VideoConfig. 49 static std::unique_ptr<VulkanContext> Create(VkInstance instance, VkPhysicalDevice gpu, 50 VkSurfaceKHR surface, bool enable_debug_reports, 51 bool enable_validation_layer); 52 53 // Enable/disable debug message runtime. 54 bool EnableDebugReports(); 55 void DisableDebugReports(); 56 57 // Global state accessors GetVulkanInstance()58 VkInstance GetVulkanInstance() const { return m_instance; } GetPhysicalDevice()59 VkPhysicalDevice GetPhysicalDevice() const { return m_physical_device; } GetDevice()60 VkDevice GetDevice() const { return m_device; } GetGraphicsQueue()61 VkQueue GetGraphicsQueue() const { return m_graphics_queue; } GetGraphicsQueueFamilyIndex()62 u32 GetGraphicsQueueFamilyIndex() const { return m_graphics_queue_family_index; } GetPresentQueue()63 VkQueue GetPresentQueue() const { return m_present_queue; } GetPresentQueueFamilyIndex()64 u32 GetPresentQueueFamilyIndex() const { return m_present_queue_family_index; } GetGraphicsQueueProperties()65 const VkQueueFamilyProperties& GetGraphicsQueueProperties() const 66 { 67 return m_graphics_queue_properties; 68 } GetDeviceMemoryProperties()69 const VkPhysicalDeviceMemoryProperties& GetDeviceMemoryProperties() const 70 { 71 return m_device_memory_properties; 72 } GetDeviceProperties()73 const VkPhysicalDeviceProperties& GetDeviceProperties() const { return m_device_properties; } GetDeviceFeatures()74 const VkPhysicalDeviceFeatures& GetDeviceFeatures() const { return m_device_features; } GetDeviceLimits()75 const VkPhysicalDeviceLimits& GetDeviceLimits() const { return m_device_properties.limits; } 76 // Support bits SupportsAnisotropicFiltering()77 bool SupportsAnisotropicFiltering() const 78 { 79 return m_device_features.samplerAnisotropy == VK_TRUE; 80 } SupportsPreciseOcclusionQueries()81 bool SupportsPreciseOcclusionQueries() const 82 { 83 return m_device_features.occlusionQueryPrecise == VK_TRUE; 84 } GetShaderSubgroupSize()85 u32 GetShaderSubgroupSize() const { return m_shader_subgroup_size; } SupportsShaderSubgroupOperations()86 bool SupportsShaderSubgroupOperations() const { return m_supports_shader_subgroup_operations; } 87 88 // Helpers for getting constants GetUniformBufferAlignment()89 VkDeviceSize GetUniformBufferAlignment() const 90 { 91 return m_device_properties.limits.minUniformBufferOffsetAlignment; 92 } GetTexelBufferAlignment()93 VkDeviceSize GetTexelBufferAlignment() const 94 { 95 return m_device_properties.limits.minUniformBufferOffsetAlignment; 96 } GetBufferImageGranularity()97 VkDeviceSize GetBufferImageGranularity() const 98 { 99 return m_device_properties.limits.bufferImageGranularity; 100 } GetMaxSamplerAnisotropy()101 float GetMaxSamplerAnisotropy() const { return m_device_properties.limits.maxSamplerAnisotropy; } 102 // Finds a memory type index for the specified memory properties and the bits returned by 103 // vkGetImageMemoryRequirements 104 std::optional<u32> GetMemoryType(u32 bits, VkMemoryPropertyFlags properties, bool strict, 105 bool* is_coherent = nullptr); 106 107 // Finds a memory type for upload or readback buffers. 108 u32 GetUploadMemoryType(u32 bits, bool* is_coherent = nullptr); 109 u32 GetReadbackMemoryType(u32 bits, bool* is_coherent = nullptr); 110 111 // Returns true if the specified extension is supported and enabled. 112 bool SupportsDeviceExtension(const char* name) const; 113 114 // Returns true if exclusive fullscreen is supported for the given surface. 115 bool SupportsExclusiveFullscreen(const WindowSystemInfo& wsi, VkSurfaceKHR surface); 116 117 #ifdef WIN32 118 // Returns the platform-specific exclusive fullscreen structure. 119 VkSurfaceFullScreenExclusiveWin32InfoEXT 120 GetPlatformExclusiveFullscreenInfo(const WindowSystemInfo& wsi); 121 #endif 122 123 private: 124 static bool SelectInstanceExtensions(std::vector<const char*>* extension_list, 125 WindowSystemType wstype, bool enable_debug_report); 126 bool SelectDeviceExtensions(bool enable_surface); 127 bool SelectDeviceFeatures(); 128 bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer); 129 void InitDriverDetails(); 130 void PopulateShaderSubgroupSupport(); 131 132 VkInstance m_instance = VK_NULL_HANDLE; 133 VkPhysicalDevice m_physical_device = VK_NULL_HANDLE; 134 VkDevice m_device = VK_NULL_HANDLE; 135 136 VkQueue m_graphics_queue = VK_NULL_HANDLE; 137 u32 m_graphics_queue_family_index = 0; 138 VkQueue m_present_queue = VK_NULL_HANDLE; 139 u32 m_present_queue_family_index = 0; 140 VkQueueFamilyProperties m_graphics_queue_properties = {}; 141 142 VkDebugReportCallbackEXT m_debug_report_callback = VK_NULL_HANDLE; 143 144 VkPhysicalDeviceFeatures m_device_features = {}; 145 VkPhysicalDeviceProperties m_device_properties = {}; 146 VkPhysicalDeviceMemoryProperties m_device_memory_properties = {}; 147 148 u32 m_shader_subgroup_size = 1; 149 bool m_supports_shader_subgroup_operations = false; 150 151 std::vector<std::string> m_device_extensions; 152 }; 153 154 extern std::unique_ptr<VulkanContext> g_vulkan_context; 155 156 } // namespace Vulkan 157