• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "zink_batch.h"
2 #include "zink_compiler.h"
3 #include "zink_context.h"
4 #include "zink_descriptors.h"
5 #include "zink_program.h"
6 #include "zink_program_state.hpp"
7 #include "zink_query.h"
8 #include "zink_resource.h"
9 #include "zink_screen.h"
10 #include "zink_state.h"
11 #include "zink_surface.h"
12 #include "zink_inlines.h"
13 
14 #include "util/hash_table.h"
15 #include "util/u_cpu_detect.h"
16 #include "util/u_debug.h"
17 #include "util/u_helpers.h"
18 #include "util/u_inlines.h"
19 #include "util/u_prim.h"
20 #include "util/u_prim_restart.h"
21 #include "util/perf/cpu_trace.h"
22 
23 static void
zink_emit_xfb_counter_barrier(struct zink_context * ctx)24 zink_emit_xfb_counter_barrier(struct zink_context *ctx)
25 {
26    for (unsigned i = 0; i < ctx->num_so_targets; i++) {
27       struct zink_so_target *t = zink_so_target(ctx->so_targets[i]);
28       if (!t)
29          continue;
30       struct zink_resource *res = zink_resource(t->counter_buffer);
31       VkAccessFlags access = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;
32       VkPipelineStageFlags stage = VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT;
33       if (t->counter_buffer_valid) {
34          /* Between the pause and resume there needs to be a memory barrier for the counter buffers
35           * with a source access of VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT
36           * at pipeline stage VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT
37           * to a destination access of VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT
38           * at pipeline stage VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT.
39           *
40           * - from VK_EXT_transform_feedback spec
41           */
42          access |= VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT;
43          stage |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
44       }
45       zink_screen(ctx->base.screen)->buffer_barrier(ctx, res, access, stage);
46       if (!ctx->unordered_blitting)
47          res->obj->unordered_read = false;
48    }
49 }
50 
51 static void
zink_emit_stream_output_targets(struct pipe_context * pctx)52 zink_emit_stream_output_targets(struct pipe_context *pctx)
53 {
54    struct zink_context *ctx = zink_context(pctx);
55    VkBuffer buffers[PIPE_MAX_SO_BUFFERS] = {0};
56    VkDeviceSize buffer_offsets[PIPE_MAX_SO_BUFFERS] = {0};
57    VkDeviceSize buffer_sizes[PIPE_MAX_SO_BUFFERS] = {0};
58 
59    for (unsigned i = 0; i < ctx->num_so_targets; i++) {
60       struct zink_so_target *t = (struct zink_so_target *)ctx->so_targets[i];
61       if (!t) {
62          /* no need to reference this or anything */
63          buffers[i] = zink_resource(ctx->dummy_xfb_buffer)->obj->buffer;
64          buffer_offsets[i] = 0;
65          buffer_sizes[i] = sizeof(uint8_t);
66          continue;
67       }
68       struct zink_resource *res = zink_resource(t->base.buffer);
69       if (!res->so_valid)
70          /* resource has been rebound */
71          t->counter_buffer_valid = false;
72       buffers[i] = res->obj->buffer;
73       zink_batch_reference_resource_rw(ctx, res, true);
74       buffer_offsets[i] = t->base.buffer_offset;
75       buffer_sizes[i] = t->base.buffer_size;
76       res->so_valid = true;
77       if (!ctx->unordered_blitting) {
78          res->obj->unordered_read = res->obj->unordered_write = false;
79          res->obj->access = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;
80          res->obj->access_stage = VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT;
81       }
82       util_range_add(t->base.buffer, &res->valid_buffer_range, t->base.buffer_offset,
83                      t->base.buffer_offset + t->base.buffer_size);
84    }
85 
86    VKCTX(CmdBindTransformFeedbackBuffersEXT)(ctx->bs->cmdbuf, 0, ctx->num_so_targets,
87                                                  buffers, buffer_offsets,
88                                                  buffer_sizes);
89    ctx->dirty_so_targets = false;
90 }
91 
92 ALWAYS_INLINE static void
check_buffer_barrier(struct zink_context * ctx,struct pipe_resource * pres,VkAccessFlags flags,VkPipelineStageFlags pipeline)93 check_buffer_barrier(struct zink_context *ctx, struct pipe_resource *pres, VkAccessFlags flags, VkPipelineStageFlags pipeline)
94 {
95    struct zink_resource *res = zink_resource(pres);
96    zink_screen(ctx->base.screen)->buffer_barrier(ctx, res, flags, pipeline);
97    if (!ctx->unordered_blitting)
98       res->obj->unordered_read = false;
99 }
100 
101 ALWAYS_INLINE static void
barrier_draw_buffers(struct zink_context * ctx,const struct pipe_draw_info * dinfo,const struct pipe_draw_indirect_info * dindirect,struct pipe_resource * index_buffer)102 barrier_draw_buffers(struct zink_context *ctx, const struct pipe_draw_info *dinfo,
103                      const struct pipe_draw_indirect_info *dindirect, struct pipe_resource *index_buffer)
104 {
105    if (index_buffer)
106       check_buffer_barrier(ctx, index_buffer, VK_ACCESS_INDEX_READ_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT);
107    if (dindirect && dindirect->buffer) {
108       check_buffer_barrier(ctx, dindirect->buffer,
109                            VK_ACCESS_INDIRECT_COMMAND_READ_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT);
110       if (dindirect->indirect_draw_count)
111          check_buffer_barrier(ctx, dindirect->indirect_draw_count,
112                               VK_ACCESS_INDIRECT_COMMAND_READ_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT);
113    }
114 }
115 
116 template <zink_dynamic_state DYNAMIC_STATE>
117 static void
zink_bind_vertex_buffers(struct zink_context * ctx)118 zink_bind_vertex_buffers(struct zink_context *ctx)
119 {
120    VkBuffer buffers[PIPE_MAX_ATTRIBS];
121    VkDeviceSize buffer_offsets[PIPE_MAX_ATTRIBS];
122    struct zink_vertex_elements_state *elems = ctx->element_state;
123    struct zink_screen *screen = zink_screen(ctx->base.screen);
124 
125    for (unsigned i = 0; i < elems->hw_state.num_bindings; i++) {
126       struct pipe_vertex_buffer *vb = ctx->vertex_buffers + elems->hw_state.binding_map[i];
127       assert(vb);
128       if (vb->buffer.resource) {
129          struct zink_resource *res = zink_resource(vb->buffer.resource);
130          assert(res->obj->buffer);
131          buffers[i] = res->obj->buffer;
132          buffer_offsets[i] = vb->buffer_offset;
133       } else {
134          buffers[i] = zink_resource(ctx->dummy_vertex_buffer)->obj->buffer;
135          buffer_offsets[i] = 0;
136       }
137    }
138 
139    if (DYNAMIC_STATE != ZINK_NO_DYNAMIC_STATE &&
140        DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT2 &&
141        DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT) {
142       if (elems->hw_state.num_bindings)
143          VKCTX(CmdBindVertexBuffers2)(ctx->bs->cmdbuf, 0,
144                                              elems->hw_state.num_bindings,
145                                              buffers, buffer_offsets, NULL, elems->hw_state.b.strides);
146    } else if (elems->hw_state.num_bindings)
147       VKSCR(CmdBindVertexBuffers)(ctx->bs->cmdbuf, 0,
148                              elems->hw_state.num_bindings,
149                              buffers, buffer_offsets);
150 
151    if (DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT2 || DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT)
152       VKCTX(CmdSetVertexInputEXT)(ctx->bs->cmdbuf,
153                                       elems->hw_state.num_bindings, elems->hw_state.dynbindings,
154                                       elems->hw_state.num_attribs, elems->hw_state.dynattribs);
155 
156    ctx->vertex_buffers_dirty = false;
157 }
158 
159 ALWAYS_INLINE static void
update_drawid(struct zink_context * ctx,unsigned draw_id)160 update_drawid(struct zink_context *ctx, unsigned draw_id)
161 {
162    VKCTX(CmdPushConstants)(ctx->bs->cmdbuf, ctx->curr_program->base.layout, VK_SHADER_STAGE_ALL_GRAPHICS,
163                       offsetof(struct zink_gfx_push_constant, draw_id), sizeof(unsigned),
164                       &draw_id);
165 }
166 
167 ALWAYS_INLINE static void
draw_indexed_need_index_buffer_unref(struct zink_context * ctx,const struct pipe_draw_info * dinfo,const struct pipe_draw_start_count_bias * draws,unsigned num_draws,unsigned draw_id,bool needs_drawid)168 draw_indexed_need_index_buffer_unref(struct zink_context *ctx,
169              const struct pipe_draw_info *dinfo,
170              const struct pipe_draw_start_count_bias *draws,
171              unsigned num_draws,
172              unsigned draw_id,
173              bool needs_drawid)
174 {
175    VkCommandBuffer cmdbuf = ctx->bs->cmdbuf;
176    if (dinfo->increment_draw_id && needs_drawid) {
177       for (unsigned i = 0; i < num_draws; i++) {
178          update_drawid(ctx, draw_id);
179          VKCTX(CmdDrawIndexed)(cmdbuf,
180             draws[i].count, dinfo->instance_count,
181             0, draws[i].index_bias, dinfo->start_instance);
182          draw_id++;
183       }
184    } else {
185       if (needs_drawid)
186          update_drawid(ctx, draw_id);
187       for (unsigned i = 0; i < num_draws; i++)
188          VKCTX(CmdDrawIndexed)(cmdbuf,
189             draws[i].count, dinfo->instance_count,
190             0, draws[i].index_bias, dinfo->start_instance);
191 
192    }
193 }
194 
195 template <zink_multidraw HAS_MULTIDRAW>
196 ALWAYS_INLINE static void
draw_indexed(struct zink_context * ctx,const struct pipe_draw_info * dinfo,const struct pipe_draw_start_count_bias * draws,unsigned num_draws,unsigned draw_id,bool needs_drawid)197 draw_indexed(struct zink_context *ctx,
198              const struct pipe_draw_info *dinfo,
199              const struct pipe_draw_start_count_bias *draws,
200              unsigned num_draws,
201              unsigned draw_id,
202              bool needs_drawid)
203 {
204    VkCommandBuffer cmdbuf = ctx->bs->cmdbuf;
205    if (dinfo->increment_draw_id && needs_drawid) {
206       for (unsigned i = 0; i < num_draws; i++) {
207          update_drawid(ctx, draw_id);
208          VKCTX(CmdDrawIndexed)(cmdbuf,
209             draws[i].count, dinfo->instance_count,
210             draws[i].start, draws[i].index_bias, dinfo->start_instance);
211          draw_id++;
212       }
213    } else {
214       if (needs_drawid)
215          update_drawid(ctx, draw_id);
216       if (HAS_MULTIDRAW) {
217          VKCTX(CmdDrawMultiIndexedEXT)(cmdbuf, num_draws, (const VkMultiDrawIndexedInfoEXT*)draws,
218                                        dinfo->instance_count,
219                                        dinfo->start_instance, sizeof(struct pipe_draw_start_count_bias),
220                                        dinfo->index_bias_varies ? NULL : &draws[0].index_bias);
221       } else {
222          for (unsigned i = 0; i < num_draws; i++)
223             VKCTX(CmdDrawIndexed)(cmdbuf,
224                draws[i].count, dinfo->instance_count,
225                draws[i].start, draws[i].index_bias, dinfo->start_instance);
226       }
227    }
228 }
229 
230 template <zink_multidraw HAS_MULTIDRAW>
231 ALWAYS_INLINE static void
draw(struct zink_context * ctx,const struct pipe_draw_info * dinfo,const struct pipe_draw_start_count_bias * draws,unsigned num_draws,unsigned draw_id,bool needs_drawid)232 draw(struct zink_context *ctx,
233      const struct pipe_draw_info *dinfo,
234      const struct pipe_draw_start_count_bias *draws,
235      unsigned num_draws,
236      unsigned draw_id,
237      bool needs_drawid)
238 {
239    VkCommandBuffer cmdbuf = ctx->bs->cmdbuf;
240    if (dinfo->increment_draw_id && needs_drawid) {
241       for (unsigned i = 0; i < num_draws; i++) {
242          update_drawid(ctx, draw_id);
243          VKCTX(CmdDraw)(cmdbuf, draws[i].count, dinfo->instance_count, draws[i].start, dinfo->start_instance);
244          draw_id++;
245       }
246    } else {
247       if (needs_drawid)
248          update_drawid(ctx, draw_id);
249       if (HAS_MULTIDRAW)
250          VKCTX(CmdDrawMultiEXT)(cmdbuf, num_draws, (const VkMultiDrawInfoEXT*)draws,
251                                 dinfo->instance_count, dinfo->start_instance,
252                                 sizeof(struct pipe_draw_start_count_bias));
253       else {
254          for (unsigned i = 0; i < num_draws; i++)
255             VKCTX(CmdDraw)(cmdbuf, draws[i].count, dinfo->instance_count, draws[i].start, dinfo->start_instance);
256 
257       }
258    }
259 }
260 
261 template <zink_dynamic_state DYNAMIC_STATE, bool BATCH_CHANGED>
262 static bool
update_gfx_pipeline(struct zink_context * ctx,struct zink_batch_state * bs,enum mesa_prim mode)263 update_gfx_pipeline(struct zink_context *ctx, struct zink_batch_state *bs, enum mesa_prim mode)
264 {
265    VkPipeline prev_pipeline = ctx->gfx_pipeline_state.pipeline;
266    const struct zink_screen *screen = zink_screen(ctx->base.screen);
267    bool shaders_changed = ctx->gfx_dirty || ctx->dirty_gfx_stages;
268    if (screen->optimal_keys && !ctx->is_generated_gs_bound)
269       zink_gfx_program_update_optimal(ctx);
270    else
271       zink_gfx_program_update(ctx);
272    bool pipeline_changed = false;
273    VkPipeline pipeline = VK_NULL_HANDLE;
274    if (!ctx->curr_program->base.uses_shobj) {
275       if (screen->info.have_EXT_graphics_pipeline_library)
276          pipeline = zink_get_gfx_pipeline<DYNAMIC_STATE, true>(ctx, ctx->curr_program, &ctx->gfx_pipeline_state, mode);
277       else
278          pipeline = zink_get_gfx_pipeline<DYNAMIC_STATE, false>(ctx, ctx->curr_program, &ctx->gfx_pipeline_state, mode);
279    }
280    if (pipeline) {
281       pipeline_changed = prev_pipeline != pipeline;
282       if (BATCH_CHANGED || pipeline_changed || ctx->shobj_draw)
283          VKCTX(CmdBindPipeline)(bs->cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
284       ctx->shobj_draw = false;
285    } else {
286       if (BATCH_CHANGED || shaders_changed || !ctx->shobj_draw) {
287          VkShaderStageFlagBits stages[] = {
288             VK_SHADER_STAGE_VERTEX_BIT,
289             VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
290             VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
291             VK_SHADER_STAGE_GEOMETRY_BIT,
292             VK_SHADER_STAGE_FRAGMENT_BIT,
293          };
294          /* always rebind all stages */
295          VKCTX(CmdBindShadersEXT)(bs->cmdbuf, ZINK_GFX_SHADER_COUNT, stages, ctx->curr_program->objects);
296          VKCTX(CmdSetDepthBiasEnable)(bs->cmdbuf, VK_TRUE);
297          VKCTX(CmdSetTessellationDomainOriginEXT)(bs->cmdbuf, VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT);
298          VKCTX(CmdSetSampleLocationsEnableEXT)(bs->cmdbuf, ctx->gfx_pipeline_state.sample_locations_enabled);
299          VKCTX(CmdSetRasterizationStreamEXT)(bs->cmdbuf, 0);
300       }
301       ctx->shobj_draw = true;
302    }
303    return pipeline_changed;
304 }
305 
306 static enum mesa_prim
zink_prim_type(const struct zink_context * ctx,const struct pipe_draw_info * dinfo)307 zink_prim_type(const struct zink_context *ctx,
308                const struct pipe_draw_info *dinfo)
309 {
310    if (ctx->gfx_pipeline_state.shader_rast_prim != MESA_PRIM_COUNT)
311       return ctx->gfx_pipeline_state.shader_rast_prim;
312 
313    return u_reduced_prim((enum mesa_prim)dinfo->mode);
314 }
315 
316 static enum mesa_prim
zink_rast_prim(const struct zink_context * ctx,const struct pipe_draw_info * dinfo)317 zink_rast_prim(const struct zink_context *ctx,
318                const struct pipe_draw_info *dinfo)
319 {
320    enum mesa_prim prim_type = zink_prim_type(ctx, dinfo);
321    assert(prim_type != MESA_PRIM_COUNT);
322 
323    if (prim_type == MESA_PRIM_TRIANGLES &&
324        ctx->rast_state->base.fill_front != PIPE_POLYGON_MODE_FILL) {
325       switch(ctx->rast_state->base.fill_front) {
326       case PIPE_POLYGON_MODE_POINT:
327          return MESA_PRIM_POINTS;
328       case PIPE_POLYGON_MODE_LINE:
329          return MESA_PRIM_LINES;
330       default:
331          unreachable("unexpected polygon mode");
332       }
333    }
334 
335    return prim_type;
336 }
337 
338 template <zink_multidraw HAS_MULTIDRAW, zink_dynamic_state DYNAMIC_STATE, bool BATCH_CHANGED, bool DRAW_STATE>
339 void
zink_draw(struct pipe_context * pctx,const struct pipe_draw_info * dinfo,unsigned drawid_offset,const struct pipe_draw_indirect_info * dindirect,const struct pipe_draw_start_count_bias * draws,unsigned num_draws,struct pipe_vertex_state * vstate,uint32_t partial_velem_mask)340 zink_draw(struct pipe_context *pctx,
341           const struct pipe_draw_info *dinfo,
342           unsigned drawid_offset,
343           const struct pipe_draw_indirect_info *dindirect,
344           const struct pipe_draw_start_count_bias *draws,
345           unsigned num_draws,
346           struct pipe_vertex_state *vstate,
347           uint32_t partial_velem_mask)
348 {
349    if (!dindirect && (!draws[0].count || !dinfo->instance_count))
350       return;
351 
352    struct zink_context *ctx = zink_context(pctx);
353    struct zink_screen *screen = zink_screen(pctx->screen);
354    struct zink_rasterizer_state *rast_state = ctx->rast_state;
355    struct zink_depth_stencil_alpha_state *dsa_state = ctx->dsa_state;
356    struct zink_batch_state *bs = ctx->bs;
357    struct zink_so_target *so_target =
358       dindirect && dindirect->count_from_stream_output ?
359          zink_so_target(dindirect->count_from_stream_output) : NULL;
360    VkBuffer counter_buffers[PIPE_MAX_SO_BUFFERS];
361    VkDeviceSize counter_buffer_offsets[PIPE_MAX_SO_BUFFERS];
362    bool need_index_buffer_unref = false;
363    bool mode_changed = ctx->gfx_pipeline_state.gfx_prim_mode != dinfo->mode;
364    bool reads_drawid = ctx->shader_reads_drawid;
365    bool reads_basevertex = ctx->shader_reads_basevertex;
366    unsigned work_count = ctx->work_count;
367    enum mesa_prim mode = (enum mesa_prim)dinfo->mode;
368 
369    if (ctx->memory_barrier && !ctx->blitting)
370       zink_flush_memory_barrier(ctx, false);
371 
372    if (unlikely(ctx->buffer_rebind_counter < screen->buffer_rebind_counter && !ctx->blitting)) {
373       ctx->buffer_rebind_counter = screen->buffer_rebind_counter;
374       zink_rebind_all_buffers(ctx);
375    }
376 
377    if (unlikely(ctx->image_rebind_counter < screen->image_rebind_counter && !ctx->blitting)) {
378       ctx->image_rebind_counter = screen->image_rebind_counter;
379       zink_rebind_all_images(ctx);
380    }
381 
382    unsigned index_offset = 0;
383    unsigned index_size = dinfo->index_size;
384    struct pipe_resource *index_buffer = NULL;
385    if (index_size > 0) {
386       if (dinfo->has_user_indices) {
387          if (!util_upload_index_buffer(pctx, dinfo, &draws[0], &index_buffer, &index_offset, 4)) {
388             debug_printf("util_upload_index_buffer() failed\n");
389             return;
390          }
391          /* this will have extra refs from tc */
392          if (screen->threaded)
393             zink_batch_reference_resource_move(ctx, zink_resource(index_buffer));
394          else
395             zink_batch_reference_resource(ctx, zink_resource(index_buffer));
396       } else {
397          index_buffer = dinfo->index.resource;
398          zink_batch_reference_resource_rw(ctx, zink_resource(index_buffer), false);
399       }
400       assert(index_size <= 4 && index_size != 3);
401       assert(index_size != 1 || screen->info.have_EXT_index_type_uint8);
402    }
403 
404    ctx->was_line_loop = dinfo->was_line_loop;
405 
406    bool have_streamout = !!ctx->num_so_targets;
407    if (have_streamout) {
408       zink_emit_xfb_counter_barrier(ctx);
409       if (ctx->dirty_so_targets) {
410          /* have to loop here and below because barriers must be emitted out of renderpass,
411           * but xfb buffers can't be bound before the renderpass is active to avoid
412           * breaking from recursion
413           */
414          for (unsigned i = 0; i < ctx->num_so_targets; i++) {
415             struct zink_so_target *t = (struct zink_so_target *)ctx->so_targets[i];
416             if (t) {
417                struct zink_resource *res = zink_resource(t->base.buffer);
418                zink_screen(ctx->base.screen)->buffer_barrier(ctx, res,
419                                             VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT);
420                if (!ctx->unordered_blitting)
421                   res->obj->unordered_read = res->obj->unordered_write = false;
422             }
423          }
424       }
425    }
426 
427    barrier_draw_buffers(ctx, dinfo, dindirect, index_buffer);
428    /* this may re-emit draw buffer barriers, but such synchronization is harmless */
429    if (!ctx->blitting)
430       zink_update_barriers(ctx, false, index_buffer, dindirect ? dindirect->buffer : NULL, dindirect ? dindirect->indirect_draw_count : NULL);
431 
432    /* ensure synchronization between doing streamout with counter buffer
433     * and using counter buffer for indirect draw
434     */
435    if (so_target && so_target->counter_buffer_valid) {
436       struct zink_resource *res = zink_resource(so_target->counter_buffer);
437       zink_screen(ctx->base.screen)->buffer_barrier(ctx, res,
438                                    VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT,
439                                    VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT);
440       if (!ctx->unordered_blitting)
441          res->obj->unordered_read = false;
442    }
443 
444    zink_query_update_gs_states(ctx);
445 
446    if (unlikely(zink_debug & ZINK_DEBUG_SYNC)) {
447       zink_batch_no_rp(ctx);
448       VkMemoryBarrier mb;
449       mb.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
450       mb.pNext = NULL;
451       mb.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
452       mb.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
453       VKSCR(CmdPipelineBarrier)(ctx->bs->cmdbuf,
454                                 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
455                                 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
456                                 0, 1, &mb, 0, NULL, 0, NULL);
457    }
458 
459    zink_batch_rp(ctx);
460    /* check dead swapchain */
461    if (unlikely(!ctx->in_rp))
462       return;
463 
464    if (BATCH_CHANGED)
465       zink_update_descriptor_refs(ctx, false);
466 
467    /* these must be after renderpass start to avoid issues with recursion */
468    bool drawid_broken = false;
469    if (reads_drawid && (!dindirect || !dindirect->buffer))
470       drawid_broken = (drawid_offset != 0 ||
471                       (!HAS_MULTIDRAW && num_draws > 1) ||
472                       (HAS_MULTIDRAW && num_draws > 1 && !dinfo->increment_draw_id));
473    if (drawid_broken != zink_get_last_vertex_key(ctx)->push_drawid)
474       zink_set_last_vertex_key(ctx)->push_drawid = drawid_broken;
475 
476    bool rast_prim_changed = false;
477    bool prim_changed = false;
478    bool rast_state_changed = ctx->rast_state_changed;
479    if (mode_changed || ctx->gfx_pipeline_state.modules_changed ||
480        rast_state_changed) {
481       enum mesa_prim rast_prim = zink_rast_prim(ctx, dinfo);
482       if (rast_prim != ctx->gfx_pipeline_state.rast_prim) {
483          bool points_changed =
484             (ctx->gfx_pipeline_state.rast_prim == MESA_PRIM_POINTS) !=
485             (rast_prim == MESA_PRIM_POINTS);
486 
487          prim_changed = ctx->gfx_pipeline_state.rast_prim != rast_prim;
488 
489          static bool rect_warned = false;
490          if (DYNAMIC_STATE >= ZINK_DYNAMIC_STATE3 && rast_prim == MESA_PRIM_LINES && !rect_warned &&
491              (VkLineRasterizationModeEXT)rast_state->hw_state.line_mode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT) {
492             if (screen->info.line_rast_feats.rectangularLines)
493                rect_warned = true;
494             else
495                warn_missing_feature(rect_warned, "rectangularLines");
496          }
497 
498          ctx->gfx_pipeline_state.rast_prim = rast_prim;
499          rast_prim_changed = true;
500 
501          if (points_changed && ctx->rast_state->base.point_quad_rasterization)
502             zink_set_fs_point_coord_key(ctx);
503       }
504    }
505    ctx->gfx_pipeline_state.gfx_prim_mode = mode;
506 
507    if ((mode_changed || prim_changed || rast_state_changed || ctx->gfx_pipeline_state.modules_changed)) {
508       zink_set_primitive_emulation_keys(ctx);
509    }
510 
511    if (index_size) {
512       const VkIndexType index_type[3] = {
513          VK_INDEX_TYPE_UINT8_EXT,
514          VK_INDEX_TYPE_UINT16,
515          VK_INDEX_TYPE_UINT32,
516       };
517       struct zink_resource *res = zink_resource(index_buffer);
518       VKCTX(CmdBindIndexBuffer)(bs->cmdbuf, res->obj->buffer, index_offset, index_type[index_size >> 1]);
519    }
520    if (DYNAMIC_STATE < ZINK_DYNAMIC_STATE2) {
521       if (ctx->gfx_pipeline_state.dyn_state2.primitive_restart != dinfo->primitive_restart)
522          ctx->gfx_pipeline_state.dirty = true;
523       ctx->gfx_pipeline_state.dyn_state2.primitive_restart = dinfo->primitive_restart;
524    }
525 
526    if (have_streamout && ctx->dirty_so_targets)
527       zink_emit_stream_output_targets(pctx);
528 
529    bool pipeline_changed = update_gfx_pipeline<DYNAMIC_STATE, BATCH_CHANGED>(ctx, bs, mode);
530 
531    if (BATCH_CHANGED || ctx->vp_state_changed || (DYNAMIC_STATE == ZINK_NO_DYNAMIC_STATE && pipeline_changed)) {
532       VkViewport viewports[PIPE_MAX_VIEWPORTS];
533       for (unsigned i = 0; i < ctx->vp_state.num_viewports; i++) {
534          VkViewport viewport = {
535             ctx->vp_state.viewport_states[i].translate[0] - ctx->vp_state.viewport_states[i].scale[0],
536             ctx->vp_state.viewport_states[i].translate[1] - ctx->vp_state.viewport_states[i].scale[1],
537             MAX2(ctx->vp_state.viewport_states[i].scale[0] * 2, 1),
538             ctx->vp_state.viewport_states[i].scale[1] * 2,
539             CLAMP(ctx->rast_state->base.clip_halfz ?
540                   ctx->vp_state.viewport_states[i].translate[2] :
541                   ctx->vp_state.viewport_states[i].translate[2] - ctx->vp_state.viewport_states[i].scale[2],
542                   0, 1),
543             CLAMP(ctx->vp_state.viewport_states[i].translate[2] + ctx->vp_state.viewport_states[i].scale[2],
544                   0, 1)
545          };
546          if (!ctx->rast_state->base.half_pixel_center) {
547              /* magic constant value from dxvk */
548              float cf = 0.5f - (1.0f / 128.0f);
549              viewport.x += cf;
550              if (viewport.height < 0)
551                 viewport.y += cf;
552              else
553                 viewport.y -= cf;
554          }
555          viewports[i] = viewport;
556       }
557       if (DYNAMIC_STATE != ZINK_NO_DYNAMIC_STATE)
558          VKCTX(CmdSetViewportWithCount)(bs->cmdbuf, ctx->vp_state.num_viewports, viewports);
559       else
560          VKCTX(CmdSetViewport)(bs->cmdbuf, 0, ctx->vp_state.num_viewports, viewports);
561    }
562    if (BATCH_CHANGED || ctx->scissor_changed || ctx->vp_state_changed || (DYNAMIC_STATE == ZINK_NO_DYNAMIC_STATE && pipeline_changed)) {
563       VkRect2D scissors[PIPE_MAX_VIEWPORTS];
564       if (ctx->rast_state->base.scissor) {
565          for (unsigned i = 0; i < ctx->vp_state.num_viewports; i++) {
566             scissors[i].offset.x = ctx->vp_state.scissor_states[i].minx;
567             scissors[i].offset.y = ctx->vp_state.scissor_states[i].miny;
568             scissors[i].extent.width = ctx->vp_state.scissor_states[i].maxx - ctx->vp_state.scissor_states[i].minx;
569             scissors[i].extent.height = ctx->vp_state.scissor_states[i].maxy - ctx->vp_state.scissor_states[i].miny;
570          }
571       } else {
572          for (unsigned i = 0; i < ctx->vp_state.num_viewports; i++) {
573             scissors[i].offset.x = 0;
574             scissors[i].offset.y = 0;
575             scissors[i].extent.width = ctx->fb_state.width;
576             scissors[i].extent.height = ctx->fb_state.height;
577          }
578       }
579       if (DYNAMIC_STATE != ZINK_NO_DYNAMIC_STATE)
580          VKCTX(CmdSetScissorWithCount)(bs->cmdbuf, ctx->vp_state.num_viewports, scissors);
581       else
582          VKCTX(CmdSetScissor)(bs->cmdbuf, 0, ctx->vp_state.num_viewports, scissors);
583    }
584    ctx->vp_state_changed = false;
585    ctx->scissor_changed = false;
586 
587    if (BATCH_CHANGED || ctx->stencil_ref_changed) {
588       VKCTX(CmdSetStencilReference)(bs->cmdbuf, VK_STENCIL_FACE_FRONT_BIT,
589                                ctx->stencil_ref.ref_value[0]);
590       VKCTX(CmdSetStencilReference)(bs->cmdbuf, VK_STENCIL_FACE_BACK_BIT,
591                                ctx->stencil_ref.ref_value[1]);
592       ctx->stencil_ref_changed = false;
593    }
594 
595    if (DYNAMIC_STATE != ZINK_NO_DYNAMIC_STATE && (BATCH_CHANGED || ctx->dsa_state_changed)) {
596       VKCTX(CmdSetDepthBoundsTestEnable)(bs->cmdbuf, dsa_state->hw_state.depth_bounds_test);
597       if (dsa_state->hw_state.depth_bounds_test)
598          VKCTX(CmdSetDepthBounds)(bs->cmdbuf,
599                              dsa_state->hw_state.min_depth_bounds,
600                              dsa_state->hw_state.max_depth_bounds);
601       VKCTX(CmdSetDepthTestEnable)(bs->cmdbuf, dsa_state->hw_state.depth_test);
602       VKCTX(CmdSetDepthCompareOp)(bs->cmdbuf, dsa_state->hw_state.depth_compare_op);
603       VKCTX(CmdSetDepthWriteEnable)(bs->cmdbuf, dsa_state->hw_state.depth_write);
604       VKCTX(CmdSetStencilTestEnable)(bs->cmdbuf, dsa_state->hw_state.stencil_test);
605       if (dsa_state->hw_state.stencil_test) {
606          VKCTX(CmdSetStencilOp)(bs->cmdbuf, VK_STENCIL_FACE_FRONT_BIT,
607                                        dsa_state->hw_state.stencil_front.failOp,
608                                        dsa_state->hw_state.stencil_front.passOp,
609                                        dsa_state->hw_state.stencil_front.depthFailOp,
610                                        dsa_state->hw_state.stencil_front.compareOp);
611          VKCTX(CmdSetStencilOp)(bs->cmdbuf, VK_STENCIL_FACE_BACK_BIT,
612                                        dsa_state->hw_state.stencil_back.failOp,
613                                        dsa_state->hw_state.stencil_back.passOp,
614                                        dsa_state->hw_state.stencil_back.depthFailOp,
615                                        dsa_state->hw_state.stencil_back.compareOp);
616          if (dsa_state->base.stencil[1].enabled) {
617             VKCTX(CmdSetStencilWriteMask)(bs->cmdbuf, VK_STENCIL_FACE_FRONT_BIT, dsa_state->hw_state.stencil_front.writeMask);
618             VKCTX(CmdSetStencilWriteMask)(bs->cmdbuf, VK_STENCIL_FACE_BACK_BIT, dsa_state->hw_state.stencil_back.writeMask);
619             VKCTX(CmdSetStencilCompareMask)(bs->cmdbuf, VK_STENCIL_FACE_FRONT_BIT, dsa_state->hw_state.stencil_front.compareMask);
620             VKCTX(CmdSetStencilCompareMask)(bs->cmdbuf, VK_STENCIL_FACE_BACK_BIT, dsa_state->hw_state.stencil_back.compareMask);
621          } else {
622             VKCTX(CmdSetStencilWriteMask)(bs->cmdbuf, VK_STENCIL_FACE_FRONT_AND_BACK, dsa_state->hw_state.stencil_front.writeMask);
623             VKCTX(CmdSetStencilCompareMask)(bs->cmdbuf, VK_STENCIL_FACE_FRONT_AND_BACK, dsa_state->hw_state.stencil_front.compareMask);
624          }
625       } else {
626          VKCTX(CmdSetStencilWriteMask)(bs->cmdbuf, VK_STENCIL_FACE_FRONT_AND_BACK, dsa_state->hw_state.stencil_front.writeMask);
627          VKCTX(CmdSetStencilCompareMask)(bs->cmdbuf, VK_STENCIL_FACE_FRONT_AND_BACK, dsa_state->hw_state.stencil_front.compareMask);
628          VKCTX(CmdSetStencilOp)(bs->cmdbuf, VK_STENCIL_FACE_FRONT_AND_BACK, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS);
629       }
630    }
631    ctx->dsa_state_changed = false;
632 
633    if (BATCH_CHANGED || rast_state_changed) {
634       if (DYNAMIC_STATE != ZINK_NO_DYNAMIC_STATE) {
635          VKCTX(CmdSetFrontFace)(bs->cmdbuf, (VkFrontFace)ctx->gfx_pipeline_state.dyn_state1.front_face);
636          VKCTX(CmdSetCullMode)(bs->cmdbuf, ctx->gfx_pipeline_state.dyn_state1.cull_mode);
637       }
638 
639       if (DYNAMIC_STATE >= ZINK_DYNAMIC_STATE3) {
640          if (ctx->ds3_states & BITFIELD_BIT(ZINK_DS3_RAST_STIPPLE))
641             VKCTX(CmdSetLineStippleEXT)(bs->cmdbuf, rast_state->base.line_stipple_factor, rast_state->base.line_stipple_pattern);
642          if (ctx->ds3_states & BITFIELD_BIT(ZINK_DS3_RAST_CLIP))
643             VKCTX(CmdSetDepthClipEnableEXT)(bs->cmdbuf, rast_state->hw_state.depth_clip);
644          if (ctx->ds3_states & BITFIELD_BIT(ZINK_DS3_RAST_CLAMP))
645             VKCTX(CmdSetDepthClampEnableEXT)(bs->cmdbuf, rast_state->hw_state.depth_clamp);
646          if (ctx->ds3_states & BITFIELD_BIT(ZINK_DS3_RAST_POLYGON))
647             VKCTX(CmdSetPolygonModeEXT)(bs->cmdbuf, (VkPolygonMode)rast_state->hw_state.polygon_mode);
648          if (ctx->ds3_states & BITFIELD_BIT(ZINK_DS3_RAST_HALFZ))
649             VKCTX(CmdSetDepthClipNegativeOneToOneEXT)(bs->cmdbuf, !rast_state->hw_state.clip_halfz);
650          if (ctx->ds3_states & BITFIELD_BIT(ZINK_DS3_RAST_PV))
651             VKCTX(CmdSetProvokingVertexModeEXT)(bs->cmdbuf,
652                                                 rast_state->hw_state.pv_last ?
653                                                 VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT :
654                                                 VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT);
655          if (ctx->ds3_states & BITFIELD_BIT(ZINK_DS3_RAST_CLIP))
656             VKCTX(CmdSetLineRasterizationModeEXT)(bs->cmdbuf, rast_state->dynamic_line_mode);
657          if (ctx->ds3_states & BITFIELD_BIT(ZINK_DS3_RAST_STIPPLE_ON))
658             VKCTX(CmdSetLineStippleEnableEXT)(bs->cmdbuf, rast_state->hw_state.line_stipple_enable);
659       }
660    }
661    if ((BATCH_CHANGED || ctx->sample_mask_changed) && screen->have_full_ds3) {
662       VKCTX(CmdSetRasterizationSamplesEXT)(bs->cmdbuf, (VkSampleCountFlagBits)(ctx->gfx_pipeline_state.rast_samples + 1));
663       VKCTX(CmdSetSampleMaskEXT)(bs->cmdbuf, (VkSampleCountFlagBits)(ctx->gfx_pipeline_state.rast_samples + 1), &ctx->gfx_pipeline_state.sample_mask);
664       ctx->sample_mask_changed = false;
665    }
666    if ((BATCH_CHANGED || ctx->blend_state_changed)) {
667       if (ctx->gfx_pipeline_state.blend_state) {
668          if (ctx->ds3_states & BITFIELD_BIT(ZINK_DS3_BLEND_A2C))
669             VKCTX(CmdSetAlphaToCoverageEnableEXT)(bs->cmdbuf, ctx->gfx_pipeline_state.blend_state->alpha_to_coverage &&
670                                                                         ctx->gfx_stages[MESA_SHADER_FRAGMENT]->info.outputs_written & BITFIELD_BIT(FRAG_RESULT_DATA0));
671          if (ctx->ds3_states & BITFIELD_BIT(ZINK_DS3_BLEND_A21))
672             VKCTX(CmdSetAlphaToOneEnableEXT)(bs->cmdbuf, ctx->gfx_pipeline_state.blend_state->alpha_to_one);
673          if (ctx->fb_state.nr_cbufs) {
674             if (ctx->ds3_states & BITFIELD_BIT(ZINK_DS3_BLEND_ON))
675                VKCTX(CmdSetColorBlendEnableEXT)(bs->cmdbuf, 0, ctx->fb_state.nr_cbufs, ctx->gfx_pipeline_state.blend_state->ds3.enables);
676             if (ctx->ds3_states & BITFIELD_BIT(ZINK_DS3_BLEND_WRITE))
677                VKCTX(CmdSetColorWriteMaskEXT)(bs->cmdbuf, 0, ctx->fb_state.nr_cbufs, ctx->gfx_pipeline_state.blend_state->ds3.wrmask);
678             if (ctx->ds3_states & BITFIELD_BIT(ZINK_DS3_BLEND_EQ))
679                VKCTX(CmdSetColorBlendEquationEXT)(bs->cmdbuf, 0, ctx->fb_state.nr_cbufs, ctx->gfx_pipeline_state.blend_state->ds3.eq);
680          }
681          if (ctx->ds3_states & BITFIELD_BIT(ZINK_DS3_BLEND_LOGIC_ON))
682             VKCTX(CmdSetLogicOpEnableEXT)(bs->cmdbuf, ctx->gfx_pipeline_state.blend_state->logicop_enable);
683          if (ctx->ds3_states & BITFIELD_BIT(ZINK_DS3_BLEND_LOGIC))
684             VKCTX(CmdSetLogicOpEXT)(bs->cmdbuf, ctx->gfx_pipeline_state.blend_state->logicop_func);
685       }
686    }
687    ctx->ds3_states = 0;
688 
689    if (BATCH_CHANGED ||
690        /* only re-emit on non-batch change when actually drawing lines */
691        ((ctx->line_width_changed || rast_prim_changed) && ctx->gfx_pipeline_state.rast_prim == MESA_PRIM_LINES)) {
692       VKCTX(CmdSetLineWidth)(bs->cmdbuf, rast_state->line_width);
693       ctx->line_width_changed = false;
694    }
695 
696    if (BATCH_CHANGED || mode_changed ||
697        ctx->gfx_pipeline_state.modules_changed ||
698        rast_state_changed) {
699       bool depth_bias =
700          zink_prim_type(ctx, dinfo) == MESA_PRIM_TRIANGLES &&
701          rast_state->offset_fill;
702 
703       if (depth_bias) {
704          if (rast_state->base.offset_units_unscaled) {
705             VKCTX(CmdSetDepthBias)(bs->cmdbuf, rast_state->offset_units * ctx->depth_bias_scale_factor, rast_state->offset_clamp, rast_state->offset_scale);
706          } else {
707             VKCTX(CmdSetDepthBias)(bs->cmdbuf, rast_state->offset_units, rast_state->offset_clamp, rast_state->offset_scale);
708          }
709       } else {
710          VKCTX(CmdSetDepthBias)(bs->cmdbuf, 0.0f, 0.0f, 0.0f);
711       }
712    }
713    ctx->rast_state_changed = false;
714 
715    if (DYNAMIC_STATE != ZINK_NO_DYNAMIC_STATE) {
716       if (ctx->sample_locations_changed) {
717          VkSampleLocationsInfoEXT loc;
718          zink_init_vk_sample_locations(ctx, &loc);
719          VKCTX(CmdSetSampleLocationsEXT)(bs->cmdbuf, &loc);
720       }
721       ctx->sample_locations_changed = false;
722    }
723 
724    if (BATCH_CHANGED || ctx->blend_color_changed) {
725       VKCTX(CmdSetBlendConstants)(bs->cmdbuf, ctx->blend_constants);
726    }
727    ctx->blend_state_changed = false;
728    ctx->blend_color_changed = false;
729 
730    if (!DRAW_STATE) {
731       if (BATCH_CHANGED || ctx->vertex_buffers_dirty) {
732          if (DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT || ctx->gfx_pipeline_state.uses_dynamic_stride)
733             zink_bind_vertex_buffers<DYNAMIC_STATE>(ctx);
734          else
735             zink_bind_vertex_buffers<ZINK_NO_DYNAMIC_STATE>(ctx);
736       }
737    }
738 
739    if (BATCH_CHANGED) {
740       ctx->pipeline_changed[0] = false;
741       zink_select_draw_vbo(ctx);
742    }
743 
744    if (DYNAMIC_STATE != ZINK_NO_DYNAMIC_STATE && (BATCH_CHANGED || mode_changed))
745       VKCTX(CmdSetPrimitiveTopology)(bs->cmdbuf, zink_primitive_topology(mode));
746 
747    if (DYNAMIC_STATE >= ZINK_DYNAMIC_STATE2 && (BATCH_CHANGED || ctx->primitive_restart != dinfo->primitive_restart)) {
748       VKCTX(CmdSetPrimitiveRestartEnable)(bs->cmdbuf, dinfo->primitive_restart);
749       ctx->primitive_restart = dinfo->primitive_restart;
750    }
751 
752    if (DYNAMIC_STATE >= ZINK_DYNAMIC_STATE2 && (BATCH_CHANGED || ctx->rasterizer_discard_changed)) {
753       VKCTX(CmdSetRasterizerDiscardEnable)(bs->cmdbuf, ctx->gfx_pipeline_state.dyn_state2.rasterizer_discard);
754       ctx->rasterizer_discard_changed = false;
755    }
756 
757    if (zink_program_has_descriptors(&ctx->curr_program->base))
758       zink_descriptors_update(ctx, false);
759 
760    if (ctx->di.any_bindless_dirty &&
761        /* some apps (d3dretrace) call MakeTextureHandleResidentARB randomly */
762        zink_program_has_descriptors(&ctx->curr_program->base) &&
763        ctx->curr_program->base.dd.bindless)
764       zink_descriptors_update_bindless(ctx);
765 
766    if (reads_basevertex) {
767       unsigned draw_mode_is_indexed = index_size > 0;
768       VKCTX(CmdPushConstants)(bs->cmdbuf, ctx->curr_program->base.layout, VK_SHADER_STAGE_ALL_GRAPHICS,
769                         offsetof(struct zink_gfx_push_constant, draw_mode_is_indexed), sizeof(unsigned),
770                         &draw_mode_is_indexed);
771    }
772    if (ctx->curr_program->shaders[MESA_SHADER_TESS_CTRL] &&
773        ctx->curr_program->shaders[MESA_SHADER_TESS_CTRL]->non_fs.is_generated) {
774       VKCTX(CmdPushConstants)(bs->cmdbuf, ctx->curr_program->base.layout, VK_SHADER_STAGE_ALL_GRAPHICS,
775                         offsetof(struct zink_gfx_push_constant, default_inner_level), sizeof(float) * 6,
776                         &ctx->tess_levels[0]);
777    }
778 
779    if (!screen->optimal_keys) {
780       if (zink_get_fs_key(ctx)->lower_line_stipple ||
781           zink_get_gs_key(ctx)->lower_gl_point ||
782           zink_get_fs_key(ctx)->lower_line_smooth) {
783 
784          assert(zink_get_gs_key(ctx)->lower_line_stipple ==
785                 zink_get_fs_key(ctx)->lower_line_stipple);
786 
787          assert(zink_get_gs_key(ctx)->lower_line_smooth ==
788                 zink_get_fs_key(ctx)->lower_line_smooth);
789 
790          float viewport_scale[2] = {
791             ctx->vp_state.viewport_states[0].scale[0],
792             ctx->vp_state.viewport_states[0].scale[1]
793          };
794          VKCTX(CmdPushConstants)(bs->cmdbuf,
795                                  ctx->curr_program->base.layout,
796                                  VK_SHADER_STAGE_ALL_GRAPHICS,
797                                  offsetof(struct zink_gfx_push_constant, viewport_scale),
798                                  sizeof(float) * 2, &viewport_scale);
799 
800          uint32_t stipple = ctx->rast_state->base.line_stipple_pattern;
801          stipple |= ctx->rast_state->base.line_stipple_factor << 16;
802          VKCTX(CmdPushConstants)(bs->cmdbuf,
803                                  ctx->curr_program->base.layout,
804                                  VK_SHADER_STAGE_ALL_GRAPHICS,
805                                  offsetof(struct zink_gfx_push_constant, line_stipple_pattern),
806                                  sizeof(uint32_t), &stipple);
807 
808          if (ctx->gfx_pipeline_state.shader_keys.key[MESA_SHADER_FRAGMENT].key.fs.lower_line_smooth) {
809             float line_width = ctx->rast_state->base.line_width;
810             VKCTX(CmdPushConstants)(bs->cmdbuf,
811                                     ctx->curr_program->base.layout,
812                                     VK_SHADER_STAGE_ALL_GRAPHICS,
813                                     offsetof(struct zink_gfx_push_constant, line_width),
814                                     sizeof(uint32_t), &line_width);
815          }
816       }
817    }
818 
819    if (have_streamout) {
820       for (unsigned i = 0; i < ctx->num_so_targets; i++) {
821          struct zink_so_target *t = zink_so_target(ctx->so_targets[i]);
822          counter_buffers[i] = VK_NULL_HANDLE;
823          if (t) {
824             struct zink_resource *res = zink_resource(t->counter_buffer);
825             t->stride = ctx->last_vertex_stage->sinfo.stride[i];
826             zink_batch_reference_resource_rw(ctx, res, true);
827             if (!ctx->unordered_blitting)
828                res->obj->unordered_read = res->obj->unordered_write = false;
829             if (t->counter_buffer_valid) {
830                counter_buffers[i] = res->obj->buffer;
831                counter_buffer_offsets[i] = t->counter_buffer_offset;
832             }
833          }
834       }
835       VKCTX(CmdBeginTransformFeedbackEXT)(bs->cmdbuf, 0, ctx->num_so_targets, counter_buffers, counter_buffer_offsets);
836    }
837 
838    bool marker = false;
839    if (unlikely(zink_tracing)) {
840       VkViewport viewport = {
841          ctx->vp_state.viewport_states[0].translate[0] - ctx->vp_state.viewport_states[0].scale[0],
842          ctx->vp_state.viewport_states[0].translate[1] - ctx->vp_state.viewport_states[0].scale[1],
843          MAX2(ctx->vp_state.viewport_states[0].scale[0] * 2, 1),
844          ctx->vp_state.viewport_states[0].scale[1] * 2,
845          CLAMP(ctx->rast_state->base.clip_halfz ?
846                ctx->vp_state.viewport_states[0].translate[2] :
847                ctx->vp_state.viewport_states[0].translate[2] - ctx->vp_state.viewport_states[0].scale[2],
848                0, 1),
849          CLAMP(ctx->vp_state.viewport_states[0].translate[2] + ctx->vp_state.viewport_states[0].scale[2],
850                0, 1)
851       };
852       if (ctx->blitting) {
853          bool is_zs = util_format_is_depth_or_stencil(ctx->sampler_views[MESA_SHADER_FRAGMENT][0]->format);
854          marker = zink_cmd_debug_marker_begin(ctx, VK_NULL_HANDLE, "u_blitter(%s->%s, %dx%d)",
855                                               util_format_short_name(ctx->sampler_views[MESA_SHADER_FRAGMENT][0]->format),
856                                               util_format_short_name((is_zs ? ctx->fb_state.zsbuf : ctx->fb_state.cbufs[0])->format),
857                                               lround(viewport.width), lround(viewport.height));
858       } else {
859          marker = zink_cmd_debug_marker_begin(ctx, VK_NULL_HANDLE, "draw(%u cbufs|%s, %dx%d)",
860                                               ctx->fb_state.nr_cbufs,
861                                               ctx->fb_state.zsbuf ? "zsbuf" : "",
862                                               lround(viewport.width), lround(viewport.height));
863       }
864    }
865 
866    bool needs_drawid = reads_drawid && zink_get_last_vertex_key(ctx)->push_drawid;
867    work_count += num_draws;
868    if (index_size > 0) {
869       if (dindirect && dindirect->buffer) {
870          assert(num_draws == 1);
871          if (needs_drawid)
872             update_drawid(ctx, drawid_offset);
873          struct zink_resource *indirect = zink_resource(dindirect->buffer);
874          zink_batch_reference_resource_rw(ctx, indirect, false);
875          if (dindirect->indirect_draw_count) {
876              struct zink_resource *indirect_draw_count = zink_resource(dindirect->indirect_draw_count);
877              zink_batch_reference_resource_rw(ctx, indirect_draw_count, false);
878              VKCTX(CmdDrawIndexedIndirectCount)(bs->cmdbuf, indirect->obj->buffer, dindirect->offset,
879                                                 indirect_draw_count->obj->buffer, dindirect->indirect_draw_count_offset,
880                                                 dindirect->draw_count, dindirect->stride);
881          } else
882             VKCTX(CmdDrawIndexedIndirect)(bs->cmdbuf, indirect->obj->buffer, dindirect->offset, dindirect->draw_count, dindirect->stride);
883       } else {
884          if (need_index_buffer_unref)
885             draw_indexed_need_index_buffer_unref(ctx, dinfo, draws, num_draws, drawid_offset, needs_drawid);
886          else
887             draw_indexed<HAS_MULTIDRAW>(ctx, dinfo, draws, num_draws, drawid_offset, needs_drawid);
888       }
889    } else {
890       if (so_target && screen->info.tf_props.transformFeedbackDraw) {
891          /* GTF-GL46.gtf40.GL3Tests.transform_feedback2.transform_feedback2_api attempts a bogus xfb
892           * draw using a streamout target that has no data
893           * to avoid hanging the gpu, reject any such draws
894           */
895          if (so_target->counter_buffer_valid) {
896             if (needs_drawid)
897                update_drawid(ctx, drawid_offset);
898             zink_batch_reference_resource_rw(ctx, zink_resource(so_target->base.buffer), false);
899             zink_batch_reference_resource_rw(ctx, zink_resource(so_target->counter_buffer), true);
900             VKCTX(CmdDrawIndirectByteCountEXT)(bs->cmdbuf, dinfo->instance_count, dinfo->start_instance,
901                                           zink_resource(so_target->counter_buffer)->obj->buffer, so_target->counter_buffer_offset, 0,
902                                           MIN2(so_target->stride, screen->info.tf_props.maxTransformFeedbackBufferDataStride));
903          }
904       } else if (dindirect && dindirect->buffer) {
905          assert(num_draws == 1);
906          if (needs_drawid)
907             update_drawid(ctx, drawid_offset);
908          struct zink_resource *indirect = zink_resource(dindirect->buffer);
909          zink_batch_reference_resource_rw(ctx, indirect, false);
910          if (dindirect->indirect_draw_count) {
911              struct zink_resource *indirect_draw_count = zink_resource(dindirect->indirect_draw_count);
912              zink_batch_reference_resource_rw(ctx, indirect_draw_count, false);
913              VKCTX(CmdDrawIndirectCount)(bs->cmdbuf, indirect->obj->buffer, dindirect->offset,
914                                            indirect_draw_count->obj->buffer, dindirect->indirect_draw_count_offset,
915                                            dindirect->draw_count, dindirect->stride);
916          } else
917             VKCTX(CmdDrawIndirect)(bs->cmdbuf, indirect->obj->buffer, dindirect->offset, dindirect->draw_count, dindirect->stride);
918       } else {
919          draw<HAS_MULTIDRAW>(ctx, dinfo, draws, num_draws, drawid_offset, needs_drawid);
920       }
921    }
922 
923    if (unlikely(zink_tracing))
924       zink_cmd_debug_marker_end(ctx, bs->cmdbuf, marker);
925 
926    if (have_streamout) {
927       for (unsigned i = 0; i < ctx->num_so_targets; i++) {
928          struct zink_so_target *t = zink_so_target(ctx->so_targets[i]);
929          if (t) {
930             counter_buffers[i] = zink_resource(t->counter_buffer)->obj->buffer;
931             counter_buffer_offsets[i] = t->counter_buffer_offset;
932             t->counter_buffer_valid = true;
933          }
934       }
935       VKCTX(CmdEndTransformFeedbackEXT)(bs->cmdbuf, 0, ctx->num_so_targets, counter_buffers, counter_buffer_offsets);
936    }
937 
938    ctx->last_work_was_compute = false;
939    ctx->work_count = work_count;
940    /* flush if there's >100k draws */
941    if (!ctx->unordered_blitting && (unlikely(work_count >= 30000) || ctx->oom_flush))
942       pctx->flush(pctx, NULL, 0);
943 }
944 
945 template <zink_multidraw HAS_MULTIDRAW, zink_dynamic_state DYNAMIC_STATE, bool BATCH_CHANGED>
946 static void
zink_draw_vbo(struct pipe_context * pctx,const struct pipe_draw_info * info,unsigned drawid_offset,const struct pipe_draw_indirect_info * indirect,const struct pipe_draw_start_count_bias * draws,unsigned num_draws)947 zink_draw_vbo(struct pipe_context *pctx,
948               const struct pipe_draw_info *info,
949               unsigned drawid_offset,
950               const struct pipe_draw_indirect_info *indirect,
951               const struct pipe_draw_start_count_bias *draws,
952               unsigned num_draws)
953 {
954    MESA_TRACE_FUNC();
955    zink_draw<HAS_MULTIDRAW, DYNAMIC_STATE, BATCH_CHANGED, false>(pctx, info, drawid_offset, indirect, draws, num_draws, NULL, 0);
956 }
957 
958 template <util_popcnt HAS_POPCNT>
959 static void
zink_vertex_state_mask(struct zink_context * ctx,struct pipe_vertex_state * vstate,uint32_t partial_velem_mask)960 zink_vertex_state_mask(struct zink_context *ctx, struct pipe_vertex_state *vstate, uint32_t partial_velem_mask)
961 {
962    struct zink_vertex_state *zstate = (struct zink_vertex_state *)vstate;
963    VkCommandBuffer cmdbuf = ctx->bs->cmdbuf;
964 
965    if (partial_velem_mask == vstate->input.full_velem_mask) {
966       VKCTX(CmdSetVertexInputEXT)(cmdbuf,
967                                  zstate->velems.hw_state.num_bindings, zstate->velems.hw_state.dynbindings,
968                                  zstate->velems.hw_state.num_attribs, zstate->velems.hw_state.dynattribs);
969       return;
970    }
971 
972    VkVertexInputAttributeDescription2EXT dynattribs[PIPE_MAX_ATTRIBS];
973    unsigned num_attribs = 0;
974    u_foreach_bit(elem, vstate->input.full_velem_mask & partial_velem_mask) {
975       unsigned idx = util_bitcount_fast<HAS_POPCNT>(vstate->input.full_velem_mask & BITFIELD_MASK(elem));
976       dynattribs[num_attribs] = zstate->velems.hw_state.dynattribs[idx];
977       dynattribs[num_attribs].location = num_attribs;
978       num_attribs++;
979    }
980 
981    VKCTX(CmdSetVertexInputEXT)(cmdbuf,
982                                zstate->velems.hw_state.num_bindings, zstate->velems.hw_state.dynbindings,
983                                num_attribs, dynattribs);
984 }
985 
986 template <util_popcnt HAS_POPCNT>
987 static void
zink_bind_vertex_state(struct zink_context * ctx,struct pipe_vertex_state * vstate,uint32_t partial_velem_mask)988 zink_bind_vertex_state(struct zink_context *ctx, struct pipe_vertex_state *vstate, uint32_t partial_velem_mask)
989 {
990    struct zink_vertex_state *zstate = (struct zink_vertex_state *)vstate;
991    VkCommandBuffer cmdbuf = ctx->bs->cmdbuf;
992    if (!vstate->input.vbuffer.buffer.resource)
993       return;
994 
995    zink_vertex_state_mask<HAS_POPCNT>(ctx, vstate, partial_velem_mask);
996 
997    struct zink_resource *res = zink_resource(vstate->input.vbuffer.buffer.resource);
998    zink_batch_resource_usage_set(ctx->bs, res, false, true);
999    VkDeviceSize offset = vstate->input.vbuffer.buffer_offset;
1000    VKCTX(CmdBindVertexBuffers)(cmdbuf, 0,
1001                                zstate->velems.hw_state.num_bindings,
1002                                &res->obj->buffer, &offset);
1003 }
1004 
1005 template <zink_multidraw HAS_MULTIDRAW, zink_dynamic_state DYNAMIC_STATE, util_popcnt HAS_POPCNT, bool BATCH_CHANGED>
1006 static void
zink_draw_vertex_state(struct pipe_context * pctx,struct pipe_vertex_state * vstate,uint32_t partial_velem_mask,struct pipe_draw_vertex_state_info info,const struct pipe_draw_start_count_bias * draws,unsigned num_draws)1007 zink_draw_vertex_state(struct pipe_context *pctx,
1008                        struct pipe_vertex_state *vstate,
1009                        uint32_t partial_velem_mask,
1010                        struct pipe_draw_vertex_state_info info,
1011                        const struct pipe_draw_start_count_bias *draws,
1012                        unsigned num_draws)
1013 {
1014    struct pipe_draw_info dinfo = {};
1015 
1016    dinfo.mode = info.mode;
1017    dinfo.index_size = 4;
1018    dinfo.instance_count = 1;
1019    dinfo.index.resource = vstate->input.indexbuf;
1020    struct zink_context *ctx = zink_context(pctx);
1021    struct zink_resource *res = zink_resource(vstate->input.vbuffer.buffer.resource);
1022    zink_screen(ctx->base.screen)->buffer_barrier(ctx, res, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
1023                                 VK_PIPELINE_STAGE_VERTEX_INPUT_BIT);
1024    if (!ctx->unordered_blitting)
1025       res->obj->unordered_read = false;
1026    zink_bind_vertex_state<HAS_POPCNT>(ctx, vstate, partial_velem_mask);
1027 
1028    zink_draw<HAS_MULTIDRAW, DYNAMIC_STATE, BATCH_CHANGED, true>(pctx, &dinfo, 0, NULL, draws, num_draws, vstate, partial_velem_mask);
1029    /* ensure ctx->vertex_buffers gets rebound on next non-vstate draw */
1030    ctx->vertex_buffers_dirty = true;
1031 
1032    if (info.take_vertex_state_ownership)
1033       pipe_vertex_state_reference(&vstate, NULL);
1034 }
1035 
1036 template <bool BATCH_CHANGED>
1037 static void
zink_launch_grid(struct pipe_context * pctx,const struct pipe_grid_info * info)1038 zink_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info)
1039 {
1040    struct zink_context *ctx = zink_context(pctx);
1041    struct zink_batch_state *bs = ctx->bs;
1042    struct zink_screen *screen = zink_screen(pctx->screen);
1043 
1044    if (ctx->render_condition_active)
1045       zink_start_conditional_render(ctx);
1046 
1047    if (info->indirect) {
1048       /*
1049          VK_ACCESS_INDIRECT_COMMAND_READ_BIT specifies read access to indirect command data read as
1050          part of an indirect build, trace, drawing or dispatching command. Such access occurs in the
1051          VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT pipeline stage.
1052 
1053          - Chapter 7. Synchronization and Cache Control
1054        */
1055       check_buffer_barrier(ctx, info->indirect, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT);
1056    }
1057 
1058    zink_update_barriers(ctx, true, NULL, info->indirect, NULL);
1059    if (ctx->memory_barrier)
1060       zink_flush_memory_barrier(ctx, true);
1061 
1062    if (unlikely(zink_debug & ZINK_DEBUG_SYNC)) {
1063       zink_batch_no_rp(ctx);
1064       VkMemoryBarrier mb;
1065       mb.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
1066       mb.pNext = NULL;
1067       mb.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
1068       mb.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
1069       VKSCR(CmdPipelineBarrier)(ctx->bs->cmdbuf,
1070                                 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1071                                 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1072                                 0, 1, &mb, 0, NULL, 0, NULL);
1073    }
1074 
1075    zink_program_update_compute_pipeline_state(ctx, ctx->curr_compute, info);
1076    VkPipeline prev_pipeline = ctx->compute_pipeline_state.pipeline;
1077 
1078    if (BATCH_CHANGED) {
1079       zink_update_descriptor_refs(ctx, true);
1080    }
1081    if (ctx->compute_dirty) {
1082       /* update inlinable constants */
1083       zink_update_compute_program(ctx);
1084       ctx->compute_dirty = false;
1085    }
1086 
1087    VkPipeline pipeline = zink_get_compute_pipeline(screen, ctx->curr_compute,
1088                                                &ctx->compute_pipeline_state);
1089 
1090    if (prev_pipeline != pipeline || BATCH_CHANGED)
1091       VKCTX(CmdBindPipeline)(bs->cmdbuf, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
1092    if (BATCH_CHANGED) {
1093       ctx->pipeline_changed[1] = false;
1094       zink_select_launch_grid(ctx);
1095    }
1096 
1097    if (zink_program_has_descriptors(&ctx->curr_compute->base))
1098       zink_descriptors_update(ctx, true);
1099    if (ctx->di.any_bindless_dirty && ctx->curr_compute->base.dd.bindless)
1100       zink_descriptors_update_bindless(ctx);
1101 
1102    ctx->work_count++;
1103    zink_batch_no_rp(ctx);
1104    if (!ctx->queries_disabled)
1105       zink_resume_cs_query(ctx);
1106    if (info->indirect) {
1107       VKCTX(CmdDispatchIndirect)(bs->cmdbuf, zink_resource(info->indirect)->obj->buffer, info->indirect_offset);
1108       zink_batch_reference_resource_rw(ctx, zink_resource(info->indirect), false);
1109    } else
1110       VKCTX(CmdDispatch)(bs->cmdbuf, info->grid[0], info->grid[1], info->grid[2]);
1111    bs->has_work = true;
1112    ctx->last_work_was_compute = true;
1113    /* flush if there's >100k computes */
1114    if (!ctx->unordered_blitting && (unlikely(ctx->work_count >= 30000) || ctx->oom_flush))
1115       pctx->flush(pctx, NULL, 0);
1116 }
1117 
1118 template <zink_multidraw HAS_MULTIDRAW, zink_dynamic_state DYNAMIC_STATE, bool BATCH_CHANGED>
1119 static void
init_batch_changed_functions(struct zink_context * ctx,pipe_draw_func draw_vbo_array[2][6][2],pipe_draw_vertex_state_func draw_state_array[2][6][2][2])1120 init_batch_changed_functions(struct zink_context *ctx, pipe_draw_func draw_vbo_array[2][6][2], pipe_draw_vertex_state_func draw_state_array[2][6][2][2])
1121 {
1122    draw_vbo_array[HAS_MULTIDRAW][DYNAMIC_STATE][BATCH_CHANGED] = zink_draw_vbo<HAS_MULTIDRAW, DYNAMIC_STATE, BATCH_CHANGED>;
1123    draw_state_array[HAS_MULTIDRAW][DYNAMIC_STATE][0][BATCH_CHANGED] = zink_draw_vertex_state<HAS_MULTIDRAW, DYNAMIC_STATE, POPCNT_NO, BATCH_CHANGED>;
1124    draw_state_array[HAS_MULTIDRAW][DYNAMIC_STATE][1][BATCH_CHANGED] = zink_draw_vertex_state<HAS_MULTIDRAW, DYNAMIC_STATE, POPCNT_YES, BATCH_CHANGED>;
1125 }
1126 
1127 template <zink_multidraw HAS_MULTIDRAW, zink_dynamic_state DYNAMIC_STATE>
1128 static void
init_dynamic_state_functions(struct zink_context * ctx,pipe_draw_func draw_vbo_array[2][6][2],pipe_draw_vertex_state_func draw_state_array[2][6][2][2])1129 init_dynamic_state_functions(struct zink_context *ctx, pipe_draw_func draw_vbo_array[2][6][2], pipe_draw_vertex_state_func draw_state_array[2][6][2][2])
1130 {
1131    init_batch_changed_functions<HAS_MULTIDRAW, DYNAMIC_STATE, false>(ctx, draw_vbo_array, draw_state_array);
1132    init_batch_changed_functions<HAS_MULTIDRAW, DYNAMIC_STATE, true>(ctx, draw_vbo_array, draw_state_array);
1133 }
1134 
1135 template <zink_multidraw HAS_MULTIDRAW>
1136 static void
init_multidraw_functions(struct zink_context * ctx,pipe_draw_func draw_vbo_array[2][6][2],pipe_draw_vertex_state_func draw_state_array[2][6][2][2])1137 init_multidraw_functions(struct zink_context *ctx, pipe_draw_func draw_vbo_array[2][6][2], pipe_draw_vertex_state_func draw_state_array[2][6][2][2])
1138 {
1139    init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_NO_DYNAMIC_STATE>(ctx, draw_vbo_array, draw_state_array);
1140    init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_DYNAMIC_STATE>(ctx, draw_vbo_array, draw_state_array);
1141    init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_DYNAMIC_STATE2>(ctx, draw_vbo_array, draw_state_array);
1142    init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_DYNAMIC_VERTEX_INPUT2>(ctx, draw_vbo_array, draw_state_array);
1143    init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_DYNAMIC_STATE3>(ctx, draw_vbo_array, draw_state_array);
1144    init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_DYNAMIC_VERTEX_INPUT>(ctx, draw_vbo_array, draw_state_array);
1145 }
1146 
1147 static void
init_all_draw_functions(struct zink_context * ctx,pipe_draw_func draw_vbo_array[2][6][2],pipe_draw_vertex_state_func draw_state_array[2][6][2][2])1148 init_all_draw_functions(struct zink_context *ctx, pipe_draw_func draw_vbo_array[2][6][2], pipe_draw_vertex_state_func draw_state_array[2][6][2][2])
1149 {
1150    init_multidraw_functions<ZINK_NO_MULTIDRAW>(ctx, draw_vbo_array, draw_state_array);
1151    init_multidraw_functions<ZINK_MULTIDRAW>(ctx, draw_vbo_array, draw_state_array);
1152 }
1153 
1154 template <bool BATCH_CHANGED>
1155 static void
init_grid_batch_changed_functions(struct zink_context * ctx)1156 init_grid_batch_changed_functions(struct zink_context *ctx)
1157 {
1158    ctx->launch_grid[BATCH_CHANGED] = zink_launch_grid<BATCH_CHANGED>;
1159 }
1160 
1161 static void
init_all_grid_functions(struct zink_context * ctx)1162 init_all_grid_functions(struct zink_context *ctx)
1163 {
1164    init_grid_batch_changed_functions<false>(ctx);
1165    init_grid_batch_changed_functions<true>(ctx);
1166 }
1167 
1168 static void
zink_invalid_draw_vbo(struct pipe_context * pipe,const struct pipe_draw_info * dinfo,unsigned drawid_offset,const struct pipe_draw_indirect_info * dindirect,const struct pipe_draw_start_count_bias * draws,unsigned num_draws)1169 zink_invalid_draw_vbo(struct pipe_context *pipe,
1170                       const struct pipe_draw_info *dinfo,
1171                       unsigned drawid_offset,
1172                       const struct pipe_draw_indirect_info *dindirect,
1173                       const struct pipe_draw_start_count_bias *draws,
1174                       unsigned num_draws)
1175 {
1176    unreachable("vertex shader not bound");
1177 }
1178 
1179 static void
zink_invalid_draw_vertex_state(struct pipe_context * pipe,struct pipe_vertex_state * vstate,uint32_t partial_velem_mask,struct pipe_draw_vertex_state_info info,const struct pipe_draw_start_count_bias * draws,unsigned num_draws)1180 zink_invalid_draw_vertex_state(struct pipe_context *pipe,
1181                                struct pipe_vertex_state *vstate,
1182                                uint32_t partial_velem_mask,
1183                                struct pipe_draw_vertex_state_info info,
1184                                const struct pipe_draw_start_count_bias *draws,
1185                                unsigned num_draws)
1186 {
1187    unreachable("vertex shader not bound");
1188 }
1189 
1190 static void
zink_invalid_launch_grid(struct pipe_context * pctx,const struct pipe_grid_info * info)1191 zink_invalid_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info)
1192 {
1193    unreachable("compute shader not bound");
1194 }
1195 
1196 #define STAGE_BASE 0
1197 #define STAGE_BASE_GS (BITFIELD_BIT(MESA_SHADER_GEOMETRY) >> 1)
1198 #define STAGE_BASE_TES (BITFIELD_BIT(MESA_SHADER_TESS_EVAL) >> 1)
1199 #define STAGE_BASE_TES_GS ((BITFIELD_BIT(MESA_SHADER_TESS_EVAL) | BITFIELD_BIT(MESA_SHADER_GEOMETRY)) >> 1)
1200 #define STAGE_BASE_TCS_TES ((BITFIELD_BIT(MESA_SHADER_TESS_CTRL) | BITFIELD_BIT(MESA_SHADER_TESS_EVAL)) >> 1)
1201 #define STAGE_BASE_TCS_TES_GS ((BITFIELD_BIT(MESA_SHADER_TESS_CTRL) | BITFIELD_BIT(MESA_SHADER_TESS_EVAL) | BITFIELD_BIT(MESA_SHADER_GEOMETRY)) >> 1)
1202 
1203 template <unsigned STAGE_MASK>
1204 static uint32_t
hash_gfx_program(const void * key)1205 hash_gfx_program(const void *key)
1206 {
1207    const struct zink_shader **shaders = (const struct zink_shader**)key;
1208    uint32_t base_hash = shaders[MESA_SHADER_VERTEX]->hash ^ shaders[MESA_SHADER_FRAGMENT]->hash;
1209    if (STAGE_MASK == STAGE_BASE) //VS+FS
1210       return base_hash;
1211    if (STAGE_MASK == STAGE_BASE_GS) //VS+GS+FS
1212       return base_hash ^ shaders[MESA_SHADER_GEOMETRY]->hash;
1213    /*VS+TCS+FS isn't a thing */
1214    /*VS+TCS+GS+FS isn't a thing */
1215    if (STAGE_MASK == STAGE_BASE_TES) //VS+TES+FS
1216       return base_hash ^ shaders[MESA_SHADER_TESS_EVAL]->hash;
1217    if (STAGE_MASK == STAGE_BASE_TES_GS) //VS+TES+GS+FS
1218       return base_hash ^ shaders[MESA_SHADER_GEOMETRY]->hash ^ shaders[MESA_SHADER_TESS_EVAL]->hash;
1219    if (STAGE_MASK == STAGE_BASE_TCS_TES) //VS+TCS+TES+FS
1220       return base_hash ^ shaders[MESA_SHADER_TESS_CTRL]->hash ^ shaders[MESA_SHADER_TESS_EVAL]->hash;
1221 
1222    /* all stages */
1223    return base_hash ^ shaders[MESA_SHADER_GEOMETRY]->hash ^ shaders[MESA_SHADER_TESS_CTRL]->hash ^ shaders[MESA_SHADER_TESS_EVAL]->hash;
1224 }
1225 
1226 template <unsigned STAGE_MASK>
1227 static bool
equals_gfx_program(const void * a,const void * b)1228 equals_gfx_program(const void *a, const void *b)
1229 {
1230    const void **sa = (const void**)a;
1231    const void **sb = (const void**)b;
1232    STATIC_ASSERT(MESA_SHADER_VERTEX == 0);
1233    STATIC_ASSERT(MESA_SHADER_TESS_CTRL == 1);
1234    STATIC_ASSERT(MESA_SHADER_TESS_EVAL == 2);
1235    STATIC_ASSERT(MESA_SHADER_GEOMETRY == 3);
1236    STATIC_ASSERT(MESA_SHADER_FRAGMENT == 4);
1237    if (STAGE_MASK == STAGE_BASE) //VS+FS
1238       return sa[MESA_SHADER_VERTEX] == sb[MESA_SHADER_VERTEX] &&
1239              sa[MESA_SHADER_FRAGMENT] == sb[MESA_SHADER_FRAGMENT];
1240    if (STAGE_MASK == STAGE_BASE_GS) //VS+GS+FS
1241       return sa[MESA_SHADER_VERTEX] == sb[MESA_SHADER_VERTEX] &&
1242              !memcmp(&sa[MESA_SHADER_GEOMETRY], &sb[MESA_SHADER_GEOMETRY], sizeof(void*) * 2);
1243    /*VS+TCS+FS isn't a thing */
1244    /*VS+TCS+GS+FS isn't a thing */
1245    if (STAGE_MASK == STAGE_BASE_TES) //VS+TES+FS
1246       return sa[MESA_SHADER_VERTEX] == sb[MESA_SHADER_VERTEX] &&
1247              sa[MESA_SHADER_TESS_EVAL] == sb[MESA_SHADER_TESS_EVAL] &&
1248              sa[MESA_SHADER_FRAGMENT] == sb[MESA_SHADER_FRAGMENT];
1249    if (STAGE_MASK == STAGE_BASE_TES_GS) //VS+TES+GS+FS
1250       return sa[MESA_SHADER_VERTEX] == sb[MESA_SHADER_VERTEX] &&
1251              !memcmp(&sa[MESA_SHADER_TESS_EVAL], &sb[MESA_SHADER_TESS_EVAL], sizeof(void*) * 3);
1252    if (STAGE_MASK == STAGE_BASE_TCS_TES) //VS+TCS+TES+FS
1253       return !memcmp(sa, sb, sizeof(void*) * 3) &&
1254              sa[MESA_SHADER_FRAGMENT] == sb[MESA_SHADER_FRAGMENT];
1255 
1256    /* all stages */
1257    return !memcmp(a, b, sizeof(void*) * ZINK_GFX_SHADER_COUNT);
1258 }
1259 
1260 extern "C"
1261 void
zink_init_draw_functions(struct zink_context * ctx,struct zink_screen * screen)1262 zink_init_draw_functions(struct zink_context *ctx, struct zink_screen *screen)
1263 {
1264    pipe_draw_func draw_vbo_array[2][6] //multidraw, zink_dynamic_state
1265                                 [2];   //batch changed
1266    pipe_draw_vertex_state_func draw_state_array[2][6] //multidraw, zink_dynamic_state
1267                                                [2][2];   //has_popcnt, batch changed
1268    zink_dynamic_state dynamic;
1269    if (screen->info.have_EXT_extended_dynamic_state) {
1270       if (screen->info.have_EXT_extended_dynamic_state2) {
1271          if (screen->info.have_EXT_extended_dynamic_state3) {
1272             if (screen->info.have_EXT_vertex_input_dynamic_state)
1273                dynamic = ZINK_DYNAMIC_VERTEX_INPUT;
1274             else
1275                dynamic = ZINK_DYNAMIC_STATE3;
1276          } else {
1277             if (screen->info.have_EXT_vertex_input_dynamic_state)
1278                dynamic = ZINK_DYNAMIC_VERTEX_INPUT2;
1279             else
1280                dynamic = ZINK_DYNAMIC_STATE2;
1281          }
1282       } else {
1283          dynamic = ZINK_DYNAMIC_STATE;
1284       }
1285    } else {
1286       dynamic = ZINK_NO_DYNAMIC_STATE;
1287    }
1288    init_all_draw_functions(ctx, draw_vbo_array, draw_state_array);
1289    memcpy(ctx->draw_vbo, &draw_vbo_array[screen->info.have_EXT_multi_draw]
1290                                         [dynamic],
1291                                         sizeof(ctx->draw_vbo));
1292    memcpy(ctx->draw_state, &draw_state_array[screen->info.have_EXT_multi_draw]
1293                                           [dynamic][util_get_cpu_caps()->has_popcnt],
1294                                           sizeof(ctx->draw_state));
1295 
1296    /* Bind a fake draw_vbo, so that draw_vbo isn't NULL, which would skip
1297     * initialization of callbacks in upper layers (such as u_threaded_context).
1298     */
1299    ctx->base.draw_vbo = zink_invalid_draw_vbo;
1300    ctx->base.draw_vertex_state = zink_invalid_draw_vertex_state;
1301 
1302    _mesa_hash_table_init(&ctx->program_cache[0], ctx, hash_gfx_program<0>, equals_gfx_program<0>);
1303    _mesa_hash_table_init(&ctx->program_cache[1], ctx, hash_gfx_program<1>, equals_gfx_program<1>);
1304    _mesa_hash_table_init(&ctx->program_cache[2], ctx, hash_gfx_program<2>, equals_gfx_program<2>);
1305    _mesa_hash_table_init(&ctx->program_cache[3], ctx, hash_gfx_program<3>, equals_gfx_program<3>);
1306    _mesa_hash_table_init(&ctx->program_cache[4], ctx, hash_gfx_program<4>, equals_gfx_program<4>);
1307    _mesa_hash_table_init(&ctx->program_cache[5], ctx, hash_gfx_program<5>, equals_gfx_program<5>);
1308    _mesa_hash_table_init(&ctx->program_cache[6], ctx, hash_gfx_program<6>, equals_gfx_program<6>);
1309    _mesa_hash_table_init(&ctx->program_cache[7], ctx, hash_gfx_program<7>, equals_gfx_program<7>);
1310    for (unsigned i = 0; i < ARRAY_SIZE(ctx->program_lock); i++)
1311       simple_mtx_init(&ctx->program_lock[i], mtx_plain);
1312 }
1313 
1314 void
zink_init_grid_functions(struct zink_context * ctx)1315 zink_init_grid_functions(struct zink_context *ctx)
1316 {
1317    init_all_grid_functions(ctx);
1318    /* Bind a fake launch_grid, so that draw_vbo isn't NULL, which would skip
1319     * initialization of callbacks in upper layers (such as u_threaded_context).
1320     */
1321    ctx->base.launch_grid = zink_invalid_launch_grid;
1322 }
1323 
1324 void
zink_init_screen_pipeline_libs(struct zink_screen * screen)1325 zink_init_screen_pipeline_libs(struct zink_screen *screen)
1326 {
1327    _mesa_set_init(&screen->pipeline_libs[0], screen, hash_gfx_program<0>, equals_gfx_program<0>);
1328    _mesa_set_init(&screen->pipeline_libs[1], screen, hash_gfx_program<1>, equals_gfx_program<1>);
1329    _mesa_set_init(&screen->pipeline_libs[2], screen, hash_gfx_program<2>, equals_gfx_program<2>);
1330    _mesa_set_init(&screen->pipeline_libs[3], screen, hash_gfx_program<3>, equals_gfx_program<3>);
1331    _mesa_set_init(&screen->pipeline_libs[4], screen, hash_gfx_program<4>, equals_gfx_program<4>);
1332    _mesa_set_init(&screen->pipeline_libs[5], screen, hash_gfx_program<5>, equals_gfx_program<5>);
1333    _mesa_set_init(&screen->pipeline_libs[6], screen, hash_gfx_program<6>, equals_gfx_program<6>);
1334    _mesa_set_init(&screen->pipeline_libs[7], screen, hash_gfx_program<7>, equals_gfx_program<7>);
1335    for (unsigned i = 0; i < ARRAY_SIZE(screen->pipeline_libs_lock); i++)
1336       simple_mtx_init(&screen->pipeline_libs_lock[i], mtx_plain);
1337 }
1338