vkd3d-shader/ir: Allow controlling fog through parameters.

Fog requires several parameters to even implement the most basic of
functionality correctly, so this commit is relatively large.
This commit is contained in:
Elizabeth Figura
2024-10-05 10:26:20 -05:00
committed by Henri Verbeet
parent a1de406de4
commit f86d1e72a4
Notes: Henri Verbeet 2024-12-02 17:19:05 +01:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1265
8 changed files with 504 additions and 29 deletions

View File

@@ -27,3 +27,46 @@ float4 main(float2 fog : fog) : sv_target
[test]
todo(msl) draw quad
probe (0, 0) rgba (0.1, 0.2, 0, 1)
[require]
fog
[input layout]
0 r32g32b32a32-float position
[vb 0]
-1.0 -1.0 0.2 1.0
-1.0 1.0 0.2 1.0
1.0 -1.0 0.6 1.0
1.0 1.0 0.6 1.0
[vertex shader]
float4 main(float4 pos : position, out float fog : fog) : sv_position
{
fog = 0.2;
return pos;
}
[pixel shader]
float4 main() : sv_target
{
return float4(0, 0, 1, 1);
}
[test]
fog-colour 0.0 1.0 1.0 1.0
fog disable
draw triangle strip 4
probe (160, 120) rgba (0.0, 0.0, 1.0, 1.0)
probe (480, 360) rgba (0.0, 0.0, 1.0, 1.0)
probe (160, 120) rgba (0.0, 0.0, 1.0, 1.0)
probe (480, 360) rgba (0.0, 0.0, 1.0, 1.0)
fog none
draw triangle strip 4
probe (160, 120) rgba (0.0, 0.8, 1.0, 1.0)
probe (480, 360) rgba (0.0, 0.8, 1.0, 1.0)
probe (160, 120) rgba (0.0, 0.8, 1.0, 1.0)
probe (480, 360) rgba (0.0, 0.8, 1.0, 1.0)

View File

