From 8f39ffc11e8b6fdf7c940f9c1853a362a886977a Mon Sep 17 00:00:00 2001 From: Axel Davy Date: Tue, 12 May 2015 21:56:04 +0200 Subject: [PATCH] st/nine: Finish Fog implementation Signed-off-by: Axel Davy --- src/gallium/state_trackers/nine/nine_shader.c | 47 +++++++++++++++++++++++-- src/gallium/state_trackers/nine/nine_shader.h | 47 +++++++++++++++++++++++++ src/gallium/state_trackers/nine/nine_state.c | 43 +++++++++++++++------- src/gallium/state_trackers/nine/nine_state.h | 5 +-- src/gallium/state_trackers/nine/pixelshader9.c | 13 ++++--- src/gallium/state_trackers/nine/pixelshader9.h | 13 ++++--- src/gallium/state_trackers/nine/vertexshader9.c | 2 ++ src/gallium/state_trackers/nine/vertexshader9.h | 3 ++ 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 d9a20a5..2e35ede 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 f2b1e8b..3ba79af 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 610798a..53efa56 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 efaee1e..f1af49f 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 5399afd..6173b0e 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 69eb87b..5d1f504 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 956f023..fdfb79a 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 6cf7749..d572015 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; -- 2.7.4