From 201d4c0b2a6f7f0c1d59c4fd5cce4916fc48a2d2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 15 Oct 2014 15:25:57 +0100 Subject: [PATCH] vc4: Add support for user clip plane and gl_ClipVertex. Fixes about 15 piglit tests about interpolation and clipping. --- src/gallium/drivers/vc4/vc4_context.h | 2 + src/gallium/drivers/vc4/vc4_program.c | 84 +++++++++++++++++++++++++++++++++-- src/gallium/drivers/vc4/vc4_qir.c | 2 + src/gallium/drivers/vc4/vc4_qir.h | 3 ++ src/gallium/drivers/vc4/vc4_state.c | 4 +- 5 files changed, 91 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/vc4/vc4_context.h b/src/gallium/drivers/vc4/vc4_context.h index 56cfc7b..45dfa02 100644 --- a/src/gallium/drivers/vc4/vc4_context.h +++ b/src/gallium/drivers/vc4/vc4_context.h @@ -58,6 +58,7 @@ #define VC4_DIRTY_SCISSOR (1 << 17) #define VC4_DIRTY_FLAT_SHADE_FLAGS (1 << 18) #define VC4_DIRTY_PRIM_MODE (1 << 19) +#define VC4_DIRTY_CLIP (1 << 20) #define VC4_SHADER_DIRTY_VP (1 << 0) #define VC4_SHADER_DIRTY_FP (1 << 1) @@ -207,6 +208,7 @@ struct vc4_context { unsigned sample_mask; struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple stipple; + struct pipe_clip_state clip; struct pipe_viewport_state viewport; struct vc4_constbuf_stateobj constbuf[PIPE_SHADER_TYPES]; struct vc4_vertexbuf_stateobj vertexbuf; diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c index a79e354..f4b723a 100644 --- a/src/gallium/drivers/vc4/vc4_program.c +++ b/src/gallium/drivers/vc4/vc4_program.c @@ -53,6 +53,7 @@ struct vc4_key { unsigned wrap_t:3; uint8_t swizzle[4]; } tex[VC4_MAX_TEXTURE_SAMPLERS]; + uint8_t ucp_enables; }; struct vc4_fs_key { @@ -1097,6 +1098,9 @@ emit_tgsi_declaration(struct vc4_compile *c, case TGSI_SEMANTIC_POSITION: c->output_position_index = decl->Range.First * 4; break; + case TGSI_SEMANTIC_CLIPVERTEX: + c->output_clipvertex_index = decl->Range.First * 4; + break; case TGSI_SEMANTIC_COLOR: c->output_color_index = decl->Range.First * 4; break; @@ -1398,6 +1402,28 @@ vc4_blend(struct vc4_compile *c, struct qreg *result, } static void +clip_distance_discard(struct vc4_compile *c) +{ + for (int i = 0; i < PIPE_MAX_CLIP_PLANES; i++) { + if (!(c->key->ucp_enables & (1 << i))) + continue; + + struct qreg dist = emit_fragment_varying(c, + TGSI_SEMANTIC_CLIPDIST, + i, + TGSI_SWIZZLE_X); + + qir_SF(c, dist); + + if (c->discard.file == QFILE_NULL) + c->discard = qir_uniform_f(c, 0.0); + + c->discard = qir_SEL_X_Y_NS(c, qir_uniform_f(c, 1.0), + c->discard); + } +} + +static void alpha_test_discard(struct vc4_compile *c) { struct qreg src_alpha; @@ -1456,6 +1482,7 @@ alpha_test_discard(struct vc4_compile *c) static void emit_frag_end(struct vc4_compile *c) { + clip_distance_discard(c); alpha_test_discard(c); enum pipe_format color_format = c->fs_key->color_format; @@ -1655,6 +1682,45 @@ emit_stub_vpm_read(struct vc4_compile *c) } static void +emit_ucp_clipdistance(struct vc4_compile *c) +{ + struct qreg *clipvertex; + + if (c->output_clipvertex_index != -1) + clipvertex = &c->outputs[c->output_clipvertex_index]; + else if (c->output_position_index != -1) + clipvertex = &c->outputs[c->output_position_index]; + else + return; + + for (int plane = 0; plane < PIPE_MAX_CLIP_PLANES; plane++) { + if (!(c->key->ucp_enables & (1 << plane))) + continue; + + /* Pick the next outputs[] that hasn't been written to, since + * there are no other program writes left to be processed at + * this point. If something had been declared but not written + * (like a w component), we'll just smash over the top of it. + */ + uint32_t output_index = c->num_outputs++; + add_output(c, output_index, + TGSI_SEMANTIC_CLIPDIST, + plane, + TGSI_SWIZZLE_X); + + struct qreg dist = qir_uniform_f(c, 0.0); + for (int i = 0; i < 4; i++) { + struct qreg ucp = + add_uniform(c, QUNIFORM_USER_CLIP_PLANE, + plane * 4 + i); + dist = qir_FADD(c, dist, qir_FMUL(c, clipvertex[i], ucp)); + } + + c->outputs[output_index] = dist; + } +} + +static void emit_vert_end(struct vc4_compile *c, struct vc4_varying_semantic *fs_inputs, uint32_t num_fs_inputs) @@ -1662,6 +1728,8 @@ emit_vert_end(struct vc4_compile *c, struct qreg rcp_w = qir_RCP(c, c->outputs[3]); emit_stub_vpm_read(c); + emit_ucp_clipdistance(c); + emit_scaled_viewport_write(c, rcp_w); emit_zs_write(c, rcp_w); emit_rcp_wc_write(c, rcp_w); @@ -1671,9 +1739,11 @@ emit_vert_end(struct vc4_compile *c, for (int i = 0; i < num_fs_inputs; i++) { struct vc4_varying_semantic *input = &fs_inputs[i]; int j; + for (j = 0; j < c->num_outputs; j++) { struct vc4_varying_semantic *output = &c->output_semantics[j]; + if (input->semantic == output->semantic && input->index == output->index && input->swizzle == output->swizzle) { @@ -1930,7 +2000,8 @@ vc4_get_compiled_shader(struct vc4_context *vc4, enum qstage stage, } static void -vc4_setup_shared_key(struct vc4_key *key, struct vc4_texture_stateobj *texstate) +vc4_setup_shared_key(struct vc4_context *vc4, struct vc4_key *key, + struct vc4_texture_stateobj *texstate) { for (int i = 0; i < texstate->num_textures; i++) { struct pipe_sampler_view *sampler = texstate->textures[i]; @@ -1949,6 +2020,8 @@ vc4_setup_shared_key(struct vc4_key *key, struct vc4_texture_stateobj *texstate) key->tex[i].wrap_t = sampler_state->wrap_t; } } + + key->ucp_enables = vc4->rasterizer->base.clip_plane_enable; } static void @@ -1969,7 +2042,7 @@ vc4_update_compiled_fs(struct vc4_context *vc4, uint8_t prim_mode) } memset(key, 0, sizeof(*key)); - vc4_setup_shared_key(&key->base, &vc4->fragtex); + vc4_setup_shared_key(vc4, &key->base, &vc4->fragtex); key->base.shader_state = vc4->prog.bind_fs; key->is_points = (prim_mode == PIPE_PRIM_POINTS); key->is_lines = (prim_mode >= PIPE_PRIM_LINES && @@ -2026,7 +2099,7 @@ vc4_update_compiled_vs(struct vc4_context *vc4, uint8_t prim_mode) } memset(key, 0, sizeof(*key)); - vc4_setup_shared_key(&key->base, &vc4->verttex); + vc4_setup_shared_key(vc4, &key->base, &vc4->verttex); key->base.shader_state = vc4->prog.bind_vs; key->compiled_fs_id = vc4->prog.fs->program_id; @@ -2345,6 +2418,11 @@ vc4_write_uniforms(struct vc4_context *vc4, struct vc4_compiled_shader *shader, cl_f(&vc4->uniforms, vc4->viewport.scale[2]); break; + case QUNIFORM_USER_CLIP_PLANE: + cl_f(&vc4->uniforms, + vc4->clip.ucp[uinfo->data[i] / 4][uinfo->data[i] % 4]); + break; + case QUNIFORM_TEXTURE_CONFIG_P0: write_texture_p0(vc4, texstate, uinfo->data[i]); break; diff --git a/src/gallium/drivers/vc4/vc4_qir.c b/src/gallium/drivers/vc4/vc4_qir.c index 432fb1b..9c7c15e 100644 --- a/src/gallium/drivers/vc4/vc4_qir.c +++ b/src/gallium/drivers/vc4/vc4_qir.c @@ -292,7 +292,9 @@ qir_compile_init(void) make_empty_list(&c->instructions); c->output_position_index = -1; + c->output_clipvertex_index = -1; c->output_color_index = -1; + c->output_point_size_index = -1; return c; } diff --git a/src/gallium/drivers/vc4/vc4_qir.h b/src/gallium/drivers/vc4/vc4_qir.h index 0e4b78c..b95dbc3 100644 --- a/src/gallium/drivers/vc4/vc4_qir.h +++ b/src/gallium/drivers/vc4/vc4_qir.h @@ -183,6 +183,8 @@ enum quniform_contents { QUNIFORM_VIEWPORT_Z_OFFSET, QUNIFORM_VIEWPORT_Z_SCALE, + QUNIFORM_USER_CLIP_PLANE, + /** * A reference to a texture config parameter 0 uniform. * @@ -272,6 +274,7 @@ struct vc4_compile { uint32_t num_outputs; uint32_t num_texture_samples; uint32_t output_position_index; + uint32_t output_clipvertex_index; uint32_t output_color_index; uint32_t output_point_size_index; diff --git a/src/gallium/drivers/vc4/vc4_state.c b/src/gallium/drivers/vc4/vc4_state.c index 7ccffeb..099006b 100644 --- a/src/gallium/drivers/vc4/vc4_state.c +++ b/src/gallium/drivers/vc4/vc4_state.c @@ -68,7 +68,9 @@ static void vc4_set_clip_state(struct pipe_context *pctx, const struct pipe_clip_state *clip) { - fprintf(stderr, "clip todo\n"); + struct vc4_context *vc4 = vc4_context(pctx); + vc4->clip = *clip; + vc4->dirty |= VC4_DIRTY_CLIP; } static void -- 2.7.4