Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/texture.c | 64 ++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 24 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 74dda1df09f..42e11661248 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -2137,10 +2137,10 @@ HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, }
static void wined3d_texture_gl_upload_bo(const struct wined3d_format *src_format, GLenum target, - unsigned int level, unsigned int src_row_pitch, unsigned int dst_x, unsigned int dst_y, - unsigned int dst_z, unsigned int update_w, unsigned int update_h, unsigned int update_d, - const BYTE *addr, BOOL srgb, struct wined3d_texture *dst_texture, - const struct wined3d_gl_info *gl_info) + unsigned int level, unsigned int src_row_pitch, unsigned int src_slice_pitch, + unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, unsigned int update_w, + unsigned int update_h, unsigned int update_d, const BYTE *addr, BOOL srgb, + struct wined3d_texture *dst_texture, const struct wined3d_gl_info *gl_info) { const struct wined3d_format_gl *format_gl = wined3d_format_gl(src_format);
@@ -2213,14 +2213,14 @@ static void wined3d_texture_gl_upload_bo(const struct wined3d_format *src_format } else { - unsigned int y, y_count; + unsigned int y, y_count, z, z_count;
TRACE("Uploading data, target %#x, level %u, x %u, y %u, z %u, " "w %u, h %u, d %u, format %#x, type %#x, addr %p.\n", target, level, dst_x, dst_y, dst_z, update_w, update_h, update_d, format_gl->format, format_gl->type, addr);
- if (src_row_pitch) + if (src_row_pitch && !(src_row_pitch % src_format->byte_count)) { gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, src_row_pitch / src_format->byte_count); y_count = 1; @@ -2231,25 +2231,41 @@ static void wined3d_texture_gl_upload_bo(const struct wined3d_format *src_format update_h = 1; }
- for (y = 0; y < y_count; ++y) + if (src_slice_pitch && !(src_slice_pitch % src_row_pitch)) { - if (target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_3D) - { - GL_EXTCALL(glTexSubImage3D(target, level, dst_x, dst_y + y, dst_z, - update_w, update_h, update_d, format_gl->format, format_gl->type, addr)); - } - else if (target == GL_TEXTURE_1D) - { - gl_info->gl_ops.gl.p_glTexSubImage1D(target, level, dst_x, - update_w, format_gl->format, format_gl->type, addr); - } - else + gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, src_slice_pitch / src_row_pitch); + z_count = 1; + } + else + { + z_count = update_d; + update_d = 1; + } + + for (z = 0; z < z_count; ++z) + { + for (y = 0; y < y_count; ++y) { - gl_info->gl_ops.gl.p_glTexSubImage2D(target, level, dst_x, dst_y + y, - update_w, update_h, format_gl->format, format_gl->type, addr); + const BYTE *upload_addr = &addr[z * src_slice_pitch + y * src_row_pitch]; + if (target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_3D) + { + GL_EXTCALL(glTexSubImage3D(target, level, dst_x, dst_y + y, dst_z + z, update_w, + update_h, update_d, format_gl->format, format_gl->type, upload_addr)); + } + else if (target == GL_TEXTURE_1D) + { + gl_info->gl_ops.gl.p_glTexSubImage1D(target, level, dst_x, + update_w, format_gl->format, format_gl->type, upload_addr); + } + else + { + gl_info->gl_ops.gl.p_glTexSubImage2D(target, level, dst_x, dst_y + y, + update_w, update_h, format_gl->format, format_gl->type, upload_addr); + } } } gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); checkGLcall("Upload texture data"); } } @@ -2462,8 +2478,8 @@ static void wined3d_texture_gl_upload_data(struct wined3d_context *context, src_format->upload(src_mem, converted_mem, src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch, update_w, update_h, 1);
- wined3d_texture_gl_upload_bo(src_format, target, level, dst_row_pitch, dst_x, dst_y, - dst_z + z, update_w, update_h, 1, converted_mem, srgb, dst_texture, gl_info); + wined3d_texture_gl_upload_bo(src_format, target, level, dst_row_pitch, dst_slice_pitch, dst_x, + dst_y, dst_z + z, update_w, update_h, 1, converted_mem, srgb, dst_texture, gl_info); }
wined3d_context_gl_unmap_bo_address(context_gl, &bo, 0, NULL); @@ -2477,8 +2493,8 @@ static void wined3d_texture_gl_upload_data(struct wined3d_context *context, checkGLcall("glBindBuffer"); }
- wined3d_texture_gl_upload_bo(src_format, target, level, src_row_pitch, dst_x, dst_y, - dst_z, update_w, update_h, update_d, bo.addr, srgb, dst_texture, gl_info); + wined3d_texture_gl_upload_bo(src_format, target, level, src_row_pitch, src_slice_pitch, dst_x, + dst_y, dst_z, update_w, update_h, update_d, bo.addr, srgb, dst_texture, gl_info);
if (bo.buffer_object) {
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/texture.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 42e11661248..33825296872 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -2169,43 +2169,44 @@ static void wined3d_texture_gl_upload_bo(const struct wined3d_format *src_format GL_EXTCALL(glCompressedTexSubImage1D(target, level, dst_x, update_w, internal, dst_row_pitch, addr)); } - else if (dst_row_pitch == src_row_pitch) + else { - if (target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_3D) + unsigned int row, y, slice, slice_count = 1, row_count = 1; + + /* glCompressedTexSubImage2D() ignores pixel store state, so we + * can't use the unpack row length like for glTexSubImage2D. */ + if (dst_row_pitch != src_row_pitch) { - GL_EXTCALL(glCompressedTexSubImage3D(target, level, dst_x, dst_y, dst_z, - update_w, update_h, update_d, internal, dst_slice_pitch * update_d, addr)); + row_count = (update_h + src_format->block_height - 1) / src_format->block_height; + update_h = src_format->block_height; + wined3d_format_calculate_pitch(src_format, 1, update_w, update_h, + &dst_row_pitch, &dst_slice_pitch); } - else + + if (dst_slice_pitch != src_slice_pitch) { - GL_EXTCALL(glCompressedTexSubImage2D(target, level, dst_x, dst_y, - update_w, update_h, internal, dst_slice_pitch, addr)); + slice_count = update_d; + update_d = 1; } - } - else - { - unsigned int row_count = (update_h + src_format->block_height - 1) / src_format->block_height; - unsigned int row, y, z;
- /* glCompressedTexSubImage2D() ignores pixel store state, so we - * can't use the unpack row length like for glTexSubImage2D. */ - for (z = dst_z; z < dst_z + update_d; ++z) + for (slice = 0; slice < slice_count; ++slice) { for (row = 0, y = dst_y; row < row_count; ++row) { + const BYTE *upload_addr = &addr[slice * src_slice_pitch + row * src_row_pitch]; + if (target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_3D) { - GL_EXTCALL(glCompressedTexSubImage3D(target, level, dst_x, y, z, - update_w, src_format->block_height, 1, internal, dst_row_pitch, addr)); + GL_EXTCALL(glCompressedTexSubImage3D(target, level, dst_x, y, dst_z + slice, update_w, + update_h, update_d, internal, update_d * dst_slice_pitch, upload_addr)); } else { - GL_EXTCALL(glCompressedTexSubImage2D(target, level, dst_x, y, - update_w, src_format->block_height, internal, dst_row_pitch, addr)); + GL_EXTCALL(glCompressedTexSubImage2D(target, level, dst_x, y, update_w, + update_h, internal, dst_slice_pitch, upload_addr)); }
y += src_format->block_height; - addr += src_row_pitch; } } }
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/d3d11/tests/d3d11.c | 129 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+)
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index acbd1856b08..04f02cb5463 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -204,6 +204,12 @@ static void set_box(D3D11_BOX *box, UINT left, UINT top, UINT front, UINT right, box->back = back; }
+static BOOL is_inside_box(D3D11_BOX *box, UINT x, UINT y, UINT z) +{ + return x >= box->left && x < box->right && y >= box->top && y < box->bottom + && z >= box->front && z < box->back; +} + static ULONG get_refcount(void *iface) { IUnknown *unknown = iface; @@ -13854,6 +13860,128 @@ static void test_update_subresource(void) release_test_context(&test_context); }
+static void test_update_subresource_3d(void) +{ + unsigned int x, y, z, left, right, top, bottom, front, back, i; + struct d3d11_test_context test_context; + D3D11_TEXTURE3D_DESC texture_desc; + ID3D11DeviceContext *context; + struct resource_readback rb; + ID3D11Texture3D *texture; + D3D11_BOX box, clear_box; + ID3D11Device *device; + HRESULT hr; + + static const DWORD color_data[] = + { + 0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20, + 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40, + 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60, + 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80, + 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0, + }; + + static const DWORD black_data[ARRAY_SIZE(color_data)] = {0}; + + static const struct + { + DXGI_FORMAT format; + unsigned int slice_pitch; + unsigned int row_pitch; + unsigned int block_width; + unsigned int block_height; + unsigned int bytes_per_block; + BOOL todo; + } + tests[] = + { + { DXGI_FORMAT_R8G8B8A8_UNORM, 2 * 2 * 4, 2 * 4, 1, 1, 4 }, + { DXGI_FORMAT_R8G8B8A8_UNORM, 2 * 2 * 4 + 4, 2 * 4, 1, 1, 4 }, + { DXGI_FORMAT_R8G8B8A8_UNORM, 2 * 2 * 4, 2 * 4 + 4, 1, 1, 4 }, + { DXGI_FORMAT_BC7_UNORM, 2 * 2 * 16, 2 * 16, 4, 4, 16 }, + { DXGI_FORMAT_BC7_UNORM, 2 * 2 * 16 + 4, 2 * 16, 4, 4, 16 }, + { DXGI_FORMAT_BC7_UNORM, 2 * 2 * 16, 2 * 16 + 4, 4, 4, 16 }, + + { DXGI_FORMAT_BC1_UNORM, 2 * 2 * 8, 2 * 8, 4, 4, 8, TRUE }, + }; + + if (!init_test_context(&test_context, NULL)) + return; + + device = test_context.device; + context = test_context.immediate_context; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + unsigned int block_width = tests[i].block_width; + unsigned int block_height = tests[i].block_height; + unsigned int slice_pitch = tests[i].slice_pitch; + unsigned int row_pitch = tests[i].row_pitch; + unsigned int dim_limit = tests[i].todo ? 1 : 2; + + texture_desc.Width = 2 * block_width; + texture_desc.Height = 2 * block_height; + texture_desc.Depth = 2; + texture_desc.MipLevels = 1; + texture_desc.Format = tests[i].format; + texture_desc.Usage = D3D11_USAGE_DEFAULT; + texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + texture_desc.CPUAccessFlags = 0; + texture_desc.MiscFlags = 0; + + set_box(&clear_box, 0, 0, 0, texture_desc.Width, texture_desc.Height, 2); + + hr = ID3D11Device_CreateTexture3D(device, &texture_desc, NULL, &texture); + if (FAILED(hr)) + { + skip("Test %u: Failed to create texture, hr %#x.\n", i, hr); + continue; + } + + for (left = 0; left < dim_limit; ++left) + for (right = left + 1; right <= dim_limit; ++right) + for (top = 0; top < dim_limit; ++top) + for (bottom = top + 1; bottom <= dim_limit; ++bottom) + for (front = 0; front < dim_limit; ++front) + for (back = front + 1; back <= dim_limit; ++back) + { + const BYTE *data = (const BYTE *)color_data + tests[i].bytes_per_block * left + + row_pitch * top + slice_pitch * front; + + ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)texture, 0, + &clear_box, black_data, 0, 0); + set_box(&box, block_width * left, block_height * top, front, + block_width * right, block_height * bottom, back); + ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)texture, 0, + &box, data, row_pitch, slice_pitch); + + get_texture3d_readback(texture, 0, &rb); + + for (z = 0; z < dim_limit; ++z) + for (y = 0; y < dim_limit; ++y) + for (x = 0; x < dim_limit; ++x) + { + const BYTE *expected = (const BYTE *)black_data; + data = get_readback_data(&rb, x, y, z, tests[i].bytes_per_block); + if (is_inside_box(&box, block_width * x, block_height * y, z)) + expected = (const BYTE *)color_data + tests[i].bytes_per_block * x + + row_pitch * y + slice_pitch * z; + + todo_wine_if(tests[i].todo) + ok(!memcmp(data, expected, tests[i].bytes_per_block), "Test %u: box (%u,%u,%u)-(%u,%u,%u), " + "invalid block at %u %u %u, got 0x%08x, expected 0x%08x.\n", i, left, top, front, + right, bottom, back, x, y, z, *(DWORD *)data, *(DWORD *)expected); + } + + release_resource_readback(&rb); + } + + ID3D11Texture3D_Release(texture); + } + + release_test_context(&test_context); +} + static void test_copy_subresource_region(void) { ID3D11Texture2D *dst_texture, *src_texture; @@ -32225,6 +32353,7 @@ START_TEST(d3d11) queue_test(test_fragment_coords); queue_test(test_initial_texture_data); queue_test(test_update_subresource); + queue_test(test_update_subresource_3d); queue_test(test_copy_subresource_region); queue_test(test_copy_subresource_region_1d); queue_test(test_copy_subresource_region_3d);
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=87135
Your paranoid android.
=== w1064 (32 bit report) ===
d3d11: d3d11.c:5817: Test failed: Got unexpected IAVertices count: 0. d3d11.c:5818: Test failed: Got unexpected IAPrimitives count: 0. d3d11.c:5819: Test failed: Got unexpected VSInvocations count: 0. d3d11.c:5822: Test failed: Got unexpected CInvocations count: 0. d3d11.c:5823: Test failed: Got unexpected CPrimitives count: 0.
=== debiant2 (64 bit WoW report) ===
d3d11: d3d11.c:18589: Test failed: Got 0x00000000, expected 0xffff0000 at (0, 0, 0), sub-resource 0.
On Wed, 17 Mar 2021 at 13:52, Jan Sikorski jsikorski@codeweavers.com wrote:
static void test_copy_subresource_region(void) { ID3D11Texture2D *dst_texture, *src_texture; @@ -32225,6 +32353,7 @@ START_TEST(d3d11) queue_test(test_fragment_coords); queue_test(test_initial_texture_data); queue_test(test_update_subresource);
- queue_test(test_update_subresource_3d);
Should this be part of test_update_subresource()?
On 18 Mar 2021, at 14:33, Henri Verbeet hverbeet@gmail.com wrote:
On Wed, 17 Mar 2021 at 13:52, Jan Sikorski jsikorski@codeweavers.com wrote:
static void test_copy_subresource_region(void) { ID3D11Texture2D *dst_texture, *src_texture; @@ -32225,6 +32353,7 @@ START_TEST(d3d11) queue_test(test_fragment_coords); queue_test(test_initial_texture_data); queue_test(test_update_subresource);
- queue_test(test_update_subresource_3d);
Should this be part of test_update_subresource()?
I kept it separate similarly to how test_copy_subresource_*d and test_clear_render_target_view_*d are. Also I thought it would be more straightforward to update and read back directly rather than draw a 3d texture by slice or something, so the flow is a bit different there. On the other hand with a draw the compressed test would maybe work too.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/d3d10core/tests/d3d10core.c | 81 ++++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 14 deletions(-)
diff --git a/dlls/d3d10core/tests/d3d10core.c b/dlls/d3d10core/tests/d3d10core.c index b2a2e2028f2..09279f5fc62 100644 --- a/dlls/d3d10core/tests/d3d10core.c +++ b/dlls/d3d10core/tests/d3d10core.c @@ -594,8 +594,8 @@ struct resource_readback { D3D10_RESOURCE_DIMENSION dimension; ID3D10Resource *resource; - D3D10_MAPPED_TEXTURE2D map_desc; - unsigned int width, height, sub_resource_idx; + D3D10_MAPPED_TEXTURE3D map_desc; + unsigned int width, height, depth, sub_resource_idx; };
static void get_buffer_readback(ID3D10Buffer *buffer, struct resource_readback *rb) @@ -623,6 +623,7 @@ static void get_buffer_readback(ID3D10Buffer *buffer, struct resource_readback *
rb->width = buffer_desc.ByteWidth; rb->height = 1; + rb->depth = 1; rb->sub_resource_idx = 0;
ID3D10Device_CopyResource(device, rb->resource, (ID3D10Resource *)buffer); @@ -633,6 +634,7 @@ static void get_buffer_readback(ID3D10Buffer *buffer, struct resource_readback * rb->resource = NULL; } rb->map_desc.RowPitch = 0; + rb->map_desc.DepthPitch = 0;
ID3D10Device_Release(device); } @@ -665,6 +667,7 @@ static void get_texture1d_readback(ID3D10Texture1D *texture, unsigned int sub_re miplevel = sub_resource_idx % texture_desc.MipLevels; rb->width = max(1, texture_desc.Width >> miplevel); rb->height = 1; + rb->depth = 1; rb->sub_resource_idx = sub_resource_idx;
ID3D10Device_CopyResource(device, rb->resource, (ID3D10Resource *)texture); @@ -676,6 +679,7 @@ static void get_texture1d_readback(ID3D10Texture1D *texture, unsigned int sub_re rb->resource = NULL; } rb->map_desc.RowPitch = 0; + rb->map_desc.DepthPitch = 0;
ID3D10Device_Release(device); } @@ -708,10 +712,55 @@ static void get_texture_readback(ID3D10Texture2D *texture, unsigned int sub_reso miplevel = sub_resource_idx % texture_desc.MipLevels; rb->width = max(1, texture_desc.Width >> miplevel); rb->height = max(1, texture_desc.Height >> miplevel); + rb->depth = 1; rb->sub_resource_idx = sub_resource_idx;
ID3D10Device_CopyResource(device, rb->resource, (ID3D10Resource *)texture); if (FAILED(hr = ID3D10Texture2D_Map((ID3D10Texture2D *)rb->resource, sub_resource_idx, + D3D10_MAP_READ, 0, (D3D10_MAPPED_TEXTURE2D *)&rb->map_desc))) + { + trace("Failed to map sub-resource %u, hr %#x.\n", sub_resource_idx, hr); + ID3D10Resource_Release(rb->resource); + rb->resource = NULL; + } + rb->map_desc.DepthPitch = 0; + + ID3D10Device_Release(device); +} + +static void get_texture3d_readback(ID3D10Texture3D *texture, unsigned int sub_resource_idx, + struct resource_readback *rb) +{ + D3D10_TEXTURE3D_DESC texture_desc; + unsigned int miplevel; + ID3D10Device *device; + HRESULT hr; + + memset(rb, 0, sizeof(*rb)); + rb->dimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D; + + ID3D10Texture3D_GetDevice(texture, &device); + + ID3D10Texture3D_GetDesc(texture, &texture_desc); + texture_desc.Usage = D3D10_USAGE_STAGING; + texture_desc.BindFlags = 0; + texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ; + texture_desc.MiscFlags = 0; + if (FAILED(hr = ID3D10Device_CreateTexture3D(device, &texture_desc, NULL, (ID3D10Texture3D **)&rb->resource))) + { + trace("Failed to create texture, hr %#x.\n", hr); + ID3D10Device_Release(device); + return; + } + + miplevel = sub_resource_idx % texture_desc.MipLevels; + rb->width = max(1, texture_desc.Width >> miplevel); + rb->height = max(1, texture_desc.Height >> miplevel); + rb->depth = max(1, texture_desc.Depth >> miplevel); + rb->sub_resource_idx = sub_resource_idx; + + ID3D10Device_CopyResource(device, rb->resource, (ID3D10Resource *)texture); + if (FAILED(hr = ID3D10Texture3D_Map((ID3D10Texture3D *)rb->resource, sub_resource_idx, D3D10_MAP_READ, 0, &rb->map_desc))) { trace("Failed to map sub-resource %u, hr %#x.\n", sub_resource_idx, hr); @@ -722,24 +771,25 @@ static void get_texture_readback(ID3D10Texture2D *texture, unsigned int sub_reso ID3D10Device_Release(device); }
-static void *get_readback_data(struct resource_readback *rb, unsigned int x, unsigned int y, unsigned byte_width) +static void *get_readback_data(struct resource_readback *rb, + unsigned int x, unsigned int y, unsigned int z, unsigned byte_width) { - return (BYTE *)rb->map_desc.pData + y * rb->map_desc.RowPitch + x * byte_width; + return (BYTE *)rb->map_desc.pData + z * rb->map_desc.DepthPitch + y * rb->map_desc.RowPitch + x * byte_width; }
static BYTE get_readback_u8(struct resource_readback *rb, unsigned int x, unsigned int y) { - return *(BYTE *)get_readback_data(rb, x, y, sizeof(BYTE)); + return *(BYTE *)get_readback_data(rb, x, y, 0, sizeof(BYTE)); }
static WORD get_readback_u16(struct resource_readback *rb, unsigned int x, unsigned int y) { - return *(WORD *)get_readback_data(rb, x, y, sizeof(WORD)); + return *(WORD *)get_readback_data(rb, x, y, 0, sizeof(WORD)); }
static DWORD get_readback_u32(struct resource_readback *rb, unsigned int x, unsigned int y) { - return *(DWORD *)get_readback_data(rb, x, y, sizeof(DWORD)); + return *(DWORD *)get_readback_data(rb, x, y, 0, sizeof(DWORD)); }
static DWORD get_readback_color(struct resource_readback *rb, unsigned int x, unsigned int y) @@ -749,17 +799,17 @@ static DWORD get_readback_color(struct resource_readback *rb, unsigned int x, un
static float get_readback_float(struct resource_readback *rb, unsigned int x, unsigned int y) { - return *(float *)get_readback_data(rb, x, y, sizeof(float)); + return *(float *)get_readback_data(rb, x, y, 0, sizeof(float)); }
static const struct vec4 *get_readback_vec4(struct resource_readback *rb, unsigned int x, unsigned int y) { - return get_readback_data(rb, x, y, sizeof(struct vec4)); + return get_readback_data(rb, x, y, 0, sizeof(struct vec4)); }
static const struct uvec4 *get_readback_uvec4(struct resource_readback *rb, unsigned int x, unsigned int y) { - return get_readback_data(rb, x, y, sizeof(struct uvec4)); + return get_readback_data(rb, x, y, 0, sizeof(struct uvec4)); }
static void release_resource_readback(struct resource_readback *rb) @@ -775,6 +825,9 @@ static void release_resource_readback(struct resource_readback *rb) case D3D10_RESOURCE_DIMENSION_TEXTURE2D: ID3D10Texture2D_Unmap((ID3D10Texture2D *)rb->resource, rb->sub_resource_idx); break; + case D3D10_RESOURCE_DIMENSION_TEXTURE3D: + ID3D10Texture3D_Unmap((ID3D10Texture3D *)rb->resource, rb->sub_resource_idx); + break; default: trace("Unhandled resource dimension %#x.\n", rb->dimension); break; @@ -15970,12 +16023,12 @@ static void test_depth_bias(void) depth_values[y] = get_readback_float(&rb, 0, y); break; case DXGI_FORMAT_D24_UNORM_S8_UINT: - u32 = get_readback_data(&rb, 0, y, sizeof(*u32)); + u32 = get_readback_data(&rb, 0, y, 0, sizeof(*u32)); u32_value = *u32 >> shift; depth_values[y] = u32_value / 16777215.0f; break; case DXGI_FORMAT_D16_UNORM: - u16 = get_readback_data(&rb, 0, y, sizeof(*u16)); + u16 = get_readback_data(&rb, 0, y, 0, sizeof(*u16)); depth_values[y] = *u16 / 65535.0f; break; default: @@ -16013,7 +16066,7 @@ static void test_depth_bias(void) "Got depth %.8e, expected %.8e.\n", data, depth); break; case DXGI_FORMAT_D24_UNORM_S8_UINT: - u32 = get_readback_data(&rb, 0, y, sizeof(*u32)); + u32 = get_readback_data(&rb, 0, y, 0, sizeof(*u32)); u32_value = *u32 >> shift; expected_value = depth * 16777215.0f + 0.5f; all_match = compare_uint(u32_value, expected_value, 3); @@ -16023,7 +16076,7 @@ static void test_depth_bias(void) expected_value, expected_value / 16777215.0f); break; case DXGI_FORMAT_D16_UNORM: - u16 = get_readback_data(&rb, 0, y, sizeof(*u16)); + u16 = get_readback_data(&rb, 0, y, 0, sizeof(*u16)); expected_value = depth * 65535.0f + 0.5f; all_match = compare_uint(*u16, expected_value, 1); ok(all_match,
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/d3d10core/tests/d3d10core.c | 125 +++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+)
diff --git a/dlls/d3d10core/tests/d3d10core.c b/dlls/d3d10core/tests/d3d10core.c index 09279f5fc62..a26523c4852 100644 --- a/dlls/d3d10core/tests/d3d10core.c +++ b/dlls/d3d10core/tests/d3d10core.c @@ -148,6 +148,12 @@ static void set_box(D3D10_BOX *box, UINT left, UINT top, UINT front, UINT right, box->back = back; }
+static BOOL is_inside_box(D3D10_BOX *box, UINT x, UINT y, UINT z) +{ + return x >= box->left && x < box->right && y >= box->top && y < box->bottom + && z >= box->front && z < box->back; +} + static ULONG get_refcount(void *iface) { IUnknown *unknown = iface; @@ -9723,6 +9729,124 @@ static void test_update_subresource(void) release_test_context(&test_context); }
+static void test_update_subresource_3d(void) +{ + unsigned int x, y, z, left, right, top, bottom, front, back, i; + struct d3d10core_test_context test_context; + D3D10_TEXTURE3D_DESC texture_desc; + struct resource_readback rb; + ID3D10Texture3D *texture; + D3D10_BOX box, clear_box; + ID3D10Device *device; + HRESULT hr; + + static const DWORD color_data[] = + { + 0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20, + 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40, + 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60, + 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80, + 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0, + }; + + static const DWORD black_data[ARRAY_SIZE(color_data)] = {0}; + + static const struct + { + DXGI_FORMAT format; + unsigned int slice_pitch; + unsigned int row_pitch; + unsigned int block_width; + unsigned int block_height; + unsigned int bytes_per_block; + BOOL todo; + } + tests[] = + { + { DXGI_FORMAT_R8G8B8A8_UNORM, 2 * 2 * 4, 2 * 4, 1, 1, 4 }, + { DXGI_FORMAT_R8G8B8A8_UNORM, 2 * 2 * 4 + 4, 2 * 4, 1, 1, 4 }, + { DXGI_FORMAT_R8G8B8A8_UNORM, 2 * 2 * 4, 2 * 4 + 4, 1, 1, 4 }, + + { DXGI_FORMAT_BC1_UNORM, 2 * 2 * 8, 2 * 8, 4, 4, 8, TRUE }, + }; + + if (!init_test_context(&test_context)) + return; + + device = test_context.device; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + unsigned int block_width = tests[i].block_width; + unsigned int block_height = tests[i].block_height; + unsigned int slice_pitch = tests[i].slice_pitch; + unsigned int row_pitch = tests[i].row_pitch; + unsigned int dim_limit = tests[i].todo ? 1 : 2; + + texture_desc.Width = 2 * block_width; + texture_desc.Height = 2 * block_height; + texture_desc.Depth = 2; + texture_desc.MipLevels = 1; + texture_desc.Format = tests[i].format; + texture_desc.Usage = D3D10_USAGE_DEFAULT; + texture_desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + texture_desc.CPUAccessFlags = 0; + texture_desc.MiscFlags = 0; + + set_box(&clear_box, 0, 0, 0, texture_desc.Width, texture_desc.Height, 2); + + hr = ID3D10Device_CreateTexture3D(device, &texture_desc, NULL, &texture); + if (FAILED(hr)) + { + skip("Test %u: Failed to create texture, hr %#x.\n", i, hr); + continue; + } + + for (left = 0; left < dim_limit; ++left) + for (right = left + 1; right <= dim_limit; ++right) + for (top = 0; top < dim_limit; ++top) + for (bottom = top + 1; bottom <= dim_limit; ++bottom) + for (front = 0; front < dim_limit; ++front) + for (back = front + 1; back <= dim_limit; ++back) + { + const BYTE *data = (const BYTE *)color_data + tests[i].bytes_per_block * left + + row_pitch * top + slice_pitch * front; + + ID3D10Device_UpdateSubresource(device, (ID3D10Resource *)texture, 0, + &clear_box, black_data, 0, 0); + set_box(&box, block_width * left, block_height * top, front, + block_width * right, block_height * bottom, back); + ID3D10Device_UpdateSubresource(device, (ID3D10Resource *)texture, 0, + &box, data, row_pitch, slice_pitch); + + get_texture3d_readback(texture, 0, &rb); + + for (z = 0; z < dim_limit; ++z) + for (y = 0; y < dim_limit; ++y) + for (x = 0; x < dim_limit; ++x) + { + const BYTE *expected = (const BYTE *)black_data; + data = get_readback_data(&rb, x, y, z, tests[i].bytes_per_block); + if (is_inside_box(&box, block_width * x, block_height * y, z)) + expected = (const BYTE *)color_data + tests[i].bytes_per_block * x + + row_pitch * y + slice_pitch * z; + + todo_wine_if(tests[i].todo) + ok(!memcmp(data, expected, tests[i].bytes_per_block), "Test %u: box (%u,%u,%u)-(%u,%u,%u), " + "invalid block at %u %u %u, got 0x%08x, expected 0x%08x.\n", i, left, top, front, + right, bottom, back, x, y, z, *(DWORD *)data, *(DWORD *)expected); + } + + release_resource_readback(&rb); + } + + ID3D10Texture3D_Release(texture); + } + + release_test_context(&test_context); +} + + static void test_copy_subresource_region(void) { struct d3d10core_test_context test_context; @@ -18905,6 +19029,7 @@ START_TEST(d3d10core) queue_test(test_fragment_coords); queue_test(test_initial_texture_data); queue_test(test_update_subresource); + queue_test(test_update_subresource_3d); queue_test(test_copy_subresource_region); queue_test(test_copy_subresource_region_1d); queue_test(test_resource_access);
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=87137
Your paranoid android.
=== w8adm (32 bit report) ===
d3d10core: 0cb0:d3d10core: unhandled exception c0000005 at 7FE95178
On Wed, 17 Mar 2021 at 13:52, Jan Sikorski jsikorski@codeweavers.com wrote:
@@ -2231,25 +2231,41 @@ static void wined3d_texture_gl_upload_bo(const struct wined3d_format *src_format update_h = 1; }
for (y = 0; y < y_count; ++y)
if (src_slice_pitch && !(src_slice_pitch % src_row_pitch)) {
That's still a potential divide by zero. The application would have to set a non-zero slice pitch and a zero row pitch to trigger that, which is perhaps questionable, but I'm not aware of it being illegal.
Note that the issue you're fixing isn't partial updates. Partial updates should work fine as long as the update uses the default slice pitch; conversely, even full updates will be mishandled with non-default slice pitches.