intel/brw: Remove unused legacy shader stages

CLIP, STRIP-FAN and FF Geometry don't apply to Gfx9+.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27691>
This commit is contained in:
Caio Oliveira
2024-02-15 00:03:56 -08:00
committed by Marge Bot
parent c621f75e7b
commit 15469b0a63
12 changed files with 0 additions and 3994 deletions
-163
View File
@@ -1,163 +0,0 @@
/*
Copyright (C) Intel Corp. 2006. All Rights Reserved.
Intel funded Tungsten Graphics to
develop this 3D driver.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**********************************************************************/
/*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#ifndef BRW_CLIP_H
#define BRW_CLIP_H
#include "brw_compiler.h"
#include "brw_eu.h"
/* Initial 3 verts, plus at most 6 additional verts from intersections
* with fixed planes, plus at most 8 additional verts from intersections
* with user clip planes
*/
#define MAX_VERTS (3+6+8)
#define PRIM_MASK (0x1f)
struct brw_clip_compile {
struct brw_codegen func;
struct brw_clip_prog_key key;
struct brw_clip_prog_data prog_data;
struct {
struct brw_reg R0;
struct brw_reg vertex[MAX_VERTS];
struct brw_reg t;
struct brw_reg t0, t1;
struct brw_reg dp0, dp1;
struct brw_reg dpPrev;
struct brw_reg dp;
struct brw_reg loopcount;
struct brw_reg nr_verts;
struct brw_reg planemask;
struct brw_reg inlist;
struct brw_reg outlist;
struct brw_reg freelist;
struct brw_reg dir;
struct brw_reg tmp0, tmp1;
struct brw_reg offset;
struct brw_reg fixed_planes;
struct brw_reg plane_equation;
struct brw_reg ff_sync;
/* Bitmask indicating which coordinate attribute should be used for
* comparison to each clipping plane. A 0 indicates that VARYING_SLOT_POS
* should be used, because it's one of the fixed +/- x/y/z planes that
* constitute the bounds of the view volume. A 1 indicates that
* VARYING_SLOT_CLIP_VERTEX should be used (if available) since it's a user-
* defined clipping plane.
*/
struct brw_reg vertex_src_mask;
/* Offset into the vertex of the current plane's clipdistance value */
struct brw_reg clipdistance_offset;
} reg;
/* Number of registers storing VUE data */
GLuint nr_regs;
GLuint first_tmp;
GLuint last_tmp;
bool need_direction;
struct intel_vue_map vue_map;
};
/**
* True if the given varying is one of the outputs of the vertex shader.
*/
static inline bool brw_clip_have_varying(struct brw_clip_compile *c,
GLuint varying)
{
return (c->key.attrs & BITFIELD64_BIT(varying)) ? 1 : 0;
}
/* Points are only culled, so no need for a clip routine, however it
* works out easier to have a dummy one.
*/
void brw_emit_unfilled_clip( struct brw_clip_compile *c );
void brw_emit_tri_clip( struct brw_clip_compile *c );
void brw_emit_line_clip( struct brw_clip_compile *c );
void brw_emit_point_clip( struct brw_clip_compile *c );
/* brw_clip_tri.c, for use by the unfilled clip routine:
*/
void brw_clip_tri_init_vertices( struct brw_clip_compile *c );
void brw_clip_tri_flat_shade( struct brw_clip_compile *c );
void brw_clip_tri( struct brw_clip_compile *c );
void brw_clip_tri_emit_polygon( struct brw_clip_compile *c );
void brw_clip_tri_alloc_regs( struct brw_clip_compile *c,
GLuint nr_verts );
/* Utils:
*/
void brw_clip_interp_vertex( struct brw_clip_compile *c,
struct brw_indirect dest_ptr,
struct brw_indirect v0_ptr, /* from */
struct brw_indirect v1_ptr, /* to */
struct brw_reg t0,
bool force_edgeflag );
void brw_clip_init_planes( struct brw_clip_compile *c );
void brw_clip_emit_vue(struct brw_clip_compile *c,
struct brw_indirect vert,
enum brw_urb_write_flags flags,
GLuint header);
void brw_clip_kill_thread(struct brw_clip_compile *c);
struct brw_reg brw_clip_plane_stride( struct brw_clip_compile *c );
struct brw_reg brw_clip_plane0_address( struct brw_clip_compile *c );
void brw_clip_copy_flatshaded_attributes( struct brw_clip_compile *c,
GLuint to, GLuint from );
void brw_clip_init_clipmask( struct brw_clip_compile *c );
struct brw_reg get_tmp( struct brw_clip_compile *c );
void brw_clip_project_position(struct brw_clip_compile *c,
struct brw_reg pos );
void brw_clip_ff_sync(struct brw_clip_compile *c);
void brw_clip_init_ff_sync(struct brw_clip_compile *c);
#endif
-303
View File
@@ -1,303 +0,0 @@
/*
Copyright (C) Intel Corp. 2006. All Rights Reserved.
Intel funded Tungsten Graphics to
develop this 3D driver.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**********************************************************************/
/*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#include "brw_clip.h"
#include "brw_prim.h"
static void brw_clip_line_alloc_regs( struct brw_clip_compile *c )
{
const struct intel_device_info *devinfo = c->func.devinfo;
GLuint i = 0,j;
/* Register usage is static, precompute here:
*/
c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;
if (c->key.nr_userclip) {
c->reg.fixed_planes = brw_vec4_grf(i, 0);
i += (6 + c->key.nr_userclip + 1) / 2;
c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2;
}
else
c->prog_data.curb_read_length = 0;
/* Payload vertices plus space for more generated vertices:
*/
for (j = 0; j < 4; j++) {
c->reg.vertex[j] = brw_vec4_grf(i, 0);
i += c->nr_regs;
}
c->reg.t = brw_vec1_grf(i, 0);
c->reg.t0 = brw_vec1_grf(i, 1);
c->reg.t1 = brw_vec1_grf(i, 2);
c->reg.planemask = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD);
c->reg.plane_equation = brw_vec4_grf(i, 4);
i++;
c->reg.dp0 = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */
c->reg.dp1 = brw_vec1_grf(i, 4);
i++;
if (!c->key.nr_userclip) {
c->reg.fixed_planes = brw_vec8_grf(i, 0);
i++;
}
c->reg.vertex_src_mask = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
c->reg.clipdistance_offset = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_W);
i++;
if (devinfo->ver == 5) {
c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
i++;
}
c->first_tmp = i;
c->last_tmp = i;
c->prog_data.urb_read_length = c->nr_regs; /* ? */
c->prog_data.total_grf = i;
}
/* Line clipping, more or less following the following algorithm:
*
* for (p=0;p<MAX_PLANES;p++) {
* if (clipmask & (1 << p)) {
* GLfloat dp0 = DOTPROD( vtx0, plane[p] );
* GLfloat dp1 = DOTPROD( vtx1, plane[p] );
*
* if (dp1 < 0.0f) {
* GLfloat t = dp1 / (dp1 - dp0);
* if (t > t1) t1 = t;
* } else {
* GLfloat t = dp0 / (dp0 - dp1);
* if (t > t0) t0 = t;
* }
*
* if (t0 + t1 >= 1.0)
* return;
* }
* }
*
* interp( ctx, newvtx0, vtx0, vtx1, t0 );
* interp( ctx, newvtx1, vtx1, vtx0, t1 );
*
*/
static void clip_and_emit_line( struct brw_clip_compile *c )
{
struct brw_codegen *p = &c->func;
struct brw_indirect vtx0 = brw_indirect(0, 0);
struct brw_indirect vtx1 = brw_indirect(1, 0);
struct brw_indirect newvtx0 = brw_indirect(2, 0);
struct brw_indirect newvtx1 = brw_indirect(3, 0);
struct brw_indirect plane_ptr = brw_indirect(4, 0);
struct brw_reg v1_null_ud = retype(vec1(brw_null_reg()), BRW_REGISTER_TYPE_UD);
GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
GLint clipdist0_offset = c->key.nr_userclip
? brw_varying_to_offset(&c->vue_map, VARYING_SLOT_CLIP_DIST0)
: 0;
brw_MOV(p, get_addr_reg(vtx0), brw_address(c->reg.vertex[0]));
brw_MOV(p, get_addr_reg(vtx1), brw_address(c->reg.vertex[1]));
brw_MOV(p, get_addr_reg(newvtx0), brw_address(c->reg.vertex[2]));
brw_MOV(p, get_addr_reg(newvtx1), brw_address(c->reg.vertex[3]));
brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));
/* Note: init t0, t1 together:
*/
brw_MOV(p, vec2(c->reg.t0), brw_imm_f(0));
brw_clip_init_planes(c);
brw_clip_init_clipmask(c);
/* -ve rhw workaround */
if (p->devinfo->has_negative_rhw_bug) {
brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
brw_imm_ud(1<<20));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(0x3f));
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
}
/* Set the initial vertex source mask: The first 6 planes are the bounds
* of the view volume; the next 8 planes are the user clipping planes.
*/
brw_MOV(p, c->reg.vertex_src_mask, brw_imm_ud(0x3fc0));
/* Set the initial clipdistance offset to be 6 floats before gl_ClipDistance[0].
* We'll increment 6 times before we start hitting actual user clipping. */
brw_MOV(p, c->reg.clipdistance_offset, brw_imm_d(clipdist0_offset - 6*sizeof(float)));
brw_DO(p, BRW_EXECUTE_1);
{
/* if (planemask & 1)
*/
brw_AND(p, v1_null_ud, c->reg.planemask, brw_imm_ud(1));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
brw_IF(p, BRW_EXECUTE_1);
{
brw_AND(p, v1_null_ud, c->reg.vertex_src_mask, brw_imm_ud(1));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
brw_IF(p, BRW_EXECUTE_1);
{
/* user clip distance: just fetch the correct float from each vertex */
struct brw_indirect temp_ptr = brw_indirect(7, 0);
brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx0), c->reg.clipdistance_offset);
brw_MOV(p, c->reg.dp0, deref_1f(temp_ptr, 0));
brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx1), c->reg.clipdistance_offset);
brw_MOV(p, c->reg.dp1, deref_1f(temp_ptr, 0));
}
brw_ELSE(p);
{
/* fixed plane: fetch the hpos, dp4 against the plane. */
if (c->key.nr_userclip)
brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
else
brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));
brw_DP4(p, vec4(c->reg.dp0), deref_4f(vtx0, hpos_offset), c->reg.plane_equation);
brw_DP4(p, vec4(c->reg.dp1), deref_4f(vtx1, hpos_offset), c->reg.plane_equation);
}
brw_ENDIF(p);
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, vec1(c->reg.dp1), brw_imm_f(0.0f));
brw_IF(p, BRW_EXECUTE_1);
{
/*
* Both can be negative on GM965/G965 due to RHW workaround
* if so, this object should be rejected.
*/
if (p->devinfo->has_negative_rhw_bug) {
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_LE, c->reg.dp0, brw_imm_f(0.0));
brw_IF(p, BRW_EXECUTE_1);
{
brw_clip_kill_thread(c);
}
brw_ENDIF(p);
}
brw_ADD(p, c->reg.t, c->reg.dp1, negate(c->reg.dp0));
brw_math_invert(p, c->reg.t, c->reg.t);
brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp1);
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t1 );
brw_MOV(p, c->reg.t1, c->reg.t);
brw_inst_set_pred_control(p->devinfo, brw_last_inst,
BRW_PREDICATE_NORMAL);
}
brw_ELSE(p);
{
/* Coming back in. We know that both cannot be negative
* because the line would have been culled in that case.
*/
/* If both are positive, do nothing */
/* Only on GM965/G965 */
if (p->devinfo->has_negative_rhw_bug) {
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.dp0, brw_imm_f(0.0));
brw_IF(p, BRW_EXECUTE_1);
}
{
brw_ADD(p, c->reg.t, c->reg.dp0, negate(c->reg.dp1));
brw_math_invert(p, c->reg.t, c->reg.t);
brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp0);
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t0 );
brw_MOV(p, c->reg.t0, c->reg.t);
brw_inst_set_pred_control(p->devinfo, brw_last_inst,
BRW_PREDICATE_NORMAL);
}
if (p->devinfo->has_negative_rhw_bug) {
brw_ENDIF(p);
}
}
brw_ENDIF(p);
}
brw_ENDIF(p);
/* plane_ptr++;
*/
brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));
/* while (planemask>>=1) != 0
*/
brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
brw_SHR(p, c->reg.vertex_src_mask, c->reg.vertex_src_mask, brw_imm_ud(1));
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
brw_ADD(p, c->reg.clipdistance_offset, c->reg.clipdistance_offset, brw_imm_w(sizeof(float)));
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
}
brw_WHILE(p);
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
brw_ADD(p, c->reg.t, c->reg.t0, c->reg.t1);
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.t, brw_imm_f(1.0));
brw_IF(p, BRW_EXECUTE_1);
{
brw_clip_interp_vertex(c, newvtx0, vtx0, vtx1, c->reg.t0, false);
brw_clip_interp_vertex(c, newvtx1, vtx1, vtx0, c->reg.t1, false);
brw_clip_emit_vue(c, newvtx0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
(_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
| URB_WRITE_PRIM_START);
brw_clip_emit_vue(c, newvtx1, BRW_URB_WRITE_EOT_COMPLETE,
(_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
| URB_WRITE_PRIM_END);
}
brw_ENDIF(p);
brw_clip_kill_thread(c);
}
void brw_emit_line_clip( struct brw_clip_compile *c )
{
brw_clip_line_alloc_regs(c);
brw_clip_init_ff_sync(c);
if (c->key.contains_flat_varying) {
if (c->key.pv_first)
brw_clip_copy_flatshaded_attributes(c, 1, 0);
else
brw_clip_copy_flatshaded_attributes(c, 0, 1);
}
clip_and_emit_line(c);
}
-45
View File
@@ -1,45 +0,0 @@
/*
Copyright (C) Intel Corp. 2006. All Rights Reserved.
Intel funded Tungsten Graphics to
develop this 3D driver.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**********************************************************************/
/*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#include "brw_clip.h"
/* Point clipping, nothing to do?
*/
void brw_emit_point_clip( struct brw_clip_compile *c )
{
/* Send an empty message to kill the thread:
*/
brw_clip_tri_alloc_regs(c, 0);
brw_clip_init_ff_sync(c);
brw_clip_kill_thread(c);
}
-659
View File
@@ -1,659 +0,0 @@
/*
Copyright (C) Intel Corp. 2006. All Rights Reserved.
Intel funded Tungsten Graphics to
develop this 3D driver.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**********************************************************************/
/*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#include "brw_clip.h"
#include "brw_prim.h"
static void release_tmps( struct brw_clip_compile *c )
{
c->last_tmp = c->first_tmp;
}
void brw_clip_tri_alloc_regs( struct brw_clip_compile *c,
GLuint nr_verts )
{
const struct intel_device_info *devinfo = c->func.devinfo;
GLuint i = 0,j;
/* Register usage is static, precompute here:
*/
c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;
if (c->key.nr_userclip) {
c->reg.fixed_planes = brw_vec4_grf(i, 0);
i += (6 + c->key.nr_userclip + 1) / 2;
c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2;
}
else
c->prog_data.curb_read_length = 0;
/* Payload vertices plus space for more generated vertices:
*/
for (j = 0; j < nr_verts; j++) {
c->reg.vertex[j] = brw_vec4_grf(i, 0);
i += c->nr_regs;
}
if (c->vue_map.num_slots % 2 && nr_verts > 0) {
/* The VUE has an odd number of slots so the last register is only half
* used. Fill the second half with zero.
*/
for (j = 0; j < 3; j++) {
GLuint delta = brw_vue_slot_to_offset(c->vue_map.num_slots);
brw_MOV(&c->func, byte_offset(c->reg.vertex[j], delta), brw_imm_f(0));
}
}
c->reg.t = brw_vec1_grf(i, 0);
c->reg.loopcount = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_D);
c->reg.nr_verts = retype(brw_vec1_grf(i, 2), BRW_REGISTER_TYPE_UD);
c->reg.planemask = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD);
c->reg.plane_equation = brw_vec4_grf(i, 4);
i++;
c->reg.dpPrev = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */
c->reg.dp = brw_vec1_grf(i, 4);
i++;
c->reg.inlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
i++;
c->reg.outlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
i++;
c->reg.freelist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
i++;
if (!c->key.nr_userclip) {
c->reg.fixed_planes = brw_vec8_grf(i, 0);
i++;
}
if (c->key.do_unfilled) {
c->reg.dir = brw_vec4_grf(i, 0);
c->reg.offset = brw_vec4_grf(i, 4);
i++;
c->reg.tmp0 = brw_vec4_grf(i, 0);
c->reg.tmp1 = brw_vec4_grf(i, 4);
i++;
}
c->reg.vertex_src_mask = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
c->reg.clipdistance_offset = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_W);
i++;
if (devinfo->ver == 5) {
c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
i++;
}
c->first_tmp = i;
c->last_tmp = i;
c->prog_data.urb_read_length = c->nr_regs; /* ? */
c->prog_data.total_grf = i;
}
void brw_clip_tri_init_vertices( struct brw_clip_compile *c )
{
struct brw_codegen *p = &c->func;
struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
/* Initial list of indices for incoming vertices:
*/
brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
brw_CMP(p,
vec1(brw_null_reg()),
BRW_CONDITIONAL_EQ,
tmp0,
brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE));
/* XXX: Is there an easier way to do this? Need to reverse every
* second tristrip element: Can ignore sometimes?
*/
brw_IF(p, BRW_EXECUTE_1);
{
brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[1]) );
brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[0]) );
if (c->need_direction)
brw_MOV(p, c->reg.dir, brw_imm_f(-1));
}
brw_ELSE(p);
{
brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[0]) );
brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[1]) );
if (c->need_direction)
brw_MOV(p, c->reg.dir, brw_imm_f(1));
}
brw_ENDIF(p);
brw_MOV(p, get_element(c->reg.inlist, 2), brw_address(c->reg.vertex[2]) );
brw_MOV(p, brw_vec8_grf(c->reg.outlist.nr, 0), brw_imm_f(0));
brw_MOV(p, c->reg.nr_verts, brw_imm_ud(3));
}
void brw_clip_tri_flat_shade( struct brw_clip_compile *c )
{
struct brw_codegen *p = &c->func;
struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
brw_CMP(p,
vec1(brw_null_reg()),
BRW_CONDITIONAL_EQ,
tmp0,
brw_imm_ud(_3DPRIM_POLYGON));
brw_IF(p, BRW_EXECUTE_1);
{
brw_clip_copy_flatshaded_attributes(c, 1, 0);
brw_clip_copy_flatshaded_attributes(c, 2, 0);
}
brw_ELSE(p);
{
if (c->key.pv_first) {
brw_CMP(p,
vec1(brw_null_reg()),
BRW_CONDITIONAL_EQ,
tmp0,
brw_imm_ud(_3DPRIM_TRIFAN));
brw_IF(p, BRW_EXECUTE_1);
{
brw_clip_copy_flatshaded_attributes(c, 0, 1);
brw_clip_copy_flatshaded_attributes(c, 2, 1);
}
brw_ELSE(p);
{
brw_clip_copy_flatshaded_attributes(c, 1, 0);
brw_clip_copy_flatshaded_attributes(c, 2, 0);
}
brw_ENDIF(p);
}
else {
brw_clip_copy_flatshaded_attributes(c, 0, 2);
brw_clip_copy_flatshaded_attributes(c, 1, 2);
}
}
brw_ENDIF(p);
}
/**
* Loads the clip distance for a vertex into `dst`, and ends with
* a comparison of it to zero with the condition `cond`.
*
* - If using a fixed plane, the distance is dot(hpos, plane).
* - If using a user clip plane, the distance is directly available in the vertex.
*/
static inline void
load_clip_distance(struct brw_clip_compile *c, struct brw_indirect vtx,
struct brw_reg dst, GLuint hpos_offset, int cond)
{
struct brw_codegen *p = &c->func;
dst = vec4(dst);
brw_AND(p, vec1(brw_null_reg()), c->reg.vertex_src_mask, brw_imm_ud(1));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
brw_IF(p, BRW_EXECUTE_1);
{
struct brw_indirect temp_ptr = brw_indirect(7, 0);
brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx), c->reg.clipdistance_offset);
brw_MOV(p, vec1(dst), deref_1f(temp_ptr, 0));
}
brw_ELSE(p);
{
brw_MOV(p, dst, deref_4f(vtx, hpos_offset));
brw_DP4(p, dst, dst, c->reg.plane_equation);
}
brw_ENDIF(p);
brw_CMP(p, brw_null_reg(), cond, vec1(dst), brw_imm_f(0.0f));
}
/* Use mesa's clipping algorithms, translated to GFX4 assembly.
*/
void brw_clip_tri( struct brw_clip_compile *c )
{
struct brw_codegen *p = &c->func;
struct brw_indirect vtx = brw_indirect(0, 0);
struct brw_indirect vtxPrev = brw_indirect(1, 0);
struct brw_indirect vtxOut = brw_indirect(2, 0);
struct brw_indirect plane_ptr = brw_indirect(3, 0);
struct brw_indirect inlist_ptr = brw_indirect(4, 0);
struct brw_indirect outlist_ptr = brw_indirect(5, 0);
struct brw_indirect freelist_ptr = brw_indirect(6, 0);
GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
GLint clipdist0_offset = c->key.nr_userclip
? brw_varying_to_offset(&c->vue_map, VARYING_SLOT_CLIP_DIST0)
: 0;
brw_MOV(p, get_addr_reg(vtxPrev), brw_address(c->reg.vertex[2]) );
brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));
brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
brw_MOV(p, get_addr_reg(freelist_ptr), brw_address(c->reg.vertex[3]) );
/* Set the initial vertex source mask: The first 6 planes are the bounds
* of the view volume; the next 8 planes are the user clipping planes.
*/
brw_MOV(p, c->reg.vertex_src_mask, brw_imm_ud(0x3fc0));
/* Set the initial clipdistance offset to be 6 floats before gl_ClipDistance[0].
* We'll increment 6 times before we start hitting actual user clipping. */
brw_MOV(p, c->reg.clipdistance_offset, brw_imm_d(clipdist0_offset - 6*sizeof(float)));
brw_DO(p, BRW_EXECUTE_1);
{
/* if (planemask & 1)
*/
brw_AND(p, vec1(brw_null_reg()), c->reg.planemask, brw_imm_ud(1));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
brw_IF(p, BRW_EXECUTE_1);
{
/* vtxOut = freelist_ptr++
*/
brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(freelist_ptr) );
brw_ADD(p, get_addr_reg(freelist_ptr), get_addr_reg(freelist_ptr), brw_imm_uw(c->nr_regs * REG_SIZE));
if (c->key.nr_userclip)
brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
else
brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));
brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
brw_MOV(p, c->reg.nr_verts, brw_imm_ud(0));
brw_DO(p, BRW_EXECUTE_1);
{
/* vtx = *input_ptr;
*/
brw_MOV(p, get_addr_reg(vtx), deref_1uw(inlist_ptr, 0));
load_clip_distance(c, vtxPrev, c->reg.dpPrev, hpos_offset, BRW_CONDITIONAL_L);
/* (prev < 0.0f) */
brw_IF(p, BRW_EXECUTE_1);
{
load_clip_distance(c, vtx, c->reg.dp, hpos_offset, BRW_CONDITIONAL_GE);
/* IS_POSITIVE(next)
*/
brw_IF(p, BRW_EXECUTE_1);
{
/* Coming back in.
*/
brw_ADD(p, c->reg.t, c->reg.dpPrev, negate(c->reg.dp));
brw_math_invert(p, c->reg.t, c->reg.t);
brw_MUL(p, c->reg.t, c->reg.t, c->reg.dpPrev);
/* If (vtxOut == 0) vtxOut = vtxPrev
*/
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtxPrev));
brw_inst_set_pred_control(p->devinfo, brw_last_inst,
BRW_PREDICATE_NORMAL);
brw_clip_interp_vertex(c, vtxOut, vtxPrev, vtx, c->reg.t, false);
/* *outlist_ptr++ = vtxOut;
* nr_verts++;
* vtxOut = 0;
*/
brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
}
brw_ENDIF(p);
}
brw_ELSE(p);
{
/* *outlist_ptr++ = vtxPrev;
* nr_verts++;
*/
brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxPrev));
brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
load_clip_distance(c, vtx, c->reg.dp, hpos_offset, BRW_CONDITIONAL_L);
/* (next < 0.0f)
*/
brw_IF(p, BRW_EXECUTE_1);
{
/* Going out of bounds. Avoid division by zero as we
* know dp != dpPrev from DIFFERENT_SIGNS, above.
*/
brw_ADD(p, c->reg.t, c->reg.dp, negate(c->reg.dpPrev));
brw_math_invert(p, c->reg.t, c->reg.t);
brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp);
/* If (vtxOut == 0) vtxOut = vtx
*/
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtx));
brw_inst_set_pred_control(p->devinfo, brw_last_inst,
BRW_PREDICATE_NORMAL);
brw_clip_interp_vertex(c, vtxOut, vtx, vtxPrev, c->reg.t, true);
/* *outlist_ptr++ = vtxOut;
* nr_verts++;
* vtxOut = 0;
*/
brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
}
brw_ENDIF(p);
}
brw_ENDIF(p);
/* vtxPrev = vtx;
* inlist_ptr++;
*/
brw_MOV(p, get_addr_reg(vtxPrev), get_addr_reg(vtx));
brw_ADD(p, get_addr_reg(inlist_ptr), get_addr_reg(inlist_ptr), brw_imm_uw(sizeof(short)));
/* while (--loopcount != 0)
*/
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
}
brw_WHILE(p);
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
/* vtxPrev = *(outlist_ptr-1) OR: outlist[nr_verts-1]
* inlist = outlist
* inlist_ptr = &inlist[0]
* outlist_ptr = &outlist[0]
*/
brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_w(-2));
brw_MOV(p, get_addr_reg(vtxPrev), deref_1uw(outlist_ptr, 0));
brw_MOV(p, brw_vec8_grf(c->reg.inlist.nr, 0), brw_vec8_grf(c->reg.outlist.nr, 0));
brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
}
brw_ENDIF(p);
/* plane_ptr++;
*/
brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));
/* nr_verts >= 3
*/
brw_CMP(p,
vec1(brw_null_reg()),
BRW_CONDITIONAL_GE,
c->reg.nr_verts,
brw_imm_ud(3));
brw_set_default_predicate_control(p, BRW_PREDICATE_NORMAL);
/* && (planemask>>=1) != 0
*/
brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
brw_SHR(p, c->reg.vertex_src_mask, c->reg.vertex_src_mask, brw_imm_ud(1));
brw_ADD(p, c->reg.clipdistance_offset, c->reg.clipdistance_offset, brw_imm_w(sizeof(float)));
}
brw_WHILE(p);
brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
}
void brw_clip_tri_emit_polygon(struct brw_clip_compile *c)
{
struct brw_codegen *p = &c->func;
/* for (loopcount = nr_verts-2; loopcount > 0; loopcount--)
*/
brw_ADD(p,
c->reg.loopcount,
c->reg.nr_verts,
brw_imm_d(-2));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_G);
brw_IF(p, BRW_EXECUTE_1);
{
struct brw_indirect v0 = brw_indirect(0, 0);
struct brw_indirect vptr = brw_indirect(1, 0);
brw_MOV(p, get_addr_reg(vptr), brw_address(c->reg.inlist));
brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT)
| URB_WRITE_PRIM_START));
brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
brw_DO(p, BRW_EXECUTE_1);
{
brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
(_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT));
brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
}
brw_WHILE(p);
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
brw_clip_emit_vue(c, v0, BRW_URB_WRITE_EOT_COMPLETE,
((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT)
| URB_WRITE_PRIM_END));
}
brw_ENDIF(p);
}
static void do_clip_tri( struct brw_clip_compile *c )
{
brw_clip_init_planes(c);
brw_clip_tri(c);
}
static void maybe_do_clip_tri( struct brw_clip_compile *c )
{
struct brw_codegen *p = &c->func;
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
brw_IF(p, BRW_EXECUTE_1);
{
do_clip_tri(c);
}
brw_ENDIF(p);
}
static void brw_clip_test( struct brw_clip_compile *c )
{
struct brw_reg t = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
struct brw_reg t1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
struct brw_reg t2 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
struct brw_reg t3 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
struct brw_reg v0 = get_tmp(c);
struct brw_reg v1 = get_tmp(c);
struct brw_reg v2 = get_tmp(c);
struct brw_indirect vt0 = brw_indirect(0, 0);
struct brw_indirect vt1 = brw_indirect(1, 0);
struct brw_indirect vt2 = brw_indirect(2, 0);
struct brw_codegen *p = &c->func;
struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
GLuint hpos_offset = brw_varying_to_offset(&c->vue_map,
VARYING_SLOT_POS);
brw_MOV(p, get_addr_reg(vt0), brw_address(c->reg.vertex[0]));
brw_MOV(p, get_addr_reg(vt1), brw_address(c->reg.vertex[1]));
brw_MOV(p, get_addr_reg(vt2), brw_address(c->reg.vertex[2]));
brw_MOV(p, v0, deref_4f(vt0, hpos_offset));
brw_MOV(p, v1, deref_4f(vt1, hpos_offset));
brw_MOV(p, v2, deref_4f(vt2, hpos_offset));
brw_AND(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(~0x3f));
/* test nearz, xmin, ymin plane */
/* clip.xyz < -clip.w */
brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, negate(get_element(v0, 3)));
brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, negate(get_element(v1, 3)));
brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, negate(get_element(v2, 3)));
/* All vertices are outside of a plane, rejected */
brw_AND(p, t, t1, t2);
brw_AND(p, t, t, t3);
brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
brw_OR(p, tmp0, tmp0, get_element(t, 2));
brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
brw_IF(p, BRW_EXECUTE_1);
{
brw_clip_kill_thread(c);
}
brw_ENDIF(p);
brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
/* some vertices are inside a plane, some are outside,need to clip */
brw_XOR(p, t, t1, t2);
brw_XOR(p, t1, t2, t3);
brw_OR(p, t, t, t1);
brw_AND(p, t, t, brw_imm_ud(0x1));
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 0), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<5)));
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 1), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<3)));
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 2), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<1)));
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
/* test farz, xmax, ymax plane */
/* clip.xyz > clip.w */
brw_CMP(p, t1, BRW_CONDITIONAL_G, v0, get_element(v0, 3));
brw_CMP(p, t2, BRW_CONDITIONAL_G, v1, get_element(v1, 3));
brw_CMP(p, t3, BRW_CONDITIONAL_G, v2, get_element(v2, 3));
/* All vertices are outside of a plane, rejected */
brw_AND(p, t, t1, t2);
brw_AND(p, t, t, t3);
brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
brw_OR(p, tmp0, tmp0, get_element(t, 2));
brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
brw_IF(p, BRW_EXECUTE_1);
{
brw_clip_kill_thread(c);
}
brw_ENDIF(p);
brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
/* some vertices are inside a plane, some are outside,need to clip */
brw_XOR(p, t, t1, t2);
brw_XOR(p, t1, t2, t3);
brw_OR(p, t, t, t1);
brw_AND(p, t, t, brw_imm_ud(0x1));
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 0), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4)));
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 1), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2)));
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
get_element(t, 2), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0)));
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
release_tmps(c);
}
void brw_emit_tri_clip( struct brw_clip_compile *c )
{
struct brw_codegen *p = &c->func;
brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
brw_clip_tri_init_vertices(c);
brw_clip_init_clipmask(c);
brw_clip_init_ff_sync(c);
/* if -ve rhw workaround bit is set,
do cliptest */
if (p->devinfo->has_negative_rhw_bug) {
brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
brw_imm_ud(1<<20));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
brw_IF(p, BRW_EXECUTE_1);
{
brw_clip_test(c);
}
brw_ENDIF(p);
}
/* Can't push into do_clip_tri because with polygon (or quad)
* flatshading, need to apply the flatshade here because we don't
* respect the PV when converting to trifan for emit:
*/
if (c->key.contains_flat_varying)
brw_clip_tri_flat_shade(c);
if ((c->key.clip_mode == BRW_CLIP_MODE_NORMAL) ||
(c->key.clip_mode == BRW_CLIP_MODE_KERNEL_CLIP))
do_clip_tri(c);
else
maybe_do_clip_tri(c);
brw_clip_tri_emit_polygon(c);
/* Send an empty message to kill the thread:
*/
brw_clip_kill_thread(c);
}
-528
View File
@@ -1,528 +0,0 @@
/*
Copyright (C) Intel Corp. 2006. All Rights Reserved.
Intel funded Tungsten Graphics to
develop this 3D driver.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**********************************************************************/
/*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#include "brw_clip.h"
#include "brw_prim.h"
/* This is performed against the original triangles, so no indirection
* required:
BZZZT!
*/
static void compute_tri_direction( struct brw_clip_compile *c )
{
struct brw_codegen *p = &c->func;
struct brw_reg e = c->reg.tmp0;
struct brw_reg f = c->reg.tmp1;
GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
struct brw_reg v0 = byte_offset(c->reg.vertex[0], hpos_offset);
struct brw_reg v1 = byte_offset(c->reg.vertex[1], hpos_offset);
struct brw_reg v2 = byte_offset(c->reg.vertex[2], hpos_offset);
struct brw_reg v0n = get_tmp(c);
struct brw_reg v1n = get_tmp(c);
struct brw_reg v2n = get_tmp(c);
/* Convert to NDC.
* NOTE: We can't modify the original vertex coordinates,
* as it may impact further operations.
* So, we have to keep normalized coordinates in temp registers.
*
* TBD-KC
* Try to optimize unnecessary MOV's.
*/
brw_MOV(p, v0n, v0);
brw_MOV(p, v1n, v1);
brw_MOV(p, v2n, v2);
brw_clip_project_position(c, v0n);
brw_clip_project_position(c, v1n);
brw_clip_project_position(c, v2n);
/* Calculate the vectors of two edges of the triangle:
*/
brw_ADD(p, e, v0n, negate(v2n));
brw_ADD(p, f, v1n, negate(v2n));
/* Take their crossproduct:
*/
brw_set_default_access_mode(p, BRW_ALIGN_16);
brw_MUL(p, vec4(brw_null_reg()), brw_swizzle(e, BRW_SWIZZLE_YZXW),
brw_swizzle(f, BRW_SWIZZLE_ZXYW));
brw_MAC(p, vec4(e), negate(brw_swizzle(e, BRW_SWIZZLE_ZXYW)),
brw_swizzle(f, BRW_SWIZZLE_YZXW));
brw_set_default_access_mode(p, BRW_ALIGN_1);
brw_MUL(p, c->reg.dir, c->reg.dir, vec4(e));
}
static void cull_direction( struct brw_clip_compile *c )
{
struct brw_codegen *p = &c->func;
GLuint conditional;
assert (!(c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL &&
c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL));
if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL)
conditional = BRW_CONDITIONAL_GE;
else
conditional = BRW_CONDITIONAL_L;
brw_CMP(p,
vec1(brw_null_reg()),
conditional,
get_element(c->reg.dir, 2),
brw_imm_f(0));
brw_IF(p, BRW_EXECUTE_1);
{
brw_clip_kill_thread(c);
}
brw_ENDIF(p);
}
static void copy_bfc( struct brw_clip_compile *c )
{
struct brw_codegen *p = &c->func;
GLuint conditional;
/* Do we have any colors to copy?
*/
if (!(brw_clip_have_varying(c, VARYING_SLOT_COL0) &&
brw_clip_have_varying(c, VARYING_SLOT_BFC0)) &&
!(brw_clip_have_varying(c, VARYING_SLOT_COL1) &&
brw_clip_have_varying(c, VARYING_SLOT_BFC1)))
return;
/* In some weird degenerate cases we can end up testing the
* direction twice, once for culling and once for bfc copying. Oh
* well, that's what you get for setting weird GL state.
*/
if (c->key.copy_bfc_ccw)
conditional = BRW_CONDITIONAL_GE;
else
conditional = BRW_CONDITIONAL_L;
brw_CMP(p,
vec1(brw_null_reg()),
conditional,
get_element(c->reg.dir, 2),
brw_imm_f(0));
brw_IF(p, BRW_EXECUTE_1);
{
GLuint i;
for (i = 0; i < 3; i++) {
if (brw_clip_have_varying(c, VARYING_SLOT_COL0) &&
brw_clip_have_varying(c, VARYING_SLOT_BFC0))
brw_MOV(p,
byte_offset(c->reg.vertex[i],
brw_varying_to_offset(&c->vue_map,
VARYING_SLOT_COL0)),
byte_offset(c->reg.vertex[i],
brw_varying_to_offset(&c->vue_map,
VARYING_SLOT_BFC0)));
if (brw_clip_have_varying(c, VARYING_SLOT_COL1) &&
brw_clip_have_varying(c, VARYING_SLOT_BFC1))
brw_MOV(p,
byte_offset(c->reg.vertex[i],
brw_varying_to_offset(&c->vue_map,
VARYING_SLOT_COL1)),
byte_offset(c->reg.vertex[i],
brw_varying_to_offset(&c->vue_map,
VARYING_SLOT_BFC1)));
}
}
brw_ENDIF(p);
}
/*
GLfloat iz = 1.0 / dir.z;
GLfloat ac = dir.x * iz;
GLfloat bc = dir.y * iz;
offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE;
offset += MAX2( abs(ac), abs(bc) ) * ctx->Polygon.OffsetFactor;
if (ctx->Polygon.OffsetClamp && isfinite(ctx->Polygon.OffsetClamp)) {
if (ctx->Polygon.OffsetClamp < 0)
offset = MAX2( offset, ctx->Polygon.OffsetClamp );
else
offset = MIN2( offset, ctx->Polygon.OffsetClamp );
}
offset *= MRD;
*/
static void compute_offset( struct brw_clip_compile *c )
{
struct brw_codegen *p = &c->func;
struct brw_reg off = c->reg.offset;
struct brw_reg dir = c->reg.dir;
brw_math_invert(p, get_element(off, 2), get_element(dir, 2));
brw_MUL(p, vec2(off), vec2(dir), get_element(off, 2));
brw_CMP(p,
vec1(brw_null_reg()),
BRW_CONDITIONAL_GE,
brw_abs(get_element(off, 0)),
brw_abs(get_element(off, 1)));
brw_SEL(p, vec1(off),
brw_abs(get_element(off, 0)), brw_abs(get_element(off, 1)));
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
brw_MUL(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_factor));
brw_ADD(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_units));
if (c->key.offset_clamp && isfinite(c->key.offset_clamp)) {
brw_CMP(p,
vec1(brw_null_reg()),
c->key.offset_clamp < 0 ? BRW_CONDITIONAL_GE : BRW_CONDITIONAL_L,
vec1(off),
brw_imm_f(c->key.offset_clamp));
brw_SEL(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_clamp));
}
}
static void merge_edgeflags( struct brw_clip_compile *c )
{
struct brw_codegen *p = &c->func;
struct brw_reg tmp0 = get_element_ud(c->reg.tmp0, 0);
brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
brw_CMP(p,
vec1(brw_null_reg()),
BRW_CONDITIONAL_EQ,
tmp0,
brw_imm_ud(_3DPRIM_POLYGON));
/* Get away with using reg.vertex because we know that this is not
* a _3DPRIM_TRISTRIP_REVERSE:
*/
brw_IF(p, BRW_EXECUTE_1);
{
brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<8));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_EQ);
brw_MOV(p, byte_offset(c->reg.vertex[0],
brw_varying_to_offset(&c->vue_map,
VARYING_SLOT_EDGE)),
brw_imm_f(0));
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<9));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_EQ);
brw_MOV(p, byte_offset(c->reg.vertex[2],
brw_varying_to_offset(&c->vue_map,
VARYING_SLOT_EDGE)),
brw_imm_f(0));
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
}
brw_ENDIF(p);
}
static void apply_one_offset( struct brw_clip_compile *c,
struct brw_indirect vert )
{
struct brw_codegen *p = &c->func;
GLuint ndc_offset = brw_varying_to_offset(&c->vue_map,
BRW_VARYING_SLOT_NDC);
struct brw_reg z = deref_1f(vert, ndc_offset +
2 * type_sz(BRW_REGISTER_TYPE_F));
brw_ADD(p, z, z, vec1(c->reg.offset));
}
/***********************************************************************
* Output clipped polygon as an unfilled primitive:
*/
static void emit_lines(struct brw_clip_compile *c,
bool do_offset)
{
struct brw_codegen *p = &c->func;
struct brw_indirect v0 = brw_indirect(0, 0);
struct brw_indirect v1 = brw_indirect(1, 0);
struct brw_indirect v0ptr = brw_indirect(2, 0);
struct brw_indirect v1ptr = brw_indirect(3, 0);
/* Need a separate loop for offset:
*/
if (do_offset) {
brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
brw_DO(p, BRW_EXECUTE_1);
{
brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
apply_one_offset(c, v0);
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_G);
}
brw_WHILE(p);
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
}
/* v1ptr = &inlist[nr_verts]
* *v1ptr = v0
*/
brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v0ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v1ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
brw_MOV(p, deref_1uw(v1ptr, 0), deref_1uw(v0ptr, 0));
brw_DO(p, BRW_EXECUTE_1);
{
brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
brw_MOV(p, get_addr_reg(v1), deref_1uw(v0ptr, 2));
brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
/* draw edge if edgeflag != 0 */
brw_CMP(p,
vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,
deref_1f(v0, brw_varying_to_offset(&c->vue_map,
VARYING_SLOT_EDGE)),
brw_imm_f(0));
brw_IF(p, BRW_EXECUTE_1);
{
brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
(_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
| URB_WRITE_PRIM_START);
brw_clip_emit_vue(c, v1, BRW_URB_WRITE_ALLOCATE_COMPLETE,
(_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
| URB_WRITE_PRIM_END);
}
brw_ENDIF(p);
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
}
brw_WHILE(p);
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
}
static void emit_points(struct brw_clip_compile *c,
bool do_offset )
{
struct brw_codegen *p = &c->func;
struct brw_indirect v0 = brw_indirect(0, 0);
struct brw_indirect v0ptr = brw_indirect(2, 0);
brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
brw_DO(p, BRW_EXECUTE_1);
{
brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
/* draw if edgeflag != 0
*/
brw_CMP(p,
vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,
deref_1f(v0, brw_varying_to_offset(&c->vue_map,
VARYING_SLOT_EDGE)),
brw_imm_f(0));
brw_IF(p, BRW_EXECUTE_1);
{
if (do_offset)
apply_one_offset(c, v0);
brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
(_3DPRIM_POINTLIST << URB_WRITE_PRIM_TYPE_SHIFT)
| URB_WRITE_PRIM_START | URB_WRITE_PRIM_END);
}
brw_ENDIF(p);
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
}
brw_WHILE(p);
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
}
static void emit_primitives( struct brw_clip_compile *c,
GLuint mode,
bool do_offset )
{
switch (mode) {
case BRW_CLIP_FILL_MODE_FILL:
brw_clip_tri_emit_polygon(c);
break;
case BRW_CLIP_FILL_MODE_LINE:
emit_lines(c, do_offset);
break;
case BRW_CLIP_FILL_MODE_POINT:
emit_points(c, do_offset);
break;
case BRW_CLIP_FILL_MODE_CULL:
unreachable("not reached");
}
}
static void emit_unfilled_primitives( struct brw_clip_compile *c )
{
struct brw_codegen *p = &c->func;
/* Direction culling has already been done.
*/
if (c->key.fill_ccw != c->key.fill_cw &&
c->key.fill_ccw != BRW_CLIP_FILL_MODE_CULL &&
c->key.fill_cw != BRW_CLIP_FILL_MODE_CULL)
{
brw_CMP(p,
vec1(brw_null_reg()),
BRW_CONDITIONAL_GE,
get_element(c->reg.dir, 2),
brw_imm_f(0));
brw_IF(p, BRW_EXECUTE_1);
{
emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);
}
brw_ELSE(p);
{
emit_primitives(c, c->key.fill_cw, c->key.offset_cw);
}
brw_ENDIF(p);
}
else if (c->key.fill_cw != BRW_CLIP_FILL_MODE_CULL) {
emit_primitives(c, c->key.fill_cw, c->key.offset_cw);
}
else if (c->key.fill_ccw != BRW_CLIP_FILL_MODE_CULL) {
emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);
}
}
static void check_nr_verts( struct brw_clip_compile *c )
{
struct brw_codegen *p = &c->func;
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.nr_verts, brw_imm_d(3));
brw_IF(p, BRW_EXECUTE_1);
{
brw_clip_kill_thread(c);
}
brw_ENDIF(p);
}
void brw_emit_unfilled_clip( struct brw_clip_compile *c )
{
struct brw_codegen *p = &c->func;
c->need_direction = ((c->key.offset_ccw || c->key.offset_cw) ||
(c->key.fill_ccw != c->key.fill_cw) ||
c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL ||
c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL ||
c->key.copy_bfc_cw ||
c->key.copy_bfc_ccw);
brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
brw_clip_tri_init_vertices(c);
brw_clip_init_ff_sync(c);
assert(brw_clip_have_varying(c, VARYING_SLOT_EDGE));
if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL &&
c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL) {
brw_clip_kill_thread(c);
return;
}
merge_edgeflags(c);
/* Need to use the inlist indirection here:
*/
if (c->need_direction)
compute_tri_direction(c);
if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL ||
c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL)
cull_direction(c);
if (c->key.offset_ccw ||
c->key.offset_cw)
compute_offset(c);
if (c->key.copy_bfc_ccw ||
c->key.copy_bfc_cw)
copy_bfc(c);
/* Need to do this whether we clip or not:
*/
if (c->key.contains_flat_varying)
brw_clip_tri_flat_shade(c);
brw_clip_init_clipmask(c);
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
brw_IF(p, BRW_EXECUTE_1);
{
brw_clip_init_planes(c);
brw_clip_tri(c);
check_nr_verts(c);
}
brw_ENDIF(p);
emit_unfilled_primitives(c);
brw_clip_kill_thread(c);
}
-464
View File
@@ -1,464 +0,0 @@
/*
Copyright (C) Intel Corp. 2006. All Rights Reserved.
Intel funded Tungsten Graphics to
develop this 3D driver.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**********************************************************************/
/*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#include "brw_clip.h"
struct brw_reg get_tmp( struct brw_clip_compile *c )
{
struct brw_reg tmp = brw_vec4_grf(c->last_tmp, 0);
if (++c->last_tmp > c->prog_data.total_grf)
c->prog_data.total_grf = c->last_tmp;
return tmp;
}
static void release_tmp( struct brw_clip_compile *c, struct brw_reg tmp )
{
if (tmp.nr == c->last_tmp-1)
c->last_tmp--;
}
static struct brw_reg make_plane_ud(GLuint x, GLuint y, GLuint z, GLuint w)
{
return brw_imm_ud((w<<24) | (z<<16) | (y<<8) | x);
}
void brw_clip_init_planes( struct brw_clip_compile *c )
{
struct brw_codegen *p = &c->func;
if (!c->key.nr_userclip) {
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 0), make_plane_ud( 0, 0, 0xff, 1));
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 1), make_plane_ud( 0, 0, 1, 1));
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 2), make_plane_ud( 0, 0xff, 0, 1));
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 3), make_plane_ud( 0, 1, 0, 1));
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 4), make_plane_ud(0xff, 0, 0, 1));
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 5), make_plane_ud( 1, 0, 0, 1));
}
}
#define W 3
/* Project 'pos' to screen space (or back again), overwrite with results:
*/
void brw_clip_project_position(struct brw_clip_compile *c, struct brw_reg pos )
{
struct brw_codegen *p = &c->func;
/* calc rhw
*/
brw_math_invert(p, get_element(pos, W), get_element(pos, W));
/* value.xyz *= value.rhw
*/
brw_set_default_access_mode(p, BRW_ALIGN_16);
brw_MUL(p, brw_writemask(pos, WRITEMASK_XYZ), pos,
brw_swizzle(pos, BRW_SWIZZLE_WWWW));
brw_set_default_access_mode(p, BRW_ALIGN_1);
}
static void brw_clip_project_vertex( struct brw_clip_compile *c,
struct brw_indirect vert_addr )
{
struct brw_codegen *p = &c->func;
struct brw_reg tmp = get_tmp(c);
GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
GLuint ndc_offset = brw_varying_to_offset(&c->vue_map,
BRW_VARYING_SLOT_NDC);
/* Fixup position. Extract from the original vertex and re-project
* to screen space:
*/
brw_MOV(p, tmp, deref_4f(vert_addr, hpos_offset));
brw_clip_project_position(c, tmp);
brw_MOV(p, deref_4f(vert_addr, ndc_offset), tmp);
release_tmp(c, tmp);
}
/* Interpolate between two vertices and put the result into a0.0.
* Increment a0.0 accordingly.
*
* Beware that dest_ptr can be equal to v0_ptr!
*/
void brw_clip_interp_vertex( struct brw_clip_compile *c,
struct brw_indirect dest_ptr,
struct brw_indirect v0_ptr, /* from */
struct brw_indirect v1_ptr, /* to */
struct brw_reg t0,
bool force_edgeflag)
{
struct brw_codegen *p = &c->func;
struct brw_reg t_nopersp, v0_ndc_copy;
GLuint slot;
/* Just copy the vertex header:
*/
/*
* After CLIP stage, only first 256 bits of the VUE are read
* back on Ironlake, so needn't change it
*/
brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1);
/* First handle the 3D and NDC interpolation, in case we
* need noperspective interpolation. Doing it early has no
* performance impact in any case.
*/
/* Take a copy of the v0 NDC coordinates, in case dest == v0. */
if (c->key.contains_noperspective_varying) {
GLuint offset = brw_varying_to_offset(&c->vue_map,
BRW_VARYING_SLOT_NDC);
v0_ndc_copy = get_tmp(c);
brw_MOV(p, v0_ndc_copy, deref_4f(v0_ptr, offset));
}
/* Compute the new 3D position
*
* dest_hpos = v0_hpos * (1 - t0) + v1_hpos * t0
*/
{
GLuint delta = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
struct brw_reg tmp = get_tmp(c);
brw_MUL(p, vec4(brw_null_reg()), deref_4f(v1_ptr, delta), t0);
brw_MAC(p, tmp, negate(deref_4f(v0_ptr, delta)), t0);
brw_ADD(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta), tmp);
release_tmp(c, tmp);
}
/* Recreate the projected (NDC) coordinate in the new vertex header */
brw_clip_project_vertex(c, dest_ptr);
/* If we have noperspective attributes,
* we need to compute the screen-space t
*/
if (c->key.contains_noperspective_varying) {
GLuint delta = brw_varying_to_offset(&c->vue_map,
BRW_VARYING_SLOT_NDC);
struct brw_reg tmp = get_tmp(c);
t_nopersp = get_tmp(c);
/* t_nopersp = vec4(v1.xy, dest.xy) */
brw_MOV(p, t_nopersp, deref_4f(v1_ptr, delta));
brw_MOV(p, tmp, deref_4f(dest_ptr, delta));
brw_set_default_access_mode(p, BRW_ALIGN_16);
brw_MOV(p,
brw_writemask(t_nopersp, WRITEMASK_ZW),
brw_swizzle(tmp, BRW_SWIZZLE_XYXY));
/* t_nopersp = vec4(v1.xy, dest.xy) - v0.xyxy */
brw_ADD(p, t_nopersp, t_nopersp,
negate(brw_swizzle(v0_ndc_copy, BRW_SWIZZLE_XYXY)));
/* Add the absolute values of the X and Y deltas so that if
* the points aren't in the same place on the screen we get
* nonzero values to divide.
*
* After that, we have vert1 - vert0 in t_nopersp.x and
* vertnew - vert0 in t_nopersp.y
*
* t_nopersp = vec2(|v1.x -v0.x| + |v1.y -v0.y|,
* |dest.x-v0.x| + |dest.y-v0.y|)
*/
brw_ADD(p,
brw_writemask(t_nopersp, WRITEMASK_XY),
brw_abs(brw_swizzle(t_nopersp, BRW_SWIZZLE_XZXZ)),
brw_abs(brw_swizzle(t_nopersp, BRW_SWIZZLE_YWYW)));
brw_set_default_access_mode(p, BRW_ALIGN_1);
/* If the points are in the same place, just substitute a
* value to avoid divide-by-zero
*/
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ,
vec1(t_nopersp),
brw_imm_f(0));
brw_IF(p, BRW_EXECUTE_1);
brw_MOV(p, t_nopersp, brw_imm_vf4(brw_float_to_vf(1.0),
brw_float_to_vf(0.0),
brw_float_to_vf(0.0),
brw_float_to_vf(0.0)));
brw_ENDIF(p);
/* Now compute t_nopersp = t_nopersp.y/t_nopersp.x and broadcast it. */
brw_math_invert(p, get_element(t_nopersp, 0), get_element(t_nopersp, 0));
brw_MUL(p, vec1(t_nopersp), vec1(t_nopersp),
vec1(suboffset(t_nopersp, 1)));
brw_set_default_access_mode(p, BRW_ALIGN_16);
brw_MOV(p, t_nopersp, brw_swizzle(t_nopersp, BRW_SWIZZLE_XXXX));
brw_set_default_access_mode(p, BRW_ALIGN_1);
release_tmp(c, tmp);
release_tmp(c, v0_ndc_copy);
}
/* Now we can iterate over each attribute
* (could be done in pairs?)
*/
for (slot = 0; slot < c->vue_map.num_slots; slot++) {
int varying = c->vue_map.slot_to_varying[slot];
GLuint delta = brw_vue_slot_to_offset(slot);
/* HPOS, NDC already handled above */
if (varying == VARYING_SLOT_POS || varying == BRW_VARYING_SLOT_NDC)
continue;
if (varying == VARYING_SLOT_EDGE) {
if (force_edgeflag)
brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1));
else
brw_MOV(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta));
} else if (varying == VARYING_SLOT_PSIZ) {
/* PSIZ doesn't need interpolation because it isn't used by the
* fragment shader.
*/
} else if (varying < VARYING_SLOT_MAX) {
/* This is a true vertex result (and not a special value for the VUE
* header), so interpolate:
*
* New = attr0 + t*attr1 - t*attr0
*
* Unless the attribute is flat shaded -- in which case just copy
* from one of the sources (doesn't matter which; already copied from pv)
*/
GLuint interp = c->key.interp_mode[slot];
if (interp != INTERP_MODE_FLAT) {
struct brw_reg tmp = get_tmp(c);
struct brw_reg t =
interp == INTERP_MODE_NOPERSPECTIVE ? t_nopersp : t0;
brw_MUL(p,
vec4(brw_null_reg()),
deref_4f(v1_ptr, delta),
t);
brw_MAC(p,
tmp,
negate(deref_4f(v0_ptr, delta)),
t);
brw_ADD(p,
deref_4f(dest_ptr, delta),
deref_4f(v0_ptr, delta),
tmp);
release_tmp(c, tmp);
}
else {
brw_MOV(p,
deref_4f(dest_ptr, delta),
deref_4f(v0_ptr, delta));
}
}
}
if (c->vue_map.num_slots % 2) {
GLuint delta = brw_vue_slot_to_offset(c->vue_map.num_slots);
brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0));
}
if (c->key.contains_noperspective_varying)
release_tmp(c, t_nopersp);
}
void brw_clip_emit_vue(struct brw_clip_compile *c,
struct brw_indirect vert,
enum brw_urb_write_flags flags,
GLuint header)
{
struct brw_codegen *p = &c->func;
bool allocate = flags & BRW_URB_WRITE_ALLOCATE;
brw_clip_ff_sync(c);
/* Any URB entry that is allocated must subsequently be used or discarded,
* so it doesn't make sense to mark EOT and ALLOCATE at the same time.
*/
assert(!(allocate && (flags & BRW_URB_WRITE_EOT)));
/* Copy the vertex from vertn into m1..mN+1:
*/
brw_copy_from_indirect(p, brw_message_reg(1), vert, c->nr_regs);
/* Overwrite PrimType and PrimStart in the message header, for
* each vertex in turn:
*/
brw_MOV(p, get_element_ud(c->reg.R0, 2), brw_imm_ud(header));
/* Send each vertex as a separate write to the urb. This
* is different to the concept in brw_sf_emit.c, where
* subsequent writes are used to build up a single urb
* entry. Each of these writes instantiates a separate
* urb entry - (I think... what about 'allocate'?)
*/
brw_urb_WRITE(p,
allocate ? c->reg.R0 : retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
0,
c->reg.R0,
flags,
c->nr_regs + 1, /* msg length */
allocate ? 1 : 0, /* response_length */
0, /* urb offset */
BRW_URB_SWIZZLE_NONE);
}
void brw_clip_kill_thread(struct brw_clip_compile *c)
{
struct brw_codegen *p = &c->func;
brw_clip_ff_sync(c);
/* Send an empty message to kill the thread and release any
* allocated urb entry:
*/
brw_urb_WRITE(p,
retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
0,
c->reg.R0,
BRW_URB_WRITE_UNUSED | BRW_URB_WRITE_EOT_COMPLETE,
1, /* msg len */
0, /* response len */
0,
BRW_URB_SWIZZLE_NONE);
}
struct brw_reg brw_clip_plane0_address( struct brw_clip_compile *c )
{
return brw_address(c->reg.fixed_planes);
}
struct brw_reg brw_clip_plane_stride( struct brw_clip_compile *c )
{
if (c->key.nr_userclip) {
return brw_imm_uw(16);
}
else {
return brw_imm_uw(4);
}
}
/* Distribute flatshaded attributes from provoking vertex prior to
* clipping.
*/
void brw_clip_copy_flatshaded_attributes( struct brw_clip_compile *c,
GLuint to, GLuint from )
{
struct brw_codegen *p = &c->func;
for (int i = 0; i < c->vue_map.num_slots; i++) {
if (c->key.interp_mode[i] == INTERP_MODE_FLAT) {
brw_MOV(p,
byte_offset(c->reg.vertex[to], brw_vue_slot_to_offset(i)),
byte_offset(c->reg.vertex[from], brw_vue_slot_to_offset(i)));
}
}
}
void brw_clip_init_clipmask( struct brw_clip_compile *c )
{
struct brw_codegen *p = &c->func;
struct brw_reg incoming = get_element_ud(c->reg.R0, 2);
/* Shift so that lowest outcode bit is rightmost:
*/
brw_SHR(p, c->reg.planemask, incoming, brw_imm_ud(26));
if (c->key.nr_userclip) {
struct brw_reg tmp = retype(vec1(get_tmp(c)), BRW_REGISTER_TYPE_UD);
/* Rearrange userclip outcodes so that they come directly after
* the fixed plane bits.
*/
if (p->devinfo->ver == 5 || p->devinfo->verx10 == 45)
brw_AND(p, tmp, incoming, brw_imm_ud(0xff<<14));
else
brw_AND(p, tmp, incoming, brw_imm_ud(0x3f<<14));
brw_SHR(p, tmp, tmp, brw_imm_ud(8));
brw_OR(p, c->reg.planemask, c->reg.planemask, tmp);
release_tmp(c, tmp);
}
}
void brw_clip_ff_sync(struct brw_clip_compile *c)
{
struct brw_codegen *p = &c->func;
if (p->devinfo->ver == 5) {
brw_AND(p, brw_null_reg(), c->reg.ff_sync, brw_imm_ud(0x1));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_Z);
brw_IF(p, BRW_EXECUTE_1);
{
brw_OR(p, c->reg.ff_sync, c->reg.ff_sync, brw_imm_ud(0x1));
brw_ff_sync(p,
c->reg.R0,
0,
c->reg.R0,
1, /* allocate */
1, /* response length */
0 /* eot */);
}
brw_ENDIF(p);
brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
}
}
void brw_clip_init_ff_sync(struct brw_clip_compile *c)
{
struct brw_codegen *p = &c->func;
if (p->devinfo->ver == 5) {
brw_MOV(p, c->reg.ff_sync, brw_imm_ud(0));
}
}
-97
View File
@@ -1,97 +0,0 @@
/*
* Copyright © 2006 - 2017 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "brw_clip.h"
#include "brw_disasm.h"
#include "dev/intel_debug.h"
const unsigned *
brw_compile_clip(const struct brw_compiler *compiler,
void *mem_ctx,
const struct brw_clip_prog_key *key,
struct brw_clip_prog_data *prog_data,
struct intel_vue_map *vue_map,
unsigned *final_assembly_size)
{
struct brw_clip_compile c;
memset(&c, 0, sizeof(c));
/* Begin the compilation:
*/
brw_init_codegen(&compiler->isa, &c.func, mem_ctx);
c.func.single_program_flow = 1;
c.key = *key;
c.vue_map = *vue_map;
/* nr_regs is the number of registers filled by reading data from the VUE.
* This program accesses the entire VUE, so nr_regs needs to be the size of
* the VUE (measured in pairs, since two slots are stored in each
* register).
*/
c.nr_regs = (c.vue_map.num_slots + 1)/2;
c.prog_data.clip_mode = c.key.clip_mode; /* XXX */
/* For some reason the thread is spawned with only 4 channels
* unmasked.
*/
brw_set_default_mask_control(&c.func, BRW_MASK_DISABLE);
/* Would ideally have the option of producing a program which could
* do all three:
*/
switch (key->primitive) {
case MESA_PRIM_TRIANGLES:
if (key->do_unfilled)
brw_emit_unfilled_clip( &c );
else
brw_emit_tri_clip( &c );
break;
case MESA_PRIM_LINES:
brw_emit_line_clip( &c );
break;
case MESA_PRIM_POINTS:
brw_emit_point_clip( &c );
break;
default:
unreachable("not reached");
}
brw_compact_instructions(&c.func, 0, NULL);
*prog_data = c.prog_data;
const unsigned *program = brw_get_program(&c.func, final_assembly_size);
if (INTEL_DEBUG(DEBUG_CLIP)) {
fprintf(stderr, "clip:\n");
brw_disassemble_with_labels(&compiler->isa,
program, 0, *final_assembly_size, stderr);
fprintf(stderr, "\n");
}
return program;
}
-662
View File
@@ -1,662 +0,0 @@
/*
Copyright (C) Intel Corp. 2006. All Rights Reserved.
Intel funded Tungsten Graphics to
develop this 3D driver.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**********************************************************************/
/*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#include "brw_compiler.h"
#include "brw_disasm.h"
#include "brw_eu.h"
#include "brw_prim.h"
#include "dev/intel_debug.h"
#define MAX_GS_VERTS (4)
struct brw_ff_gs_compile {
struct brw_codegen func;
struct brw_ff_gs_prog_key key;
struct brw_ff_gs_prog_data *prog_data;
struct {
struct brw_reg R0;
/**
* Register holding streamed vertex buffer pointers -- see the Sandy
* Bridge PRM, volume 2 part 1, section 4.4.2 (GS Thread Payload
* [DevSNB]). These pointers are delivered in GRF 1.
*/
struct brw_reg SVBI;
struct brw_reg vertex[MAX_GS_VERTS];
struct brw_reg header;
struct brw_reg temp;
/**
* Register holding destination indices for streamed buffer writes.
* Only used for SOL programs.
*/
struct brw_reg destination_indices;
} reg;
/* Number of registers used to store vertex data */
GLuint nr_regs;
struct intel_vue_map vue_map;
};
/**
* Allocate registers for GS.
*
* If sol_program is true, then:
*
* - The thread will be spawned with the "SVBI Payload Enable" bit set, so GRF
* 1 needs to be set aside to hold the streamed vertex buffer indices.
*
* - The thread will need to use the destination_indices register.
*/
static void brw_ff_gs_alloc_regs(struct brw_ff_gs_compile *c,
GLuint nr_verts,
bool sol_program)
{
GLuint i = 0,j;
/* Register usage is static, precompute here:
*/
c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;
/* Streamed vertex buffer indices */
if (sol_program)
c->reg.SVBI = retype(brw_vec8_grf(i++, 0), BRW_REGISTER_TYPE_UD);
/* Payload vertices plus space for more generated vertices:
*/
for (j = 0; j < nr_verts; j++) {
c->reg.vertex[j] = brw_vec4_grf(i, 0);
i += c->nr_regs;
}
c->reg.header = retype(brw_vec8_grf(i++, 0), BRW_REGISTER_TYPE_UD);
c->reg.temp = retype(brw_vec8_grf(i++, 0), BRW_REGISTER_TYPE_UD);
if (sol_program) {
c->reg.destination_indices =
retype(brw_vec4_grf(i++, 0), BRW_REGISTER_TYPE_UD);
}
c->prog_data->urb_read_length = c->nr_regs;
c->prog_data->total_grf = i;
}
/**
* Set up the initial value of c->reg.header register based on c->reg.R0.
*
* The following information is passed to the GS thread in R0, and needs to be
* included in the first URB_WRITE or FF_SYNC message sent by the GS:
*
* - DWORD 0 [31:0] handle info (Gen4 only)
* - DWORD 5 [7:0] FFTID
* - DWORD 6 [31:0] Debug info
* - DWORD 7 [31:0] Debug info
*
* This function sets up the above data by copying by copying the contents of
* R0 to the header register.
*/
static void brw_ff_gs_initialize_header(struct brw_ff_gs_compile *c)
{
struct brw_codegen *p = &c->func;
brw_MOV(p, c->reg.header, c->reg.R0);
}
/**
* Overwrite DWORD 2 of c->reg.header with the given immediate unsigned value.
*
* In URB_WRITE messages, DWORD 2 contains the fields PrimType, PrimStart,
* PrimEnd, Increment CL_INVOCATIONS, and SONumPrimsWritten, many of which we
* need to be able to update on a per-vertex basis.
*/
static void brw_ff_gs_overwrite_header_dw2(struct brw_ff_gs_compile *c,
unsigned dw2)
{
struct brw_codegen *p = &c->func;
brw_MOV(p, get_element_ud(c->reg.header, 2), brw_imm_ud(dw2));
}
/**
* Overwrite DWORD 2 of c->reg.header with the primitive type from c->reg.R0.
*
* When the thread is spawned, GRF 0 contains the primitive type in bits 4:0
* of DWORD 2. URB_WRITE messages need the primitive type in bits 6:2 of
* DWORD 2. So this function extracts the primitive type field, bitshifts it
* appropriately, and stores it in c->reg.header.
*/
static void brw_ff_gs_overwrite_header_dw2_from_r0(struct brw_ff_gs_compile *c)
{
struct brw_codegen *p = &c->func;
brw_AND(p, get_element_ud(c->reg.header, 2), get_element_ud(c->reg.R0, 2),
brw_imm_ud(0x1f));
brw_SHL(p, get_element_ud(c->reg.header, 2),
get_element_ud(c->reg.header, 2), brw_imm_ud(2));
}
/**
* Apply an additive offset to DWORD 2 of c->reg.header.
*
* This is used to set/unset the "PrimStart" and "PrimEnd" flags appropriately
* for each vertex.
*/
static void brw_ff_gs_offset_header_dw2(struct brw_ff_gs_compile *c,
int offset)
{
struct brw_codegen *p = &c->func;
brw_ADD(p, get_element_d(c->reg.header, 2), get_element_d(c->reg.header, 2),
brw_imm_d(offset));
}
/**
* Emit a vertex using the URB_WRITE message. Use the contents of
* c->reg.header for the message header, and the registers starting at \c vert
* for the vertex data.
*
* If \c last is true, then this is the last vertex, so no further URB space
* should be allocated, and this message should end the thread.
*
* If \c last is false, then a new URB entry will be allocated, and its handle
* will be stored in DWORD 0 of c->reg.header for use in the next URB_WRITE
* message.
*/
static void brw_ff_gs_emit_vue(struct brw_ff_gs_compile *c,
struct brw_reg vert,
bool last)
{
struct brw_codegen *p = &c->func;
int write_offset = 0;
bool complete = false;
do {
/* We can't write more than 14 registers at a time to the URB */
int write_len = MIN2(c->nr_regs - write_offset, 14);
if (write_len == c->nr_regs - write_offset)
complete = true;
/* Copy the vertex from vertn into m1..mN+1:
*/
brw_copy8(p, brw_message_reg(1), offset(vert, write_offset), write_len);
/* Send the vertex data to the URB. If this is the last write for this
* vertex, then we mark it as complete, and either end the thread or
* allocate another vertex URB entry (depending whether this is the last
* vertex).
*/
enum brw_urb_write_flags flags;
if (!complete)
flags = BRW_URB_WRITE_NO_FLAGS;
else if (last)
flags = BRW_URB_WRITE_EOT_COMPLETE;
else
flags = BRW_URB_WRITE_ALLOCATE_COMPLETE;
brw_urb_WRITE(p,
(flags & BRW_URB_WRITE_ALLOCATE) ? c->reg.temp
: retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
0,
c->reg.header,
flags,
write_len + 1, /* msg length */
(flags & BRW_URB_WRITE_ALLOCATE) ? 1
: 0, /* response length */
write_offset, /* urb offset */
BRW_URB_SWIZZLE_NONE);
write_offset += write_len;
} while (!complete);
if (!last) {
brw_MOV(p, get_element_ud(c->reg.header, 0),
get_element_ud(c->reg.temp, 0));
}
}
/**
* Send an FF_SYNC message to ensure that all previously spawned GS threads
* have finished sending primitives down the pipeline, and to allocate a URB
* entry for the first output vertex. Only needed on Ironlake+.
*
* This function modifies c->reg.header: in DWORD 1, it stores num_prim (which
* is needed by the FF_SYNC message), and in DWORD 0, it stores the handle to
* the allocated URB entry (which will be needed by the URB_WRITE meesage that
* follows).
*/
static void brw_ff_gs_ff_sync(struct brw_ff_gs_compile *c, int num_prim)
{
struct brw_codegen *p = &c->func;
brw_MOV(p, get_element_ud(c->reg.header, 1), brw_imm_ud(num_prim));
brw_ff_sync(p,
c->reg.temp,
0,
c->reg.header,
1, /* allocate */
1, /* response length */
0 /* eot */);
brw_MOV(p, get_element_ud(c->reg.header, 0),
get_element_ud(c->reg.temp, 0));
}
static void
brw_ff_gs_quads(struct brw_ff_gs_compile *c,
const struct brw_ff_gs_prog_key *key)
{
brw_ff_gs_alloc_regs(c, 4, false);
brw_ff_gs_initialize_header(c);
/* Use polygons for correct edgeflag behaviour. Note that vertex 3
* is the PV for quads, but vertex 0 for polygons:
*/
if (c->func.devinfo->ver == 5)
brw_ff_gs_ff_sync(c, 1);
brw_ff_gs_overwrite_header_dw2(
c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT)
| URB_WRITE_PRIM_START));
if (key->pv_first) {
brw_ff_gs_emit_vue(c, c->reg.vertex[0], 0);
brw_ff_gs_overwrite_header_dw2(
c, _3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT);
brw_ff_gs_emit_vue(c, c->reg.vertex[1], 0);
brw_ff_gs_emit_vue(c, c->reg.vertex[2], 0);
brw_ff_gs_overwrite_header_dw2(
c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT)
| URB_WRITE_PRIM_END));
brw_ff_gs_emit_vue(c, c->reg.vertex[3], 1);
}
else {
brw_ff_gs_emit_vue(c, c->reg.vertex[3], 0);
brw_ff_gs_overwrite_header_dw2(
c, _3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT);
brw_ff_gs_emit_vue(c, c->reg.vertex[0], 0);
brw_ff_gs_emit_vue(c, c->reg.vertex[1], 0);
brw_ff_gs_overwrite_header_dw2(
c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT)
| URB_WRITE_PRIM_END));
brw_ff_gs_emit_vue(c, c->reg.vertex[2], 1);
}
}
static void
brw_ff_gs_quad_strip(struct brw_ff_gs_compile *c,
const struct brw_ff_gs_prog_key *key)
{
brw_ff_gs_alloc_regs(c, 4, false);
brw_ff_gs_initialize_header(c);
if (c->func.devinfo->ver == 5)
brw_ff_gs_ff_sync(c, 1);
brw_ff_gs_overwrite_header_dw2(
c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT)
| URB_WRITE_PRIM_START));
if (key->pv_first) {
brw_ff_gs_emit_vue(c, c->reg.vertex[0], 0);
brw_ff_gs_overwrite_header_dw2(
c, _3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT);
brw_ff_gs_emit_vue(c, c->reg.vertex[1], 0);
brw_ff_gs_emit_vue(c, c->reg.vertex[2], 0);
brw_ff_gs_overwrite_header_dw2(
c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT)
| URB_WRITE_PRIM_END));
brw_ff_gs_emit_vue(c, c->reg.vertex[3], 1);
}
else {
brw_ff_gs_emit_vue(c, c->reg.vertex[2], 0);
brw_ff_gs_overwrite_header_dw2(
c, _3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT);
brw_ff_gs_emit_vue(c, c->reg.vertex[3], 0);
brw_ff_gs_emit_vue(c, c->reg.vertex[0], 0);
brw_ff_gs_overwrite_header_dw2(
c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT)
| URB_WRITE_PRIM_END));
brw_ff_gs_emit_vue(c, c->reg.vertex[1], 1);
}
}
static void brw_ff_gs_lines(struct brw_ff_gs_compile *c)
{
brw_ff_gs_alloc_regs(c, 2, false);
brw_ff_gs_initialize_header(c);
if (c->func.devinfo->ver == 5)
brw_ff_gs_ff_sync(c, 1);
brw_ff_gs_overwrite_header_dw2(
c, ((_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
| URB_WRITE_PRIM_START));
brw_ff_gs_emit_vue(c, c->reg.vertex[0], 0);
brw_ff_gs_overwrite_header_dw2(
c, ((_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
| URB_WRITE_PRIM_END));
brw_ff_gs_emit_vue(c, c->reg.vertex[1], 1);
}
/**
* Generate the geometry shader program used on Gen6 to perform stream output
* (transform feedback).
*/
static void
gfx6_sol_program(struct brw_ff_gs_compile *c, const struct brw_ff_gs_prog_key *key,
unsigned num_verts, bool check_edge_flags)
{
struct brw_codegen *p = &c->func;
brw_inst *inst;
c->prog_data->svbi_postincrement_value = num_verts;
brw_ff_gs_alloc_regs(c, num_verts, true);
brw_ff_gs_initialize_header(c);
if (key->num_transform_feedback_bindings > 0) {
unsigned vertex, binding;
struct brw_reg destination_indices_uw =
vec8(retype(c->reg.destination_indices, BRW_REGISTER_TYPE_UW));
/* Note: since we use the binding table to keep track of buffer offsets
* and stride, the GS doesn't need to keep track of a separate pointer
* into each buffer; it uses a single pointer which increments by 1 for
* each vertex. So we use SVBI0 for this pointer, regardless of whether
* transform feedback is in interleaved or separate attribs mode.
*
* Make sure that the buffers have enough room for all the vertices.
*/
brw_ADD(p, get_element_ud(c->reg.temp, 0),
get_element_ud(c->reg.SVBI, 0), brw_imm_ud(num_verts));
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_LE,
get_element_ud(c->reg.temp, 0),
get_element_ud(c->reg.SVBI, 4));
brw_IF(p, BRW_EXECUTE_1);
/* Compute the destination indices to write to. Usually we use SVBI[0]
* + (0, 1, 2). However, for odd-numbered triangles in tristrips, the
* vertices come down the pipeline in reversed winding order, so we need
* to flip the order when writing to the transform feedback buffer. To
* ensure that flatshading accuracy is preserved, we need to write them
* in order SVBI[0] + (0, 2, 1) if we're using the first provoking
* vertex convention, and in order SVBI[0] + (1, 0, 2) if we're using
* the last provoking vertex convention.
*
* Note: since brw_imm_v can only be used in instructions in
* packed-word execution mode, and SVBI is a double-word, we need to
* first move the appropriate immediate constant ((0, 1, 2), (0, 2, 1),
* or (1, 0, 2)) to the destination_indices register, and then add SVBI
* using a separate instruction. Also, since the immediate constant is
* expressed as packed words, and we need to load double-words into
* destination_indices, we need to intersperse zeros to fill the upper
* halves of each double-word.
*/
brw_MOV(p, destination_indices_uw,
brw_imm_v(0x00020100)); /* (0, 1, 2) */
if (num_verts == 3) {
/* Get primitive type into temp register. */
brw_AND(p, get_element_ud(c->reg.temp, 0),
get_element_ud(c->reg.R0, 2), brw_imm_ud(0x1f));
/* Test if primitive type is TRISTRIP_REVERSE. We need to do this as
* an 8-wide comparison so that the conditional MOV that follows
* moves all 8 words correctly.
*/
brw_CMP(p, vec8(brw_null_reg()), BRW_CONDITIONAL_EQ,
get_element_ud(c->reg.temp, 0),
brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE));
/* If so, then overwrite destination_indices_uw with the appropriate
* reordering.
*/
inst = brw_MOV(p, destination_indices_uw,
brw_imm_v(key->pv_first ? 0x00010200 /* (0, 2, 1) */
: 0x00020001)); /* (1, 0, 2) */
brw_inst_set_pred_control(p->devinfo, inst, BRW_PREDICATE_NORMAL);
}
assert(c->reg.destination_indices.width == BRW_EXECUTE_4);
brw_push_insn_state(p);
brw_set_default_exec_size(p, BRW_EXECUTE_4);
brw_ADD(p, c->reg.destination_indices,
c->reg.destination_indices, get_element_ud(c->reg.SVBI, 0));
brw_pop_insn_state(p);
/* For each vertex, generate code to output each varying using the
* appropriate binding table entry.
*/
for (vertex = 0; vertex < num_verts; ++vertex) {
/* Set up the correct destination index for this vertex */
brw_MOV(p, get_element_ud(c->reg.header, 5),
get_element_ud(c->reg.destination_indices, vertex));
for (binding = 0; binding < key->num_transform_feedback_bindings;
++binding) {
unsigned char varying =
key->transform_feedback_bindings[binding];
unsigned char slot = c->vue_map.varying_to_slot[varying];
/* From the Sandybridge PRM, Volume 2, Part 1, Section 4.5.1:
*
* "Prior to End of Thread with a URB_WRITE, the kernel must
* ensure that all writes are complete by sending the final
* write as a committed write."
*/
bool final_write =
binding == key->num_transform_feedback_bindings - 1 &&
vertex == num_verts - 1;
struct brw_reg vertex_slot = c->reg.vertex[vertex];
vertex_slot.nr += slot / 2;
vertex_slot.subnr = (slot % 2) * 16;
/* gl_PointSize is stored in VARYING_SLOT_PSIZ.w. */
vertex_slot.swizzle = varying == VARYING_SLOT_PSIZ
? BRW_SWIZZLE_WWWW : key->transform_feedback_swizzles[binding];
brw_set_default_access_mode(p, BRW_ALIGN_16);
brw_push_insn_state(p);
brw_set_default_exec_size(p, BRW_EXECUTE_4);
brw_MOV(p, stride(c->reg.header, 4, 4, 1),
retype(vertex_slot, BRW_REGISTER_TYPE_UD));
brw_pop_insn_state(p);
brw_set_default_access_mode(p, BRW_ALIGN_1);
brw_svb_write(p,
final_write ? c->reg.temp : brw_null_reg(), /* dest */
1, /* msg_reg_nr */
c->reg.header, /* src0 */
BRW_GFX6_SOL_BINDING_START + binding, /* binding_table_index */
final_write); /* send_commit_msg */
}
}
brw_ENDIF(p);
/* Now, reinitialize the header register from R0 to restore the parts of
* the register that we overwrote while streaming out transform feedback
* data.
*/
brw_ff_gs_initialize_header(c);
/* Finally, wait for the write commit to occur so that we can proceed to
* other things safely.
*
* From the Sandybridge PRM, Volume 4, Part 1, Section 3.3:
*
* The write commit does not modify the destination register, but
* merely clears the dependency associated with the destination
* register. Thus, a simple “mov” instruction using the register as a
* source is sufficient to wait for the write commit to occur.
*/
brw_MOV(p, c->reg.temp, c->reg.temp);
}
brw_ff_gs_ff_sync(c, 1);
brw_ff_gs_overwrite_header_dw2_from_r0(c);
switch (num_verts) {
case 1:
brw_ff_gs_offset_header_dw2(c,
URB_WRITE_PRIM_START | URB_WRITE_PRIM_END);
brw_ff_gs_emit_vue(c, c->reg.vertex[0], true);
break;
case 2:
brw_ff_gs_offset_header_dw2(c, URB_WRITE_PRIM_START);
brw_ff_gs_emit_vue(c, c->reg.vertex[0], false);
brw_ff_gs_offset_header_dw2(c,
URB_WRITE_PRIM_END - URB_WRITE_PRIM_START);
brw_ff_gs_emit_vue(c, c->reg.vertex[1], true);
break;
case 3:
if (check_edge_flags) {
/* Only emit vertices 0 and 1 if this is the first triangle of the
* polygon. Otherwise they are redundant.
*/
brw_AND(p, retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
get_element_ud(c->reg.R0, 2),
brw_imm_ud(BRW_GS_EDGE_INDICATOR_0));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
brw_IF(p, BRW_EXECUTE_1);
}
brw_ff_gs_offset_header_dw2(c, URB_WRITE_PRIM_START);
brw_ff_gs_emit_vue(c, c->reg.vertex[0], false);
brw_ff_gs_offset_header_dw2(c, -URB_WRITE_PRIM_START);
brw_ff_gs_emit_vue(c, c->reg.vertex[1], false);
if (check_edge_flags) {
brw_ENDIF(p);
/* Only emit vertex 2 in PRIM_END mode if this is the last triangle
* of the polygon. Otherwise leave the primitive incomplete because
* there are more polygon vertices coming.
*/
brw_AND(p, retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
get_element_ud(c->reg.R0, 2),
brw_imm_ud(BRW_GS_EDGE_INDICATOR_1));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
brw_set_default_predicate_control(p, BRW_PREDICATE_NORMAL);
}
brw_ff_gs_offset_header_dw2(c, URB_WRITE_PRIM_END);
brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
brw_ff_gs_emit_vue(c, c->reg.vertex[2], true);
break;
}
}
const unsigned *
brw_compile_ff_gs_prog(struct brw_compiler *compiler,
void *mem_ctx,
const struct brw_ff_gs_prog_key *key,
struct brw_ff_gs_prog_data *prog_data,
struct intel_vue_map *vue_map,
unsigned *final_assembly_size)
{
struct brw_ff_gs_compile c;
const GLuint *program;
memset(&c, 0, sizeof(c));
c.key = *key;
c.vue_map = *vue_map;
c.nr_regs = (c.vue_map.num_slots + 1)/2;
c.prog_data = prog_data;
mem_ctx = ralloc_context(NULL);
/* Begin the compilation:
*/
brw_init_codegen(&compiler->isa, &c.func, mem_ctx);
c.func.single_program_flow = 1;
/* For some reason the thread is spawned with only 4 channels
* unmasked.
*/
brw_set_default_mask_control(&c.func, BRW_MASK_DISABLE);
if (compiler->devinfo->ver >= 6) {
unsigned num_verts;
bool check_edge_flag;
/* On Sandybridge, we use the GS for implementing transform feedback
* (called "Stream Out" in the PRM).
*/
switch (key->primitive) {
case _3DPRIM_POINTLIST:
num_verts = 1;
check_edge_flag = false;
break;
case _3DPRIM_LINELIST:
case _3DPRIM_LINESTRIP:
case _3DPRIM_LINELOOP:
num_verts = 2;
check_edge_flag = false;
break;
case _3DPRIM_TRILIST:
case _3DPRIM_TRIFAN:
case _3DPRIM_TRISTRIP:
case _3DPRIM_RECTLIST:
num_verts = 3;
check_edge_flag = false;
break;
case _3DPRIM_QUADLIST:
case _3DPRIM_QUADSTRIP:
case _3DPRIM_POLYGON:
num_verts = 3;
check_edge_flag = true;
break;
default:
unreachable("Unexpected primitive type in Gen6 SOL program.");
}
gfx6_sol_program(&c, key, num_verts, check_edge_flag);
} else {
/* On Gen4-5, we use the GS to decompose certain types of primitives.
* Note that primitives which don't require a GS program have already
* been weeded out by now.
*/
switch (key->primitive) {
case _3DPRIM_QUADLIST:
brw_ff_gs_quads( &c, key );
break;
case _3DPRIM_QUADSTRIP:
brw_ff_gs_quad_strip( &c, key );
break;
case _3DPRIM_LINELOOP:
brw_ff_gs_lines( &c );
break;
default:
return NULL;
}
}
brw_compact_instructions(&c.func, 0, NULL);
/* get the program
*/
program = brw_get_program(&c.func, final_assembly_size);
if (INTEL_DEBUG(DEBUG_GS)) {
fprintf(stderr, "gs:\n");
brw_disassemble_with_labels(&compiler->isa, c.func.store,
0, *final_assembly_size, stderr);
fprintf(stderr, "\n");
}
return program;
}
-881
View File
@@ -1,881 +0,0 @@
/*
* Copyright © 2006 - 2017 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "brw_compiler.h"
#include "brw_disasm.h"
#include "brw_eu.h"
#include "brw_prim.h"
#include "dev/intel_debug.h"
struct brw_sf_compile {
struct brw_codegen func;
struct brw_sf_prog_key key;
struct brw_sf_prog_data prog_data;
struct brw_reg pv;
struct brw_reg det;
struct brw_reg dx0;
struct brw_reg dx2;
struct brw_reg dy0;
struct brw_reg dy2;
/* z and 1/w passed in separately:
*/
struct brw_reg z[3];
struct brw_reg inv_w[3];
/* The vertices:
*/
struct brw_reg vert[3];
/* Temporaries, allocated after last vertex reg.
*/
struct brw_reg inv_det;
struct brw_reg a1_sub_a0;
struct brw_reg a2_sub_a0;
struct brw_reg tmp;
struct brw_reg m1Cx;
struct brw_reg m2Cy;
struct brw_reg m3C0;
GLuint nr_verts;
GLuint nr_attr_regs;
GLuint nr_setup_regs;
int urb_entry_read_offset;
/** The last known value of the f0.0 flag register. */
unsigned flag_value;
struct intel_vue_map vue_map;
};
/**
* Determine the vue slot corresponding to the given half of the given register.
*/
static inline int vert_reg_to_vue_slot(struct brw_sf_compile *c, GLuint reg,
int half)
{
return (reg + c->urb_entry_read_offset) * 2 + half;
}
/**
* Determine the varying corresponding to the given half of the given
* register. half=0 means the first half of a register, half=1 means the
* second half.
*/
static inline int vert_reg_to_varying(struct brw_sf_compile *c, GLuint reg,
int half)
{
int vue_slot = vert_reg_to_vue_slot(c, reg, half);
return c->vue_map.slot_to_varying[vue_slot];
}
/**
* Determine the register corresponding to the given vue slot
*/
static struct brw_reg get_vue_slot(struct brw_sf_compile *c,
struct brw_reg vert,
int vue_slot)
{
GLuint off = vue_slot / 2 - c->urb_entry_read_offset;
GLuint sub = vue_slot % 2;
return brw_vec4_grf(vert.nr + off, sub * 4);
}
/**
* Determine the register corresponding to the given varying.
*/
static struct brw_reg get_varying(struct brw_sf_compile *c,
struct brw_reg vert,
GLuint varying)
{
int vue_slot = c->vue_map.varying_to_slot[varying];
assert (vue_slot >= c->urb_entry_read_offset);
return get_vue_slot(c, vert, vue_slot);
}
static bool
have_attr(struct brw_sf_compile *c, GLuint attr)
{
return (c->key.attrs & BITFIELD64_BIT(attr)) ? 1 : 0;
}
/***********************************************************************
* Twoside lighting
*/
static void copy_bfc( struct brw_sf_compile *c,
struct brw_reg vert )
{
struct brw_codegen *p = &c->func;
GLuint i;
for (i = 0; i < 2; i++) {
if (have_attr(c, VARYING_SLOT_COL0+i) &&
have_attr(c, VARYING_SLOT_BFC0+i))
brw_MOV(p,
get_varying(c, vert, VARYING_SLOT_COL0+i),
get_varying(c, vert, VARYING_SLOT_BFC0+i));
}
}
static void do_twoside_color( struct brw_sf_compile *c )
{
struct brw_codegen *p = &c->func;
GLuint backface_conditional = c->key.frontface_ccw ? BRW_CONDITIONAL_G : BRW_CONDITIONAL_L;
/* Already done in clip program:
*/
if (c->key.primitive == BRW_SF_PRIM_UNFILLED_TRIS)
return;
/* If the vertex shader provides backface color, do the selection. The VS
* promises to set up the front color if the backface color is provided, but
* it may contain junk if never written to.
*/
if (!(have_attr(c, VARYING_SLOT_COL0) && have_attr(c, VARYING_SLOT_BFC0)) &&
!(have_attr(c, VARYING_SLOT_COL1) && have_attr(c, VARYING_SLOT_BFC1)))
return;
/* Need to use BRW_EXECUTE_4 and also do an 4-wide compare in order
* to get all channels active inside the IF. In the clipping code
* we run with NoMask, so it's not an option and we can use
* BRW_EXECUTE_1 for all comparisons.
*/
brw_CMP(p, vec4(brw_null_reg()), backface_conditional, c->det, brw_imm_f(0));
brw_IF(p, BRW_EXECUTE_4);
{
switch (c->nr_verts) {
case 3: copy_bfc(c, c->vert[2]); FALLTHROUGH;
case 2: copy_bfc(c, c->vert[1]); FALLTHROUGH;
case 1: copy_bfc(c, c->vert[0]);
}
}
brw_ENDIF(p);
}
/***********************************************************************
* Flat shading
*/
static void copy_flatshaded_attributes(struct brw_sf_compile *c,
struct brw_reg dst,
struct brw_reg src)
{
struct brw_codegen *p = &c->func;
int i;
for (i = 0; i < c->vue_map.num_slots; i++) {
if (c->key.interp_mode[i] == INTERP_MODE_FLAT) {
brw_MOV(p,
get_vue_slot(c, dst, i),
get_vue_slot(c, src, i));
}
}
}
static int count_flatshaded_attributes(struct brw_sf_compile *c)
{
int i;
int count = 0;
for (i = 0; i < c->vue_map.num_slots; i++)
if (c->key.interp_mode[i] == INTERP_MODE_FLAT)
count++;
return count;
}
/* Need to use a computed jump to copy flatshaded attributes as the
* vertices are ordered according to y-coordinate before reaching this
* point, so the PV could be anywhere.
*/
static void do_flatshade_triangle( struct brw_sf_compile *c )
{
struct brw_codegen *p = &c->func;
GLuint nr;
GLuint jmpi = 1;
/* Already done in clip program:
*/
if (c->key.primitive == BRW_SF_PRIM_UNFILLED_TRIS)
return;
if (p->devinfo->ver == 5)
jmpi = 2;
nr = count_flatshaded_attributes(c);
brw_MUL(p, c->pv, c->pv, brw_imm_d(jmpi*(nr*2+1)));
brw_JMPI(p, c->pv, BRW_PREDICATE_NONE);
copy_flatshaded_attributes(c, c->vert[1], c->vert[0]);
copy_flatshaded_attributes(c, c->vert[2], c->vert[0]);
brw_JMPI(p, brw_imm_d(jmpi*(nr*4+1)), BRW_PREDICATE_NONE);
copy_flatshaded_attributes(c, c->vert[0], c->vert[1]);
copy_flatshaded_attributes(c, c->vert[2], c->vert[1]);
brw_JMPI(p, brw_imm_d(jmpi*nr*2), BRW_PREDICATE_NONE);
copy_flatshaded_attributes(c, c->vert[0], c->vert[2]);
copy_flatshaded_attributes(c, c->vert[1], c->vert[2]);
}
static void do_flatshade_line( struct brw_sf_compile *c )
{
struct brw_codegen *p = &c->func;
GLuint nr;
GLuint jmpi = 1;
/* Already done in clip program:
*/
if (c->key.primitive == BRW_SF_PRIM_UNFILLED_TRIS)
return;
if (p->devinfo->ver == 5)
jmpi = 2;
nr = count_flatshaded_attributes(c);
brw_MUL(p, c->pv, c->pv, brw_imm_d(jmpi*(nr+1)));
brw_JMPI(p, c->pv, BRW_PREDICATE_NONE);
copy_flatshaded_attributes(c, c->vert[1], c->vert[0]);
brw_JMPI(p, brw_imm_ud(jmpi*nr), BRW_PREDICATE_NONE);
copy_flatshaded_attributes(c, c->vert[0], c->vert[1]);
}
/***********************************************************************
* Triangle setup.
*/
static void alloc_regs( struct brw_sf_compile *c )
{
GLuint reg, i;
/* Values computed by fixed function unit:
*/
c->pv = retype(brw_vec1_grf(1, 1), BRW_REGISTER_TYPE_D);
c->det = brw_vec1_grf(1, 2);
c->dx0 = brw_vec1_grf(1, 3);
c->dx2 = brw_vec1_grf(1, 4);
c->dy0 = brw_vec1_grf(1, 5);
c->dy2 = brw_vec1_grf(1, 6);
/* z and 1/w passed in separately:
*/
c->z[0] = brw_vec1_grf(2, 0);
c->inv_w[0] = brw_vec1_grf(2, 1);
c->z[1] = brw_vec1_grf(2, 2);
c->inv_w[1] = brw_vec1_grf(2, 3);
c->z[2] = brw_vec1_grf(2, 4);
c->inv_w[2] = brw_vec1_grf(2, 5);
/* The vertices:
*/
reg = 3;
for (i = 0; i < c->nr_verts; i++) {
c->vert[i] = brw_vec8_grf(reg, 0);
reg += c->nr_attr_regs;
}
/* Temporaries, allocated after last vertex reg.
*/
c->inv_det = brw_vec1_grf(reg, 0); reg++;
c->a1_sub_a0 = brw_vec8_grf(reg, 0); reg++;
c->a2_sub_a0 = brw_vec8_grf(reg, 0); reg++;
c->tmp = brw_vec8_grf(reg, 0); reg++;
/* Note grf allocation:
*/
c->prog_data.total_grf = reg;
/* Outputs of this program - interpolation coefficients for
* rasterization:
*/
c->m1Cx = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 1, 0);
c->m2Cy = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 2, 0);
c->m3C0 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 3, 0);
}
static void copy_z_inv_w( struct brw_sf_compile *c )
{
struct brw_codegen *p = &c->func;
GLuint i;
/* Copy both scalars with a single MOV:
*/
for (i = 0; i < c->nr_verts; i++)
brw_MOV(p, vec2(suboffset(c->vert[i], 2)), vec2(c->z[i]));
}
static void invert_det( struct brw_sf_compile *c)
{
/* Looks like we invert all 8 elements just to get 1/det in
* position 2 !?!
*/
gfx4_math(&c->func,
c->inv_det,
BRW_MATH_FUNCTION_INV,
0,
c->det,
BRW_MATH_PRECISION_FULL);
}
static bool
calculate_masks(struct brw_sf_compile *c,
GLuint reg,
GLushort *pc,
GLushort *pc_persp,
GLushort *pc_linear)
{
bool is_last_attr = (reg == c->nr_setup_regs - 1);
enum glsl_interp_mode interp;
*pc_persp = 0;
*pc_linear = 0;
*pc = 0xf;
interp = c->key.interp_mode[vert_reg_to_vue_slot(c, reg, 0)];
if (interp == INTERP_MODE_SMOOTH) {
*pc_linear = 0xf;
*pc_persp = 0xf;
} else if (interp == INTERP_MODE_NOPERSPECTIVE)
*pc_linear = 0xf;
/* Maybe only process one attribute on the final round:
*/
if (vert_reg_to_varying(c, reg, 1) != BRW_VARYING_SLOT_COUNT) {
*pc |= 0xf0;
interp = c->key.interp_mode[vert_reg_to_vue_slot(c, reg, 1)];
if (interp == INTERP_MODE_SMOOTH) {
*pc_linear |= 0xf0;
*pc_persp |= 0xf0;
} else if (interp == INTERP_MODE_NOPERSPECTIVE)
*pc_linear |= 0xf0;
}
return is_last_attr;
}
/* Calculates the predicate control for which channels of a reg
* (containing 2 attrs) to do point sprite coordinate replacement on.
*/
static uint16_t
calculate_point_sprite_mask(struct brw_sf_compile *c, GLuint reg)
{
int varying1, varying2;
uint16_t pc = 0;
varying1 = vert_reg_to_varying(c, reg, 0);
if (varying1 >= VARYING_SLOT_TEX0 && varying1 <= VARYING_SLOT_TEX7) {
if (c->key.point_sprite_coord_replace & (1 << (varying1 - VARYING_SLOT_TEX0)))
pc |= 0x0f;
}
if (varying1 == BRW_VARYING_SLOT_PNTC)
pc |= 0x0f;
varying2 = vert_reg_to_varying(c, reg, 1);
if (varying2 >= VARYING_SLOT_TEX0 && varying2 <= VARYING_SLOT_TEX7) {
if (c->key.point_sprite_coord_replace & (1 << (varying2 -
VARYING_SLOT_TEX0)))
pc |= 0xf0;
}
if (varying2 == BRW_VARYING_SLOT_PNTC)
pc |= 0xf0;
return pc;
}
static void
set_predicate_control_flag_value(struct brw_codegen *p,
struct brw_sf_compile *c,
unsigned value)
{
brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
if (value != 0xff) {
if (value != c->flag_value) {
brw_MOV(p, brw_flag_reg(0, 0), brw_imm_uw(value));
c->flag_value = value;
}
brw_set_default_predicate_control(p, BRW_PREDICATE_NORMAL);
}
}
static void brw_emit_tri_setup(struct brw_sf_compile *c, bool allocate)
{
struct brw_codegen *p = &c->func;
GLuint i;
c->flag_value = 0xff;
c->nr_verts = 3;
if (allocate)
alloc_regs(c);
invert_det(c);
copy_z_inv_w(c);
if (c->key.do_twoside_color)
do_twoside_color(c);
if (c->key.contains_flat_varying)
do_flatshade_triangle(c);
for (i = 0; i < c->nr_setup_regs; i++)
{
/* Pair of incoming attributes:
*/
struct brw_reg a0 = offset(c->vert[0], i);
struct brw_reg a1 = offset(c->vert[1], i);
struct brw_reg a2 = offset(c->vert[2], i);
GLushort pc, pc_persp, pc_linear;
bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
if (pc_persp)
{
set_predicate_control_flag_value(p, c, pc_persp);
brw_MUL(p, a0, a0, c->inv_w[0]);
brw_MUL(p, a1, a1, c->inv_w[1]);
brw_MUL(p, a2, a2, c->inv_w[2]);
}
/* Calculate coefficients for interpolated values:
*/
if (pc_linear)
{
set_predicate_control_flag_value(p, c, pc_linear);
brw_ADD(p, c->a1_sub_a0, a1, negate(a0));
brw_ADD(p, c->a2_sub_a0, a2, negate(a0));
/* calculate dA/dx
*/
brw_MUL(p, brw_null_reg(), c->a1_sub_a0, c->dy2);
brw_MAC(p, c->tmp, c->a2_sub_a0, negate(c->dy0));
brw_MUL(p, c->m1Cx, c->tmp, c->inv_det);
/* calculate dA/dy
*/
brw_MUL(p, brw_null_reg(), c->a2_sub_a0, c->dx0);
brw_MAC(p, c->tmp, c->a1_sub_a0, negate(c->dx2));
brw_MUL(p, c->m2Cy, c->tmp, c->inv_det);
}
{
set_predicate_control_flag_value(p, c, pc);
/* start point for interpolation
*/
brw_MOV(p, c->m3C0, a0);
/* Copy m0..m3 to URB. m0 is implicitly copied from r0 in
* the send instruction:
*/
brw_urb_WRITE(p,
brw_null_reg(),
0,
brw_vec8_grf(0, 0), /* r0, will be copied to m0 */
last ? BRW_URB_WRITE_EOT_COMPLETE
: BRW_URB_WRITE_NO_FLAGS,
4, /* msg len */
0, /* response len */
i*4, /* offset */
BRW_URB_SWIZZLE_TRANSPOSE); /* XXX: Swizzle control "SF to windower" */
}
}
brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
}
static void brw_emit_line_setup(struct brw_sf_compile *c, bool allocate)
{
struct brw_codegen *p = &c->func;
GLuint i;
c->flag_value = 0xff;
c->nr_verts = 2;
if (allocate)
alloc_regs(c);
invert_det(c);
copy_z_inv_w(c);
if (c->key.contains_flat_varying)
do_flatshade_line(c);
for (i = 0; i < c->nr_setup_regs; i++)
{
/* Pair of incoming attributes:
*/
struct brw_reg a0 = offset(c->vert[0], i);
struct brw_reg a1 = offset(c->vert[1], i);
GLushort pc, pc_persp, pc_linear;
bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
if (pc_persp)
{
set_predicate_control_flag_value(p, c, pc_persp);
brw_MUL(p, a0, a0, c->inv_w[0]);
brw_MUL(p, a1, a1, c->inv_w[1]);
}
/* Calculate coefficients for position, color:
*/
if (pc_linear) {
set_predicate_control_flag_value(p, c, pc_linear);
brw_ADD(p, c->a1_sub_a0, a1, negate(a0));
brw_MUL(p, c->tmp, c->a1_sub_a0, c->dx0);
brw_MUL(p, c->m1Cx, c->tmp, c->inv_det);
brw_MUL(p, c->tmp, c->a1_sub_a0, c->dy0);
brw_MUL(p, c->m2Cy, c->tmp, c->inv_det);
}
{
set_predicate_control_flag_value(p, c, pc);
/* start point for interpolation
*/
brw_MOV(p, c->m3C0, a0);
/* Copy m0..m3 to URB.
*/
brw_urb_WRITE(p,
brw_null_reg(),
0,
brw_vec8_grf(0, 0),
last ? BRW_URB_WRITE_EOT_COMPLETE
: BRW_URB_WRITE_NO_FLAGS,
4, /* msg len */
0, /* response len */
i*4, /* urb destination offset */
BRW_URB_SWIZZLE_TRANSPOSE);
}
}
brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
}
static void brw_emit_point_sprite_setup(struct brw_sf_compile *c, bool allocate)
{
struct brw_codegen *p = &c->func;
GLuint i;
c->flag_value = 0xff;
c->nr_verts = 1;
if (allocate)
alloc_regs(c);
copy_z_inv_w(c);
for (i = 0; i < c->nr_setup_regs; i++)
{
struct brw_reg a0 = offset(c->vert[0], i);
GLushort pc, pc_persp, pc_linear, pc_coord_replace;
bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
pc_coord_replace = calculate_point_sprite_mask(c, i);
pc_persp &= ~pc_coord_replace;
if (pc_persp) {
set_predicate_control_flag_value(p, c, pc_persp);
brw_MUL(p, a0, a0, c->inv_w[0]);
}
/* Point sprite coordinate replacement: A texcoord with this
* enabled gets replaced with the value (x, y, 0, 1) where x and
* y vary from 0 to 1 across the horizontal and vertical of the
* point.
*/
if (pc_coord_replace) {
set_predicate_control_flag_value(p, c, pc_coord_replace);
/* Calculate 1.0/PointWidth */
gfx4_math(&c->func,
c->tmp,
BRW_MATH_FUNCTION_INV,
0,
c->dx0,
BRW_MATH_PRECISION_FULL);
brw_set_default_access_mode(p, BRW_ALIGN_16);
/* dA/dx, dA/dy */
brw_MOV(p, c->m1Cx, brw_imm_f(0.0));
brw_MOV(p, c->m2Cy, brw_imm_f(0.0));
brw_MOV(p, brw_writemask(c->m1Cx, WRITEMASK_X), c->tmp);
if (c->key.sprite_origin_lower_left) {
brw_MOV(p, brw_writemask(c->m2Cy, WRITEMASK_Y), negate(c->tmp));
} else {
brw_MOV(p, brw_writemask(c->m2Cy, WRITEMASK_Y), c->tmp);
}
/* attribute constant offset */
brw_MOV(p, c->m3C0, brw_imm_f(0.0));
if (c->key.sprite_origin_lower_left) {
brw_MOV(p, brw_writemask(c->m3C0, WRITEMASK_YW), brw_imm_f(1.0));
} else {
brw_MOV(p, brw_writemask(c->m3C0, WRITEMASK_W), brw_imm_f(1.0));
}
brw_set_default_access_mode(p, BRW_ALIGN_1);
}
if (pc & ~pc_coord_replace) {
set_predicate_control_flag_value(p, c, pc & ~pc_coord_replace);
brw_MOV(p, c->m1Cx, brw_imm_ud(0));
brw_MOV(p, c->m2Cy, brw_imm_ud(0));
brw_MOV(p, c->m3C0, a0); /* constant value */
}
set_predicate_control_flag_value(p, c, pc);
/* Copy m0..m3 to URB. */
brw_urb_WRITE(p,
brw_null_reg(),
0,
brw_vec8_grf(0, 0),
last ? BRW_URB_WRITE_EOT_COMPLETE
: BRW_URB_WRITE_NO_FLAGS,
4, /* msg len */
0, /* response len */
i*4, /* urb destination offset */
BRW_URB_SWIZZLE_TRANSPOSE);
}
brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
}
/* Points setup - several simplifications as all attributes are
* constant across the face of the point (point sprites excluded!)
*/
static void brw_emit_point_setup(struct brw_sf_compile *c, bool allocate)
{
struct brw_codegen *p = &c->func;
GLuint i;
c->flag_value = 0xff;
c->nr_verts = 1;
if (allocate)
alloc_regs(c);
copy_z_inv_w(c);
brw_MOV(p, c->m1Cx, brw_imm_ud(0)); /* zero - move out of loop */
brw_MOV(p, c->m2Cy, brw_imm_ud(0)); /* zero - move out of loop */
for (i = 0; i < c->nr_setup_regs; i++)
{
struct brw_reg a0 = offset(c->vert[0], i);
GLushort pc, pc_persp, pc_linear;
bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
if (pc_persp)
{
/* This seems odd as the values are all constant, but the
* fragment shader will be expecting it:
*/
set_predicate_control_flag_value(p, c, pc_persp);
brw_MUL(p, a0, a0, c->inv_w[0]);
}
/* The delta values are always zero, just send the starting
* coordinate. Again, this is to fit in with the interpolation
* code in the fragment shader.
*/
{
set_predicate_control_flag_value(p, c, pc);
brw_MOV(p, c->m3C0, a0); /* constant value */
/* Copy m0..m3 to URB.
*/
brw_urb_WRITE(p,
brw_null_reg(),
0,
brw_vec8_grf(0, 0),
last ? BRW_URB_WRITE_EOT_COMPLETE
: BRW_URB_WRITE_NO_FLAGS,
4, /* msg len */
0, /* response len */
i*4, /* urb destination offset */
BRW_URB_SWIZZLE_TRANSPOSE);
}
}
brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
}
static void brw_emit_anyprim_setup( struct brw_sf_compile *c )
{
struct brw_codegen *p = &c->func;
struct brw_reg payload_prim = brw_uw1_reg(BRW_GENERAL_REGISTER_FILE, 1, 0);
struct brw_reg payload_attr = get_element_ud(brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, 1, 0), 0);
struct brw_reg primmask;
int jmp;
struct brw_reg v1_null_ud = vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD));
c->nr_verts = 3;
alloc_regs(c);
primmask = retype(get_element(c->tmp, 0), BRW_REGISTER_TYPE_UD);
brw_MOV(p, primmask, brw_imm_ud(1));
brw_SHL(p, primmask, primmask, payload_prim);
brw_AND(p, v1_null_ud, primmask, brw_imm_ud((1<<_3DPRIM_TRILIST) |
(1<<_3DPRIM_TRISTRIP) |
(1<<_3DPRIM_TRIFAN) |
(1<<_3DPRIM_TRISTRIP_REVERSE) |
(1<<_3DPRIM_POLYGON) |
(1<<_3DPRIM_RECTLIST) |
(1<<_3DPRIM_TRIFAN_NOSTIPPLE)));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_Z);
jmp = brw_JMPI(p, brw_imm_d(0), BRW_PREDICATE_NORMAL) - p->store;
brw_emit_tri_setup(c, false);
brw_land_fwd_jump(p, jmp);
brw_AND(p, v1_null_ud, primmask, brw_imm_ud((1<<_3DPRIM_LINELIST) |
(1<<_3DPRIM_LINESTRIP) |
(1<<_3DPRIM_LINELOOP) |
(1<<_3DPRIM_LINESTRIP_CONT) |
(1<<_3DPRIM_LINESTRIP_BF) |
(1<<_3DPRIM_LINESTRIP_CONT_BF)));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_Z);
jmp = brw_JMPI(p, brw_imm_d(0), BRW_PREDICATE_NORMAL) - p->store;
brw_emit_line_setup(c, false);
brw_land_fwd_jump(p, jmp);
brw_AND(p, v1_null_ud, payload_attr, brw_imm_ud(1<<BRW_SPRITE_POINT_ENABLE));
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_Z);
jmp = brw_JMPI(p, brw_imm_d(0), BRW_PREDICATE_NORMAL) - p->store;
brw_emit_point_sprite_setup(c, false);
brw_land_fwd_jump(p, jmp);
brw_emit_point_setup( c, false );
}
const unsigned *
brw_compile_sf(const struct brw_compiler *compiler,
void *mem_ctx,
const struct brw_sf_prog_key *key,
struct brw_sf_prog_data *prog_data,
struct intel_vue_map *vue_map,
unsigned *final_assembly_size)
{
struct brw_sf_compile c;
memset(&c, 0, sizeof(c));
/* Begin the compilation:
*/
brw_init_codegen(&compiler->isa, &c.func, mem_ctx);
c.key = *key;
c.vue_map = *vue_map;
if (c.key.do_point_coord) {
/*
* gl_PointCoord is a FS instead of VS builtin variable, thus it's
* not included in c.vue_map generated in VS stage. Here we add
* it manually to let SF shader generate the needed interpolation
* coefficient for FS shader.
*/
c.vue_map.varying_to_slot[BRW_VARYING_SLOT_PNTC] = c.vue_map.num_slots;
c.vue_map.slot_to_varying[c.vue_map.num_slots++] = BRW_VARYING_SLOT_PNTC;
}
c.urb_entry_read_offset = BRW_SF_URB_ENTRY_READ_OFFSET;
c.nr_attr_regs = (c.vue_map.num_slots + 1)/2 - c.urb_entry_read_offset;
c.nr_setup_regs = c.nr_attr_regs;
c.prog_data.urb_read_length = c.nr_attr_regs;
c.prog_data.urb_entry_size = c.nr_setup_regs * 2;
/* Which primitive? Or all three?
*/
switch (key->primitive) {
case BRW_SF_PRIM_TRIANGLES:
c.nr_verts = 3;
brw_emit_tri_setup( &c, true );
break;
case BRW_SF_PRIM_LINES:
c.nr_verts = 2;
brw_emit_line_setup( &c, true );
break;
case BRW_SF_PRIM_POINTS:
c.nr_verts = 1;
if (key->do_point_sprite)
brw_emit_point_sprite_setup( &c, true );
else
brw_emit_point_setup( &c, true );
break;
case BRW_SF_PRIM_UNFILLED_TRIS:
c.nr_verts = 3;
brw_emit_anyprim_setup( &c );
break;
default:
unreachable("not reached");
}
/* FINISHME: SF programs use calculated jumps (i.e., JMPI with a register
* source). Compacting would be difficult.
*/
/* brw_compact_instructions(&c.func, 0, 0, NULL); */
*prog_data = c.prog_data;
const unsigned *program = brw_get_program(&c.func, final_assembly_size);
if (INTEL_DEBUG(DEBUG_SF)) {
fprintf(stderr, "sf:\n");
brw_disassemble_with_labels(&compiler->isa,
program, 0, *final_assembly_size, stderr);
fprintf(stderr, "\n");
}
return program;
}
-182
View File
@@ -431,69 +431,6 @@ struct brw_mesh_prog_key
unsigned padding:31;
};
enum brw_sf_primitive {
BRW_SF_PRIM_POINTS = 0,
BRW_SF_PRIM_LINES = 1,
BRW_SF_PRIM_TRIANGLES = 2,
BRW_SF_PRIM_UNFILLED_TRIS = 3,
};
struct brw_sf_prog_key {
uint64_t attrs;
bool contains_flat_varying;
unsigned char interp_mode[65]; /* BRW_VARYING_SLOT_COUNT */
uint8_t point_sprite_coord_replace;
enum brw_sf_primitive primitive:2;
bool do_twoside_color:1;
bool frontface_ccw:1;
bool do_point_sprite:1;
bool do_point_coord:1;
bool sprite_origin_lower_left:1;
bool userclip_active:1;
unsigned padding: 32;
};
enum brw_clip_mode {
BRW_CLIP_MODE_NORMAL = 0,
BRW_CLIP_MODE_CLIP_ALL = 1,
BRW_CLIP_MODE_CLIP_NON_REJECTED = 2,
BRW_CLIP_MODE_REJECT_ALL = 3,
BRW_CLIP_MODE_ACCEPT_ALL = 4,
BRW_CLIP_MODE_KERNEL_CLIP = 5,
};
enum brw_clip_fill_mode {
BRW_CLIP_FILL_MODE_LINE = 0,
BRW_CLIP_FILL_MODE_POINT = 1,
BRW_CLIP_FILL_MODE_FILL = 2,
BRW_CLIP_FILL_MODE_CULL = 3,
};
/* Note that if unfilled primitives are being emitted, we have to fix
* up polygon offset and flatshading at this point:
*/
struct brw_clip_prog_key {
uint64_t attrs;
float offset_factor;
float offset_units;
float offset_clamp;
bool contains_flat_varying;
bool contains_noperspective_varying;
unsigned char interp_mode[65]; /* BRW_VARYING_SLOT_COUNT */
unsigned primitive:4;
unsigned nr_userclip:4;
bool pv_first:1;
bool do_unfilled:1;
enum brw_clip_fill_mode fill_cw:2; /* includes cull information */
enum brw_clip_fill_mode fill_ccw:2; /* includes cull information */
bool offset_cw:1;
bool offset_ccw:1;
bool copy_bfc_cw:1;
bool copy_bfc_ccw:1;
enum brw_clip_mode clip_mode:3;
uint64_t padding:51;
};
/* A big lookup table is used to figure out which and how many
* additional regs will inserted before the main payload in the WM
* program execution. These mainly relate to depth and stencil
@@ -581,38 +518,6 @@ struct brw_bs_prog_key {
uint32_t pipeline_ray_flags;
};
struct brw_ff_gs_prog_key {
uint64_t attrs;
/**
* Map from the index of a transform feedback binding table entry to the
* gl_varying_slot that should be streamed out through that binding table
* entry.
*/
unsigned char transform_feedback_bindings[BRW_MAX_SOL_BINDINGS];
/**
* Map from the index of a transform feedback binding table entry to the
* swizzles that should be used when streaming out data through that
* binding table entry.
*/
unsigned char transform_feedback_swizzles[BRW_MAX_SOL_BINDINGS];
/**
* Hardware primitive type being drawn, e.g. _3DPRIM_TRILIST.
*/
unsigned primitive:8;
unsigned pv_first:1;
unsigned need_gs_prog:1;
/**
* Number of varyings that are output to transform feedback.
*/
unsigned num_transform_feedback_bindings:7; /* 0-BRW_MAX_SOL_BINDINGS */
uint64_t padding:47;
};
/* brw_any_prog_key is any of the keys that map to an API stage */
union brw_any_prog_key {
struct brw_base_prog_key base;
@@ -1302,17 +1207,6 @@ struct brw_bs_prog_data {
uint32_t num_resume_shaders;
};
struct brw_ff_gs_prog_data {
unsigned urb_read_length;
unsigned total_grf;
/**
* Gfx6 transform feedback: Amount by which the streaming vertex buffer
* indices should be incremented each time the GS is invoked.
*/
unsigned svbi_postincrement_value;
};
/**
* Enum representing the i965-specific vertex results that don't correspond
* exactly to any element of gl_varying_slot. The values of this enum are
@@ -1322,13 +1216,6 @@ typedef enum
{
BRW_VARYING_SLOT_NDC = VARYING_SLOT_MAX,
BRW_VARYING_SLOT_PAD,
/**
* Technically this is not a varying but just a placeholder that
* compile_sf_prog() inserts into its VUE map to cause the gl_PointCoord
* builtin variable to be compiled correctly. see compile_sf_prog() for
* more info.
*/
BRW_VARYING_SLOT_PNTC,
BRW_VARYING_SLOT_COUNT
} brw_varying_slot;
@@ -1509,26 +1396,6 @@ struct brw_gs_prog_data
unsigned char transform_feedback_swizzles[64 /* BRW_MAX_SOL_BINDINGS */];
};
struct brw_sf_prog_data {
uint32_t urb_read_length;
uint32_t total_grf;
/* Each vertex may have up to 12 attributes, 4 components each,
* except WPOS which requires only 2. (11*4 + 2) == 44 ==> 11
* rows.
*
* Actually we use 4 for each, so call it 12 rows.
*/
unsigned urb_entry_size;
};
struct brw_clip_prog_data {
uint32_t curb_read_length; /* user planes? */
uint32_t clip_mode;
uint32_t urb_read_length;
uint32_t total_grf;
};
struct brw_tue_map {
uint32_t size_dw;
@@ -1628,10 +1495,6 @@ DEFINE_PROG_DATA_DOWNCAST(vue, prog_data->stage == MESA_SHADER_VERTEX ||
DEFINE_PROG_DATA_DOWNCAST(task, prog_data->stage == MESA_SHADER_TASK)
DEFINE_PROG_DATA_DOWNCAST(mesh, prog_data->stage == MESA_SHADER_MESH)
/* These are not really brw_stage_prog_data. */
DEFINE_PROG_DATA_DOWNCAST(ff_gs, true)
DEFINE_PROG_DATA_DOWNCAST(clip, true)
DEFINE_PROG_DATA_DOWNCAST(sf, true)
#undef DEFINE_PROG_DATA_DOWNCAST
struct brw_compile_stats {
@@ -1787,38 +1650,6 @@ const unsigned *
brw_compile_gs(const struct brw_compiler *compiler,
struct brw_compile_gs_params *params);
/**
* Compile a strips and fans shader.
*
* This is a fixed-function shader determined entirely by the shader key and
* a VUE map.
*
* Returns the final assembly and the program's size.
*/
const unsigned *
brw_compile_sf(const struct brw_compiler *compiler,
void *mem_ctx,
const struct brw_sf_prog_key *key,
struct brw_sf_prog_data *prog_data,
struct intel_vue_map *vue_map,
unsigned *final_assembly_size);
/**
* Compile a clipper shader.
*
* This is a fixed-function shader determined entirely by the shader key and
* a VUE map.
*
* Returns the final assembly and the program's size.
*/
const unsigned *
brw_compile_clip(const struct brw_compiler *compiler,
void *mem_ctx,
const struct brw_clip_prog_key *key,
struct brw_clip_prog_data *prog_data,
struct intel_vue_map *vue_map,
unsigned *final_assembly_size);
struct brw_compile_task_params {
struct brw_compile_params base;
@@ -1915,19 +1746,6 @@ const unsigned *
brw_compile_bs(const struct brw_compiler *compiler,
struct brw_compile_bs_params *params);
/**
* Compile a fixed function geometry shader.
*
* Returns the final assembly and the program's size.
*/
const unsigned *
brw_compile_ff_gs_prog(struct brw_compiler *compiler,
void *mem_ctx,
const struct brw_ff_gs_prog_key *key,
struct brw_ff_gs_prog_data *prog_data,
struct intel_vue_map *vue_map,
unsigned *final_assembly_size);
void brw_debug_key_recompile(const struct brw_compiler *c, void *log,
gl_shader_stage stage,
const struct brw_base_prog_key *old_key,
-1
View File
@@ -291,7 +291,6 @@ varying_name(brw_varying_slot slot, gl_shader_stage stage)
static const char *brw_names[] = {
[BRW_VARYING_SLOT_NDC - VARYING_SLOT_MAX] = "BRW_VARYING_SLOT_NDC",
[BRW_VARYING_SLOT_PAD - VARYING_SLOT_MAX] = "BRW_VARYING_SLOT_PAD",
[BRW_VARYING_SLOT_PNTC - VARYING_SLOT_MAX] = "BRW_VARYING_SLOT_PNTC",
};
return brw_names[slot - VARYING_SLOT_MAX];
-9
View File
@@ -39,16 +39,7 @@ intel_nir_files = files(
libintel_compiler_brw_files = files(
'brw_cfg.cpp',
'brw_cfg.h',
'brw_clip.h',
'brw_clip_line.c',
'brw_clip_point.c',
'brw_clip_tri.c',
'brw_clip_unfilled.c',
'brw_clip_util.c',
'brw_compile_clip.c',
'brw_compile_ff_gs.c',
'brw_compile_gs.cpp',
'brw_compile_sf.c',
'brw_compile_tcs.cpp',
'brw_compile_vs.cpp',
'brw_compiler.c',