@@ -335,6 +335,7 @@ static const char *const shader_cap_strings[] =
[SHADER_CAP_CLIP_PLANES] = "clip-planes",
[SHADER_CAP_DEPTH_BOUNDS] = "depth-bounds",
[SHADER_CAP_FLOAT64] = "float64",
[SHADER_CAP_FOG] = "fog",
[SHADER_CAP_GEOMETRY_SHADER] = "geometry-shader",
[SHADER_CAP_INT64] = "int64",
[SHADER_CAP_POINT_SIZE] = "point-size",
@@ -1424,6 +1425,28 @@ static void parse_test_directive(struct shader_runner *runner, const char *line)
else
runner->point_sprite = false;
}
else if (match_string(line, "fog", &line))
{
if (match_string(line, "disable", &line))
runner->fog_mode = FOG_MODE_DISABLE;
else if (match_string(line, "none", &line))
runner->fog_mode = FOG_MODE_NONE;
else if (match_string(line, "linear", &line))
runner->fog_mode = FOG_MODE_LINEAR;
else if (match_string(line, "exp", &line))
runner->fog_mode = FOG_MODE_EXP;
else if (match_string(line, "exp2", &line))
runner->fog_mode = FOG_MODE_EXP2;
else
fatal_error("Invalid fog mode '%s'.\n", line);
}
else if (match_string(line, "fog-colour", &line))
{
struct vec4 *v = &runner->fog_colour;
if (sscanf(line, "%f %f %f %f", &v->x, &v->y, &v->z, &v->w) < 4)
fatal_error("Malformed float4 constant '%s'.\n", line);
}
else
{
fatal_error("Unknown test directive '%s'.\n", line);
@@ -1872,6 +1895,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_c
runner->point_size = 1.0f;
runner->point_size_min = 1.0f;
runner->point_size_max = FLT_MAX;
runner->fog_mode = FOG_MODE_DISABLE;
runner->sample_mask = ~0u;
runner->depth_bounds = false;

View File

@@ -141,6 +141,7 @@ enum shader_cap
SHADER_CAP_CLIP_PLANES,
SHADER_CAP_DEPTH_BOUNDS,
SHADER_CAP_FLOAT64,
SHADER_CAP_FOG,
SHADER_CAP_GEOMETRY_SHADER,
SHADER_CAP_INT64,
SHADER_CAP_POINT_SIZE,
@@ -173,6 +174,15 @@ static inline unsigned int shader_runner_caps_get_feature_flags(const struct sha
return flags;
}
enum fog_mode
{
FOG_MODE_NONE = 0,
FOG_MODE_EXP = 1,
FOG_MODE_EXP2 = 2,
FOG_MODE_LINEAR = 3,
FOG_MODE_DISABLE,
};
struct shader_runner
{
const struct shader_runner_ops *ops;
@@ -222,6 +232,8 @@ struct shader_runner
struct vec4 clip_planes[8];
float point_size, point_size_min, point_size_max;
bool point_sprite;
struct vec4 fog_colour;
enum fog_mode fog_mode;
};
struct shader_runner_ops

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2021 Zebediah Figura for CodeWeavers
* Copyright 2021-2024 Elizabeth Figura for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -145,6 +145,7 @@ static bool init_test_context(struct d3d9_shader_runner *runner)
runner->caps.minimum_shader_model = SHADER_MODEL_2_0;
runner->caps.maximum_shader_model = SHADER_MODEL_3_0;
runner->caps.shader_caps[SHADER_CAP_CLIP_PLANES] = true;
runner->caps.shader_caps[SHADER_CAP_FOG] = true;
runner->caps.shader_caps[SHADER_CAP_POINT_SIZE] = true;
return true;
@@ -325,16 +326,19 @@ static bool d3d9_runner_dispatch(struct shader_runner *r, unsigned int x, unsign
fatal_error("Compute shaders are not supported.\n");
}
static uint32_t d3d_color_from_vec4(const struct vec4 *v)
{
return vkd3d_make_u32(vkd3d_make_u16(v->z * 255.0f, v->y * 255.0f),
vkd3d_make_u16(v->x * 255.0f, v->w * 255.0f));
}
static void d3d9_runner_clear(struct shader_runner *r, struct resource *resource, const struct vec4 *clear_value)
{
struct d3d9_shader_runner *runner = d3d9_shader_runner(r);
unsigned int colour;
HRESULT hr;
colour = vkd3d_make_u32(vkd3d_make_u16(clear_value->z * 255.0, clear_value->y * 255.0),
vkd3d_make_u16(clear_value->x * 255.0, clear_value->w * 255.0));
hr = IDirect3DDevice9_ColorFill(runner->device, d3d9_resource(resource)->surface, NULL, colour);
hr = IDirect3DDevice9_ColorFill(runner->device, d3d9_resource(resource)->surface,
NULL, d3d_color_from_vec4(clear_value));
ok(hr == S_OK, "Got hr %#lx.\n", hr);
}
@@ -498,6 +502,16 @@ static bool d3d9_runner_draw(struct shader_runner *r,
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSPRITEENABLE, runner->r.point_sprite);
ok(hr == D3D_OK, "Failed to set render state, hr %#lx.\n", hr);
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, (runner->r.fog_mode != FOG_MODE_DISABLE));
ok(hr == D3D_OK, "Failed to set render state, hr %#lx.\n", hr);
if (runner->r.fog_mode != FOG_MODE_DISABLE)
{
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, runner->r.fog_mode);
ok(hr == D3D_OK, "Failed to set render state, hr %#lx.\n", hr);
}
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, d3d_color_from_vec4(&runner->r.fog_colour));
ok(hr == D3D_OK, "Failed to set render state, hr %#lx.\n", hr);
hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
ok(hr == D3D_OK, "Failed to create vertex declaration, hr %#lx.\n", hr);
hr = IDirect3DDevice9_CreateVertexShader(device, ID3D10Blob_GetBufferPointer(vs_code), &vs);

View File

