-- v5: vkd3d: Pass an offset and size to d3d12_heap_unmap() in d3d12_resource_WriteToSubresource(). vkd3d: Call vkFlushMappedMemoryRanges() when unmapping of a heap is requested. vkd3d: Pass an offset and size to d3d12_heap_map() in d3d12_resource_ReadFromSubresource(). vkd3d: Call vkInvalidateMappedMemoryRanges() when a mapping is requested on a heap.
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d/resource.c | 48 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 8c050cfe..dde7db31 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -437,8 +437,28 @@ struct d3d12_heap *unsafe_impl_from_ID3D12Heap(ID3D12Heap *iface) return impl_from_ID3D12Heap(iface); }
-static HRESULT d3d12_heap_map(struct d3d12_heap *heap, uint64_t offset, - struct d3d12_resource *resource, void **data) +static void d3d12_heap_update_mapping_locked(struct d3d12_heap *heap, uint64_t offset, uint64_t size) +{ + const struct vkd3d_vk_device_procs *vk_procs; + struct d3d12_device *device = heap->device; + VkMappedMemoryRange range; + + if (!size) + return; + + vk_procs = &device->vk_procs; + + range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range.pNext = NULL; + range.memory = heap->vk_memory; + range.offset = offset; + range.size = size; + + VK_CALL(vkInvalidateMappedMemoryRanges(device->vk_device, 1, &range)); +} + +static HRESULT d3d12_heap_map(struct d3d12_heap *heap, uint64_t offset, uint64_t read_offset, + uint64_t read_size, struct d3d12_resource *resource, void **data) { struct d3d12_device *device = heap->device; HRESULT hr = S_OK; @@ -478,6 +498,7 @@ static HRESULT d3d12_heap_map(struct d3d12_heap *heap, uint64_t offset, if (data) *data = (BYTE *)heap->map_ptr + offset; ++resource->map_count; + d3d12_heap_update_mapping_locked(heap, offset + read_offset, read_size); } else { @@ -1223,11 +1244,26 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_GetDevice(ID3D12Resource *iface, return d3d12_device_query_interface(resource->device, iid, device); }
+static uint64_t offset_and_size_from_d3d12_range(const D3D12_RANGE *range, uint64_t default_size, uint64_t *size) +{ + if (range) + { + *size = (range->End > range->Begin) ? range->End - range->Begin : 0; + return range->Begin; + } + else + { + *size = default_size; + return 0; + } +} + static HRESULT STDMETHODCALLTYPE d3d12_resource_Map(ID3D12Resource *iface, UINT sub_resource, const D3D12_RANGE *read_range, void **data) { struct d3d12_resource *resource = impl_from_ID3D12Resource(iface); unsigned int sub_resource_count; + uint64_t read_offset, read_size; HRESULT hr;
TRACE("iface %p, sub_resource %u, read_range %p, data %p.\n", @@ -1259,9 +1295,9 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_Map(ID3D12Resource *iface, UINT return E_NOTIMPL; }
- WARN("Ignoring read range %p.\n", read_range); + read_offset = offset_and_size_from_d3d12_range(read_range, resource->desc.Width, &read_size);
- if (FAILED(hr = d3d12_heap_map(resource->heap, resource->heap_offset, resource, data))) + if (FAILED(hr = d3d12_heap_map(resource->heap, resource->heap_offset, read_offset, read_size, resource, data))) WARN("Failed to map resource %p, hr %#x.\n", resource, hr);
if (data) @@ -1381,7 +1417,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_WriteToSubresource(ID3D12Resourc TRACE("Offset %#"PRIx64", size %#"PRIx64", row pitch %#"PRIx64", depth pitch %#"PRIx64".\n", vk_layout.offset, vk_layout.size, vk_layout.rowPitch, vk_layout.depthPitch);
- if (FAILED(hr = d3d12_heap_map(resource->heap, resource->heap_offset, resource, (void **)&dst_data))) + if (FAILED(hr = d3d12_heap_map(resource->heap, resource->heap_offset, 0, 0, resource, (void **)&dst_data))) { WARN("Failed to map resource %p, hr %#x.\n", resource, hr); return hr; @@ -1469,7 +1505,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_ReadFromSubresource(ID3D12Resour TRACE("Offset %#"PRIx64", size %#"PRIx64", row pitch %#"PRIx64", depth pitch %#"PRIx64".\n", vk_layout.offset, vk_layout.size, vk_layout.rowPitch, vk_layout.depthPitch);
- if (FAILED(hr = d3d12_heap_map(resource->heap, resource->heap_offset, resource, (void **)&src_data))) + if (FAILED(hr = d3d12_heap_map(resource->heap, resource->heap_offset, 0, 0, resource, (void **)&src_data))) { WARN("Failed to map resource %p, hr %#x.\n", resource, hr); return hr;
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d/resource.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index dde7db31..2ff684a0 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1443,6 +1443,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_ReadFromSubresource(ID3D12Resour const struct vkd3d_vk_device_procs *vk_procs; VkImageSubresource vk_sub_resource; const struct vkd3d_format *format; + uint64_t read_offset, read_size; VkSubresourceLayout vk_layout; struct d3d12_device *device; uint8_t *src_data; @@ -1505,14 +1506,20 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_ReadFromSubresource(ID3D12Resour TRACE("Offset %#"PRIx64", size %#"PRIx64", row pitch %#"PRIx64", depth pitch %#"PRIx64".\n", vk_layout.offset, vk_layout.size, vk_layout.rowPitch, vk_layout.depthPitch);
- if (FAILED(hr = d3d12_heap_map(resource->heap, resource->heap_offset, 0, 0, resource, (void **)&src_data))) + read_offset = vkd3d_format_get_data_offset(format, vk_layout.rowPitch, + vk_layout.depthPitch, src_box->left, src_box->top, src_box->front); + read_size = vkd3d_format_get_data_offset(format, vk_layout.rowPitch, + vk_layout.depthPitch, src_box->right, src_box->bottom, src_box->back) - read_offset; + read_offset += vk_layout.offset; + + if (FAILED(hr = d3d12_heap_map(resource->heap, resource->heap_offset, read_offset, read_size, + resource, (void **)&src_data))) { WARN("Failed to map resource %p, hr %#x.\n", resource, hr); return hr; }
- src_data += vk_layout.offset + vkd3d_format_get_data_offset(format, vk_layout.rowPitch, - vk_layout.depthPitch, src_box->left, src_box->top, src_box->front); + src_data += read_offset;
vkd3d_format_copy_data(format, src_data, vk_layout.rowPitch, vk_layout.depthPitch, dst_data, dst_row_pitch, dst_slice_pitch, src_box->right - src_box->left,
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d/resource.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 2ff684a0..b65ab34e 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -437,7 +437,7 @@ struct d3d12_heap *unsafe_impl_from_ID3D12Heap(ID3D12Heap *iface) return impl_from_ID3D12Heap(iface); }
-static void d3d12_heap_update_mapping_locked(struct d3d12_heap *heap, uint64_t offset, uint64_t size) +static void d3d12_heap_update_mapping_locked(struct d3d12_heap *heap, uint64_t offset, uint64_t size, bool written) { const struct vkd3d_vk_device_procs *vk_procs; struct d3d12_device *device = heap->device; @@ -454,7 +454,10 @@ static void d3d12_heap_update_mapping_locked(struct d3d12_heap *heap, uint64_t o range.offset = offset; range.size = size;
- VK_CALL(vkInvalidateMappedMemoryRanges(device->vk_device, 1, &range)); + if (written) + VK_CALL(vkFlushMappedMemoryRanges(device->vk_device, 1, &range)); + else + VK_CALL(vkInvalidateMappedMemoryRanges(device->vk_device, 1, &range)); }
static HRESULT d3d12_heap_map(struct d3d12_heap *heap, uint64_t offset, uint64_t read_offset, @@ -498,7 +501,7 @@ static HRESULT d3d12_heap_map(struct d3d12_heap *heap, uint64_t offset, uint64_t if (data) *data = (BYTE *)heap->map_ptr + offset; ++resource->map_count; - d3d12_heap_update_mapping_locked(heap, offset + read_offset, read_size); + d3d12_heap_update_mapping_locked(heap, offset + read_offset, read_size, false); } else { @@ -512,9 +515,11 @@ static HRESULT d3d12_heap_map(struct d3d12_heap *heap, uint64_t offset, uint64_t return hr; }
-static void d3d12_heap_unmap(struct d3d12_heap *heap, struct d3d12_resource *resource) +static void d3d12_heap_unmap(struct d3d12_heap *heap, uint64_t written_offset, uint64_t written_size, + struct d3d12_resource *resource) { struct d3d12_device *device = heap->device; + bool need_update = false;
vkd3d_mutex_lock(&heap->mutex);
@@ -524,6 +529,8 @@ static void d3d12_heap_unmap(struct d3d12_heap *heap, struct d3d12_resource *res goto done; }
+ need_update = !!heap->map_count; + --resource->map_count; if (resource->map_count) goto done; @@ -546,6 +553,9 @@ static void d3d12_heap_unmap(struct d3d12_heap *heap, struct d3d12_resource *res }
done: + if (need_update) + d3d12_heap_update_mapping_locked(heap, resource->heap_offset + written_offset, written_size, true); + vkd3d_mutex_unlock(&heap->mutex); }
@@ -1310,6 +1320,7 @@ static void STDMETHODCALLTYPE d3d12_resource_Unmap(ID3D12Resource *iface, UINT s const D3D12_RANGE *written_range) { struct d3d12_resource *resource = impl_from_ID3D12Resource(iface); + uint64_t written_offset, written_size; unsigned int sub_resource_count;
TRACE("iface %p, sub_resource %u, written_range %p.\n", @@ -1322,9 +1333,10 @@ static void STDMETHODCALLTYPE d3d12_resource_Unmap(ID3D12Resource *iface, UINT s return; }
- WARN("Ignoring written range %p.\n", written_range); + /* As long as Map() is only implemented for buffers we can use the resource width here. */ + written_offset = offset_and_size_from_d3d12_range(written_range, resource->desc.Width, &written_size);
- d3d12_heap_unmap(resource->heap, resource); + d3d12_heap_unmap(resource->heap, written_offset, written_size, resource); }
static D3D12_RESOURCE_DESC * STDMETHODCALLTYPE d3d12_resource_GetDesc(ID3D12Resource *iface, @@ -1430,7 +1442,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_WriteToSubresource(ID3D12Resourc dst_data, vk_layout.rowPitch, vk_layout.depthPitch, dst_box->right - dst_box->left, dst_box->bottom - dst_box->top, dst_box->back - dst_box->front);
- d3d12_heap_unmap(resource->heap, resource); + d3d12_heap_unmap(resource->heap, 0, 0, resource);
return S_OK; } @@ -1525,7 +1537,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_ReadFromSubresource(ID3D12Resour dst_data, dst_row_pitch, dst_slice_pitch, src_box->right - src_box->left, src_box->bottom - src_box->top, src_box->back - src_box->front);
- d3d12_heap_unmap(resource->heap, resource); + d3d12_heap_unmap(resource->heap, 0, 0, resource);
return S_OK; }
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d/resource.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index b65ab34e..8ca45c01 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1365,6 +1365,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_WriteToSubresource(ID3D12Resourc { struct d3d12_resource *resource = impl_from_ID3D12Resource(iface); const struct vkd3d_vk_device_procs *vk_procs; + uint64_t written_offset, written_size; VkImageSubresource vk_sub_resource; const struct vkd3d_format *format; VkSubresourceLayout vk_layout; @@ -1435,14 +1436,18 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_WriteToSubresource(ID3D12Resourc return hr; }
- dst_data += vk_layout.offset + vkd3d_format_get_data_offset(format, vk_layout.rowPitch, + written_offset = vkd3d_format_get_data_offset(format, vk_layout.rowPitch, vk_layout.depthPitch, dst_box->left, dst_box->top, dst_box->front); + written_size = vkd3d_format_get_data_offset(format, vk_layout.rowPitch, + vk_layout.depthPitch, dst_box->right, dst_box->bottom, dst_box->back) - written_offset; + written_offset += vk_layout.offset; + dst_data += written_offset;
vkd3d_format_copy_data(format, src_data, src_row_pitch, src_slice_pitch, dst_data, vk_layout.rowPitch, vk_layout.depthPitch, dst_box->right - dst_box->left, dst_box->bottom - dst_box->top, dst_box->back - dst_box->front);
- d3d12_heap_unmap(resource->heap, 0, 0, resource); + d3d12_heap_unmap(resource->heap, written_offset, written_size, resource);
return S_OK; }
Note that we would only need to invalidate and flush when the memory isn't coherent. I.e., when device->memory_properties[heap->vk_memory_type] doesn't include VK_MEMORY_PROPERTY_HOST_COHERENT_BIT. (Which isn't that common, actually.)
I don't think the d3d12_heap_update_mapping_locked() helper is that helpful; it mostly just obfuscates whether we're doing a vkFlushMappedMemoryRanges() or vkInvalidateMappedMemoryRanges() call, and constructing the VkMappedMemoryRange structure isn't that complicated.
Just to throw something of a spanner in the works, I've submitted merge request 131.
This merge request was closed by Conor McCarthy.