i965: Implement ARB_fragment_layer_viewport.

Normally, we could read gl_Layer from bits 26:16 of R0.0.  However, the
specification requires that bogus out-of-range 32-bit values written by
previous stages need to appear in the fragment shader as-written.

Instead, we pass in the full 32-bit value from the VUE header as an
extra flat-shaded varying.  We have the SF override the value to 0
when the previous stage didn't actually write a value (it's actually
defined to return 0).

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Chris Forbes <chrisf@ijw.co.nz>
This commit is contained in:
Kenneth Graunke 2015-06-17 13:06:18 -07:00
parent 5392328a32
commit 8c902a580a
4 changed files with 46 additions and 1 deletions

View File

@ -1442,6 +1442,9 @@ fs_visitor::calculate_urb_setup()
}
}
} else {
bool include_vue_header =
nir->info.inputs_read & (VARYING_BIT_LAYER | VARYING_BIT_VIEWPORT);
/* We have enough input varyings that the SF/SBE pipeline stage can't
* arbitrarily rearrange them to suit our whim; we have to put them
* in an order that matches the output of the previous pipeline stage
@ -1451,7 +1454,9 @@ fs_visitor::calculate_urb_setup()
brw_compute_vue_map(devinfo, &prev_stage_vue_map,
key->input_slots_valid,
nir->info.separate_shader);
int first_slot = 2 * BRW_SF_URB_ENTRY_READ_OFFSET;
int first_slot =
include_vue_header ? 0 : 2 * BRW_SF_URB_ENTRY_READ_OFFSET;
assert(prev_stage_vue_map.num_slots <= first_slot + 32);
for (int slot = first_slot; slot < prev_stage_vue_map.num_slots;
slot++) {

View File

@ -71,6 +71,14 @@ fs_visitor::nir_setup_inputs()
var->data.origin_upper_left);
emit_percomp(bld, fs_inst(BRW_OPCODE_MOV, bld.dispatch_width(),
input, reg), 0xF);
} else if (var->data.location == VARYING_SLOT_LAYER) {
struct brw_reg reg = suboffset(interp_reg(VARYING_SLOT_LAYER, 1), 3);
reg.type = BRW_REGISTER_TYPE_D;
bld.emit(FS_OPCODE_CINTERP, retype(input, BRW_REGISTER_TYPE_D), reg);
} else if (var->data.location == VARYING_SLOT_VIEWPORT) {
struct brw_reg reg = suboffset(interp_reg(VARYING_SLOT_VIEWPORT, 2), 3);
reg.type = BRW_REGISTER_TYPE_D;
bld.emit(FS_OPCODE_CINTERP, retype(input, BRW_REGISTER_TYPE_D), reg);
} else {
emit_general_interpolation(input, var->name, var->type,
(glsl_interp_qualifier) var->data.interpolation,

View File

@ -60,6 +60,23 @@ get_attr_override(const struct brw_vue_map *vue_map, int urb_entry_read_offset,
/* Find the VUE slot for this attribute. */
int slot = vue_map->varying_to_slot[fs_attr];
/* Viewport and Layer are stored in the VUE header. We need to override
* them to zero if earlier stages didn't write them, as GL requires that
* they read back as zero when not explicitly set.
*/
if (fs_attr == VARYING_SLOT_VIEWPORT || fs_attr == VARYING_SLOT_LAYER) {
unsigned override =
ATTRIBUTE_0_OVERRIDE_X | ATTRIBUTE_0_OVERRIDE_W |
ATTRIBUTE_CONST_0000 << ATTRIBUTE_0_CONST_SOURCE_SHIFT;
if (!(vue_map->slots_valid & VARYING_BIT_LAYER))
override |= ATTRIBUTE_0_OVERRIDE_Y;
if (!(vue_map->slots_valid & VARYING_BIT_VIEWPORT))
override |= ATTRIBUTE_0_OVERRIDE_Z;
return override;
}
/* If there was only a back color written but not front, use back
* as the color instead of undefined
*/
@ -169,6 +186,20 @@ calculate_attr_overrides(const struct brw_context *brw,
*urb_entry_read_offset = BRW_SF_URB_ENTRY_READ_OFFSET;
/* BRW_NEW_FRAGMENT_PROGRAM
*
* If the fragment shader reads VARYING_SLOT_LAYER, then we need to pass in
* the full vertex header. Otherwise, we can program the SF to start
* reading at an offset of 1 (2 varying slots) to skip unnecessary data:
* - VARYING_SLOT_PSIZ and BRW_VARYING_SLOT_NDC on gen4-5
* - VARYING_SLOT_{PSIZ,LAYER} and VARYING_SLOT_POS on gen6+
*/
bool fs_needs_vue_header = brw->fragment_program->Base.InputsRead &
(VARYING_BIT_LAYER | VARYING_BIT_VIEWPORT);
*urb_entry_read_offset = fs_needs_vue_header ? 0 : 1;
/* _NEW_LIGHT */
bool shade_model_flat = brw->ctx.Light.ShadeModel == GL_FLAT;

View File

@ -287,6 +287,7 @@ intelInitExtensions(struct gl_context *ctx)
ctx->Extensions.ARB_conditional_render_inverted = true;
ctx->Extensions.ARB_draw_buffers_blend = true;
ctx->Extensions.ARB_ES3_compatibility = true;
ctx->Extensions.ARB_fragment_layer_viewport = true;
ctx->Extensions.ARB_sample_shading = true;
ctx->Extensions.ARB_shading_language_420pack = true;
ctx->Extensions.ARB_shading_language_packing = true;