wined3d: Add decompression information for BC4_UNORM.

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Henri Verbeet 2021-06-22 14:36:00 +02:00 committed by Alexandre Julliard
parent da171b8f90
commit 2aeab85c27
3 changed files with 387 additions and 2 deletions

View file

@ -18935,6 +18935,158 @@ static void test_unbound_streams(void)
release_test_context(&test_context);
}
static void test_texture_compressed_3d(void)
{
struct d3d10core_test_context test_context;
D3D10_SUBRESOURCE_DATA resource_data;
D3D10_TEXTURE3D_DESC texture_desc;
ID3D10SamplerState *sampler_state;
unsigned int idx, r0, r1, x, y, z;
D3D10_SAMPLER_DESC sampler_desc;
ID3D10ShaderResourceView *srv;
struct resource_readback rb;
ID3D10Texture3D *texture;
DWORD colour, expected;
ID3D10PixelShader *ps;
ID3D10Device *device;
DWORD *texture_data;
BOOL equal = TRUE;
HRESULT hr;
static const DWORD ps_code[] =
{
#if 0
Texture3D t;
SamplerState s;
float4 main(float4 position : SV_POSITION) : SV_Target
{
return t.Sample(s, position.xyz / float3(640, 480, 1));
}
#endif
0x43425844, 0x27b15ae8, 0xbebf46f7, 0x6cd88d8d, 0x5118de51, 0x00000001, 0x00000134, 0x00000003,
0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000070f, 0x505f5653, 0x5449534f, 0x004e4f49,
0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000098, 0x00000040,
0x00000026, 0x0300005a, 0x00106000, 0x00000000, 0x04002858, 0x00107000, 0x00000000, 0x00005555,
0x04002064, 0x00101072, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068,
0x00000001, 0x0a000038, 0x00100072, 0x00000000, 0x00101246, 0x00000000, 0x00004002, 0x3acccccd,
0x3b088889, 0x3f800000, 0x00000000, 0x09000045, 0x001020f2, 0x00000000, 0x00100246, 0x00000000,
0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0100003e,
};
static const unsigned int block_indices[] =
{
0, 1, 3, 2,
6, 7, 5, 4,
0, 1, 3, 2,
6, 7, 5, 4,
};
if (!init_test_context(&test_context))
return;
device = test_context.device;
hr = ID3D10Device_CreatePixelShader(device, ps_code, sizeof(ps_code), &ps);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
/* Simply test all combinations of r0 and r1. */
texture_data = heap_alloc(256 * 256 * sizeof(UINT64));
for (r1 = 0; r1 < 256; ++r1)
{
for (r0 = 0; r0 < 256; ++r0)
{
/* bits = block_indices[] */
texture_data[(r1 * 256 + r0) * 2 + 0] = 0xe4c80000 | (r1 << 8) | r0;
texture_data[(r1 * 256 + r0) * 2 + 1] = 0x97e4c897;
}
}
resource_data.pSysMem = texture_data;
resource_data.SysMemPitch = 64 * sizeof(UINT64);
resource_data.SysMemSlicePitch = 64 * resource_data.SysMemPitch;
texture_desc.Width = 256;
texture_desc.Height = 256;
texture_desc.Depth = 16;
texture_desc.MipLevels = 1;
texture_desc.Format = DXGI_FORMAT_BC4_UNORM;
texture_desc.Usage = D3D10_USAGE_DEFAULT;
texture_desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
texture_desc.CPUAccessFlags = 0;
texture_desc.MiscFlags = 0;
hr = ID3D10Device_CreateTexture3D(device, &texture_desc, &resource_data, &texture);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
heap_free(texture_data);
hr = ID3D10Device_CreateShaderResourceView(device, (ID3D10Resource *)texture, NULL, &srv);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
sampler_desc.Filter = D3D10_FILTER_MIN_MAG_MIP_POINT;
sampler_desc.AddressU = D3D10_TEXTURE_ADDRESS_CLAMP;
sampler_desc.AddressV = D3D10_TEXTURE_ADDRESS_CLAMP;
sampler_desc.AddressW = D3D10_TEXTURE_ADDRESS_CLAMP;
sampler_desc.MipLODBias = 0.0f;
sampler_desc.MaxAnisotropy = 0;
sampler_desc.ComparisonFunc = D3D10_COMPARISON_NEVER;
sampler_desc.BorderColor[0] = 0.0f;
sampler_desc.BorderColor[1] = 0.0f;
sampler_desc.BorderColor[2] = 0.0f;
sampler_desc.BorderColor[3] = 0.0f;
sampler_desc.MinLOD = 0.0f;
sampler_desc.MaxLOD = 0.0f;
hr = ID3D10Device_CreateSamplerState(device, &sampler_desc, &sampler_state);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ID3D10Device_PSSetShader(device, ps);
ID3D10Device_PSSetShaderResources(device, 0, 1, &srv);
ID3D10Device_PSSetSamplers(device, 0, 1, &sampler_state);
for (z = 0; z < 16; ++z)
{
draw_quad_z(&test_context, (z * 2.0f + 1.0f) / 32.0f);
get_texture_readback(test_context.backbuffer, 0, &rb);
for (y = 0; y < 256; ++y)
{
for (x = 0; x < 256; ++x)
{
idx = z * 64 * 64 + (y / 4) * 64 + (x / 4);
r0 = idx % 256;
r1 = idx / 256;
switch (block_indices[(y % 4) * 4 + (x % 4)])
{
case 0: expected = r0; break;
case 1: expected = r1; break;
case 2: expected = r0 > r1 ? (12 * r0 + 2 * r1 + 7) / 14 : (8 * r0 + 2 * r1 + 5) / 10; break;
case 3: expected = r0 > r1 ? (10 * r0 + 4 * r1 + 7) / 14 : (6 * r0 + 4 * r1 + 5) / 10; break;
case 4: expected = r0 > r1 ? ( 8 * r0 + 6 * r1 + 7) / 14 : (4 * r0 + 6 * r1 + 5) / 10; break;
case 5: expected = r0 > r1 ? ( 6 * r0 + 8 * r1 + 7) / 14 : (2 * r0 + 8 * r1 + 5) / 10; break;
case 6: expected = r0 > r1 ? ( 4 * r0 + 10 * r1 + 7) / 14 : 0x00; break;
case 7: expected = r0 > r1 ? ( 2 * r0 + 12 * r1 + 7) / 14 : 0xff; break;
default: expected = ~0u; break;
}
expected |= 0xff000000;
colour = get_readback_color(&rb, (x * 640 + 128) / 256, (y * 480 + 128) / 256);
if (!(equal = compare_color(colour, expected, 2)))
break;
}
if (!equal)
break;
}
release_resource_readback(&rb);
if (!equal)
break;
}
ok(equal, "Got unexpected colour 0x%08x at (%u, %u, %u), expected 0x%08x.\n", colour, x, y, z, expected);
ID3D10PixelShader_Release(ps);
ID3D10SamplerState_Release(sampler_state);
ID3D10ShaderResourceView_Release(srv);
ID3D10Texture3D_Release(texture);
release_test_context(&test_context);
}
START_TEST(d3d10core)
{
unsigned int argc, i;
@ -19060,6 +19212,7 @@ START_TEST(d3d10core)
queue_test(test_independent_blend);
queue_test(test_dual_source_blend);
queue_test(test_unbound_streams);
queue_test(test_texture_compressed_3d);
run_queued_tests();

View file

@ -33285,6 +33285,160 @@ static void test_deferred_context_map(void)
release_test_context(&test_context);
}
static void test_texture_compressed_3d(void)
{
struct d3d11_test_context test_context;
D3D11_SUBRESOURCE_DATA resource_data;
D3D11_TEXTURE3D_DESC texture_desc;
ID3D11SamplerState *sampler_state;
unsigned int idx, r0, r1, x, y, z;
D3D11_SAMPLER_DESC sampler_desc;
ID3D11ShaderResourceView *srv;
ID3D11DeviceContext *context;
struct resource_readback rb;
ID3D11Texture3D *texture;
DWORD colour, expected;
ID3D11PixelShader *ps;
ID3D11Device *device;
DWORD *texture_data;
BOOL equal = TRUE;
HRESULT hr;
static const DWORD ps_code[] =
{
#if 0
Texture3D t;
SamplerState s;
float4 main(float4 position : SV_POSITION) : SV_Target
{
return t.Sample(s, position.xyz / float3(640, 480, 1));
}
#endif
0x43425844, 0x27b15ae8, 0xbebf46f7, 0x6cd88d8d, 0x5118de51, 0x00000001, 0x00000134, 0x00000003,
0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000070f, 0x505f5653, 0x5449534f, 0x004e4f49,
0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000098, 0x00000040,
0x00000026, 0x0300005a, 0x00106000, 0x00000000, 0x04002858, 0x00107000, 0x00000000, 0x00005555,
0x04002064, 0x00101072, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068,
0x00000001, 0x0a000038, 0x00100072, 0x00000000, 0x00101246, 0x00000000, 0x00004002, 0x3acccccd,
0x3b088889, 0x3f800000, 0x00000000, 0x09000045, 0x001020f2, 0x00000000, 0x00100246, 0x00000000,
0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0100003e,
};
static const unsigned int block_indices[] =
{
0, 1, 3, 2,
6, 7, 5, 4,
0, 1, 3, 2,
6, 7, 5, 4,
};
if (!init_test_context(&test_context, NULL))
return;
device = test_context.device;
context = test_context.immediate_context;
hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
/* Simply test all combinations of r0 and r1. */
texture_data = heap_alloc(256 * 256 * sizeof(UINT64));
for (r1 = 0; r1 < 256; ++r1)
{
for (r0 = 0; r0 < 256; ++r0)
{
/* bits = block_indices[] */
texture_data[(r1 * 256 + r0) * 2 + 0] = 0xe4c80000 | (r1 << 8) | r0;
texture_data[(r1 * 256 + r0) * 2 + 1] = 0x97e4c897;
}
}
resource_data.pSysMem = texture_data;
resource_data.SysMemPitch = 64 * sizeof(UINT64);
resource_data.SysMemSlicePitch = 64 * resource_data.SysMemPitch;
texture_desc.Width = 256;
texture_desc.Height = 256;
texture_desc.Depth = 16;
texture_desc.MipLevels = 1;
texture_desc.Format = DXGI_FORMAT_BC4_UNORM;
texture_desc.Usage = D3D11_USAGE_DEFAULT;
texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
texture_desc.CPUAccessFlags = 0;
texture_desc.MiscFlags = 0;
hr = ID3D11Device_CreateTexture3D(device, &texture_desc, &resource_data, &texture);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
heap_free(texture_data);
hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, NULL, &srv);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
sampler_desc.MipLODBias = 0.0f;
sampler_desc.MaxAnisotropy = 0;
sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
sampler_desc.BorderColor[0] = 0.0f;
sampler_desc.BorderColor[1] = 0.0f;
sampler_desc.BorderColor[2] = 0.0f;
sampler_desc.BorderColor[3] = 0.0f;
sampler_desc.MinLOD = 0.0f;
sampler_desc.MaxLOD = 0.0f;
hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler_state);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0);
ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv);
ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler_state);
for (z = 0; z < 16; ++z)
{
draw_quad_z(&test_context, (z * 2.0f + 1.0f) / 32.0f);
get_texture_readback(test_context.backbuffer, 0, &rb);
for (y = 0; y < 256; ++y)
{
for (x = 0; x < 256; ++x)
{
idx = z * 64 * 64 + (y / 4) * 64 + (x / 4);
r0 = idx % 256;
r1 = idx / 256;
switch (block_indices[(y % 4) * 4 + (x % 4)])
{
case 0: expected = r0; break;
case 1: expected = r1; break;
case 2: expected = r0 > r1 ? (12 * r0 + 2 * r1 + 7) / 14 : (8 * r0 + 2 * r1 + 5) / 10; break;
case 3: expected = r0 > r1 ? (10 * r0 + 4 * r1 + 7) / 14 : (6 * r0 + 4 * r1 + 5) / 10; break;
case 4: expected = r0 > r1 ? ( 8 * r0 + 6 * r1 + 7) / 14 : (4 * r0 + 6 * r1 + 5) / 10; break;
case 5: expected = r0 > r1 ? ( 6 * r0 + 8 * r1 + 7) / 14 : (2 * r0 + 8 * r1 + 5) / 10; break;
case 6: expected = r0 > r1 ? ( 4 * r0 + 10 * r1 + 7) / 14 : 0x00; break;
case 7: expected = r0 > r1 ? ( 2 * r0 + 12 * r1 + 7) / 14 : 0xff; break;
default: expected = ~0u; break;
}
expected |= 0xff000000;
colour = get_readback_color(&rb, (x * 640 + 128) / 256, (y * 480 + 128) / 256, 0);
if (!(equal = compare_color(colour, expected, 2)))
break;
}
if (!equal)
break;
}
release_resource_readback(&rb);
if (!equal)
break;
}
ok(equal, "Got unexpected colour 0x%08x at (%u, %u, %u), expected 0x%08x.\n", colour, x, y, z, expected);
ID3D11PixelShader_Release(ps);
ID3D11SamplerState_Release(sampler_state);
ID3D11ShaderResourceView_Release(srv);
ID3D11Texture3D_Release(texture);
release_test_context(&test_context);
}
START_TEST(d3d11)
{
unsigned int argc, i;
@ -33457,6 +33611,7 @@ START_TEST(d3d11)
queue_test(test_deferred_context_rendering);
queue_test(test_deferred_context_map);
queue_test(test_unbound_streams);
queue_test(test_texture_compressed_3d);
run_queued_tests();
}

