From: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- libs/vkd3d/device.c | 18 ++++-- libs/vkd3d/resource.c | 129 ++++++++++++++++++++++++++++++------- libs/vkd3d/vkd3d_private.h | 3 + 3 files changed, 119 insertions(+), 31 deletions(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index ddec0f7cae67..e83b7fa9258c 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -2780,14 +2780,20 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePlacedResource(ID3D12Device
static HRESULT STDMETHODCALLTYPE d3d12_device_CreateReservedResource(ID3D12Device *iface, const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state, - const D3D12_CLEAR_VALUE *optimized_clear_value, - REFIID riid, void **resource) + const D3D12_CLEAR_VALUE *optimized_clear_value, REFIID iid, void **resource) { - FIXME("iface %p, desc %p, initial_state %#x, optimized_clear_value %p, " - "riid %s, resource %p stub!\n", - iface, desc, initial_state, optimized_clear_value, debugstr_guid(riid), resource); + struct d3d12_device *device = impl_from_ID3D12Device(iface); + struct d3d12_resource *object; + HRESULT hr;
- return E_NOTIMPL; + TRACE("iface %p, desc %p, initial_state %#x, optimized_clear_value %p, iid %s, resource %p.\n", + iface, desc, initial_state, optimized_clear_value, debugstr_guid(iid), resource); + + if (FAILED(hr = d3d12_reserved_resource_create(device, + desc, initial_state, optimized_clear_value, &object))) + return hr; + + return return_interface(&object->ID3D12Resource_iface, &IID_ID3D12Resource, iid, resource); }
static HRESULT STDMETHODCALLTYPE d3d12_device_CreateSharedHandle(ID3D12Device *iface, diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index c3c92386da08..30ef9018d775 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -21,6 +21,8 @@ #define VKD3D_NULL_BUFFER_SIZE 16 #define VKD3D_NULL_VIEW_FORMAT DXGI_FORMAT_R8G8B8A8_UNORM
+#define VKD3D_HEAP_TYPE_INVALID ((D3D12_HEAP_TYPE)~0u) + static unsigned int vkd3d_select_memory_type(struct d3d12_device *device, uint32_t memory_type_mask, const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags) { @@ -497,14 +499,25 @@ HRESULT vkd3d_create_buffer(struct d3d12_device *device, const D3D12_RESOURCE_DESC *desc, VkBuffer *vk_buffer) { const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; + const bool sparse_resource = !heap_properties; VkBufferCreateInfo buffer_info; + D3D12_HEAP_TYPE heap_type; VkResult vr;
+ heap_type = heap_properties ? heap_properties->Type : D3D12_HEAP_TYPE_DEFAULT; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; buffer_info.pNext = NULL; buffer_info.flags = 0; buffer_info.size = desc->Width;
+ if (sparse_resource) + { + buffer_info.flags |= VK_BUFFER_CREATE_SPARSE_BINDING_BIT; + if (device->vk_info.sparse_properties.residencyNonResidentStrict) + buffer_info.flags |= VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT; + } + buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT @@ -512,16 +525,15 @@ HRESULT vkd3d_create_buffer(struct d3d12_device *device, | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
- if (heap_properties->Type == D3D12_HEAP_TYPE_DEFAULT - && device->vk_info.EXT_transform_feedback) + if (heap_type == D3D12_HEAP_TYPE_DEFAULT && device->vk_info.EXT_transform_feedback) { buffer_info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT; }
- if (heap_properties->Type == D3D12_HEAP_TYPE_UPLOAD) + if (heap_type == D3D12_HEAP_TYPE_UPLOAD) buffer_info.usage &= ~VK_BUFFER_USAGE_TRANSFER_DST_BIT; - else if (heap_properties->Type == D3D12_HEAP_TYPE_READBACK) + else if (heap_type == D3D12_HEAP_TYPE_READBACK) buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS) @@ -573,6 +585,7 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device, const D3D12_RESOURCE_DESC *desc, VkImage *vk_image) { const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; + const bool sparse_resource = !heap_properties; const struct vkd3d_format *format; VkImageCreateInfo image_info; VkResult vr; @@ -595,6 +608,13 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device, if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D) image_info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR;
+ if (sparse_resource) + { + image_info.flags |= VK_IMAGE_CREATE_SPARSE_BINDING_BIT; + if (device->vk_info.sparse_properties.residencyNonResidentStrict) + image_info.flags |= VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT; + } + image_info.imageType = vk_image_type_from_d3d12_resource_dimension(desc->Dimension); image_info.format = format->vk_format; image_info.extent.width = desc->Width; @@ -614,7 +634,17 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device, image_info.mipLevels = min(desc->MipLevels, max_miplevel_count(desc)); image_info.samples = vk_samples_from_dxgi_sample_desc(&desc->SampleDesc);
- if (desc->Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN) + if (sparse_resource) + { + if (desc->Layout != D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE) + { + WARN("D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE must be used for reserved texture.\n"); + return E_INVALIDARG; + } + + image_info.tiling = VK_IMAGE_TILING_OPTIMAL; + } + else if (desc->Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN) { image_info.tiling = VK_IMAGE_TILING_OPTIMAL; } @@ -652,7 +682,7 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device, image_info.pQueueFamilyIndices = NULL; }
- image_info.initialLayout = is_cpu_accessible_heap(heap_properties) ? + image_info.initialLayout = heap_properties && is_cpu_accessible_heap(heap_properties) ? VK_IMAGE_LAYOUT_PREINITIALIZED : VK_IMAGE_LAYOUT_UNDEFINED;
if ((vr = VK_CALL(vkCreateImage(device->vk_device, &image_info, NULL, vk_image))) < 0) @@ -1155,6 +1185,12 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_GetHeapProperties(ID3D12Resource TRACE("iface %p, heap_properties %p, flags %p.\n", iface, heap_properties, flags);
+ if (resource->heap_properties.Type == VKD3D_HEAP_TYPE_INVALID) + { + WARN("Cannot get heap properties for reserved resources.\n"); + return E_INVALIDARG; + } + if (heap_properties) *heap_properties = resource->heap_properties; if (flags) @@ -1255,46 +1291,55 @@ HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc) return S_OK; }
-static HRESULT d3d12_resource_init(struct d3d12_resource *resource, 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, - const D3D12_CLEAR_VALUE *optimized_clear_value) +static bool d3d12_resource_validate_heap_properties(const struct d3d12_resource *resource, + const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_RESOURCE_STATES initial_state) { - HRESULT hr; - - resource->ID3D12Resource_iface.lpVtbl = &d3d12_resource_vtbl; - resource->refcount = 1; - resource->internal_refcount = 1; - - resource->desc = *desc; - if (heap_properties->Type == D3D12_HEAP_TYPE_UPLOAD || heap_properties->Type == D3D12_HEAP_TYPE_READBACK) { if (d3d12_resource_is_texture(resource)) { WARN("Textures cannot be created on upload/readback heaps.\n"); - return E_INVALIDARG; + return false; }
- if (desc->Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)) + if (resource->desc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)) { WARN("Render target and unordered access buffers cannot be created on upload/readback heaps.\n"); - return E_INVALIDARG; + return false; } }
if (heap_properties->Type == D3D12_HEAP_TYPE_UPLOAD && initial_state != D3D12_RESOURCE_STATE_GENERIC_READ) { WARN("For D3D12_HEAP_TYPE_UPLOAD the state must be D3D12_RESOURCE_STATE_GENERIC_READ.\n"); - return E_INVALIDARG; + return false; } if (heap_properties->Type == D3D12_HEAP_TYPE_READBACK && initial_state != D3D12_RESOURCE_STATE_COPY_DEST) { WARN("For D3D12_HEAP_TYPE_READBACK the state must be D3D12_RESOURCE_STATE_COPY_DEST.\n"); - return E_INVALIDARG; + return false; }
+ return true; +} + +static HRESULT d3d12_resource_init(struct d3d12_resource *resource, 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, + const D3D12_CLEAR_VALUE *optimized_clear_value) +{ + HRESULT hr; + + resource->ID3D12Resource_iface.lpVtbl = &d3d12_resource_vtbl; + resource->refcount = 1; + resource->internal_refcount = 1; + + resource->desc = *desc; + + if (heap_properties && !d3d12_resource_validate_heap_properties(resource, heap_properties, initial_state)) + return E_INVALIDARG; + if (!is_valid_resource_state(initial_state)) { WARN("Invalid initial resource state %#x.\n", initial_state); @@ -1351,8 +1396,18 @@ static HRESULT d3d12_resource_init(struct d3d12_resource *resource, struct d3d12 resource->map_count = 0; resource->map_ptr = NULL;
- resource->heap_properties = *heap_properties; - resource->heap_flags = heap_flags; + if (heap_properties) + { + resource->heap_properties = *heap_properties; + resource->heap_flags = heap_flags; + } + else + { + memset(&resource->heap_properties, 0, sizeof(resource->heap_properties)); + resource->heap_properties.Type = VKD3D_HEAP_TYPE_INVALID; + resource->heap_flags = 0; + } + resource->initial_state = initial_state;
resource->heap = NULL; @@ -1417,6 +1472,12 @@ HRESULT d3d12_committed_resource_create(struct d3d12_device *device, struct d3d12_resource *object; HRESULT hr;
+ if (!heap_properties) + { + WARN("Heap properties are NULL.\n"); + return E_INVALIDARG; + } + if (FAILED(hr = d3d12_resource_create(device, heap_properties, heap_flags, desc, initial_state, optimized_clear_value, &object))) return hr; @@ -1503,6 +1564,24 @@ HRESULT d3d12_placed_resource_create(struct d3d12_device *device, struct d3d12_h return S_OK; }
+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) +{ + struct d3d12_resource *object; + HRESULT hr; + + if (FAILED(hr = d3d12_resource_create(device, NULL, 0, + desc, initial_state, optimized_clear_value, &object))) + return hr; + + TRACE("Created reserved resource %p.\n", object); + + *resource = object; + + return S_OK; +} + HRESULT vkd3d_create_image_resource(ID3D12Device *device, const struct vkd3d_image_resource_create_info *create_info, ID3D12Resource **resource) { diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 71e05b245230..2d31cacc101e 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -402,6 +402,9 @@ HRESULT d3d12_committed_resource_create(struct d3d12_device *device, HRESULT d3d12_placed_resource_create(struct d3d12_device *device, struct d3d12_heap *heap, UINT64 heap_offset, const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state, const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource) DECLSPEC_HIDDEN; +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) DECLSPEC_HIDDEN; struct d3d12_resource *unsafe_impl_from_ID3D12Resource(ID3D12Resource *iface) DECLSPEC_HIDDEN;
HRESULT vkd3d_allocate_buffer_memory(struct d3d12_device *device, VkBuffer vk_buffer,