+static void
+v3d_update_compiled_gs(struct v3d_context *v3d, uint8_t prim_mode)
+{
+ struct v3d_gs_key local_key;
+ struct v3d_gs_key *key = &local_key;
+
+ if (!(v3d->dirty & (VC5_DIRTY_GEOMTEX |
+ VC5_DIRTY_RASTERIZER |
+ VC5_DIRTY_UNCOMPILED_GS |
+ VC5_DIRTY_PRIM_MODE |
+ VC5_DIRTY_FS_INPUTS))) {
+ return;
+ }
+
+ if (!v3d->prog.bind_gs) {
+ v3d->prog.gs = NULL;
+ v3d->prog.gs_bin = NULL;
+ return;
+ }
+
+ memset(key, 0, sizeof(*key));
+ v3d_setup_shared_key(v3d, &key->base, &v3d->tex[PIPE_SHADER_GEOMETRY]);
+ key->base.shader_state = v3d->prog.bind_gs;
+ key->base.ucp_enables = v3d->rasterizer->base.clip_plane_enable;
+ key->base.is_last_geometry_stage = true;
+ key->num_used_outputs = v3d->prog.fs->prog_data.fs->num_inputs;
+ STATIC_ASSERT(sizeof(key->used_outputs) ==
+ sizeof(v3d->prog.fs->prog_data.fs->input_slots));
+ memcpy(key->used_outputs, v3d->prog.fs->prog_data.fs->input_slots,
+ sizeof(key->used_outputs));
+
+ key->per_vertex_point_size =
+ (prim_mode == PIPE_PRIM_POINTS &&
+ v3d->rasterizer->base.point_size_per_vertex);
+
+ struct v3d_compiled_shader *gs =
+ v3d_get_compiled_shader(v3d, &key->base, sizeof(*key));
+ if (gs != v3d->prog.gs) {
+ v3d->prog.gs = gs;
+ v3d->dirty |= VC5_DIRTY_COMPILED_GS;
+ }
+
+ key->is_coord = true;
+
+ /* The last bin-mode shader in the geometry pipeline only outputs
+ * varyings used by transform feedback.
+ */
+ struct v3d_uncompiled_shader *shader_state = key->base.shader_state;
+ memcpy(key->used_outputs, shader_state->tf_outputs,
+ sizeof(*key->used_outputs) * shader_state->num_tf_outputs);
+ if (shader_state->num_tf_outputs < key->num_used_outputs) {
+ uint32_t size = sizeof(*key->used_outputs) *
+ (key->num_used_outputs -
+ shader_state->num_tf_outputs);
+ memset(&key->used_outputs[shader_state->num_tf_outputs],
+ 0, size);
+ }
+ key->num_used_outputs = shader_state->num_tf_outputs;
+
+ struct v3d_compiled_shader *old_gs = v3d->prog.gs;
+ struct v3d_compiled_shader *gs_bin =
+ v3d_get_compiled_shader(v3d, &key->base, sizeof(*key));
+ if (gs_bin != old_gs) {
+ v3d->prog.gs_bin = gs_bin;
+ v3d->dirty |= VC5_DIRTY_COMPILED_GS_BIN;
+ }
+
+ if (old_gs && memcmp(v3d->prog.gs->prog_data.gs->input_slots,
+ old_gs->prog_data.gs->input_slots,
+ sizeof(v3d->prog.gs->prog_data.gs->input_slots))) {
+ v3d->dirty |= VC5_DIRTY_GS_INPUTS;
+ }
+}
+