Enables ReadFromSubresource() to succeed in cases where it would have failed otherwise.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/resource.c | 54 +++++++++++++++++++++++++++++++++----- libs/vkd3d/vkd3d_private.h | 1 + 2 files changed, 48 insertions(+), 7 deletions(-)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 0f7ce5e..22deaef 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -781,9 +781,36 @@ static unsigned int max_miplevel_count(const D3D12_RESOURCE_DESC *desc) return vkd3d_log2i(size) + 1; }
+static void image_create_info_adjust_tiling(struct d3d12_device *device, VkImageCreateInfo *image_info) +{ + const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; + VkImageFormatProperties image_properties; + VkResult vr; + + vr = VK_CALL(vkGetPhysicalDeviceImageFormatProperties(device->vk_physical_device, image_info->format, + image_info->imageType, VK_IMAGE_TILING_LINEAR, image_info->usage, image_info->flags, &image_properties)); + if (vr == VK_ERROR_FORMAT_NOT_SUPPORTED) + { + /* No change. The requested parameters are not supported for linear tiling. */ + return; + } + else if (vr != VK_SUCCESS) + { + WARN("Failed to get device image format properties, vr %d.\n", vr); + } + else if (image_info->extent.depth <= image_properties.maxExtent.depth + && image_info->mipLevels <= image_properties.maxMipLevels + && image_info->arrayLayers <= image_properties.maxArrayLayers + && (image_info->samples & image_properties.sampleCounts) == image_info->samples) + { + WARN("Changing layout from VK_IMAGE_TILING_OPTIMAL to VK_IMAGE_TILING_LINEAR on custom heap.\n"); + image_info->tiling = VK_IMAGE_TILING_LINEAR; + } +} + static HRESULT vkd3d_create_image(struct d3d12_device *device, const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, - const D3D12_RESOURCE_DESC *desc, VkImage *vk_image) + const D3D12_RESOURCE_DESC *desc, VkImage *vk_image, bool *is_linear) { const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; const bool sparse_resource = !heap_properties; @@ -883,8 +910,20 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device, image_info.pQueueFamilyIndices = NULL; }
- image_info.initialLayout = heap_properties && is_cpu_accessible_heap(heap_properties) ? - VK_IMAGE_LAYOUT_PREINITIALIZED : VK_IMAGE_LAYOUT_UNDEFINED; + if (heap_properties && is_cpu_accessible_heap(heap_properties)) + { + image_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; + + if (image_info.tiling == VK_IMAGE_TILING_OPTIMAL) + image_create_info_adjust_tiling(device, &image_info); + } + else + { + image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } + + if (is_linear) + *is_linear = image_info.tiling == VK_IMAGE_TILING_LINEAR;
if ((vr = VK_CALL(vkCreateImage(device->vk_device, &image_info, NULL, vk_image))) < 0) { @@ -916,7 +955,7 @@ HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device, }
/* XXX: We have to create an image to get its memory requirements. */ - if (SUCCEEDED(hr = vkd3d_create_image(device, &heap_properties, 0, desc, &vk_image))) + if (SUCCEEDED(hr = vkd3d_create_image(device, &heap_properties, 0, desc, &vk_image, NULL))) { VK_CALL(vkGetImageMemoryRequirements(device->vk_device, vk_image, &requirements)); VK_CALL(vkDestroyImage(device->vk_device, vk_image, NULL)); @@ -1385,6 +1424,7 @@ static HRESULT d3d12_resource_init(struct d3d12_resource *resource, struct d3d12 resource->internal_refcount = 1;
resource->desc = *desc; + resource->is_linear_texture = false;
if (heap_properties && !d3d12_resource_validate_heap_properties(resource, heap_properties, initial_state)) return E_INVALIDARG; @@ -1432,7 +1472,7 @@ static HRESULT d3d12_resource_init(struct d3d12_resource *resource, struct d3d12 resource->desc.MipLevels = max_miplevel_count(desc); resource->flags |= VKD3D_RESOURCE_INITIAL_STATE_TRANSITION; if (FAILED(hr = vkd3d_create_image(device, heap_properties, heap_flags, - &resource->desc, &resource->u.vk_image))) + &resource->desc, &resource->u.vk_image, &resource->is_linear_texture))) return hr; break;
@@ -3656,7 +3696,7 @@ HRESULT vkd3d_init_null_resources(struct vkd3d_null_resources *null_resources, resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE;
if (FAILED(hr = vkd3d_create_image(device, &heap_properties, D3D12_HEAP_FLAG_NONE, - &resource_desc, &null_resources->vk_2d_image))) + &resource_desc, &null_resources->vk_2d_image, NULL))) goto fail; if (FAILED(hr = vkd3d_allocate_image_memory(device, null_resources->vk_2d_image, &heap_properties, D3D12_HEAP_FLAG_NONE, &null_resources->vk_2d_image_memory, NULL, NULL))) @@ -3677,7 +3717,7 @@ HRESULT vkd3d_init_null_resources(struct vkd3d_null_resources *null_resources, resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
if (FAILED(hr = vkd3d_create_image(device, use_sparse_resources ? NULL : &heap_properties, D3D12_HEAP_FLAG_NONE, - &resource_desc, &null_resources->vk_2d_storage_image))) + &resource_desc, &null_resources->vk_2d_storage_image, NULL))) goto fail; if (!use_sparse_resources && FAILED(hr = vkd3d_allocate_image_memory(device, null_resources->vk_2d_storage_image, &heap_properties, D3D12_HEAP_FLAG_NONE, &null_resources->vk_2d_storage_image_memory, NULL, NULL))) diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 4398351..4640113 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -389,6 +389,7 @@ struct d3d12_resource LONG internal_refcount;
D3D12_RESOURCE_DESC desc; + bool is_linear_texture;
D3D12_GPU_VIRTUAL_ADDRESS gpu_address; union
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/resource.c | 92 +++++++++++++++++++++++++++++++++++++++++-- tests/d3d12.c | 10 ++--- 2 files changed, 94 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 22deaef..f34de9d 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1244,12 +1244,98 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_ReadFromSubresource(ID3D12Resour void *dst_data, UINT dst_row_pitch, UINT dst_slice_pitch, UINT src_sub_resource, const D3D12_BOX *src_box) { - FIXME("iface %p, dst_data %p, dst_row_pitch %u, dst_slice_pitch %u, " - "src_sub_resource %u, src_box %p stub!\n", + struct d3d12_resource *resource = impl_from_ID3D12Resource(iface); + const struct vkd3d_vk_device_procs *vk_procs; + VkImageSubresource vk_sub_resource; + const struct vkd3d_format *format; + VkSubresourceLayout vk_layout; + struct d3d12_device *device; + void *src_map_ptr; + unsigned int y, z; + D3D12_BOX box; + HRESULT hr; + BYTE *dst; + + TRACE("iface %p, dst_data %p, dst_row_pitch %u, dst_slice_pitch %u, " + "src_sub_resource %u, src_box %p.\n", iface, dst_data, dst_row_pitch, dst_slice_pitch, src_sub_resource, src_box);
- return E_NOTIMPL; + if (src_box) + { + box = *src_box; + } + else + { + box.left = 0; + box.top = 0; + box.front = 0; + box.right = resource->desc.Width; + box.bottom = resource->desc.Height; + box.back = d3d12_resource_desc_get_depth(&resource->desc, src_sub_resource % resource->desc.MipLevels); + } + if (box.right <= box.left || box.bottom <= box.top || box.back <= box.front) + return S_OK; + + if (d3d12_resource_is_buffer(resource)) + { + WARN("Buffers are not supported.\n"); + return E_INVALIDARG; + } + + if (!d3d12_resource_is_cpu_accessible(resource)) + { + FIXME("Not implemented for this resource type.\n"); + return E_NOTIMPL; + } + + device = resource->device; + vk_procs = &device->vk_procs; + + if (!(format = vkd3d_format_from_d3d12_resource_desc(device, &resource->desc, 0))) + { + WARN("Invalid DXGI format %#x.\n", resource->desc.Format); + return E_INVALIDARG; + } + + if (!resource->is_linear_texture) + { + FIXME("Not implemented for layouts other than D3D12_TEXTURE_LAYOUT_ROW_MAJOR.\n"); + return E_NOTIMPL; + } + + if (FAILED(hr = d3d12_heap_map(resource->heap, resource->heap_offset, resource, &src_map_ptr))) + { + WARN("Failed to map resource %p, hr %#x.\n", resource, hr); + return hr; + } + + vk_sub_resource.arrayLayer = src_sub_resource / resource->desc.MipLevels; + vk_sub_resource.mipLevel = src_sub_resource % resource->desc.MipLevels; + vk_sub_resource.aspectMask = format->vk_aspect_mask; + VK_CALL(vkGetImageSubresourceLayout(device->vk_device, resource->u.vk_image, &vk_sub_resource, &vk_layout)); + TRACE("Offset %#"PRIx64", size %#"PRIx64", row pitch %#"PRIx64", array pitch %#"PRIx64", depth pitch %#"PRIx64".\n", + vk_layout.offset, vk_layout.size, vk_layout.rowPitch, vk_layout.arrayPitch, vk_layout.depthPitch); + + src_map_ptr = (BYTE*)src_map_ptr + vk_layout.offset; + for (z = box.front; z < box.back; ++z) + { + dst = dst_data + (z - box.front) * dst_slice_pitch; + for (y = box.top; y < box.bottom; y += format->block_height) + { + size_t size = (box.right - box.left) / format->block_width + * format->byte_count * format->block_byte_count; + const BYTE *src = (BYTE*)src_map_ptr + z * vk_layout.depthPitch + + y / format->block_height * vk_layout.rowPitch + + box.left / format->block_width * format->byte_count * format->block_byte_count; + memcpy(dst, src, size); + dst += dst_row_pitch; + } + } + + d3d12_heap_unmap(resource->heap, resource); + + return S_OK; }
static HRESULT STDMETHODCALLTYPE d3d12_resource_GetHeapProperties(ID3D12Resource *iface, diff --git a/tests/d3d12.c b/tests/d3d12.c index 80f3f2d..a7647e0 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -30227,7 +30227,7 @@ static void test_read_write_subresource(void) todo ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Resource_ReadFromSubresource(rb_buffer, dst_buffer, row_pitch, slice_pitch, 0, &box); - todo ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
ID3D12Resource_Release(rb_buffer);
@@ -30261,7 +30261,7 @@ static void test_read_write_subresource(void) todo ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Resource_ReadFromSubresource(src_texture, dst_buffer, row_pitch, slice_pitch, 0, NULL); - todo ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
/* Empty box */ set_box(&box, 0, 0, 0, 0, 0, 0); @@ -30269,7 +30269,7 @@ static void test_read_write_subresource(void) todo ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Resource_ReadFromSubresource(src_texture, dst_buffer, row_pitch, slice_pitch, 0, &box); - todo ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
for (z = 0; z < 64; ++z) { @@ -30304,13 +30304,13 @@ static void test_read_write_subresource(void) /* Read region 1 */ set_box(&box, 0, 0, 0, 2, 2, 2); hr = ID3D12Resource_ReadFromSubresource(src_texture, dst_buffer, row_pitch, slice_pitch, 0, &box); - todo ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
/* Read region 2 */ set_box(&box, 2, 2, 2, 11, 13, 17); hr = ID3D12Resource_ReadFromSubresource(src_texture, &dst_buffer[2 * 128 * 100 + 2 * 128 + 2], row_pitch, slice_pitch, 0, &box); - todo ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
for (z = 0; z < 64; ++z) {
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- tests/d3d12.c | 131 +++++++++++++++++++++++++++++++------------------- 1 file changed, 81 insertions(+), 50 deletions(-)
diff --git a/tests/d3d12.c b/tests/d3d12.c index a7647e0..6d2040d 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -30180,6 +30180,29 @@ static void test_vertex_shader_stream_output(void) destroy_test_context(&context); }
+static void write_subresource_test_data(unsigned int *dst_buffer) +{ + unsigned int x, y, z; + unsigned int *ptr; + + for (z = 0; z < 64; ++z) + { + for (y = 0; y < 100; ++y) + { + for (x = 0; x < 128; ++x) + { + ptr = &dst_buffer[z * 128 * 100 + y * 128 + x]; + if (x < 2 && y< 2 && z < 2) /* Region 1 */ + *ptr = (z + 1) << 16 | (y + 1) << 8 | (x + 1); + else if (2 <= x && x < 11 && 2 <= y && y < 13 && 2 <= z && z < 17) /* Region 2 */ + *ptr = (z + 2) << 16 | (y + 2) << 8 | (x + 2); + else + *ptr = 0xdeadbeef; + } + } + } +} + static void test_read_write_subresource(void) { D3D12_TEXTURE_COPY_LOCATION src_location, dst_location; @@ -30201,9 +30224,9 @@ static void test_read_write_subresource(void) unsigned int row_pitch; unsigned int x, y, z; ID3D12Device *device; - unsigned int *ptr; D3D12_BOX box; HRESULT hr; + int i;
memset(&desc, 0, sizeof(desc)); desc.no_render_target = true; @@ -30271,71 +30294,79 @@ static void test_read_write_subresource(void) hr = ID3D12Resource_ReadFromSubresource(src_texture, dst_buffer, row_pitch, slice_pitch, 0, &box); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
- for (z = 0; z < 64; ++z) + for (i = 0; i < 2; ++i) { - for (y = 0; y < 100; ++y) - { - for (x = 0; x < 128; ++x) - { - ptr = &dst_buffer[z * 128 * 100 + y * 128 + x]; - if (x < 2 && y< 2 && z < 2) /* Region 1 */ - *ptr = (z + 1) << 16 | (y + 1) << 8 | (x + 1); - else if (2 <= x && x < 11 && 2 <= y && y < 13 && 2 <= z && z < 17) /* Region 2 */ - *ptr = (z + 2) << 16 | (y + 2) << 8 | (x + 2); - else - *ptr = 0xdeadbeef; - } - } - } + vkd3d_test_set_context("Test %u", i);
- /* Write region 1 */ - set_box(&box, 0, 0, 0, 2, 2, 2); - hr = ID3D12Resource_WriteToSubresource(src_texture, 0, &box, dst_buffer, row_pitch, slice_pitch); - todo ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + write_subresource_test_data(dst_buffer);
- /* Write region 2 */ - set_box(&box, 2, 2, 2, 11, 13, 17); - hr = ID3D12Resource_WriteToSubresource(src_texture, 0, &box, &dst_buffer[2 * 128 * 100 + 2 * 128 + 2], - row_pitch, slice_pitch); - todo ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + if (!i) + { + /* Write region 1 */ + set_box(&box, 0, 0, 0, 2, 2, 2); + hr = ID3D12Resource_WriteToSubresource(src_texture, 0, &box, dst_buffer, row_pitch, slice_pitch); + todo ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
- memset(dst_buffer, 0, buffer_size); + /* Write region 2 */ + set_box(&box, 2, 2, 2, 11, 13, 17); + hr = ID3D12Resource_WriteToSubresource(src_texture, 0, &box, &dst_buffer[2 * 128 * 100 + 2 * 128 + 2], + row_pitch, slice_pitch); + todo ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + } + else + { + /* Upload the test data */ + transition_resource_state(command_list, src_texture, + D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST); + texture_data.pData = dst_buffer; + texture_data.RowPitch = row_pitch; + texture_data.SlicePitch = slice_pitch; + upload_texture_data(src_texture, &texture_data, 1, queue, command_list); + reset_command_list(command_list, context.allocator); + transition_resource_state(command_list, src_texture, + D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COMMON); + }
- /* Read region 1 */ - set_box(&box, 0, 0, 0, 2, 2, 2); - hr = ID3D12Resource_ReadFromSubresource(src_texture, dst_buffer, row_pitch, slice_pitch, 0, &box); - ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + memset(dst_buffer, 0, buffer_size);
- /* Read region 2 */ - set_box(&box, 2, 2, 2, 11, 13, 17); - hr = ID3D12Resource_ReadFromSubresource(src_texture, &dst_buffer[2 * 128 * 100 + 2 * 128 + 2], row_pitch, - slice_pitch, 0, &box); - ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + /* Read region 1 */ + set_box(&box, 0, 0, 0, 2, 2, 2); + hr = ID3D12Resource_ReadFromSubresource(src_texture, dst_buffer, row_pitch, slice_pitch, 0, &box); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
- for (z = 0; z < 64; ++z) - { - for (y = 0; y < 100; ++y) + /* Read region 2 */ + set_box(&box, 2, 2, 2, 11, 13, 17); + hr = ID3D12Resource_ReadFromSubresource(src_texture, &dst_buffer[2 * 128 * 100 + 2 * 128 + 2], row_pitch, + slice_pitch, 0, &box); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + + for (z = 0; z < 64; ++z) { - for (x = 0; x < 128; ++x) + for (y = 0; y < 100; ++y) { - if (x < 2 && y < 2 && z < 2) /* Region 1 */ - expected = (z + 1) << 16 | (y + 1) << 8 | (x + 1); - else if (2 <= x && x < 11 && 2 <= y && y < 13 && 2 <= z && z < 17) /* Region 2 */ - expected = (z + 2) << 16 | (y + 2) << 8 | (x + 2); - else /* Untouched */ - expected = 0; - - got = dst_buffer[z * 128 * 100 + y * 128 + x]; + for (x = 0; x < 128; ++x) + { + if (x < 2 && y < 2 && z < 2) /* Region 1 */ + expected = (z + 1) << 16 | (y + 1) << 8 | (x + 1); + else if (2 <= x && x < 11 && 2 <= y && y < 13 && 2 <= z && z < 17) /* Region 2 */ + expected = (z + 2) << 16 | (y + 2) << 8 | (x + 2); + else /* Untouched */ + expected = 0; + + got = dst_buffer[z * 128 * 100 + y * 128 + x]; + if (got != expected) + break; + } if (got != expected) break; } if (got != expected) break; } - if (got != expected) - break; + todo_if(!i) + ok(got == expected, "Got unexpected value 0x%08x at (%u, %u, %u), expected 0x%08x.\n", got, x, y, z, expected); } - todo ok(got == expected, "Got unexpected value 0x%08x at (%u, %u, %u), expected 0x%08x.\n", got, x, y, z, expected); + vkd3d_test_set_context(NULL);
/* Test layout is the same */ dst_texture = create_default_texture3d(device, 128, 100, 64, 1, DXGI_FORMAT_R8G8B8A8_UNORM, 0,