Mostly preparation for the HLSL replacement pipe.
From: Elizabeth Figura zfigura@codeweavers.com
NVidia and WARP clamp before interpolation in the oFog case; AMD clamps only after interpolation (which we also do).
On the other hand, test_fog() proves that clamping should not be done before interpolation in the FFP case, for any driver.
In order to emulate an FFP vertex shader with a real compiled shader, we need to avoid clamping before interpolation, choosing the AMD behaviour here. --- dlls/wined3d/glsl_shader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 7bf9a5a9679..6c9f308b9f8 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -7366,7 +7366,7 @@ static GLuint shader_glsl_generate_vs3_rasterizer_input_setup(struct shader_glsl } else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG)) { - shader_addline(buffer, "%s = clamp(outputs[%u].%c, 0.0, 1.0);\n", + shader_addline(buffer, "%s = outputs[%u].%c;\n", legacy_syntax ? "gl_FogFragCoord" : "ffp_varying_fogcoord", output->register_idx, reg_mask[1]); }
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/stateblock.c | 7 +------ dlls/wined3d/utils.c | 24 +++++++++++++++--------- dlls/wined3d/wined3d_private.h | 4 ++-- 3 files changed, 18 insertions(+), 17 deletions(-)
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index f2307b97e08..a79eb7b5f9f 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -3697,14 +3697,9 @@ void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device, if (changed->texture_matrices) { struct wined3d_ffp_vs_constants constants; - struct wined3d_stream_info si; - - /* FIXME: This is a bit fragile. Ideally we should be calculating - * stream info from the stateblock state. */ - wined3d_stream_info_from_declaration(&si, context->state, &device->adapter->d3d_info);
for (i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i) - get_texture_matrix(&si, state, i, &constants.texture_matrices[i]); + get_texture_matrix(state, i, &constants.texture_matrices[i]); wined3d_device_context_push_constants(context, WINED3D_PUSH_CONSTANTS_VS_FFP, WINED3D_SHADER_CONST_FFP_TEXMATRIX, offsetof(struct wined3d_ffp_vs_constants, texture_matrices), diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 30572bc0ded..bf970b055a3 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -5649,23 +5649,29 @@ static void compute_texture_matrix(const struct wined3d_matrix *matrix, uint32_t *out_matrix = mat; }
-void get_texture_matrix(const struct wined3d_stream_info *si, - const struct wined3d_stateblock_state *state, const unsigned int tex, struct wined3d_matrix *mat) +static enum wined3d_format_id get_texcoord_format(const struct wined3d_vertex_declaration *decl, unsigned int index) +{ + for (unsigned int i = 0; i < decl->element_count; ++i) + { + if (decl->elements[i].usage == WINED3D_DECL_USAGE_TEXCOORD + && decl->elements[i].usage_idx == index) + return decl->elements[i].format->id; + } + + return WINED3DFMT_UNKNOWN; +} + +void get_texture_matrix(const struct wined3d_stateblock_state *state, + const unsigned int tex, struct wined3d_matrix *mat) { BOOL generated = (state->texture_states[tex][WINED3D_TSS_TEXCOORD_INDEX] & 0xffff0000) != WINED3DTSS_TCI_PASSTHRU; unsigned int coord_idx = min(state->texture_states[tex][WINED3D_TSS_TEXCOORD_INDEX] & 0x0000ffff, WINED3D_MAX_FFP_TEXTURES - 1); - enum wined3d_format_id attribute_format; - - if (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coord_idx))) - attribute_format = si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].format->id; - else - attribute_format = WINED3DFMT_UNKNOWN;
compute_texture_matrix(&state->transforms[WINED3D_TS_TEXTURE0 + tex], state->texture_states[tex][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS], - generated, attribute_format, mat); + generated, get_texcoord_format(state->vertex_declaration, coord_idx), mat); }
void get_pointsize_minmax(const struct wined3d_context *context, const struct wined3d_state *state, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 511d135a8f5..50418992163 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4376,8 +4376,8 @@ static inline BOOL shader_sampler_is_shadow(const struct wined3d_shader *shader,
void get_identity_matrix(struct wined3d_matrix *mat); void get_modelview_matrix(const struct wined3d_stateblock_state *state, unsigned int index, struct wined3d_matrix *mat); -void get_texture_matrix(const struct wined3d_stream_info *si, - const struct wined3d_stateblock_state *state, const unsigned int tex, struct wined3d_matrix *mat); +void get_texture_matrix(const struct wined3d_stateblock_state *state, + const unsigned int tex, struct wined3d_matrix *mat); void get_pointsize_minmax(const struct wined3d_context *context, const struct wined3d_state *state, float *out_min, float *out_max); void get_fog_start_end(const struct wined3d_context *context, const struct wined3d_state *state,
From: Elizabeth Figura zfigura@codeweavers.com
Make the function easier to understand, and use language that's a little less GL-centric. --- dlls/wined3d/utils.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-)
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index bf970b055a3..2011a724d27 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -5608,38 +5608,43 @@ static void compute_texture_matrix(const struct wined3d_matrix *matrix, uint32_t
mat = *matrix;
- /* Under Direct3D the R/Z coord can be used for translation, under - * OpenGL we use the Q coord instead. */ + /* When less than 4 components are provided for an attribute, the remaining + * components are filled with (..., 0, 0, 1). This is the case when using + * shaders in Direct3D as well as in GL and Vulkan. + * + * However, when using the Direct3D fixed function vertex pipeline, the + * texture coordinates transformed by texture matrices effectively have + * 1 in the first "default" component and 0 in the others (e.g. for + * R32_FLOAT the coordinates are (..., 1, 0, 0). + * + * We could approximate this by modifying the shader, but modifying uniforms + * is generally cheaper, so instead we change the matrix, copying the 2nd or + * 3rd column to the 4th. That is, whichever coefficients expect a value of + * 1 will instead be used as the coefficients for the 4th column, which + * actually has a value of 1. The coefficients for other columns don't need + * to be modified, since the corresponding texcoord components are zero. */ + if (!(flags & WINED3D_TTFF_PROJECTED) && !calculated_coords) { switch (format_id) { - /* Direct3D passes the default 1.0 in the 2nd coord, while GL - * passes it in the 4th. Swap 2nd and 4th coord. No need to - * store the value of mat._41 in mat._21 because the input - * value to the transformation will be 0, so the matrix value - * is irrelevant. */ case WINED3DFMT_R32_FLOAT: mat._41 = mat._21; mat._42 = mat._22; mat._43 = mat._23; mat._44 = mat._24; break; - /* See above, just 3rd and 4th coord. */ + case WINED3DFMT_R32G32_FLOAT: mat._41 = mat._31; mat._42 = mat._32; mat._43 = mat._33; mat._44 = mat._34; break; - case WINED3DFMT_R32G32B32_FLOAT: /* Opengl defaults match dx defaults */ - case WINED3DFMT_R32G32B32A32_FLOAT: /* No defaults apply, all app defined */
- /* This is to prevent swapping the matrix lines and put the default 4th coord = 1.0 - * into a bad place. The division elimination below will apply to make sure the - * 1.0 doesn't do anything bad. The caller will set this value if the stride is 0 - */ - case WINED3DFMT_UNKNOWN: /* No texture coords, 0/0/0/1 defaults are passed */ + case WINED3DFMT_R32G32B32_FLOAT: + case WINED3DFMT_R32G32B32A32_FLOAT: + case WINED3DFMT_UNKNOWN: break; default: FIXME("Unexpected fixed function texture coord input\n");
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/glsl_shader.c | 4 ++++ dlls/wined3d/shader_spirv.c | 2 ++ 2 files changed, 6 insertions(+)
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 6c9f308b9f8..7ff9ce0427b 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -11402,6 +11402,8 @@ static void shader_glsl_get_caps(const struct wined3d_adapter *adapter, struct s
TRACE("Shader model %u.\n", shader_model);
+ memset(caps, 0, sizeof(*caps)); + caps->vs_version = min(wined3d_settings.max_sm_vs, shader_model); caps->hs_version = min(wined3d_settings.max_sm_hs, shader_model); caps->ds_version = min(wined3d_settings.max_sm_ds, shader_model); @@ -11743,6 +11745,8 @@ static void glsl_vertex_pipe_vp_get_caps(const struct wined3d_adapter *adapter, { const struct wined3d_gl_info *gl_info = &wined3d_adapter_gl_const(adapter)->gl_info;
+ memset(caps, 0, sizeof(*caps)); + caps->emulated_flatshading = !needs_legacy_glsl_syntax(gl_info); caps->max_active_lights = WINED3D_MAX_ACTIVE_LIGHTS; caps->max_vertex_blend_matrices = MAX_VERTEX_BLENDS; diff --git a/dlls/wined3d/shader_spirv.c b/dlls/wined3d/shader_spirv.c index 51567c3d280..81600a7a459 100644 --- a/dlls/wined3d/shader_spirv.c +++ b/dlls/wined3d/shader_spirv.c @@ -1065,6 +1065,8 @@ static void shader_spirv_init_context_state(struct wined3d_context *context)
static void shader_spirv_get_caps(const struct wined3d_adapter *adapter, struct shader_caps *caps) { + memset(caps, 0, sizeof(*caps)); + caps->vs_version = min(wined3d_settings.max_sm_vs, 5); caps->hs_version = min(wined3d_settings.max_sm_hs, 5); caps->ds_version = min(wined3d_settings.max_sm_ds, 5);
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/shader_spirv.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/wined3d/shader_spirv.c b/dlls/wined3d/shader_spirv.c index 81600a7a459..7825ee7e02c 100644 --- a/dlls/wined3d/shader_spirv.c +++ b/dlls/wined3d/shader_spirv.c @@ -1198,6 +1198,7 @@ static void spirv_fragment_pipe_vk_fp_disable(const struct wined3d_context *cont static void spirv_fragment_pipe_vk_fp_get_caps(const struct wined3d_adapter *adapter, struct fragment_caps *caps) { memset(caps, 0, sizeof(*caps)); + caps->max_blend_stages = WINED3D_MAX_FFP_TEXTURES; }
static unsigned int spirv_fragment_pipe_vk_fp_get_emul_mask(const struct wined3d_adapter *adapter)
This merge request was approved by Jan Sikorski.