mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-09-12 18:50:22 -07:00
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:
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
@@ -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)
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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 = ¶meter_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);
|
||||
|
Reference in New Issue
Block a user