Merge pull request #13050 from TellowKrinkle/HKIsNotMVK
Vulkan: Don't do MoltenVK things on Asahi Linux
This commit is contained in:
commit
2d9f789940
|
@ -627,24 +627,24 @@ bool ObjectCache::ValidatePipelineCache(const u8* data, size_t data_length)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.vendor_id != g_vulkan_context->GetDeviceProperties().vendorID)
|
if (header.vendor_id != g_vulkan_context->GetDeviceInfo().vendorID)
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(
|
ERROR_LOG_FMT(
|
||||||
VIDEO, "Pipeline cache failed validation: Incorrect vendor ID (file: {:#X}, device: {:#X})",
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.device_id != g_vulkan_context->GetDeviceProperties().deviceID)
|
if (header.device_id != g_vulkan_context->GetDeviceInfo().deviceID)
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(
|
ERROR_LOG_FMT(
|
||||||
VIDEO, "Pipeline cache failed validation: Incorrect device ID (file: {:#X}, device: {:#X})",
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::memcmp(header.uuid, g_vulkan_context->GetDeviceProperties().pipelineCacheUUID,
|
if (std::memcmp(header.uuid, g_vulkan_context->GetDeviceInfo().pipelineCacheUUID, VK_UUID_SIZE) !=
|
||||||
VK_UUID_SIZE) != 0)
|
0)
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(VIDEO, "Pipeline cache failed validation: Incorrect UUID");
|
ERROR_LOG_FMT(VIDEO, "Pipeline cache failed validation: Incorrect UUID");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -54,11 +54,8 @@ void VideoBackend::InitBackendInfo(const WindowSystemInfo& wsi)
|
||||||
device_index = 0;
|
device_index = 0;
|
||||||
|
|
||||||
VkPhysicalDevice gpu = gpu_list[device_index];
|
VkPhysicalDevice gpu = gpu_list[device_index];
|
||||||
VkPhysicalDeviceProperties properties;
|
VulkanContext::PhysicalDeviceInfo properties(gpu);
|
||||||
vkGetPhysicalDeviceProperties(gpu, &properties);
|
VulkanContext::PopulateBackendInfoFeatures(&g_Config, gpu, properties);
|
||||||
VkPhysicalDeviceFeatures features;
|
|
||||||
vkGetPhysicalDeviceFeatures(gpu, &features);
|
|
||||||
VulkanContext::PopulateBackendInfoFeatures(&g_Config, gpu, properties, features);
|
|
||||||
VulkanContext::PopulateBackendInfoMultisampleModes(&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
|
// 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.
|
// to initialize the backend information, so that we don't need to enumerate everything again.
|
||||||
VulkanContext::PopulateBackendInfoFeatures(&g_Config, g_vulkan_context->GetPhysicalDevice(),
|
VulkanContext::PopulateBackendInfoFeatures(&g_Config, g_vulkan_context->GetPhysicalDevice(),
|
||||||
g_vulkan_context->GetDeviceProperties(),
|
g_vulkan_context->GetDeviceInfo());
|
||||||
g_vulkan_context->GetDeviceFeatures());
|
|
||||||
VulkanContext::PopulateBackendInfoMultisampleModes(
|
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 =
|
g_Config.backend_info.bSupportsExclusiveFullscreen =
|
||||||
enable_surface && g_vulkan_context->SupportsExclusiveFullscreen(wsi, surface);
|
enable_surface && g_vulkan_context->SupportsExclusiveFullscreen(wsi, surface);
|
||||||
|
|
||||||
|
|
|
@ -92,8 +92,8 @@ bool VertexManager::Initialize()
|
||||||
// Prefer an 8MB buffer if possible, but use less if the device doesn't support this.
|
// 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
|
// This buffer is potentially going to be addressed as R8s in the future, so we assume
|
||||||
// that one element is one byte.
|
// that one element is one byte.
|
||||||
const u32 texel_buffer_size = std::min(
|
const u32 texel_buffer_size =
|
||||||
TEXEL_STREAM_BUFFER_SIZE, g_vulkan_context->GetDeviceLimits().maxTexelBufferElements);
|
std::min(TEXEL_STREAM_BUFFER_SIZE, g_vulkan_context->GetDeviceInfo().maxTexelBufferElements);
|
||||||
m_texel_stream_buffer =
|
m_texel_stream_buffer =
|
||||||
StreamBuffer::Create(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, texel_buffer_size);
|
StreamBuffer::Create(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, texel_buffer_size);
|
||||||
if (!m_texel_stream_buffer)
|
if (!m_texel_stream_buffer)
|
||||||
|
|
|
@ -22,22 +22,113 @@ static constexpr const char* VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validatio
|
||||||
|
|
||||||
std::unique_ptr<VulkanContext> g_vulkan_context;
|
std::unique_ptr<VulkanContext> g_vulkan_context;
|
||||||
|
|
||||||
VulkanContext::VulkanContext(VkInstance instance, VkPhysicalDevice physical_device)
|
template <typename Chain, typename Element>
|
||||||
: m_instance(instance), m_physical_device(physical_device)
|
static void InsertIntoChain(Chain* chain, Element* element)
|
||||||
{
|
{
|
||||||
// Read device physical memory properties, we need it for allocating buffers
|
element->pNext = chain->pNext;
|
||||||
vkGetPhysicalDeviceProperties(physical_device, &m_device_properties);
|
chain->pNext = element;
|
||||||
vkGetPhysicalDeviceMemoryProperties(physical_device, &m_device_memory_properties);
|
}
|
||||||
|
|
||||||
// Would any drivers be this silly? I hope not...
|
VulkanContext::PhysicalDeviceInfo::PhysicalDeviceInfo(VkPhysicalDevice device)
|
||||||
m_device_properties.limits.minUniformBufferOffsetAlignment = std::max(
|
{
|
||||||
m_device_properties.limits.minUniformBufferOffsetAlignment, static_cast<VkDeviceSize>(1));
|
VkPhysicalDeviceFeatures features;
|
||||||
m_device_properties.limits.minTexelBufferOffsetAlignment = std::max(
|
VkPhysicalDeviceProperties2 properties2;
|
||||||
m_device_properties.limits.minTexelBufferOffsetAlignment, static_cast<VkDeviceSize>(1));
|
VkPhysicalDeviceProperties& properties = properties2.properties;
|
||||||
m_device_properties.limits.optimalBufferCopyOffsetAlignment = std::max(
|
|
||||||
m_device_properties.limits.optimalBufferCopyOffsetAlignment, static_cast<VkDeviceSize>(1));
|
vkGetPhysicalDeviceProperties(device, &properties);
|
||||||
m_device_properties.limits.optimalBufferCopyRowPitchAlignment = std::max(
|
vkGetPhysicalDeviceFeatures(device, &features);
|
||||||
m_device_properties.limits.optimalBufferCopyRowPitchAlignment, static_cast<VkDeviceSize>(1));
|
apiVersion = vkGetPhysicalDeviceProperties2 ? properties.apiVersion : VK_API_VERSION_1_0;
|
||||||
|
|
||||||
|
if (apiVersion >= VK_API_VERSION_1_1)
|
||||||
|
{
|
||||||
|
VkPhysicalDeviceSubgroupProperties properties_subgroup = {};
|
||||||
|
VkPhysicalDeviceVulkan12Properties properties_vk12 = {};
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (apiVersion >= VK_API_VERSION_1_2)
|
||||||
|
{
|
||||||
|
properties_vk12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES;
|
||||||
|
InsertIntoChain(&properties2, &properties_vk12);
|
||||||
|
}
|
||||||
|
|
||||||
|
vkGetPhysicalDeviceProperties2(device, &properties2);
|
||||||
|
|
||||||
|
if (apiVersion >= VK_API_VERSION_1_2)
|
||||||
|
{
|
||||||
|
driverID = properties_vk12.driverID;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_device_info(physical_device)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanContext::~VulkanContext()
|
VulkanContext::~VulkanContext()
|
||||||
|
@ -115,6 +206,27 @@ bool VulkanContext::CheckValidationLayerAvailablility()
|
||||||
return supports_debug_utils && supports_validation_layers;
|
return supports_debug_utils && supports_validation_layers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 getAPIVersion()
|
||||||
|
{
|
||||||
|
u32 supported_version;
|
||||||
|
u32 used_version = VK_API_VERSION_1_0;
|
||||||
|
if (vkEnumerateInstanceVersion && vkEnumerateInstanceVersion(&supported_version) == VK_SUCCESS)
|
||||||
|
{
|
||||||
|
// The device itself may not support 1.1, so we check that before using any 1.1 functionality.
|
||||||
|
if (supported_version >= VK_API_VERSION_1_2)
|
||||||
|
used_version = VK_API_VERSION_1_2;
|
||||||
|
else if (supported_version >= VK_API_VERSION_1_1)
|
||||||
|
used_version = VK_API_VERSION_1_1;
|
||||||
|
WARN_LOG_FMT(HOST_GPU, "Using Vulkan 1.{}, supported: {}.{}", VK_VERSION_MINOR(used_version),
|
||||||
|
VK_VERSION_MAJOR(supported_version), VK_VERSION_MINOR(supported_version));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WARN_LOG_FMT(HOST_GPU, "Using Vulkan 1.0");
|
||||||
|
}
|
||||||
|
return used_version;
|
||||||
|
}
|
||||||
|
|
||||||
VkInstance VulkanContext::CreateVulkanInstance(WindowSystemType wstype, bool enable_debug_utils,
|
VkInstance VulkanContext::CreateVulkanInstance(WindowSystemType wstype, bool enable_debug_utils,
|
||||||
bool enable_validation_layer,
|
bool enable_validation_layer,
|
||||||
u32* out_vk_api_version)
|
u32* out_vk_api_version)
|
||||||
|
@ -131,31 +243,7 @@ VkInstance VulkanContext::CreateVulkanInstance(WindowSystemType wstype, bool ena
|
||||||
app_info.applicationVersion = VK_MAKE_VERSION(5, 0, 0);
|
app_info.applicationVersion = VK_MAKE_VERSION(5, 0, 0);
|
||||||
app_info.pEngineName = "Dolphin Emulator";
|
app_info.pEngineName = "Dolphin Emulator";
|
||||||
app_info.engineVersion = VK_MAKE_VERSION(5, 0, 0);
|
app_info.engineVersion = VK_MAKE_VERSION(5, 0, 0);
|
||||||
app_info.apiVersion = VK_MAKE_VERSION(1, 0, 0);
|
app_info.apiVersion = getAPIVersion();
|
||||||
|
|
||||||
// Try for Vulkan 1.1 if the loader supports it.
|
|
||||||
if (vkEnumerateInstanceVersion)
|
|
||||||
{
|
|
||||||
u32 supported_api_version = 0;
|
|
||||||
VkResult res = vkEnumerateInstanceVersion(&supported_api_version);
|
|
||||||
if (res == VK_SUCCESS && (VK_VERSION_MAJOR(supported_api_version) > 1 ||
|
|
||||||
VK_VERSION_MINOR(supported_api_version) >= 1))
|
|
||||||
{
|
|
||||||
// The device itself may not support 1.1, so we check that before using any 1.1 functionality.
|
|
||||||
app_info.apiVersion = VK_MAKE_VERSION(1, 1, 0);
|
|
||||||
WARN_LOG_FMT(HOST_GPU, "Using Vulkan 1.1, supported: {}.{}",
|
|
||||||
VK_VERSION_MAJOR(supported_api_version),
|
|
||||||
VK_VERSION_MINOR(supported_api_version));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WARN_LOG_FMT(HOST_GPU, "Using Vulkan 1.0");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WARN_LOG_FMT(HOST_GPU, "Using Vulkan 1.0");
|
|
||||||
}
|
|
||||||
|
|
||||||
*out_vk_api_version = app_info.apiVersion;
|
*out_vk_api_version = app_info.apiVersion;
|
||||||
|
|
||||||
|
@ -397,55 +485,49 @@ void VulkanContext::PopulateBackendInfoAdapters(VideoConfig* config, const GPULi
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanContext::PopulateBackendInfoFeatures(VideoConfig* config, VkPhysicalDevice gpu,
|
void VulkanContext::PopulateBackendInfoFeatures(VideoConfig* config, VkPhysicalDevice gpu,
|
||||||
const VkPhysicalDeviceProperties& properties,
|
const PhysicalDeviceInfo& info)
|
||||||
const VkPhysicalDeviceFeatures& features)
|
|
||||||
{
|
{
|
||||||
config->backend_info.MaxTextureSize = properties.limits.maxImageDimension2D;
|
config->backend_info.MaxTextureSize = info.maxImageDimension2D;
|
||||||
config->backend_info.bUsesLowerLeftOrigin = false;
|
config->backend_info.bUsesLowerLeftOrigin = false;
|
||||||
config->backend_info.bSupportsDualSourceBlend = (features.dualSrcBlend == VK_TRUE);
|
config->backend_info.bSupportsDualSourceBlend = info.dualSrcBlend;
|
||||||
config->backend_info.bSupportsGeometryShaders = (features.geometryShader == VK_TRUE);
|
config->backend_info.bSupportsGeometryShaders = info.geometryShader;
|
||||||
config->backend_info.bSupportsGSInstancing = (features.geometryShader == VK_TRUE);
|
config->backend_info.bSupportsGSInstancing = info.geometryShader;
|
||||||
config->backend_info.bSupportsBBox = config->backend_info.bSupportsFragmentStoresAndAtomics =
|
config->backend_info.bSupportsBBox = config->backend_info.bSupportsFragmentStoresAndAtomics =
|
||||||
(features.fragmentStoresAndAtomics == VK_TRUE);
|
info.fragmentStoresAndAtomics;
|
||||||
config->backend_info.bSupportsSSAA = (features.sampleRateShading == VK_TRUE);
|
config->backend_info.bSupportsSSAA = info.sampleRateShading;
|
||||||
config->backend_info.bSupportsLogicOp = (features.logicOp == VK_TRUE);
|
config->backend_info.bSupportsLogicOp = info.logicOp;
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
// Metal doesn't support this.
|
// Metal doesn't support this.
|
||||||
config->backend_info.bSupportsLodBiasInSampler = false;
|
config->backend_info.bSupportsLodBiasInSampler = info.driverID != VK_DRIVER_ID_MOLTENVK;
|
||||||
#else
|
|
||||||
config->backend_info.bSupportsLodBiasInSampler = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Disable geometry shader when shaderTessellationAndGeometryPointSize is not supported.
|
// Disable geometry shader when shaderTessellationAndGeometryPointSize is not supported.
|
||||||
// Seems this is needed for gl_Layer.
|
// Seems this is needed for gl_Layer.
|
||||||
if (!features.shaderTessellationAndGeometryPointSize)
|
if (!info.shaderTessellationAndGeometryPointSize)
|
||||||
{
|
{
|
||||||
config->backend_info.bSupportsGeometryShaders = VK_FALSE;
|
config->backend_info.bSupportsGeometryShaders = VK_FALSE;
|
||||||
config->backend_info.bSupportsGSInstancing = VK_FALSE;
|
config->backend_info.bSupportsGSInstancing = VK_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Depth clamping implies shaderClipDistance and depthClamp
|
// Depth clamping implies shaderClipDistance and depthClamp
|
||||||
config->backend_info.bSupportsDepthClamp =
|
config->backend_info.bSupportsDepthClamp = info.depthClamp && info.shaderClipDistance;
|
||||||
(features.depthClamp == VK_TRUE && features.shaderClipDistance == VK_TRUE);
|
|
||||||
|
|
||||||
// textureCompressionBC implies BC1 through BC7, which is a superset of DXT1/3/5, which we need.
|
// 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 = info.textureCompressionBC;
|
||||||
config->backend_info.bSupportsST3CTextures = supports_bc;
|
config->backend_info.bSupportsBPTCTextures = info.textureCompressionBC;
|
||||||
config->backend_info.bSupportsBPTCTextures = supports_bc;
|
|
||||||
|
|
||||||
// Some devices don't support point sizes >1 (e.g. Adreno).
|
// 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.
|
// 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.
|
// This means a 6x increase in the size of the vertices, though.
|
||||||
config->backend_info.bSupportsLargePoints = features.largePoints &&
|
config->backend_info.bSupportsLargePoints =
|
||||||
properties.limits.pointSizeRange[0] <= 1.0f &&
|
info.largePoints && info.pointSizeRange[0] <= 1.0f && info.pointSizeRange[1] >= 16;
|
||||||
properties.limits.pointSizeRange[1] >= 16;
|
|
||||||
|
|
||||||
std::string device_name = properties.deviceName;
|
std::string device_name = info.deviceName;
|
||||||
u32 vendor_id = properties.vendorID;
|
u32 vendor_id = info.vendorID;
|
||||||
|
bool is_moltenvk = info.driverID == VK_DRIVER_ID_MOLTENVK;
|
||||||
|
|
||||||
// Only Apple family GPUs support framebuffer fetch.
|
// Only Apple family GPUs support framebuffer fetch.
|
||||||
if (vendor_id == 0x106B || device_name.find("Apple") != std::string::npos)
|
// We currently use a hacked MoltenVK to implement this, so don't attempt outside of MVK
|
||||||
|
if (is_moltenvk && (vendor_id == 0x106B || device_name.find("Apple") != std::string::npos))
|
||||||
{
|
{
|
||||||
config->backend_info.bSupportsFramebufferFetch = true;
|
config->backend_info.bSupportsFramebufferFetch = true;
|
||||||
}
|
}
|
||||||
|
@ -465,8 +547,8 @@ void VulkanContext::PopulateBackendInfoFeatures(VideoConfig* config, VkPhysicalD
|
||||||
config->backend_info.bSupportsDynamicSamplerIndexing = false;
|
config->backend_info.bSupportsDynamicSamplerIndexing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanContext::PopulateBackendInfoMultisampleModes(
|
void VulkanContext::PopulateBackendInfoMultisampleModes(VideoConfig* config, VkPhysicalDevice gpu,
|
||||||
VideoConfig* config, VkPhysicalDevice gpu, const VkPhysicalDeviceProperties& properties)
|
const PhysicalDeviceInfo& info)
|
||||||
{
|
{
|
||||||
// Query image support for the EFB texture formats.
|
// Query image support for the EFB texture formats.
|
||||||
VkImageFormatProperties efb_color_properties = {};
|
VkImageFormatProperties efb_color_properties = {};
|
||||||
|
@ -479,10 +561,9 @@ void VulkanContext::PopulateBackendInfoMultisampleModes(
|
||||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0, &efb_depth_properties);
|
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.
|
// We can only support MSAA if it's supported on our render target formats.
|
||||||
VkSampleCountFlags supported_sample_counts = properties.limits.framebufferColorSampleCounts &
|
VkSampleCountFlags supported_sample_counts =
|
||||||
properties.limits.framebufferDepthSampleCounts &
|
info.framebufferColorSampleCounts & info.framebufferDepthSampleCounts &
|
||||||
efb_color_properties.sampleCounts &
|
efb_color_properties.sampleCounts & efb_depth_properties.sampleCounts;
|
||||||
efb_depth_properties.sampleCounts;
|
|
||||||
|
|
||||||
// No AA
|
// No AA
|
||||||
config->backend_info.AAModes.clear();
|
config->backend_info.AAModes.clear();
|
||||||
|
@ -522,7 +603,6 @@ std::unique_ptr<VulkanContext> VulkanContext::Create(VkInstance instance, VkPhys
|
||||||
|
|
||||||
// Initialize DriverDetails so that we can check for bugs to disable features if needed.
|
// Initialize DriverDetails so that we can check for bugs to disable features if needed.
|
||||||
context->InitDriverDetails();
|
context->InitDriverDetails();
|
||||||
context->PopulateShaderSubgroupSupport();
|
|
||||||
|
|
||||||
// Enable debug messages if the "Host GPU" log category is enabled.
|
// Enable debug messages if the "Host GPU" log category is enabled.
|
||||||
if (enable_debug_utils)
|
if (enable_debug_utils)
|
||||||
|
@ -599,41 +679,15 @@ bool VulkanContext::SelectDeviceExtensions(bool enable_surface)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VulkanContext::SelectDeviceFeatures()
|
void VulkanContext::WarnMissingDeviceFeatures()
|
||||||
{
|
{
|
||||||
VkPhysicalDeviceProperties properties;
|
if (!m_device_info.largePoints)
|
||||||
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)
|
|
||||||
WARN_LOG_FMT(VIDEO, "Vulkan: Missing large points feature. CPU EFB writes will be slower.");
|
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,
|
WARN_LOG_FMT(VIDEO,
|
||||||
"Vulkan: Missing precise occlusion queries. Perf queries will be inaccurate.");
|
"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)
|
bool VulkanContext::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer)
|
||||||
|
@ -749,11 +803,10 @@ bool VulkanContext::CreateDevice(VkSurfaceKHR surface, bool enable_validation_la
|
||||||
device_info.enabledExtensionCount = static_cast<uint32_t>(extension_name_pointers.size());
|
device_info.enabledExtensionCount = static_cast<uint32_t>(extension_name_pointers.size());
|
||||||
device_info.ppEnabledExtensionNames = extension_name_pointers.data();
|
device_info.ppEnabledExtensionNames = extension_name_pointers.data();
|
||||||
|
|
||||||
// Check for required features before creating.
|
WarnMissingDeviceFeatures();
|
||||||
if (!SelectDeviceFeatures())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
device_info.pEnabledFeatures = &m_device_features;
|
VkPhysicalDeviceFeatures device_features = m_device_info.features();
|
||||||
|
device_info.pEnabledFeatures = &device_features;
|
||||||
|
|
||||||
// Enable debug layer on debug builds
|
// Enable debug layer on debug builds
|
||||||
if (enable_validation_layer)
|
if (enable_validation_layer)
|
||||||
|
@ -880,6 +933,41 @@ bool VulkanContext::SupportsDeviceExtension(const char* name) const
|
||||||
[name](const std::string& extension) { return extension == name; });
|
[name](const std::string& extension) { return extension == name; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool DriverIsMesa(VkDriverId driver_id)
|
||||||
|
{
|
||||||
|
switch (driver_id)
|
||||||
|
{
|
||||||
|
case VK_DRIVER_ID_MESA_RADV:
|
||||||
|
case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA:
|
||||||
|
case VK_DRIVER_ID_MESA_LLVMPIPE:
|
||||||
|
case VK_DRIVER_ID_MESA_TURNIP:
|
||||||
|
case VK_DRIVER_ID_MESA_V3DV:
|
||||||
|
case VK_DRIVER_ID_MESA_PANVK:
|
||||||
|
case VK_DRIVER_ID_MESA_VENUS:
|
||||||
|
case VK_DRIVER_ID_MESA_DOZEN:
|
||||||
|
case VK_DRIVER_ID_MESA_NVK:
|
||||||
|
case VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA:
|
||||||
|
case VK_DRIVER_ID_MESA_HONEYKRISP:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static DriverDetails::Driver GetMesaDriver(VkDriverId driver_id)
|
||||||
|
{
|
||||||
|
switch (driver_id)
|
||||||
|
{
|
||||||
|
// clang-format off
|
||||||
|
case VK_DRIVER_ID_MESA_RADV: return DriverDetails::DRIVER_R600;
|
||||||
|
case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA: return DriverDetails::DRIVER_I965;
|
||||||
|
case VK_DRIVER_ID_MESA_NVK: return DriverDetails::DRIVER_NOUVEAU;
|
||||||
|
case VK_DRIVER_ID_MESA_TURNIP: return DriverDetails::DRIVER_FREEDRENO;
|
||||||
|
default: return DriverDetails::DRIVER_UNKNOWN;
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VulkanContext::InitDriverDetails()
|
void VulkanContext::InitDriverDetails()
|
||||||
{
|
{
|
||||||
DriverDetails::Vendor vendor;
|
DriverDetails::Vendor vendor;
|
||||||
|
@ -888,9 +976,17 @@ void VulkanContext::InitDriverDetails()
|
||||||
// String comparisons aren't ideal, but there doesn't seem to be any other way to tell
|
// 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
|
// which vendor a driver is for. These names are based on the reports submitted to
|
||||||
// vulkan.gpuinfo.org, as of 19/09/2017.
|
// vulkan.gpuinfo.org, as of 19/09/2017.
|
||||||
std::string device_name = m_device_properties.deviceName;
|
std::string device_name = m_device_info.deviceName;
|
||||||
u32 vendor_id = m_device_properties.vendorID;
|
u32 vendor_id = m_device_info.vendorID;
|
||||||
if (vendor_id == 0x10DE)
|
// Note: driver_id may be 0 on vulkan < 1.2
|
||||||
|
VkDriverId driver_id = m_device_info.driverID;
|
||||||
|
|
||||||
|
if (DriverIsMesa(driver_id))
|
||||||
|
{
|
||||||
|
vendor = DriverDetails::VENDOR_MESA;
|
||||||
|
driver = GetMesaDriver(driver_id);
|
||||||
|
}
|
||||||
|
else if (vendor_id == 0x10DE)
|
||||||
{
|
{
|
||||||
// Currently, there is only the official NV binary driver.
|
// Currently, there is only the official NV binary driver.
|
||||||
// "NVIDIA" does not appear in the device name.
|
// "NVIDIA" does not appear in the device name.
|
||||||
|
@ -958,51 +1054,17 @@ void VulkanContext::InitDriverDetails()
|
||||||
driver = DriverDetails::DRIVER_UNKNOWN;
|
driver = DriverDetails::DRIVER_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
// Vulkan on macOS goes through Metal, and is not susceptible to the same bugs
|
// Vulkan on macOS goes through Metal, and is not susceptible to the same bugs
|
||||||
// as the vendor's native Vulkan drivers. We use a different driver fields to
|
// as the vendor's native Vulkan drivers. We use a different driver fields to
|
||||||
// differentiate MoltenVK.
|
// differentiate MoltenVK.
|
||||||
driver = DriverDetails::DRIVER_PORTABILITY;
|
if (driver_id == VK_DRIVER_ID_MOLTENVK)
|
||||||
#endif
|
driver = DriverDetails::DRIVER_PORTABILITY;
|
||||||
|
|
||||||
DriverDetails::Init(DriverDetails::API_VULKAN, vendor, driver,
|
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));
|
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)
|
bool VulkanContext::SupportsExclusiveFullscreen(const WindowSystemInfo& wsi, VkSurfaceKHR surface)
|
||||||
{
|
{
|
||||||
#ifdef SUPPORTS_VULKAN_EXCLUSIVE_FULLSCREEN
|
#ifdef SUPPORTS_VULKAN_EXCLUSIVE_FULLSCREEN
|
||||||
|
|
|
@ -18,6 +18,44 @@ namespace Vulkan
|
||||||
class VulkanContext
|
class VulkanContext
|
||||||
{
|
{
|
||||||
public:
|
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;
|
||||||
|
VkDriverId driverID = static_cast<VkDriverId>(0);
|
||||||
|
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(VkInstance instance, VkPhysicalDevice physical_device);
|
||||||
~VulkanContext();
|
~VulkanContext();
|
||||||
|
|
||||||
|
@ -37,10 +75,9 @@ public:
|
||||||
static void PopulateBackendInfo(VideoConfig* config);
|
static void PopulateBackendInfo(VideoConfig* config);
|
||||||
static void PopulateBackendInfoAdapters(VideoConfig* config, const GPUList& gpu_list);
|
static void PopulateBackendInfoAdapters(VideoConfig* config, const GPUList& gpu_list);
|
||||||
static void PopulateBackendInfoFeatures(VideoConfig* config, VkPhysicalDevice gpu,
|
static void PopulateBackendInfoFeatures(VideoConfig* config, VkPhysicalDevice gpu,
|
||||||
const VkPhysicalDeviceProperties& properties,
|
const PhysicalDeviceInfo& info);
|
||||||
const VkPhysicalDeviceFeatures& features);
|
|
||||||
static void PopulateBackendInfoMultisampleModes(VideoConfig* config, VkPhysicalDevice gpu,
|
static void PopulateBackendInfoMultisampleModes(VideoConfig* config, VkPhysicalDevice gpu,
|
||||||
const VkPhysicalDeviceProperties& properties);
|
const PhysicalDeviceInfo& info);
|
||||||
|
|
||||||
// Creates a Vulkan device context.
|
// Creates a Vulkan device context.
|
||||||
// This assumes that PopulateBackendInfo and PopulateBackendInfoAdapters has already
|
// This assumes that PopulateBackendInfo and PopulateBackendInfoAdapters has already
|
||||||
|
@ -65,39 +102,20 @@ public:
|
||||||
{
|
{
|
||||||
return m_graphics_queue_properties;
|
return m_graphics_queue_properties;
|
||||||
}
|
}
|
||||||
const VkPhysicalDeviceMemoryProperties& GetDeviceMemoryProperties() const
|
const PhysicalDeviceInfo& GetDeviceInfo() const { return m_device_info; }
|
||||||
{
|
|
||||||
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; }
|
|
||||||
// Support bits
|
// Support bits
|
||||||
bool SupportsAnisotropicFiltering() const
|
bool SupportsAnisotropicFiltering() const { return m_device_info.samplerAnisotropy; }
|
||||||
{
|
bool SupportsPreciseOcclusionQueries() const { return m_device_info.occlusionQueryPrecise; }
|
||||||
return m_device_features.samplerAnisotropy == VK_TRUE;
|
u32 GetShaderSubgroupSize() const { return m_device_info.subgroupSize; }
|
||||||
}
|
bool SupportsShaderSubgroupOperations() const { return m_device_info.shaderSubgroupOperations; }
|
||||||
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; }
|
|
||||||
|
|
||||||
// Helpers for getting constants
|
// Helpers for getting constants
|
||||||
VkDeviceSize GetUniformBufferAlignment() const
|
VkDeviceSize GetUniformBufferAlignment() const
|
||||||
{
|
{
|
||||||
return m_device_properties.limits.minUniformBufferOffsetAlignment;
|
return m_device_info.minUniformBufferOffsetAlignment;
|
||||||
}
|
}
|
||||||
VkDeviceSize GetTexelBufferAlignment() const
|
VkDeviceSize GetBufferImageGranularity() const { return m_device_info.bufferImageGranularity; }
|
||||||
{
|
float GetMaxSamplerAnisotropy() const { return m_device_info.maxSamplerAnisotropy; }
|
||||||
return m_device_properties.limits.minUniformBufferOffsetAlignment;
|
|
||||||
}
|
|
||||||
VkDeviceSize GetBufferImageGranularity() const
|
|
||||||
{
|
|
||||||
return m_device_properties.limits.bufferImageGranularity;
|
|
||||||
}
|
|
||||||
float GetMaxSamplerAnisotropy() const { return m_device_properties.limits.maxSamplerAnisotropy; }
|
|
||||||
|
|
||||||
// Returns true if the specified extension is supported and enabled.
|
// Returns true if the specified extension is supported and enabled.
|
||||||
bool SupportsDeviceExtension(const char* name) const;
|
bool SupportsDeviceExtension(const char* name) const;
|
||||||
|
@ -118,10 +136,9 @@ private:
|
||||||
WindowSystemType wstype, bool enable_debug_utils,
|
WindowSystemType wstype, bool enable_debug_utils,
|
||||||
bool validation_layer_enabled);
|
bool validation_layer_enabled);
|
||||||
bool SelectDeviceExtensions(bool enable_surface);
|
bool SelectDeviceExtensions(bool enable_surface);
|
||||||
bool SelectDeviceFeatures();
|
void WarnMissingDeviceFeatures();
|
||||||
bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer);
|
bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer);
|
||||||
void InitDriverDetails();
|
void InitDriverDetails();
|
||||||
void PopulateShaderSubgroupSupport();
|
|
||||||
bool CreateAllocator(u32 vk_api_version);
|
bool CreateAllocator(u32 vk_api_version);
|
||||||
|
|
||||||
VkInstance m_instance = VK_NULL_HANDLE;
|
VkInstance m_instance = VK_NULL_HANDLE;
|
||||||
|
@ -137,12 +154,7 @@ private:
|
||||||
|
|
||||||
VkDebugUtilsMessengerEXT m_debug_utils_messenger = VK_NULL_HANDLE;
|
VkDebugUtilsMessengerEXT m_debug_utils_messenger = VK_NULL_HANDLE;
|
||||||
|
|
||||||
VkPhysicalDeviceFeatures m_device_features = {};
|
PhysicalDeviceInfo m_device_info;
|
||||||
VkPhysicalDeviceProperties m_device_properties = {};
|
|
||||||
VkPhysicalDeviceMemoryProperties m_device_memory_properties = {};
|
|
||||||
|
|
||||||
u32 m_shader_subgroup_size = 1;
|
|
||||||
bool m_supports_shader_subgroup_operations = false;
|
|
||||||
|
|
||||||
std::vector<std::string> m_device_extensions;
|
std::vector<std::string> m_device_extensions;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue