summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAxel Davy <axel.davy@ens.fr>2015-05-12 21:56:04 +0200
committerAxel Davy <axel.davy@ens.fr>2015-08-21 22:21:47 +0200
commit8f39ffc11e8b6fdf7c940f9c1853a362a886977a (patch)
tree8a8df571e545e5593dd219fb5dda7442bec35a68
parent69de5d626f2e67e74e4de94ce13f7ac50fa52161 (diff)
st/nine: Finish Fog implementation
Signed-off-by: Axel Davy <axel.davy@ens.fr>
-rw-r--r--src/gallium/state_trackers/nine/nine_shader.c47
-rw-r--r--src/gallium/state_trackers/nine/nine_shader.h47
-rw-r--r--src/gallium/state_trackers/nine/nine_state.c43
-rw-r--r--src/gallium/state_trackers/nine/nine_state.h5
-rw-r--r--src/gallium/state_trackers/nine/pixelshader9.c13
-rw-r--r--src/gallium/state_trackers/nine/pixelshader9.h13
-rw-r--r--src/gallium/state_trackers/nine/vertexshader9.c2
-rw-r--r--src/gallium/state_trackers/nine/vertexshader9.h3
8 files changed, 147 insertions, 26 deletions
diff --git a/src/gallium/state_trackers/nine/nine_shader.c b/src/gallium/state_trackers/nine/nine_shader.c
index d9a20a58f8f..2e35edecaf7 100644
--- a/src/gallium/state_trackers/nine/nine_shader.c
+++ b/src/gallium/state_trackers/nine/nine_shader.c
@@ -3199,9 +3199,50 @@ shader_add_ps_fog_stage(struct shader_translator *tx, struct ureg_src src_col)
{
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( \
@@ -3285,7 +3326,7 @@ nine_translate_shader(struct NineDevice9 *device, struct nine_shader_info *info)
}
}
- 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));
}
diff --git a/src/gallium/state_trackers/nine/nine_shader.h b/src/gallium/state_trackers/nine/nine_shader.h
index f2b1e8bf6e2..3ba79af47c7 100644
--- a/src/gallium/state_trackers/nine/nine_shader.h
+++ b/src/gallium/state_trackers/nine/nine_shader.h
@@ -59,6 +59,9 @@ struct nine_shader_info
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;
@@ -138,4 +141,48 @@ nine_shader_variants_free(struct nine_shader_variant *list)
}
}
+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_ */
diff --git a/src/gallium/state_trackers/nine/nine_state.c b/src/gallium/state_trackers/nine/nine_state.c
index 610798a3be7..53efa56d081 100644
--- a/src/gallium/state_trackers/nine/nine_state.c
+++ b/src/gallium/state_trackers/nine/nine_state.c
@@ -280,9 +280,6 @@ prepare_ps_constants_userbuf(struct NineDevice9 *device)
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));
@@ -303,6 +300,27 @@ prepare_ps_constants_userbuf(struct NineDevice9 *device)
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,
@@ -931,7 +949,8 @@ commit_ps(struct NineDevice9 *device)
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
@@ -996,13 +1015,13 @@ nine_update_state(struct NineDevice9 *device)
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) {
@@ -1486,13 +1505,13 @@ const uint32_t nine_render_state_group[NINED3DRS_LAST + 1] =
[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,
diff --git a/src/gallium/state_trackers/nine/nine_state.h b/src/gallium/state_trackers/nine/nine_state.h
index efaee1ee95e..f1af49fa137 100644
--- a/src/gallium/state_trackers/nine/nine_state.h
+++ b/src/gallium/state_trackers/nine/nine_state.h
@@ -75,8 +75,9 @@
#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)
diff --git a/src/gallium/state_trackers/nine/pixelshader9.c b/src/gallium/state_trackers/nine/pixelshader9.c
index 5399afd3698..6173b0eea05 100644
--- a/src/gallium/state_trackers/nine/pixelshader9.c
+++ b/src/gallium/state_trackers/nine/pixelshader9.c
@@ -57,6 +57,7 @@ NinePixelShader9_ctor( struct NinePixelShader9 *This,
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))
@@ -90,7 +91,7 @@ NinePixelShader9_dtor( struct NinePixelShader9 *This )
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) {
@@ -107,7 +108,7 @@ NinePixelShader9_dtor( struct NinePixelShader9 *This )
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 */
@@ -138,13 +139,13 @@ void *
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;
@@ -156,11 +157,13 @@ NinePixelShader9_GetVariant( struct NinePixelShader9 *This )
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;
}
diff --git a/src/gallium/state_trackers/nine/pixelshader9.h b/src/gallium/state_trackers/nine/pixelshader9.h
index 69eb87b2e27..5d1f5041c47 100644
--- a/src/gallium/state_trackers/nine/pixelshader9.h
+++ b/src/gallium/state_trackers/nine/pixelshader9.h
@@ -33,7 +33,7 @@ struct nine_lconstf;
struct NinePixelShader9
{
struct NineUnknown base;
- struct nine_shader_variant variant;
+ struct nine_shader_variant64 variant;
struct {
const DWORD *tokens;
@@ -50,10 +50,10 @@ struct NinePixelShader9
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 )
@@ -67,7 +67,7 @@ NinePixelShader9_UpdateKey( struct NinePixelShader9 *ps,
{
uint16_t samplers_shadow;
uint32_t samplers_ps1_types;
- uint32_t key;
+ uint64_t key;
BOOL res;
if (unlikely(ps->byte_code.version < 0x20)) {
@@ -85,6 +85,11 @@ NinePixelShader9_UpdateKey( struct NinePixelShader9 *ps,
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;
diff --git a/src/gallium/state_trackers/nine/vertexshader9.c b/src/gallium/state_trackers/nine/vertexshader9.c
index 956f0234b25..fdfb79a138e 100644
--- a/src/gallium/state_trackers/nine/vertexshader9.c
+++ b/src/gallium/state_trackers/nine/vertexshader9.c
@@ -60,6 +60,7 @@ NineVertexShader9_ctor( struct NineVertexShader9 *This,
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))
@@ -161,6 +162,7 @@ NineVertexShader9_GetVariant( struct NineVertexShader9 *This )
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))
diff --git a/src/gallium/state_trackers/nine/vertexshader9.h b/src/gallium/state_trackers/nine/vertexshader9.h
index 6cf7749e0ac..d5720157cc0 100644
--- a/src/gallium/state_trackers/nine/vertexshader9.h
+++ b/src/gallium/state_trackers/nine/vertexshader9.h
@@ -80,6 +80,9 @@ NineVertexShader9_UpdateKey( struct NineVertexShader9 *vs,
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;