View file

@ -568,6 +568,84 @@ static void decompress_bc1(const BYTE *src, BYTE *dst, unsigned int src_row_pitc
dst_slice_pitch, width, height, depth, WINED3DFMT_BC1_UNORM);
}
static void build_rgtc_colour_table(uint8_t red0, uint8_t red1, uint8_t colour_table[8])
{
unsigned int i;
colour_table[0] = red0;
colour_table[1] = red1;
if (red0 <= red1)
{
for (i = 0; i < 4; ++i)
{
colour_table[i + 2] = ((8 - 2 * i) * red0 + (2 + 2 * i) * red1 + 5) / 10;
}
colour_table[6] = 0x00;
colour_table[7] = 0xff;
}
else
{
for (i = 0; i < 6; ++i)
{
colour_table[i + 2] = ((12 - 2 * i) * red0 + (2 + 2 * i) * red1 + 7) / 14;
}
}
}
static void decompress_rgtc_block(const uint8_t *src, uint8_t *dst,
unsigned int width, unsigned int height, unsigned int dst_row_pitch)
{
const uint64_t *s = (const uint64_t *)src;
uint8_t red0, red1, red_idx;
uint8_t colour_table[8];
unsigned int x, y;
uint32_t *dst_row;
uint64_t bits;
red0 = s[0] & 0xff;
red1 = (s[0] >> 8) & 0xff;
bits = s[0] >> 16;
build_rgtc_colour_table(red0, red1, colour_table);
for (y = 0; y < height; ++y)
{
dst_row = (uint32_t *)&dst[y * dst_row_pitch];
for (x = 0; x < width; ++x)
{
red_idx = (bits >> (y * 12 + x * 3)) & 0x7;
/* Decompressing to bgra32 is perhaps not ideal for RGTC formats.
* It's convenient though. */
dst_row[x] = 0xff000000 | (colour_table[red_idx] << 16);
}
}
}
static void decompress_bc4(const uint8_t *src, uint8_t *dst, unsigned int src_row_pitch,
unsigned int src_slice_pitch, unsigned int dst_row_pitch, unsigned int dst_slice_pitch,
unsigned int width, unsigned int height, unsigned int depth)
{
unsigned int block_w, block_h, x, y, z;
const uint8_t *src_row, *src_slice;
uint8_t *dst_row, *dst_slice;
for (z = 0; z < depth; ++z)
{
src_slice = &src[z * src_slice_pitch];
dst_slice = &dst[z * dst_slice_pitch];
for (y = 0; y < height; y += 4)
{
src_row = &src_slice[(y / 4) * src_row_pitch];
dst_row = &dst_slice[y * dst_row_pitch];
for (x = 0; x < width; x += 4)
{
block_w = min(width - x, 4);
block_h = min(height - y, 4);
decompress_rgtc_block(&src_row[(x / 4) * 8], &dst_row[x * 4], block_w, block_h, dst_row_pitch);
}
}
}
}
static const struct wined3d_format_decompress_info
{
enum wined3d_format_id id;
@ -585,6 +663,7 @@ format_decompress_info[] =
{WINED3DFMT_BC1_UNORM, decompress_bc1},
{WINED3DFMT_BC2_UNORM, decompress_bc2},
{WINED3DFMT_BC3_UNORM, decompress_bc3},
{WINED3DFMT_BC4_UNORM, decompress_bc4},
};
struct wined3d_format_block_info
@ -3683,8 +3762,6 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_
format->f.flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
format = get_format_gl_internal(adapter, WINED3DFMT_ATI2N);
format->f.flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
format = get_format_gl_internal(adapter, WINED3DFMT_BC4_UNORM);
format->f.flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
format = get_format_gl_internal(adapter, WINED3DFMT_BC4_SNORM);
format->f.flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
format = get_format_gl_internal(adapter, WINED3DFMT_BC5_UNORM);