[Mesa-dev] [PATCH 51/71] st/nine: Rework shader states

Axel Davy axel.davy at ens.fr
Sun Aug 16 08:28:15 PDT 2015


Signed-off-by: Axel Davy <axel.davy at ens.fr>
---
 src/gallium/state_trackers/nine/nine_state.c    | 188 +++++++++++-------------
 src/gallium/state_trackers/nine/nine_state.h    |   4 +-
 src/gallium/state_trackers/nine/pixelshader9.c  |  30 +++-
 src/gallium/state_trackers/nine/pixelshader9.h  |  41 +++++-
 src/gallium/state_trackers/nine/vertexshader9.c |  31 +++-
 src/gallium/state_trackers/nine/vertexshader9.h |  28 +++-
 6 files changed, 207 insertions(+), 115 deletions(-)

diff --git a/src/gallium/state_trackers/nine/nine_state.c b/src/gallium/state_trackers/nine/nine_state.c
index 3a02a8e..610798a 100644
--- a/src/gallium/state_trackers/nine/nine_state.c
+++ b/src/gallium/state_trackers/nine/nine_state.c
@@ -328,6 +328,70 @@ prepare_ps_constants_userbuf(struct NineDevice9 *device)
     state->commit |= NINE_STATE_COMMIT_CONST_PS;
 }
 
+static inline uint32_t
+prepare_vs(struct NineDevice9 *device, uint8_t shader_changed)
+{
+    struct nine_state *state = &device->state;
+    struct NineVertexShader9 *vs = state->vs;
+    uint32_t changed_group = 0;
+    int has_key_changed = 0;
+
+    if (likely(vs))
+        has_key_changed = NineVertexShader9_UpdateKey(vs, state);
+
+    if (!shader_changed && !has_key_changed)
+        return 0;
+
+    /* likely because we dislike FF */
+    if (likely(vs)) {
+        state->cso.vs = NineVertexShader9_GetVariant(vs);
+    } else {
+        vs = device->ff.vs;
+        state->cso.vs = vs->ff_cso;
+    }
+
+    if (state->rs[NINED3DRS_VSPOINTSIZE] != vs->point_size) {
+        state->rs[NINED3DRS_VSPOINTSIZE] = vs->point_size;
+        changed_group |= NINE_STATE_RASTERIZER;
+    }
+
+    if ((state->bound_samplers_mask_vs & vs->sampler_mask) != vs->sampler_mask)
+        /* Bound dummy sampler. */
+        changed_group |= NINE_STATE_SAMPLER;
+
+    state->commit |= NINE_STATE_COMMIT_VS;
+    return changed_group;
+}
+
+static inline uint32_t
+prepare_ps(struct NineDevice9 *device, uint8_t shader_changed)
+{
+    struct nine_state *state = &device->state;
+    struct NinePixelShader9 *ps = state->ps;
+    uint32_t changed_group = 0;
+    int has_key_changed = 0;
+
+    if (likely(ps))
+        has_key_changed = NinePixelShader9_UpdateKey(ps, state);
+
+    if (!shader_changed && !has_key_changed)
+        return 0;
+
+    if (likely(ps)) {
+        state->cso.ps = NinePixelShader9_GetVariant(ps);
+    } else {
+        ps = device->ff.ps;
+        state->cso.ps = ps->ff_cso;
+    }
+
+    if ((state->bound_samplers_mask_ps & ps->sampler_mask) != ps->sampler_mask)
+        /* Bound dummy sampler. */
+        changed_group |= NINE_STATE_SAMPLER;
+
+    state->commit |= NINE_STATE_COMMIT_PS;
+    return changed_group;
+}
+
 /* State preparation incremental */
 
 /* State preparation + State commit */
@@ -563,92 +627,6 @@ update_vertex_elements(struct NineDevice9 *device)
     state->changed.stream_freq = 0;
 }
 
