draw: clipdistance support (v2)
Add support for using the clipdistance instead of clip plane. Passes all piglit clipdistance tests. v2: fixup some comments from Brian in review. Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
@@ -36,12 +36,19 @@ static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
|
||||
/* const */ float (*plane)[4] = pvs->draw->plane;
|
||||
const unsigned pos = draw_current_shader_position_output(pvs->draw);
|
||||
const unsigned cv = draw_current_shader_clipvertex_output(pvs->draw);
|
||||
unsigned cd[2];
|
||||
const unsigned ef = pvs->draw->vs.edgeflag_output;
|
||||
const unsigned ucp_enable = pvs->draw->rasterizer->clip_plane_enable;
|
||||
const unsigned flags = (FLAGS);
|
||||
unsigned need_pipeline = 0;
|
||||
unsigned j;
|
||||
unsigned i;
|
||||
bool have_cd = false;
|
||||
cd[0] = draw_current_shader_clipdistance_output(pvs->draw, 0);
|
||||
cd[1] = draw_current_shader_clipdistance_output(pvs->draw, 1);
|
||||
|
||||
if (cd[0] != pos || cd[1] != pos)
|
||||
have_cd = true;
|
||||
|
||||
for (j = 0; j < info->count; j++) {
|
||||
float *position = out->data[pos];
|
||||
@@ -89,14 +96,31 @@ static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
|
||||
|
||||
if (flags & DO_CLIP_USER) {
|
||||
unsigned ucp_mask = ucp_enable;
|
||||
|
||||
int num_written_clipdistance = pvs->draw->vs.vertex_shader->info.num_written_clipdistance;
|
||||
while (ucp_mask) {
|
||||
unsigned plane_idx = ffs(ucp_mask)-1;
|
||||
ucp_mask &= ~(1 << plane_idx);
|
||||
plane_idx += 6;
|
||||
|
||||
if (dot4(clipvertex, plane[plane_idx]) < 0) {
|
||||
mask |= 1 << plane_idx;
|
||||
/*
|
||||
* for user clipping check if we have a clip distance output
|
||||
* and the shader has written to it, otherwise use clipvertex
|
||||
* to decide when the plane is clipping.
|
||||
*/
|
||||
if (have_cd && num_written_clipdistance) {
|
||||
float clipdist;
|
||||
i = plane_idx - 6;
|
||||
out->have_clipdist = 1;
|
||||
/* first four clip distance in first vector etc. */
|
||||
if (i < 4)
|
||||
clipdist = out->data[cd[0]][i];
|
||||
else
|
||||
clipdist = out->data[cd[1]][i-4];
|
||||
if (clipdist < 0)
|
||||
mask |= 1 << plane_idx;
|
||||
} else {
|
||||
if (dot4(clipvertex, plane[plane_idx]) < 0)
|
||||
mask |= 1 << plane_idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -701,6 +701,12 @@ draw_current_shader_clipvertex_output(const struct draw_context *draw)
|
||||
return draw->vs.clipvertex_output;
|
||||
}
|
||||
|
||||
uint
|
||||
draw_current_shader_clipdistance_output(const struct draw_context *draw, int index)
|
||||
{
|
||||
return draw->vs.clipdistance_output[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pointer/handle for a driver/CSO rasterizer object which
|
||||
* disabled culling, stippling, unfilled tris, etc.
|
||||
|
@@ -119,13 +119,17 @@ static void interp( const struct clip_stage *clip,
|
||||
const unsigned nr_attrs = draw_current_shader_outputs(clip->stage.draw);
|
||||
const unsigned pos_attr = draw_current_shader_position_output(clip->stage.draw);
|
||||
const unsigned clip_attr = draw_current_shader_clipvertex_output(clip->stage.draw);
|
||||
unsigned clip_dist[2];
|
||||
unsigned j;
|
||||
|
||||
clip_dist[0] = draw_current_shader_clipdistance_output(clip->stage.draw, 0);
|
||||
clip_dist[1] = draw_current_shader_clipdistance_output(clip->stage.draw, 1);
|
||||
|
||||
/* Vertex header.
|
||||
*/
|
||||
dst->clipmask = 0;
|
||||
dst->edgeflag = 0; /* will get overwritten later */
|
||||
dst->pad = 0;
|
||||
dst->have_clipdist = in->have_clipdist;
|
||||
dst->vertex_id = UNDEFINED_VERTEX_ID;
|
||||
|
||||
/* Interpolate the clip-space coords.
|
||||
@@ -241,6 +245,29 @@ dot4(const float *a, const float *b)
|
||||
a[3] * b[3]);
|
||||
}
|
||||
|
||||
/*
|
||||
* this function extracts the clip distance for the current plane,
|
||||
* it first checks if the shader provided a clip distance, otherwise
|
||||
* it works out the value using the clipvertex
|
||||
*/
|
||||
static INLINE float getclipdist(const struct clip_stage *clipper,
|
||||
struct vertex_header *vert,
|
||||
int plane_idx)
|
||||
{
|
||||
const float *plane;
|
||||
float dp;
|
||||
if (vert->have_clipdist && plane_idx >= 6) {
|
||||
/* pick the correct clipdistance element from the output vectors */
|
||||
int _idx = plane_idx - 6;
|
||||
int cdi = _idx >= 4;
|
||||
int vidx = cdi ? _idx - 4 : _idx;
|
||||
dp = vert->data[draw_current_shader_clipdistance_output(clipper->stage.draw, cdi)][vidx];
|
||||
} else {
|
||||
plane = clipper->plane[plane_idx];
|
||||
dp = dot4(vert->clip, plane);
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
/* Clip a triangle against the viewport and user clip planes.
|
||||
*/
|
||||
@@ -281,12 +308,12 @@ do_clip_tri( struct draw_stage *stage,
|
||||
while (clipmask && n >= 3) {
|
||||
const unsigned plane_idx = ffs(clipmask)-1;
|
||||
const boolean is_user_clip_plane = plane_idx >= 6;
|
||||
const float *plane = clipper->plane[plane_idx];
|
||||
struct vertex_header *vert_prev = inlist[0];
|
||||
boolean *edge_prev = &inEdges[0];
|
||||
float dp_prev = dot4( vert_prev->clip, plane );
|
||||
float dp_prev;
|
||||
unsigned outcount = 0;
|
||||
|
||||
dp_prev = getclipdist(clipper, vert_prev, plane_idx);
|
||||
clipmask &= ~(1<<plane_idx);
|
||||
|
||||
assert(n < MAX_CLIPPED_VERTICES);
|
||||
@@ -299,7 +326,7 @@ do_clip_tri( struct draw_stage *stage,
|
||||
struct vertex_header *vert = inlist[i];
|
||||
boolean *edge = &inEdges[i];
|
||||
|
||||
float dp = dot4( vert->clip, plane );
|
||||
float dp = getclipdist(clipper, vert, plane_idx);
|
||||
|
||||
if (!IS_NEGATIVE(dp_prev)) {
|
||||
assert(outcount < MAX_CLIPPED_VERTICES);
|
||||
@@ -421,17 +448,14 @@ do_clip_line( struct draw_stage *stage,
|
||||
const struct clip_stage *clipper = clip_stage( stage );
|
||||
struct vertex_header *v0 = header->v[0];
|
||||
struct vertex_header *v1 = header->v[1];
|
||||
const float *pos0 = v0->clip;
|
||||
const float *pos1 = v1->clip;
|
||||
float t0 = 0.0F;
|
||||
float t1 = 0.0F;
|
||||
struct prim_header newprim;
|
||||
|
||||
while (clipmask) {
|
||||
const unsigned plane_idx = ffs(clipmask)-1;
|
||||
const float *plane = clipper->plane[plane_idx];
|
||||
const float dp0 = dot4( pos0, plane );
|
||||
const float dp1 = dot4( pos1, plane );
|
||||
const float dp0 = getclipdist(clipper, v0, plane_idx);
|
||||
const float dp1 = getclipdist(clipper, v1, plane_idx);
|
||||
|
||||
if (dp1 < 0.0F) {
|
||||
float t = dp1 / (dp1 - dp0);
|
||||
|
@@ -72,7 +72,7 @@ struct tgsi_sampler;
|
||||
struct vertex_header {
|
||||
unsigned clipmask:DRAW_TOTAL_CLIP_PLANES;
|
||||
unsigned edgeflag:1;
|
||||
unsigned pad:1;
|
||||
unsigned have_clipdist:1;
|
||||
unsigned vertex_id:16;
|
||||
|
||||
float clip[4];
|
||||
@@ -232,7 +232,7 @@ struct draw_context
|
||||
uint position_output;
|
||||
uint edgeflag_output;
|
||||
uint clipvertex_output;
|
||||
|
||||
uint clipdistance_output[2];
|
||||
/** TGSI program interpreter runtime state */
|
||||
struct tgsi_exec_machine *machine;
|
||||
|
||||
@@ -381,6 +381,7 @@ void draw_gs_destroy( struct draw_context *draw );
|
||||
uint draw_current_shader_outputs(const struct draw_context *draw);
|
||||
uint draw_current_shader_position_output(const struct draw_context *draw);
|
||||
uint draw_current_shader_clipvertex_output(const struct draw_context *draw);
|
||||
uint draw_current_shader_clipdistance_output(const struct draw_context *draw, int index);
|
||||
int draw_alloc_extra_vertex_attrib(struct draw_context *draw,
|
||||
uint semantic_name, uint semantic_index);
|
||||
void draw_remove_extra_vertex_attribs(struct draw_context *draw);
|
||||
|
@@ -31,7 +31,7 @@
|
||||
#include "draw/draw_context.h"
|
||||
#include "draw/draw_private.h"
|
||||
#include "draw/draw_pt.h"
|
||||
|
||||
#include "draw/draw_vs.h"
|
||||
|
||||
#define DO_CLIP_XY 0x1
|
||||
#define DO_CLIP_FULL_Z 0x2
|
||||
@@ -56,7 +56,7 @@ initialize_vertex_header(struct vertex_header *header)
|
||||
{
|
||||
header->clipmask = 0;
|
||||
header->edgeflag = 1;
|
||||
header->pad = 0;
|
||||
header->have_clipdist = 0;
|
||||
header->vertex_id = UNDEFINED_VERTEX_ID;
|
||||
}
|
||||
|
||||
|
@@ -132,6 +132,11 @@ draw_create_vertex_shader(struct draw_context *draw,
|
||||
vs->info.output_semantic_index[i] == 0) {
|
||||
found_clipvertex = TRUE;
|
||||
vs->clipvertex_output = i;
|
||||
} else if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPDIST) {
|
||||
if (vs->info.output_semantic_index[i] == 0)
|
||||
vs->clipdistance_output[0] = i;
|
||||
else
|
||||
vs->clipdistance_output[1] = i;
|
||||
}
|
||||
}
|
||||
if (!found_clipvertex)
|
||||
@@ -156,6 +161,8 @@ draw_bind_vertex_shader(struct draw_context *draw,
|
||||
draw->vs.position_output = dvs->position_output;
|
||||
draw->vs.edgeflag_output = dvs->edgeflag_output;
|
||||
draw->vs.clipvertex_output = dvs->clipvertex_output;
|
||||
draw->vs.clipdistance_output[0] = dvs->clipdistance_output[0];
|
||||
draw->vs.clipdistance_output[1] = dvs->clipdistance_output[1];
|
||||
dvs->prepare( dvs, draw );
|
||||
}
|
||||
else {
|
||||
|
@@ -112,7 +112,7 @@ struct draw_vertex_shader {
|
||||
unsigned position_output;
|
||||
unsigned edgeflag_output;
|
||||
unsigned clipvertex_output;
|
||||
|
||||
unsigned clipdistance_output[2];
|
||||
/* Extracted from shader:
|
||||
*/
|
||||
const float (*immediates)[4];
|
||||
|
Reference in New Issue
Block a user