vkd3d: Setup resizable bar budget.

Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
Hans-Kristian Arntzen 2021-07-14 15:57:14 +02:00
parent cec741706d
commit 710fa98918
2 changed files with 61 additions and 1 deletions

View File

@ -201,7 +201,12 @@ static HRESULT vkd3d_try_allocate_device_memory(struct d3d12_device *device,
WARN("Attempting to allocate from memory type %u, but exceeding fixed budget: %"PRIu64" + %"PRIu64" > %"PRIu64".\n",
type_index, *type_current, size, *type_budget);
pthread_mutex_unlock(&memory_info->budget_lock);
continue;
/* If we're out of DEVICE budget, don't try other types. */
if (type_flags & optional_flags)
return E_OUTOFMEMORY;
else
continue;
}
}

View File

@ -5983,6 +5983,60 @@ static uint32_t vkd3d_memory_info_find_global_mask(const struct vkd3d_memory_top
return ~mask;
}
static void vkd3d_memory_info_init_budgets(struct vkd3d_memory_info *info,
const struct vkd3d_memory_topology *topology,
struct d3d12_device *device)
{
bool heap_index_needs_budget;
VkMemoryPropertyFlags flags;
uint32_t heap_index;
uint32_t i;
info->budget_sensitive_mask = 0;
/* Nothing to do if we don't have separate heaps. */
if (topology->device_local_heap_count == 0 || topology->host_only_heap_count == 0)
return;
if (!topology->exists_device_only_type || !topology->exists_host_only_type)
return;
for (i = 0; i < device->memory_properties.memoryTypeCount; i++)
{
const VkMemoryPropertyFlags pinned_mask = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
flags = device->memory_properties.memoryTypes[i].propertyFlags;
heap_index = device->memory_properties.memoryTypes[i].heapIndex;
/* Work around a driver workaround on NV drivers which targets certain
* older DXVK versions (use of DXVK DXGI is likely what impacts us here),
* since we don't see this behavior in native builds.
* Even with resizable BAR, we might observe two different heaps,
* with very slightly different heap sizes.
* It's straight forward to be universally robust against these kinds of scenarios,
* so just go for that.
* If we're within 75% of the actual VRAM size, assume we've hit this scenario.
* This should exclude small BAR from explicit budget, since that's just 256 MB. */
heap_index_needs_budget =
(device->memory_properties.memoryHeaps[heap_index].size >
3 * device->memory_properties.memoryHeaps[topology->largest_device_local_heap_index].size / 4) &&
(device->memory_properties.memoryHeaps[heap_index].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT);
if ((flags & pinned_mask) == pinned_mask && heap_index_needs_budget)
{
/* Limit this type. This limit is a pure heuristic and we might need further tuning here.
* If there's a separate heap type for PCI-e BAR,
* don't bother limiting it since the size is already going to be tiny.
* The driver will limit us naturally. */
info->budget_sensitive_mask |= 1u << i;
info->type_budget[i] = device->memory_properties.memoryHeaps[heap_index].size / 16;
info->type_current[i] = 0;
}
}
INFO("Applying resizable BAR budget to memory types: 0x%x.\n", info->budget_sensitive_mask);
}
void vkd3d_memory_info_cleanup(struct vkd3d_memory_info *info,
struct d3d12_device *device)
{
@ -6010,6 +6064,7 @@ HRESULT vkd3d_memory_info_init(struct vkd3d_memory_info *info,
vkd3d_memory_info_get_topology(&topology, device);
info->global_mask = vkd3d_memory_info_find_global_mask(&topology, device);
vkd3d_memory_info_init_budgets(info, &topology, device);
if (pthread_mutex_init(&info->budget_lock, NULL) != 0)
return E_OUTOFMEMORY;