From a8627ac19268df367c55d8f79f6e530af63e0e62 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Tue, 20 Mar 2007 17:52:28 +0000 Subject: Add a state-checking stage to the render pipeline for attribute size changes. Use this to correctly set the vertex format for texture coordinates. --- src/mesa/drivers/dri/i915tex/i915_cache.c | 2 +- src/mesa/drivers/dri/i915tex/i915_cache.h | 3 + src/mesa/drivers/dri/i915tex/i915_differencer.c | 4 +- src/mesa/drivers/dri/i915tex/i915_state_vertex.c | 71 ++++++++++------------ src/mesa/drivers/dri/i915tex/i915_vtbl.c | 14 +++++ src/mesa/drivers/dri/i915tex/intel_batchbuffer.c | 1 + src/mesa/drivers/dri/i915tex/intel_blit.c | 1 - src/mesa/drivers/dri/i915tex/intel_buffers.c | 10 +-- src/mesa/drivers/dri/i915tex/intel_context.c | 12 ++-- src/mesa/drivers/dri/i915tex/intel_context.h | 9 ++- src/mesa/drivers/dri/i915tex/intel_idx_render.c | 11 ++-- src/mesa/drivers/dri/i915tex/intel_render.c | 77 ++++++++++++++++++++++++ src/mesa/drivers/dri/i915tex/intel_state.c | 11 +++- src/mesa/drivers/dri/i915tex/intel_tris.c | 12 +--- 14 files changed, 162 insertions(+), 76 deletions(-) diff --git a/src/mesa/drivers/dri/i915tex/i915_cache.c b/src/mesa/drivers/dri/i915tex/i915_cache.c index 2a97e1ca52..330fbf89b8 100644 --- a/src/mesa/drivers/dri/i915tex/i915_cache.c +++ b/src/mesa/drivers/dri/i915tex/i915_cache.c @@ -73,7 +73,7 @@ static GLuint emit_packet( struct intel_context *intel, GLuint offset = intel->batch->segment_finish_offset[segment]; GLuint i; - /* XXX: + /* This should not be possible: */ assert(intel->batch->segment_finish_offset[segment] + size < intel->batch->segment_max_offset[segment]); diff --git a/src/mesa/drivers/dri/i915tex/i915_cache.h b/src/mesa/drivers/dri/i915tex/i915_cache.h index 41ee2a162d..471f7ecfc4 100644 --- a/src/mesa/drivers/dri/i915tex/i915_cache.h +++ b/src/mesa/drivers/dri/i915tex/i915_cache.h @@ -90,6 +90,9 @@ static inline void packet_init( struct i915_cache_packet *packet, GLuint nr_dwords, GLuint nr_relocs ) { + assert(nr_dwords < PACKET_MAX_DWORDS); + assert(nr_relocs < PACKET_MAX_RELOCS); + packet->nr_dwords = 0; packet->nr_relocs = 0; packet->reloc = (struct i915_cache_reloc *)&packet->dword[nr_dwords]; diff --git a/src/mesa/drivers/dri/i915tex/i915_differencer.c b/src/mesa/drivers/dri/i915tex/i915_differencer.c index 5518d4ad87..d9e1d381ad 100644 --- a/src/mesa/drivers/dri/i915tex/i915_differencer.c +++ b/src/mesa/drivers/dri/i915tex/i915_differencer.c @@ -173,9 +173,9 @@ static void emit_dynamic_indirect( struct intel_context *intel, ((offset + size*4 - 4) | DIS0_BUFFER_VALID | flag) ); ADVANCE_BATCH(); - /* XXX: + /* This should not be possible: */ - assert( offset + size*4 < intel->batch->segment_max_offset[segment]); + assert( offset + size*4 < intel->batch->segment_max_offset[segment]); intel->batch->segment_finish_offset[segment] += size*4; ptr = (GLuint *)(intel->batch->map + offset); diff --git a/src/mesa/drivers/dri/i915tex/i915_state_vertex.c b/src/mesa/drivers/dri/i915tex/i915_state_vertex.c index 631352db16..d4a268fcf2 100644 --- a/src/mesa/drivers/dri/i915tex/i915_state_vertex.c +++ b/src/mesa/drivers/dri/i915tex/i915_state_vertex.c @@ -37,37 +37,6 @@ #include "tnl/t_vertex.h" -#if 0 -/* Scan the TNL VB struct and look at the size of each attribute - * coming out. - * - * The fragment program has been determined by this point, so it is ok - * to restrict the list to the inputs referenced by the fragprog. - * - * This is not a - */ -void check_input_sizes( struct intel_context *intel ) -{ - struct i915_context *i915 = i915_context( &intel->ctx ); - GLcontext *ctx = &intel->ctx; - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - GLubyte old_sizes[8]; - GLuint i; - - memcpy(old_sizes, i915->fragprog.input_sizes, sizeof(old_sizes)); - - for (i = 0; i < FRAG_ATTRIB_MAX; i++) { - GLvector4f *attrib = VB->AttribPtr[i]; - i915->fragprog.input_sizes[i] = attrib->size; - } - - /* Raise statechanges if input sizes and varying have changed: - */ - if (memcmp(i915->fragprog.input_sizes, old_sizes, sizeof(old_sizes)) != 0) - intel->state.dirty.intel |= I915_NEW_INPUT_SIZES; -} - -#endif /*********************************************************************** @@ -97,7 +66,10 @@ do { \ /*********************************************************************** * */ - +static inline GLuint attr_size(GLuint sizes, GLuint attr) +{ + return ((sizes >> (attr*2)) & 0x3) + 1; +} static void i915_calculate_vertex_format( struct intel_context *intel ) { @@ -105,10 +77,14 @@ static void i915_calculate_vertex_format( struct intel_context *intel ) struct i915_fragment_program *fp = i915_fragment_program(intel->state.FragmentProgram->_Current); const GLuint inputsRead = fp->Base.Base.InputsRead; + const GLuint sizes = intel->frag_attrib_sizes; GLuint s2 = S2_TEXCOORD_NONE; GLuint s4 = 0; GLuint offset = 0; GLuint i; + GLboolean need_w = (inputsRead & FRAG_BITS_TEX_ANY); + GLboolean have_w = (attr_size(sizes, FRAG_ATTRIB_WPOS) == 4); + GLboolean have_z = (attr_size(sizes, FRAG_ATTRIB_WPOS) >= 3); intel->vertex_attr_count = 0; intel->wpos_offset = 0; @@ -116,12 +92,21 @@ static void i915_calculate_vertex_format( struct intel_context *intel ) intel->coloroffset = 0; intel->specoffset = 0; - if (inputsRead & FRAG_BITS_TEX_ANY) { + + if (have_w && need_w) { EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16); } - else { + else if (1 || have_z) { EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, S4_VFMT_XYZ, 12); } + else { + /* Need to update default z values to whatever zero maps to in + * the current viewport. Or figure out that we don't need z in + * the current state. + */ + EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_2F_VIEWPORT, S4_VFMT_XY, 8); + } + if (inputsRead & FRAG_BIT_COL0) { intel->coloroffset = offset / 4; @@ -135,18 +120,26 @@ static void i915_calculate_vertex_format( struct intel_context *intel ) } if (inputsRead & FRAG_BIT_FOGC) { - EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1F, S4_VFMT_FOG_PARAM, 4); } for (i = 0; i < I915_TEX_UNITS; i++) { if (inputsRead & (FRAG_BIT_TEX0 << i)) { - /* _NEW_VB_OUTPUT_SIZES + /* INTEL_NEW_FRAG_ATTRIB_SIZES + * + * Basically need to know whether or not to include the W + * value. This could be used to transform TXP->TEX + * instructions in the fragment program, but so far haven't + * seen much performance benefit from doing that. + * + * There could also be benefit in things like turning off + * perspective interpolation for the texture coordinates when + * it is detected that the application is really doing + * 2d-type texture operations. */ -/* int sz = VB->TexCoordPtr[i]->size; */ - int sz = 2; - + int sz = attr_size(sizes, FRAG_ATTRIB_TEX0+i); + s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK); s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(sz)); diff --git a/src/mesa/drivers/dri/i915tex/i915_vtbl.c b/src/mesa/drivers/dri/i915tex/i915_vtbl.c index 5e215b0dc3..e3eacaee48 100644 --- a/src/mesa/drivers/dri/i915tex/i915_vtbl.c +++ b/src/mesa/drivers/dri/i915tex/i915_vtbl.c @@ -236,6 +236,19 @@ static void i915_lost_hardware( struct intel_context *intel ) } +static GLboolean i915_check_indirect_space( struct intel_context *intel ) +{ + GLuint dynamic_space = + intel_batchbuffer_space( intel->batch, + SEGMENT_DYNAMIC_INDIRECT); + GLuint cache_space = + intel_batchbuffer_space( intel->batch, + SEGMENT_OTHER_INDIRECT); + + return (dynamic_space > I915_MAX_DYNAMIC * sizeof(GLuint) && + cache_space > I915_MAX_CACHE * PACKET_MAX_DWORDS * sizeof(GLuint)); +} + void i915InitVtbl(struct i915_context *i915) { @@ -245,4 +258,5 @@ i915InitVtbl(struct i915_context *i915) i915->intel.vtbl.debug_packet = i915_debug_packet; i915->intel.vtbl.get_hardware_state_size = i915_get_hardware_state_size; i915->intel.vtbl.emit_hardware_state = i915_emit_hardware_state; + i915->intel.vtbl.check_indirect_space = i915_check_indirect_space; } diff --git a/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c b/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c index dcc688e682..361b220913 100644 --- a/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c +++ b/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c @@ -438,3 +438,4 @@ intel_batchbuffer_data(struct intel_batchbuffer *batch, __memcpy(batch->map + batch->segment_finish_offset[segment], data, bytes); batch->segment_finish_offset[segment] += bytes; } + diff --git a/src/mesa/drivers/dri/i915tex/intel_blit.c b/src/mesa/drivers/dri/i915tex/intel_blit.c index 550669ab0c..bbd8274160 100644 --- a/src/mesa/drivers/dri/i915tex/intel_blit.c +++ b/src/mesa/drivers/dri/i915tex/intel_blit.c @@ -430,7 +430,6 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask) skipBuffers = BUFFER_BIT_STENCIL; } - /* XXX Move this flush/lock into the following conditional? */ intelFlush(&intel->ctx); LOCK_HARDWARE(intel); diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.c b/src/mesa/drivers/dri/i915tex/intel_buffers.c index a3f52f6752..f5906e0f05 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.c +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.c @@ -313,9 +313,6 @@ intelClearWithTris(struct intel_context *intel, GLbitfield mask) else intel_meta_no_depth_write(intel); - /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the - * drawing origin may not be correctly emitted. - */ intel_meta_draw_quad(intel, clear.x1, clear.x2, clear.y1, clear.y2, @@ -343,10 +340,9 @@ intelClearWithTris(struct intel_context *intel, GLbitfield mask) intel_meta_color_mask(intel, GL_TRUE); intel_meta_draw_region(intel, irbColor->region, NULL); - /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the - * drawing origin may not be correctly emitted. - */ - intel_meta_draw_quad(intel, clear.x1, clear.x2, clear.y1, clear.y2, 0, /* depth clear val */ + intel_meta_draw_quad(intel, + clear.x1, clear.x2, + clear.y1, clear.y2, 0, /* depth clear val */ color, 0, 0, 0, 0); /* texcoords */ mask &= ~bufBit; diff --git a/src/mesa/drivers/dri/i915tex/intel_context.c b/src/mesa/drivers/dri/i915tex/intel_context.c index a7fd4f89ff..259863f4a5 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.c +++ b/src/mesa/drivers/dri/i915tex/intel_context.c @@ -201,6 +201,7 @@ const struct dri_extension card_extensions[] = { }; extern const struct tnl_pipeline_stage _intel_render_stage; +extern const struct tnl_pipeline_stage _intel_check_frag_attrib_sizes; static const struct tnl_pipeline_stage *intel_pipeline[] = { &_tnl_vertex_transform_stage, @@ -212,13 +213,10 @@ static const struct tnl_pipeline_stage *intel_pipeline[] = { &_tnl_texture_transform_stage, &_tnl_point_attenuation_stage, &_tnl_arb_vertex_program_stage, - &_tnl_vertex_program_stage, -#if 1 - &_intel_render_stage, /* ADD: unclipped rastersetup-to-dma */ -#endif -#if 1 - &_tnl_indexed_render_stage, /* ADD: rastersetup-to-dma, indexed prims */ -#endif + &_tnl_vertex_program_stage, + &_intel_check_frag_attrib_sizes, + &_intel_render_stage, /* ADD: unclipped rastersetup-to-dma */ + &_tnl_indexed_render_stage, /* ADD: rastersetup-to-dma, indexed prims */ &_tnl_render_stage, 0, }; diff --git a/src/mesa/drivers/dri/i915tex/intel_context.h b/src/mesa/drivers/dri/i915tex/intel_context.h index 24a154dd55..685d4f1c0d 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.h +++ b/src/mesa/drivers/dri/i915tex/intel_context.h @@ -84,7 +84,7 @@ extern void intelFallback(struct intel_context *intel, GLuint bit, #define INTEL_NEW_MESA 0x1 /* Mesa state has changed */ #define INTEL_NEW_FRAGMENT_PROGRAM 0x2 #define INTEL_NEW_VERTEX_SIZE 0x4 -#define INTEL_NEW_INPUT_SIZES 0x8 +#define INTEL_NEW_FRAG_ATTRIB_SIZES 0x8 #define INTEL_NEW_CONTEXT 0x10 /* Lost hardware? */ #define INTEL_NEW_REDUCED_PRIMITIVE 0x20 #define INTEL_NEW_FALLBACK 0x40 @@ -189,6 +189,8 @@ struct intel_context void (*emit_hardware_state) (struct intel_context *intel); + GLboolean (*check_indirect_space) (struct intel_context *intel); + } vtbl; @@ -248,6 +250,11 @@ struct intel_context */ GLuint program_id; + /* Track TNL attrib sizes: + */ + GLuint frag_attrib_sizes; + GLuint frag_attrib_varying; + /* State for intelvb.c and inteltris.c. */ GLuint coloroffset; diff --git a/src/mesa/drivers/dri/i915tex/intel_idx_render.c b/src/mesa/drivers/dri/i915tex/intel_idx_render.c index c0e78c02f2..09b0a437fa 100644 --- a/src/mesa/drivers/dri/i915tex/intel_idx_render.c +++ b/src/mesa/drivers/dri/i915tex/intel_idx_render.c @@ -179,12 +179,11 @@ static void emit_prims( GLcontext *ctx, if (nr == 0) continue; - /* XXX: Need to ensure that both the state and the primitive - * command below end up in the same batchbuffer, otherwise there - * is a risk that another context might interpose a batchbuffer - * containing different statesetting commands. Using logical - * contexts would fix this, as would the BRW scheme of only - * emitting batch commands while holding the lock. + /* The 'dwords' usage below ensures that both the state and the + * primitive command below end up in the same batchbuffer, + * otherwise there is a risk that another context might + * interpose a batchbuffer containing different statesetting + * commands. */ /* intelRenderPrimitive() */ { diff --git a/src/mesa/drivers/dri/i915tex/intel_render.c b/src/mesa/drivers/dri/i915tex/intel_render.c index daee49a2e2..f699feeba0 100644 --- a/src/mesa/drivers/dri/i915tex/intel_render.c +++ b/src/mesa/drivers/dri/i915tex/intel_render.c @@ -45,6 +45,7 @@ #include "intel_tris.h" #include "intel_batchbuffer.h" #include "intel_reg.h" +#include "intel_state.h" /* * Render unclipped vertex buffers by emitting vertices directly to @@ -239,3 +240,79 @@ const struct tnl_pipeline_stage _intel_render_stage = { NULL, intel_run_render /* run */ }; + +static GLuint frag_attr_to_VB( GLuint attr ) +{ + switch(attr) { + case FRAG_ATTRIB_WPOS: return VERT_ATTRIB_POS; + case FRAG_ATTRIB_COL0: return VERT_ATTRIB_COLOR0; + case FRAG_ATTRIB_COL1: return VERT_ATTRIB_COLOR1; + case FRAG_ATTRIB_FOGC: return VERT_ATTRIB_FOG; + case FRAG_ATTRIB_TEX0: return VERT_ATTRIB_TEX0; + case FRAG_ATTRIB_TEX1: return VERT_ATTRIB_TEX1; + case FRAG_ATTRIB_TEX2: return VERT_ATTRIB_TEX2; + case FRAG_ATTRIB_TEX3: return VERT_ATTRIB_TEX3; + case FRAG_ATTRIB_TEX4: return VERT_ATTRIB_TEX4; + case FRAG_ATTRIB_TEX5: return VERT_ATTRIB_TEX5; + case FRAG_ATTRIB_TEX6: return VERT_ATTRIB_TEX6; + case FRAG_ATTRIB_TEX7: return VERT_ATTRIB_TEX7; + default: return 0; + } +} + + +/* A mini stage just to update our state regarding the pipeline: + */ +static GLboolean frag_attrib_size_check( GLcontext * ctx, + struct tnl_pipeline_stage *stage ) +{ + struct intel_context *intel = intel_context(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint i; + + + /* Look at the size of each attribute coming out, and raise a + * statechange if different. + */ + GLuint sizes = 0; + GLuint varying = 0; + + /* We need to do this first: + */ + VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; + + for (i = 0; i < FRAG_ATTRIB_MAX; i++) { + GLvector4f *attrib = VB->AttribPtr[frag_attr_to_VB(i)]; + sizes |= (attrib->size - 1) << (i * 2); + varying |= (attrib->stride != 0) << i; + } + + /* Raise statechanges if input sizes and varying have changed: + */ + if (intel->frag_attrib_sizes != sizes || + intel->frag_attrib_varying != varying) + { + intel->state.dirty.intel |= INTEL_NEW_FRAG_ATTRIB_SIZES; + intel->frag_attrib_varying = varying; + intel->frag_attrib_sizes = sizes; + + _mesa_printf("sizes: %x varying: %x\n", sizes, varying); + } + + + /* Catch any changes from the pipeline... + */ + intel_update_software_state(intel); + + return GL_TRUE; +} + +const struct tnl_pipeline_stage _intel_check_frag_attrib_sizes = { + "intel check frag attrib sizes", + NULL, + NULL, + NULL, + NULL, + frag_attrib_size_check +}; diff --git a/src/mesa/drivers/dri/i915tex/intel_state.c b/src/mesa/drivers/dri/i915tex/intel_state.c index f52b79e656..40be0d3291 100644 --- a/src/mesa/drivers/dri/i915tex/intel_state.c +++ b/src/mesa/drivers/dri/i915tex/intel_state.c @@ -68,8 +68,11 @@ void intel_update_software_state( struct intel_context *intel ) struct intel_state_flags *state = &intel->state.dirty; GLuint i; - if (state->intel == 0) + if (state->intel == 0) { + assert(state->mesa == 0); + assert(state->extra == 0); return; + } if (!intel->metaops.active) { intel->state.DrawBuffer = intel->ctx.DrawBuffer; @@ -78,6 +81,9 @@ void intel_update_software_state( struct intel_context *intel ) intel->state._ColorDrawBufferMask0 = intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]; } + if (!intel->vtbl.check_indirect_space( intel )) + intel_batchbuffer_flush( intel->batch ); + if (INTEL_DEBUG) { /* Debug version which enforces various sanity checks on the * state flags which are generated and checked to help ensure @@ -131,8 +137,7 @@ void intel_emit_hardware_state( struct intel_context *intel, for (i = 0; i < 2; i++) { - if (intel->state.dirty.intel) - intel_update_software_state( intel ); + intel_update_software_state( intel ); if (intel_batchbuffer_space( intel->batch, SEGMENT_IMMEDIATE ) < intel->vtbl.get_hardware_state_size( intel ) + dwords * sizeof(GLuint)) diff --git a/src/mesa/drivers/dri/i915tex/intel_tris.c b/src/mesa/drivers/dri/i915tex/intel_tris.c index ec53ebd910..6e61fc6ff8 100644 --- a/src/mesa/drivers/dri/i915tex/intel_tris.c +++ b/src/mesa/drivers/dri/i915tex/intel_tris.c @@ -888,8 +888,10 @@ intelRunPipeline(GLcontext * ctx) if (ctx->NewState) _mesa_update_state_locked(ctx); - /* Want to update state but not emit: */ +#if 0 + /* Maybe need this for fallbacks??? */ intel_update_software_state( intel ); +#endif _tnl_run_pipeline(ctx); @@ -899,14 +901,6 @@ intelRunPipeline(GLcontext * ctx) static void intelRenderStart(GLcontext * ctx) { - struct intel_context *intel = intel_context(ctx); - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - - VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; - - assert(!intel->state.dirty.intel); - intel_update_software_state(intel); } static void -- cgit v1.2.3