-static inline uint32_t
-update_shader_variant_keys(struct NineDevice9 *device)
-{
-    struct nine_state *state = &device->state;
-    uint32_t mask = 0;
-    uint32_t vs_key = state->samplers_shadow;
-    uint32_t ps_key = state->samplers_shadow;
-
-    vs_key = (vs_key & NINE_VS_SAMPLERS_MASK) >> NINE_SAMPLER_VS(0);
-    ps_key = (ps_key & NINE_PS_SAMPLERS_MASK) >> NINE_SAMPLER_PS(0);
-
-    if (state->vs) vs_key &= state->vs->sampler_mask;
-    if (state->ps) {
-        if (unlikely(state->ps->byte_code.version < 0x20)) {
-            /* no depth textures, but variable targets */
-            uint32_t m = state->ps->sampler_mask;
-            ps_key = 0;
-            while (m) {
-                int s = ffs(m) - 1;
-                m &= ~(1 << s);
-                ps_key |= (state->texture[s] ? state->texture[s]->pstype : 1) << (s * 2);
-            }
-        } else {
-            ps_key &= state->ps->sampler_mask;
-        }
-    }
-
-    if (state->vs && state->vs_key != vs_key) {
-        state->vs_key = vs_key;
-        mask |= NINE_STATE_VS;
-    }
-    if (state->ps && state->ps_key != ps_key) {
-        state->ps_key = ps_key;
-        mask |= NINE_STATE_PS;
-    }
-    return mask;
-}
-
-static inline uint32_t
-update_vs(struct NineDevice9 *device)
-{
-    struct nine_state *state = &device->state;
-    struct NineVertexShader9 *vs = state->vs;
-    uint32_t changed_group = 0;
-
-    /* likely because we dislike FF */
-    if (likely(vs)) {
-        state->cso.vs = NineVertexShader9_GetVariant(vs, state->vs_key);
-    } else {
-        vs = device->ff.vs;
-        state->cso.vs = vs->variant.cso;
-    }
-    device->pipe->bind_vs_state(device->pipe, state->cso.vs);
-
-    if (state->rs[NINED3DRS_VSPOINTSIZE] != vs->point_size) {
-        state->rs[NINED3DRS_VSPOINTSIZE] = vs->point_size;
-        changed_group |= NINE_STATE_RASTERIZER;
-    }
-
-    if ((state->bound_samplers_mask_vs & vs->sampler_mask) != vs->sampler_mask)
-        /* Bound dummy sampler. */
-        changed_group |= NINE_STATE_SAMPLER;
-    return changed_group;
-}
-
-static inline uint32_t
-update_ps(struct NineDevice9 *device)
-{
-    struct nine_state *state = &device->state;
-    struct NinePixelShader9 *ps = state->ps;
-    uint32_t changed_group = 0;
-
-    if (likely(ps)) {
-        state->cso.ps = NinePixelShader9_GetVariant(ps, state->ps_key);
-    } else {
-        ps = device->ff.ps;
-        state->cso.ps = ps->variant.cso;
-    }
-    device->pipe->bind_fs_state(device->pipe, state->cso.ps);
-
-    if ((state->bound_samplers_mask_ps & ps->sampler_mask) != ps->sampler_mask)
-        /* Bound dummy sampler. */
-        changed_group |= NINE_STATE_SAMPLER;
-    return changed_group;
-}
-
 static void
 update_vertex_buffers(struct NineDevice9 *device)
 {
@@ -924,6 +902,22 @@ commit_ps_constants(struct NineDevice9 *device)
         pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &device->state.pipe.cb_ps);
 }
 
+static inline void
+commit_vs(struct NineDevice9 *device)
+{
+    struct nine_state *state = &device->state;
+
+    device->pipe->bind_vs_state(device->pipe, state->cso.vs);
+}
+
+
+static inline void
+commit_ps(struct NineDevice9 *device)
+{
+    struct nine_state *state = &device->state;
+
+    device->pipe->bind_fs_state(device->pipe, state->cso.ps);
+}
 /* State Update */
 
 #define NINE_STATE_FREQ_GROUP_0 \
@@ -941,11 +935,6 @@ commit_ps_constants(struct NineDevice9 *device)
 
 #define NINE_STATE_FREQ_GROUP_1 ~NINE_STATE_FREQ_GROUP_0
 
-#define NINE_STATE_SHADER_VARIANT_GROUP \
-    (NINE_STATE_TEXTURE | \
-     NINE_STATE_VS | \
-     NINE_STATE_PS)
-
 /* TODO: only go through dirty textures */
 static void
 validate_textures(struct NineDevice9 *device)
@@ -994,10 +983,7 @@ nine_update_state(struct NineDevice9 *device)
         nine_ff_update(device);
     group = state->changed.group;
 
