From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/ffp_hlsl.c | 489 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 486 insertions(+), 3 deletions(-)
diff --git a/dlls/wined3d/ffp_hlsl.c b/dlls/wined3d/ffp_hlsl.c index 959ecd4195a..bc726c7ce10 100644 --- a/dlls/wined3d/ffp_hlsl.c +++ b/dlls/wined3d/ffp_hlsl.c @@ -146,11 +146,494 @@ static bool ffp_hlsl_generate_vertex_shader(const struct wined3d_ffp_vs_settings return true; }
+static const char *get_fragment_op_arg(struct wined3d_string_buffer *buffer, + unsigned int argnum, unsigned int stage, unsigned int arg) +{ + const char *ret; + + if (arg == ARG_UNUSED) + return "<unused arg>"; + + switch (arg & WINED3DTA_SELECTMASK) + { + case WINED3DTA_DIFFUSE: + ret = "i.diffuse"; + break; + + case WINED3DTA_CURRENT: + ret = "ret"; + break; + + case WINED3DTA_TEXTURE: + switch (stage) + { + case 0: ret = "tex0"; break; + case 1: ret = "tex1"; break; + case 2: ret = "tex2"; break; + case 3: ret = "tex3"; break; + case 4: ret = "tex4"; break; + case 5: ret = "tex5"; break; + case 6: ret = "tex6"; break; + case 7: ret = "tex7"; break; + default: + ret = "<invalid texture>"; + break; + } + break; + + case WINED3DTA_TFACTOR: + ret = "c.texture_factor"; + break; + + case WINED3DTA_SPECULAR: + ret = "i.specular"; + break; + + case WINED3DTA_TEMP: + ret = "temp_reg"; + break; + + case WINED3DTA_CONSTANT: + switch (stage) + { + case 0: ret = "c.texture_constants[0]"; break; + case 1: ret = "c.texture_constants[1]"; break; + case 2: ret = "c.texture_constants[2]"; break; + case 3: ret = "c.texture_constants[3]"; break; + case 4: ret = "c.texture_constants[4]"; break; + case 5: ret = "c.texture_constants[5]"; break; + case 6: ret = "c.texture_constants[6]"; break; + case 7: ret = "c.texture_constants[7]"; break; + default: + ret = "<invalid constant>"; + break; + } + break; + + default: + return "<unhandled arg>"; + } + + if (arg & WINED3DTA_COMPLEMENT) + { + shader_addline(buffer, " arg%u = 1.0 - %s;\n", argnum, ret); + if (argnum == 0) + ret = "arg0"; + else if (argnum == 1) + ret = "arg1"; + else if (argnum == 2) + ret = "arg2"; + } + + if (arg & WINED3DTA_ALPHAREPLICATE) + { + shader_addline(buffer, " arg%u = %s.w;\n", argnum, ret); + if (argnum == 0) + ret = "arg0"; + else if (argnum == 1) + ret = "arg1"; + else if (argnum == 2) + ret = "arg2"; + } + + return ret; +} + +static void generate_fragment_op(struct wined3d_string_buffer *buffer, unsigned int stage, bool color, + bool alpha, bool tmp_dst, unsigned int op, unsigned int dw_arg0, unsigned int dw_arg1, unsigned int dw_arg2) +{ + const char *dstmask, *dstreg, *arg0, *arg1, *arg2; + + if (color && alpha) + dstmask = ""; + else if (color) + dstmask = ".xyz"; + else + dstmask = ".w"; + + dstreg = tmp_dst ? "temp_reg" : "ret"; + + arg0 = get_fragment_op_arg(buffer, 0, stage, dw_arg0); + arg1 = get_fragment_op_arg(buffer, 1, stage, dw_arg1); + arg2 = get_fragment_op_arg(buffer, 2, stage, dw_arg2); + + switch (op) + { + case WINED3D_TOP_DISABLE: + break; + + case WINED3D_TOP_SELECT_ARG1: + shader_addline(buffer, " %s%s = %s%s;\n", dstreg, dstmask, arg1, dstmask); + break; + + case WINED3D_TOP_SELECT_ARG2: + shader_addline(buffer, " %s%s = %s%s;\n", dstreg, dstmask, arg2, dstmask); + break; + + case WINED3D_TOP_MODULATE: + shader_addline(buffer, " %s%s = %s%s * %s%s;\n", dstreg, dstmask, arg1, dstmask, arg2, dstmask); + break; + + case WINED3D_TOP_MODULATE_4X: + shader_addline(buffer, " %s%s = saturate(%s%s * %s%s * 4.0);\n", + dstreg, dstmask, arg1, dstmask, arg2, dstmask); + break; + + case WINED3D_TOP_MODULATE_2X: + shader_addline(buffer, " %s%s = saturate(%s%s * %s%s * 2.0);\n", + dstreg, dstmask, arg1, dstmask, arg2, dstmask); + break; + + case WINED3D_TOP_ADD: + shader_addline(buffer, " %s%s = saturate(%s%s + %s%s);\n", + dstreg, dstmask, arg1, dstmask, arg2, dstmask); + break; + + case WINED3D_TOP_ADD_SIGNED: + shader_addline(buffer, " %s%s = saturate(%s%s + (%s - 0.5)%s);\n", + dstreg, dstmask, arg1, dstmask, arg2, dstmask); + break; + + case WINED3D_TOP_ADD_SIGNED_2X: + shader_addline(buffer, " %s%s = saturate((%s%s + (%s - 0.5)%s) * 2.0);\n", + dstreg, dstmask, arg1, dstmask, arg2, dstmask); + break; + + case WINED3D_TOP_SUBTRACT: + shader_addline(buffer, " %s%s = saturate(%s%s - %s%s);\n", + dstreg, dstmask, arg1, dstmask, arg2, dstmask); + break; + + case WINED3D_TOP_ADD_SMOOTH: + shader_addline(buffer, " %s%s = saturate((1.0 - %s)%s * %s%s + %s%s);\n", + dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg1, dstmask); + break; + + case WINED3D_TOP_BLEND_DIFFUSE_ALPHA: + arg0 = get_fragment_op_arg(buffer, 0, stage, WINED3DTA_DIFFUSE); + shader_addline(buffer, " %s%s = lerp(%s%s, %s%s, %s.w);\n", + dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0); + break; + + case WINED3D_TOP_BLEND_TEXTURE_ALPHA: + arg0 = get_fragment_op_arg(buffer, 0, stage, WINED3DTA_TEXTURE); + shader_addline(buffer, " %s%s = lerp(%s%s, %s%s, %s.w);\n", + dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0); + break; + + case WINED3D_TOP_BLEND_FACTOR_ALPHA: + arg0 = get_fragment_op_arg(buffer, 0, stage, WINED3DTA_TFACTOR); + shader_addline(buffer, " %s%s = lerp(%s%s, %s%s, %s.w);\n", + dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0); + break; + + case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM: + arg0 = get_fragment_op_arg(buffer, 0, stage, WINED3DTA_TEXTURE); + shader_addline(buffer, " %s%s = saturate(%s%s * (1.0 - %s.w) + %s%s);\n", + dstreg, dstmask, arg2, dstmask, arg0, arg1, dstmask); + break; + + case WINED3D_TOP_BLEND_CURRENT_ALPHA: + arg0 = get_fragment_op_arg(buffer, 0, stage, WINED3DTA_CURRENT); + shader_addline(buffer, " %s%s = lerp(%s%s, %s%s, %s.w);\n", + dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0); + break; + + case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR: + shader_addline(buffer, " %s%s = saturate(%s%s * %s.w + %s%s);\n", + dstreg, dstmask, arg2, dstmask, arg1, arg1, dstmask); + break; + + case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA: + shader_addline(buffer, " %s%s = saturate(%s%s * %s%s + %s.w);\n", + dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg1); + break; + + case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR: + shader_addline(buffer, " %s%s = saturate(%s%s * (1.0 - %s.w) + %s%s);\n", + dstreg, dstmask, arg2, dstmask, arg1, arg1, dstmask); + break; + case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA: + shader_addline(buffer, " %s%s = saturate((1.0 - %s)%s * %s%s + %s.w);\n", + dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg1); + break; + + case WINED3D_TOP_BUMPENVMAP: + case WINED3D_TOP_BUMPENVMAP_LUMINANCE: + /* These are handled in the first pass, nothing to do. */ + break; + + case WINED3D_TOP_DOTPRODUCT3: + shader_addline(buffer, " %s%s = saturate(dot(%s.xyz - 0.5, %s.xyz - 0.5) * 4.0);\n", + dstreg, dstmask, arg1, arg2); + break; + + case WINED3D_TOP_MULTIPLY_ADD: + shader_addline(buffer, " %s%s = saturate(%s%s * %s%s + %s%s);\n", + dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg0, dstmask); + break; + + case WINED3D_TOP_LERP: + /* MSDN isn't quite right here. */ + shader_addline(buffer, " %s%s = lerp(%s%s, %s%s, %s%s);\n", + dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0, dstmask); + break; + + default: + FIXME("Unhandled operation %#x.\n", op); + break; + } +} + static bool ffp_hlsl_generate_pixel_shader(const struct ffp_frag_settings *settings, - struct wined3d_string_buffer *string) + struct wined3d_string_buffer *buffer) { - FIXME("Not yet implemented.\n"); - return false; + uint8_t tex_map = 0; + unsigned int i; + + if (settings->color_key_enabled) + FIXME("Ignoring color key.\n"); + + /* Find out which textures are read. */ + for (i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i) + { + unsigned int arg0, arg1, arg2; + + if (settings->op[i].cop == WINED3D_TOP_DISABLE) + break; + + arg0 = settings->op[i].carg0 & WINED3DTA_SELECTMASK; + arg1 = settings->op[i].carg1 & WINED3DTA_SELECTMASK; + arg2 = settings->op[i].carg2 & WINED3DTA_SELECTMASK; + + if (arg0 == WINED3DTA_TEXTURE || arg1 == WINED3DTA_TEXTURE || arg2 == WINED3DTA_TEXTURE + || (i == 0 && settings->color_key_enabled)) + tex_map |= 1u << i; + + switch (settings->op[i].cop) + { + case WINED3D_TOP_BUMPENVMAP_LUMINANCE: + case WINED3D_TOP_BUMPENVMAP: + case WINED3D_TOP_BLEND_TEXTURE_ALPHA: + case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM: + tex_map |= 1u << i; + break; + + default: + break; + } + + if (settings->op[i].aop == WINED3D_TOP_DISABLE) + continue; + + arg0 = settings->op[i].aarg0 & WINED3DTA_SELECTMASK; + arg1 = settings->op[i].aarg1 & WINED3DTA_SELECTMASK; + arg2 = settings->op[i].aarg2 & WINED3DTA_SELECTMASK; + + if (arg0 == WINED3DTA_TEXTURE || arg1 == WINED3DTA_TEXTURE || arg2 == WINED3DTA_TEXTURE) + tex_map |= 1u << i; + } + + for (i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i) + { + const char *sampler_type; + + if (!(tex_map & (1u << i))) + continue; + + switch (settings->op[i].tex_type) + { + case WINED3D_GL_RES_TYPE_TEX_1D: + sampler_type = "1D"; + break; + case WINED3D_GL_RES_TYPE_TEX_2D: + sampler_type = "2D"; + break; + case WINED3D_GL_RES_TYPE_TEX_3D: + sampler_type = "3D"; + break; + case WINED3D_GL_RES_TYPE_TEX_CUBE: + sampler_type = "CUBE"; + break; + default: + FIXME("Unhandled sampler type %#x.\n", settings->op[i].tex_type); + sampler_type = NULL; + break; + } + if (sampler_type) + shader_addline(buffer, "sampler%s ps_sampler%u : register(s%u);\n", sampler_type, i, i); + + shader_addline(buffer, "static float4 tex%u;\n", i); + } + + /* This must be kept in sync with struct wined3d_ffp_vs_constants. */ + shader_addline(buffer, "uniform struct\n"); + shader_addline(buffer, "{\n"); + shader_addline(buffer, " float4 texture_constants[%u];\n", WINED3D_MAX_FFP_TEXTURES); + shader_addline(buffer, " float4 texture_factor;\n"); + shader_addline(buffer, " float4 specular_enable;\n"); + shader_addline(buffer, " float4 color_key[2];\n"); + shader_addline(buffer, "} c;\n"); + + shader_addline(buffer, "struct input\n"); + shader_addline(buffer, "{\n"); + shader_addline(buffer, " float4 pos : POSITION;\n"); + shader_addline(buffer, " float4 diffuse : COLOR0;\n"); + shader_addline(buffer, " float4 specular : COLOR1;\n"); + shader_addline(buffer, " float4 texcoord[%u] : TEXCOORD;\n", WINED3D_MAX_FFP_TEXTURES); + shader_addline(buffer, "};\n\n"); + + shader_addline(buffer, "struct output\n"); + shader_addline(buffer, "{\n"); + shader_addline(buffer, " float4 colour : COLOR;\n"); + shader_addline(buffer, "};\n\n"); + + shader_addline(buffer, "void main(in struct input i, out struct output o)\n"); + shader_addline(buffer, "{\n"); + + shader_addline(buffer, " float4 texcoord[%u];\n", WINED3D_MAX_FFP_TEXTURES); + shader_addline(buffer, " float4 temp_reg = 0.0;\n\n"); + shader_addline(buffer, " float4 ret, arg0, arg1, arg2;\n\n"); + + for (i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i) + { + if (tex_map & (1u << i)) + { + if (settings->pointsprite || (settings->texcoords_initialized & (1u << i))) + shader_addline(buffer, " texcoord[%u] = i.texcoord[%u];\n", i, i); + else + shader_addline(buffer, " texcoord[%u] = 0.0;\n", i); + } + } + + /* Texture sampling. */ + + for (i = 0; i < WINED3D_MAX_FFP_TEXTURES && settings->op[i].cop != WINED3D_TOP_DISABLE; ++i) + { + const char *texture_function, *coord_mask; + bool proj; + + if (!(tex_map & (1u << i))) + continue; + + if (settings->op[i].projected == WINED3D_PROJECTION_NONE) + { + proj = false; + } + else if (settings->op[i].projected == WINED3D_PROJECTION_COUNT4 + || settings->op[i].projected == WINED3D_PROJECTION_COUNT3) + { + proj = true; + } + else + { + FIXME("Unexpected projection mode %d.\n", settings->op[i].projected); + proj = true; + } + + switch (settings->op[i].tex_type) + { + case WINED3D_GL_RES_TYPE_TEX_1D: + texture_function = "tex1D"; + coord_mask = "x"; + break; + case WINED3D_GL_RES_TYPE_TEX_2D: + texture_function = "tex2D"; + coord_mask = "xy"; + break; + case WINED3D_GL_RES_TYPE_TEX_3D: + texture_function = "tex3D"; + coord_mask = "xyz"; + break; + case WINED3D_GL_RES_TYPE_TEX_CUBE: + texture_function = "texCUBE"; + coord_mask = "xyz"; + break; + default: + FIXME("Unhandled texture type %#x.\n", settings->op[i].tex_type); + texture_function = ""; + coord_mask = "xyzw"; + proj = false; + break; + } + + if (proj) + coord_mask = "xyzw"; + + if (i > 0 + && (settings->op[i - 1].cop == WINED3D_TOP_BUMPENVMAP + || settings->op[i - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE)) + { + FIXME("I could not speak, and my eyes failed.\n"); + } + else if (settings->op[i].projected == WINED3D_PROJECTION_COUNT3) + { + shader_addline(buffer, " tex%u = %s%s(ps_sampler%u, texcoord[%u].xyzz);\n", + i, texture_function, proj ? "proj" : "", i, i); + } + else + { + shader_addline(buffer, " tex%u = %s%s(ps_sampler%u, texcoord[%u].%s);\n", + i, texture_function, proj ? "proj" : "", i, i, coord_mask); + } + } + + shader_addline(buffer, " ret = i.diffuse;\n"); + + for (i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i) + { + bool op_equal; + + if (settings->op[i].cop == WINED3D_TOP_DISABLE) + break; + + if (settings->op[i].cop == WINED3D_TOP_SELECT_ARG1 + && settings->op[i].aop == WINED3D_TOP_SELECT_ARG1) + op_equal = settings->op[i].carg1 == settings->op[i].aarg1; + else if (settings->op[i].cop == WINED3D_TOP_SELECT_ARG1 + && settings->op[i].aop == WINED3D_TOP_SELECT_ARG2) + op_equal = settings->op[i].carg1 == settings->op[i].aarg2; + else if (settings->op[i].cop == WINED3D_TOP_SELECT_ARG2 + && settings->op[i].aop == WINED3D_TOP_SELECT_ARG1) + op_equal = settings->op[i].carg2 == settings->op[i].aarg1; + else if (settings->op[i].cop == WINED3D_TOP_SELECT_ARG2 + && settings->op[i].aop == WINED3D_TOP_SELECT_ARG2) + op_equal = settings->op[i].carg2 == settings->op[i].aarg2; + else + op_equal = settings->op[i].aop == settings->op[i].cop + && settings->op[i].carg0 == settings->op[i].aarg0 + && settings->op[i].carg1 == settings->op[i].aarg1 + && settings->op[i].carg2 == settings->op[i].aarg2; + + if (settings->op[i].aop == WINED3D_TOP_DISABLE) + { + generate_fragment_op(buffer, i, true, false, settings->op[i].tmp_dst, + settings->op[i].cop, settings->op[i].carg0, + settings->op[i].carg1, settings->op[i].carg2); + } + else if (op_equal) + { + generate_fragment_op(buffer, i, true, true, settings->op[i].tmp_dst, + settings->op[i].cop, settings->op[i].carg0, + settings->op[i].carg1, settings->op[i].carg2); + } + else if (settings->op[i].cop != WINED3D_TOP_BUMPENVMAP + && settings->op[i].cop != WINED3D_TOP_BUMPENVMAP_LUMINANCE) + { + generate_fragment_op(buffer, i, true, false, settings->op[i].tmp_dst, + settings->op[i].cop, settings->op[i].carg0, + settings->op[i].carg1, settings->op[i].carg2); + generate_fragment_op(buffer, i, false, true, settings->op[i].tmp_dst, + settings->op[i].aop, settings->op[i].aarg0, + settings->op[i].aarg1, settings->op[i].aarg2); + } + } + + shader_addline(buffer, " o.colour = i.specular * c.specular_enable + ret;\n"); + + shader_addline(buffer, "}\n"); + + return true; }
static bool compile_hlsl_shader(const struct wined3d_string_buffer *hlsl,
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/ffp_hlsl.c | 40 +++++++++++++++----- dlls/wined3d/stateblock.c | 77 ++++++++++++++++++++++++++++----------- 2 files changed, 86 insertions(+), 31 deletions(-)
diff --git a/dlls/wined3d/ffp_hlsl.c b/dlls/wined3d/ffp_hlsl.c index bc726c7ce10..973fc064ed7 100644 --- a/dlls/wined3d/ffp_hlsl.c +++ b/dlls/wined3d/ffp_hlsl.c @@ -30,15 +30,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); static bool ffp_hlsl_generate_vertex_shader(const struct wined3d_ffp_vs_settings *settings, struct wined3d_string_buffer *buffer) { + struct wined3d_string_buffer texcoord; + if (settings->lighting) FIXME("Ignoring lighting.\n");
if (settings->point_size) FIXME("Ignoring point size.\n");
- if (settings->transformed) - FIXME("Ignoring pretransformed vertices.\n"); - if (settings->vertexblends) FIXME("Ignoring vertex blend.\n");
@@ -99,12 +98,27 @@ static bool ffp_hlsl_generate_vertex_shader(const struct wined3d_ffp_vs_settings
shader_addline(buffer, "void main(in struct input i, out struct output o)\n"); shader_addline(buffer, "{\n"); - shader_addline(buffer, " float4 ec_pos = 0.0;\n\n");
- shader_addline(buffer, " ec_pos += mul(c.modelview_matrices[0], float4(i.pos.xyz, 1.0));\n\n"); + if (settings->transformed) + { + shader_addline(buffer, " float4 ec_pos = float4(i.pos.xyz, 1.0);\n"); + /* We reuse the projection matrix to undo the transformation from clip + * coordinates to pixel coordinates. */ + shader_addline(buffer, " float4 out_pos = mul(c.projection_matrix, ec_pos);\n\n"); + + /* Use a ternary; this is not the most natural way to write it but is + * nicer to the compiler. */ + shader_addline(buffer, " o.pos = (i.pos.w == 0.0 ? out_pos : out_pos / i.pos.w);\n"); + } + else + { + shader_addline(buffer, " float4 ec_pos = 0.0;\n\n"); + + shader_addline(buffer, " ec_pos += mul(c.modelview_matrices[0], float4(i.pos.xyz, 1.0));\n\n");
- shader_addline(buffer, " o.pos = mul(c.projection_matrix, ec_pos);\n"); - shader_addline(buffer, " ec_pos /= ec_pos.w;\n\n"); + shader_addline(buffer, " o.pos = mul(c.projection_matrix, ec_pos);\n"); + shader_addline(buffer, " ec_pos /= ec_pos.w;\n\n"); + }
/* No lighting. */ if (settings->diffuse) @@ -113,14 +127,16 @@ static bool ffp_hlsl_generate_vertex_shader(const struct wined3d_ffp_vs_settings shader_addline(buffer, " o.diffuse = 1.0;\n"); shader_addline(buffer, " o.specular = i.specular;\n\n");
+ string_buffer_init(&texcoord); for (unsigned int i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i) { + string_buffer_clear(&texcoord); + switch (settings->texgen[i] & 0xffff0000) { case WINED3DTSS_TCI_PASSTHRU: if (settings->texcoords & (1u << i)) - shader_addline(buffer, " o.texcoord%u = mul(c.texture_matrices[%u], i.texcoord[%u]);\n", - i, i, settings->texgen[i] & 0x0000ffff); + shader_addline(&texcoord, "i.texcoord[%u]", settings->texgen[i] & 0x0000ffff); else continue; break; @@ -129,7 +145,13 @@ static bool ffp_hlsl_generate_vertex_shader(const struct wined3d_ffp_vs_settings FIXME("Unhandled texgen %#x.\n", settings->texgen[i]); break; } + + if (settings->transformed) + shader_addline(buffer, " o.texcoord%u = %s;\n", i, texcoord.buffer); + else + shader_addline(buffer, " o.texcoord%u = mul(c.texture_matrices[%u], %s);\n", i, i, texcoord.buffer); } + string_buffer_free(&texcoord);
switch (settings->fog_mode) { diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index d24b356dc1f..9e10dbafb10 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -67,6 +67,7 @@ struct wined3d_saved_states uint32_t ffp_vs_settings : 1; uint32_t ffp_ps_settings : 1; uint32_t rasterizer_state : 1; + uint32_t position_transformed : 1; };
struct stage_state @@ -1577,10 +1578,18 @@ void CDECL wined3d_stateblock_set_vertex_declaration(struct wined3d_stateblock * }
if (declaration->position_transformed != prev->position_transformed) + { + /* We reuse the projection matrix to undo the translation between + * clip coordinates and pixel coordinates, so we need to invalidate + * it here. */ stateblock->changed.ffp_vs_settings = 1; + stateblock->changed.position_transformed = 1; + stateblock->changed.transforms = 1; + } } else { + stateblock->changed.position_transformed = 1; stateblock->changed.ffp_vs_settings = 1; } } @@ -3537,33 +3546,57 @@ void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device, } }
- if (changed->transforms) + if (state->vertex_declaration && state->vertex_declaration->position_transformed) { - for (i = 0; i < ARRAY_SIZE(changed->transform); ++i) + /* We reuse the projection matrix to undo the translation between + * clip coordinates and pixel coordinates. */ + if (changed->position_transformed || changed->viewport) { - map = changed->transform[i]; - while (map) + float x = state->viewport.x; + float y = state->viewport.y; + float w = state->viewport.width; + float h = state->viewport.height; + float x_scale = 2.0f / w; + float x_offset = (-(2.0f * x) - w) / w; + float y_scale = 2.0f / -h; + float y_offset = (-(2.0f * y) - h) / -h; + float z_scale = state->rs[WINED3D_RS_ZENABLE] ? 1.0f : 0.0f; + const struct wined3d_matrix matrix = { - j = wined3d_bit_scan(&map); - idx = i * word_bit_count + j; + x_scale, 0.0f, 0.0f, 0.0f, + 0.0f, y_scale, 0.0f, 0.0f, + 0.0f, 0.0f, z_scale, 0.0f, + x_offset, y_offset, 0.0f, 1.0f, + }; + + wined3d_device_context_push_constants(context, WINED3D_PUSH_CONSTANTS_VS_FFP, WINED3D_SHADER_CONST_FFP_PROJ, + offsetof(struct wined3d_ffp_vs_constants, projection_matrix), sizeof(matrix), &matrix); + }
- if (idx == WINED3D_TS_VIEW) - { - changed->lights = 1; - changed->clipplane = wined3d_mask_from_size(WINED3D_MAX_CLIP_DISTANCES); - } + if (wined3d_bitmap_is_set(changed->transform, WINED3D_TS_PROJECTION)) + { + /* wined3d_ffp_vs_settings.ortho_fog still needs the + * device state to be set. */ + wined3d_device_set_transform(device, WINED3D_TS_PROJECTION, &state->transforms[WINED3D_TS_PROJECTION]); + } + } + else if (changed->transforms) + { + if (wined3d_bitmap_is_set(changed->transform, WINED3D_TS_VIEW)) + { + changed->lights = 1; + changed->clipplane = wined3d_mask_from_size(WINED3D_MAX_CLIP_DISTANCES); + }
- if (idx == WINED3D_TS_PROJECTION) - { - wined3d_device_context_push_constants(context, - WINED3D_PUSH_CONSTANTS_VS_FFP, WINED3D_SHADER_CONST_FFP_PROJ, - offsetof(struct wined3d_ffp_vs_constants, projection_matrix), - sizeof(state->transforms[idx]), &state->transforms[idx]); - /* wined3d_ffp_vs_settings.ortho_fog and vs_compile_args.ortho_fog - * still need the device state to be set. */ - wined3d_device_set_transform(device, idx, &state->transforms[idx]); - } - } + if (wined3d_bitmap_is_set(changed->transform, WINED3D_TS_PROJECTION) || changed->position_transformed) + { + wined3d_device_context_push_constants(context, + WINED3D_PUSH_CONSTANTS_VS_FFP, WINED3D_SHADER_CONST_FFP_PROJ, + offsetof(struct wined3d_ffp_vs_constants, projection_matrix), + sizeof(state->transforms[WINED3D_TS_PROJECTION]), &state->transforms[WINED3D_TS_PROJECTION]); + /* wined3d_ffp_vs_settings.ortho_fog and vs_compile_args.ortho_fog + * still need the device state to be set. */ + wined3d_device_set_transform(device, WINED3D_TS_PROJECTION, &state->transforms[WINED3D_TS_PROJECTION]); }
/* Clip planes are affected by the view matrix. */
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/d3d8/device.c | 1 + dlls/d3d9/device.c | 1 + dlls/ddraw/device.c | 3 +++ dlls/ddraw/surface.c | 5 +++++ dlls/wined3d/stateblock.c | 17 ++++++++++++++++- dlls/wined3d/wined3d.spec | 1 + include/wine/wined3d.h | 1 + 7 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index 8a1393909d3..b5bf370790a 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -1601,6 +1601,7 @@ static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface, wined3d_device_context_set_depth_stencil_view(device->immediate_context, original_dsv); } d3d8_surface_release_rendertarget_view(rt_impl, rtv); + wined3d_stateblock_depth_buffer_changed(device->state); }
wined3d_mutex_unlock(); diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index e9499a3be9b..3ba5764af60 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -2200,6 +2200,7 @@ static HRESULT WINAPI d3d9_device_SetDepthStencilSurface(IDirect3DDevice9Ex *ifa wined3d_mutex_lock(); rtv = ds_impl ? d3d9_surface_acquire_rendertarget_view(ds_impl) : NULL; hr = wined3d_device_context_set_depth_stencil_view(device->immediate_context, rtv); + wined3d_stateblock_depth_buffer_changed(device->state); d3d9_surface_release_rendertarget_view(ds_impl, rtv); wined3d_mutex_unlock();
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 399857adf9d..360f93b516b 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -3410,6 +3410,7 @@ static void d3d_device_sync_rendertarget(struct d3d_device *device) dsv = device->target_ds ? ddraw_surface_get_rendertarget_view(device->target_ds) : NULL; if (FAILED(wined3d_device_context_set_depth_stencil_view(device->immediate_context, dsv))) ERR("wined3d_device_context_set_depth_stencil_view failed.\n"); + wined3d_stateblock_depth_buffer_changed(device->state);
if (device->hardware_device) return; @@ -6820,6 +6821,7 @@ enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device { TRACE("Setting wined3d depth stencil to NULL\n"); wined3d_device_context_set_depth_stencil_view(device->immediate_context, NULL); + wined3d_stateblock_depth_buffer_changed(device->state); device->target_ds = NULL; return WINED3D_ZB_FALSE; } @@ -6827,6 +6829,7 @@ enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device device->target_ds = impl_from_IDirectDrawSurface7(depthStencil); wined3d_device_context_set_depth_stencil_view(device->immediate_context, ddraw_surface_get_rendertarget_view(device->target_ds)); + wined3d_stateblock_depth_buffer_changed(device->state);
IDirectDrawSurface7_Release(depthStencil); return WINED3D_ZB_TRUE; diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 179262a629e..8cdaa48b753 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -2191,6 +2191,7 @@ static HRESULT ddraw_surface_delete_attached_surface(struct ddraw_surface *surfa { struct wined3d_rendertarget_view *dsv; struct ddraw_surface *prev = surface; + struct d3d_device *device;
TRACE("surface %p, attachment %p, detach_iface %p.\n", surface, attachment, detach_iface);
@@ -2239,7 +2240,11 @@ static HRESULT ddraw_surface_delete_attached_surface(struct ddraw_surface *surfa * but don't cleanup properly after the relevant dll is unloaded. */ dsv = wined3d_device_context_get_depth_stencil_view(surface->ddraw->immediate_context); if (attachment->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER && dsv == attachment->wined3d_rtv) + { wined3d_device_context_set_depth_stencil_view(surface->ddraw->immediate_context, NULL); + LIST_FOR_EACH_ENTRY(device, &surface->ddraw->d3ddevice_list, struct d3d_device, ddraw_entry) + wined3d_stateblock_depth_buffer_changed(device->state); + } wined3d_mutex_unlock();
/* Set attached_iface to NULL before releasing it, the surface may go diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index 9e10dbafb10..80c1a6ea5b7 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -3560,7 +3560,8 @@ void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device, float x_offset = (-(2.0f * x) - w) / w; float y_scale = 2.0f / -h; float y_offset = (-(2.0f * y) - h) / -h; - float z_scale = state->rs[WINED3D_RS_ZENABLE] ? 1.0f : 0.0f; + bool depth = (state->rs[WINED3D_RS_ZENABLE] && context->state->fb.depth_stencil); + float z_scale = depth ? 1.0f : 0.0f; const struct wined3d_matrix matrix = { x_scale, 0.0f, 0.0f, 0.0f, @@ -3926,3 +3927,17 @@ void CDECL wined3d_stateblock_texture_changed(struct wined3d_stateblock *statebl stateblock->changed.textures |= (1u << i); } } + +void CDECL wined3d_stateblock_depth_buffer_changed(struct wined3d_stateblock *stateblock) +{ + struct wined3d_vertex_declaration *decl = stateblock->stateblock_state.vertex_declaration; + + /* The presence of a depth buffer affects depth clipping when drawing RHW. + * The depth buffer is not part of the stateblock, though, so we need a + * separate function to invalidate it. + * We pass this via the projection matrix, but use + * changed->position_transformed to invalidate it. */ + + if (decl && decl->position_transformed) + stateblock->changed.position_transformed = 1; +} diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 4d19e6d975f..16c7624eb9c 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -232,6 +232,7 @@ @ cdecl wined3d_stateblock_capture(ptr ptr) @ cdecl wined3d_stateblock_create(ptr ptr long ptr) @ cdecl wined3d_stateblock_decref(ptr) +@ cdecl wined3d_stateblock_depth_buffer_changed(ptr) @ cdecl wined3d_stateblock_get_light(ptr long ptr ptr) @ cdecl wined3d_stateblock_get_ps_consts_b(ptr long long ptr) @ cdecl wined3d_stateblock_get_ps_consts_f(ptr long long ptr) diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 73af1be484b..b9ae23bac16 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2760,6 +2760,7 @@ void __cdecl wined3d_stateblock_capture(struct wined3d_stateblock *stateblock, HRESULT __cdecl wined3d_stateblock_create(struct wined3d_device *device, const struct wined3d_stateblock *device_state, enum wined3d_stateblock_type type, struct wined3d_stateblock **stateblock); ULONG __cdecl wined3d_stateblock_decref(struct wined3d_stateblock *stateblock); +void __cdecl wined3d_stateblock_depth_buffer_changed(struct wined3d_stateblock *stateblock); HRESULT __cdecl wined3d_stateblock_get_light(const struct wined3d_stateblock *stateblock, UINT light_idx, struct wined3d_light *light, BOOL *enabled); HRESULT __cdecl wined3d_stateblock_get_ps_consts_b(struct wined3d_stateblock *stateblock,
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/ffp_hlsl.c | 210 ++++++++++++++++++++++++++++++--- dlls/wined3d/shader.c | 2 +- dlls/wined3d/wined3d_private.h | 3 +- 3 files changed, 196 insertions(+), 19 deletions(-)
diff --git a/dlls/wined3d/ffp_hlsl.c b/dlls/wined3d/ffp_hlsl.c index 973fc064ed7..88d968d03a5 100644 --- a/dlls/wined3d/ffp_hlsl.c +++ b/dlls/wined3d/ffp_hlsl.c @@ -27,23 +27,186 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
+static const char *get_material_colour_source(enum wined3d_material_color_source mcs, const char *material) +{ + switch (mcs) + { + case WINED3D_MCS_MATERIAL: + return material; + case WINED3D_MCS_COLOR1: + return "i.diffuse"; + case WINED3D_MCS_COLOR2: + return "i.specular"; + default: + ERR("Invalid material color source %#x.\n", mcs); + return "<invalid>"; + } +} + +static void generate_lighting_footer(struct wined3d_string_buffer *buffer, + const struct wined3d_ffp_vs_settings *settings, unsigned int idx, bool legacy_lighting) +{ + shader_addline(buffer, " diffuse += saturate(dot(dir, normal)) * c.lights[%u].diffuse.xyz * att;\n", idx); + if (settings->localviewer) + shader_addline(buffer, " t = dot(normal, ffp_normalize(dir - ffp_normalize(ec_pos.xyz)));\n"); + else + shader_addline(buffer, " t = dot(normal, ffp_normalize(dir + float3(0.0, 0.0, -1.0)));\n"); + if (settings->specular_enable) + { + shader_addline(buffer, " if (dot(dir, normal) > 0.0 && t > 0.0"); + if (legacy_lighting) + shader_addline(buffer, " && c.material.power > 0.0"); + shader_addline(buffer, ")\n"); + shader_addline(buffer, " specular += pow(t, c.material.power) * c.lights[%u].specular * att;\n", idx); + } +} + +static void generate_lighting(struct wined3d_string_buffer *buffer, + const struct wined3d_ffp_vs_settings *settings, bool legacy_lighting) +{ + const char *ambient, *diffuse, *specular, *emissive; + unsigned int idx = 0; + + if (!settings->lighting) + { + if (settings->diffuse) + shader_addline(buffer, " o.diffuse = i.diffuse;\n"); + else + shader_addline(buffer, " o.diffuse = 1.0;\n"); + shader_addline(buffer, " o.specular = i.specular;\n"); + return; + } + + shader_addline(buffer, " float3 ambient = c.ambient_colour.xyz;\n"); + shader_addline(buffer, " float3 diffuse = 0.0;\n"); + shader_addline(buffer, " float3 dir, dst;\n"); + shader_addline(buffer, " float att, t, range, falloff, cos_htheta, cos_hphi;\n"); + + if (settings->specular_enable) + shader_addline(buffer, " float4 specular = 0.0;\n"); + + ambient = get_material_colour_source(settings->ambient_source, "c.material.ambient"); + diffuse = get_material_colour_source(settings->diffuse_source, "c.material.diffuse"); + specular = get_material_colour_source(settings->specular_source, "c.material.specular"); + emissive = get_material_colour_source(settings->emissive_source, "c.material.emissive"); + + for (unsigned int i = 0; i < settings->point_light_count; ++i) + { + shader_addline(buffer, " dir = c.lights[%u].position.xyz - ec_pos.xyz;\n", idx); + shader_addline(buffer, " dst.z = dot(dir, dir);\n"); + shader_addline(buffer, " dst.y = sqrt(dst.z);\n"); + shader_addline(buffer, " dst.x = 1.0;\n"); + + shader_addline(buffer, " range = c.lights[%u].packed_params.x;\n", idx); + + if (legacy_lighting) + { + shader_addline(buffer, " dst.y = (range - dst.y) / range;\n"); + shader_addline(buffer, " dst.z = dst.y * dst.y;\n"); + shader_addline(buffer, " if (dst.y > 0.0)\n{\n"); + shader_addline(buffer, " att = dot(dst.xyz, c.lights[%u].attenuation.xyz);\n", idx); + } + else + { + shader_addline(buffer, " if (dst.y <= range)\n{\n"); + shader_addline(buffer, " att = 1.0 / dot(dst.xyz, c.lights[%u].attenuation.xyz);\n", idx); + } + shader_addline(buffer, " ambient += c.lights[%u].ambient.xyz * att;\n", idx); + if (settings->normal) + { + shader_addline(buffer, " dir = ffp_normalize(dir);\n"); + generate_lighting_footer(buffer, settings, idx, legacy_lighting); + } + shader_addline(buffer, " }\n"); + + ++idx; + } + + for (unsigned int i = 0; i < settings->spot_light_count; ++i) + { + shader_addline(buffer, " dir = c.lights[%u].position.xyz - ec_pos.xyz;\n", idx); + shader_addline(buffer, " dst.z = dot(dir, dir);\n"); + shader_addline(buffer, " dst.y = sqrt(dst.z);\n"); + shader_addline(buffer, " dst.x = 1.0;\n"); + + shader_addline(buffer, " range = c.lights[%u].packed_params.x;\n", idx); + shader_addline(buffer, " falloff = c.lights[%u].packed_params.y;\n", idx); + shader_addline(buffer, " cos_htheta = c.lights[%u].packed_params.z;\n", idx); + shader_addline(buffer, " cos_hphi = c.lights[%u].packed_params.w;\n", idx); + + if (legacy_lighting) + { + shader_addline(buffer, " dst.y = (range - dst.y) / range;\n"); + shader_addline(buffer, " dst.z = dst.y * dst.y;\n"); + shader_addline(buffer, " if (dst.y > 0.0)\n{\n"); + } + else + { + shader_addline(buffer, " if (dst.y <= range)\n{\n"); + } + shader_addline(buffer, " dir = ffp_normalize(dir);\n"); + shader_addline(buffer, " t = dot(-dir, ffp_normalize(c.lights[%u].direction.xyz));\n", idx); + shader_addline(buffer, " if (t > cos_htheta) att = 1.0;\n"); + shader_addline(buffer, " else if (t <= cos_hphi) att = 0.0;\n"); + shader_addline(buffer, " else att = pow((t - cos_hphi) / (cos_htheta - cos_hphi), falloff);\n"); + if (legacy_lighting) + shader_addline(buffer, " att *= dot(dst.xyz, c.lights[%u].attenuation.xyz);\n", idx); + else + shader_addline(buffer, " att /= dot(dst.xyz, c.lights[%u].attenuation.xyz);\n", idx); + shader_addline(buffer, " ambient += c.lights[%u].ambient.xyz * att;\n", idx); + if (settings->normal) + generate_lighting_footer(buffer, settings, idx, legacy_lighting); + shader_addline(buffer, " }\n"); + + ++idx; + } + + for (unsigned int i = 0; i < settings->directional_light_count; ++i) + { + shader_addline(buffer, " ambient += c.lights[%u].ambient.xyz;\n", idx); + if (settings->normal) + { + shader_addline(buffer, " att = 1.0;\n"); + shader_addline(buffer, " dir = ffp_normalize(c.lights[%u].direction.xyz);\n", idx); + generate_lighting_footer(buffer, settings, idx, legacy_lighting); + } + + ++idx; + } + + for (unsigned int i = 0; i < settings->parallel_point_light_count; ++i) + { + shader_addline(buffer, " ambient += c.lights[%u].ambient.xyz;\n", idx); + if (settings->normal) + { + shader_addline(buffer, " att = 1.0;\n"); + shader_addline(buffer, " dir = ffp_normalize(c.lights[%u].position.xyz);\n", idx); + generate_lighting_footer(buffer, settings, idx, legacy_lighting); + } + + ++idx; + } + + shader_addline(buffer, " o.diffuse.xyz = %s.xyz * ambient + %s.xyz * diffuse + %s.xyz;\n", + ambient, diffuse, emissive); + shader_addline(buffer, " o.diffuse.w = %s.w;\n", diffuse); + if (settings->specular_enable) + shader_addline(buffer, " o.specular = %s * specular;\n", specular); + else + shader_addline(buffer, " o.specular = i.specular;\n"); +} + static bool ffp_hlsl_generate_vertex_shader(const struct wined3d_ffp_vs_settings *settings, - struct wined3d_string_buffer *buffer) + struct wined3d_string_buffer *buffer, bool legacy_lighting) { struct wined3d_string_buffer texcoord;
- if (settings->lighting) - FIXME("Ignoring lighting.\n"); - if (settings->point_size) FIXME("Ignoring point size.\n");
if (settings->vertexblends) FIXME("Ignoring vertex blend.\n");
- if (settings->normal) - FIXME("Ignoring normals.\n"); - if (settings->fog_mode != WINED3D_FFP_VS_FOG_OFF) FIXME("Ignoring fog.\n");
@@ -96,6 +259,11 @@ static bool ffp_hlsl_generate_vertex_shader(const struct wined3d_ffp_vs_settings } shader_addline(buffer, "};\n\n");
+ shader_addline(buffer, "float3 ffp_normalize(float3 n)\n{\n"); + shader_addline(buffer, " float lensq = dot(n, n);\n"); + shader_addline(buffer, " return lensq == 0.0 ? n : (n * rsqrt(lensq));\n"); + shader_addline(buffer, "}\n\n"); + shader_addline(buffer, "void main(in struct input i, out struct output o)\n"); shader_addline(buffer, "{\n");
@@ -120,12 +288,19 @@ static bool ffp_hlsl_generate_vertex_shader(const struct wined3d_ffp_vs_settings shader_addline(buffer, " ec_pos /= ec_pos.w;\n\n"); }
- /* No lighting. */ - if (settings->diffuse) - shader_addline(buffer, " o.diffuse = i.diffuse;\n"); - else - shader_addline(buffer, " o.diffuse = 1.0;\n"); - shader_addline(buffer, " o.specular = i.specular;\n\n"); + shader_addline(buffer, " float3 normal = 0.0;\n"); + if (settings->normal) + { + if (settings->transformed) + shader_addline(buffer, " normal = i.normal;\n"); + else + shader_addline(buffer, " normal = mul((float3x3)c.modelview_matrices[1], i.normal);\n"); + + if (settings->normalize) + shader_addline(buffer, " normal = ffp_normalize(normal);\n"); + } + + generate_lighting(buffer, settings, legacy_lighting);
string_buffer_init(&texcoord); for (unsigned int i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i) @@ -698,7 +873,8 @@ static bool compile_hlsl_shader(const struct wined3d_string_buffer *hlsl, return true; }
-bool ffp_hlsl_compile_vs(const struct wined3d_ffp_vs_settings *settings, struct wined3d_shader_desc *shader_desc) +bool ffp_hlsl_compile_vs(const struct wined3d_ffp_vs_settings *settings, + struct wined3d_shader_desc *shader_desc, struct wined3d_device *device) { struct wined3d_string_buffer string; struct vkd3d_shader_code sm1; @@ -706,13 +882,13 @@ bool ffp_hlsl_compile_vs(const struct wined3d_ffp_vs_settings *settings, struct if (!string_buffer_init(&string)) return false;
- if (!ffp_hlsl_generate_vertex_shader(settings, &string)) + if (!ffp_hlsl_generate_vertex_shader(settings, &string, device->wined3d->flags & WINED3D_LEGACY_FFP_LIGHTING)) { string_buffer_free(&string); return false; }
- if (!compile_hlsl_shader(&string, &sm1, "vs_2_0")) + if (!compile_hlsl_shader(&string, &sm1, "vs_2_a")) { string_buffer_free(&string); return false; @@ -738,7 +914,7 @@ bool ffp_hlsl_compile_ps(const struct ffp_frag_settings *settings, struct wined3 return false; }
- if (!compile_hlsl_shader(&string, &sm1, "ps_2_0")) + if (!compile_hlsl_shader(&string, &sm1, "ps_2_a")) { string_buffer_free(&string); return false; diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c index 7c18c96dbf6..c40dc69e8ec 100644 --- a/dlls/wined3d/shader.c +++ b/dlls/wined3d/shader.c @@ -2555,7 +2555,7 @@ static void wined3d_shader_init_object(void *object) struct wined3d_ffp_vs_settings *settings = shader->byte_code; struct wined3d_shader_desc desc;
- if (!ffp_hlsl_compile_vs(settings, &desc)) + if (!ffp_hlsl_compile_vs(settings, &desc, device)) return; free(settings); shader_set_function(shader, &desc, WINED3D_SHADER_TYPE_VERTEX, NULL, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 2e0a541cea5..39a4aa5da9c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4298,7 +4298,8 @@ BOOL shader_match_semantic(const char *semantic_name, enum wined3d_decl_usage us
enum vkd3d_shader_visibility vkd3d_shader_visibility_from_wined3d(enum wined3d_shader_type shader_type);
-bool ffp_hlsl_compile_vs(const struct wined3d_ffp_vs_settings *settings, struct wined3d_shader_desc *shader_desc); +bool ffp_hlsl_compile_vs(const struct wined3d_ffp_vs_settings *settings, + struct wined3d_shader_desc *shader_desc, struct wined3d_device *device); bool ffp_hlsl_compile_ps(const struct ffp_frag_settings *settings, struct wined3d_shader_desc *shader_desc);
static inline BOOL shader_is_scalar(const struct wined3d_shader_register *reg)
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/ffp_hlsl.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/dlls/wined3d/ffp_hlsl.c b/dlls/wined3d/ffp_hlsl.c index 88d968d03a5..b662f1756c8 100644 --- a/dlls/wined3d/ffp_hlsl.c +++ b/dlls/wined3d/ffp_hlsl.c @@ -207,9 +207,6 @@ static bool ffp_hlsl_generate_vertex_shader(const struct wined3d_ffp_vs_settings if (settings->vertexblends) FIXME("Ignoring vertex blend.\n");
- if (settings->fog_mode != WINED3D_FFP_VS_FOG_OFF) - FIXME("Ignoring fog.\n"); - /* This must be kept in sync with struct wined3d_ffp_vs_constants. */ shader_addline(buffer, "uniform struct\n"); shader_addline(buffer, "{\n"); @@ -257,6 +254,8 @@ static bool ffp_hlsl_generate_vertex_shader(const struct wined3d_ffp_vs_settings if (((settings->texgen[i] & 0xffff0000) != WINED3DTSS_TCI_PASSTHRU) || (settings->texcoords & (1u << i))) shader_addline(buffer, " float4 texcoord%u : TEXCOORD%u;\n", i, i); } + if (settings->fog_mode == WINED3D_FFP_VS_FOG_DEPTH || settings->fog_mode == WINED3D_FFP_VS_FOG_RANGE) + shader_addline(buffer, " float fogcoord : FOG;\n"); shader_addline(buffer, "};\n\n");
shader_addline(buffer, "float3 ffp_normalize(float3 n)\n{\n"); @@ -333,8 +332,21 @@ static bool ffp_hlsl_generate_vertex_shader(const struct wined3d_ffp_vs_settings case WINED3D_FFP_VS_FOG_OFF: break;
- default: - FIXME("Unhandled fog mode %#x.\n", settings->fog_mode); + case WINED3D_FFP_VS_FOG_FOGCOORD: + /* This is FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE. + * The specular W is used in that case, even if we output fogcoord, + * so there's no point in outputting fogcoord. */ + break; + + case WINED3D_FFP_VS_FOG_RANGE: + shader_addline(buffer, " o.fogcoord = length(ec_pos.xyz);\n"); + break; + + case WINED3D_FFP_VS_FOG_DEPTH: + if (settings->transformed) + shader_addline(buffer, " o.fogcoord = ec_pos.z;\n"); + else + shader_addline(buffer, " o.fogcoord = abs(o.pos.z);\n"); break; }
This merge request was approved by Jan Sikorski.