Commit a8627ac1 authored by Keith Whitwell's avatar Keith Whitwell
Browse files

Add a state-checking stage to the render pipeline for attribute size changes.

Use this to correctly set the vertex format for texture coordinates.
parent 527be7b2
......@@ -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]);
......
......@@ -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];
......
......@@ -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);
......
......@@ -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));
......
......@@ -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;
}
......@@ -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;
}
......@@ -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);
......
......@@ -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;
......
......@@ -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,
};
......
......@@ -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;
......
......@@ -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() */
{
......
......@@ -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
};
......@@ -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))
......
......@@ -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
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment