summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
diff options
context:
space:
mode:
authorStenzek <stenzek@gmail.com>2019-10-02 21:27:32 +1000
committerStenzek <stenzek@gmail.com>2019-10-02 21:27:32 +1000
commitc557aa4a15b577fdaf2f5de71078c41037aea01e (patch)
treedc23c17a35148556e384c3f02b4e53d339a993b4 /Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
parente6ae204600306edd67ccbdeb32032f061c5128c0 (diff)
Vulkan: Add strict flag to memory type selection
Diffstat (limited to 'Source/Core/VideoBackends/Vulkan/VulkanContext.cpp')
-rw-r--r--Source/Core/VideoBackends/Vulkan/VulkanContext.cpp133
1 files changed, 67 insertions, 66 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
index ee6e11bba0..6a8256b683 100644
--- a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
+++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
@@ -710,96 +710,97 @@ void VulkanContext::DisableDebugReports()
}
}
-bool VulkanContext::GetMemoryType(u32 bits, VkMemoryPropertyFlags properties, u32* out_type_index)
+std::optional<u32> VulkanContext::GetMemoryType(u32 bits, VkMemoryPropertyFlags properties,
+ bool strict, bool* is_coherent)
{
+ static constexpr u32 ALL_MEMORY_PROPERTY_FLAGS = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+ VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
+ VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+
+ const u32 mask = strict ? ALL_MEMORY_PROPERTY_FLAGS : properties;
+
for (u32 i = 0; i < VK_MAX_MEMORY_TYPES; i++)
{
if ((bits & (1 << i)) != 0)
{
- u32 supported = m_device_memory_properties.memoryTypes[i].propertyFlags & properties;
+ const VkMemoryPropertyFlags type_flags =
+ m_device_memory_properties.memoryTypes[i].propertyFlags;
+ const VkMemoryPropertyFlags supported = type_flags & mask;
if (supported == properties)
{
- *out_type_index = i;
- return true;
+ if (is_coherent)
+ *is_coherent = (type_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0;
+ return i;
}
}
}
- return false;
-}
-
-u32 VulkanContext::GetMemoryType(u32 bits, VkMemoryPropertyFlags properties)
-{
- u32 type_index = VK_MAX_MEMORY_TYPES;
- if (!GetMemoryType(bits, properties, &type_index))
- PanicAlert("Unable to find memory type for %x:%x", bits, properties);
-
- return type_index;
+ return std::nullopt;
}
u32 VulkanContext::GetUploadMemoryType(u32 bits, bool* is_coherent)
{
- // Try for coherent memory first.
- VkMemoryPropertyFlags flags =
+ static constexpr VkMemoryPropertyFlags COHERENT_FLAGS =
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
- u32 type_index;
- if (!GetMemoryType(bits, flags, &type_index))
- {
- WARN_LOG(
- VIDEO,
- "Vulkan: Failed to find a coherent memory type for uploads, this will affect performance.");
+ // Try for coherent memory. Some drivers (looking at you, Adreno) have the cached type before the
+ // uncached type, so use a strict check first.
+ std::optional<u32> type_index = GetMemoryType(bits, COHERENT_FLAGS, true, is_coherent);
+ if (type_index)
+ return type_index.value();
- // Try non-coherent memory.
- flags &= ~VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
- if (!GetMemoryType(bits, flags, &type_index))
- {
- // We shouldn't have any memory types that aren't host-visible.
- PanicAlert("Unable to get memory type for upload.");
- type_index = 0;
- }
+ // Try for coherent memory, with any other bits set.
+ type_index = GetMemoryType(bits, COHERENT_FLAGS, false, is_coherent);
+ if (type_index)
+ {
+ WARN_LOG(VIDEO,
+ "Strict check for upload memory properties failed, this may affect performance");
+ return type_index.value();
}
- if (is_coherent)
- *is_coherent = ((flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0);
+ // Fall back to non-coherent memory.
+ WARN_LOG(
+ VIDEO,
+ "Vulkan: Failed to find a coherent memory type for uploads, this will affect performance.");
+ type_index = GetMemoryType(bits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, false, is_coherent);
+ if (type_index)
+ return type_index.value();
- return type_index;
+ // Shouldn't happen, there should be at least one host-visible heap.
+ PanicAlert("Unable to get memory type for upload.");
+ return 0;
}
-u32 VulkanContext::GetReadbackMemoryType(u32 bits, bool* is_coherent, bool* is_cached)
+u32 VulkanContext::GetReadbackMemoryType(u32 bits, bool* is_coherent)
{
- // Try for cached and coherent memory first.
- VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
- VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
- VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
-
- u32 type_index;
- if (!GetMemoryType(bits, flags, &type_index))
- {
- // For readbacks, caching is more important than coherency.
- flags &= ~VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
- if (!GetMemoryType(bits, flags, &type_index))
- {
- WARN_LOG(VIDEO, "Vulkan: Failed to find a cached memory type for readbacks, this will affect "
- "performance.");
-
- // Remove the cached bit as well.
- flags &= ~VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
- if (!GetMemoryType(bits, flags, &type_index))
- {
- // We shouldn't have any memory types that aren't host-visible.
- PanicAlert("Unable to get memory type for upload.");
- type_index = 0;
- }
- }
- }
-
- if (is_coherent)
- *is_coherent = ((flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0);
- if (is_cached)
- *is_cached = ((flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0);
-
- return type_index;
+ std::optional<u32> type_index;
+
+ // Optimal config uses cached+coherent.
+ type_index =
+ GetMemoryType(bits,
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
+ VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+ true, is_coherent);
+ if (type_index)
+ return type_index.value();
+
+ // Otherwise, prefer cached over coherent if we must choose one.
+ type_index =
+ GetMemoryType(bits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
+ false, is_coherent);
+ if (type_index)
+ return type_index.value();
+
+ WARN_LOG(VIDEO, "Vulkan: Failed to find a cached memory type for readbacks, this will affect "
+ "performance.");
+ type_index = GetMemoryType(bits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, false, is_coherent);
+ *is_coherent = false;
+ if (type_index)
+ return type_index.value();
+
+ // We should have at least one host visible memory type...
+ PanicAlert("Unable to get memory type for upload.");
+ return 0;
}
void VulkanContext::InitDriverDetails()