wined3d: Send sub-resource update calls through the command stream.

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Henri Verbeet 2017-03-06 10:45:24 +01:00 committed by Alexandre Julliard
parent 2338060142
commit fbff59ae4a
3 changed files with 122 additions and 48 deletions

View File

@ -63,6 +63,7 @@ enum wined3d_cs_op
WINED3D_CS_OP_UNLOAD_RESOURCE,
WINED3D_CS_OP_MAP,
WINED3D_CS_OP_UNMAP,
WINED3D_CS_OP_UPDATE_SUB_RESOURCE,
};
struct wined3d_cs_present
@ -344,6 +345,15 @@ struct wined3d_cs_unmap
HRESULT *hr;
};
struct wined3d_cs_update_sub_resource
{
enum wined3d_cs_op opcode;
struct wined3d_resource *resource;
unsigned int sub_resource_idx;
struct wined3d_box box;
struct wined3d_sub_resource_data data;
};
static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data)
{
const struct wined3d_cs_present *op = data;
@ -1647,6 +1657,85 @@ HRESULT wined3d_cs_unmap(struct wined3d_cs *cs, struct wined3d_resource *resourc
return hr;
}
static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const void *data)
{
const struct wined3d_cs_update_sub_resource *op = data;
const struct wined3d_box *box = &op->box;
unsigned int width, height, depth, level;
struct wined3d_const_bo_address addr;
struct wined3d_context *context;
struct wined3d_texture *texture;
if (op->resource->type == WINED3D_RTYPE_BUFFER)
{
struct wined3d_buffer *buffer = buffer_from_resource(op->resource);
context = context_acquire(op->resource->device, NULL, 0);
if (!wined3d_buffer_load_location(buffer, context, WINED3D_LOCATION_BUFFER))
{
ERR("Failed to load buffer location.\n");
context_release(context);
goto done;
}
wined3d_buffer_upload_data(buffer, context, box, op->data.data);
wined3d_buffer_invalidate_location(buffer, ~WINED3D_LOCATION_BUFFER);
context_release(context);
goto done;
}
texture = wined3d_texture_from_resource(op->resource);
level = op->sub_resource_idx % texture->level_count;
width = wined3d_texture_get_level_width(texture, level);
height = wined3d_texture_get_level_height(texture, level);
depth = wined3d_texture_get_level_depth(texture, level);
addr.buffer_object = 0;
addr.addr = op->data.data;
context = context_acquire(op->resource->device, NULL, 0);
/* Only load the sub-resource for partial updates. */
if (!box->left && !box->top && !box->front
&& box->right == width && box->bottom == height && box->back == depth)
wined3d_texture_prepare_texture(texture, context, FALSE);
else
wined3d_texture_load_location(texture, op->sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB);
wined3d_texture_bind_and_dirtify(texture, context, FALSE);
wined3d_texture_upload_data(texture, op->sub_resource_idx, context,
box, &addr, op->data.row_pitch, op->data.slice_pitch);
context_release(context);
wined3d_texture_validate_location(texture, op->sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
wined3d_texture_invalidate_location(texture, op->sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
done:
wined3d_resource_release(op->resource);
}
void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource,
unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch,
unsigned int slice_pitch)
{
struct wined3d_cs_update_sub_resource *op;
op = cs->ops->require_space(cs, sizeof(*op));
op->opcode = WINED3D_CS_OP_UPDATE_SUB_RESOURCE;
op->resource = resource;
op->sub_resource_idx = sub_resource_idx;
op->box = *box;
op->data.row_pitch = row_pitch;
op->data.slice_pitch = slice_pitch;
op->data.data = data;
wined3d_resource_acquire(resource);
cs->ops->submit(cs);
}
static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
{
/* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present,
@ -1686,6 +1775,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
/* WINED3D_CS_OP_UNLOAD_RESOURCE */ wined3d_cs_exec_unload_resource,
/* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map,
/* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap,
/* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource,
};
static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size)

View File

@ -4011,84 +4011,65 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str
unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch,
unsigned int depth_pitch)
{
unsigned int width, height, depth, level;
struct wined3d_const_bo_address addr;
struct wined3d_context *context;
struct wined3d_texture *texture;
unsigned int width, height, depth;
struct wined3d_box b;
TRACE("device %p, resource %p, sub_resource_idx %u, box %s, data %p, row_pitch %u, depth_pitch %u.\n",
device, resource, sub_resource_idx, debug_box(box), data, row_pitch, depth_pitch);
if (resource->type == WINED3D_RTYPE_BUFFER)
{
struct wined3d_buffer *buffer = buffer_from_resource(resource);
if (sub_resource_idx > 0)
{
WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
return;
}
context = context_acquire(resource->device, NULL, 0);
if (!wined3d_buffer_load_location(buffer, context, WINED3D_LOCATION_BUFFER))
width = resource->size;
height = 1;
depth = 1;
}
else if (resource->type == WINED3D_RTYPE_TEXTURE_2D || resource->type == WINED3D_RTYPE_TEXTURE_3D)
{
struct wined3d_texture *texture = texture_from_resource(resource);
unsigned int level;
if (sub_resource_idx >= texture->level_count * texture->layer_count)
{
ERR("Failed to load buffer location.\n");
context_release(context);
WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
return;
}
wined3d_buffer_upload_data(buffer, context, box, data);
wined3d_buffer_invalidate_location(buffer, ~WINED3D_LOCATION_BUFFER);
context_release(context);
return;
level = sub_resource_idx % texture->level_count;
width = wined3d_texture_get_level_width(texture, level);
height = wined3d_texture_get_level_height(texture, level);
depth = wined3d_texture_get_level_depth(texture, level);
}
if (resource->type != WINED3D_RTYPE_TEXTURE_2D && resource->type != WINED3D_RTYPE_TEXTURE_3D)
else
{
FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type));
return;
}
texture = texture_from_resource(resource);
if (sub_resource_idx >= texture->level_count * texture->layer_count)
if (!box)
{
WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
return;
b.left = 0;
b.top = 0;
b.right = width;
b.bottom = height;
b.front = 0;
b.back = depth;
box = &b;
}
level = sub_resource_idx % texture->level_count;
width = wined3d_texture_get_level_width(texture, level);
height = wined3d_texture_get_level_height(texture, level);
depth = wined3d_texture_get_level_depth(texture, level);
if (box && (box->left >= box->right || box->right > width
else if (box->left >= box->right || box->right > width
|| box->top >= box->bottom || box->bottom > height
|| box->front >= box->back || box->back > depth))
|| box->front >= box->back || box->back > depth)
{
WARN("Invalid box %s specified.\n", debug_box(box));
return;
}
addr.buffer_object = 0;
addr.addr = data;
context = context_acquire(resource->device, NULL, 0);
/* Only load the sub-resource for partial updates. */
if (!box || (!box->left && !box->top && !box->front
&& box->right == width && box->bottom == height && box->back == depth))
wined3d_texture_prepare_texture(texture, context, FALSE);
else
wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB);
wined3d_texture_bind_and_dirtify(texture, context, FALSE);
wined3d_texture_upload_data(texture, sub_resource_idx, context, box, &addr, row_pitch, depth_pitch);
context_release(context);
wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
wined3d_texture_invalidate_location(texture, sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
wined3d_cs_emit_update_sub_resource(device->cs, resource, sub_resource_idx, box, data, row_pitch, depth_pitch);
}
HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *device,

View File

@ -3271,6 +3271,9 @@ void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs,
struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN;
void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN;
void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource,
unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch,
unsigned int slice_pitch) DECLSPEC_HIDDEN;
void wined3d_cs_init_object(struct wined3d_cs *cs,
void (*callback)(void *object), void *object) DECLSPEC_HIDDEN;
HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, unsigned int sub_resource_idx,