diff -urNap mesa_orig//src/mesa/drivers/dri/i965/brw_context.c mesa_haihao//src/mesa/drivers/dri/i965/brw_context.c --- mesa_orig//src/mesa/drivers/dri/i965/brw_context.c 2009-01-12 13:29:40.000000000 +0800 +++ mesa_haihao//src/mesa/drivers/dri/i965/brw_context.c 2009-01-13 16:43:37.000000000 +0800 @@ -33,6 +33,7 @@ #include "brw_context.h" #include "brw_defines.h" #include "brw_draw.h" +#include "brw_state.h" #include "brw_vs.h" #include "imports.h" #include "intel_tex.h" diff -urNap mesa_orig//src/mesa/drivers/dri/i965/brw_context.h mesa_haihao//src/mesa/drivers/dri/i965/brw_context.h --- mesa_orig//src/mesa/drivers/dri/i965/brw_context.h 2009-01-12 13:29:36.000000000 +0800 +++ mesa_haihao//src/mesa/drivers/dri/i965/brw_context.h 2009-01-13 16:43:37.000000000 +0800 @@ -431,6 +431,19 @@ struct brw_context GLuint nr_draw_regions; struct intel_region *draw_regions[MAX_DRAW_BUFFERS]; struct intel_region *depth_region; + + /** + * List of buffers accumulated in brw_validate_state to receive + * dri_bo_check_aperture treatment before exec, so we can know if we + * should flush the batch and try again before emitting primitives. + * + * This can be a fixed number as we only have a limited number of + * objects referenced from the batchbuffer in a primitive emit, + * consisting of the vertex buffers, pipelined state pointers, + * the CURBE, the depth buffer, and a query BO. + */ + dri_bo *validated_bos[VERT_ATTRIB_MAX + 16]; + int validated_bo_count; } state; struct brw_state_pointers attribs; @@ -659,14 +672,6 @@ GLboolean brwCreateContext( const __GLco /*====================================================================== - * brw_state.c - */ -void brw_validate_state( struct brw_context *brw ); -void brw_init_state( struct brw_context *brw ); -void brw_destroy_state( struct brw_context *brw ); - - -/*====================================================================== * brw_state_dump.c */ void brw_debug_batch(struct intel_context *intel); diff -urNap mesa_orig//src/mesa/drivers/dri/i965/brw_curbe.c mesa_haihao//src/mesa/drivers/dri/i965/brw_curbe.c --- mesa_orig//src/mesa/drivers/dri/i965/brw_curbe.c 2009-01-12 13:29:40.000000000 +0800 +++ mesa_haihao//src/mesa/drivers/dri/i965/brw_curbe.c 2009-01-13 16:47:46.000000000 +0800 @@ -307,6 +307,7 @@ static void prepare_constant_buffer(stru dri_bo_subdata(brw->curbe.curbe_bo, brw->curbe.curbe_offset, bufsz, buf); } + brw_add_validated_bo(brw, brw->curbe.curbe_bo); /* Because this provokes an action (ie copy the constants into the * URB), it shouldn't be shortcircuited if identical to the @@ -328,13 +329,6 @@ static void emit_constant_buffer(struct { struct intel_context *intel = &brw->intel; GLuint sz = brw->curbe.total_size; - dri_bo *aper_array[] = { - brw->intel.batch->buf, - brw->curbe.curbe_bo, - }; - - if (dri_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array))) - intel_batchbuffer_flush(intel->batch); BEGIN_BATCH(2, IGNORE_CLIPRECTS); if (sz == 0) { diff -urNap mesa_orig//src/mesa/drivers/dri/i965/brw_draw.c mesa_haihao//src/mesa/drivers/dri/i965/brw_draw.c --- mesa_orig//src/mesa/drivers/dri/i965/brw_draw.c 2009-01-12 13:29:37.000000000 +0800 +++ mesa_haihao//src/mesa/drivers/dri/i965/brw_draw.c 2009-01-13 16:43:37.000000000 +0800 @@ -105,6 +105,7 @@ static GLuint brw_set_prim(struct brw_co } brw_validate_state(brw); + brw_upload_state(brw); } return hw_prim[prim]; @@ -256,6 +257,7 @@ static GLboolean brw_try_draw_prims( GLc struct intel_context *intel = intel_context(ctx); struct brw_context *brw = brw_context(ctx); GLboolean retval = GL_FALSE; + GLboolean warn = GL_FALSE; GLuint i; if (ctx->NewState) @@ -304,8 +306,6 @@ static GLboolean brw_try_draw_prims( GLc */ brw_set_prim(brw, prim[0].mode); - /* XXX: Need to separate validate and upload of state. - */ brw_validate_state( brw ); /* Various fallback checks: @@ -316,6 +316,31 @@ static GLboolean brw_try_draw_prims( GLc if (check_fallbacks( brw, prim, nr_prims )) goto out; + /* Check that we can fit our state in with our existing batchbuffer, or + * flush otherwise. + */ + if (dri_bufmgr_check_aperture_space(brw->state.validated_bos, + brw->state.validated_bo_count)) { + static GLboolean warned; + intel_batchbuffer_flush(intel->batch); + + /* Validate the state after we flushed the batch (which would have + * changed the set of dirty state). If we still fail to + * check_aperture, warn of what's happening, but attempt to continue + * on since it may succeed anyway, and the user would probably rather + * see a failure and a warning than a fallback. + */ + brw_validate_state(brw); + if (!warned && + dri_bufmgr_check_aperture_space(brw->state.validated_bos, + brw->state.validated_bo_count)) { + warn = GL_TRUE; + warned = GL_TRUE; + } + } + + brw_upload_state(brw); + for (i = 0; i < nr_prims; i++) { brw_emit_prim(brw, &prim[i]); } @@ -326,6 +351,10 @@ static GLboolean brw_try_draw_prims( GLc out: UNLOCK_HARDWARE(intel); + if (warn) + fprintf(stderr, "i965: Single primitive emit potentially exceeded " + "available aperture space\n"); + if (!retval) DBG("%s failed\n", __FUNCTION__); diff -urNap mesa_orig//src/mesa/drivers/dri/i965/brw_draw_upload.c mesa_haihao//src/mesa/drivers/dri/i965/brw_draw_upload.c --- mesa_orig//src/mesa/drivers/dri/i965/brw_draw_upload.c 2009-01-12 13:29:36.000000000 +0800 +++ mesa_haihao//src/mesa/drivers/dri/i965/brw_draw_upload.c 2009-01-13 16:43:37.000000000 +0800 @@ -250,10 +250,10 @@ static void get_space( struct brw_contex wrap_buffers(brw, size); } + assert(*bo_return == NULL); dri_bo_reference(brw->vb.upload.bo); *bo_return = brw->vb.upload.bo; *offset_return = brw->vb.upload.offset; - brw->vb.upload.offset += size; } @@ -353,12 +353,21 @@ static void brw_prepare_vertices(struct intel_buffer_object(input->glarray->BufferObj); /* Named buffer object: Just reference its contents directly. */ + dri_bo_unreference(input->bo); input->bo = intel_bufferobj_buffer(intel, intel_buffer, INTEL_READ); dri_bo_reference(input->bo); input->offset = (unsigned long)input->glarray->Ptr; input->stride = input->glarray->StrideB; } else { + if (input->bo != NULL) { + /* Already-uploaded vertex data is present from a previous + * prepare_vertices, but we had to re-validate state due to + * check_aperture failing and a new batch being produced. + */ + continue; + } + /* Queue the buffer object up to be uploaded in the next pass, * when we've decided if we're doing interleaved or not. */ @@ -415,6 +424,11 @@ static void brw_prepare_vertices(struct copy_array_to_vbo_array(brw, upload[i], upload[i]->element_size); } } + + for (i = 0; i < nr_enabled; i++) { + struct brw_vertex_element *input = enabled[i]; + brw_add_validated_bo(brw, input->bo); + } } static void brw_emit_vertices(struct brw_context *brw) @@ -509,7 +523,7 @@ static void brw_prepare_indices(struct b struct intel_context *intel = &brw->intel; const struct _mesa_index_buffer *index_buffer = brw->ib.ib; GLuint ib_size; - dri_bo *bo; + dri_bo *bo = NULL; struct gl_buffer_object *bufferobj; GLuint offset; @@ -558,6 +572,8 @@ static void brw_prepare_indices(struct b dri_bo_unreference(brw->ib.bo); brw->ib.bo = bo; brw->ib.offset = offset; + + brw_add_validated_bo(brw, brw->ib.bo); } static void brw_emit_indices(struct brw_context *brw) diff -urNap mesa_orig//src/mesa/drivers/dri/i965/brw_misc_state.c mesa_haihao//src/mesa/drivers/dri/i965/brw_misc_state.c --- mesa_orig//src/mesa/drivers/dri/i965/brw_misc_state.c 2009-01-12 13:29:39.000000000 +0800 +++ mesa_haihao//src/mesa/drivers/dri/i965/brw_misc_state.c 2009-01-13 16:50:17.000000000 +0800 @@ -71,6 +71,11 @@ const struct brw_tracked_state brw_blend .emit = upload_blend_constant_color }; +static void prepare_binding_table_pointers(struct brw_context *brw) +{ + brw_add_validated_bo(brw, brw->wm.bind_bo); +} + /** * Upload the binding table pointers, which point each stage's array of surface * state pointers. @@ -81,13 +86,6 @@ const struct brw_tracked_state brw_blend static void upload_binding_table_pointers(struct brw_context *brw) { struct intel_context *intel = &brw->intel; - dri_bo *aper_array[] = { - intel->batch->buf, - brw->wm.bind_bo, - }; - - if (dri_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array))) - intel_batchbuffer_flush(intel->batch); BEGIN_BATCH(6, IGNORE_CLIPRECTS); OUT_BATCH(CMD_BINDING_TABLE_PTRS << 16 | (6 - 2)); @@ -107,6 +105,7 @@ const struct brw_tracked_state brw_bindi .brw = BRW_NEW_BATCH, .cache = CACHE_NEW_SURF_BIND, }, + .prepare = prepare_binding_table_pointers, .emit = upload_binding_table_pointers, }; @@ -140,21 +139,18 @@ static void upload_pipelined_state_point brw->state.dirty.brw |= BRW_NEW_PSP; } + +static void prepare_psp_urb_cbs(struct brw_context *brw) +{ + brw_add_validated_bo(brw, brw->vs.state_bo); + brw_add_validated_bo(brw, brw->gs.state_bo); + brw_add_validated_bo(brw, brw->clip.state_bo); + brw_add_validated_bo(brw, brw->wm.state_bo); + brw_add_validated_bo(brw, brw->cc.state_bo); +} + static void upload_psp_urb_cbs(struct brw_context *brw ) { - struct intel_context *intel = &brw->intel; - dri_bo *aper_array[] = { - intel->batch->buf, - brw->vs.state_bo, - brw->gs.state_bo, - brw->clip.state_bo, - brw->wm.state_bo, - brw->cc.state_bo, - }; - - if (dri_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array))) - intel_batchbuffer_flush(intel->batch); - upload_pipelined_state_pointers(brw); brw_upload_urb_fence(brw); brw_upload_constant_buffer_state(brw); @@ -172,9 +168,18 @@ const struct brw_tracked_state brw_psp_u CACHE_NEW_WM_UNIT | CACHE_NEW_CC_UNIT) }, + .prepare = prepare_psp_urb_cbs, .emit = upload_psp_urb_cbs, }; +static void prepare_depthbuffer(struct brw_context *brw) +{ + struct intel_region *region = brw->state.depth_region; + + if (region != NULL) + brw_add_validated_bo(brw, region->buffer); +} + static void emit_depthbuffer(struct brw_context *brw) { struct intel_context *intel = &brw->intel; @@ -196,10 +201,6 @@ static void emit_depthbuffer(struct brw_ ADVANCE_BATCH(); } else { unsigned int format; - dri_bo *aper_array[] = { - intel->batch->buf, - region->buffer - }; switch (region->cpp) { case 2: @@ -216,9 +217,6 @@ static void emit_depthbuffer(struct brw_ return; } - if (dri_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array))) - intel_batchbuffer_flush(intel->batch); - BEGIN_BATCH(len, IGNORE_CLIPRECTS); OUT_BATCH(CMD_DEPTH_BUFFER << 16 | (len - 2)); OUT_BATCH(((region->pitch * region->cpp) - 1) | @@ -247,6 +245,7 @@ const struct brw_tracked_state brw_depth .brw = BRW_NEW_DEPTH_BUFFER | BRW_NEW_BATCH, .cache = 0, }, + .prepare = prepare_depthbuffer, .emit = emit_depthbuffer, }; diff -urNap mesa_orig//src/mesa/drivers/dri/i965/brw_state.h mesa_haihao//src/mesa/drivers/dri/i965/brw_state.h --- mesa_orig//src/mesa/drivers/dri/i965/brw_state.h 2009-01-12 13:29:39.000000000 +0800 +++ mesa_haihao//src/mesa/drivers/dri/i965/brw_state.h 2009-01-13 16:43:37.000000000 +0800 @@ -35,6 +35,16 @@ #include "brw_context.h" +static inline void +brw_add_validated_bo(struct brw_context *brw, dri_bo *bo) +{ + assert(brw->state.validated_bo_count < ARRAY_SIZE(brw->state.validated_bos)); + + if (bo != NULL) { + dri_bo_reference(bo); + brw->state.validated_bos[brw->state.validated_bo_count++] = bo; + } +}; const struct brw_tracked_state brw_blend_constant_color; const struct brw_tracked_state brw_cc_unit; @@ -84,6 +94,14 @@ const struct brw_tracked_state brw_indic const struct brw_tracked_state brw_vertices; /*********************************************************************** + * brw_state.c + */ +void brw_validate_state(struct brw_context *brw); +void brw_upload_state(struct brw_context *brw); +void brw_init_state(struct brw_context *brw); +void brw_destroy_state(struct brw_context *brw); + +/*********************************************************************** * brw_state_cache.c */ dri_bo *brw_cache_data(struct brw_cache *cache, diff -urNap mesa_orig//src/mesa/drivers/dri/i965/brw_state_upload.c mesa_haihao//src/mesa/drivers/dri/i965/brw_state_upload.c --- mesa_orig//src/mesa/drivers/dri/i965/brw_state_upload.c 2009-01-12 13:29:39.000000000 +0800 +++ mesa_haihao//src/mesa/drivers/dri/i965/brw_state_upload.c 2009-01-13 16:43:37.000000000 +0800 @@ -169,6 +169,18 @@ static void xor_states( struct brw_state result->cache = a->cache ^ b->cache; } +static void +brw_clear_validated_bos(struct brw_context *brw) +{ + int i; + + /* Clear the last round of validated bos */ + for (i = 0; i < brw->state.validated_bo_count; i++) { + dri_bo_unreference(brw->state.validated_bos[i]); + brw->state.validated_bos[i] = NULL; + } + brw->state.validated_bo_count = 0; +} /*********************************************************************** * Emit all state: @@ -177,12 +189,15 @@ void brw_validate_state( struct brw_cont { struct intel_context *intel = &brw->intel; struct brw_state_flags *state = &brw->state.dirty; - GLuint i, count, pass = 0; - dri_bo *last_batch_bo = NULL; + GLuint i; + + brw_clear_validated_bos(brw); state->mesa |= brw->intel.NewGLState; brw->intel.NewGLState = 0; + brw_add_validated_bo(brw, intel->batch->buf); + if (brw->wrap) state->brw |= BRW_NEW_CONTEXT; @@ -211,8 +226,6 @@ void brw_validate_state( struct brw_cont brw->intel.Fallback = 0; - count = 0; - /* do prepare stage for all atoms */ for (i = 0; i < Elements(atoms); i++) { const struct brw_tracked_state *atom = brw->state.atoms[i]; @@ -226,19 +239,15 @@ void brw_validate_state( struct brw_cont } } } +} - if (brw->intel.Fallback) - return; - /* We're about to try to set up a coherent state in the batchbuffer for - * the emission of primitives. If we exceed the aperture size in any of the - * emit() calls, we need to go back to square 1 and try setting up again. - */ -got_flushed: - dri_bo_unreference(last_batch_bo); - last_batch_bo = intel->batch->buf; - dri_bo_reference(last_batch_bo); - assert(pass++ <= 2); +void brw_upload_state(struct brw_context *brw) +{ + struct brw_state_flags *state = &brw->state.dirty; + int i; + + brw_clear_validated_bos(brw); if (INTEL_DEBUG) { /* Debug version which enforces various sanity checks on the @@ -263,8 +272,6 @@ got_flushed: if (check_state(state, &atom->dirty)) { if (atom->emit) { atom->emit( brw ); - if (intel->batch->buf != last_batch_bo) - goto got_flushed; } } @@ -289,15 +296,11 @@ got_flushed: if (check_state(state, &atom->dirty)) { if (atom->emit) { atom->emit( brw ); - if (intel->batch->buf != last_batch_bo) - goto got_flushed; } } } } - dri_bo_unreference(last_batch_bo); - if (!brw->intel.Fallback) memset(state, 0, sizeof(*state)); }