[Mesa-dev] [PATCH] draw: handle edge flags in llvm path
sroland at vmware.com
sroland at vmware.com
Tue Dec 15 09:06:57 PST 2015
From: Roland Scheidegger <sroland at vmware.com>
We just ignored them altogether. While this feature is rather old-fashioned
supporting it is actually rather trivial.
This fixes the associated piglit tests (2 gl-1.0-edgeflag, 2 gl-2.0-edgeflag
and all (7) of point-vertex-id).
v2: comment fixes, and make the use of the edgeflag in clipmask consistent
with when it's actually there (should be impossible to hit a case where the
difference would actually matter but still...)
---
src/gallium/auxiliary/draw/draw_llvm.c | 86 +++++++++++++++-------
.../draw/draw_pt_fetch_shade_pipeline_llvm.c | 1 +
2 files changed, 61 insertions(+), 26 deletions(-)
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index a966e45..89ed045 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_llvm.c
@@ -880,7 +880,8 @@ store_aos_array(struct gallivm_state *gallivm,
LLVMValueRef* aos,
int attrib,
int num_outputs,
- LLVMValueRef clipmask)
+ LLVMValueRef clipmask,
+ boolean need_edgeflag)
{
LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef attr_index = lp_build_const_int32(gallivm, attrib);
@@ -912,8 +913,14 @@ store_aos_array(struct gallivm_state *gallivm,
*/
assert(DRAW_TOTAL_CLIP_PLANES==14);
/* initialize vertex id:16 = 0xffff, pad:1 = 0, edgeflag:1 = 1 */
- vertex_id_pad_edgeflag = (0xffff << 16) | (1 << DRAW_TOTAL_CLIP_PLANES);
- val = lp_build_const_int_vec(gallivm, lp_int_type(soa_type), vertex_id_pad_edgeflag);
+ if (!need_edgeflag) {
+ vertex_id_pad_edgeflag = (0xffff << 16) | (1 << DRAW_TOTAL_CLIP_PLANES);
+ }
+ else {
+ vertex_id_pad_edgeflag = (0xffff << 16);
+ }
+ val = lp_build_const_int_vec(gallivm, lp_int_type(soa_type),
+ vertex_id_pad_edgeflag);
/* OR with the clipmask */
cliptmp = LLVMBuildOr(builder, val, clipmask, "");
for (i = 0; i < vector_length; i++) {
@@ -943,7 +950,7 @@ convert_to_aos(struct gallivm_state *gallivm,
LLVMValueRef clipmask,
int num_outputs,
struct lp_type soa_type,
- boolean have_clipdist)
+ boolean need_edgeflag)
{
LLVMBuilderRef builder = gallivm->builder;
unsigned chan, attrib, i;
@@ -999,7 +1006,8 @@ convert_to_aos(struct gallivm_state *gallivm,
aos,
attrib,
num_outputs,
- clipmask);
+ clipmask,
+ need_edgeflag);
}
#if DEBUG_STORE
lp_build_printf(gallivm, " # storing end\n");
@@ -1135,11 +1143,7 @@ generate_clipmask(struct draw_llvm *llvm,
struct gallivm_state *gallivm,
struct lp_type vs_type,
LLVMValueRef (*outputs)[TGSI_NUM_CHANNELS],
- boolean clip_xy,
- boolean clip_z,
- boolean clip_user,
- boolean clip_halfz,
- unsigned ucp_enable,
+ struct draw_llvm_variant_key *key,
LLVMValueRef context_ptr,
boolean *have_clipdist)
{
@@ -1155,7 +1159,9 @@ generate_clipmask(struct draw_llvm *llvm,
const unsigned pos = llvm->draw->vs.position_output;
const unsigned cv = llvm->draw->vs.clipvertex_output;
int num_written_clipdistance = llvm->draw->vs.vertex_shader->info.num_written_clipdistance;
- bool have_cd = false;
+ boolean have_cd = false;
+ boolean clip_user = key->clip_user;
+ unsigned ucp_enable = key->ucp_enable;
unsigned cd[2];
cd[0] = llvm->draw->vs.clipdistance_output[0];
@@ -1196,7 +1202,11 @@ generate_clipmask(struct draw_llvm *llvm,
}
/* Cliptest, for hardwired planes */
- if (clip_xy) {
+ /*
+ * XXX should take guardband into account (currently not in key).
+ * Otherwise might run the draw pipeline stages for nothing.
+ */
+ if (key->clip_xy) {
/* plane 1 */
test = lp_build_compare(gallivm, f32_type, PIPE_FUNC_GREATER, pos_x , pos_w);
temp = shift;
@@ -1224,9 +1234,9 @@ generate_clipmask(struct draw_llvm *llvm,
mask = LLVMBuildOr(builder, mask, test, "");
}
- if (clip_z) {
+ if (key->clip_z) {
temp = lp_build_const_int_vec(gallivm, i32_type, 16);
- if (clip_halfz) {
+ if (key->clip_halfz) {
/* plane 5 */
test = lp_build_compare(gallivm, f32_type, PIPE_FUNC_GREATER, zero, pos_z);
test = LLVMBuildAnd(builder, test, temp, "");
@@ -1313,6 +1323,20 @@ generate_clipmask(struct draw_llvm *llvm,
}
}
}
+ if (key->need_edgeflags) {
+ /*
+ * This isn't really part of clipmask but stored the same in vertex
+ * header later, so do it here.
+ */
+ unsigned edge_attr = llvm->draw->vs.edgeflag_output;
+ LLVMValueRef one = lp_build_const_vec(gallivm, f32_type, 1.0);
+ LLVMValueRef edgeflag = LLVMBuildLoad(builder, outputs[edge_attr][0], "");
+ test = lp_build_compare(gallivm, f32_type, PIPE_FUNC_EQUAL, one, edgeflag);
+ temp = lp_build_const_int_vec(gallivm, i32_type,
+ 1LL << DRAW_TOTAL_CLIP_PLANES);
+ test = LLVMBuildAnd(builder, test, temp, "");
+ mask = LLVMBuildOr(builder, mask, test, "");
+ }
return mask;
}
@@ -1324,7 +1348,8 @@ generate_clipmask(struct draw_llvm *llvm,
static LLVMValueRef
clipmask_booli32(struct gallivm_state *gallivm,
const struct lp_type vs_type,
- LLVMValueRef clipmask_bool_ptr)
+ LLVMValueRef clipmask_bool_ptr,
+ boolean edgeflag_in_clipmask)
{
LLVMBuilderRef builder = gallivm->builder;
LLVMTypeRef int32_type = LLVMInt32TypeInContext(gallivm->context);
@@ -1334,8 +1359,18 @@ clipmask_booli32(struct gallivm_state *gallivm,
int i;
/*
- * Can do this with log2(vector length) pack instructions and one extract
- * (as we don't actually need a or) with sse2 which would be way better.
+ * We need to invert the edgeflag bit from the clipmask here
+ * (because the result is really if we want to run the pipeline or not
+ * and we (may) need it if edgeflag was 0).
+ */
+ if (edgeflag_in_clipmask) {
+ struct lp_type i32_type = lp_int_type(vs_type);
+ LLVMValueRef edge = lp_build_const_int_vec(gallivm, i32_type,
+ 1LL << DRAW_TOTAL_CLIP_PLANES);
+ clipmask_bool = LLVMBuildXor(builder, clipmask_bool, edge, "");
+ }
+ /*
+ * Could do much better with just cmp/movmskps.
*/
for (i=0; i < vs_type.length; i++) {
temp = LLVMBuildExtractElement(builder, clipmask_bool,
@@ -1531,8 +1566,9 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
const boolean bypass_viewport = key->has_gs || key->bypass_viewport ||
llvm->draw->vs.vertex_shader->info.writes_viewport_index;
const boolean enable_cliptest = !key->has_gs && (key->clip_xy ||
- key->clip_z ||
- key->clip_user);
+ key->clip_z ||
+ key->clip_user ||
+ key->need_edgeflags);
LLVMValueRef variant_func;
const unsigned pos = llvm->draw->vs.position_output;
const unsigned cv = llvm->draw->vs.clipvertex_output;
@@ -1771,11 +1807,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
gallivm,
vs_type,
outputs,
- key->clip_xy,
- key->clip_z,
- key->clip_user,
- key->clip_halfz,
- key->ucp_enable,
+ key,
context_ptr, &have_clipdist);
temp = LLVMBuildOr(builder, clipmask, temp, "");
/* store temporary clipping boolean value */
@@ -1800,14 +1832,15 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
*/
convert_to_aos(gallivm, io, NULL, outputs, clipmask,
vs_info->num_outputs, vs_type,
- have_clipdist);
+ enable_cliptest && key->need_edgeflags);
}
lp_build_loop_end_cond(&lp_loop, count, step, LLVMIntUGE);
sampler->destroy(sampler);
/* return clipping boolean value for function */
- ret = clipmask_booli32(gallivm, vs_type, clipmask_bool_ptr);
+ ret = clipmask_booli32(gallivm, vs_type, clipmask_bool_ptr,
+ enable_cliptest && key->need_edgeflags);
LLVMBuildRet(builder, ret);
@@ -1841,6 +1874,7 @@ draw_llvm_make_variant_key(struct draw_llvm *llvm, char *store)
key->clip_user = llvm->draw->clip_user;
key->bypass_viewport = llvm->draw->bypass_viewport;
key->clip_halfz = llvm->draw->rasterizer->clip_halfz;
+ /* XXX assumes edgeflag output not at 0 */
key->need_edgeflags = (llvm->draw->vs.edgeflag_output ? TRUE : FALSE);
key->ucp_enable = llvm->draw->rasterizer->clip_plane_enable;
key->has_gs = llvm->draw->gs.geometry_shader != NULL;
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
index 2d7569b..edd4541 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
@@ -453,6 +453,7 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle,
draw->vs.vertex_shader->info.writes_viewport_index)) {
clipped = draw_pt_post_vs_run( fpme->post_vs, vert_info, prim_info );
}
+ /* "clipped" also includes non-one edgeflag */
if (clipped) {
opt |= PT_PIPELINE;
}
--
2.1.4
More information about the mesa-dev
mailing list