From: Józef Kucia Subject: [PATCH 1/6] wined3d: Introduce "copy sub-resource" command stream operation. Message-Id: <20170317115757.14800-1-jkucia@codeweavers.com> Date: Fri, 17 Mar 2017 12:57:52 +0100 Signed-off-by: Józef Kucia --- This patch series fixes copying resource data between d3d10+ typeless formats. The idea behind the patch series is to split blit and memcpy-like copy operations. A few arguments in favor of this idea: * memcpy-like is simpler operation (doesn't support conversion or stretching), * we shouldn't need to extend blitter to handle other resource types (it's fine to support just 2D textures), * blit and copy operations should produce different results between different formats (blitter performs conversions), * copy operation should be allowed between various formats of the same size (including compressed and non-compressed formats), * it should be possible to implement wined3d_device_update_texture() on top of wined3d_cs_emit_copy_sub_resource(). --- dlls/wined3d/cs.c | 82 +++++++++++++++++++++++++++++++++++++----- dlls/wined3d/device.c | 12 +++---- dlls/wined3d/wined3d_private.h | 3 ++ 3 files changed, 82 insertions(+), 15 deletions(-) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index dd6feab..b1d9bc4 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -64,6 +64,7 @@ enum wined3d_cs_op WINED3D_CS_OP_MAP, WINED3D_CS_OP_UNMAP, WINED3D_CS_OP_BLT_SUB_RESOURCE, + WINED3D_CS_OP_COPY_SUB_RESOURCE, WINED3D_CS_OP_UPDATE_SUB_RESOURCE, }; @@ -360,6 +361,17 @@ struct wined3d_cs_blt_sub_resource enum wined3d_texture_filter_type filter; }; +struct wined3d_cs_copy_sub_resource +{ + enum wined3d_cs_op opcode; + struct wined3d_resource *dst_resource; + unsigned int dst_sub_resource_idx; + struct wined3d_box dst_box; + struct wined3d_resource *src_resource; + unsigned int src_sub_resource_idx; + struct wined3d_box src_box; +}; + struct wined3d_cs_update_sub_resource { enum wined3d_cs_op opcode; @@ -1676,14 +1688,7 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void * { const struct wined3d_cs_blt_sub_resource *op = data; - if (op->dst_resource->type == WINED3D_RTYPE_BUFFER) - { - if (FAILED(wined3d_buffer_copy(buffer_from_resource(op->dst_resource), op->dst_box.left, - buffer_from_resource(op->src_resource), op->src_box.left, - op->src_box.right - op->src_box.left))) - ERR("Failed to copy buffer.\n"); - } - else if (op->dst_resource->type == WINED3D_RTYPE_TEXTURE_2D) + if (op->dst_resource->type == WINED3D_RTYPE_TEXTURE_2D) { struct wined3d_surface *dst_surface, *src_surface = NULL; struct wined3d_texture *dst_texture, *src_texture; @@ -1705,7 +1710,7 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void * } else { - FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(op->dst_resource->type)); + ERR("Unexpected resource type %s.\n", debug_d3dresourcetype(op->dst_resource->type)); } if (op->src_resource) @@ -1740,6 +1745,64 @@ void wined3d_cs_emit_blt_sub_resource(struct wined3d_cs *cs, struct wined3d_reso cs->ops->submit(cs); } +static void wined3d_cs_exec_copy_sub_resource(struct wined3d_cs *cs, const void *data) +{ + const struct wined3d_cs_copy_sub_resource *op = data; + + if (op->dst_resource->type == WINED3D_RTYPE_BUFFER) + { + if (FAILED(wined3d_buffer_copy(buffer_from_resource(op->dst_resource), op->dst_box.left, + buffer_from_resource(op->src_resource), op->src_box.left, + op->src_box.right - op->src_box.left))) + ERR("Failed to copy buffer.\n"); + } + else if (op->dst_resource->type == WINED3D_RTYPE_TEXTURE_2D) + { + struct wined3d_texture *dst_texture, *src_texture; + struct wined3d_surface *dst_surface, *src_surface; + RECT dst_rect, src_rect; + + dst_texture = texture_from_resource(op->dst_resource); + dst_surface = dst_texture->sub_resources[op->dst_sub_resource_idx].u.surface; + src_texture = texture_from_resource(op->src_resource); + src_surface = src_texture->sub_resources[op->src_sub_resource_idx].u.surface; + SetRect(&dst_rect, op->dst_box.left, op->dst_box.top, op->dst_box.right, op->dst_box.bottom); + SetRect(&src_rect, op->src_box.left, op->src_box.top, op->src_box.right, op->src_box.bottom); + + if (FAILED(wined3d_surface_blt(dst_surface, &dst_rect, src_surface, + &src_rect, 0, NULL, WINED3D_TEXF_POINT))) + FIXME("Blit failed.\n"); + } + else + { + FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(op->dst_resource->type)); + } + + wined3d_resource_release(op->src_resource); + wined3d_resource_release(op->dst_resource); +} + +void wined3d_cs_emit_copy_sub_resource(struct wined3d_cs *cs, + struct wined3d_resource *dst_resource, unsigned int dst_sub_resource_idx, const struct wined3d_box *dst_box, + struct wined3d_resource *src_resource, unsigned int src_sub_resource_idx, const struct wined3d_box *src_box) +{ + struct wined3d_cs_copy_sub_resource *op; + + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_COPY_SUB_RESOURCE; + op->dst_resource = dst_resource; + op->dst_sub_resource_idx = dst_sub_resource_idx; + op->dst_box = *dst_box; + op->src_resource = src_resource; + op->src_sub_resource_idx = src_sub_resource_idx; + op->src_box = *src_box; + + wined3d_resource_acquire(dst_resource); + wined3d_resource_acquire(src_resource); + + cs->ops->submit(cs); +} + static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_update_sub_resource *op = data; @@ -1859,6 +1922,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void /* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map, /* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap, /* WINED3D_CS_OP_BLT_SUB_RESOURCE */ wined3d_cs_exec_blt_sub_resource, + /* WINED3D_CS_OP_COPY_SUB_RESOURCE */ wined3d_cs_exec_copy_sub_resource, /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, }; diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index eef9818..0bc494e 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -3886,8 +3886,8 @@ void CDECL wined3d_device_copy_resource(struct wined3d_device *device, box.front = 0; box.back = 1; - wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, 0, &box, - src_resource, 0, &box, 0, NULL, WINED3D_TEXF_POINT); + wined3d_cs_emit_copy_sub_resource(device->cs, dst_resource, 0, &box, + src_resource, 0, &box); return; } @@ -3922,8 +3922,8 @@ void CDECL wined3d_device_copy_resource(struct wined3d_device *device, { unsigned int idx = j * dst_texture->level_count + i; - wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, idx, &box, - src_resource, idx, &box, 0, NULL, WINED3D_TEXF_POINT); + wined3d_cs_emit_copy_sub_resource(device->cs, dst_resource, idx, &box, + src_resource, idx, &box); } } } @@ -4075,8 +4075,8 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev return WINED3DERR_INVALIDCALL; } - wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, dst_sub_resource_idx, &dst_box, - src_resource, src_sub_resource_idx, src_box, 0, NULL, WINED3D_TEXF_POINT); + wined3d_cs_emit_copy_sub_resource(device->cs, dst_resource, dst_sub_resource_idx, &dst_box, + src_resource, src_sub_resource_idx, src_box); return WINED3D_OK; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 1a01106..d0f7e7e 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3231,6 +3231,9 @@ void wined3d_cs_emit_blt_sub_resource(struct wined3d_cs *cs, struct wined3d_reso const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) DECLSPEC_HIDDEN; +void wined3d_cs_emit_copy_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *dst_resource, + unsigned int dst_sub_resource_idx, const struct wined3d_box *dst_box, struct wined3d_resource *src_resource, + unsigned int src_sub_resource_idx, const struct wined3d_box *src_box) DECLSPEC_HIDDEN; void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, unsigned int group_count_x, unsigned int group_count_y, unsigned int group_count_z) DECLSPEC_HIDDEN; void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, int base_vertex_idx, -- 2.10.2