svga: Ensure rendertargets and textures are always rebound at every command buffer start.

The svga_update_state() mechanism is inadequate as it will always end up
flushing the primitives before processing the SVGA_NEW_COMMAND_BUFFER
dirty state flag.
This commit is contained in:
José Fonseca
2011-02-23 13:32:37 +00:00
parent f19439940c
commit 369ece1702
4 changed files with 138 additions and 9 deletions
+16
View File
@@ -204,6 +204,7 @@ void svga_context_flush( struct svga_context *svga,
{
struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
struct pipe_fence_handle *fence = NULL;
enum pipe_error ret;
svga->curr.nr_fbs = 0;
@@ -223,6 +224,21 @@ void svga_context_flush( struct svga_context *svga,
*/
svga->dirty |= SVGA_NEW_COMMAND_BUFFER;
/*
* We must reemit the surface bindings here, because svga_update_state
* will always flush the primitives before processing the
* SVGA_NEW_COMMAND_BUFFER state change.
*
* TODO: Refactor this.
*/
ret = svga_reemit_framebuffer_bindings(svga);
assert(ret == PIPE_OK);
ret = svga_reemit_tss_bindings(svga);
assert(ret == PIPE_OK);
svga->dirty &= ~SVGA_NEW_COMMAND_BUFFER;
if (SVGA_DEBUG & DEBUG_SYNC) {
if (fence)
svga->pipe.screen->fence_finish( svga->pipe.screen, fence, 0);
+4
View File
@@ -92,4 +92,8 @@ void svga_update_state_retry( struct svga_context *svga,
enum pipe_error svga_emit_initial_state( struct svga_context *svga );
enum pipe_error svga_reemit_framebuffer_bindings( struct svga_context *svga );
enum pipe_error svga_reemit_tss_bindings( struct svga_context *svga );
#endif
@@ -93,6 +93,55 @@ static int emit_framebuffer( struct svga_context *svga,
}
/*
* Rebind rendertargets.
*
* Similar to emit_framebuffer, but without any state checking/update.
*
* Called at the beginning of every new command buffer to ensure that
* non-dirty rendertargets are properly paged-in.
*/
enum pipe_error
svga_reemit_framebuffer_bindings(struct svga_context *svga)
{
struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
unsigned i;
enum pipe_error ret;
for (i = 0; i < MIN2(PIPE_MAX_COLOR_BUFS, 8); ++i) {
if (hw->cbufs[i]) {
ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_COLOR0 + i, hw->cbufs[i]);
if (ret != PIPE_OK) {
return ret;
}
}
}
if (hw->zsbuf) {
ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_DEPTH, hw->zsbuf);
if (ret != PIPE_OK) {
return ret;
}
if (hw->zsbuf &&
hw->zsbuf->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM) {
ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, hw->zsbuf);
if (ret != PIPE_OK) {
return ret;
}
}
else {
ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, NULL);
if (ret != PIPE_OK) {
return ret;
}
}
}
return PIPE_OK;
}
struct svga_tracked_state svga_hw_framebuffer =
{
"hw framebuffer state",
+69 -9
View File
@@ -52,6 +52,16 @@ void svga_cleanup_tss_binding(struct svga_context *svga)
}
struct bind_queue {
struct {
unsigned unit;
struct svga_hw_view_state *view;
} bind[PIPE_MAX_SAMPLERS];
unsigned bind_count;
};
static int
update_tss_binding(struct svga_context *svga,
unsigned dirty )
@@ -63,15 +73,7 @@ update_tss_binding(struct svga_context *svga,
unsigned min_lod;
unsigned max_lod;
struct {
struct {
unsigned unit;
struct svga_hw_view_state *view;
} bind[PIPE_MAX_SAMPLERS];
unsigned bind_count;
} queue;
struct bind_queue queue;
queue.bind_count = 0;
@@ -164,6 +166,64 @@ fail:
}
/*
* Rebind textures.
*
* Similar to update_tss_binding, but without any state checking/update.
*
* Called at the beginning of every new command buffer to ensure that
* non-dirty textures are properly paged-in.
*/
enum pipe_error
svga_reemit_tss_bindings(struct svga_context *svga)
{
unsigned i;
enum pipe_error ret;
struct bind_queue queue;
queue.bind_count = 0;
for (i = 0; i < svga->state.hw_draw.num_views; i++) {
struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
if (view->v) {
queue.bind[queue.bind_count].unit = i;
queue.bind[queue.bind_count].view = view;
queue.bind_count++;
}
}
if (queue.bind_count) {
SVGA3dTextureState *ts;
ret = SVGA3D_BeginSetTextureState(svga->swc,
&ts,
queue.bind_count);
if (ret != PIPE_OK) {
return ret;
}
for (i = 0; i < queue.bind_count; i++) {
struct svga_winsys_surface *handle;
ts[i].stage = queue.bind[i].unit;
ts[i].name = SVGA3D_TS_BIND_TEXTURE;
assert(queue.bind[i].view->v);
handle = queue.bind[i].view->v->handle;
svga->swc->surface_relocation(svga->swc,
&ts[i].value,
handle,
SVGA_RELOC_READ);
}
SVGA_FIFOCommitAll(svga->swc);
}
return PIPE_OK;
}
struct svga_tracked_state svga_hw_tss_binding = {
"texture binding emit",
SVGA_NEW_TEXTURE_BINDING |