From 4a00e4cdc970582df338ebf880168a4ef4ec05d9 Mon Sep 17 00:00:00 2001 From: Axel Davy Date: Thu, 14 May 2015 01:27:33 +0200 Subject: [PATCH] st/nine: Programmable ps D3DTTSS_PROJECTED support The implementation used Wine tests for conformance Signed-off-by: Axel Davy --- src/gallium/state_trackers/nine/device9.c | 3 ++ src/gallium/state_trackers/nine/nine_shader.c | 59 ++++++++++++++++++++++++-- src/gallium/state_trackers/nine/nine_shader.h | 1 + src/gallium/state_trackers/nine/nine_state.c | 5 ++- src/gallium/state_trackers/nine/nine_state.h | 5 ++- src/gallium/state_trackers/nine/pixelshader9.c | 2 + src/gallium/state_trackers/nine/pixelshader9.h | 7 +++ 7 files changed, 74 insertions(+), 8 deletions(-) diff --git a/src/gallium/state_trackers/nine/device9.c b/src/gallium/state_trackers/nine/device9.c index 8023f785e10..aa5734b90f3 100644 --- a/src/gallium/state_trackers/nine/device9.c +++ b/src/gallium/state_trackers/nine/device9.c @@ -2637,6 +2637,9 @@ NineDevice9_SetTextureStageState( struct NineDevice9 *This, case D3DTSS_BUMPENVLOFFSET: bumpmap_index = 4 * 8 + 2 * Stage + 1; break; + case D3DTSS_TEXTURETRANSFORMFLAGS: + state->changed.group |= NINE_STATE_PS1X_SHADER; + break; default: break; } diff --git a/src/gallium/state_trackers/nine/nine_shader.c b/src/gallium/state_trackers/nine/nine_shader.c index 2e35edecaf7..7e76d7d5ba8 100644 --- a/src/gallium/state_trackers/nine/nine_shader.c +++ b/src/gallium/state_trackers/nine/nine_shader.c @@ -681,6 +681,54 @@ tx_pred_alloc(struct shader_translator *tx, INT idx) tx->regs.p = ureg_DECL_predicate(tx->ureg); } +/* NOTE: It's not very clear on which ps1.1-ps1.3 instructions + * the projection should be applied on the texture. It doesn't + * apply on texkill. + * The doc is very imprecise here (it says the projection is done + * before rasterization, thus in vs, which seems wrong since ps instructions + * are affected differently) + * For now we only apply to the ps TEX instruction and TEXBEM. + * Perhaps some other instructions would need it */ +static inline void +apply_ps1x_projection(struct shader_translator *tx, struct ureg_dst dst, + struct ureg_src src, INT idx) +{ + struct ureg_dst tmp; + unsigned dim = 1 + ((tx->info->projected >> (2 * idx)) & 3); + + /* no projection */ + if (dim == 1) { + ureg_MOV(tx->ureg, dst, src); + } else { + tmp = tx_scratch_scalar(tx); + ureg_RCP(tx->ureg, tmp, ureg_scalar(src, dim-1)); + ureg_MUL(tx->ureg, dst, tx_src_scalar(tmp), src); + } +} + +static inline void +TEX_with_ps1x_projection(struct shader_translator *tx, struct ureg_dst dst, + unsigned target, struct ureg_src src0, + struct ureg_src src1, INT idx) +{ + unsigned dim = 1 + ((tx->info->projected >> (2 * idx)) & 3); + struct ureg_dst tmp; + + /* dim == 1: no projection + * Looks like must be disabled when it makes no + * sense according the texture dimensions + */ + if (dim == 1 || dim <= target) { + ureg_TEX(tx->ureg, dst, target, src0, src1); + } else if (dim == 4) { + ureg_TXP(tx->ureg, dst, target, src0, src1); + } else { + tmp = tx_scratch(tx); + apply_ps1x_projection(tx, tmp, src0, idx); + ureg_TEX(tx->ureg, dst, target, ureg_src(tmp), src1); + } +} + static inline void tx_texcoord_alloc(struct shader_translator *tx, INT idx) { @@ -2155,7 +2203,7 @@ DECL_SPECIAL(TEXBEM) { struct ureg_program *ureg = tx->ureg; struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_dst tmp, tmp2; + struct ureg_dst tmp, tmp2, texcoord; struct ureg_src sample, m00, m01, m10, m11; struct ureg_src bumpenvlscale, bumpenvloffset; const int m = tx->insn.dst[0].idx; @@ -2170,6 +2218,7 @@ DECL_SPECIAL(TEXBEM) tmp = tx_scratch(tx); tmp2 = tx_scratch(tx); + texcoord = tx_scratch(tx); /* * Bump-env-matrix: * 00 is X @@ -2192,9 +2241,11 @@ DECL_SPECIAL(TEXBEM) bumpenvloffset = NINE_CONSTANT_SRC_SWIZZLE(8 + 8 + m / 2, W); } + apply_ps1x_projection(tx, texcoord, tx->regs.vT[m], m); + /* u' = TextureCoordinates(stage m)u + D3DTSS_BUMPENVMAT00(stage m)*t(n)R */ ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), m00, - NINE_APPLY_SWIZZLE(ureg_src(tx->regs.tS[n]), X), tx->regs.vT[m]); + NINE_APPLY_SWIZZLE(ureg_src(tx->regs.tS[n]), X), ureg_src(texcoord)); /* u' = u' + D3DTSS_BUMPENVMAT10(stage m)*t(n)G */ ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), m10, NINE_APPLY_SWIZZLE(ureg_src(tx->regs.tS[n]), Y), @@ -2202,7 +2253,7 @@ DECL_SPECIAL(TEXBEM) /* v' = TextureCoordinates(stage m)v + D3DTSS_BUMPENVMAT01(stage m)*t(n)R */ ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), m01, - NINE_APPLY_SWIZZLE(ureg_src(tx->regs.tS[n]), X), tx->regs.vT[m]); + NINE_APPLY_SWIZZLE(ureg_src(tx->regs.tS[n]), X), ureg_src(texcoord)); /* v' = v' + D3DTSS_BUMPENVMAT11(stage m)*t(n)G*/ ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), m11, NINE_APPLY_SWIZZLE(ureg_src(tx->regs.tS[n]), Y), @@ -2600,7 +2651,7 @@ DECL_SPECIAL(TEX) src[1] = ureg_DECL_sampler(ureg, s); tx->info->sampler_mask |= 1 << s; - ureg_TEX(ureg, dst, t, src[0], src[1]); + TEX_with_ps1x_projection(tx, dst, t, src[0], src[1], s); return D3D_OK; } diff --git a/src/gallium/state_trackers/nine/nine_shader.h b/src/gallium/state_trackers/nine/nine_shader.h index 3ba79af47c7..41577ac572b 100644 --- a/src/gallium/state_trackers/nine/nine_shader.h +++ b/src/gallium/state_trackers/nine/nine_shader.h @@ -61,6 +61,7 @@ struct nine_shader_info uint8_t fog_enable; uint8_t fog_mode; + uint16_t projected; /* ps 1.1 to 1.3 */ unsigned const_i_base; /* in vec4 (16 byte) units */ unsigned const_b_base; /* in vec4 (16 byte) units */ diff --git a/src/gallium/state_trackers/nine/nine_state.c b/src/gallium/state_trackers/nine/nine_state.c index e185b025134..a4392171f2c 100644 --- a/src/gallium/state_trackers/nine/nine_state.c +++ b/src/gallium/state_trackers/nine/nine_state.c @@ -961,7 +961,8 @@ commit_ps(struct NineDevice9 *device) NINE_STATE_BLEND_COLOR | \ NINE_STATE_STENCIL_REF | \ NINE_STATE_SAMPLE_MASK | \ - NINE_STATE_FOG_SHADER) + NINE_STATE_FOG_SHADER | \ + NINE_STATE_PS1X_SHADER) #define NINE_STATE_FREQ_GROUP_1 ~NINE_STATE_FREQ_GROUP_0 @@ -1032,7 +1033,7 @@ nine_update_state(struct NineDevice9 *device) if (group & NINE_STATE_RASTERIZER) prepare_rasterizer(device); - if (group & (NINE_STATE_PS | NINE_STATE_TEXTURE | NINE_STATE_FOG_SHADER)) + if (group & (NINE_STATE_PS | NINE_STATE_TEXTURE | NINE_STATE_FOG_SHADER | NINE_STATE_PS1X_SHADER)) group |= prepare_ps(device, (group & NINE_STATE_PS) != 0); if (group & NINE_STATE_BLEND_COLOR) { diff --git a/src/gallium/state_trackers/nine/nine_state.h b/src/gallium/state_trackers/nine/nine_state.h index f1af49fa137..109c0bb93ca 100644 --- a/src/gallium/state_trackers/nine/nine_state.h +++ b/src/gallium/state_trackers/nine/nine_state.h @@ -76,8 +76,9 @@ #define NINE_STATE_FF_PSSTAGES (1 << 22) #define NINE_STATE_FF_OTHER (1 << 23) #define NINE_STATE_FOG_SHADER (1 << 24) -#define NINE_STATE_ALL 0x1ffffff -#define NINE_STATE_UNHANDLED (1 << 25) +#define NINE_STATE_PS1X_SHADER (1 << 25) +#define NINE_STATE_ALL 0x3ffffff +#define NINE_STATE_UNHANDLED (1 << 26) #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 6173b0eea05..42bc349c2cc 100644 --- a/src/gallium/state_trackers/nine/pixelshader9.c +++ b/src/gallium/state_trackers/nine/pixelshader9.c @@ -58,6 +58,7 @@ NinePixelShader9_ctor( struct NinePixelShader9 *This, info.sampler_mask_shadow = 0x0; info.sampler_ps1xtypes = 0x0; info.fog_enable = 0; + info.projected = 0; hr = nine_translate_shader(device, &info); if (FAILED(hr)) @@ -159,6 +160,7 @@ NinePixelShader9_GetVariant( struct NinePixelShader9 *This ) info.sampler_ps1xtypes = key; info.fog_enable = device->state.rs[D3DRS_FOGENABLE]; info.fog_mode = device->state.rs[D3DRS_FOGTABLEMODE]; + info.projected = (key >> 48) & 0xffff; hr = nine_translate_shader(This->base.device, &info); if (FAILED(hr)) diff --git a/src/gallium/state_trackers/nine/pixelshader9.h b/src/gallium/state_trackers/nine/pixelshader9.h index 5d1f5041c47..e09009f6621 100644 --- a/src/gallium/state_trackers/nine/pixelshader9.h +++ b/src/gallium/state_trackers/nine/pixelshader9.h @@ -27,6 +27,7 @@ #include "nine_shader.h" #include "nine_state.h" #include "basetexture9.h" +#include "nine_ff.h" struct nine_lconstf; @@ -67,6 +68,7 @@ NinePixelShader9_UpdateKey( struct NinePixelShader9 *ps, { uint16_t samplers_shadow; uint32_t samplers_ps1_types; + uint16_t projected; uint64_t key; BOOL res; @@ -90,6 +92,11 @@ NinePixelShader9_UpdateKey( struct NinePixelShader9 *ps, key |= ((uint64_t)state->rs[D3DRS_FOGTABLEMODE]) << 33; } + if (unlikely(ps->byte_code.version < 0x14)) { + projected = nine_ff_get_projected_key(state); + key |= ((uint64_t) projected) << 48; + } + res = ps->last_key != key; if (res) ps->next_key = key; -- 2.11.0