}
/* Source is either W or Z.
- * When we use vs ff,
* Z is when an orthogonal projection matrix is detected,
* W (WFOG) else.
- * Z is used for programmable vs.
- * Note: Tests indicate that the projection matrix coefficients do
- * actually affect pixel fog (and not vertex fog) when vs ff is used,
- * which justifies taking the position's w instead of taking the z coordinate
- * before the projection in the vs shader.
*/
if (!key->fog_source)
ureg_MOV(ureg, rFog, _ZZZZ(vPos));
nine_ff_get_ps(struct NineDevice9 *device)
{
struct nine_context *context = &device->context;
- D3DMATRIX *projection_matrix = GET_D3DTS(PROJECTION);
struct NinePixelShader9 *ps;
struct nine_ff_ps_key key;
unsigned s;
if (context->rs[D3DRS_FOGENABLE])
key.fog_mode = context->rs[D3DRS_FOGTABLEMODE];
key.fog = !!context->rs[D3DRS_FOGENABLE];
- /* Pixel fog (with WFOG advertised): source is either Z or W.
- * W is the source if vs ff is used, and the
- * projection matrix is not orthogonal.
- * Tests on Win 10 seem to indicate _34
- * and _33 are checked against 0, 1. */
if (key.fog_mode && key.fog)
- key.fog_source = !context->programmable_vs &&
- !(projection_matrix->_34 == 0.0f &&
- projection_matrix->_44 == 1.0f);
+ key.fog_source = !context->zfog;
DBG("PS ff key hash: %x\n", nine_ff_ps_key_hash(&key));
ps = util_hash_table_get(device->ff.ht_ps, &key);
if (tx->info->fog_mode != D3DFOG_NONE) {
depth = tx_scratch_scalar(tx);
- /* Depth used for fog is perspective interpolated */
- ureg_RCP(ureg, depth, ureg_scalar(nine_get_position_input(tx), TGSI_SWIZZLE_W));
- ureg_MUL(ureg, depth, ureg_src(depth), ureg_scalar(nine_get_position_input(tx), TGSI_SWIZZLE_Z));
+ if (tx->info->zfog)
+ ureg_MOV(ureg, depth, ureg_scalar(nine_get_position_input(tx), TGSI_SWIZZLE_Z));
+ else /* wfog: use w. position's w contains 1/w */
+ ureg_RCP(ureg, depth, ureg_scalar(nine_get_position_input(tx), TGSI_SWIZZLE_W));
}
fog_color = nine_float_constant_src(tx, 32);
uint8_t fog_enable;
uint8_t fog_mode;
+ uint8_t zfog;
uint8_t force_color_in_centroid;
uint8_t projected; /* ps 1.1 to 1.3 */
uint16_t fetch4;
D3DMATRIX *M = nine_state_access_transform(&context->ff, State, TRUE);
*M = *pMatrix;
+ if (State == D3DTS_PROJECTION) {
+ BOOL prev_zfog = context->zfog;
+ /* Pixel fog (with WFOG advertised): source is either Z or W.
+ * W is the source if the projection matrix is not orthogonal.
+ * Tests on Win 10 seem to indicate _34
+ * and _33 are checked against 0, 1. */
+ context->zfog = (M->_34 == 0.0f &&
+ M->_44 == 1.0f);
+ if (context->zfog != prev_zfog)
+ context->changed.group |= NINE_STATE_PS_PARAMS_MISC;
+ }
context->ff.changed.transform[State / 32] |= 1 << (State % 32);
context->changed.group |= NINE_STATE_FF;
}
memset(context->ps_const_i, 0, sizeof(context->ps_const_i));
memset(state->ps_const_b, 0, sizeof(state->ps_const_b));
memset(context->ps_const_b, 0, sizeof(context->ps_const_b));
+ context->zfog = false; /* Guess from wine tests: both true or false are ok */
/* Cap dependent initial state:
*/
int ps_const_i[NINE_MAX_CONST_I][4];
BOOL ps_const_b[NINE_MAX_CONST_B];
float *ps_lconstf_temp;
+ BOOL zfog;
struct NineVertexDeclaration9 *vdecl;
}
info.fog_enable = device->context.rs[D3DRS_FOGENABLE];
info.fog_mode = device->context.rs[D3DRS_FOGTABLEMODE];
- info.force_color_in_centroid = (key >> 23) & 1;
+ info.zfog = device->context.zfog;
info.add_constants_defs.c_combination =
nine_shader_constant_combination_get(This->c_combinations, (key >> 24) & 0xff);
info.add_constants_defs.int_const_added = &This->int_slots_used;
info.add_constants_defs.bool_const_added = &This->bool_slots_used;
- info.fetch4 = key >> 32 ;
+ info.fetch4 = (key >> 32) & 0xffff;
+ info.force_color_in_centroid = (key >> 48) & 1;
info.process_vertices = false;
info.swvp_on = false;
}
}
- if (ps->byte_code.version < 0x30) {
- key |= ((uint64_t)context->rs[D3DRS_FOGENABLE]) << 20;
+ if (ps->byte_code.version < 0x30 && context->rs[D3DRS_FOGENABLE]) {
+ key |= 1 << 20;
key |= ((uint64_t)context->rs[D3DRS_FOGTABLEMODE]) << 21; /* 2 bits */
+ key |= ((uint64_t)context->zfog) << 23;
}
- /* centroid interpolation automatically used for color ps inputs */
- if (context->rt[0]->base.info.nr_samples)
- key |= ((uint64_t)1) << 23;
-
if ((ps->const_int_slots > 0 || ps->const_bool_slots > 0) && context->inline_constants)
key |= ((uint64_t)nine_shader_constant_combination_key(&ps->c_combinations,
ps->int_slots_used,
(void *)context->ps_const_i,
context->ps_const_b)) << 24;
- key |= ((uint64_t)(context->rs[NINED3DRS_FETCH4] & samplers_fetch4)) << 32;
+ key |= ((uint64_t)(context->rs[NINED3DRS_FETCH4] & samplers_fetch4)) << 32; /* 16 bits */
+
+ /* centroid interpolation automatically used for color ps inputs */
+ if (context->rt[0]->base.info.nr_samples)
+ key |= ((uint64_t)1) << 48;
+
res = ps->last_key != key;
if (res)
ps->next_key = key;