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:
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user