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:
@@ -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);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 |
|
||||
|
||||
Reference in New Issue
Block a user