Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/texture.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 1323d533eff..64cc7c8c3eb 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -789,6 +789,19 @@ BOOL wined3d_texture_load_location(struct wined3d_texture *texture, return TRUE; }
+ if (current & WINED3D_LOCATION_CLEARED) + { + struct wined3d_bo_address addr; + + /* FIXME: Clear textures on the GPU if possible. */ + + if (!wined3d_texture_prepare_location(texture, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM)) + return FALSE; + wined3d_texture_get_memory(texture, sub_resource_idx, &addr, WINED3D_LOCATION_SYSMEM); + memset(addr.addr, 0, texture->sub_resources[sub_resource_idx].size); + current = WINED3D_LOCATION_SYSMEM; + } + if (!current) { ERR("Sub-resource %u of texture %p does not have any up to date location.\n",
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ddraw/tests/ddraw1.c | 4 ++-- dlls/ddraw/tests/ddraw2.c | 4 ++-- dlls/ddraw/tests/ddraw4.c | 4 ++-- dlls/ddraw/tests/ddraw7.c | 4 ++-- dlls/wined3d/texture.c | 17 +---------------- 5 files changed, 9 insertions(+), 24 deletions(-)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c index e0393a3a591..30fadeb7a88 100644 --- a/dlls/ddraw/tests/ddraw1.c +++ b/dlls/ddraw/tests/ddraw1.c @@ -10101,9 +10101,9 @@ static void test_yv12_overlay(void) base = desc.lpSurface; ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]); base += desc.dwHeight * U1(desc).lPitch; - todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]); + ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]); base += desc.dwHeight / 4 * U1(desc).lPitch; - todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]); + ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
hr = IDirectDrawSurface_Unlock(dst_surface, NULL); ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c index 03f1d488673..96da40ac838 100644 --- a/dlls/ddraw/tests/ddraw2.c +++ b/dlls/ddraw/tests/ddraw2.c @@ -10934,9 +10934,9 @@ static void test_yv12_overlay(void) base = desc.lpSurface; ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]); base += desc.dwHeight * U1(desc).lPitch; - todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]); + ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]); base += desc.dwHeight / 4 * U1(desc).lPitch; - todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]); + ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
hr = IDirectDrawSurface_Unlock(dst_surface, NULL); ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index 858d39e6f8e..d9f0f43130c 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -12893,9 +12893,9 @@ static void test_yv12_overlay(void) base = desc.lpSurface; ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]); base += desc.dwHeight * U1(desc).lPitch; - todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]); + ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]); base += desc.dwHeight / 4 * U1(desc).lPitch; - todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]); + ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
hr = IDirectDrawSurface4_Unlock(dst_surface, NULL); ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index d448bd76c01..d510a8e4ee7 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -12885,9 +12885,9 @@ static void test_yv12_overlay(void) base = desc.lpSurface; ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]); base += desc.dwHeight * U1(desc).lPitch; - todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]); + ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]); base += desc.dwHeight / 4 * U1(desc).lPitch; - todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]); + ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
hr = IDirectDrawSurface7_Unlock(dst_surface, NULL); ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 64cc7c8c3eb..7703de6c4ef 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -3888,16 +3888,6 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc if (wined3d_texture_use_pbo(texture, d3d_info)) texture->resource.map_binding = WINED3D_LOCATION_BUFFER;
- if (desc->resource_type != WINED3D_RTYPE_TEXTURE_3D - || !wined3d_texture_use_pbo(texture, d3d_info)) - { - if (!wined3d_resource_prepare_sysmem(&texture->resource)) - { - wined3d_texture_cleanup_sync(texture); - return E_OUTOFMEMORY; - } - } - sub_count = level_count * layer_count; if (sub_count / layer_count != level_count) { @@ -3926,12 +3916,7 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc struct wined3d_texture_sub_resource *sub_resource;
sub_resource = &texture->sub_resources[i]; - sub_resource->locations = WINED3D_LOCATION_DISCARDED; - if (desc->resource_type != WINED3D_RTYPE_TEXTURE_3D) - { - wined3d_texture_validate_location(texture, i, WINED3D_LOCATION_SYSMEM); - wined3d_texture_invalidate_location(texture, i, ~WINED3D_LOCATION_SYSMEM); - } + sub_resource->locations = WINED3D_LOCATION_CLEARED;
if (FAILED(hr = device_parent->ops->texture_sub_resource_created(device_parent, desc->resource_type, texture, i, &sub_resource->parent, &sub_resource->parent_ops)))
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=108708
Your paranoid android.
=== w8 (32 bit report) ===
ddraw: ddraw7.c:18858: Test failed: Got unexpected color 0x00000040.
=== w8adm (32 bit report) ===
ddraw: ddraw7.c:18858: Test failed: Got unexpected color 0x0000ff00.
=== w1064v1809 (32 bit report) ===
ddraw: ddraw7.c:18858: Test failed: Got unexpected color 0x0000ff00.
=== w1064_tsign (32 bit report) ===
ddraw: ddraw7.c:18858: Test failed: Got unexpected color 0x00000040.
=== debian11 (32 bit Chinese:China report) ===
Report validation errors: ddraw1: Timeout
=== debian11 (build log) ===
WineRunWineTest.pl:error: The task timed out
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/cs.c | 30 ++---------------------------- dlls/wined3d/texture.c | 26 ++++++++++++++++++++++++++ dlls/wined3d/wined3d_private.h | 3 +++ 3 files changed, 31 insertions(+), 28 deletions(-)
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index ae1f4ad18e0..81cdb51f207 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -2741,43 +2741,17 @@ static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const voi const struct wined3d_cs_update_sub_resource *op = data; struct wined3d_resource *resource = op->resource; const struct wined3d_box *box = &op->box; - unsigned int width, height, depth, level; struct wined3d_context *context; - struct wined3d_texture *texture; - struct wined3d_box src_box;
context = context_acquire(cs->c.device, NULL, 0);
if (resource->type == WINED3D_RTYPE_BUFFER) - { wined3d_buffer_update_sub_resource(buffer_from_resource(resource), context, &op->bo, box->left, box->right - box->left); - goto done; - } - - texture = wined3d_texture_from_resource(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); - - /* 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_location(texture, op->sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); else - wined3d_texture_load_location(texture, op->sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); - - wined3d_box_set(&src_box, 0, 0, box->right - box->left, box->bottom - box->top, 0, box->back - box->front); - texture->texture_ops->texture_upload_data(context, &op->bo.addr, texture->resource.format, &src_box, - op->row_pitch, op->slice_pitch, texture, op->sub_resource_idx, - WINED3D_LOCATION_TEXTURE_RGB, box->left, box->top, box->front); - - 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); + wined3d_texture_update_sub_resource(texture_from_resource(resource), + op->sub_resource_idx, context, &op->bo, box, op->row_pitch, op->slice_pitch);
-done: context_release(context);
wined3d_resource_release(resource); diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 7703de6c4ef..c1d04ceb119 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -4531,6 +4531,32 @@ void wined3d_texture_download_from_texture(struct wined3d_texture *dst_texture, wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~dst_location); }
+void wined3d_texture_update_sub_resource(struct wined3d_texture *texture, unsigned int sub_resource_idx, + struct wined3d_context *context, const struct upload_bo *upload_bo, const struct wined3d_box *box, + unsigned int row_pitch, unsigned int slice_pitch) +{ + unsigned int level = sub_resource_idx % texture->level_count; + unsigned int width = wined3d_texture_get_level_width(texture, level); + unsigned int height = wined3d_texture_get_level_height(texture, level); + unsigned int depth = wined3d_texture_get_level_depth(texture, level); + struct wined3d_box src_box; + + /* 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_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); + else + wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); + + wined3d_box_set(&src_box, 0, 0, box->right - box->left, box->bottom - box->top, 0, box->back - box->front); + texture->texture_ops->texture_upload_data(context, &upload_bo->addr, texture->resource.format, + &src_box, row_pitch, slice_pitch, texture, sub_resource_idx, + WINED3D_LOCATION_TEXTURE_RGB, box->left, box->top, box->front); + + wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB); + wined3d_texture_invalidate_location(texture, sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB); +} + static void wined3d_texture_no3d_upload_data(struct wined3d_context *context, const struct wined3d_const_bo_address *src_bo_addr, const struct wined3d_format *src_format, const struct wined3d_box *src_box, unsigned int src_row_pitch, unsigned int src_slice_pitch, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 989fd33d2bf..277d5a94fb0 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4643,6 +4643,9 @@ BOOL wined3d_texture_can_use_pbo(const struct wined3d_texture *texture, const st void wined3d_texture_sub_resources_destroyed(struct wined3d_texture *texture) DECLSPEC_HIDDEN; void wined3d_texture_translate_drawable_coords(const struct wined3d_texture *texture, HWND window, RECT *rect) DECLSPEC_HIDDEN; +void wined3d_texture_update_sub_resource(struct wined3d_texture *texture, unsigned int sub_resource_idx, + struct wined3d_context *context, const struct upload_bo *upload_bo, const struct wined3d_box *box, + unsigned int row_pitch, unsigned int slice_pitch) DECLSPEC_HIDDEN; void wined3d_texture_upload_from_texture(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, const struct wined3d_box *src_box) DECLSPEC_HIDDEN;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/texture.c | 41 ++++++++++++++++++++++++---------- dlls/wined3d/wined3d_private.h | 7 +----- 2 files changed, 30 insertions(+), 18 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index c1d04ceb119..9b32b9f3d1a 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -845,7 +845,7 @@ void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int su if (locations & WINED3D_LOCATION_BUFFER) { data->addr = NULL; - data->buffer_object = &sub_resource->bo.b; + data->buffer_object = sub_resource->bo; return; }
@@ -873,12 +873,13 @@ void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int su static void wined3d_texture_remove_buffer_object(struct wined3d_texture *texture, unsigned int sub_resource_idx, struct wined3d_context_gl *context_gl) { - struct wined3d_bo_gl *bo = &texture->sub_resources[sub_resource_idx].bo.gl; + struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx];
TRACE("texture %p, sub_resource_idx %u, context_gl %p.\n", texture, sub_resource_idx, context_gl);
- wined3d_context_gl_destroy_bo(context_gl, bo); + wined3d_context_gl_destroy_bo(context_gl, wined3d_bo_gl(sub_resource->bo)); wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER); + sub_resource->bo = NULL; }
static void wined3d_texture_unload_location(struct wined3d_texture *texture, @@ -2029,16 +2030,23 @@ static void wined3d_texture_gl_prepare_buffer_object(struct wined3d_texture_gl * struct wined3d_bo_gl *bo;
sub_resource = &texture_gl->t.sub_resources[sub_resource_idx]; - bo = &sub_resource->bo.gl; - if (bo->id) + + if (sub_resource->bo) + return; + + if (!(bo = heap_alloc(sizeof(*bo)))) return;
if (!wined3d_device_gl_create_bo(wined3d_device_gl(texture_gl->t.resource.device), context_gl, sub_resource->size, GL_PIXEL_UNPACK_BUFFER, GL_STREAM_DRAW, true, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_CLIENT_STORAGE_BIT, bo)) + { + heap_free(bo); return; + }
TRACE("Created buffer object %u for texture %p, sub-resource %u.\n", bo->id, texture_gl, sub_resource_idx); + sub_resource->bo = &bo->b; }
static void wined3d_texture_force_reload(struct wined3d_texture *texture) @@ -3219,7 +3227,7 @@ static BOOL wined3d_texture_gl_load_texture(struct wined3d_texture_gl *texture_g /* Don't use PBOs for converted surfaces. During PBO conversion we look at * WINED3D_TEXTURE_CONVERTED but it isn't set (yet) in all cases it is * getting called. */ - if (conversion && sub_resource->bo.gl.id) + if (conversion && sub_resource->bo) { TRACE("Removing the pbo attached to texture %p, %u.\n", texture_gl, sub_resource_idx);
@@ -3356,7 +3364,7 @@ static void wined3d_texture_gl_unload_location(struct wined3d_texture *texture, sub_count = texture->level_count * texture->layer_count; for (i = 0; i < sub_count; ++i) { - if (texture_gl->t.sub_resources[i].bo.gl.id) + if (texture_gl->t.sub_resources[i].bo) wined3d_texture_remove_buffer_object(&texture_gl->t, i, context_gl); } break; @@ -5265,18 +5273,24 @@ static BOOL wined3d_texture_vk_prepare_buffer_object(struct wined3d_texture_vk * struct wined3d_bo_vk *bo;
sub_resource = &texture_vk->t.sub_resources[sub_resource_idx]; - bo = &sub_resource->bo.vk; - if (bo->vk_buffer) + if (sub_resource->bo) return TRUE;
+ if (!(bo = heap_alloc(sizeof(*bo)))) + return FALSE; + if (!wined3d_context_vk_create_bo(context_vk, sub_resource->size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bo)) + { + heap_free(bo); return FALSE; + }
/* Texture buffer objects receive a barrier to HOST_READ in wined3d_texture_vk_download_data(), * so they don't need it when they are mapped for reading. */ bo->host_synced = true; + sub_resource->bo = &bo->b; TRACE("Created buffer object %p for texture %p, sub-resource %u.\n", bo, texture_vk, sub_resource_idx); return TRUE; } @@ -5351,10 +5365,13 @@ static void wined3d_texture_vk_unload_location(struct wined3d_texture *texture, sub_count = texture->level_count * texture->layer_count; for (i = 0; i < sub_count; ++i) { - if (texture->sub_resources[i].bo.vk.vk_buffer) + struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[i]; + + if (sub_resource->bo) { - wined3d_context_vk_destroy_bo(context_vk, &texture->sub_resources[i].bo.vk); - texture->sub_resources[i].bo.vk.vk_buffer = VK_NULL_HANDLE; + wined3d_context_vk_destroy_bo(context_vk, wined3d_bo_vk(sub_resource->bo)); + heap_free(sub_resource->bo); + sub_resource->bo = NULL; } } break; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 277d5a94fb0..c3a44b3a7bd 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4532,12 +4532,7 @@ struct wined3d_texture unsigned int map_count; uint32_t map_flags; DWORD locations; - union - { - struct wined3d_bo b; - struct wined3d_bo_gl gl; - struct wined3d_bo_vk vk; - } bo; + struct wined3d_bo *bo;
void *user_memory; } *sub_resources;
On Mon, 21 Feb 2022 at 06:22, Zebediah Figura zfigura@codeweavers.com wrote:
@@ -873,12 +873,13 @@ void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int su static void wined3d_texture_remove_buffer_object(struct wined3d_texture *texture, unsigned int sub_resource_idx, struct wined3d_context_gl *context_gl) {
- struct wined3d_bo_gl *bo = &texture->sub_resources[sub_resource_idx].bo.gl;
struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx];
TRACE("texture %p, sub_resource_idx %u, context_gl %p.\n", texture, sub_resource_idx, context_gl);
- wined3d_context_gl_destroy_bo(context_gl, bo);
- wined3d_context_gl_destroy_bo(context_gl, wined3d_bo_gl(sub_resource->bo)); wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER);
- sub_resource->bo = NULL;
}
That leaks sub_resource->bo.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_gl.c | 76 ++++++++++++++++++++++----------------- dlls/wined3d/adapter_vk.c | 54 ++++++++++++++++------------ dlls/wined3d/cs.c | 9 ++--- dlls/wined3d/texture.c | 31 ++++++++++++++++ 4 files changed, 111 insertions(+), 59 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 4e93e25452d..6247f60716f 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4618,60 +4618,70 @@ static bool adapter_gl_alloc_bo(struct wined3d_device *device, struct wined3d_re { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct wined3d_device_gl *device_gl = wined3d_device_gl(device); + struct wined3d_bo_gl *bo_gl; + GLenum binding, usage; + bool coherent = true; + GLbitfield flags; + GLsizeiptr size;
wined3d_not_from_cs(device->cs); assert(device->context_count);
if (resource->type == WINED3D_RTYPE_BUFFER) { - GLenum usage = GL_STATIC_DRAW; - struct wined3d_bo_gl *bo_gl; - bool coherent = true; - + size = resource->size; + binding = wined3d_buffer_gl_binding_from_bind_flags(gl_info, resource->bind_flags); + usage = GL_STATIC_DRAW; + flags = wined3d_resource_gl_storage_flags(resource); if (resource->usage & WINED3DUSAGE_DYNAMIC) { - usage = GL_STREAM_DRAW_ARB; + usage = GL_STREAM_DRAW; coherent = false; } + } + else + { + struct wined3d_texture *texture = texture_from_resource(resource);
- if (!(bo_gl = heap_alloc(sizeof(*bo_gl)))) - return false; + size = texture->sub_resources[sub_resource_idx].size; + binding = GL_PIXEL_UNPACK_BUFFER; + usage = GL_STREAM_DRAW; + flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_CLIENT_STORAGE_BIT; + }
- if (!(wined3d_device_gl_create_bo(device_gl, NULL, resource->size, - wined3d_buffer_gl_binding_from_bind_flags(gl_info, resource->bind_flags), - usage, coherent, wined3d_resource_gl_storage_flags(resource), bo_gl))) - { - WARN("Failed to create OpenGL buffer.\n"); - heap_free(bo_gl); - return false; - } + if (!(bo_gl = heap_alloc(sizeof(*bo_gl)))) + return false;
- if (bo_gl->memory) - { - struct wined3d_allocator_chunk_gl *chunk = wined3d_allocator_chunk_gl(bo_gl->memory->chunk); + if (!(wined3d_device_gl_create_bo(device_gl, NULL, size, binding, usage, coherent, flags, bo_gl))) + { + WARN("Failed to create OpenGL buffer.\n"); + heap_free(bo_gl); + return false; + }
- wined3d_allocator_chunk_gl_lock(chunk); + if (bo_gl->memory) + { + struct wined3d_allocator_chunk_gl *chunk = wined3d_allocator_chunk_gl(bo_gl->memory->chunk);
- if ((bo_gl->b.map_ptr = chunk->c.map_ptr)) - ++chunk->c.map_count; + wined3d_allocator_chunk_gl_lock(chunk);
- wined3d_allocator_chunk_gl_unlock(chunk); - } + if ((bo_gl->b.map_ptr = chunk->c.map_ptr)) + ++chunk->c.map_count;
- addr->buffer_object = &bo_gl->b; - addr->addr = NULL; + wined3d_allocator_chunk_gl_unlock(chunk); + }
- if (!bo_gl->b.map_ptr) - { - WARN_(d3d_perf)("BO %p (chunk %p) is not persistently mapped.\n", - bo_gl, bo_gl->memory ? bo_gl->memory->chunk : NULL); - wined3d_cs_map_bo_address(device->cs, addr, resource->size, WINED3D_MAP_WRITE | WINED3D_MAP_DISCARD); - } + addr->buffer_object = &bo_gl->b; + addr->addr = NULL;
- return true; + if (!bo_gl->b.map_ptr) + { + WARN_(d3d_perf)("BO %p (chunk %p) is not persistently mapped.\n", + bo_gl, bo_gl->memory ? bo_gl->memory->chunk : NULL); + wined3d_cs_map_bo_address(device->cs, addr, resource->size, WINED3D_MAP_WRITE | WINED3D_MAP_DISCARD); }
- return false; + return true; }
static void adapter_gl_destroy_bo(struct wined3d_context *context, struct wined3d_bo *bo) diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 9b9b399a810..72f945bddb0 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -1253,41 +1253,51 @@ static bool adapter_vk_alloc_bo(struct wined3d_device *device, struct wined3d_re { struct wined3d_device_vk *device_vk = wined3d_device_vk(device); struct wined3d_context_vk *context_vk = &device_vk->context_vk; + VkMemoryPropertyFlags memory_type; + VkBufferUsageFlags buffer_usage; + struct wined3d_bo_vk *bo_vk; + VkDeviceSize size;
wined3d_not_from_cs(device->cs); assert(device->context_count);
if (resource->type == WINED3D_RTYPE_BUFFER) { - struct wined3d_bo_vk *bo_vk; + buffer_usage = vk_buffer_usage_from_bind_flags(resource->bind_flags); + memory_type = vk_memory_type_from_access_flags(resource->access, resource->usage); + size = resource->size; + } + else + { + struct wined3d_texture *texture = texture_from_resource(resource);
- if (!(bo_vk = heap_alloc(sizeof(*bo_vk)))) - return false; + buffer_usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + memory_type = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + size = texture->sub_resources[sub_resource_idx].size; + }
- if (!(wined3d_context_vk_create_bo(context_vk, resource->size, - vk_buffer_usage_from_bind_flags(resource->bind_flags), - vk_memory_type_from_access_flags(resource->access, resource->usage), bo_vk))) - { - WARN("Failed to create Vulkan buffer.\n"); - heap_free(bo_vk); - return false; - } + if (!(bo_vk = heap_alloc(sizeof(*bo_vk)))) + return false;
- if (!bo_vk->b.map_ptr) - { - WARN_(d3d_perf)("BO %p (chunk %p, slab %p) is not mapped.\n", - bo_vk, bo_vk->memory ? bo_vk->memory->chunk : NULL, bo_vk->slab); + if (!(wined3d_context_vk_create_bo(context_vk, size, buffer_usage, memory_type, bo_vk))) + { + WARN("Failed to create Vulkan buffer.\n"); + heap_free(bo_vk); + return false; + }
- if (!wined3d_bo_vk_map(bo_vk, context_vk)) - ERR("Failed to map bo.\n"); - } + if (!bo_vk->b.map_ptr) + { + WARN_(d3d_perf)("BO %p (chunk %p, slab %p) is not mapped.\n", + bo_vk, bo_vk->memory ? bo_vk->memory->chunk : NULL, bo_vk->slab);
- addr->buffer_object = &bo_vk->b; - addr->addr = NULL; - return true; + if (!wined3d_bo_vk_map(bo_vk, context_vk)) + ERR("Failed to map bo.\n"); }
- return false; + addr->buffer_object = &bo_vk->b; + addr->addr = NULL; + return true; }
static void adapter_vk_destroy_bo(struct wined3d_context *context, struct wined3d_bo *bo) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 81cdb51f207..f0384748105 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -3093,9 +3093,7 @@ static void wined3d_cs_st_finish(struct wined3d_device_context *context, enum wi static bool wined3d_cs_map_upload_bo(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, uint32_t flags) { - /* Limit NOOVERWRITE maps to buffers for now; there are too many ways that - * a texture can be invalidated to even count. */ - if (resource->type == WINED3D_RTYPE_BUFFER && (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))) + if (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)) { const struct wined3d_d3d_info *d3d_info = &context->device->adapter->d3d_info; struct wined3d_client_resource *client = &resource->client; @@ -3126,7 +3124,10 @@ static bool wined3d_cs_map_upload_bo(struct wined3d_device_context *context, str if (!device->adapter->adapter_ops->adapter_alloc_bo(device, resource, sub_resource_idx, &addr)) return false;
- client->addr = addr; + /* Limit NOOVERWRITE maps to buffers for now; there are too many + * ways that a texture can be invalidated to even count. */ + if (resource->type == WINED3D_RTYPE_BUFFER) + client->addr = addr; } else { diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 9b32b9f3d1a..6905dd4c2a9 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -4539,6 +4539,30 @@ void wined3d_texture_download_from_texture(struct wined3d_texture *dst_texture, wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~dst_location); }
+static void wined3d_texture_set_bo(struct wined3d_texture *texture, + unsigned sub_resource_idx, struct wined3d_context *context, struct wined3d_bo *bo) +{ + struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx]; + struct wined3d_bo *prev_bo = sub_resource->bo; + + TRACE("texture %p, sub_resource_idx %u, context %p, bo %p.\n", texture, sub_resource_idx, context, bo); + + if (prev_bo) + { + struct wined3d_bo_user *bo_user; + + LIST_FOR_EACH_ENTRY(bo_user, &prev_bo->users, struct wined3d_bo_user, entry) + bo_user->valid = false; + assert(list_empty(&bo->users)); + list_move_head(&bo->users, &prev_bo->users); + + wined3d_context_destroy_bo(context, prev_bo); + heap_free(prev_bo); + } + + sub_resource->bo = bo; +} + void wined3d_texture_update_sub_resource(struct wined3d_texture *texture, unsigned int sub_resource_idx, struct wined3d_context *context, const struct upload_bo *upload_bo, const struct wined3d_box *box, unsigned int row_pitch, unsigned int slice_pitch) @@ -4549,6 +4573,13 @@ void wined3d_texture_update_sub_resource(struct wined3d_texture *texture, unsign unsigned int depth = wined3d_texture_get_level_depth(texture, level); struct wined3d_box src_box;
+ if (upload_bo->flags & UPLOAD_BO_RENAME_ON_UNMAP) + { + wined3d_texture_set_bo(texture, sub_resource_idx, context, upload_bo->addr.buffer_object); + wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER); + wined3d_texture_invalidate_location(texture, sub_resource_idx, ~WINED3D_LOCATION_BUFFER); + } + /* Only load the sub-resource for partial updates. */ if (!box->left && !box->top && !box->front && box->right == width && box->bottom == height && box->back == depth)
On Mon, 21 Feb 2022 at 06:22, Zebediah Figura zfigura@codeweavers.com wrote:
@@ -4549,6 +4573,13 @@ void wined3d_texture_update_sub_resource(struct wined3d_texture *texture, unsign unsigned int depth = wined3d_texture_get_level_depth(texture, level); struct wined3d_box src_box;
- if (upload_bo->flags & UPLOAD_BO_RENAME_ON_UNMAP)
- {
wined3d_texture_set_bo(texture, sub_resource_idx, context, upload_bo->addr.buffer_object);
wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER);
wined3d_texture_invalidate_location(texture, sub_resource_idx, ~WINED3D_LOCATION_BUFFER);
- }
- /* Only load the sub-resource for partial updates. */ if (!box->left && !box->top && !box->front && box->right == width && box->bottom == height && box->back == depth)
Now that we're also using this in cases where wined3d_map_persistent() returns "false", shouldn't be unmap the upload bo here?
On 2/21/22 10:16, Henri Verbeet wrote:
On Mon, 21 Feb 2022 at 06:22, Zebediah Figura zfigura@codeweavers.com wrote:
@@ -4549,6 +4573,13 @@ void wined3d_texture_update_sub_resource(struct wined3d_texture *texture, unsign unsigned int depth = wined3d_texture_get_level_depth(texture, level); struct wined3d_box src_box;
- if (upload_bo->flags & UPLOAD_BO_RENAME_ON_UNMAP)
- {
wined3d_texture_set_bo(texture, sub_resource_idx, context, upload_bo->addr.buffer_object);
wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER);
wined3d_texture_invalidate_location(texture, sub_resource_idx, ~WINED3D_LOCATION_BUFFER);
- }
/* Only load the sub-resource for partial updates. */ if (!box->left && !box->top && !box->front && box->right == width && box->bottom == height && box->back == depth)
Now that we're also using this in cases where wined3d_map_persistent() returns "false", shouldn't be unmap the upload bo here?
Yes, indeed.
On Mon, 21 Feb 2022 at 06:22, Zebediah Figura zfigura@codeweavers.com wrote:
@@ -789,6 +789,19 @@ BOOL wined3d_texture_load_location(struct wined3d_texture *texture, return TRUE; }
- if (current & WINED3D_LOCATION_CLEARED)
- {
struct wined3d_bo_address addr;
/* FIXME: Clear textures on the GPU if possible. */
if (!wined3d_texture_prepare_location(texture, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM))
return FALSE;
wined3d_texture_get_memory(texture, sub_resource_idx, &addr, WINED3D_LOCATION_SYSMEM);
memset(addr.addr, 0, texture->sub_resources[sub_resource_idx].size);
current = WINED3D_LOCATION_SYSMEM;
- }
This is broken. If WINED3D_LOCATION_BUFFER exists, wined3d_texture_get_memory() will return that instead of WINED3D_LOCATION_SYSMEM. (It won't if WINED3D_LOCATION_CLEARED is the only location that's current, but nothing prevents us from e.g. first calling wined3d_load_location(..., WINED3D_LOCATION_BUFFER), and then subsequently calling wined3d_load_location(..., WINED3D_LOCATION_TEXTURE_RGB).)
More generally, wined3d_texture_get_memory() should only be used in cases where we don't care about the exact location that's returned.
On 2/21/22 10:16, Henri Verbeet wrote:
On Mon, 21 Feb 2022 at 06:22, Zebediah Figura zfigura@codeweavers.com wrote:
@@ -789,6 +789,19 @@ BOOL wined3d_texture_load_location(struct wined3d_texture *texture, return TRUE; }
- if (current & WINED3D_LOCATION_CLEARED)
- {
struct wined3d_bo_address addr;
/* FIXME: Clear textures on the GPU if possible. */
if (!wined3d_texture_prepare_location(texture, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM))
return FALSE;
wined3d_texture_get_memory(texture, sub_resource_idx, &addr, WINED3D_LOCATION_SYSMEM);
memset(addr.addr, 0, texture->sub_resources[sub_resource_idx].size);
current = WINED3D_LOCATION_SYSMEM;
- }
This is broken. If WINED3D_LOCATION_BUFFER exists, wined3d_texture_get_memory() will return that instead of WINED3D_LOCATION_SYSMEM. (It won't if WINED3D_LOCATION_CLEARED is the only location that's current, but nothing prevents us from e.g. first calling wined3d_load_location(..., WINED3D_LOCATION_BUFFER), and then subsequently calling wined3d_load_location(..., WINED3D_LOCATION_TEXTURE_RGB).)
More generally, wined3d_texture_get_memory() should only be used in cases where we don't care about the exact location that's returned.
Maybe I'm misreading something, but wined3d_texture_get_memory() doesn't check sub_resource->locations, only the requested location, so this isn't broken per se.
Regardless, if we want to preserve this model, I'll write a helper that retrieves the correct BO address for a given location.
On Thu, 24 Feb 2022 at 01:13, Zebediah Figura zfigura@codeweavers.com wrote:
On 2/21/22 10:16, Henri Verbeet wrote:
On Mon, 21 Feb 2022 at 06:22, Zebediah Figura zfigura@codeweavers.com wrote:
@@ -789,6 +789,19 @@ BOOL wined3d_texture_load_location(struct wined3d_texture *texture, return TRUE; }
- if (current & WINED3D_LOCATION_CLEARED)
- {
struct wined3d_bo_address addr;
/* FIXME: Clear textures on the GPU if possible. */
if (!wined3d_texture_prepare_location(texture, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM))
return FALSE;
wined3d_texture_get_memory(texture, sub_resource_idx, &addr, WINED3D_LOCATION_SYSMEM);
memset(addr.addr, 0, texture->sub_resources[sub_resource_idx].size);
current = WINED3D_LOCATION_SYSMEM;
- }
This is broken. If WINED3D_LOCATION_BUFFER exists, wined3d_texture_get_memory() will return that instead of WINED3D_LOCATION_SYSMEM. (It won't if WINED3D_LOCATION_CLEARED is the only location that's current, but nothing prevents us from e.g. first calling wined3d_load_location(..., WINED3D_LOCATION_BUFFER), and then subsequently calling wined3d_load_location(..., WINED3D_LOCATION_TEXTURE_RGB).)
More generally, wined3d_texture_get_memory() should only be used in cases where we don't care about the exact location that's returned.
Maybe I'm misreading something, but wined3d_texture_get_memory() doesn't check sub_resource->locations, only the requested location, so this isn't broken per se.
You're in fact right, of course. Still, I do indeed like the new series better.