libs/vkd3d: Allocate GPU virtual addresses for resources.

Direct3D 12 resources, buffers in particular, are bound to the pipeline
by their GPU virtual address. In Vulkan, these addresses are not visible
to the application. We previously handled this by returning the VkBuffer
handle as virtual address, but this can't work when the application
binds anything other than the resource's base GPU VA. Instead, we
allocate ranges of GPU address space and associate resources with it.

This uses the (naive) approach of simply allocating subsequent ranges,
and never reclaiming them. Eventually we'll have to revisit that.
This commit is contained in:
Henri Verbeet
2017-07-25 01:56:16 +02:00
parent 1acd3d44b1
commit 605a02274e
4 changed files with 124 additions and 13 deletions

View File

@@ -276,10 +276,20 @@ static HRESULT vkd3d_allocate_buffer_memory(struct d3d12_resource *resource, str
if (FAILED(hr = vkd3d_allocate_device_memory(device, heap_properties, heap_flags,
&memory_requirements, &resource->vk_memory)))
return hr;
if (!(resource->gpu_address = vkd3d_gpu_va_allocator_allocate(&device->gpu_va_allocator,
memory_requirements.size, resource)))
{
ERR("Failed to allocate GPU VA.\n");
VK_CALL(vkFreeMemory(device->vk_device, resource->vk_memory, NULL));
resource->vk_memory = VK_NULL_HANDLE;
return E_OUTOFMEMORY;
}
if ((vr = VK_CALL(vkBindBufferMemory(device->vk_device, resource->u.vk_buffer, resource->vk_memory, 0))) < 0)
{
WARN("Failed to bind memory, vr %d.\n", vr);
vkd3d_gpu_va_allocator_free(&device->gpu_va_allocator, resource->gpu_address);
resource->gpu_address = 0;
VK_CALL(vkFreeMemory(device->vk_device, resource->vk_memory, NULL));
resource->vk_memory = VK_NULL_HANDLE;
return hresult_from_vk_result(vr);
@@ -322,6 +332,9 @@ static void d3d12_resource_destroy(struct d3d12_resource *resource, struct d3d12
if (resource->flags & VKD3D_RESOURCE_EXTERNAL)
return;
if (resource->gpu_address)
vkd3d_gpu_va_allocator_free(&device->gpu_va_allocator, resource->gpu_address);
if (d3d12_resource_is_buffer(resource))
VK_CALL(vkDestroyBuffer(device->vk_device, resource->u.vk_buffer, NULL));
else
@@ -531,13 +544,7 @@ static D3D12_GPU_VIRTUAL_ADDRESS STDMETHODCALLTYPE d3d12_resource_GetGPUVirtualA
TRACE("iface %p.\n", iface);
if (!d3d12_resource_is_buffer(resource))
{
WARN("GPU virtual address for textures is always 0.\n");
return 0;
}
return resource->u.gpu_address;
return resource->gpu_address;
}
static HRESULT STDMETHODCALLTYPE d3d12_resource_WriteToSubresource(ID3D12Resource *iface,
@@ -649,6 +656,7 @@ static HRESULT d3d12_committed_resource_init(struct d3d12_resource *resource, st
if (optimized_clear_value)
FIXME("Ignoring optimized clear value.\n");
resource->gpu_address = 0;
resource->flags = 0;
switch (desc->Dimension)