[PATCH 2/2] wined3d: Implement wined3d_deferred_context_map().
Zebediah Figura
z.figura12 at gmail.com
Fri May 28 00:21:27 CDT 2021
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
dlls/d3d11/tests/d3d11.c | 15 +---
dlls/wined3d/buffer.c | 14 ++++
dlls/wined3d/cs.c | 136 ++++++++++++++++++++++++++++++---
dlls/wined3d/resource.c | 29 +++----
dlls/wined3d/texture.c | 25 ++++++
dlls/wined3d/wined3d_private.h | 5 ++
6 files changed, 189 insertions(+), 35 deletions(-)
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c
index 408c0492cd2..a2fdc116e61 100644
--- a/dlls/d3d11/tests/d3d11.c
+++ b/dlls/d3d11/tests/d3d11.c
@@ -32735,21 +32735,14 @@ static void test_deferred_context_map(void)
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = ID3D11DeviceContext_Map(deferred, (ID3D11Resource *)buffer, 0, D3D11_MAP_WRITE, 0, &map_desc);
- todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
+ ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = ID3D11DeviceContext_Map(deferred, (ID3D11Resource *)buffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &map_desc);
- todo_wine ok(hr == D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD, "Got unexpected hr %#x.\n", hr);
+ ok(hr == D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD, "Got unexpected hr %#x.\n", hr);
hr = ID3D11DeviceContext_Map(deferred, (ID3D11Resource *)buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc);
- todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
- if (hr != S_OK)
- {
- ID3D11Buffer_Release(buffer2);
- ID3D11Buffer_Release(buffer);
- ID3D11DeviceContext_Release(deferred);
- release_test_context(&test_context);
- return;
- }
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+
map_data = map_desc.pData;
/* The previous contents of map_data are undefined and may in practice be
* uninitialized garbage. */
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 12d038c0120..12b90cb54c2 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -826,6 +826,19 @@ struct wined3d_resource * CDECL wined3d_buffer_get_resource(struct wined3d_buffe
return &buffer->resource;
}
+static HRESULT buffer_resource_sub_resource_get_size(struct wined3d_resource *resource,
+ unsigned int sub_resource_idx, unsigned int *size, unsigned int *row_pitch, unsigned int *slice_pitch)
+{
+ if (sub_resource_idx)
+ {
+ WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
+ return E_INVALIDARG;
+ }
+
+ *size = *row_pitch = *slice_pitch = resource->size;
+ return S_OK;
+}
+
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)
{
@@ -1084,6 +1097,7 @@ static const struct wined3d_resource_ops buffer_resource_ops =
buffer_resource_decref,
buffer_resource_preload,
buffer_resource_unload,
+ buffer_resource_sub_resource_get_size,
buffer_resource_sub_resource_map,
buffer_resource_sub_resource_unmap,
};
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index e6f84134795..1f7213232fa 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -26,6 +26,13 @@ WINE_DECLARE_DEBUG_CHANNEL(fps);
#define WINED3D_INITIAL_CS_SIZE 4096
+struct wined3d_acquired_resource
+{
+ struct wined3d_resource *resource;
+ unsigned int sub_resource_idx;
+ void *sysmem;
+};
+
struct wined3d_command_list
{
LONG refcount;
@@ -36,7 +43,7 @@ struct wined3d_command_list
void *data;
SIZE_T resource_count;
- struct wined3d_resource **resources;
+ struct wined3d_acquired_resource *resources;
/* List of command lists queued for execution on this command list. We might
* be the only thing holding a pointer to another command list, so we need
@@ -48,9 +55,13 @@ struct wined3d_command_list
static void wined3d_command_list_destroy_object(void *object)
{
struct wined3d_command_list *list = object;
+ SIZE_T i;
TRACE("list %p.\n", list);
+ for (i = 0; i < list->resource_count; ++i)
+ wined3d_free_sysmem(list->resources[i].sysmem);
+
heap_free(list->resources);
heap_free(list->data);
heap_free(list);
@@ -79,7 +90,7 @@ ULONG CDECL wined3d_command_list_decref(struct wined3d_command_list *list)
for (i = 0; i < list->command_list_count; ++i)
wined3d_command_list_decref(list->command_lists[i]);
for (i = 0; i < list->resource_count; ++i)
- wined3d_resource_decref(list->resources[i]);
+ wined3d_resource_decref(list->resources[i].resource);
wined3d_cs_destroy_object(device->cs, wined3d_command_list_destroy_object, list);
}
@@ -139,6 +150,7 @@ enum wined3d_cs_op
WINED3D_CS_OP_COPY_UAV_COUNTER,
WINED3D_CS_OP_GENERATE_MIPMAPS,
WINED3D_CS_OP_EXECUTE_COMMAND_LIST,
+ WINED3D_CS_OP_UPLOAD_SUB_RESOURCE,
WINED3D_CS_OP_STOP,
};
@@ -469,6 +481,15 @@ struct wined3d_cs_unmap
HRESULT *hr;
};
+struct wined3d_cs_upload_sub_resource
+{
+ enum wined3d_cs_op opcode;
+ struct wined3d_resource *resource;
+ unsigned int sub_resource_idx;
+ unsigned int size;
+ const void *data;
+};
+
struct wined3d_cs_blt_sub_resource
{
enum wined3d_cs_op opcode;
@@ -616,6 +637,7 @@ static const char *debug_cs_op(enum wined3d_cs_op op)
WINED3D_TO_STR(WINED3D_CS_OP_COPY_UAV_COUNTER);
WINED3D_TO_STR(WINED3D_CS_OP_GENERATE_MIPMAPS);
WINED3D_TO_STR(WINED3D_CS_OP_EXECUTE_COMMAND_LIST);
+ WINED3D_TO_STR(WINED3D_CS_OP_UPLOAD_SUB_RESOURCE);
WINED3D_TO_STR(WINED3D_CS_OP_STOP);
#undef WINED3D_TO_STR
}
@@ -2342,7 +2364,7 @@ static void wined3d_cs_execute_command_list(struct wined3d_device_context *conte
op->list = list;
for (i = 0; i < list->resource_count; ++i)
- wined3d_resource_acquire(list->resources[i]);
+ wined3d_resource_acquire(list->resources[i].resource);
wined3d_device_context_submit(context, WINED3D_CS_QUEUE_DEFAULT);
@@ -2463,6 +2485,28 @@ static HRESULT wined3d_cs_unmap(struct wined3d_device_context *context, struct w
return hr;
}
+static void wined3d_cs_exec_upload_sub_resource(struct wined3d_cs *cs, const void *data)
+{
+ const struct wined3d_cs_upload_sub_resource *op = data;
+ struct wined3d_resource *resource = op->resource;
+ unsigned int sub_resource_idx = op->sub_resource_idx;
+ struct wined3d_map_desc map_desc;
+ HRESULT hr;
+
+ if (FAILED(hr = resource->resource_ops->resource_sub_resource_map(resource,
+ sub_resource_idx, &map_desc, NULL, WINED3D_MAP_WRITE | WINED3D_MAP_DISCARD)))
+ {
+ ERR("Failed to map resource, hr %#x.\n", hr);
+ return;
+ }
+
+ memcpy(map_desc.data, op->data, op->size);
+
+ resource->resource_ops->resource_sub_resource_unmap(resource, sub_resource_idx);
+
+ wined3d_resource_release(resource);
+}
+
static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void *data)
{
const struct wined3d_cs_blt_sub_resource *op = data;
@@ -2870,6 +2914,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
/* WINED3D_CS_OP_COPY_UAV_COUNTER */ wined3d_cs_exec_copy_uav_counter,
/* WINED3D_CS_OP_GENERATE_MIPMAPS */ wined3d_cs_exec_generate_mipmaps,
/* WINED3D_CS_OP_EXECUTE_COMMAND_LIST */ wined3d_cs_exec_execute_command_list,
+ /* WINED3D_CS_OP_UPLOAD_SUB_RESOURCE */ wined3d_cs_exec_upload_sub_resource,
};
static void wined3d_cs_exec_execute_command_list(struct wined3d_cs *cs, const void *data)
@@ -3301,7 +3346,7 @@ struct wined3d_deferred_context
void *data;
SIZE_T resource_count, resources_capacity;
- struct wined3d_resource **resources;
+ struct wined3d_acquired_resource *resources;
/* List of command lists queued for execution on this context. A command
* list can be the only thing holding a pointer to another command list, so
@@ -3361,16 +3406,78 @@ static HRESULT wined3d_deferred_context_map(struct wined3d_device_context *conte
struct wined3d_resource *resource, unsigned int sub_resource_idx,
struct wined3d_map_desc *map_desc, 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);
- return E_NOTIMPL;
+ struct wined3d_deferred_context *deferred = wined3d_deferred_context_from_context(context);
+ struct wined3d_acquired_resource *acquired_resource;
+ unsigned int size;
+ HRESULT hr;
+
+ if (box)
+ {
+ ERR("Unexpected box.\n");
+ return E_INVALIDARG;
+ }
+
+ if (FAILED(hr = resource->resource_ops->resource_sub_resource_get_size(resource,
+ sub_resource_idx, &size, &map_desc->row_pitch, &map_desc->slice_pitch)))
+ return E_INVALIDARG;
+
+ if (flags & WINED3D_MAP_DISCARD)
+ {
+ struct wined3d_cs_upload_sub_resource *op;
+ void *sysmem;
+
+ if (!(sysmem = wined3d_allocate_sysmem(size)))
+ return E_OUTOFMEMORY;
+
+ if (!wined3d_array_reserve((void **)&deferred->resources, &deferred->resources_capacity,
+ deferred->resource_count + 1, sizeof(*deferred->resources)))
+ return E_OUTOFMEMORY;
+
+ acquired_resource = &deferred->resources[deferred->resource_count++];
+ acquired_resource->resource = resource;
+ wined3d_resource_incref(resource);
+ acquired_resource->sub_resource_idx = sub_resource_idx;
+ acquired_resource->sysmem = sysmem;
+
+ op = wined3d_device_context_require_space(context, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT);
+ op->opcode = WINED3D_CS_OP_UPLOAD_SUB_RESOURCE;
+ op->resource = resource;
+ op->sub_resource_idx = sub_resource_idx;
+ op->size = size;
+ op->data = sysmem;
+
+ map_desc->data = sysmem;
+ return S_OK;
+ }
+ else if (flags & WINED3D_MAP_NOOVERWRITE)
+ {
+ int i = deferred->resource_count;
+
+ while (i--)
+ {
+ acquired_resource = &deferred->resources[i];
+
+ if (acquired_resource->resource == resource
+ && acquired_resource->sub_resource_idx == sub_resource_idx && acquired_resource->sysmem)
+ {
+ map_desc->data = acquired_resource->sysmem;
+ return S_OK;
+ }
+ }
+
+ return D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD;
+ }
+ else
+ {
+ WARN("Invalid flags %#x, returning E_INVALIDARG.\n", flags);
+ return E_INVALIDARG;
+ }
}
static HRESULT wined3d_deferred_context_unmap(struct wined3d_device_context *context,
struct wined3d_resource *resource, unsigned int sub_resource_idx)
{
- FIXME("context %p, resource %p, sub_resource_idx %u, stub!\n", context, resource, sub_resource_idx);
- return E_NOTIMPL;
+ return S_OK;
}
static void wined3d_deferred_context_update_sub_resource(struct wined3d_device_context *context,
@@ -3423,13 +3530,17 @@ static void wined3d_deferred_context_acquire_resource(struct wined3d_device_cont
struct wined3d_resource *resource)
{
struct wined3d_deferred_context *deferred = wined3d_deferred_context_from_context(context);
+ struct wined3d_acquired_resource *acquired_resource;
if (!wined3d_array_reserve((void **)&deferred->resources, &deferred->resources_capacity,
deferred->resource_count + 1, sizeof(*deferred->resources)))
return;
- deferred->resources[deferred->resource_count++] = resource;
+ acquired_resource = &deferred->resources[deferred->resource_count++];
+ acquired_resource->resource = resource;
wined3d_resource_incref(resource);
+ acquired_resource->sub_resource_idx = 0;
+ acquired_resource->sysmem = NULL;
}
static void wined3d_deferred_context_execute_command_list(struct wined3d_device_context *context,
@@ -3504,7 +3615,10 @@ void CDECL wined3d_deferred_context_destroy(struct wined3d_device_context *conte
TRACE("context %p.\n", context);
for (i = 0; i < deferred->resource_count; ++i)
- wined3d_resource_decref(deferred->resources[i]);
+ {
+ wined3d_resource_decref(deferred->resources[i].resource);
+ wined3d_free_sysmem(deferred->resources[i].sysmem);
+ }
heap_free(deferred->resources);
wined3d_state_destroy(deferred->c.state);
diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c
index 58e3e5c77fd..42e45a2745c 100644
--- a/dlls/wined3d/resource.c
+++ b/dlls/wined3d/resource.c
@@ -334,24 +334,32 @@ void CDECL wined3d_resource_preload(struct wined3d_resource *resource)
wined3d_cs_emit_preload_resource(resource->device->cs, resource);
}
-static BOOL wined3d_resource_allocate_sysmem(struct wined3d_resource *resource)
+void *wined3d_allocate_sysmem(SIZE_T size)
{
void **p;
- SIZE_T align = RESOURCE_ALIGNMENT - 1 + sizeof(*p);
+ static const SIZE_T align = RESOURCE_ALIGNMENT - 1 + sizeof(*p);
void *mem;
- if (!(mem = heap_alloc_zero(resource->size + align)))
+ if (!(mem = heap_alloc_zero(size + align)))
{
ERR("Failed to allocate system memory.\n");
- return FALSE;
+ return NULL;
}
p = (void **)(((ULONG_PTR)mem + align) & ~(RESOURCE_ALIGNMENT - 1)) - 1;
*p = mem;
- resource->heap_memory = ++p;
+ return ++p;
+}
- return TRUE;
+void wined3d_free_sysmem(void *mem)
+{
+ void **p = mem;
+
+ if (!p)
+ return;
+
+ heap_free(*(--p));
}
BOOL wined3d_resource_prepare_sysmem(struct wined3d_resource *resource)
@@ -359,17 +367,12 @@ BOOL wined3d_resource_prepare_sysmem(struct wined3d_resource *resource)
if (resource->heap_memory)
return TRUE;
- return wined3d_resource_allocate_sysmem(resource);
+ return !!(resource->heap_memory = wined3d_allocate_sysmem(resource->size));
}
void wined3d_resource_free_sysmem(struct wined3d_resource *resource)
{
- void **p = resource->heap_memory;
-
- if (!p)
- return;
-
- heap_free(*(--p));
+ wined3d_free_sysmem(resource->heap_memory);
resource->heap_memory = NULL;
}
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index c7a9b4da3e1..663503bdf39 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -3506,6 +3506,30 @@ static void texture_resource_unload(struct wined3d_resource *resource)
resource_unload(&texture->resource);
}
+static HRESULT texture_resource_sub_resource_get_size(struct wined3d_resource *resource,
+ unsigned int sub_resource_idx, unsigned int *size, unsigned int *row_pitch, unsigned int *slice_pitch)
+{
+ struct wined3d_texture *texture = texture_from_resource(resource);
+ unsigned int texture_level = sub_resource_idx % texture->level_count;
+ struct wined3d_texture_sub_resource *sub_resource;
+
+ if (!(sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx)))
+ return E_INVALIDARG;
+
+ if (resource->format_flags & WINED3DFMT_FLAG_BROKEN_PITCH)
+ {
+ *row_pitch = wined3d_texture_get_level_width(texture, texture_level) * resource->format->byte_count;
+ *slice_pitch = wined3d_texture_get_level_height(texture, texture_level) * (*row_pitch);
+ }
+ else
+ {
+ wined3d_texture_get_pitch(texture, texture_level, row_pitch, slice_pitch);
+ }
+
+ *size = sub_resource->size;
+ return S_OK;
+}
+
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)
{
@@ -3692,6 +3716,7 @@ static const struct wined3d_resource_ops texture_resource_ops =
texture_resource_decref,
texture_resource_preload,
texture_resource_unload,
+ texture_resource_sub_resource_get_size,
texture_resource_sub_resource_map,
texture_resource_sub_resource_unmap,
};
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 8e3efccffc2..db6e1619e8f 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -4048,6 +4048,8 @@ struct wined3d_resource_ops
ULONG (*resource_decref)(struct wined3d_resource *resource);
void (*resource_preload)(struct wined3d_resource *resource);
void (*resource_unload)(struct wined3d_resource *resource);
+ HRESULT (*resource_sub_resource_get_size)(struct wined3d_resource *resource, unsigned int sub_resource_idx,
+ unsigned int *size, unsigned int *row_pitch, unsigned int *slice_pitch);
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);
HRESULT (*resource_sub_resource_unmap)(struct wined3d_resource *resource, unsigned int sub_resource_idx);
@@ -4131,6 +4133,9 @@ void wined3d_resource_update_draw_binding(struct wined3d_resource *resource) DEC
#define RESOURCE_ALIGNMENT 16
#define WINED3D_CONSTANT_BUFFER_ALIGNMENT 16
+void *wined3d_allocate_sysmem(SIZE_T size) DECLSPEC_HIDDEN;
+void wined3d_free_sysmem(void *mem) DECLSPEC_HIDDEN;
+
#define WINED3D_LOCATION_DISCARDED 0x00000001
#define WINED3D_LOCATION_SYSMEM 0x00000002
#define WINED3D_LOCATION_BUFFER 0x00000008
--
2.30.2
More information about the wine-devel
mailing list