X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi965%2Fgen6_sf_state.c;h=6a9fa602c6a3d0d59fcba9c98434b7e9968e2faf;hb=a4546ec114853235db375b20fb47ddcd6a7f21e7;hp=4482e9cc09fd9ae5e0b640f5cd3619651fdb9ee7;hpb=d158f6e73b0b7306f7bee246d2349c490041e449;p=mesa.git diff --git a/src/mesa/drivers/dri/i965/gen6_sf_state.c b/src/mesa/drivers/dri/i965/gen6_sf_state.c index 4482e9cc09f..6a9fa602c6a 100644 --- a/src/mesa/drivers/dri/i965/gen6_sf_state.c +++ b/src/mesa/drivers/dri/i965/gen6_sf_state.c @@ -30,6 +30,7 @@ #include "brw_defines.h" #include "brw_util.h" #include "main/macros.h" +#include "main/fbobject.h" #include "intel_batchbuffer.h" /** @@ -51,34 +52,35 @@ * the VUE that are not needed by the fragment shader. It is measured in * 256-bit increments. */ -uint32_t -get_attr_override(struct brw_vue_map *vue_map, int urb_entry_read_offset, - int fs_attr, bool two_side_color) +static uint32_t +get_attr_override(const struct brw_vue_map *vue_map, int urb_entry_read_offset, + int fs_attr, bool two_side_color, uint32_t *max_source_attr) { - int attr_override, slot; - int vs_attr = _mesa_frag_attrib_to_vert_result(fs_attr); - if (vs_attr < 0 || vs_attr == VERT_RESULT_HPOS) { - /* These attributes will be overwritten by the fragment shader's - * interpolation code (see emit_interp() in brw_wm_fp.c), so just let - * them reference the first available attribute. - */ - return 0; - } - /* Find the VUE slot for this attribute. */ - slot = vue_map->vert_result_to_slot[vs_attr]; + int slot = vue_map->varying_to_slot[fs_attr]; /* If there was only a back color written but not front, use back * as the color instead of undefined */ - if (slot == -1 && vs_attr == VERT_RESULT_COL0) - slot = vue_map->vert_result_to_slot[VERT_RESULT_BFC0]; - if (slot == -1 && vs_attr == VERT_RESULT_COL1) - slot = vue_map->vert_result_to_slot[VERT_RESULT_BFC1]; + if (slot == -1 && fs_attr == VARYING_SLOT_COL0) + slot = vue_map->varying_to_slot[VARYING_SLOT_BFC0]; + if (slot == -1 && fs_attr == VARYING_SLOT_COL1) + slot = vue_map->varying_to_slot[VARYING_SLOT_BFC1]; if (slot == -1) { /* This attribute does not exist in the VUE--that means that the vertex - * shader did not write to it. Behavior is undefined in this case, so + * shader did not write to it. This means that either: + * + * (a) This attribute is a texture coordinate, and it is going to be + * replaced with point coordinates (as a consequence of a call to + * glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE)), so the + * hardware will ignore whatever attribute override we supply. + * + * (b) This attribute is read by the fragment shader but not written by + * the vertex shader, so its value is undefined. Therefore the + * attribute override we supply doesn't matter. + * + * In either case the attribute override we supply doesn't matter, so * just reference the first available attribute. */ return 0; @@ -88,69 +90,139 @@ get_attr_override(struct brw_vue_map *vue_map, int urb_entry_read_offset, * Each increment of urb_entry_read_offset represents a 256-bit value, so * it counts for two 128-bit VUE slots. */ - attr_override = slot - 2 * urb_entry_read_offset; - assert (attr_override >= 0 && attr_override < 32); + int source_attr = slot - 2 * urb_entry_read_offset; + assert(source_attr >= 0 && source_attr < 32); /* If we are doing two-sided color, and the VUE slot following this one * represents a back-facing color, then we need to instruct the SF unit to * do back-facing swizzling. */ - if (two_side_color) { - if (vue_map->slot_to_vert_result[slot] == VERT_RESULT_COL0 && - vue_map->slot_to_vert_result[slot+1] == VERT_RESULT_BFC0) - attr_override |= (ATTRIBUTE_SWIZZLE_INPUTATTR_FACING << ATTRIBUTE_SWIZZLE_SHIFT); - else if (vue_map->slot_to_vert_result[slot] == VERT_RESULT_COL1 && - vue_map->slot_to_vert_result[slot+1] == VERT_RESULT_BFC1) - attr_override |= (ATTRIBUTE_SWIZZLE_INPUTATTR_FACING << ATTRIBUTE_SWIZZLE_SHIFT); + bool swizzling = two_side_color && + ((vue_map->slot_to_varying[slot] == VARYING_SLOT_COL0 && + vue_map->slot_to_varying[slot+1] == VARYING_SLOT_BFC0) || + (vue_map->slot_to_varying[slot] == VARYING_SLOT_COL1 && + vue_map->slot_to_varying[slot+1] == VARYING_SLOT_BFC1)); + + /* Update max_source_attr. If swizzling, the SF will read this slot + 1. */ + if (*max_source_attr < source_attr + swizzling) + *max_source_attr = source_attr + swizzling; + + if (swizzling) { + return source_attr | + (ATTRIBUTE_SWIZZLE_INPUTATTR_FACING << ATTRIBUTE_SWIZZLE_SHIFT); + } + + return source_attr; +} + + +/** + * Create the mapping from the FS inputs we produce to the previous pipeline + * stage (GS or VS) outputs they source from. + */ +void +calculate_attr_overrides(const struct brw_context *brw, + uint16_t *attr_overrides, + uint32_t *point_sprite_enables, + uint32_t *flat_enables, + uint32_t *urb_entry_read_length) +{ + const int urb_entry_read_offset = BRW_SF_URB_ENTRY_READ_OFFSET; + uint32_t max_source_attr = 0; + + /* _NEW_LIGHT */ + bool shade_model_flat = brw->ctx.Light.ShadeModel == GL_FLAT; + + /* Initialize all the attr_overrides to 0. In the loop below we'll modify + * just the ones that correspond to inputs used by the fs. + */ + memset(attr_overrides, 0, 16*sizeof(*attr_overrides)); + + for (int attr = 0; attr < VARYING_SLOT_MAX; attr++) { + enum glsl_interp_qualifier interp_qualifier = + brw->fragment_program->InterpQualifier[attr]; + bool is_gl_Color = attr == VARYING_SLOT_COL0 || attr == VARYING_SLOT_COL1; + /* CACHE_NEW_WM_PROG */ + int input_index = brw->wm.prog_data->urb_setup[attr]; + + if (input_index < 0) + continue; + + /* _NEW_POINT */ + if (brw->ctx.Point.PointSprite && + (attr >= VARYING_SLOT_TEX0 && attr <= VARYING_SLOT_TEX7) && + brw->ctx.Point.CoordReplace[attr - VARYING_SLOT_TEX0]) { + *point_sprite_enables |= (1 << input_index); + } + + if (attr == VARYING_SLOT_PNTC) + *point_sprite_enables |= (1 << input_index); + + /* flat shading */ + if (interp_qualifier == INTERP_QUALIFIER_FLAT || + (shade_model_flat && is_gl_Color && + interp_qualifier == INTERP_QUALIFIER_NONE)) + *flat_enables |= (1 << input_index); + + /* BRW_NEW_VUE_MAP_GEOM_OUT | _NEW_LIGHT | _NEW_PROGRAM */ + uint16_t attr_override = + get_attr_override(&brw->vue_map_geom_out, + urb_entry_read_offset, attr, + brw->ctx.VertexProgram._TwoSideEnabled, + &max_source_attr); + + /* The hardware can only do the overrides on 16 overrides at a + * time, and the other up to 16 have to be lined up so that the + * input index = the output index. We'll need to do some + * tweaking to make sure that's the case. + */ + if (input_index < 16) + attr_overrides[input_index] = attr_override; + else + assert(attr_override == input_index); } - return attr_override; + /* From the Sandy Bridge PRM, Volume 2, Part 1, documentation for + * 3DSTATE_SF DWord 1 bits 15:11, "Vertex URB Entry Read Length": + * + * "This field should be set to the minimum length required to read the + * maximum source attribute. The maximum source attribute is indicated + * by the maximum value of the enabled Attribute # Source Attribute if + * Attribute Swizzle Enable is set, Number of Output Attributes-1 if + * enable is not set. + * read_length = ceiling((max_source_attr + 1) / 2) + * + * [errata] Corruption/Hang possible if length programmed larger than + * recommended" + * + * Similar text exists for Ivy Bridge. + */ + *urb_entry_read_length = ALIGN(max_source_attr + 1, 2) / 2; } + static void upload_sf_state(struct brw_context *brw) { - struct intel_context *intel = &brw->intel; - struct gl_context *ctx = &intel->ctx; - struct brw_vue_map vue_map; - uint32_t urb_entry_read_length; - /* CACHE_NEW_VS_PROG */ - GLbitfield64 vs_outputs_written = brw->vs.prog_data->outputs_written; - /* BRW_NEW_FRAGMENT_PROGRAM */ - uint32_t num_outputs = brw_count_bits(brw->fragment_program->Base.InputsRead); + struct gl_context *ctx = &brw->ctx; + /* CACHE_NEW_WM_PROG */ + uint32_t num_outputs = brw->wm.prog_data->num_varying_inputs; uint32_t dw1, dw2, dw3, dw4, dw16, dw17; int i; /* _NEW_BUFFER */ - GLboolean render_to_fbo = brw->intel.ctx.DrawBuffer->Name != 0; - int attr = 0, input_index = 0; - int urb_entry_read_offset; + bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); + bool multisampled_fbo = ctx->DrawBuffer->Visual.samples > 1; + + const int urb_entry_read_offset = BRW_SF_URB_ENTRY_READ_OFFSET; float point_size; - uint16_t attr_overrides[FRAG_ATTRIB_MAX]; - int nr_userclip; - - /* _NEW_TRANSFORM */ - if (ctx->Transform.ClipPlanesEnabled) - urb_entry_read_offset = 2; - else - urb_entry_read_offset = 1; - nr_userclip = brw_count_bits(ctx->Transform.ClipPlanesEnabled); - - brw_compute_vue_map(&vue_map, intel, nr_userclip, vs_outputs_written); - urb_entry_read_length = (vue_map.num_slots + 1)/2 - urb_entry_read_offset; - if (urb_entry_read_length == 0) { - /* Setting the URB entry read length to 0 causes undefined behavior, so - * if we have no URB data to read, set it to 1. - */ - urb_entry_read_length = 1; - } + uint16_t attr_overrides[16]; + uint32_t point_sprite_origin; + + dw1 = GEN6_SF_SWIZZLE_ENABLE | num_outputs << GEN6_SF_NUM_OUTPUTS_SHIFT; + + dw2 = GEN6_SF_STATISTICS_ENABLE | + GEN6_SF_VIEWPORT_TRANSFORM_ENABLE; - dw1 = - GEN6_SF_SWIZZLE_ENABLE | - num_outputs << GEN6_SF_NUM_OUTPUTS_SHIFT | - urb_entry_read_length << GEN6_SF_URB_ENTRY_READ_LENGTH_SHIFT | - urb_entry_read_offset << GEN6_SF_URB_ENTRY_READ_OFFSET_SHIFT; - dw2 = GEN6_SF_VIEWPORT_TRANSFORM_ENABLE | - GEN6_SF_STATISTICS_ENABLE; dw3 = 0; dw4 = 0; dw16 = 0; @@ -230,15 +302,23 @@ upload_sf_state(struct brw_context *brw) } /* _NEW_LINE */ - dw3 |= U_FIXED(CLAMP(ctx->Line.Width, 0.0, 7.99), 7) << - GEN6_SF_LINE_WIDTH_SHIFT; + { + uint32_t line_width_u3_7 = U_FIXED(CLAMP(ctx->Line.Width, 0.0, 7.99), 7); + /* TODO: line width of 0 is not allowed when MSAA enabled */ + if (line_width_u3_7 == 0) + line_width_u3_7 = 1; + dw3 |= line_width_u3_7 << GEN6_SF_LINE_WIDTH_SHIFT; + } if (ctx->Line.SmoothFlag) { dw3 |= GEN6_SF_LINE_AA_ENABLE; dw3 |= GEN6_SF_LINE_AA_MODE_TRUE; dw3 |= GEN6_SF_LINE_END_CAP_WIDTH_1_0; } + /* _NEW_MULTISAMPLE */ + if (multisampled_fbo && ctx->Multisample.Enabled) + dw3 |= GEN6_SF_MSRAST_ON_PATTERN; - /* _NEW_POINT */ + /* _NEW_PROGRAM | _NEW_POINT */ if (!(ctx->VertexProgram.PointSizeEnabled || ctx->Point._Attenuated)) dw4 |= GEN6_SF_USE_STATE_POINT_WIDTH; @@ -249,8 +329,16 @@ upload_sf_state(struct brw_context *brw) /* Clamp to the hardware limits and convert to fixed point */ dw4 |= U_FIXED(CLAMP(point_size, 0.125, 255.875), 3); - if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) - dw1 |= GEN6_SF_POINT_SPRITE_LOWERLEFT; + /* + * Window coordinates in an FBO are inverted, which means point + * sprite origin must be inverted, too. + */ + if ((ctx->Point.SpriteOrigin == GL_LOWER_LEFT) != render_to_fbo) { + point_sprite_origin = GEN6_SF_POINT_SPRITE_LOWERLEFT; + } else { + point_sprite_origin = GEN6_SF_POINT_SPRITE_UPPERLEFT; + } + dw1 |= point_sprite_origin; /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex != GL_FIRST_VERTEX_CONVENTION) { @@ -263,44 +351,14 @@ upload_sf_state(struct brw_context *brw) (1 << GEN6_SF_TRIFAN_PROVOKE_SHIFT); } - /* flat shading */ - if (ctx->Light.ShadeModel == GL_FLAT) { - dw17 |= ((brw->fragment_program->Base.InputsRead & (FRAG_BIT_COL0 | FRAG_BIT_COL1)) >> - ((brw->fragment_program->Base.InputsRead & FRAG_BIT_WPOS) ? 0 : 1)); - } - - /* Create the mapping from the FS inputs we produce to the VS outputs - * they source from. + /* BRW_NEW_VUE_MAP_GEOM_OUT | _NEW_POINT | _NEW_LIGHT | _NEW_PROGRAM | + * CACHE_NEW_WM_PROG */ - for (; attr < FRAG_ATTRIB_MAX; attr++) { - if (!(brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(attr))) - continue; - - /* _NEW_POINT */ - if (ctx->Point.PointSprite && - (attr >= FRAG_ATTRIB_TEX0 && attr <= FRAG_ATTRIB_TEX7) && - ctx->Point.CoordReplace[attr - FRAG_ATTRIB_TEX0]) { - dw16 |= (1 << input_index); - } - - if (attr == FRAG_ATTRIB_PNTC) - dw16 |= (1 << input_index); - - /* The hardware can only do the overrides on 16 overrides at a - * time, and the other up to 16 have to be lined up so that the - * input index = the output index. We'll need to do some - * tweaking to make sure that's the case. - */ - assert(input_index < 16 || attr == input_index); - - /* _NEW_LIGHT | _NEW_PROGRAM */ - attr_overrides[input_index++] = - get_attr_override(&vue_map, urb_entry_read_offset, attr, - ctx->VertexProgram._TwoSideEnabled); - } - - for (; input_index < FRAG_ATTRIB_MAX; input_index++) - attr_overrides[input_index] = 0; + uint32_t urb_entry_read_length; + calculate_attr_overrides(brw, attr_overrides, &dw16, &dw17, + &urb_entry_read_length); + dw1 |= (urb_entry_read_length << GEN6_SF_URB_ENTRY_READ_LENGTH_SHIFT | + urb_entry_read_offset << GEN6_SF_URB_ENTRY_READ_OFFSET_SHIFT); BEGIN_BATCH(20); OUT_BATCH(_3DSTATE_SF << 16 | (20 - 2)); @@ -330,10 +388,11 @@ const struct brw_tracked_state gen6_sf_state = { _NEW_SCISSOR | _NEW_BUFFERS | _NEW_POINT | - _NEW_TRANSFORM), + _NEW_MULTISAMPLE), .brw = (BRW_NEW_CONTEXT | - BRW_NEW_FRAGMENT_PROGRAM), - .cache = CACHE_NEW_VS_PROG + BRW_NEW_FRAGMENT_PROGRAM | + BRW_NEW_VUE_MAP_GEOM_OUT), + .cache = CACHE_NEW_WM_PROG }, .emit = upload_sf_state, };