st/nine: Use ff vertex shader when position_t is used
authorAxel Davy <axel.davy@ens.fr>
Sat, 7 Nov 2015 16:47:06 +0000 (17:47 +0100)
committerAxel Davy <axel.davy@ens.fr>
Thu, 4 Feb 2016 21:12:17 +0000 (22:12 +0100)
When an application sets a vertex shader, we are supposed
to use it, and when no vertex shader are set, we are supposed
to revert to fixed function vertex shader.

It seems there is an exception: when the vertex declaration
has a position_t index, we should revert to fixed function
vertex shader.

Up to know we were checking if device->state.vs is set
to know whether to use programmable shader or not.

With this commit we determine whether we use programmable shader
or not when vertex shader/declaration are set, but
stateblocks do complicate things a bit.

Signed-off-by: Axel Davy <axel.davy@ens.fr>
Reviewed-by: Patrick Rudolph <siro@das-labor.org>
src/gallium/state_trackers/nine/device9.c
src/gallium/state_trackers/nine/nine_ff.c
src/gallium/state_trackers/nine/nine_state.c
src/gallium/state_trackers/nine/nine_state.h
src/gallium/state_trackers/nine/stateblock9.c
src/gallium/state_trackers/nine/vertexdeclaration9.c
src/gallium/state_trackers/nine/vertexdeclaration9.h

index 29e8aae54f6f28568d7bacbebd5ff04479725a03..055433ac85b0062ba6d820978cc06ba8ac2765ce 100644 (file)
@@ -3185,13 +3185,21 @@ NineDevice9_SetVertexDeclaration( struct NineDevice9 *This,
                                   IDirect3DVertexDeclaration9 *pDecl )
 {
     struct nine_state *state = This->update;
+    BOOL was_programmable_vs = This->state.programmable_vs;
 
     DBG("This=%p pDecl=%p\n", This, pDecl);
 
     if (likely(!This->is_recording) && state->vdecl == NineVertexDeclaration9(pDecl))
         return D3D_OK;
+
     nine_bind(&state->vdecl, pDecl);
 
+    This->state.programmable_vs = This->state.vs && !(This->state.vdecl && This->state.vdecl->position_t);
+    if (likely(!This->is_recording) && was_programmable_vs != This->state.programmable_vs) {
+        state->commit |= NINE_STATE_COMMIT_CONST_VS;
+        state->changed.group |= NINE_STATE_VS;
+    }
+
     state->changed.group |= NINE_STATE_VDECL;
 
     return D3D_OK;
@@ -3263,18 +3271,21 @@ NineDevice9_SetVertexShader( struct NineDevice9 *This,
                              IDirect3DVertexShader9 *pShader )
 {
     struct nine_state *state = This->update;
+    BOOL was_programmable_vs = This->state.programmable_vs;
 
     DBG("This=%p pShader=%p\n", This, pShader);
 
     if (!This->is_recording && state->vs == (struct NineVertexShader9*)pShader)
       return D3D_OK;
 
+    nine_bind(&state->vs, pShader);
+
+    This->state.programmable_vs = This->state.vs && !(This->state.vdecl && This->state.vdecl->position_t);
+
     /* ff -> non-ff: commit back non-ff constants */
-    if (!state->vs && pShader)
+    if (!was_programmable_vs && This->state.programmable_vs)
         state->commit |= NINE_STATE_COMMIT_CONST_VS;
 
-    nine_bind(&state->vs, pShader);
-
     state->changed.group |= NINE_STATE_VS;
 
     return D3D_OK;
index 9098684cb684102b80db80d3db3bef8e8d55abb2..120c605658bd2e536589ffa72abc9aa95f372019 100644 (file)
@@ -1868,7 +1868,7 @@ nine_ff_update(struct NineDevice9 *device)
     DBG("vs=%p ps=%p\n", device->state.vs, device->state.ps);
 
     /* NOTE: the only reference belongs to the hash table */
-    if (!device->state.vs) {
+    if (!state->programmable_vs) {
         device->ff.vs = nine_ff_get_vs(device);
         device->state.changed.group |= NINE_STATE_VS;
     }
@@ -1877,7 +1877,7 @@ nine_ff_update(struct NineDevice9 *device)
         device->state.changed.group |= NINE_STATE_PS;
     }
 
-    if (!device->state.vs) {
+    if (!state->programmable_vs) {
         nine_ff_load_vs_transforms(device);
         nine_ff_load_tex_matrices(device);
         nine_ff_load_lights(device);
index aee316220884405323d057093093e4cd98ddde3b..2e77d62b64fbf429ea1f1a9549e5ff8d8faf8407 100644 (file)
@@ -367,14 +367,14 @@ prepare_vs(struct NineDevice9 *device, uint8_t shader_changed)
     uint32_t changed_group = 0;
     int has_key_changed = 0;
 
-    if (likely(vs))
+    if (likely(state->programmable_vs))
         has_key_changed = NineVertexShader9_UpdateKey(vs, state);
 
     if (!shader_changed && !has_key_changed)
         return 0;
 
     /* likely because we dislike FF */
-    if (likely(vs)) {
+    if (likely(state->programmable_vs)) {
         state->cso.vs = NineVertexShader9_GetVariant(vs);
     } else {
         vs = device->ff.vs;
@@ -567,7 +567,7 @@ update_vertex_elements(struct NineDevice9 *device)
     state->stream_usage_mask = 0;
     memset(vdecl_index_map, -1, 16);
     memset(used_streams, 0, device->caps.MaxStreams);
-    vs = device->state.vs ? device->state.vs : device->ff.vs;
+    vs = state->programmable_vs ? device->state.vs : device->ff.vs;
 
     if (vdecl) {
         for (n = 0; n < vs->num_inputs; ++n) {
@@ -761,7 +761,7 @@ update_textures_and_samplers(struct NineDevice9 *device)
         cso_single_sampler_done(device->cso, PIPE_SHADER_FRAGMENT);
 
     commit_samplers = FALSE;
-    sampler_mask = state->vs ? state->vs->sampler_mask : 0;
+    sampler_mask = state->programmable_vs ? state->vs->sampler_mask : 0;
     state->bound_samplers_mask_vs = 0;
     for (num_textures = 0, i = 0; i < NINE_MAX_SAMPLERS_VS; ++i) {
         const unsigned s = NINE_SAMPLER_VS(i);
@@ -854,7 +854,7 @@ commit_vs_constants(struct NineDevice9 *device)
 {
     struct pipe_context *pipe = device->pipe;
 
-    if (unlikely(!device->state.vs))
+    if (unlikely(!device->state.programmable_vs))
         pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &device->state.pipe.cb_vs_ff);
     else
         pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &device->state.pipe.cb_vs);
@@ -964,7 +964,7 @@ nine_update_state(struct NineDevice9 *device)
     validate_textures(device); /* may clobber state */
 
     /* ff_update may change VS/PS dirty bits */
-    if (unlikely(!state->vs || !state->ps))
+    if (unlikely(!state->programmable_vs || !state->ps))
         nine_ff_update(device);
     group = state->changed.group;
 
@@ -997,12 +997,12 @@ nine_update_state(struct NineDevice9 *device)
         if (group & (NINE_STATE_TEXTURE | NINE_STATE_SAMPLER))
             update_textures_and_samplers(device);
         if (device->prefer_user_constbuf) {
-            if ((group & (NINE_STATE_VS_CONST | NINE_STATE_VS)) && state->vs)
+            if ((group & (NINE_STATE_VS_CONST | NINE_STATE_VS)) && state->programmable_vs)
                 prepare_vs_constants_userbuf(device);
             if ((group & (NINE_STATE_PS_CONST | NINE_STATE_PS)) && state->ps)
                 prepare_ps_constants_userbuf(device);
         } else {
-            if ((group & NINE_STATE_VS_CONST) && state->vs)
+            if ((group & NINE_STATE_VS_CONST) && state->programmable_vs)
                 upload_constants(device, PIPE_SHADER_VERTEX);
             if ((group & NINE_STATE_PS_CONST) && state->ps)
                 upload_constants(device, PIPE_SHADER_FRAGMENT);
index b34da70ef486c2c66681bc71e6a772175e74d1e1..88e5665c8c21a2c8ae3812b1977d05a946208a3a 100644 (file)
@@ -152,6 +152,7 @@ struct nine_state
     int    vs_const_i[NINE_MAX_CONST_I][4];
     BOOL   vs_const_b[NINE_MAX_CONST_B];
     float *vs_lconstf_temp;
+    BOOL programmable_vs;
 
     struct NinePixelShader9 *ps;
     float *ps_const_f;
index 77039596fdc2a9b826bbc8494e2af5aac55cc677..a1227f929c1318a8b808afb193f72b115ec5b6fe 100644 (file)
@@ -24,6 +24,7 @@
 #include "device9.h"
 #include "basetexture9.h"
 #include "nine_helpers.h"
+#include "vertexdeclaration9.h"
 
 #define DBG_CHANNEL DBG_STATEBLOCK
 
@@ -490,7 +491,10 @@ NineStateBlock9_Apply( struct NineStateBlock9 *This )
         nine_state_copy_common(dst, src, src, TRUE, pool);
 
     if ((src->changed.group & NINE_STATE_VDECL) && src->vdecl)
-        nine_bind(&dst->vdecl, src->vdecl);
+        NineDevice9_SetVertexDeclaration(This->base.device, (IDirect3DVertexDeclaration9 *)src->vdecl);
+
+    /* Recomputing it is needed if we changed vs but not vdecl */
+    dst->programmable_vs = dst->vs && !(dst->vdecl && dst->vdecl->position_t);
 
     /* Textures */
     if (src->changed.texture) {
index b35e72c3223cd62f1fb0633bcc47075b282b3f9d..36c594b5be3b87ac5c87b05eaa65bfcda8c5954a 100644 (file)
@@ -203,6 +203,9 @@ NineVertexDeclaration9_ctor( struct NineVertexDeclaration9 *This,
                                                      This->decls[i].UsageIndex);
         This->usage_map[i] = usage;
 
+        if (This->decls[i].Usage == D3DDECLUSAGE_POSITIONT)
+            This->position_t = TRUE;
+
         This->elems[i].src_offset = This->decls[i].Offset;
         This->elems[i].instance_divisor = 0;
         This->elems[i].vertex_buffer_index = This->decls[i].Stream;
index 655bcfbf165a22985e25d5217aeebc4822b23bf0..e39f259440fd6e378a830728549989f75550ab81 100644 (file)
@@ -46,6 +46,8 @@ struct NineVertexDeclaration9
 
     D3DVERTEXELEMENT9 *decls;
     DWORD fvf;
+
+    BOOL position_t;
 };
 static inline struct NineVertexDeclaration9 *
 NineVertexDeclaration9( void *data )