st/nine: Use ff vertex shader when position_t is used

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>
This commit is contained in:
Axel Davy 2015-11-07 17:47:06 +01:00
parent 531acbc56b
commit b5876e4762
7 changed files with 36 additions and 15 deletions

View 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;
/* 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;

View 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);

View 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);

View 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;

View 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) {

View 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;

View file

@ -46,6 +46,8 @@ struct NineVertexDeclaration9
D3DVERTEXELEMENT9 *decls;
DWORD fvf;
BOOL position_t;
};
static inline struct NineVertexDeclaration9 *
NineVertexDeclaration9( void *data )