@@ -1,7 +1,7 @@
/*
* Shader runner which uses libvkd3d-shader to compile HLSL -> D3D bytecode -> SPIR-V
*
* Copyright 2020-2022 Zebediah Figura for CodeWeavers
* Copyright 2020-2024 Elizabeth Figura for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -267,15 +267,27 @@ static void vulkan_runner_destroy_resource(struct shader_runner *r, struct resou
free(resource);
}
static enum vkd3d_shader_fog_fragment_mode get_fog_fragment_mode(enum fog_mode mode)
{
switch (mode)
{
case FOG_MODE_DISABLE: return VKD3D_SHADER_FOG_FRAGMENT_NONE;
case FOG_MODE_NONE: return VKD3D_SHADER_FOG_FRAGMENT_LINEAR;
default: fatal_error("Unhandled fog mode %#x.\n", mode);
}
}
static bool compile_hlsl_and_scan(struct vulkan_shader_runner *runner, enum shader_type type)
{
struct vkd3d_shader_parameter_info parameter_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_PARAMETER_INFO};
struct vkd3d_shader_compile_info info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO};
struct vkd3d_shader_parameter1 parameters[1];
enum vkd3d_result ret;
if (!(runner->d3d_blobs[type] = compile_hlsl(&runner->r, type)))
return false;
info.next = &runner->signatures[type];
info.next = &parameter_info;
info.source.code = ID3D10Blob_GetBufferPointer(runner->d3d_blobs[type]);
info.source.size = ID3D10Blob_GetBufferSize(runner->d3d_blobs[type]);
if (runner->r.minimum_shader_model < SHADER_MODEL_4_0)
@@ -284,6 +296,15 @@ static bool compile_hlsl_and_scan(struct vulkan_shader_runner *runner, enum shad
info.source_type = VKD3D_SHADER_SOURCE_DXBC_TPF;
info.target_type = VKD3D_SHADER_TARGET_SPIRV_BINARY;
parameter_info.next = &runner->signatures[type];
parameter_info.parameter_count = ARRAY_SIZE(parameters);
parameter_info.parameters = parameters;
parameters[0].name = VKD3D_SHADER_PARAMETER_NAME_FOG_FRAGMENT_MODE;
parameters[0].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
parameters[0].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32;
parameters[0].u.immediate_constant.u.u32 = get_fog_fragment_mode(runner->r.fog_mode);
runner->signatures[type].type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_SIGNATURE_INFO;
runner->signatures[type].next = NULL;
ret = vkd3d_shader_scan(&info, NULL);
@@ -306,7 +327,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[17];
struct vkd3d_shader_parameter1 parameters[21];
unsigned int i;
char *messages;
int ret;
@@ -460,6 +481,30 @@ static bool compile_d3d_code(struct vulkan_shader_runner *runner,
parameters[16].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32;
parameters[16].u.immediate_constant.u.u32 = runner->r.point_sprite;
parameters[17].name = VKD3D_SHADER_PARAMETER_NAME_FOG_COLOUR;
parameters[17].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
parameters[17].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4;
memcpy(parameters[17].u.immediate_constant.u.f32_vec4, &runner->r.fog_colour, sizeof(struct vec4));
parameters[18].name = VKD3D_SHADER_PARAMETER_NAME_FOG_FRAGMENT_MODE;
parameters[18].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
parameters[18].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32;
parameters[18].u.immediate_constant.u.u32 = get_fog_fragment_mode(runner->r.fog_mode);
parameters[19].name = VKD3D_SHADER_PARAMETER_NAME_FOG_END;
parameters[19].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
parameters[19].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32;
parameters[20].name = VKD3D_SHADER_PARAMETER_NAME_FOG_SCALE;
parameters[20].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
parameters[20].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32;
if (runner->r.fog_mode == FOG_MODE_NONE)
{
parameters[19].u.immediate_constant.u.f32 = 0.0f;
parameters[20].u.immediate_constant.u.f32 = -1.0f;
}
parameter_info.parameter_count = ARRAY_SIZE(parameters);
parameter_info.parameters = parameters;
@@ -1656,6 +1701,7 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner)
}
runner->caps.shader_caps[SHADER_CAP_CLIP_PLANES] = true;
runner->caps.shader_caps[SHADER_CAP_FOG] = true;
runner->caps.shader_caps[SHADER_CAP_POINT_SIZE] = true;
device_desc.pEnabledFeatures = &features;
@@ -1758,6 +1804,9 @@ void run_shader_tests_vulkan(void)
runner.caps.maximum_shader_model = SHADER_MODEL_3_0;
run_shader_tests(&runner.r, &runner.caps, &vulkan_runner_ops, NULL);
/* Fog requires remapping, which is only correct for sm1. */
runner.caps.shader_caps[SHADER_CAP_FOG] = false;
runner.caps.minimum_shader_model = SHADER_MODEL_4_0;
runner.caps.maximum_shader_model = SHADER_MODEL_5_1;
run_shader_tests(&runner.r, &runner.caps, &vulkan_runner_ops, NULL);