{
struct ureg_program *ureg = tx->ureg;
struct ureg_dst oCol0 = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
+ struct ureg_src fog_end, fog_coeff, fog_density;
+ struct ureg_src fog_vs, depth, fog_color;
+ struct ureg_dst fog_factor;
- /* TODO: fog computation */
- ureg_MOV(ureg, oCol0, src_col);
+ if (!tx->info->fog_enable) {
+ ureg_MOV(ureg, oCol0, src_col);
+ return;
+ }
+
+ if (tx->info->fog_mode != D3DFOG_NONE)
+ depth = ureg_scalar(ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_POSITION, 0,
+ TGSI_INTERPOLATE_LINEAR),
+ TGSI_SWIZZLE_Z);
+
+ nine_info_mark_const_f_used(tx->info, 33);
+ fog_color = NINE_CONSTANT_SRC(32);
+ fog_factor = tx_scratch_scalar(tx);
+
+ if (tx->info->fog_mode == D3DFOG_LINEAR) {
+ fog_end = NINE_CONSTANT_SRC_SWIZZLE(33, X);
+ fog_coeff = NINE_CONSTANT_SRC_SWIZZLE(33, Y);
+ ureg_SUB(ureg, fog_factor, fog_end, depth);
+ ureg_MUL(ureg, ureg_saturate(fog_factor), tx_src_scalar(fog_factor), fog_coeff);
+ } else if (tx->info->fog_mode == D3DFOG_EXP) {
+ fog_density = NINE_CONSTANT_SRC_SWIZZLE(33, X);
+ ureg_MUL(ureg, fog_factor, depth, fog_density);
+ ureg_MUL(ureg, fog_factor, tx_src_scalar(fog_factor), ureg_imm1f(ureg, -1.442695f));
+ ureg_EX2(ureg, fog_factor, tx_src_scalar(fog_factor));
+ } else if (tx->info->fog_mode == D3DFOG_EXP2) {
+ fog_density = NINE_CONSTANT_SRC_SWIZZLE(33, X);
+ ureg_MUL(ureg, fog_factor, depth, fog_density);
+ ureg_MUL(ureg, fog_factor, tx_src_scalar(fog_factor), tx_src_scalar(fog_factor));
+ ureg_MUL(ureg, fog_factor, tx_src_scalar(fog_factor), ureg_imm1f(ureg, -1.442695f));
+ ureg_EX2(ureg, fog_factor, tx_src_scalar(fog_factor));
+ } else {
+ fog_vs = ureg_scalar(ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_FOG, 0,
+ TGSI_INTERPOLATE_PERSPECTIVE),
+ TGSI_SWIZZLE_X);
+ ureg_MOV(ureg, fog_factor, fog_vs);
+ }
+
+ ureg_LRP(ureg, ureg_writemask(oCol0, TGSI_WRITEMASK_XYZ),
+ tx_src_scalar(fog_factor), src_col, fog_color);
+ ureg_MOV(ureg, ureg_writemask(oCol0, TGSI_WRITEMASK_W), src_col);
}
#define GET_CAP(n) device->screen->get_param( \
}
}
- if (IS_VS && tx->version.major < 3 && ureg_dst_is_undef(tx->regs.oFog)) {
+ if (IS_VS && tx->version.major < 3 && ureg_dst_is_undef(tx->regs.oFog) && info->fog_enable) {
tx->regs.oFog = ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_FOG, 0);
ureg_MOV(tx->ureg, ureg_writemask(tx->regs.oFog, TGSI_WRITEMASK_X), ureg_imm1f(tx->ureg, 0.0f));
}
uint16_t sampler_mask_shadow; /* in, which samplers use depth compare */
uint8_t rt_mask; /* out, which render targets are being written */
+ uint8_t fog_enable;
+ uint8_t fog_mode;
+
unsigned const_i_base; /* in vec4 (16 byte) units */
unsigned const_b_base; /* in vec4 (16 byte) units */
unsigned const_used_size;
}
}
+struct nine_shader_variant64
+{
+ struct nine_shader_variant64 *next;
+ void *cso;
+ uint64_t key;
+};
+
+static inline void *
+nine_shader_variant_get64(struct nine_shader_variant64 *list, uint64_t key)
+{
+ while (list->key != key && list->next)
+ list = list->next;
+ if (list->key == key)
+ return list->cso;
+ return NULL;
+}
+
+static inline boolean
+nine_shader_variant_add64(struct nine_shader_variant64 *list,
+ uint64_t key, void *cso)
+{
+ while (list->next) {
+ assert(list->key != key);
+ list = list->next;
+ }
+ list->next = MALLOC_STRUCT(nine_shader_variant64);
+ if (!list->next)
+ return FALSE;
+ list->next->next = NULL;
+ list->next->key = key;
+ list->next->cso = cso;
+ return TRUE;
+}
+
+static inline void
+nine_shader_variants_free64(struct nine_shader_variant64 *list)
+{
+ while (list->next) {
+ struct nine_shader_variant64 *ptr = list->next;
+ list->next = ptr->next;
+ FREE(ptr);
+ }
+}
+
#endif /* _NINE_SHADER_H_ */
cb.buffer_size = device->state.ps->const_used_size;
cb.user_buffer = device->state.ps_const_f;
- if (!cb.buffer_size)
- return;
-
if (state->changed.ps_const_i) {
int *idst = (int *)&state->ps_const_f[4 * device->max_ps_const_f];
memcpy(idst, state->ps_const_i, sizeof(state->ps_const_i));
cb.user_buffer = device->state.ps_lconstf_temp;
}
+ if (state->ps->byte_code.version < 0x30 &&
+ state->rs[D3DRS_FOGENABLE]) {
+ float *dst = &state->ps_lconstf_temp[4 * 32];
+ if (cb.user_buffer != state->ps_lconstf_temp) {
+ memcpy(state->ps_lconstf_temp, cb.user_buffer, cb.buffer_size);
+ cb.user_buffer = state->ps_lconstf_temp;
+ }
+
+ d3dcolor_to_rgba(dst, state->rs[D3DRS_FOGCOLOR]);
+ if (state->rs[D3DRS_FOGTABLEMODE] == D3DFOG_LINEAR) {
+ dst[4] = asfloat(state->rs[D3DRS_FOGEND]);
+ dst[5] = 1.0f / (asfloat(state->rs[D3DRS_FOGEND]) - asfloat(state->rs[D3DRS_FOGSTART]));
+ } else if (state->rs[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
+ dst[4] = asfloat(state->rs[D3DRS_FOGDENSITY]);
+ }
+ cb.buffer_size = 4 * 4 * 34;
+ }
+
+ if (!cb.buffer_size)
+ return;
+
if (!device->driver_caps.user_cbufs) {
u_upload_data(device->constbuf_uploader,
0,
NINE_STATE_PS | \
NINE_STATE_BLEND_COLOR | \
NINE_STATE_STENCIL_REF | \
- NINE_STATE_SAMPLE_MASK)
+ NINE_STATE_SAMPLE_MASK | \
+ NINE_STATE_FOG_SHADER)
#define NINE_STATE_FREQ_GROUP_1 ~NINE_STATE_FREQ_GROUP_0
if (group & NINE_STATE_BLEND)
prepare_blend(device);
- if (group & (NINE_STATE_VS | NINE_STATE_TEXTURE))
+ if (group & (NINE_STATE_VS | NINE_STATE_TEXTURE | NINE_STATE_FOG_SHADER))
group |= prepare_vs(device, (group & NINE_STATE_VS) != 0);
if (group & NINE_STATE_RASTERIZER)
prepare_rasterizer(device);
- if (group & (NINE_STATE_PS | NINE_STATE_TEXTURE))
+ if (group & (NINE_STATE_PS | NINE_STATE_TEXTURE | NINE_STATE_FOG_SHADER))
group |= prepare_ps(device, (group & NINE_STATE_PS) != 0);
if (group & NINE_STATE_BLEND_COLOR) {
[D3DRS_ALPHAFUNC] = NINE_STATE_DSA,
[D3DRS_DITHERENABLE] = NINE_STATE_BLEND,
[D3DRS_ALPHABLENDENABLE] = NINE_STATE_BLEND,
- [D3DRS_FOGENABLE] = NINE_STATE_FF_OTHER,
+ [D3DRS_FOGENABLE] = NINE_STATE_FF_OTHER | NINE_STATE_FOG_SHADER | NINE_STATE_PS_CONST,
[D3DRS_SPECULARENABLE] = NINE_STATE_FF_LIGHTING,
- [D3DRS_FOGCOLOR] = NINE_STATE_FF_OTHER,
- [D3DRS_FOGTABLEMODE] = NINE_STATE_FF_OTHER,
- [D3DRS_FOGSTART] = NINE_STATE_FF_OTHER,
- [D3DRS_FOGEND] = NINE_STATE_FF_OTHER,
- [D3DRS_FOGDENSITY] = NINE_STATE_FF_OTHER,
+ [D3DRS_FOGCOLOR] = NINE_STATE_FF_OTHER | NINE_STATE_PS_CONST,
+ [D3DRS_FOGTABLEMODE] = NINE_STATE_FF_OTHER | NINE_STATE_FOG_SHADER | NINE_STATE_PS_CONST,
+ [D3DRS_FOGSTART] = NINE_STATE_FF_OTHER | NINE_STATE_PS_CONST,
+ [D3DRS_FOGEND] = NINE_STATE_FF_OTHER | NINE_STATE_PS_CONST,
+ [D3DRS_FOGDENSITY] = NINE_STATE_FF_OTHER | NINE_STATE_PS_CONST,
[D3DRS_RANGEFOGENABLE] = NINE_STATE_FF_OTHER,
[D3DRS_STENCILENABLE] = NINE_STATE_DSA,
[D3DRS_STENCILFAIL] = NINE_STATE_DSA,
#define NINE_STATE_FF_VSTRANSF (1 << 21)
#define NINE_STATE_FF_PSSTAGES (1 << 22)
#define NINE_STATE_FF_OTHER (1 << 23)
-#define NINE_STATE_ALL 0x0ffffff
-#define NINE_STATE_UNHANDLED (1 << 24)
+#define NINE_STATE_FOG_SHADER (1 << 24)
+#define NINE_STATE_ALL 0x1ffffff
+#define NINE_STATE_UNHANDLED (1 << 25)
#define NINE_STATE_COMMIT_DSA (1 << 0)
#define NINE_STATE_COMMIT_RASTERIZER (1 << 1)
info.const_b_base = NINE_CONST_B_BASE(device->max_ps_const_f) / 16;
info.sampler_mask_shadow = 0x0;
info.sampler_ps1xtypes = 0x0;
+ info.fog_enable = 0;
hr = nine_translate_shader(device, &info);
if (FAILED(hr))
if (This->base.device) {
struct pipe_context *pipe = This->base.device->pipe;
- struct nine_shader_variant *var = &This->variant;
+ struct nine_shader_variant64 *var = &This->variant;
do {
if (var->cso) {
pipe->delete_fs_state(pipe, This->ff_cso);
}
}
- nine_shader_variants_free(&This->variant);
+ nine_shader_variants_free64(&This->variant);
FREE((void *)This->byte_code.tokens); /* const_cast */
NinePixelShader9_GetVariant( struct NinePixelShader9 *This )
{
void *cso;
- uint32_t key;
+ uint64_t key;
key = This->next_key;
if (key == This->last_key)
return This->last_cso;
- cso = nine_shader_variant_get(&This->variant, key);
+ cso = nine_shader_variant_get64(&This->variant, key);
if (!cso) {
struct NineDevice9 *device = This->base.device;
struct nine_shader_info info;
info.byte_code = This->byte_code.tokens;
info.sampler_mask_shadow = key & 0xffff;
info.sampler_ps1xtypes = key;
+ info.fog_enable = device->state.rs[D3DRS_FOGENABLE];
+ info.fog_mode = device->state.rs[D3DRS_FOGTABLEMODE];
hr = nine_translate_shader(This->base.device, &info);
if (FAILED(hr))
return NULL;
- nine_shader_variant_add(&This->variant, key, info.cso);
+ nine_shader_variant_add64(&This->variant, key, info.cso);
cso = info.cso;
}
struct NinePixelShader9
{
struct NineUnknown base;
- struct nine_shader_variant variant;
+ struct nine_shader_variant64 variant;
struct {
const DWORD *tokens;
uint64_t ff_key[6];
void *ff_cso;
- uint32_t last_key;
+ uint64_t last_key;
void *last_cso;
- uint32_t next_key;
+ uint64_t next_key;
};
static inline struct NinePixelShader9 *
NinePixelShader9( void *data )
{
uint16_t samplers_shadow;
uint32_t samplers_ps1_types;
- uint32_t key;
+ uint64_t key;
BOOL res;
if (unlikely(ps->byte_code.version < 0x20)) {
key = samplers_shadow & ps->sampler_mask;
}
+ if (ps->byte_code.version < 0x30) {
+ key |= ((uint64_t)state->rs[D3DRS_FOGENABLE]) << 32;
+ key |= ((uint64_t)state->rs[D3DRS_FOGTABLEMODE]) << 33;
+ }
+
res = ps->last_key != key;
if (res)
ps->next_key = key;
info.const_b_base = NINE_CONST_B_BASE(device->max_vs_const_f) / 16;
info.sampler_mask_shadow = 0x0;
info.sampler_ps1xtypes = 0x0;
+ info.fog_enable = 0;
hr = nine_translate_shader(device, &info);
if (FAILED(hr))
info.const_b_base = NINE_CONST_B_BASE(device->max_vs_const_f) / 16;
info.byte_code = This->byte_code.tokens;
info.sampler_mask_shadow = key & 0xf;
+ info.fog_enable = device->state.rs[D3DRS_FOGENABLE];
hr = nine_translate_shader(This->base.device, &info);
if (FAILED(hr))
samplers_shadow &= vs->sampler_mask;
key = samplers_shadow;
+ if (vs->byte_code.version < 0x30)
+ key |= state->rs[D3DRS_FOGENABLE] << 8;
+
res = vs->last_key != key;
if (res)
vs->next_key = key;