diff options
Diffstat (limited to 'src/gallium/state_trackers/nine')
-rw-r--r-- | src/gallium/state_trackers/nine/device9.c | 39 | ||||
-rw-r--r-- | src/gallium/state_trackers/nine/device9.h | 3 | ||||
-rw-r--r-- | src/gallium/state_trackers/nine/nine_ff.c | 7 | ||||
-rw-r--r-- | src/gallium/state_trackers/nine/nine_state.c | 155 | ||||
-rw-r--r-- | src/gallium/state_trackers/nine/nine_state.h | 2 |
5 files changed, 163 insertions, 43 deletions
diff --git a/src/gallium/state_trackers/nine/device9.c b/src/gallium/state_trackers/nine/device9.c index 25e1444f6b4..e0524644f8a 100644 --- a/src/gallium/state_trackers/nine/device9.c +++ b/src/gallium/state_trackers/nine/device9.c @@ -298,6 +298,43 @@ NineDevice9_ctor( struct NineDevice9 *This, return E_OUTOFMEMORY; } + /* allocate dummy texture/sampler for when there are missing ones bound */ + { + struct pipe_resource tmplt; + struct pipe_sampler_view templ; + + tmplt.target = PIPE_TEXTURE_2D; + tmplt.width0 = 1; + tmplt.height0 = 1; + tmplt.depth0 = 1; + tmplt.last_level = 0; + tmplt.array_size = 1; + tmplt.usage = PIPE_USAGE_DEFAULT; + tmplt.flags = 0; + tmplt.format = PIPE_FORMAT_B8G8R8A8_UNORM; + tmplt.bind = PIPE_BIND_SAMPLER_VIEW; + tmplt.nr_samples = 0; + + This->dummy_texture = This->screen->resource_create(This->screen, &tmplt); + if (!This->dummy_texture) + return D3DERR_DRIVERINTERNALERROR; + + templ.format = PIPE_FORMAT_B8G8R8A8_UNORM; + templ.u.tex.first_layer = 0; + templ.u.tex.last_layer = 0; + templ.u.tex.first_level = 0; + templ.u.tex.last_level = 0; + templ.swizzle_r = PIPE_SWIZZLE_ZERO; + templ.swizzle_g = PIPE_SWIZZLE_ZERO; + templ.swizzle_b = PIPE_SWIZZLE_ZERO; + templ.swizzle_a = PIPE_SWIZZLE_ONE; + templ.target = This->dummy_texture->target; + + This->dummy_sampler = This->pipe->create_sampler_view(This->pipe, This->dummy_texture, &templ); + if (!This->dummy_sampler) + return D3DERR_DRIVERINTERNALERROR; + } + /* Allocate upload helper for drivers that suck (from st pov ;). */ { unsigned bind = 0; @@ -346,6 +383,8 @@ NineDevice9_dtor( struct NineDevice9 *This ) nine_bind(&This->record, NULL); + pipe_sampler_view_reference(&This->dummy_sampler, NULL); + pipe_resource_reference(&This->dummy_texture, NULL); pipe_resource_reference(&This->constbuf_vs, NULL); pipe_resource_reference(&This->constbuf_ps, NULL); FREE(This->state.vs_const_f); diff --git a/src/gallium/state_trackers/nine/device9.h b/src/gallium/state_trackers/nine/device9.h index dc97ae7161d..54da9e3a624 100644 --- a/src/gallium/state_trackers/nine/device9.h +++ b/src/gallium/state_trackers/nine/device9.h @@ -82,6 +82,9 @@ struct NineDevice9 uint16_t max_vs_const_f; uint16_t max_ps_const_f; + struct pipe_resource *dummy_texture; + struct pipe_sampler_view *dummy_sampler; + struct gen_mipmap_state *gen_mipmap; struct { diff --git a/src/gallium/state_trackers/nine/nine_ff.c b/src/gallium/state_trackers/nine/nine_ff.c index 2e3470f92ef..e6f2b21dd4d 100644 --- a/src/gallium/state_trackers/nine/nine_ff.c +++ b/src/gallium/state_trackers/nine/nine_ff.c @@ -1493,6 +1493,7 @@ nine_ff_get_ps(struct NineDevice9 *device) enum pipe_error err; struct nine_ff_ps_key key; unsigned s; + uint8_t sampler_mask = 0; assert(sizeof(key) <= sizeof(key.value32)); @@ -1506,12 +1507,17 @@ nine_ff_get_ps(struct NineDevice9 *device) key.ts[s].alphaop = D3DTOP_DISABLE; /* DISABLE == 1, avoid degenerate keys */ break; } + if (!state->texture[s] && state->ff.tex_stage[s][D3DTSS_COLORARG1] == D3DTA_TEXTURE) { /* This should also disable the stage. */ key.ts[s].colorop = key.ts[s].alphaop = D3DTOP_DISABLE; break; } + + if (state->ff.tex_stage[s][D3DTSS_COLORARG1] == D3DTA_TEXTURE) + sampler_mask |= (1 << s); + if (key.ts[s].colorop != D3DTOP_DISABLE) { uint8_t used_c = ps_d3dtop_args_mask(key.ts[s].colorop); if (used_c & 0x1) key.ts[s].colorarg0 = state->ff.tex_stage[s][D3DTSS_COLORARG0]; @@ -1570,6 +1576,7 @@ nine_ff_get_ps(struct NineDevice9 *device) NineUnknown_ConvertRefToBind(NineUnknown(ps)); ps->rt_mask = 0x1; + ps->sampler_mask = sampler_mask; } return ps; } diff --git a/src/gallium/state_trackers/nine/nine_state.c b/src/gallium/state_trackers/nine/nine_state.c index 86a6ca8ee40..ba758176f49 100644 --- a/src/gallium/state_trackers/nine/nine_state.c +++ b/src/gallium/state_trackers/nine/nine_state.c @@ -279,6 +279,7 @@ 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)) { @@ -291,17 +292,13 @@ update_vs(struct NineDevice9 *device) if (state->rs[NINED3DRS_VSPOINTSIZE] != vs->point_size) { state->rs[NINED3DRS_VSPOINTSIZE] = vs->point_size; - return NINE_STATE_RASTERIZER; + changed_group |= NINE_STATE_RASTERIZER; } -#ifdef DEBUG - { - unsigned s, mask = vs->sampler_mask; - for (s = 0; mask; ++s, mask >>= 1) - if ((mask & 1) && !(device->state.texture[NINE_SAMPLER_VS(s)])) - WARN_ONCE("FIXME: unbound sampler should return alpha=1\n"); - } -#endif - return 0; + + 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 @@ -309,6 +306,7 @@ 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); @@ -318,15 +316,10 @@ update_ps(struct NineDevice9 *device) } device->pipe->bind_fs_state(device->pipe, state->cso.ps); -#ifdef DEBUG - { - unsigned s, mask = ps->sampler_mask; - for (s = 0; mask; ++s, mask >>= 1) - if ((mask & 1) && !(device->state.texture[NINE_SAMPLER_PS(s)])) - WARN_ONCE("FIXME: unbound sampler should return alpha=1\n"); - } -#endif - return 0; + if ((state->bound_samplers_mask_ps & ps->sampler_mask) != ps->sampler_mask) + /* Bound dummy sampler. */ + changed_group |= NINE_STATE_SAMPLER; + return changed_group; } #define DO_UPLOAD_CONST_F(buf,p,c,d) \ @@ -651,66 +644,142 @@ update_textures_and_samplers(struct NineDevice9 *device) struct pipe_context *pipe = device->pipe; struct nine_state *state = &device->state; struct pipe_sampler_view *view[NINE_MAX_SAMPLERS]; + struct pipe_sampler_state samp; unsigned num_textures; unsigned i; + boolean commit_views; boolean commit_samplers; + uint16_t sampler_mask = state->ps ? state->ps->sampler_mask : + device->ff.ps->sampler_mask; /* TODO: Can we reduce iterations here ? */ + commit_views = FALSE; commit_samplers = FALSE; + state->bound_samplers_mask_ps = 0; for (num_textures = 0, i = 0; i < NINE_MAX_SAMPLERS_PS; ++i) { const unsigned s = NINE_SAMPLER_PS(i); int sRGB; - if (!state->texture[s]) { + + if (!state->texture[s] && !(sampler_mask & (1 << i))) { view[i] = NULL; -#ifdef DEBUG - if (state->ps && state->ps->sampler_mask & (1 << i)) - WARN_ONCE("FIXME: unbound sampler should return alpha=1\n"); -#endif continue; } - sRGB = state->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0; - view[i] = NineBaseTexture9_GetSamplerView(state->texture[s], sRGB); - num_textures = i + 1; + if (state->texture[s]) { + sRGB = state->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0; - if (update_sampler_derived(state, s) || (state->changed.sampler[s] & 0x05fe)) { - state->changed.sampler[s] = 0; + view[i] = NineBaseTexture9_GetSamplerView(state->texture[s], sRGB); + num_textures = i + 1; + + if (update_sampler_derived(state, s) || (state->changed.sampler[s] & 0x05fe)) { + state->changed.sampler[s] = 0; + commit_samplers = TRUE; + nine_convert_sampler_state(device->cso, s, state->samp[s]); + } + } else { + /* Bind dummy sampler. We do not bind dummy sampler when + * it is not needed because it could add overhead. The + * dummy sampler should have r=g=b=0 and a=1. We do not + * unbind dummy sampler directly when they are not needed + * anymore, but they're going to be removed as long as texture + * or sampler states are changed. */ + view[i] = device->dummy_sampler; + num_textures = i + 1; + + memset(&samp, 0, sizeof(samp)); + samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + samp.max_lod = 15.0f; + samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + samp.min_img_filter = PIPE_TEX_FILTER_NEAREST; + samp.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + samp.compare_mode = PIPE_TEX_COMPARE_NONE; + samp.compare_func = PIPE_FUNC_LEQUAL; + samp.normalized_coords = 1; + samp.seamless_cube_map = 1; + + cso_single_sampler(device->cso, PIPE_SHADER_FRAGMENT, + s - NINE_SAMPLER_PS(0), &samp); + + commit_views = TRUE; commit_samplers = TRUE; - nine_convert_sampler_state(device->cso, s, state->samp[s]); + state->changed.sampler[s] = ~0; } + + state->bound_samplers_mask_ps |= (1 << s); } - if (state->changed.texture & NINE_PS_SAMPLERS_MASK || state->changed.srgb) + + commit_views |= (state->changed.texture & NINE_PS_SAMPLERS_MASK) != 0; + commit_views |= state->changed.srgb; + if (commit_views) pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, num_textures, view); if (commit_samplers) cso_single_sampler_done(device->cso, PIPE_SHADER_FRAGMENT); + commit_views = FALSE; commit_samplers = FALSE; + sampler_mask = state->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); int sRGB; - if (!state->texture[s]) { + + if (!state->texture[s] && !(sampler_mask & (1 << i))) { view[i] = NULL; -#ifdef DEBUG - if (state->vs && state->vs->sampler_mask & (1 << i)) - WARN_ONCE("FIXME: unbound sampler should return alpha=1\n"); -#endif continue; } - sRGB = state->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0; - view[i] = NineBaseTexture9_GetSamplerView(state->texture[s], sRGB); - num_textures = i + 1; + if (state->texture[s]) { + sRGB = state->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0; + + view[i] = NineBaseTexture9_GetSamplerView(state->texture[s], sRGB); + num_textures = i + 1; - if (update_sampler_derived(state, s) || (state->changed.sampler[s] & 0x05fe)) { - state->changed.sampler[s] = 0; + if (update_sampler_derived(state, s) || (state->changed.sampler[s] & 0x05fe)) { + state->changed.sampler[s] = 0; + commit_samplers = TRUE; + nine_convert_sampler_state(device->cso, s, state->samp[s]); + } + } else { + /* Bind dummy sampler. We do not bind dummy sampler when + * it is not needed because it could add overhead. The + * dummy sampler should have r=g=b=0 and a=1. We do not + * unbind dummy sampler directly when they are not needed + * anymore, but they're going to be removed as long as texture + * or sampler states are changed. */ + view[i] = device->dummy_sampler; + num_textures = i + 1; + + memset(&samp, 0, sizeof(samp)); + samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + samp.max_lod = 15.0f; + samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + samp.min_img_filter = PIPE_TEX_FILTER_NEAREST; + samp.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + samp.compare_mode = PIPE_TEX_COMPARE_NONE; + samp.compare_func = PIPE_FUNC_LEQUAL; + samp.normalized_coords = 1; + samp.seamless_cube_map = 1; + + cso_single_sampler(device->cso, PIPE_SHADER_VERTEX, + s - NINE_SAMPLER_VS(0), &samp); + + commit_views = TRUE; commit_samplers = TRUE; - nine_convert_sampler_state(device->cso, s, state->samp[s]); + state->changed.sampler[s] = ~0; } + + state->bound_samplers_mask_vs |= (1 << s); } - if (state->changed.texture & NINE_VS_SAMPLERS_MASK || state->changed.srgb) + commit_views |= (state->changed.texture & NINE_VS_SAMPLERS_MASK) != 0; + commit_views |= state->changed.srgb; + if (commit_views) pipe->set_sampler_views(pipe, PIPE_SHADER_VERTEX, 0, num_textures, view); diff --git a/src/gallium/state_trackers/nine/nine_state.h b/src/gallium/state_trackers/nine/nine_state.h index 0cb293396d6..25ca3dba305 100644 --- a/src/gallium/state_trackers/nine/nine_state.h +++ b/src/gallium/state_trackers/nine/nine_state.h @@ -175,6 +175,8 @@ struct nine_state DWORD samp[NINE_MAX_SAMPLERS][NINED3DSAMP_COUNT]; uint32_t samplers_shadow; + uint8_t bound_samplers_mask_vs; + uint16_t bound_samplers_mask_ps; struct { struct { |