summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorTellowKrinkle <tellowkrinkle@gmail.com>2024-09-03 23:24:05 -0500
committerTellowKrinkle <tellowkrinkle@gmail.com>2024-09-05 22:15:29 -0500
commit1416dc7e6aee2fdf861eb83037c7c3bbc924adce (patch)
tree95c7dfb9346b48ea30864182a91fea7e1ba4b3bc /Source/Core
parentefc395f7f424f71f4f6ccd055a1dd5817ad8fbc8 (diff)
VideoBackends:Vulkan: Consolidate feature checking into one struct
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/VideoBackends/Vulkan/ObjectCache.cpp12
-rw-r--r--Source/Core/VideoBackends/Vulkan/VKMain.cpp12
-rw-r--r--Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp4
-rw-r--r--Source/Core/VideoBackends/Vulkan/VulkanContext.cpp233
-rw-r--r--Source/Core/VideoBackends/Vulkan/VulkanContext.h87
5 files changed, 184 insertions, 164 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp
index c32365f3fc..e32675fe57 100644
--- a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp
+++ b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp
@@ -627,24 +627,24 @@ bool ObjectCache::ValidatePipelineCache(const u8* data, size_t data_length)
return false;
}
- if (header.vendor_id != g_vulkan_context->GetDeviceProperties().vendorID)
+ if (header.vendor_id != g_vulkan_context->GetDeviceInfo().vendorID)
{
ERROR_LOG_FMT(
VIDEO, "Pipeline cache failed validation: Incorrect vendor ID (file: {:#X}, device: {:#X})",
- header.vendor_id, g_vulkan_context->GetDeviceProperties().vendorID);
+ header.vendor_id, g_vulkan_context->GetDeviceInfo().vendorID);
return false;
}
- if (header.device_id != g_vulkan_context->GetDeviceProperties().deviceID)
+ if (header.device_id != g_vulkan_context->GetDeviceInfo().deviceID)
{
ERROR_LOG_FMT(
VIDEO, "Pipeline cache failed validation: Incorrect device ID (file: {:#X}, device: {:#X})",
- header.device_id, g_vulkan_context->GetDeviceProperties().deviceID);
+ header.device_id, g_vulkan_context->GetDeviceInfo().deviceID);
return false;
}
- if (std::memcmp(header.uuid, g_vulkan_context->GetDeviceProperties().pipelineCacheUUID,
- VK_UUID_SIZE) != 0)
+ if (std::memcmp(header.uuid, g_vulkan_context->GetDeviceInfo().pipelineCacheUUID, VK_UUID_SIZE) !=
+ 0)
{
ERROR_LOG_FMT(VIDEO, "Pipeline cache failed validation: Incorrect UUID");
return false;
diff --git a/Source/Core/VideoBackends/Vulkan/VKMain.cpp b/Source/Core/VideoBackends/Vulkan/VKMain.cpp
index 2eb9b34106..55ebfdf239 100644
--- a/Source/Core/VideoBackends/Vulkan/VKMain.cpp
+++ b/Source/Core/VideoBackends/Vulkan/VKMain.cpp
@@ -54,11 +54,8 @@ void VideoBackend::InitBackendInfo(const WindowSystemInfo& wsi)
device_index = 0;
VkPhysicalDevice gpu = gpu_list[device_index];
- VkPhysicalDeviceProperties properties;
- vkGetPhysicalDeviceProperties(gpu, &properties);
- VkPhysicalDeviceFeatures features;
- vkGetPhysicalDeviceFeatures(gpu, &features);
- VulkanContext::PopulateBackendInfoFeatures(&g_Config, gpu, properties, features);
+ VulkanContext::PhysicalDeviceInfo properties(gpu);
+ VulkanContext::PopulateBackendInfoFeatures(&g_Config, gpu, properties);
VulkanContext::PopulateBackendInfoMultisampleModes(&g_Config, gpu, properties);
}
}
@@ -187,10 +184,9 @@ bool VideoBackend::Initialize(const WindowSystemInfo& wsi)
// Since VulkanContext maintains a copy of the device features and properties, we can use this
// to initialize the backend information, so that we don't need to enumerate everything again.
VulkanContext::PopulateBackendInfoFeatures(&g_Config, g_vulkan_context->GetPhysicalDevice(),
- g_vulkan_context->GetDeviceProperties(),
- g_vulkan_context->GetDeviceFeatures());
+ g_vulkan_context->GetDeviceInfo());
VulkanContext::PopulateBackendInfoMultisampleModes(
- &g_Config, g_vulkan_context->GetPhysicalDevice(), g_vulkan_context->GetDeviceProperties());
+ &g_Config, g_vulkan_context->GetPhysicalDevice(), g_vulkan_context->GetDeviceInfo());
g_Config.backend_info.bSupportsExclusiveFullscreen =
enable_surface && g_vulkan_context->SupportsExclusiveFullscreen(wsi, surface);
diff --git a/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp b/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp
index 73c9dfde59..e18a5ffd81 100644
--- a/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp
+++ b/Source/Core/VideoBackends/Vulkan/VKVertexManager.cpp
@@ -92,8 +92,8 @@ bool VertexManager::Initialize()
// Prefer an 8MB buffer if possible, but use less if the device doesn't support this.
// This buffer is potentially going to be addressed as R8s in the future, so we assume
// that one element is one byte.
- const u32 texel_buffer_size = std::min(
- TEXEL_STREAM_BUFFER_SIZE, g_vulkan_context->GetDeviceLimits().maxTexelBufferElements);
+ const u32 texel_buffer_size =
+ std::min(TEXEL_STREAM_BUFFER_SIZE, g_vulkan_context->GetDeviceInfo().maxTexelBufferElements);
m_texel_stream_buffer =
StreamBuffer::Create(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, texel_buffer_size);
if (!m_texel_stream_buffer)
diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
index db6d8b99d4..7efcd008a5 100644
--- a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
+++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
@@ -22,22 +22,101 @@ static constexpr const char* VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validatio
std::unique_ptr<VulkanContext> g_vulkan_context;
+template <typename Chain, typename Element>
+static void InsertIntoChain(Chain* chain, Element* element)
+{
+ element->pNext = chain->pNext;
+ chain->pNext = element;
+}
+
+VulkanContext::PhysicalDeviceInfo::PhysicalDeviceInfo(VkPhysicalDevice device)
+{
+ VkPhysicalDeviceFeatures features;
+ VkPhysicalDeviceProperties2 properties2;
+ VkPhysicalDeviceProperties& properties = properties2.properties;
+
+ vkGetPhysicalDeviceProperties(device, &properties);
+ vkGetPhysicalDeviceFeatures(device, &features);
+ apiVersion = vkGetPhysicalDeviceProperties2 ? properties.apiVersion : VK_API_VERSION_1_0;
+
+ if (apiVersion >= VK_API_VERSION_1_1)
+ {
+ VkPhysicalDeviceSubgroupProperties properties_subgroup = {};
+ properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+ properties2.pNext = nullptr;
+ properties_subgroup.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
+ InsertIntoChain(&properties2, &properties_subgroup);
+
+ vkGetPhysicalDeviceProperties2(device, &properties2);
+
+ subgroupSize = properties_subgroup.subgroupSize;
+
+ // We require basic ops (for gl_SubgroupInvocationID), ballot (for subgroupBallot,
+ // subgroupBallotFindLSB), and arithmetic (for subgroupMin/subgroupMax).
+ // Shuffle is enabled as a workaround until SPIR-V >= 1.5 is enabled with broadcast(uniform)
+ // support.
+ constexpr VkSubgroupFeatureFlags required_operations =
+ VK_SUBGROUP_FEATURE_BASIC_BIT | VK_SUBGROUP_FEATURE_ARITHMETIC_BIT |
+ VK_SUBGROUP_FEATURE_BALLOT_BIT | VK_SUBGROUP_FEATURE_SHUFFLE_BIT;
+ shaderSubgroupOperations =
+ (properties_subgroup.supportedOperations & required_operations) == required_operations &&
+ properties_subgroup.supportedStages & VK_SHADER_STAGE_FRAGMENT_BIT;
+ }
+
+ memcpy(deviceName, properties.deviceName, sizeof(deviceName));
+ memcpy(pipelineCacheUUID, properties.pipelineCacheUUID, sizeof(pipelineCacheUUID));
+ vendorID = properties.vendorID;
+ deviceID = properties.deviceID;
+ minUniformBufferOffsetAlignment =
+ std::max<VkDeviceSize>(properties.limits.minUniformBufferOffsetAlignment, 1);
+ bufferImageGranularity = std::max<VkDeviceSize>(properties.limits.bufferImageGranularity, 1);
+ maxTexelBufferElements = properties.limits.maxTexelBufferElements;
+ maxImageDimension2D = properties.limits.maxImageDimension2D;
+ framebufferColorSampleCounts = properties.limits.framebufferColorSampleCounts;
+ framebufferDepthSampleCounts = properties.limits.framebufferDepthSampleCounts;
+ memcpy(pointSizeRange, properties.limits.pointSizeRange, sizeof(pointSizeRange));
+ maxSamplerAnisotropy = properties.limits.maxSamplerAnisotropy;
+
+ dualSrcBlend = features.dualSrcBlend != VK_FALSE;
+ geometryShader = features.geometryShader != VK_FALSE;
+ samplerAnisotropy = features.samplerAnisotropy != VK_FALSE;
+ logicOp = features.logicOp != VK_FALSE;
+ fragmentStoresAndAtomics = features.fragmentStoresAndAtomics != VK_FALSE;
+ sampleRateShading = features.sampleRateShading != VK_FALSE;
+ largePoints = features.largePoints != VK_FALSE;
+ shaderStorageImageMultisample = features.shaderStorageImageMultisample != VK_FALSE;
+ shaderTessellationAndGeometryPointSize =
+ features.shaderTessellationAndGeometryPointSize != VK_FALSE;
+ occlusionQueryPrecise = features.occlusionQueryPrecise != VK_FALSE;
+ shaderClipDistance = features.shaderClipDistance != VK_FALSE;
+ depthClamp = features.depthClamp != VK_FALSE;
+ textureCompressionBC = features.textureCompressionBC != VK_FALSE;
+}
+
+VkPhysicalDeviceFeatures VulkanContext::PhysicalDeviceInfo::features() const
+{
+ VkPhysicalDeviceFeatures features;
+ memset(&features, 0, sizeof(features));
+ features.dualSrcBlend = dualSrcBlend ? VK_TRUE : VK_FALSE;
+ features.geometryShader = geometryShader ? VK_TRUE : VK_FALSE;
+ features.samplerAnisotropy = samplerAnisotropy ? VK_TRUE : VK_FALSE;
+ features.logicOp = logicOp ? VK_TRUE : VK_FALSE;
+ features.fragmentStoresAndAtomics = fragmentStoresAndAtomics ? VK_TRUE : VK_FALSE;
+ features.sampleRateShading = sampleRateShading ? VK_TRUE : VK_FALSE;
+ features.largePoints = largePoints ? VK_TRUE : VK_FALSE;
+ features.shaderStorageImageMultisample = shaderStorageImageMultisample ? VK_TRUE : VK_FALSE;
+ features.shaderTessellationAndGeometryPointSize =
+ shaderTessellationAndGeometryPointSize ? VK_TRUE : VK_FALSE;
+ features.occlusionQueryPrecise = occlusionQueryPrecise ? VK_TRUE : VK_FALSE;
+ features.shaderClipDistance = shaderClipDistance ? VK_TRUE : VK_FALSE;
+ features.depthClamp = depthClamp ? VK_TRUE : VK_FALSE;
+ features.textureCompressionBC = textureCompressionBC ? VK_TRUE : VK_FALSE;
+ return features;
+}
+
VulkanContext::VulkanContext(VkInstance instance, VkPhysicalDevice physical_device)
- : m_instance(instance), m_physical_device(physical_device)
+ : m_instance(instance), m_physical_device(physical_device), m_device_info(physical_device)
{
- // Read device physical memory properties, we need it for allocating buffers
- vkGetPhysicalDeviceProperties(physical_device, &m_device_properties);
- vkGetPhysicalDeviceMemoryProperties(physical_device, &m_device_memory_properties);
-
- // Would any drivers be this silly? I hope not...
- m_device_properties.limits.minUniformBufferOffsetAlignment = std::max(
- m_device_properties.limits.minUniformBufferOffsetAlignment, static_cast<VkDeviceSize>(1));
- m_device_properties.limits.minTexelBufferOffsetAlignment = std::max(
- m_device_properties.limits.minTexelBufferOffsetAlignment, static_cast<VkDeviceSize>(1));
- m_device_properties.limits.optimalBufferCopyOffsetAlignment = std::max(
- m_device_properties.limits.optimalBufferCopyOffsetAlignment, static_cast<VkDeviceSize>(1));
- m_device_properties.limits.optimalBufferCopyRowPitchAlignment = std::max(
- m_device_properties.limits.optimalBufferCopyRowPitchAlignment, static_cast<VkDeviceSize>(1));
}
VulkanContext::~VulkanContext()
@@ -397,18 +476,17 @@ void VulkanContext::PopulateBackendInfoAdapters(VideoConfig* config, const GPULi
}
void VulkanContext::PopulateBackendInfoFeatures(VideoConfig* config, VkPhysicalDevice gpu,
- const VkPhysicalDeviceProperties& properties,
- const VkPhysicalDeviceFeatures& features)
+ const PhysicalDeviceInfo& info)
{
- config->backend_info.MaxTextureSize = properties.limits.maxImageDimension2D;
+ config->backend_info.MaxTextureSize = info.maxImageDimension2D;
config->backend_info.bUsesLowerLeftOrigin = false;
- config->backend_info.bSupportsDualSourceBlend = (features.dualSrcBlend == VK_TRUE);
- config->backend_info.bSupportsGeometryShaders = (features.geometryShader == VK_TRUE);
- config->backend_info.bSupportsGSInstancing = (features.geometryShader == VK_TRUE);
+ config->backend_info.bSupportsDualSourceBlend = info.dualSrcBlend;
+ config->backend_info.bSupportsGeometryShaders = info.geometryShader;
+ config->backend_info.bSupportsGSInstancing = info.geometryShader;
config->backend_info.bSupportsBBox = config->backend_info.bSupportsFragmentStoresAndAtomics =
- (features.fragmentStoresAndAtomics == VK_TRUE);
- config->backend_info.bSupportsSSAA = (features.sampleRateShading == VK_TRUE);
- config->backend_info.bSupportsLogicOp = (features.logicOp == VK_TRUE);
+ info.fragmentStoresAndAtomics;
+ config->backend_info.bSupportsSSAA = info.sampleRateShading;
+ config->backend_info.bSupportsLogicOp = info.logicOp;
#ifdef __APPLE__
// Metal doesn't support this.
@@ -419,30 +497,27 @@ void VulkanContext::PopulateBackendInfoFeatures(VideoConfig* config, VkPhysicalD
// Disable geometry shader when shaderTessellationAndGeometryPointSize is not supported.
// Seems this is needed for gl_Layer.
- if (!features.shaderTessellationAndGeometryPointSize)
+ if (!info.shaderTessellationAndGeometryPointSize)
{
config->backend_info.bSupportsGeometryShaders = VK_FALSE;
config->backend_info.bSupportsGSInstancing = VK_FALSE;
}
// Depth clamping implies shaderClipDistance and depthClamp
- config->backend_info.bSupportsDepthClamp =
- (features.depthClamp == VK_TRUE && features.shaderClipDistance == VK_TRUE);
+ config->backend_info.bSupportsDepthClamp = info.depthClamp && info.shaderClipDistance;
// textureCompressionBC implies BC1 through BC7, which is a superset of DXT1/3/5, which we need.
- const bool supports_bc = features.textureCompressionBC == VK_TRUE;
- config->backend_info.bSupportsST3CTextures = supports_bc;
- config->backend_info.bSupportsBPTCTextures = supports_bc;
+ config->backend_info.bSupportsST3CTextures = info.textureCompressionBC;
+ config->backend_info.bSupportsBPTCTextures = info.textureCompressionBC;
// Some devices don't support point sizes >1 (e.g. Adreno).
// If we can't use a point size above our maximum IR, use triangles instead for EFB pokes.
// This means a 6x increase in the size of the vertices, though.
- config->backend_info.bSupportsLargePoints = features.largePoints &&
- properties.limits.pointSizeRange[0] <= 1.0f &&
- properties.limits.pointSizeRange[1] >= 16;
+ config->backend_info.bSupportsLargePoints =
+ info.largePoints && info.pointSizeRange[0] <= 1.0f && info.pointSizeRange[1] >= 16;
- std::string device_name = properties.deviceName;
- u32 vendor_id = properties.vendorID;
+ std::string device_name = info.deviceName;
+ u32 vendor_id = info.vendorID;
// Only Apple family GPUs support framebuffer fetch.
if (vendor_id == 0x106B || device_name.find("Apple") != std::string::npos)
@@ -465,8 +540,8 @@ void VulkanContext::PopulateBackendInfoFeatures(VideoConfig* config, VkPhysicalD
config->backend_info.bSupportsDynamicSamplerIndexing = false;
}
-void VulkanContext::PopulateBackendInfoMultisampleModes(
- VideoConfig* config, VkPhysicalDevice gpu, const VkPhysicalDeviceProperties& properties)
+void VulkanContext::PopulateBackendInfoMultisampleModes(VideoConfig* config, VkPhysicalDevice gpu,
+ const PhysicalDeviceInfo& info)
{
// Query image support for the EFB texture formats.
VkImageFormatProperties efb_color_properties = {};
@@ -479,10 +554,9 @@ void VulkanContext::PopulateBackendInfoMultisampleModes(
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0, &efb_depth_properties);
// We can only support MSAA if it's supported on our render target formats.
- VkSampleCountFlags supported_sample_counts = properties.limits.framebufferColorSampleCounts &
- properties.limits.framebufferDepthSampleCounts &
- efb_color_properties.sampleCounts &
- efb_depth_properties.sampleCounts;
+ VkSampleCountFlags supported_sample_counts =
+ info.framebufferColorSampleCounts & info.framebufferDepthSampleCounts &
+ efb_color_properties.sampleCounts & efb_depth_properties.sampleCounts;
// No AA
config->backend_info.AAModes.clear();
@@ -522,7 +596,6 @@ std::unique_ptr<VulkanContext> VulkanContext::Create(VkInstance instance, VkPhys
// Initialize DriverDetails so that we can check for bugs to disable features if needed.
context->InitDriverDetails();
- context->PopulateShaderSubgroupSupport();
// Enable debug messages if the "Host GPU" log category is enabled.
if (enable_debug_utils)
@@ -599,41 +672,15 @@ bool VulkanContext::SelectDeviceExtensions(bool enable_surface)
return true;
}
-bool VulkanContext::SelectDeviceFeatures()
+void VulkanContext::WarnMissingDeviceFeatures()
{
- VkPhysicalDeviceProperties properties;
- vkGetPhysicalDeviceProperties(m_physical_device, &properties);
-
- VkPhysicalDeviceFeatures available_features;
- vkGetPhysicalDeviceFeatures(m_physical_device, &available_features);
-
- // Not having geometry shaders or wide lines will cause issues with rendering.
- if (!available_features.geometryShader && !available_features.wideLines)
- WARN_LOG_FMT(VIDEO, "Vulkan: Missing both geometryShader and wideLines features.");
- if (!available_features.largePoints)
+ if (!m_device_info.largePoints)
WARN_LOG_FMT(VIDEO, "Vulkan: Missing large points feature. CPU EFB writes will be slower.");
- if (!available_features.occlusionQueryPrecise)
+ if (!m_device_info.occlusionQueryPrecise)
{
WARN_LOG_FMT(VIDEO,
"Vulkan: Missing precise occlusion queries. Perf queries will be inaccurate.");
}
- // Enable the features we use.
- m_device_features.dualSrcBlend = available_features.dualSrcBlend;
- m_device_features.geometryShader = available_features.geometryShader;
- m_device_features.samplerAnisotropy = available_features.samplerAnisotropy;
- m_device_features.logicOp = available_features.logicOp;
- m_device_features.fragmentStoresAndAtomics = available_features.fragmentStoresAndAtomics;
- m_device_features.sampleRateShading = available_features.sampleRateShading;
- m_device_features.largePoints = available_features.largePoints;
- m_device_features.shaderStorageImageMultisample =
- available_features.shaderStorageImageMultisample;
- m_device_features.shaderTessellationAndGeometryPointSize =
- available_features.shaderTessellationAndGeometryPointSize;
- m_device_features.occlusionQueryPrecise = available_features.occlusionQueryPrecise;
- m_device_features.shaderClipDistance = available_features.shaderClipDistance;
- m_device_features.depthClamp = available_features.depthClamp;
- m_device_features.textureCompressionBC = available_features.textureCompressionBC;
- return true;
}
bool VulkanContext::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer)
@@ -749,11 +796,10 @@ bool VulkanContext::CreateDevice(VkSurfaceKHR surface, bool enable_validation_la
device_info.enabledExtensionCount = static_cast<uint32_t>(extension_name_pointers.size());
device_info.ppEnabledExtensionNames = extension_name_pointers.data();
- // Check for required features before creating.
- if (!SelectDeviceFeatures())
- return false;
+ WarnMissingDeviceFeatures();
- device_info.pEnabledFeatures = &m_device_features;
+ VkPhysicalDeviceFeatures device_features = m_device_info.features();
+ device_info.pEnabledFeatures = &device_features;
// Enable debug layer on debug builds
if (enable_validation_layer)
@@ -888,8 +934,8 @@ void VulkanContext::InitDriverDetails()
// String comparisons aren't ideal, but there doesn't seem to be any other way to tell
// which vendor a driver is for. These names are based on the reports submitted to
// vulkan.gpuinfo.org, as of 19/09/2017.
- std::string device_name = m_device_properties.deviceName;
- u32 vendor_id = m_device_properties.vendorID;
+ std::string device_name = m_device_info.deviceName;
+ u32 vendor_id = m_device_info.vendorID;
if (vendor_id == 0x10DE)
{
// Currently, there is only the official NV binary driver.
@@ -966,43 +1012,10 @@ void VulkanContext::InitDriverDetails()
#endif
DriverDetails::Init(DriverDetails::API_VULKAN, vendor, driver,
- static_cast<double>(m_device_properties.driverVersion),
+ static_cast<double>(m_device_info.driverVersion),
DriverDetails::Family::UNKNOWN, std::move(device_name));
}
-void VulkanContext::PopulateShaderSubgroupSupport()
-{
- // Vulkan 1.1 support is required for vkGetPhysicalDeviceProperties2(), but we can't rely on the
- // function pointer alone.
- if (!vkGetPhysicalDeviceProperties2 || (VK_VERSION_MAJOR(m_device_properties.apiVersion) == 1 &&
- VK_VERSION_MINOR(m_device_properties.apiVersion) < 1))
- {
- return;
- }
-
- VkPhysicalDeviceProperties2 device_properties_2 = {};
- device_properties_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
-
- VkPhysicalDeviceSubgroupProperties subgroup_properties = {};
- subgroup_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
- device_properties_2.pNext = &subgroup_properties;
-
- vkGetPhysicalDeviceProperties2(m_physical_device, &device_properties_2);
-
- m_shader_subgroup_size = subgroup_properties.subgroupSize;
-
- // We require basic ops (for gl_SubgroupInvocationID), ballot (for subgroupBallot,
- // subgroupBallotFindLSB), and arithmetic (for subgroupMin/subgroupMax).
- // Shuffle is enabled as a workaround until SPIR-V >= 1.5 is enabled with broadcast(uniform)
- // support.
- constexpr VkSubgroupFeatureFlags required_operations =
- VK_SUBGROUP_FEATURE_BASIC_BIT | VK_SUBGROUP_FEATURE_ARITHMETIC_BIT |
- VK_SUBGROUP_FEATURE_BALLOT_BIT | VK_SUBGROUP_FEATURE_SHUFFLE_BIT;
- m_supports_shader_subgroup_operations =
- (subgroup_properties.supportedOperations & required_operations) == required_operations &&
- subgroup_properties.supportedStages & VK_SHADER_STAGE_FRAGMENT_BIT;
-}
-
bool VulkanContext::SupportsExclusiveFullscreen(const WindowSystemInfo& wsi, VkSurfaceKHR surface)
{
#ifdef SUPPORTS_VULKAN_EXCLUSIVE_FULLSCREEN
diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.h b/Source/Core/VideoBackends/Vulkan/VulkanContext.h
index 17b1459aa6..2ec870661c 100644
--- a/Source/Core/VideoBackends/Vulkan/VulkanContext.h
+++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.h
@@ -18,6 +18,43 @@ namespace Vulkan
class VulkanContext
{
public:
+ struct PhysicalDeviceInfo
+ {
+ PhysicalDeviceInfo(const PhysicalDeviceInfo&) = default;
+ explicit PhysicalDeviceInfo(VkPhysicalDevice device);
+ VkPhysicalDeviceFeatures features() const;
+
+ char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE];
+ u8 pipelineCacheUUID[VK_UUID_SIZE];
+ u32 apiVersion;
+ u32 driverVersion;
+ u32 vendorID;
+ u32 deviceID;
+ VkDeviceSize minUniformBufferOffsetAlignment;
+ VkDeviceSize bufferImageGranularity;
+ u32 maxTexelBufferElements;
+ u32 maxImageDimension2D;
+ VkSampleCountFlags framebufferColorSampleCounts;
+ VkSampleCountFlags framebufferDepthSampleCounts;
+ float pointSizeRange[2];
+ float maxSamplerAnisotropy;
+ u32 subgroupSize = 1;
+ bool dualSrcBlend;
+ bool geometryShader;
+ bool samplerAnisotropy;
+ bool logicOp;
+ bool fragmentStoresAndAtomics;
+ bool sampleRateShading;
+ bool largePoints;
+ bool shaderStorageImageMultisample;
+ bool shaderTessellationAndGeometryPointSize;
+ bool occlusionQueryPrecise;
+ bool shaderClipDistance;
+ bool depthClamp;
+ bool textureCompressionBC;
+ bool shaderSubgroupOperations = false;
+ };
+
VulkanContext(VkInstance instance, VkPhysicalDevice physical_device);
~VulkanContext();
@@ -37,10 +74,9 @@ public:
static void PopulateBackendInfo(VideoConfig* config);
static void PopulateBackendInfoAdapters(VideoConfig* config, const GPUList& gpu_list);
static void PopulateBackendInfoFeatures(VideoConfig* config, VkPhysicalDevice gpu,
- const VkPhysicalDeviceProperties& properties,
- const VkPhysicalDeviceFeatures& features);
+ const PhysicalDeviceInfo& info);
static void PopulateBackendInfoMultisampleModes(VideoConfig* config, VkPhysicalDevice gpu,
- const VkPhysicalDeviceProperties& properties);
+ const PhysicalDeviceInfo& info);
// Creates a Vulkan device context.
// This assumes that PopulateBackendInfo and PopulateBackendInfoAdapters has already
@@ -65,39 +101,20 @@ public:
{
return m_graphics_queue_properties;
}
- const VkPhysicalDeviceMemoryProperties& GetDeviceMemoryProperties() const
- {
- return m_device_memory_properties;
- }
- const VkPhysicalDeviceProperties& GetDeviceProperties() const { return m_device_properties; }
- const VkPhysicalDeviceFeatures& GetDeviceFeatures() const { return m_device_features; }
- const VkPhysicalDeviceLimits& GetDeviceLimits() const { return m_device_properties.limits; }
+ const PhysicalDeviceInfo& GetDeviceInfo() const { return m_device_info; }
// Support bits
- bool SupportsAnisotropicFiltering() const
- {
- return m_device_features.samplerAnisotropy == VK_TRUE;
- }
- bool SupportsPreciseOcclusionQueries() const
- {
- return m_device_features.occlusionQueryPrecise == VK_TRUE;
- }
- u32 GetShaderSubgroupSize() const { return m_shader_subgroup_size; }
- bool SupportsShaderSubgroupOperations() const { return m_supports_shader_subgroup_operations; }
+ bool SupportsAnisotropicFiltering() const { return m_device_info.samplerAnisotropy; }
+ bool SupportsPreciseOcclusionQueries() const { return m_device_info.occlusionQueryPrecise; }
+ u32 GetShaderSubgroupSize() const { return m_device_info.subgroupSize; }
+ bool SupportsShaderSubgroupOperations() const { return m_device_info.shaderSubgroupOperations; }
// Helpers for getting constants
VkDeviceSize GetUniformBufferAlignment() const
{
- return m_device_properties.limits.minUniformBufferOffsetAlignment;
- }
- VkDeviceSize GetTexelBufferAlignment() const
- {
- return m_device_properties.limits.minUniformBufferOffsetAlignment;
+ return m_device_info.minUniformBufferOffsetAlignment;
}
- VkDeviceSize GetBufferImageGranularity() const
- {
- return m_device_properties.limits.bufferImageGranularity;
- }
- float GetMaxSamplerAnisotropy() const { return m_device_properties.limits.maxSamplerAnisotropy; }
+ VkDeviceSize GetBufferImageGranularity() const { return m_device_info.bufferImageGranularity; }
+ float GetMaxSamplerAnisotropy() const { return m_device_info.maxSamplerAnisotropy; }
// Returns true if the specified extension is supported and enabled.
bool SupportsDeviceExtension(const char* name) const;
@@ -118,10 +135,9 @@ private:
WindowSystemType wstype, bool enable_debug_utils,
bool validation_layer_enabled);
bool SelectDeviceExtensions(bool enable_surface);
- bool SelectDeviceFeatures();
+ void WarnMissingDeviceFeatures();
bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer);
void InitDriverDetails();
- void PopulateShaderSubgroupSupport();
bool CreateAllocator(u32 vk_api_version);
VkInstance m_instance = VK_NULL_HANDLE;
@@ -137,12 +153,7 @@ private:
VkDebugUtilsMessengerEXT m_debug_utils_messenger = VK_NULL_HANDLE;
- VkPhysicalDeviceFeatures m_device_features = {};
- VkPhysicalDeviceProperties m_device_properties = {};
- VkPhysicalDeviceMemoryProperties m_device_memory_properties = {};
-
- u32 m_shader_subgroup_size = 1;
- bool m_supports_shader_subgroup_operations = false;
+ PhysicalDeviceInfo m_device_info;
std::vector<std::string> m_device_extensions;
};