vkd3d-shader: Implement shader model 1.0-1.3 texture projection.

This commit is contained in:
Elizabeth Figura
2025-08-09 15:33:46 -05:00
committed by Henri Verbeet
parent 44c80c60b8
commit c50210f230
Notes: Henri Verbeet 2025-11-20 18:37:00 +01:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1814
9 changed files with 209 additions and 9 deletions

View File

@@ -67,10 +67,15 @@ ffff0101 % ps_1_1
[test]
bump 1 f32(0.1, 0.2, 0.3, 0.5) 2.0 0.3
projected 1 disable
draw quad
% WARP transposes the matrix for TEXBEM/TEXBEML, but not for BEM.
if(!warp) probe (250, 500) f32(0.58, 0.27, 0.73, 0.42) 32
if(!warp) probe (750, 500) f32(0.47, 0.33, 0.67, 0.53) 16
projected 1 enable
draw quad
if(!warp) probe (250, 500) f32(0.28, 0.47, 0.53, 0.72) 32
if(!warp) probe (750, 500) f32(0.17, 0.53, 0.47, 0.83) 16
[pixel shader d3dbc-hex]
% TODO: Convert to assembly.
@@ -82,11 +87,16 @@ ffff0101 % ps_1_1
[test]
bump 1 f32(0.1, 0.2, 0.3, 0.5) 2.0 0.3
projected 1 disable
draw quad
% Besides transposing the matrix, WARP also uses the texcoord t1.z (0.4)
% as a luminance factor, instead of the textured value t0.z (0.3 or 0.2).
if(!warp) probe (250, 500) f32(0.522, 0.243, 0.657, 0.378) 32
if(!warp) probe (750, 500) f32(0.329, 0.231, 0.469, 0.371) 16
projected 1 enable
draw quad
if(!warp) probe (250, 500) f32(0.252, 0.423, 0.477, 0.648) 32
if(!warp) probe (750, 500) f32(0.119, 0.371, 0.329, 0.581) 32
[pixel shader d3dbc-hex]
% TODO: Convert to assembly.

View File

@@ -0,0 +1,62 @@
% Test for the D3DTTFF_* projected texture flags.
[require]
shader model < 3.0
[sampler 0]
filter point point point
address clamp clamp clamp
[srv 0]
size (2d, 5, 5)
.0 .0 .0 .1 .1 .0 .0 .1 .2 .0 .0 .1 .3 .0 .0 .1 .4 .0 .0 .1
.0 .1 .0 .1 .1 .1 .0 .1 .2 .1 .0 .1 .3 .1 .0 .1 .4 .1 .0 .1
.0 .2 .0 .1 .1 .2 .0 .1 .2 .2 .0 .1 .3 .2 .0 .1 .4 .2 .0 .1
.0 .3 .0 .1 .1 .3 .0 .1 .2 .3 .0 .1 .3 .3 .0 .1 .4 .3 .0 .1
.0 .4 .0 .1 .1 .4 .0 .1 .2 .4 .0 .1 .3 .4 .0 .1 .4 .4 .0 .1
[vertex shader]
void main(inout float4 pos : position, out float4 tex : texcoord)
{
tex = float4(1.2, 0.5, 4.0, 2.0);
}
[pixel shader d3dbc-hex]
% TODO: Convert to assembly or HLSL.
ffff0101 % ps_1_1
00000042 b00f0000 % tex t0
00000001 800f0000 b0e40000 % mov r0, t0
0000ffff % end
[test]
projected 0 disable
draw quad
probe (0, 0) f32(0.4, 0.2, 0.0, 0.1)
projected 0 enable
draw quad
probe (0, 0) f32(0.3, 0.1, 0.0, 0.1)
% Doesn't affect 1.4 or 2.0.
[pixel shader d3dbc-hex]
% TODO: Convert to assembly or HLSL.
ffff0104 % ps_1_4
00000042 800f0000 b0e40000 % texld r0, t0
0000ffff % end
[test]
projected 0 enable
draw quad
probe (0, 0) f32(0.4, 0.2, 0.0, 0.1)
[pixel shader]
sampler sam;
float4 main(float2 tex : texcoord) : sv_target
{
return tex2D(sam, tex);
}
[test]
projected 0 enable
draw quad
probe (0, 0) f32(0.4, 0.2, 0.0, 0.1)

View File

@@ -765,8 +765,10 @@ static void parse_resource_directive(struct resource_params *resource, const cha
for (;;)
{
while (isspace(*line))
++line;
u.u = strtoul(line, &rest, 0);
if (rest && *rest == '.')
if (*line == '.' || (rest && *rest == '.'))
u.f = strtof(line, &rest);
if (rest == line)
@@ -1764,6 +1766,20 @@ static void parse_test_directive(struct shader_runner *runner, const char *line)
else
fatal_error("Invalid denorm mode '%s'.\n", line);
}
else if (match_string(line, "projected", &line))
{
unsigned int index;
index = strtoul(line, (char **)&rest, 10);
if (rest == line || index >= 6)
fatal_error("Malformed projection directive '%s'.\n", line);
line = rest;
if (match_string(line, "enable", &line))
runner->projected_texture_mask |= (1u << index);
else
runner->projected_texture_mask &= ~(1u << index);
}
else
{
fatal_error("Unknown test directive '%s'.\n", line);

View File

@@ -304,6 +304,7 @@ struct shader_runner
float matrix[2][2];
float luminance_scale, luminance_offset;
} bump[8];
uint8_t projected_texture_mask;
enum denorm_mode denorm_mode;

View File

@@ -651,6 +651,10 @@ static bool d3d9_runner_draw(struct shader_runner *r,
hr = IDirect3DDevice9_SetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET,
float_to_int(runner->r.bump[i].luminance_offset));
ok(hr == D3D_OK, "Failed to set texture state, hr %#lx.\n", hr);
hr = IDirect3DDevice9_SetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS,
(runner->r.projected_texture_mask & (1u << i)) ? D3DTTFF_PROJECTED : 0);
ok(hr == D3D_OK, "Failed to set texture state, hr %#lx.\n", hr);
}
hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);

View File

@@ -366,7 +366,7 @@ static bool compile_d3d_code(struct vulkan_shader_runner *runner,
struct vkd3d_shader_varying_map varying_map[12];
struct vkd3d_shader_resource_binding *binding;
struct vkd3d_shader_compile_option options[2];
struct vkd3d_shader_parameter1 parameters[40];
struct vkd3d_shader_parameter1 parameters[41];
unsigned int i;
char *messages;
int ret;
@@ -609,6 +609,11 @@ static bool compile_d3d_code(struct vulkan_shader_runner *runner,
parameters[34 + i].u.immediate_constant.u.f32 = runner->r.bump[i].luminance_offset;
}
parameters[40].name = VKD3D_SHADER_PARAMETER_NAME_PROJECTED_TEXTURE_MASK;
parameters[40].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
parameters[40].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32;
parameters[40].u.immediate_constant.u.u32 = runner->r.projected_texture_mask;
parameter_info.parameter_count = ARRAY_SIZE(parameters);
parameter_info.parameters = parameters;