summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/state_trackers/nine/nine_state.c188
-rw-r--r--src/gallium/state_trackers/nine/nine_state.h4
-rw-r--r--src/gallium/state_trackers/nine/pixelshader9.c30
-rw-r--r--src/gallium/state_trackers/nine/pixelshader9.h41
-rw-r--r--src/gallium/state_trackers/nine/vertexshader9.c31
-rw-r--r--src/gallium/state_trackers/nine/vertexshader9.h28
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 3a02a8e4146..610798a3be7 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 b3a2babbd4f..efaee1ee95e 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 010c4f4bd28..5399afd3698 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 fc0a9a29687..69eb87b2e27 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 bbd5ce99d9a..956f0234b25 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 6e2810c989c..6cf7749e0ac 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 ***/