vkd3d: Allow CreateHeap to fail in certain fallback situations.

If we deduce that fallback heap allocation is impossible, we will accept
this, and defer allocation to CreatePlacedResource() instead where we make a committed resource.
This breaks aliasing, but in practice, this situation will only arise for render
targets, and it's not like we have a choice in the matter here on NV :\

Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
Hans-Kristian Arntzen 2021-10-04 18:05:07 +02:00
parent 7ee8eac818
commit 26dc9e7da5
2 changed files with 46 additions and 1 deletions

View File

@ -1396,10 +1396,31 @@ HRESULT vkd3d_allocate_memory(struct d3d12_device *device, struct vkd3d_memory_a
return hr;
}
static bool vkd3d_heap_allocation_accept_deferred_resource_placements(struct d3d12_device *device,
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags)
{
uint32_t type_mask;
/* Normally, if a memory allocation fails, we consider it an error, but there are some exceptions
* where we can defer memory allocation, like CreateHeap where fallback system memory type is not available.
* In this case, we will defer memory allocation until CreatePlacedResource() time, and we should
* accept that a memory allocation failed. */
/* Only accept deferrals for DEFAULT / CPU_NOT_AVAILABLE heaps.
* If we're going for host memory, we have nowhere left to fall back to either way. */
if (is_cpu_accessible_heap(heap_properties))
return false;
type_mask = vkd3d_select_memory_types(device, heap_properties, heap_flags);
return device->memory_properties.memoryHeapCount > 1 &&
!vkd3d_memory_info_type_mask_covers_multiple_memory_heaps(&device->memory_properties, type_mask);
}
HRESULT vkd3d_allocate_heap_memory(struct d3d12_device *device, struct vkd3d_memory_allocator *allocator,
const struct vkd3d_allocate_heap_memory_info *info, struct vkd3d_memory_allocation *allocation)
{
struct vkd3d_allocate_memory_info alloc_info;
HRESULT hr;
memset(&alloc_info, 0, sizeof(alloc_info));
alloc_info.memory_requirements.memoryTypeBits = ~0u;
@ -1412,7 +1433,17 @@ HRESULT vkd3d_allocate_heap_memory(struct d3d12_device *device, struct vkd3d_mem
if (!(info->heap_desc.Flags & D3D12_HEAP_FLAG_DENY_BUFFERS))
alloc_info.flags |= VKD3D_ALLOCATION_FLAG_GLOBAL_BUFFER;
return vkd3d_allocate_memory(device, allocator, &alloc_info, allocation);
hr = vkd3d_allocate_memory(device, allocator, &alloc_info, allocation);
if (hr == E_OUTOFMEMORY && vkd3d_heap_allocation_accept_deferred_resource_placements(device,
&info->heap_desc.Properties, info->heap_desc.Flags))
{
/* It's okay and sometimes expected that we fail here.
* Defer allocation until CreatePlacedResource(). */
memset(allocation, 0, sizeof(*allocation));
hr = S_OK;
}
return hr;
}
HRESULT vkd3d_allocate_buffer_memory(struct d3d12_device *device, VkBuffer vk_buffer,

View File

@ -2630,6 +2630,20 @@ HRESULT d3d12_resource_create_placed(struct d3d12_device *device, const D3D12_RE
if (FAILED(hr = d3d12_resource_validate_heap(desc, heap)))
return hr;
if (heap->allocation.device_allocation.vk_memory == VK_NULL_HANDLE)
{
WARN("Placing resource on heap with no memory backing it. Falling back to committed resource.\n");
if (FAILED(hr = d3d12_resource_create_committed(device, desc, &heap->desc.Properties,
heap->desc.Flags & ~(D3D12_HEAP_FLAG_DENY_BUFFERS |
D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES |
D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES),
initial_state, optimized_clear_value, resource)))
{
ERR("Failed to create fallback committed resource.\n");
}
return hr;
}
if (FAILED(hr = d3d12_resource_create(device, VKD3D_RESOURCE_PLACED, desc,
&heap->desc.Properties, heap->desc.Flags, initial_state, optimized_clear_value, &object)))
return hr;