vkd3d: Add new functions to create and destroy resources.
Signed-off-by: Philip Rebohle <philip.rebohle@tu-dortmund.de>
This commit is contained in:
parent
fee47ef695
commit
ba632148d7
|
@ -3181,6 +3181,347 @@ static HRESULT d3d12_resource_init(struct d3d12_resource *resource, struct d3d12
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static void d3d12_resource_destroy_2(struct d3d12_resource *resource, struct d3d12_device *device)
|
||||
{
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
||||
|
||||
vkd3d_view_map_destroy(&resource->view_map, resource->device);
|
||||
|
||||
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
|
||||
vkd3d_descriptor_debug_unregister_cookie(resource->cookie);
|
||||
#endif
|
||||
|
||||
if (resource->flags & VKD3D_RESOURCE_EXTERNAL)
|
||||
return;
|
||||
|
||||
if (resource->flags & VKD3D_RESOURCE_SPARSE)
|
||||
{
|
||||
VK_CALL(vkFreeMemory(device->vk_device, resource->sparse.vk_metadata_memory, NULL));
|
||||
|
||||
vkd3d_free(resource->sparse.tiles);
|
||||
vkd3d_free(resource->sparse.tilings);
|
||||
|
||||
if (resource->res.va)
|
||||
{
|
||||
vkd3d_va_map_remove(&device->memory_allocator.va_map, &resource->res);
|
||||
|
||||
if (!device->device_info.buffer_device_address_features.bufferDeviceAddress)
|
||||
vkd3d_va_map_free_fake_va(&device->memory_allocator.va_map, resource->res.va, resource->res.size);
|
||||
}
|
||||
}
|
||||
|
||||
if (d3d12_resource_is_texture(resource))
|
||||
VK_CALL(vkDestroyImage(device->vk_device, resource->vk_image, NULL));
|
||||
else if (resource->flags & VKD3D_RESOURCE_SPARSE)
|
||||
VK_CALL(vkDestroyBuffer(device->vk_device, resource->vk_buffer, NULL));
|
||||
|
||||
if ((resource->flags & VKD3D_RESOURCE_ALLOCATION) && resource->mem.vk_memory)
|
||||
vkd3d_free_memory_2(device, &device->memory_allocator, &resource->mem);
|
||||
|
||||
vkd3d_private_store_destroy(&resource->private_store);
|
||||
d3d12_device_release(resource->device);
|
||||
vkd3d_free(resource);
|
||||
}
|
||||
|
||||
static HRESULT d3d12_resource_create_vk_resource(struct d3d12_resource *resource, struct d3d12_device *device)
|
||||
{
|
||||
const D3D12_HEAP_PROPERTIES *heap_properties;
|
||||
HRESULT hr;
|
||||
|
||||
heap_properties = resource->flags & VKD3D_RESOURCE_SPARSE
|
||||
? NULL : &resource->heap_properties;
|
||||
|
||||
if (resource->desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
|
||||
{
|
||||
if (FAILED(hr = vkd3d_create_buffer(device, heap_properties,
|
||||
D3D12_HEAP_FLAG_NONE, &resource->desc, &resource->vk_buffer)))
|
||||
return hr;
|
||||
}
|
||||
else
|
||||
{
|
||||
resource->initial_layout_transition = 1;
|
||||
|
||||
if (!resource->desc.MipLevels)
|
||||
resource->desc.MipLevels = max_miplevel_count(&resource->desc);
|
||||
|
||||
if (FAILED(hr = vkd3d_create_image(device, heap_properties,
|
||||
D3D12_HEAP_FLAG_NONE, &resource->desc, resource, &resource->vk_image)))
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT d3d12_resource_create_2(struct d3d12_device *device, uint32_t flags,
|
||||
const D3D12_RESOURCE_DESC *desc, const D3D12_HEAP_PROPERTIES *heap_properties,
|
||||
D3D12_RESOURCE_STATES initial_state, const D3D12_CLEAR_VALUE *optimized_clear_value,
|
||||
struct d3d12_resource **resource)
|
||||
{
|
||||
struct d3d12_resource *object;
|
||||
HRESULT hr;
|
||||
|
||||
if (FAILED(hr = d3d12_resource_validate_create_info(desc,
|
||||
heap_properties, initial_state, optimized_clear_value, device)))
|
||||
return hr;
|
||||
|
||||
if (!(object = vkd3d_malloc(sizeof(*object))))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
memset(object, 0, sizeof(*object));
|
||||
object->ID3D12Resource_iface.lpVtbl = &d3d12_resource_vtbl;
|
||||
|
||||
if (FAILED(hr = vkd3d_view_map_init(&object->view_map)))
|
||||
{
|
||||
vkd3d_free(object);
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (FAILED(hr = vkd3d_private_store_init(&object->private_store)))
|
||||
{
|
||||
vkd3d_view_map_destroy(&object->view_map, device);
|
||||
vkd3d_free(object);
|
||||
return hr;
|
||||
}
|
||||
|
||||
object->refcount = 1;
|
||||
object->internal_refcount = 1;
|
||||
object->desc = *desc;
|
||||
object->device = device;
|
||||
object->flags = flags;
|
||||
object->cookie = InterlockedIncrement64(&global_cookie_counter);
|
||||
object->format = vkd3d_format_from_d3d12_resource_desc(device, desc, 0);
|
||||
|
||||
if (heap_properties)
|
||||
object->heap_properties = *heap_properties;
|
||||
|
||||
d3d12_device_add_ref(device);
|
||||
|
||||
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
|
||||
vkd3d_descriptor_debug_register_resource_cookie(object->cookie, desc);
|
||||
#endif
|
||||
|
||||
*resource = object;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT d3d12_resource_create_committed_2(struct d3d12_device *device, const D3D12_RESOURCE_DESC *desc,
|
||||
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, D3D12_RESOURCE_STATES initial_state,
|
||||
const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource)
|
||||
{
|
||||
struct d3d12_resource *object;
|
||||
HRESULT hr;
|
||||
|
||||
if (FAILED(hr = d3d12_resource_create_2(device, VKD3D_RESOURCE_COMMITTED | VKD3D_RESOURCE_ALLOCATION,
|
||||
desc, heap_properties, initial_state, optimized_clear_value, &object)))
|
||||
return hr;
|
||||
|
||||
if (d3d12_resource_is_texture(object))
|
||||
{
|
||||
struct vkd3d_allocate_resource_memory_info allocate_info;
|
||||
|
||||
if (FAILED(hr = d3d12_resource_create_vk_resource(object, device)))
|
||||
goto fail;
|
||||
|
||||
memset(&allocate_info, 0, sizeof(allocate_info));
|
||||
allocate_info.heap_properties = *heap_properties;
|
||||
allocate_info.heap_flags = heap_flags;
|
||||
|
||||
if (desc->Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL))
|
||||
allocate_info.heap_flags |= D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES;
|
||||
else
|
||||
allocate_info.heap_flags |= D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES;
|
||||
|
||||
allocate_info.vk_image = object->vk_image;
|
||||
|
||||
if (FAILED(hr = vkd3d_allocate_resource_memory_2(device,
|
||||
&device->memory_allocator, &allocate_info, &object->mem)))
|
||||
goto fail;
|
||||
|
||||
object->heap_offset = object->mem.offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct vkd3d_allocate_heap_memory_info allocate_info;
|
||||
|
||||
memset(&allocate_info, 0, sizeof(allocate_info));
|
||||
allocate_info.heap_desc.Properties = *heap_properties;
|
||||
allocate_info.heap_desc.Alignment = desc->Alignment ? desc->Alignment : D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
|
||||
allocate_info.heap_desc.SizeInBytes = align(desc->Width, allocate_info.heap_desc.Alignment);
|
||||
allocate_info.heap_desc.Flags = heap_flags | D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
|
||||
|
||||
if (FAILED(hr = vkd3d_allocate_heap_memory_2(device,
|
||||
&device->memory_allocator, &allocate_info, &object->mem)))
|
||||
goto fail;
|
||||
|
||||
object->vk_buffer = object->mem.resource.vk_buffer;
|
||||
object->gpu_address = object->mem.resource.va;
|
||||
object->heap_offset = object->mem.offset;
|
||||
}
|
||||
|
||||
*resource = object;
|
||||
return S_OK;
|
||||
|
||||
fail:
|
||||
d3d12_resource_destroy_2(object, device);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT d3d12_resource_bind_image_memory_2(struct d3d12_resource *resource, struct d3d12_device *device)
|
||||
{
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
||||
VkMemoryRequirements memory_requirements;
|
||||
VkResult vr;
|
||||
HRESULT hr;
|
||||
|
||||
VK_CALL(vkGetImageMemoryRequirements(device->vk_device, resource->vk_image, &memory_requirements));
|
||||
|
||||
/* TODO implement sparse fallback instead to enforce alignment */
|
||||
if (resource->heap_offset & (memory_requirements.alignment - 1))
|
||||
{
|
||||
struct vkd3d_allocate_heap_memory_info allocate_info;
|
||||
|
||||
FIXME("Cannot allocate image %p with alignment %#"PRIx64" at heap offset %#"PRIx64", allocating device memory.\n",
|
||||
resource->vk_image, memory_requirements.alignment, resource->heap_offset);
|
||||
|
||||
memset(&allocate_info, 0, sizeof(allocate_info));
|
||||
allocate_info.heap_desc.Properties = resource->heap_2->desc.Properties;
|
||||
allocate_info.heap_desc.SizeInBytes = memory_requirements.size;
|
||||
allocate_info.heap_desc.Alignment = memory_requirements.alignment;
|
||||
allocate_info.heap_desc.Flags = resource->heap_2->desc.Flags | D3D12_HEAP_FLAG_DENY_BUFFERS;
|
||||
|
||||
if (FAILED(hr = vkd3d_allocate_heap_memory_2(device,
|
||||
&device->memory_allocator, &allocate_info, &resource->mem)))
|
||||
return hr;
|
||||
|
||||
resource->flags |= VKD3D_RESOURCE_ALLOCATION;
|
||||
resource->heap_offset = resource->mem.offset;
|
||||
}
|
||||
|
||||
if ((vr = VK_CALL(vkBindImageMemory(device->vk_device, resource->vk_image,
|
||||
resource->mem.vk_memory, resource->heap_offset)) < 0))
|
||||
{
|
||||
ERR("Failed to bind image memory, vr %d.\n", vr);
|
||||
return hresult_from_vk_result(vr);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT d3d12_resource_validate_heap(const D3D12_RESOURCE_DESC *resource_desc, struct d3d12_heap_2 *heap)
|
||||
{
|
||||
D3D12_HEAP_FLAGS deny_flag;
|
||||
|
||||
if (resource_desc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
|
||||
deny_flag = D3D12_HEAP_FLAG_DENY_BUFFERS;
|
||||
else if (resource_desc->Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL))
|
||||
deny_flag = D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES;
|
||||
else
|
||||
deny_flag = D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES;
|
||||
|
||||
if (heap->desc.Flags & deny_flag)
|
||||
{
|
||||
WARN("Cannot create placed resource on heap that denies resource category %#x.\n", deny_flag);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if ((heap->desc.Flags & D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER) &&
|
||||
!(resource_desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER))
|
||||
{
|
||||
ERR("Must declare ALLOW_CROSS_ADAPTER resource flag when heap is cross adapter.\n");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT d3d12_resource_create_placed_2(struct d3d12_device *device, const D3D12_RESOURCE_DESC *desc,
|
||||
struct d3d12_heap_2 *heap, uint64_t heap_offset, D3D12_RESOURCE_STATES initial_state,
|
||||
const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource)
|
||||
{
|
||||
struct d3d12_resource *object;
|
||||
HRESULT hr;
|
||||
|
||||
if (FAILED(hr = d3d12_resource_validate_heap(desc, heap)))
|
||||
return hr;
|
||||
|
||||
if (FAILED(hr = d3d12_resource_create_2(device, VKD3D_RESOURCE_PLACED,
|
||||
desc, &heap->desc.Properties, initial_state, optimized_clear_value, &object)))
|
||||
return hr;
|
||||
|
||||
object->heap_2 = heap;
|
||||
/* The exact allocation size is not important here since the
|
||||
* resource does not own the allocation, so just set it to 0. */
|
||||
vkd3d_memory_allocation_slice(&object->mem, &heap->allocation, heap_offset, 0);
|
||||
object->heap_offset = object->mem.offset;
|
||||
|
||||
if (d3d12_resource_is_texture(object))
|
||||
{
|
||||
if (FAILED(hr = d3d12_resource_create_vk_resource(object, device)))
|
||||
goto fail;
|
||||
|
||||
if (FAILED(hr = d3d12_resource_bind_image_memory_2(object, device)))
|
||||
goto fail;
|
||||
}
|
||||
else
|
||||
{
|
||||
object->vk_buffer = object->mem.resource.vk_buffer;
|
||||
object->gpu_address = object->mem.resource.va;
|
||||
}
|
||||
|
||||
*resource = object;
|
||||
return S_OK;
|
||||
|
||||
fail:
|
||||
d3d12_resource_destroy_2(object, device);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT d3d12_resource_create_reserved_2(struct d3d12_device *device,
|
||||
const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
|
||||
const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource)
|
||||
{
|
||||
struct d3d12_resource *object;
|
||||
HRESULT hr;
|
||||
|
||||
if (FAILED(hr = d3d12_resource_create_2(device, VKD3D_RESOURCE_SPARSE,
|
||||
desc, NULL, initial_state, optimized_clear_value, &object)))
|
||||
return hr;
|
||||
|
||||
if (FAILED(hr = d3d12_resource_create_vk_resource(object, device)))
|
||||
goto fail;
|
||||
|
||||
if (FAILED(hr = d3d12_resource_init_sparse_info(object, device, &object->sparse)))
|
||||
goto fail;
|
||||
|
||||
if (d3d12_resource_is_buffer(object))
|
||||
{
|
||||
object->res.vk_buffer = object->vk_buffer;
|
||||
object->res.cookie = object->cookie;
|
||||
object->res.size = object->desc.Width;
|
||||
|
||||
if (device->device_info.buffer_device_address_features.bufferDeviceAddress)
|
||||
object->res.va = vkd3d_get_buffer_device_address(device, object->vk_buffer);
|
||||
else
|
||||
object->res.va = vkd3d_va_map_alloc_fake_va(&device->memory_allocator.va_map, object->res.size);
|
||||
|
||||
if (!object->res.va)
|
||||
{
|
||||
ERR("Failed to get VA for sparse resource.\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
object->gpu_address = object->res.va;
|
||||
vkd3d_va_map_insert(&device->memory_allocator.va_map, &object->res);
|
||||
}
|
||||
|
||||
*resource = object;
|
||||
return S_OK;
|
||||
|
||||
fail:
|
||||
d3d12_resource_destroy_2(object, device);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT d3d12_resource_create(struct d3d12_device *device,
|
||||
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
|
||||
const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
|
||||
|
|
|
@ -632,11 +632,17 @@ HRESULT d3d12_heap_create_2(struct d3d12_device *device, const D3D12_HEAP_DESC *
|
|||
void *host_address, struct d3d12_heap_2 **heap);
|
||||
struct d3d12_heap_2 *unsafe_impl_from_ID3D12Heap_2(ID3D12Heap *iface);
|
||||
|
||||
#define VKD3D_RESOURCE_EXTERNAL 0x00000004
|
||||
#define VKD3D_RESOURCE_DEDICATED_HEAP 0x00000008
|
||||
#define VKD3D_RESOURCE_LINEAR_TILING 0x00000010
|
||||
#define VKD3D_RESOURCE_PLACED_BUFFER 0x00000020
|
||||
#define VKD3D_RESOURCE_SPARSE 0x00000040
|
||||
enum vkd3d_resource_flag
|
||||
{
|
||||
VKD3D_RESOURCE_COMMITTED = (1u << 0),
|
||||
VKD3D_RESOURCE_PLACED = (1u << 1),
|
||||
VKD3D_RESOURCE_SPARSE = (1u << 2),
|
||||
VKD3D_RESOURCE_ALLOCATION = (1u << 3),
|
||||
VKD3D_RESOURCE_LINEAR_TILING = (1u << 4),
|
||||
VKD3D_RESOURCE_EXTERNAL = (1u << 5),
|
||||
VKD3D_RESOURCE_DEDICATED_HEAP = (1u << 6),
|
||||
VKD3D_RESOURCE_PLACED_BUFFER = (1u << 7),
|
||||
};
|
||||
|
||||
struct d3d12_sparse_image_region
|
||||
{
|
||||
|
@ -697,8 +703,10 @@ struct d3d12_resource
|
|||
uint64_t cookie;
|
||||
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
|
||||
D3D12_HEAP_PROPERTIES heap_properties;
|
||||
D3D12_GPU_VIRTUAL_ADDRESS gpu_address;
|
||||
struct vkd3d_memory_allocation mem;
|
||||
struct vkd3d_unique_resource res;
|
||||
union
|
||||
{
|
||||
VkBuffer vk_buffer;
|
||||
|
@ -706,6 +714,7 @@ struct d3d12_resource
|
|||
};
|
||||
|
||||
struct d3d12_heap *heap;
|
||||
struct d3d12_heap_2 *heap_2;
|
||||
uint64_t heap_offset;
|
||||
|
||||
uint32_t flags;
|
||||
|
@ -755,6 +764,15 @@ HRESULT d3d12_placed_resource_create(struct d3d12_device *device, struct d3d12_h
|
|||
HRESULT d3d12_reserved_resource_create(struct d3d12_device *device,
|
||||
const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
|
||||
const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource);
|
||||
HRESULT d3d12_resource_create_committed_2(struct d3d12_device *device, const D3D12_RESOURCE_DESC *desc,
|
||||
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, D3D12_RESOURCE_STATES initial_state,
|
||||
const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource);
|
||||
HRESULT d3d12_resource_create_placed_2(struct d3d12_device *device, const D3D12_RESOURCE_DESC *desc,
|
||||
struct d3d12_heap_2 *heap, uint64_t heap_offset, D3D12_RESOURCE_STATES initial_state,
|
||||
const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource);
|
||||
HRESULT d3d12_resource_create_reserved_2(struct d3d12_device *device,
|
||||
const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
|
||||
const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource);
|
||||
struct d3d12_resource *unsafe_impl_from_ID3D12Resource(ID3D12Resource *iface);
|
||||
|
||||
HRESULT vkd3d_allocate_buffer_memory(struct d3d12_device *device, VkBuffer vk_buffer, void *host_memory,
|
||||
|
|
Loading…
Reference in New Issue