-    if (group & NINE_STATE_SHADER_VARIANT_GROUP)
-        group |= update_shader_variant_keys(device);
-
-    if (group & NINE_STATE_FREQ_GROUP_0) {
+    if (group & (NINE_STATE_FREQ_GROUP_0 | NINE_STATE_TEXTURE)) {
         if (group & NINE_STATE_FB)
             group = update_framebuffer(device);
         if (group & NINE_STATE_VIEWPORT)
@@ -1010,14 +996,14 @@ nine_update_state(struct NineDevice9 *device)
         if (group & NINE_STATE_BLEND)
             prepare_blend(device);
 
-        if (group & NINE_STATE_VS)
-            group |= update_vs(device);
+        if (group & (NINE_STATE_VS | NINE_STATE_TEXTURE))
+            group |= prepare_vs(device, (group & NINE_STATE_VS) != 0);
 
         if (group & NINE_STATE_RASTERIZER)
             prepare_rasterizer(device);
 
-        if (group & NINE_STATE_PS)
-            group |= update_ps(device);
+        if (group & (NINE_STATE_PS | NINE_STATE_TEXTURE))
+            group |= prepare_ps(device, (group & NINE_STATE_PS) != 0);
 
         if (group & NINE_STATE_BLEND_COLOR) {
             struct pipe_blend_color color;
@@ -1076,6 +1062,10 @@ nine_update_state(struct NineDevice9 *device)
         commit_vs_constants(device);
     if (state->commit & NINE_STATE_COMMIT_CONST_PS)
         commit_ps_constants(device);
+    if (state->commit & NINE_STATE_COMMIT_VS)
+        commit_vs(device);
+    if (state->commit & NINE_STATE_COMMIT_PS)
+        commit_ps(device);
 
     state->commit = 0;
 
diff --git a/src/gallium/state_trackers/nine/nine_state.h b/src/gallium/state_trackers/nine/nine_state.h
index b3a2bab..efaee1e 100644
--- a/src/gallium/state_trackers/nine/nine_state.h
+++ b/src/gallium/state_trackers/nine/nine_state.h
@@ -83,6 +83,8 @@
 #define NINE_STATE_COMMIT_BLEND (1 << 2)
 #define NINE_STATE_COMMIT_CONST_VS (1 << 3)
 #define NINE_STATE_COMMIT_CONST_PS (1 << 4)
+#define NINE_STATE_COMMIT_VS (1 << 5)
+#define NINE_STATE_COMMIT_PS (1 << 6)
 
 
 #define NINE_MAX_SIMULTANEOUS_RENDERTARGETS 4
@@ -148,7 +150,6 @@ struct nine_state
     int    vs_const_i[NINE_MAX_CONST_I][4];
     BOOL   vs_const_b[NINE_MAX_CONST_B];
     float *vs_lconstf_temp;
-    uint32_t vs_key;
 
     struct NinePixelShader9 *ps;
     float *ps_const_f;
@@ -156,7 +157,6 @@ struct nine_state
     BOOL   ps_const_b[NINE_MAX_CONST_B];
     float *ps_lconstf_temp;
     uint32_t bumpmap_vars[48];
-    uint32_t ps_key;
 
     struct {
         void *vs;
diff --git a/src/gallium/state_trackers/nine/pixelshader9.c b/src/gallium/state_trackers/nine/pixelshader9.c
index 010c4f4..5399afd 100644
--- a/src/gallium/state_trackers/nine/pixelshader9.c
+++ b/src/gallium/state_trackers/nine/pixelshader9.c
@@ -46,7 +46,7 @@ NinePixelShader9_ctor( struct NinePixelShader9 *This,
         return hr;
 
     if (cso) {
-        This->variant.cso = cso;
+        This->ff_cso = cso;
         return D3D_OK;
     }
     device = This->base.device;
@@ -69,6 +69,9 @@ NinePixelShader9_ctor( struct NinePixelShader9 *This,
     This->byte_code.size = info.byte_size;
 
     This->variant.cso = info.cso;
+    This->last_cso = info.cso;
+    This->last_key = 0;
+
     This->sampler_mask = info.sampler_mask;
     This->rt_mask = info.rt_mask;
     This->const_used_size = info.const_used_size;
@@ -83,11 +86,12 @@ NinePixelShader9_ctor( struct NinePixelShader9 *This,
 void
 NinePixelShader9_dtor( struct NinePixelShader9 *This )
 {
-    DBG("This=%p cso=%p\n", This, This->variant.cso);
+    DBG("This=%p\n", This);
 
     if (This->base.device) {
         struct pipe_context *pipe = This->base.device->pipe;
         struct nine_shader_variant *var = &This->variant;
+
         do {
             if (var->cso) {
                 if (This->base.device->state.cso.ps == var->cso)
@@ -96,6 +100,12 @@ NinePixelShader9_dtor( struct NinePixelShader9 *This )
             }
             var = var->next;
         } while (var);
+
+        if (This->ff_cso) {
+            if (This->ff_cso == This->base.device->state.cso.ps)
+                pipe->bind_fs_state(pipe, NULL);
+            pipe->delete_fs_state(pipe, This->ff_cso);
+        }
     }
     nine_shader_variants_free(&This->variant);
 
@@ -125,10 +135,16 @@ NinePixelShader9_GetFunction( struct NinePixelShader9 *This,
 }
 
 void *
-NinePixelShader9_GetVariant( struct NinePixelShader9 *This,
-                             uint32_t key )
+NinePixelShader9_GetVariant( struct NinePixelShader9 *This )
 {
-    void *cso = nine_shader_variant_get(&This->variant, key);
+    void *cso;
+    uint32_t key;
+
+    key = This->next_key;
+    if (key == This->last_key)
+        return This->last_cso;
+
+    cso = nine_shader_variant_get(&This->variant, key);
     if (!cso) {
         struct NineDevice9 *device = This->base.device;
         struct nine_shader_info info;
@@ -147,6 +163,10 @@ NinePixelShader9_GetVariant( struct NinePixelShader9 *This,
         nine_shader_variant_add(&This->variant, key, info.cso);
         cso = info.cso;
     }
+
+    This->last_key = key;
+    This->last_cso = cso;
+
     return cso;
 }
 
diff --git a/src/gallium/state_trackers/nine/pixelshader9.h b/src/gallium/state_trackers/nine/pixelshader9.h
index fc0a9a2..69eb87b 100644
--- a/src/gallium/state_trackers/nine/pixelshader9.h
+++ b/src/gallium/state_trackers/nine/pixelshader9.h
@@ -25,6 +25,8 @@
 
 #include "iunknown.h"
 #include "nine_shader.h"
+#include "nine_state.h"
+#include "basetexture9.h"
 
 struct nine_lconstf;
 
@@ -46,6 +48,12 @@ struct NinePixelShader9
     uint8_t rt_mask;
 
     uint64_t ff_key[6];
+    void *ff_cso;
+
+    uint32_t last_key;
+    void *last_cso;
+
+    uint32_t next_key;
 };
 static inline struct NinePixelShader9 *
 NinePixelShader9( void *data )
@@ -53,9 +61,38 @@ NinePixelShader9( void *data )
     return (struct NinePixelShader9 *)data;
 }
 
+static inline BOOL
+NinePixelShader9_UpdateKey( struct NinePixelShader9 *ps,
+                            struct nine_state *state )
+{
+    uint16_t samplers_shadow;
+    uint32_t samplers_ps1_types;
+    uint32_t key;
+    BOOL res;
+
+    if (unlikely(ps->byte_code.version < 0x20)) {
+        /* no depth textures, but variable targets */
+        uint32_t m = ps->sampler_mask;
+        samplers_ps1_types = 0;
+        while (m) {
+            int s = ffs(m) - 1;
+            m &= ~(1 << s);
+            samplers_ps1_types |= (state->texture[s] ? state->texture[s]->pstype : 1) << (s * 2);
+        }
+        key = samplers_ps1_types;
+    } else {
+        samplers_shadow = (uint16_t)((state->samplers_shadow & NINE_PS_SAMPLERS_MASK) >> NINE_SAMPLER_PS(0));
+        key = samplers_shadow & ps->sampler_mask;
+    }
+
+    res = ps->last_key != key;
+    if (res)
+        ps->next_key = key;
+    return res;
+}
+
 void *
-NinePixelShader9_GetVariant( struct NinePixelShader9 *vs,
-                             uint32_t key );
+NinePixelShader9_GetVariant( struct NinePixelShader9 *ps );
 
 /*** public ***/
 
diff --git a/src/gallium/state_trackers/nine/vertexshader9.c b/src/gallium/state_trackers/nine/vertexshader9.c
index bbd5ce9..956f023 100644
--- a/src/gallium/state_trackers/nine/vertexshader9.c
+++ b/src/gallium/state_trackers/nine/vertexshader9.c
@@ -48,9 +48,10 @@ NineVertexShader9_ctor( struct NineVertexShader9 *This,
         return hr;
 
     if (cso) {
-        This->variant.cso = cso;
+        This->ff_cso = cso;
         return D3D_OK;
     }
+
     device = This->base.device;
 
     info.type = PIPE_SHADER_VERTEX;
@@ -71,6 +72,9 @@ NineVertexShader9_ctor( struct NineVertexShader9 *This,
     This->byte_code.size = info.byte_size;
 
     This->variant.cso = info.cso;
+    This->last_cso = info.cso;
+    This->last_key = 0;
+
     This->const_used_size = info.const_used_size;
     This->lconstf = info.lconstf;
     This->sampler_mask = info.sampler_mask;
@@ -87,11 +91,12 @@ NineVertexShader9_ctor( struct NineVertexShader9 *This,
 void
 NineVertexShader9_dtor( struct NineVertexShader9 *This )
 {
-    DBG("This=%p cso=%p\n", This, This->variant.cso);
+    DBG("This=%p\n", This);
 
     if (This->base.device) {
         struct pipe_context *pipe = This->base.device->pipe;
         struct nine_shader_variant *var = &This->variant;
+
         do {
             if (var->cso) {
                 if (This->base.device->state.cso.vs == var->cso)
@@ -100,6 +105,12 @@ NineVertexShader9_dtor( struct NineVertexShader9 *This )
             }
             var = var->next;
         } while (var);
+
+        if (This->ff_cso) {
+            if (This->ff_cso == This->base.device->state.cso.vs)
+                pipe->bind_vs_state(pipe, NULL);
+            pipe->delete_vs_state(pipe, This->ff_cso);
+        }
     }
     nine_shader_variants_free(&This->variant);
 
@@ -130,10 +141,16 @@ NineVertexShader9_GetFunction( struct NineVertexShader9 *This,
 }
 
 void *
-NineVertexShader9_GetVariant( struct NineVertexShader9 *This,
-                              uint32_t key )
+NineVertexShader9_GetVariant( struct NineVertexShader9 *This )
 {
-    void *cso = nine_shader_variant_get(&This->variant, key);
+    void *cso;
+    uint32_t key;
+
+    key = This->next_key;
+    if (key == This->last_key)
+        return This->last_cso;
+
+    cso = nine_shader_variant_get(&This->variant, key);
     if (!cso) {
         struct NineDevice9 *device = This->base.device;
         struct nine_shader_info info;
@@ -151,6 +168,10 @@ NineVertexShader9_GetVariant( struct NineVertexShader9 *This,
         nine_shader_variant_add(&This->variant, key, info.cso);
         cso = info.cso;
     }
+
+    This->last_key = key;
+    This->last_cso = cso;
+
     return cso;
 }
 
diff --git a/src/gallium/state_trackers/nine/vertexshader9.h b/src/gallium/state_trackers/nine/vertexshader9.h
index 6e2810c..6cf7749 100644
--- a/src/gallium/state_trackers/nine/vertexshader9.h
+++ b/src/gallium/state_trackers/nine/vertexshader9.h
@@ -25,6 +25,7 @@
 
 #include "iunknown.h"
 #include "nine_shader.h"
+#include "nine_state.h"
 
 struct NineVertexShader9
 {
@@ -54,6 +55,12 @@ struct NineVertexShader9
     const struct pipe_stream_output_info *so;
 
     uint64_t ff_key[2];
+    void *ff_cso;
+
+    uint32_t last_key;
+    void *last_cso;
+
+    uint32_t next_key;
 };
 static inline struct NineVertexShader9 *
 NineVertexShader9( void *data )
@@ -61,9 +68,26 @@ NineVertexShader9( void *data )
     return (struct NineVertexShader9 *)data;
 }
 
+static inline BOOL
+NineVertexShader9_UpdateKey( struct NineVertexShader9 *vs,
+                             struct nine_state *state )
+{
+    uint8_t samplers_shadow;
+    uint32_t key;
+    BOOL res;
+
+    samplers_shadow = (uint8_t)((state->samplers_shadow & NINE_VS_SAMPLERS_MASK) >> NINE_SAMPLER_VS(0));
+    samplers_shadow &= vs->sampler_mask;
+    key = samplers_shadow;
+
+    res = vs->last_key != key;
+    if (res)
+        vs->next_key = key;
+    return res;
+}
+
 void *
-NineVertexShader9_GetVariant( struct NineVertexShader9 *vs,
-                              uint32_t key );
+NineVertexShader9_GetVariant( struct NineVertexShader9 *vs );
 
 /*** public ***/
 
-- 
2.1.0



More information about the mesa-dev mailing list