st/nine: Programmable ps D3DTTSS_PROJECTED support
authorAxel Davy <axel.davy@ens.fr>
Wed, 13 May 2015 23:27:33 +0000 (01:27 +0200)
committerAxel Davy <axel.davy@ens.fr>
Fri, 21 Aug 2015 20:21:48 +0000 (22:21 +0200)
The implementation used Wine tests for conformance

Signed-off-by: Axel Davy <axel.davy@ens.fr>
src/gallium/state_trackers/nine/device9.c
src/gallium/state_trackers/nine/nine_shader.c
src/gallium/state_trackers/nine/nine_shader.h
src/gallium/state_trackers/nine/nine_state.c
src/gallium/state_trackers/nine/nine_state.h
src/gallium/state_trackers/nine/pixelshader9.c
src/gallium/state_trackers/nine/pixelshader9.h

index 8023f785e10f0228a4382588cc162c4e1d4e5bca..aa5734b90f318832a10ac5b66690aa77f7028247 100644 (file)
@@ -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;
     }
index 2e35edecaf7bea4f8d7f03d1bec163f6f5cfc95e..7e76d7d5ba8df17f3cadac1ec07868159c795bc7 100644 (file)
@@ -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;
 }
index 3ba79af47c74a12d0d920e378d43204891d763c9..41577ac572b2a747ca7fbf01f2850070b0aa2e4f 100644 (file)
@@ -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 */
index e185b025134db4708e65e05597cd9a719a2fc62c..a4392171f2ca78747ac8dcd8ea6dc77eaa22464f 100644 (file)
@@ -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) {
index f1af49fa137b63a5ff6faf2b2cbed68a643869b3..109c0bb93caca34185230763e2d46be89ebb774d 100644 (file)
@@ -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)
index 6173b0eea05fd8f20072f9bb457980bf072f8505..42bc349c2cc0f95a2a46b6cf567400435ff8bba8 100644 (file)
@@ -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))
index 5d1f5041c474d702a2bf7e3a98429b9a4a6d0d90..e09009f6621d8698e2a5cc60ae4506ff822b6d3e 100644 (file)
@@ -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;