vc4: Add support for user clip plane and gl_ClipVertex.
authorEric Anholt <eric@anholt.net>
Wed, 15 Oct 2014 14:25:57 +0000 (15:25 +0100)
committerEric Anholt <eric@anholt.net>
Wed, 15 Oct 2014 17:11:46 +0000 (18:11 +0100)
Fixes about 15 piglit tests about interpolation and clipping.

src/gallium/drivers/vc4/vc4_context.h
src/gallium/drivers/vc4/vc4_program.c
src/gallium/drivers/vc4/vc4_qir.c
src/gallium/drivers/vc4/vc4_qir.h
src/gallium/drivers/vc4/vc4_state.c

index 56cfc7b51fa7aef949cd9c7a24d6ccae525c9dd6..45dfa020551470ee036c5a7c60148cece3a2a4bd 100644 (file)
@@ -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;
index a79e354fd81f9878eda5e2e63e8d4358e5492498..f4b723ae8208f9bda62a8dc982449e5589fd9e7e 100644 (file)
@@ -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;
@@ -1397,6 +1401,28 @@ vc4_blend(struct vc4_compile *c, struct qreg *result,
                                    blend->alpha_func);
 }
 
+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)
 {
@@ -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;
@@ -1654,6 +1681,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,
@@ -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;
index 432fb1bf55569e280d1dd4f06f7b624db1102ad4..9c7c15e4924e7de7ca138ae8b138d8576a3b22aa 100644 (file)
@@ -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;
 }
index 0e4b78c02b6f4f645f230bcb74f0164e4f7e27a9..b95dbc33d515953d3393edd2b3a2ae2810c4421a 100644 (file)
@@ -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;
 
index 7ccffebe12e1db9b64e0129c9a033b2bff445221..099006b3e579d16ca9f0dae080102669e9b9022b 100644 (file)
@@ -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