/** * Determine the appropriate attribute override value to store into the * 3DSTATE_SF structure for a given fragment shader attribute. The attribute * override value contains two pieces of information: the location of the * attribute in the VUE (relative to urb_entry_read_offset, see below), and a * flag indicating whether to "swizzle" the attribute based on the direction * the triangle is facing. * * If an attribute is "swizzled", then the given VUE location is used for * front-facing triangles, and the VUE location that immediately follows is * used for back-facing triangles. We use this to implement the mapping from * gl_FrontColor/gl_BackColor to gl_Color. * * urb_entry_read_offset is the offset into the VUE at which the SF unit is * being instructed to begin reading attribute data. It can be set to a * nonzero value to prevent the SF unit from wasting time reading elements of * 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) { 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]; /* 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) { /* 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 * just reference the first available attribute. */ return 0; } /* Compute the location of the attribute relative to 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); /* 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); } return attr_override; }
/** * Determine the appropriate attribute override value to store into the * 3DSTATE_SF structure for a given fragment shader attribute. The attribute * override value contains two pieces of information: the location of the * attribute in the VUE (relative to urb_entry_read_offset, see below), and a * flag indicating whether to "swizzle" the attribute based on the direction * the triangle is facing. * * If an attribute is "swizzled", then the given VUE location is used for * front-facing triangles, and the VUE location that immediately follows is * used for back-facing triangles. We use this to implement the mapping from * gl_FrontColor/gl_BackColor to gl_Color. * * urb_entry_read_offset is the offset into the VUE at which the SF unit is * being instructed to begin reading attribute data. It can be set to a * nonzero value to prevent the SF unit from wasting time reading elements of * 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, uint32_t *max_source_attr) { 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. */ int slot = vue_map->vert_result_to_slot[vs_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) { /* This attribute does not exist in the VUE--that means that the vertex * 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; } /* Compute the location of the attribute relative to 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. */ 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. */ bool swizzling = two_side_color && ((vue_map->slot_to_vert_result[slot] == VERT_RESULT_COL0 && vue_map->slot_to_vert_result[slot+1] == VERT_RESULT_BFC0) || (vue_map->slot_to_vert_result[slot] == VERT_RESULT_COL1 && vue_map->slot_to_vert_result[slot+1] == VERT_RESULT_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; }