Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/wined3d/texture.c | 34 +++++++++++++++++++++++----------- dlls/wined3d/wined3d_private.h | 2 ++ 2 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 165d83eb035..ad34e44b406 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -1711,6 +1711,20 @@ void CDECL wined3d_texture_get_pitch(const struct wined3d_texture *texture, width, height, row_pitch, slice_pitch); }
+static void wined3d_texture_get_map_pitch(const struct wined3d_texture *texture, + unsigned int level, unsigned int *row_pitch, unsigned int *slice_pitch) +{ + if (texture->resource.format_flags & WINED3DFMT_FLAG_BROKEN_PITCH) + { + *row_pitch = wined3d_texture_get_level_width(texture, level) * texture->resource.format->byte_count; + *slice_pitch = wined3d_texture_get_level_height(texture, level) * (*row_pitch); + } + else + { + wined3d_texture_get_pitch(texture, level, row_pitch, slice_pitch); + } +} + DWORD CDECL wined3d_texture_set_lod(struct wined3d_texture *texture, DWORD lod) { struct wined3d_resource *resource; @@ -1992,6 +2006,8 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, unsig sub_resource->size = texture->slice_pitch; sub_resource->locations = WINED3D_LOCATION_DISCARDED;
+ wined3d_texture_get_map_pitch(texture, level, &sub_resource->map_row_pitch, &sub_resource->map_slice_pitch); + if (texture->texture_ops == &texture_gl_ops) { if (multisample_type && gl_info->supported[ARB_TEXTURE_MULTISAMPLE]) @@ -3587,15 +3603,8 @@ static HRESULT texture_resource_sub_resource_map(struct wined3d_resource *resour
context_release(context);
- if (fmt_flags & WINED3DFMT_FLAG_BROKEN_PITCH) - { - map_desc->row_pitch = wined3d_texture_get_level_width(texture, texture_level) * format->byte_count; - map_desc->slice_pitch = wined3d_texture_get_level_height(texture, texture_level) * map_desc->row_pitch; - } - else - { - wined3d_texture_get_pitch(texture, texture_level, &map_desc->row_pitch, &map_desc->slice_pitch); - } + map_desc->row_pitch = sub_resource->map_row_pitch; + map_desc->slice_pitch = sub_resource->map_slice_pitch;
if (!box) { @@ -3950,6 +3959,8 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc for (i = 0; i < sub_count; ++i) { struct wined3d_texture_sub_resource *sub_resource; + unsigned int level = i % texture->level_count; + unsigned int layer = i / texture->level_count;
sub_resource = &texture->sub_resources[i]; sub_resource->locations = WINED3D_LOCATION_DISCARDED; @@ -3959,6 +3970,8 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc wined3d_texture_invalidate_location(texture, i, ~WINED3D_LOCATION_SYSMEM); }
+ wined3d_texture_get_map_pitch(texture, level, &sub_resource->map_row_pitch, &sub_resource->map_slice_pitch); + if (FAILED(hr = device_parent->ops->texture_sub_resource_created(device_parent, desc->resource_type, texture, i, &sub_resource->parent, &sub_resource->parent_ops))) { @@ -3970,8 +3983,7 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc
TRACE("parent %p, parent_ops %p.\n", sub_resource->parent, sub_resource->parent_ops);
- TRACE("Created sub-resource %u (level %u, layer %u).\n", - i, i % texture->level_count, i / texture->level_count); + TRACE("Created sub-resource %u (level %u, layer %u).\n", i, level, layer);
if (desc->usage & WINED3DUSAGE_OWNDC) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index da1cf638606..1e6a315e72c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4259,6 +4259,8 @@ struct wined3d_texture DWORD locations; struct wined3d_bo_gl bo;
+ unsigned int map_row_pitch, map_slice_pitch; + void *user_memory; } *sub_resources; };
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- I don't know if there's an advantage to caching these, although it seems plausible, but mostly this is just for ease of access.
dlls/wined3d/buffer.c | 13 +++++++++++++ dlls/wined3d/device.c | 32 +++++++------------------------- dlls/wined3d/texture.c | 19 +++++++++++++++++++ dlls/wined3d/wined3d_private.h | 16 ++++++++++++++++ 4 files changed, 55 insertions(+), 25 deletions(-)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 7b8c8904961..33f2bf7994b 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -1080,6 +1080,14 @@ static void wined3d_buffer_init_data(struct wined3d_buffer *buffer, } }
+static struct wined3d_sub_resource *buffer_resource_get_sub_resource(struct wined3d_resource *resource, + unsigned int sub_resource_idx) +{ + if (!sub_resource_idx) + return &buffer_from_resource(resource)->sub_resource; + return NULL; +} + static ULONG buffer_resource_incref(struct wined3d_resource *resource) { return wined3d_buffer_incref(buffer_from_resource(resource)); @@ -1101,6 +1109,7 @@ static void buffer_resource_preload(struct wined3d_resource *resource)
static const struct wined3d_resource_ops buffer_resource_ops = { + buffer_resource_get_sub_resource, buffer_resource_incref, buffer_resource_decref, buffer_resource_preload, @@ -1209,6 +1218,10 @@ static HRESULT wined3d_buffer_init(struct wined3d_buffer *buffer, struct wined3d } buffer->maps_size = 1;
+ buffer->sub_resource.width = buffer->resource.size; + buffer->sub_resource.height = 1; + buffer->sub_resource.depth = 1; + if (data) wined3d_buffer_init_data(buffer, device, data);
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index a11f137729f..fa035af2e13 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4649,6 +4649,7 @@ void CDECL wined3d_device_context_update_sub_resource(struct wined3d_device_cont struct wined3d_resource *resource, unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, unsigned int depth_pitch, unsigned int flags) { + struct wined3d_sub_resource *sub_resource; unsigned int width, height, depth; struct wined3d_box b;
@@ -4664,34 +4665,15 @@ void CDECL wined3d_device_context_update_sub_resource(struct wined3d_device_cont return; }
- if (resource->type == WINED3D_RTYPE_BUFFER) + if (!(sub_resource = wined3d_resource_get_sub_resource(resource, sub_resource_idx))) { - if (sub_resource_idx > 0) - { - WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx); - return; - } - - width = resource->size; - height = 1; - depth = 1; + WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx); + return; } - else - { - struct wined3d_texture *texture = texture_from_resource(resource); - unsigned int level;
- if (sub_resource_idx >= texture->level_count * texture->layer_count) - { - WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx); - 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); - } + width = sub_resource->width; + height = sub_resource->height; + depth = sub_resource->depth;
if (!box) { diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index ad34e44b406..62788419ede 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -2006,6 +2006,10 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, unsig sub_resource->size = texture->slice_pitch; sub_resource->locations = WINED3D_LOCATION_DISCARDED;
+ sub_resource->sub_resource.width = wined3d_texture_get_level_width(texture, level); + sub_resource->sub_resource.height = wined3d_texture_get_level_height(texture, level); + sub_resource->sub_resource.depth = wined3d_texture_get_level_depth(texture, level); + wined3d_texture_get_map_pitch(texture, level, &sub_resource->map_row_pitch, &sub_resource->map_slice_pitch);
if (texture->texture_ops == &texture_gl_ops) @@ -3447,6 +3451,16 @@ struct wined3d_texture * __cdecl wined3d_texture_from_resource(struct wined3d_re return texture_from_resource(resource); }
+static struct wined3d_sub_resource *texture_resource_get_sub_resource(struct wined3d_resource *resource, + unsigned int sub_resource_idx) +{ + struct wined3d_texture *texture = texture_from_resource(resource); + + if (sub_resource_idx < texture->level_count * texture->layer_count) + return &texture->sub_resources[sub_resource_idx].sub_resource; + return NULL; +} + static ULONG texture_resource_incref(struct wined3d_resource *resource) { return wined3d_texture_incref(texture_from_resource(resource)); @@ -3697,6 +3711,7 @@ static HRESULT texture_resource_sub_resource_unmap(struct wined3d_resource *reso
static const struct wined3d_resource_ops texture_resource_ops = { + texture_resource_get_sub_resource, texture_resource_incref, texture_resource_decref, texture_resource_preload, @@ -3970,6 +3985,10 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc wined3d_texture_invalidate_location(texture, i, ~WINED3D_LOCATION_SYSMEM); }
+ sub_resource->sub_resource.width = wined3d_texture_get_level_width(texture, level); + sub_resource->sub_resource.height = wined3d_texture_get_level_height(texture, level); + sub_resource->sub_resource.depth = wined3d_texture_get_level_depth(texture, level); + wined3d_texture_get_map_pitch(texture, level, &sub_resource->map_row_pitch, &sub_resource->map_slice_pitch);
if (FAILED(hr = device_parent->ops->texture_sub_resource_created(device_parent, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 1e6a315e72c..dd73b564452 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4044,8 +4044,14 @@ static inline BOOL wined3d_resource_access_is_managed(unsigned int access) return !(~access & (WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU)); }
+struct wined3d_sub_resource +{ + unsigned int width, height, depth; +}; + struct wined3d_resource_ops { + struct wined3d_sub_resource *(*resource_get_sub_resource)(struct wined3d_resource *resource, unsigned int sub_resource_idx); ULONG (*resource_incref)(struct wined3d_resource *resource); ULONG (*resource_decref)(struct wined3d_resource *resource); void (*resource_preload)(struct wined3d_resource *resource); @@ -4110,6 +4116,12 @@ static inline void wined3d_resource_release(struct wined3d_resource *resource) InterlockedDecrement(&resource->access_count); }
+static inline struct wined3d_sub_resource *wined3d_resource_get_sub_resource(struct wined3d_resource *resource, + unsigned int sub_resource_idx) +{ + return resource->resource_ops->resource_get_sub_resource(resource, sub_resource_idx); +} + void resource_cleanup(struct wined3d_resource *resource) DECLSPEC_HIDDEN; HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *device, enum wined3d_resource_type type, const struct wined3d_format *format, @@ -4248,6 +4260,8 @@ struct wined3d_texture
struct wined3d_texture_sub_resource { + struct wined3d_sub_resource sub_resource; + void *parent; const struct wined3d_parent_ops *parent_ops;
@@ -4891,6 +4905,8 @@ struct wined3d_buffer UINT stride; /* 0 if no conversion */ enum wined3d_buffer_conversion_type *conversion_map; /* NULL if no conversion */ UINT conversion_stride; /* 0 if no shifted conversion */ + + struct wined3d_sub_resource sub_resource; };
static inline struct wined3d_buffer *buffer_from_resource(struct wined3d_resource *resource)
On Wed, 23 Jun 2021 at 23:39, Zebediah Figura z.figura12@gmail.com wrote:
I don't know if there's an advantage to caching these, although it seems plausible, but mostly this is just for ease of access.
Well, we already have wined3d_texture_get_sub_resource_desc(). We could certainly extend that to buffers and expose it through the resource ops.
About caching the values I mostly feel the same here as in patch 1/5; it's fine if it makes a performance difference, but otherwise it doesn't seem worth it.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/wined3d/buffer.c | 12 ------------ dlls/wined3d/device.c | 12 ++++++++++++ dlls/wined3d/texture.c | 6 ++---- 3 files changed, 14 insertions(+), 16 deletions(-)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 33f2bf7994b..28007076ea6 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -853,12 +853,6 @@ static HRESULT buffer_resource_sub_resource_map(struct wined3d_resource *resourc TRACE("resource %p, sub_resource_idx %u, map_desc %p, box %s, flags %#x.\n", resource, sub_resource_idx, map_desc, debug_box(box), flags);
- if (sub_resource_idx) - { - WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx); - return E_INVALIDARG; - } - if (box) { offset = box->left; @@ -973,12 +967,6 @@ static HRESULT buffer_resource_sub_resource_unmap(struct wined3d_resource *resou
TRACE("resource %p, sub_resource_idx %u.\n", resource, sub_resource_idx);
- if (sub_resource_idx) - { - WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx); - return E_INVALIDARG; - } - if (!resource->map_count) { WARN("Unmap called without a previous map call.\n"); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index fa035af2e13..8bb70ac77ab 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4865,6 +4865,12 @@ HRESULT CDECL wined3d_device_context_map(struct wined3d_device_context *context,
flags = sanitise_map_flags(resource, flags);
+ if (!wined3d_resource_get_sub_resource(resource, sub_resource_idx)) + { + WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx); + return E_INVALIDARG; + } + return context->ops->map(context, resource, sub_resource_idx, map_desc, box, flags); }
@@ -4873,6 +4879,12 @@ HRESULT CDECL wined3d_device_context_unmap(struct wined3d_device_context *contex { TRACE("context %p, resource %p, sub_resource_idx %u.\n", context, resource, sub_resource_idx);
+ if (!wined3d_resource_get_sub_resource(resource, sub_resource_idx)) + { + WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx); + return E_INVALIDARG; + } + return context->ops->unmap(context, resource, sub_resource_idx); }
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 62788419ede..d69adc4a315 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -3554,8 +3554,7 @@ static HRESULT texture_resource_sub_resource_map(struct wined3d_resource *resour resource, sub_resource_idx, map_desc, debug_box(box), flags);
texture = texture_from_resource(resource); - if (!(sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx))) - return E_INVALIDARG; + sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx);
texture_level = sub_resource_idx % texture->level_count; if (box && FAILED(wined3d_texture_check_box_dimensions(texture, texture_level, box))) @@ -3676,8 +3675,7 @@ static HRESULT texture_resource_sub_resource_unmap(struct wined3d_resource *reso TRACE("resource %p, sub_resource_idx %u.\n", resource, sub_resource_idx);
texture = texture_from_resource(resource); - if (!(sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx))) - return E_INVALIDARG; + sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx);
if (!sub_resource->map_count) {
On Wed, 23 Jun 2021 at 23:39, Zebediah Figura z.figura12@gmail.com wrote:
dlls/wined3d/buffer.c | 12 ------------ dlls/wined3d/device.c | 12 ++++++++++++ dlls/wined3d/texture.c | 6 ++---- 3 files changed, 14 insertions(+), 16 deletions(-)
I think it's fine to move sub_resource_idx validation to the upper layers, although we may not need wined3d_resource_get_sub_resource() for that. We could even go so far as to just require valid indices in the wined3d API and doing the validation in the client libraries.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/wined3d/buffer.c | 14 +++++++------- dlls/wined3d/cs.c | 18 ++++++++---------- dlls/wined3d/device.c | 12 ++++++++++-- dlls/wined3d/texture.c | 34 ++++++++++++++++++---------------- dlls/wined3d/wined3d_private.h | 8 +++----- 5 files changed, 46 insertions(+), 40 deletions(-)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 28007076ea6..5e98a1eb3df 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -841,7 +841,7 @@ struct wined3d_resource * CDECL wined3d_buffer_get_resource(struct wined3d_buffe }
static HRESULT buffer_resource_sub_resource_map(struct wined3d_resource *resource, unsigned int sub_resource_idx, - struct wined3d_map_desc *map_desc, const struct wined3d_box *box, uint32_t flags) + void **map_ptr, const struct wined3d_box *box, uint32_t flags) { struct wined3d_buffer *buffer = buffer_from_resource(resource); struct wined3d_device *device = resource->device; @@ -850,8 +850,8 @@ static HRESULT buffer_resource_sub_resource_map(struct wined3d_resource *resourc uint8_t *base; LONG count;
- TRACE("resource %p, sub_resource_idx %u, map_desc %p, box %s, flags %#x.\n", - resource, sub_resource_idx, map_desc, debug_box(box), flags); + TRACE("resource %p, sub_resource_idx %u, map_ptr %p, box %s, flags %#x.\n", + resource, sub_resource_idx, map_ptr, debug_box(box), flags);
if (box) { @@ -863,8 +863,6 @@ static HRESULT buffer_resource_sub_resource_map(struct wined3d_resource *resourc offset = size = 0; }
- map_desc->row_pitch = map_desc->slice_pitch = resource->size; - count = ++resource->map_count;
if (buffer->buffer_object) @@ -950,9 +948,9 @@ static HRESULT buffer_resource_sub_resource_map(struct wined3d_resource *resourc }
base = buffer->map_ptr ? buffer->map_ptr : resource->heap_memory; - map_desc->data = base + offset; + *map_ptr = base + offset;
- TRACE("Returning memory at %p (base %p, offset %u).\n", map_desc->data, base, offset); + TRACE("Returning memory at %p (base %p, offset %u).\n", *map_ptr, base, offset);
return WINED3D_OK; } @@ -1209,6 +1207,8 @@ static HRESULT wined3d_buffer_init(struct wined3d_buffer *buffer, struct wined3d buffer->sub_resource.width = buffer->resource.size; buffer->sub_resource.height = 1; buffer->sub_resource.depth = 1; + buffer->sub_resource.map_row_pitch = buffer->resource.size; + buffer->sub_resource.map_slice_pitch = buffer->resource.size;
if (data) wined3d_buffer_init_data(buffer, device, data); diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 544b76534d0..ad393c203c4 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -455,7 +455,7 @@ struct wined3d_cs_map enum wined3d_cs_op opcode; struct wined3d_resource *resource; unsigned int sub_resource_idx; - struct wined3d_map_desc *map_desc; + void **map_ptr; const struct wined3d_box *box; DWORD flags; HRESULT *hr; @@ -2402,12 +2402,11 @@ static void wined3d_cs_exec_map(struct wined3d_cs *cs, const void *data) struct wined3d_resource *resource = op->resource;
*op->hr = resource->resource_ops->resource_sub_resource_map(resource, - op->sub_resource_idx, op->map_desc, op->box, op->flags); + op->sub_resource_idx, op->map_ptr, op->box, op->flags); }
static HRESULT wined3d_cs_map(struct wined3d_device_context *context, struct wined3d_resource *resource, - unsigned int sub_resource_idx, struct wined3d_map_desc *map_desc, const struct wined3d_box *box, - unsigned int flags) + unsigned int sub_resource_idx, void **map_ptr, const struct wined3d_box *box, unsigned int flags) { struct wined3d_cs *cs = wined3d_cs_from_context(context); struct wined3d_cs_map *op; @@ -2423,7 +2422,7 @@ static HRESULT wined3d_cs_map(struct wined3d_device_context *context, struct win op->opcode = WINED3D_CS_OP_MAP; op->resource = resource; op->sub_resource_idx = sub_resource_idx; - op->map_desc = map_desc; + op->map_ptr = map_ptr; op->box = box; op->flags = flags; op->hr = &hr; @@ -3357,12 +3356,11 @@ static void wined3d_deferred_context_push_constants(struct wined3d_device_contex FIXME("context %p, p %#x, start_idx %u, count %u, constants %p, stub!\n", context, p, start_idx, count, constants); }
-static HRESULT wined3d_deferred_context_map(struct wined3d_device_context *context, - struct wined3d_resource *resource, unsigned int sub_resource_idx, - struct wined3d_map_desc *map_desc, const struct wined3d_box *box, unsigned int flags) +static HRESULT wined3d_deferred_context_map(struct wined3d_device_context *context, struct wined3d_resource *resource, + unsigned int sub_resource_idx, void **map_ptr, const struct wined3d_box *box, unsigned int flags) { - FIXME("context %p, resource %p, sub_resource_idx %u, map_desc %p, box %p, flags %#x, stub!\n", - context, resource, sub_resource_idx, map_desc, box, flags); + FIXME("context %p, resource %p, sub_resource_idx %u, map_ptr %p, box %p, flags %#x, stub!\n", + context, resource, sub_resource_idx, map_ptr, box, flags); return E_NOTIMPL; }
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 8bb70ac77ab..b93959089dd 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4842,6 +4842,9 @@ HRESULT CDECL wined3d_device_context_map(struct wined3d_device_context *context, struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_map_desc *map_desc, const struct wined3d_box *box, unsigned int flags) { + struct wined3d_sub_resource *sub_resource; + HRESULT hr; + TRACE("context %p, resource %p, sub_resource_idx %u, map_desc %p, box %s, flags %#x.\n", context, resource, sub_resource_idx, map_desc, debug_box(box), flags);
@@ -4865,13 +4868,18 @@ HRESULT CDECL wined3d_device_context_map(struct wined3d_device_context *context,
flags = sanitise_map_flags(resource, flags);
- if (!wined3d_resource_get_sub_resource(resource, sub_resource_idx)) + if (!(sub_resource = wined3d_resource_get_sub_resource(resource, sub_resource_idx))) { WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx); return E_INVALIDARG; }
- return context->ops->map(context, resource, sub_resource_idx, map_desc, box, flags); + if (SUCCEEDED(hr = context->ops->map(context, resource, sub_resource_idx, &map_desc->data, box, flags))) + { + map_desc->row_pitch = sub_resource->map_row_pitch; + map_desc->slice_pitch = sub_resource->map_slice_pitch; + } + return hr; }
HRESULT CDECL wined3d_device_context_unmap(struct wined3d_device_context *context, diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index d69adc4a315..c5074ed7c21 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -2010,7 +2010,8 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, unsig sub_resource->sub_resource.height = wined3d_texture_get_level_height(texture, level); sub_resource->sub_resource.depth = wined3d_texture_get_level_depth(texture, level);
- wined3d_texture_get_map_pitch(texture, level, &sub_resource->map_row_pitch, &sub_resource->map_slice_pitch); + wined3d_texture_get_map_pitch(texture, level, &sub_resource->sub_resource.map_row_pitch, + &sub_resource->sub_resource.map_slice_pitch);
if (texture->texture_ops == &texture_gl_ops) { @@ -3537,12 +3538,13 @@ static void texture_resource_unload(struct wined3d_resource *resource) }
static HRESULT texture_resource_sub_resource_map(struct wined3d_resource *resource, unsigned int sub_resource_idx, - struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) + void **map_ptr, const struct wined3d_box *box, DWORD flags) { const struct wined3d_format *format = resource->format; struct wined3d_texture_sub_resource *sub_resource; struct wined3d_device *device = resource->device; unsigned int fmt_flags = resource->format_flags; + unsigned int row_pitch, slice_pitch; struct wined3d_context *context; struct wined3d_texture *texture; struct wined3d_bo_address data; @@ -3550,8 +3552,8 @@ static HRESULT texture_resource_sub_resource_map(struct wined3d_resource *resour BYTE *base_memory; BOOL ret;
- TRACE("resource %p, sub_resource_idx %u, map_desc %p, box %s, flags %#x.\n", - resource, sub_resource_idx, map_desc, debug_box(box), flags); + TRACE("resource %p, sub_resource_idx %u, map_ptr %p, box %s, flags %#x.\n", + resource, sub_resource_idx, map_ptr, debug_box(box), flags);
texture = texture_from_resource(resource); sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx); @@ -3616,12 +3618,12 @@ static HRESULT texture_resource_sub_resource_map(struct wined3d_resource *resour
context_release(context);
- map_desc->row_pitch = sub_resource->map_row_pitch; - map_desc->slice_pitch = sub_resource->map_slice_pitch; + row_pitch = sub_resource->sub_resource.map_row_pitch; + slice_pitch = sub_resource->sub_resource.map_slice_pitch;
if (!box) { - map_desc->data = base_memory; + *map_ptr = base_memory; } else { @@ -3629,16 +3631,16 @@ static HRESULT texture_resource_sub_resource_map(struct wined3d_resource *resour { /* Compressed textures are block based, so calculate the offset of * the block that contains the top-left pixel of the mapped box. */ - map_desc->data = base_memory - + (box->front * map_desc->slice_pitch) - + ((box->top / format->block_height) * map_desc->row_pitch) + *map_ptr = base_memory + + (box->front * slice_pitch) + + ((box->top / format->block_height) * row_pitch) + ((box->left / format->block_width) * format->block_byte_count); } else { - map_desc->data = base_memory - + (box->front * map_desc->slice_pitch) - + (box->top * map_desc->row_pitch) + *map_ptr = base_memory + + (box->front * slice_pitch) + + (box->top * row_pitch) + (box->left * format->byte_count); } } @@ -3657,8 +3659,7 @@ static HRESULT texture_resource_sub_resource_map(struct wined3d_resource *resour ++resource->map_count; ++sub_resource->map_count;
- TRACE("Returning memory %p, row pitch %u, slice pitch %u.\n", - map_desc->data, map_desc->row_pitch, map_desc->slice_pitch); + TRACE("Returning memory %p.\n", *map_ptr);
return WINED3D_OK; } @@ -3987,7 +3988,8 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc sub_resource->sub_resource.height = wined3d_texture_get_level_height(texture, level); sub_resource->sub_resource.depth = wined3d_texture_get_level_depth(texture, level);
- wined3d_texture_get_map_pitch(texture, level, &sub_resource->map_row_pitch, &sub_resource->map_slice_pitch); + wined3d_texture_get_map_pitch(texture, level, &sub_resource->sub_resource.map_row_pitch, + &sub_resource->sub_resource.map_slice_pitch);
if (FAILED(hr = device_parent->ops->texture_sub_resource_created(device_parent, desc->resource_type, texture, i, &sub_resource->parent, &sub_resource->parent_ops))) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index dd73b564452..d6c526b2c6d 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4047,6 +4047,7 @@ static inline BOOL wined3d_resource_access_is_managed(unsigned int access) struct wined3d_sub_resource { unsigned int width, height, depth; + unsigned int map_row_pitch, map_slice_pitch; };
struct wined3d_resource_ops @@ -4057,7 +4058,7 @@ struct wined3d_resource_ops void (*resource_preload)(struct wined3d_resource *resource); void (*resource_unload)(struct wined3d_resource *resource); HRESULT (*resource_sub_resource_map)(struct wined3d_resource *resource, unsigned int sub_resource_idx, - struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags); + void **map_ptr, const struct wined3d_box *box, DWORD flags); HRESULT (*resource_sub_resource_unmap)(struct wined3d_resource *resource, unsigned int sub_resource_idx); };
@@ -4273,8 +4274,6 @@ struct wined3d_texture DWORD locations; struct wined3d_bo_gl bo;
- unsigned int map_row_pitch, map_slice_pitch; - void *user_memory; } *sub_resources; }; @@ -4701,8 +4700,7 @@ struct wined3d_device_context_ops void (*push_constants)(struct wined3d_device_context *context, enum wined3d_push_constants p, unsigned int start_idx, unsigned int count, const void *constants); HRESULT (*map)(struct wined3d_device_context *context, struct wined3d_resource *resource, - unsigned int sub_resource_idx, struct wined3d_map_desc *map_desc, const struct wined3d_box *box, - unsigned int flags); + unsigned int sub_resource_idx, void **map_ptr, const struct wined3d_box *box, unsigned int flags); HRESULT (*unmap)(struct wined3d_device_context *context, struct wined3d_resource *resource, unsigned int sub_resource_idx); void (*update_sub_resource)(struct wined3d_device_context *context, struct wined3d_resource *resource,
On Wed, 23 Jun 2021 at 23:39, Zebediah Figura z.figura12@gmail.com wrote:
dlls/wined3d/buffer.c | 14 +++++++------- dlls/wined3d/cs.c | 18 ++++++++---------- dlls/wined3d/device.c | 12 ++++++++++-- dlls/wined3d/texture.c | 34 ++++++++++++++++++---------------- dlls/wined3d/wined3d_private.h | 8 +++----- 5 files changed, 46 insertions(+), 40 deletions(-)
Why would we want that?
On 6/24/21 10:03 AM, Henri Verbeet wrote:
On Wed, 23 Jun 2021 at 23:39, Zebediah Figura z.figura12@gmail.com wrote:
dlls/wined3d/buffer.c | 14 +++++++------- dlls/wined3d/cs.c | 18 ++++++++---------- dlls/wined3d/device.c | 12 ++++++++++-- dlls/wined3d/texture.c | 34 ++++++++++++++++++---------------- dlls/wined3d/wined3d_private.h | 8 +++----- 5 files changed, 46 insertions(+), 40 deletions(-)
Why would we want that?
Same reason as most of the rest of this series; I'd like to allow for multiple mapping paths (e.g. alternatives to WINED3D_CS_OP_MAP) without having to duplicate a whole bunch of code.
Storing fields in wined3d_resource/wined3d_sub_resource is also nice because it means we don't need a bunch of extra branching or sub_resource_ops. But I guess it does take up more memory...
On Thu, 24 Jun 2021 at 17:51, Zebediah Figura (she/her) zfigura@codeweavers.com wrote:
On 6/24/21 10:03 AM, Henri Verbeet wrote:
On Wed, 23 Jun 2021 at 23:39, Zebediah Figura z.figura12@gmail.com wrote:
dlls/wined3d/buffer.c | 14 +++++++------- dlls/wined3d/cs.c | 18 ++++++++---------- dlls/wined3d/device.c | 12 ++++++++++-- dlls/wined3d/texture.c | 34 ++++++++++++++++++---------------- dlls/wined3d/wined3d_private.h | 8 +++----- 5 files changed, 46 insertions(+), 40 deletions(-)
Why would we want that?
Same reason as most of the rest of this series; I'd like to allow for multiple mapping paths (e.g. alternatives to WINED3D_CS_OP_MAP) without having to duplicate a whole bunch of code.
Actually, I looked at the subject more than the actual patch, and this initialises the map pitch in wined3d_texture_init(), instead of what I thought it did based on the description. That does make much more sense.
As for storing this information in the texture, it's perhaps worth pointing out that while dimensions, pitch, etc. are different between mip-levels, they're the same for each layer at a particular mip-level. At the same time, the maximum number of levels is much more limited than the maximum number of layers. E.g., GL_MAX_ARRAY_TEXTURE_LAYERS = 2048 here, while GL_MAX_TEXTURE_SIZE = 16384 would translate to 15 levels.
On 6/24/21 11:51 AM, Henri Verbeet wrote:
On Thu, 24 Jun 2021 at 17:51, Zebediah Figura (she/her) zfigura@codeweavers.com wrote:
On 6/24/21 10:03 AM, Henri Verbeet wrote:
On Wed, 23 Jun 2021 at 23:39, Zebediah Figura z.figura12@gmail.com wrote:
dlls/wined3d/buffer.c | 14 +++++++------- dlls/wined3d/cs.c | 18 ++++++++---------- dlls/wined3d/device.c | 12 ++++++++++-- dlls/wined3d/texture.c | 34 ++++++++++++++++++---------------- dlls/wined3d/wined3d_private.h | 8 +++----- 5 files changed, 46 insertions(+), 40 deletions(-)
Why would we want that?
Same reason as most of the rest of this series; I'd like to allow for multiple mapping paths (e.g. alternatives to WINED3D_CS_OP_MAP) without having to duplicate a whole bunch of code.
Actually, I looked at the subject more than the actual patch, and this initialises the map pitch in wined3d_texture_init(), instead of what I thought it did based on the description. That does make much more sense.
Sorry the patch subject is misleading. I'll see what I can do to improve it.
As for storing this information in the texture, it's perhaps worth pointing out that while dimensions, pitch, etc. are different between mip-levels, they're the same for each layer at a particular mip-level. At the same time, the maximum number of levels is much more limited than the maximum number of layers. E.g., GL_MAX_ARRAY_TEXTURE_LAYERS = 2048 here, while GL_MAX_TEXTURE_SIZE = 16384 would translate to 15 levels.
I'll see what I can come up with along the lines of not using more memory; I think with the right set of helpers it should be relatively painless. Especially if we can move things like level_count and layer_count to wined3d_resource (granted, that does take up a couple of extra bytes per buffer, but I'm guessing that's less of a concern...)
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/wined3d/buffer.c | 11 ++--------- dlls/wined3d/device.c | 7 +++++++ dlls/wined3d/texture.c | 36 +++++++++++++----------------------- 3 files changed, 22 insertions(+), 32 deletions(-)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 5e98a1eb3df..a37071a5b9c 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -853,15 +853,8 @@ static HRESULT buffer_resource_sub_resource_map(struct wined3d_resource *resourc TRACE("resource %p, sub_resource_idx %u, map_ptr %p, box %s, flags %#x.\n", resource, sub_resource_idx, map_ptr, debug_box(box), flags);
- if (box) - { - offset = box->left; - size = box->right - box->left; - } - else - { - offset = size = 0; - } + offset = box->left; + size = box->right - box->left;
count = ++resource->map_count;
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index b93959089dd..aa26e1528fb 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4843,6 +4843,7 @@ HRESULT CDECL wined3d_device_context_map(struct wined3d_device_context *context, struct wined3d_map_desc *map_desc, const struct wined3d_box *box, unsigned int flags) { struct wined3d_sub_resource *sub_resource; + struct wined3d_box b; HRESULT hr;
TRACE("context %p, resource %p, sub_resource_idx %u, map_desc %p, box %s, flags %#x.\n", @@ -4874,6 +4875,12 @@ HRESULT CDECL wined3d_device_context_map(struct wined3d_device_context *context, return E_INVALIDARG; }
+ if (!box) + { + wined3d_box_set(&b, 0, 0, sub_resource->width, sub_resource->height, 0, sub_resource->depth); + box = &b; + } + if (SUCCEEDED(hr = context->ops->map(context, resource, sub_resource_idx, &map_desc->data, box, flags))) { map_desc->row_pitch = sub_resource->map_row_pitch; diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index c5074ed7c21..470bbc677bc 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -3559,7 +3559,7 @@ static HRESULT texture_resource_sub_resource_map(struct wined3d_resource *resour sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx);
texture_level = sub_resource_idx % texture->level_count; - if (box && FAILED(wined3d_texture_check_box_dimensions(texture, texture_level, box))) + if (FAILED(wined3d_texture_check_box_dimensions(texture, texture_level, box))) { WARN("Map box is invalid.\n"); if (((fmt_flags & WINED3DFMT_FLAG_BLOCKS) && !(resource->access & WINED3D_RESOURCE_ACCESS_CPU)) @@ -3621,38 +3621,28 @@ static HRESULT texture_resource_sub_resource_map(struct wined3d_resource *resour row_pitch = sub_resource->sub_resource.map_row_pitch; slice_pitch = sub_resource->sub_resource.map_slice_pitch;
- if (!box) + if ((fmt_flags & (WINED3DFMT_FLAG_BLOCKS | WINED3DFMT_FLAG_BROKEN_PITCH)) == WINED3DFMT_FLAG_BLOCKS) { - *map_ptr = base_memory; + /* Compressed textures are block based, so calculate the offset of + * the block that contains the top-left pixel of the mapped box. */ + *map_ptr = base_memory + + (box->front * slice_pitch) + + ((box->top / format->block_height) * row_pitch) + + ((box->left / format->block_width) * format->block_byte_count); } else { - if ((fmt_flags & (WINED3DFMT_FLAG_BLOCKS | WINED3DFMT_FLAG_BROKEN_PITCH)) == WINED3DFMT_FLAG_BLOCKS) - { - /* Compressed textures are block based, so calculate the offset of - * the block that contains the top-left pixel of the mapped box. */ - *map_ptr = base_memory - + (box->front * slice_pitch) - + ((box->top / format->block_height) * row_pitch) - + ((box->left / format->block_width) * format->block_byte_count); - } - else - { - *map_ptr = base_memory - + (box->front * slice_pitch) - + (box->top * row_pitch) - + (box->left * format->byte_count); - } + *map_ptr = base_memory + + (box->front * slice_pitch) + + (box->top * row_pitch) + + (box->left * format->byte_count); }
if (texture->swapchain && texture->swapchain->front_buffer == texture) { RECT *r = &texture->swapchain->front_buffer_update;
- if (!box) - SetRect(r, 0, 0, resource->width, resource->height); - else - SetRect(r, box->left, box->top, box->right, box->bottom); + SetRect(r, box->left, box->top, box->right, box->bottom); TRACE("Mapped front buffer %s.\n", wine_dbgstr_rect(r)); }
On Wed, 23 Jun 2021 at 23:39, Zebediah Figura z.figura12@gmail.com wrote:
+static void wined3d_texture_get_map_pitch(const struct wined3d_texture *texture,
unsigned int level, unsigned int *row_pitch, unsigned int *slice_pitch)
+{
- if (texture->resource.format_flags & WINED3DFMT_FLAG_BROKEN_PITCH)
- {
*row_pitch = wined3d_texture_get_level_width(texture, level) * texture->resource.format->byte_count;
*slice_pitch = wined3d_texture_get_level_height(texture, level) * (*row_pitch);
- }
- else
- {
wined3d_texture_get_pitch(texture, level, row_pitch, slice_pitch);
- }
+}
The helper seems fine, although the reason we don't already have one is that it's really only needed in a single place.
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index da1cf638606..1e6a315e72c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4259,6 +4259,8 @@ struct wined3d_texture DWORD locations; struct wined3d_bo_gl bo;
unsigned int map_row_pitch, map_slice_pitch;
} *sub_resources;void *user_memory;
};
I'm not as convinced about storing the pitch in the wined3d_texture_sub_resource structure though. The cost of calculating the pitch seems insignificant compared to the cost of actually mapping the resource, and with large texture arrays there can be quite a number of sub-resources here, so there's a memory cost to balance this against as well. That said, if this ends up making a difference in e.g. benchmarks I'd find that sufficient justification.