+ 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;
+ }
+}
+
+static void
+v3d_update_compiled_vs(struct v3d_context *v3d, uint8_t prim_mode)
+{
+ struct v3d_vs_key local_key;
+ struct v3d_vs_key *key = &local_key;
+
+ if (!(v3d->dirty & (VC5_DIRTY_VERTTEX |
+ VC5_DIRTY_VTXSTATE |
+ VC5_DIRTY_UNCOMPILED_VS |
+ (v3d->prog.bind_gs ? 0 : VC5_DIRTY_RASTERIZER) |
+ (v3d->prog.bind_gs ? 0 : VC5_DIRTY_PRIM_MODE) |
+ (v3d->prog.bind_gs ? VC5_DIRTY_GS_INPUTS :
+ VC5_DIRTY_FS_INPUTS)))) {
+ return;
+ }
+
+ memset(key, 0, sizeof(*key));
+ v3d_setup_shared_key(v3d, &key->base, &v3d->tex[PIPE_SHADER_VERTEX]);
+ key->base.shader_state = v3d->prog.bind_vs;
+ key->base.ucp_enables = v3d->rasterizer->base.clip_plane_enable;
+ key->base.is_last_geometry_stage = !v3d->prog.bind_gs;
+
+ if (!v3d->prog.bind_gs) {
+ 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));
+ } else {
+ key->num_used_outputs = v3d->prog.gs->prog_data.gs->num_inputs;
+ STATIC_ASSERT(sizeof(key->used_outputs) ==
+ sizeof(v3d->prog.gs->prog_data.gs->input_slots));
+ memcpy(key->used_outputs, v3d->prog.gs->prog_data.gs->input_slots,
+ sizeof(key->used_outputs));
+ }
+
+ key->clamp_color = v3d->rasterizer->base.clamp_vertex_color;
+
+ key->per_vertex_point_size =
+ (prim_mode == PIPE_PRIM_POINTS &&
+ v3d->rasterizer->base.point_size_per_vertex);
+
+ struct v3d_compiled_shader *vs =
+ v3d_get_compiled_shader(v3d, &key->base, sizeof(*key));
+ if (vs != v3d->prog.vs) {
+ v3d->prog.vs = vs;
+ v3d->dirty |= VC5_DIRTY_COMPILED_VS;
+ }
+
+ key->is_coord = true;
+
+ /* Coord shaders only output varyings used by transform feedback,
+ * unless they are linked to other shaders in the geometry side
+ * of the pipeline, since in that case any of the output varyings
+ * could be required in later geometry stages to compute
+ * gl_Position or TF outputs.
+ */
+ if (!v3d->prog.bind_gs) {
+ 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 tail_bytes =
+ sizeof(*key->used_outputs) *
+ (key->num_used_outputs -
+ shader_state->num_tf_outputs);
+ memset(&key->used_outputs[shader_state->num_tf_outputs],
+ 0, tail_bytes);
+ }
+ key->num_used_outputs = shader_state->num_tf_outputs;
+ }
+