diff --git a/src/gallium/state_trackers/nine/device9.c b/src/gallium/state_trackers/nine/device9.c index 29e8aae54f6..055433ac85b 100644 --- a/src/gallium/state_trackers/nine/device9.c +++ b/src/gallium/state_trackers/nine/device9.c @@ -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; - /* ff -> non-ff: commit back non-ff constants */ - if (!state->vs && pShader) - state->commit |= NINE_STATE_COMMIT_CONST_VS; - 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 (!was_programmable_vs && This->state.programmable_vs) + state->commit |= NINE_STATE_COMMIT_CONST_VS; + state->changed.group |= NINE_STATE_VS; return D3D_OK; diff --git a/src/gallium/state_trackers/nine/nine_ff.c b/src/gallium/state_trackers/nine/nine_ff.c index 9098684cb68..120c605658b 100644 --- a/src/gallium/state_trackers/nine/nine_ff.c +++ b/src/gallium/state_trackers/nine/nine_ff.c @@ -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); diff --git a/src/gallium/state_trackers/nine/nine_state.c b/src/gallium/state_trackers/nine/nine_state.c index aee31622088..2e77d62b64f 100644 --- a/src/gallium/state_trackers/nine/nine_state.c +++ b/src/gallium/state_trackers/nine/nine_state.c @@ -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); diff --git a/src/gallium/state_trackers/nine/nine_state.h b/src/gallium/state_trackers/nine/nine_state.h index b34da70ef48..88e5665c8c2 100644 --- a/src/gallium/state_trackers/nine/nine_state.h +++ b/src/gallium/state_trackers/nine/nine_state.h @@ -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; diff --git a/src/gallium/state_trackers/nine/stateblock9.c b/src/gallium/state_trackers/nine/stateblock9.c index 77039596fdc..a1227f929c1 100644 --- a/src/gallium/state_trackers/nine/stateblock9.c +++ b/src/gallium/state_trackers/nine/stateblock9.c @@ -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) { diff --git a/src/gallium/state_trackers/nine/vertexdeclaration9.c b/src/gallium/state_trackers/nine/vertexdeclaration9.c index b35e72c3223..36c594b5be3 100644 --- a/src/gallium/state_trackers/nine/vertexdeclaration9.c +++ b/src/gallium/state_trackers/nine/vertexdeclaration9.c @@ -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; diff --git a/src/gallium/state_trackers/nine/vertexdeclaration9.h b/src/gallium/state_trackers/nine/vertexdeclaration9.h index 655bcfbf165..e39f259440f 100644 --- a/src/gallium/state_trackers/nine/vertexdeclaration9.h +++ b/src/gallium/state_trackers/nine/vertexdeclaration9.h @@ -46,6 +46,8 @@ struct NineVertexDeclaration9 D3DVERTEXELEMENT9 *decls; DWORD fvf; + + BOOL position_t; }; static inline struct NineVertexDeclaration9 * NineVertexDeclaration9( void *data )