1/*
2 * Copyright © 2020 Raspberry Pi
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24#include "v3dv_private.h"
25#include "v3dv_meta_common.h"
26
27#include "compiler/nir/nir_builder.h"
28#include "vk_format_info.h"
29#include "util/u_pack_color.h"
30
31static void
32get_hw_clear_color(struct v3dv_device *device,
33                   const VkClearColorValue *color,
34                   VkFormat fb_format,
35                   VkFormat image_format,
36                   uint32_t internal_type,
37                   uint32_t internal_bpp,
38                   uint32_t *hw_color)
39{
40   const uint32_t internal_size = 4 << internal_bpp;
41
42   /* If the image format doesn't match the framebuffer format, then we are
43    * trying to clear an unsupported tlb format using a compatible
44    * format for the framebuffer. In this case, we want to make sure that
45    * we pack the clear value according to the original format semantics,
46    * not the compatible format.
47    */
48   if (fb_format == image_format) {
49      v3dv_X(device, get_hw_clear_color)(color, internal_type, internal_size,
50                                         hw_color);
51   } else {
52      union util_color uc;
53      enum pipe_format pipe_image_format =
54         vk_format_to_pipe_format(image_format);
55      util_pack_color(color->float32, pipe_image_format, &uc);
56      memcpy(hw_color, uc.ui, internal_size);
57   }
58}
59
60/* Returns true if the implementation is able to handle the case, false
61 * otherwise.
62*/
63static bool
64clear_image_tlb(struct v3dv_cmd_buffer *cmd_buffer,
65                struct v3dv_image *image,
66                const VkClearValue *clear_value,
67                const VkImageSubresourceRange *range)
68{
69   const VkOffset3D origin = { 0, 0, 0 };
70   VkFormat fb_format;
71   if (!v3dv_meta_can_use_tlb(image, &origin, &fb_format))
72      return false;
73
74   uint32_t internal_type, internal_bpp;
75   v3dv_X(cmd_buffer->device, get_internal_type_bpp_for_image_aspects)
76      (fb_format, range->aspectMask,
77       &internal_type, &internal_bpp);
78
79   union v3dv_clear_value hw_clear_value = { 0 };
80   if (range->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
81      get_hw_clear_color(cmd_buffer->device, &clear_value->color, fb_format,
82                         image->vk.format, internal_type, internal_bpp,
83                         &hw_clear_value.color[0]);
84   } else {
85      assert((range->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) ||
86             (range->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT));
87      hw_clear_value.z = clear_value->depthStencil.depth;
88      hw_clear_value.s = clear_value->depthStencil.stencil;
89   }
90
91   uint32_t level_count = vk_image_subresource_level_count(&image->vk, range);
92   uint32_t min_level = range->baseMipLevel;
93   uint32_t max_level = range->baseMipLevel + level_count;
94
95   /* For 3D images baseArrayLayer and layerCount must be 0 and 1 respectively.
96    * Instead, we need to consider the full depth dimension of the image, which
97    * goes from 0 up to the level's depth extent.
98    */
99   uint32_t min_layer;
100   uint32_t max_layer;
101   if (image->vk.image_type != VK_IMAGE_TYPE_3D) {
102      min_layer = range->baseArrayLayer;
103      max_layer = range->baseArrayLayer +
104                  vk_image_subresource_layer_count(&image->vk, range);
105   } else {
106      min_layer = 0;
107      max_layer = 0;
108   }
109
110   for (uint32_t level = min_level; level < max_level; level++) {
111      if (image->vk.image_type == VK_IMAGE_TYPE_3D)
112         max_layer = u_minify(image->vk.extent.depth, level);
113
114      uint32_t width = u_minify(image->vk.extent.width, level);
115      uint32_t height = u_minify(image->vk.extent.height, level);
116
117      struct v3dv_job *job =
118         v3dv_cmd_buffer_start_job(cmd_buffer, -1, V3DV_JOB_TYPE_GPU_CL);
119
120      if (!job)
121         return true;
122
123      v3dv_job_start_frame(job, width, height, max_layer, false,
124                           1, internal_bpp,
125                           image->vk.samples > VK_SAMPLE_COUNT_1_BIT);
126
127      struct v3dv_meta_framebuffer framebuffer;
128      v3dv_X(job->device, meta_framebuffer_init)(&framebuffer, fb_format,
129                                                 internal_type,
130                                                 &job->frame_tiling);
131
132      v3dv_X(job->device, job_emit_binning_flush)(job);
133
134      /* If this triggers it is an application bug: the spec requires
135       * that any aspects to clear are present in the image.
136       */
137      assert(range->aspectMask & image->vk.aspects);
138
139      v3dv_X(job->device, meta_emit_clear_image_rcl)
140         (job, image, &framebuffer, &hw_clear_value,
141          range->aspectMask, min_layer, max_layer, level);
142
143      v3dv_cmd_buffer_finish_job(cmd_buffer);
144   }
145
146   return true;
147}
148
149VKAPI_ATTR void VKAPI_CALL
150v3dv_CmdClearColorImage(VkCommandBuffer commandBuffer,
151                        VkImage _image,
152                        VkImageLayout imageLayout,
153                        const VkClearColorValue *pColor,
154                        uint32_t rangeCount,
155                        const VkImageSubresourceRange *pRanges)
156{
157   V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
158   V3DV_FROM_HANDLE(v3dv_image, image, _image);
159
160   const VkClearValue clear_value = {
161      .color = *pColor,
162   };
163
164   for (uint32_t i = 0; i < rangeCount; i++) {
165      if (clear_image_tlb(cmd_buffer, image, &clear_value, &pRanges[i]))
166         continue;
167      unreachable("Unsupported color clear.");
168   }
169}
170
171VKAPI_ATTR void VKAPI_CALL
172v3dv_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer,
173                               VkImage _image,
174                               VkImageLayout imageLayout,
175                               const VkClearDepthStencilValue *pDepthStencil,
176                               uint32_t rangeCount,
177                               const VkImageSubresourceRange *pRanges)
178{
179   V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
180   V3DV_FROM_HANDLE(v3dv_image, image, _image);
181
182   const VkClearValue clear_value = {
183      .depthStencil = *pDepthStencil,
184   };
185
186   for (uint32_t i = 0; i < rangeCount; i++) {
187      if (clear_image_tlb(cmd_buffer, image, &clear_value, &pRanges[i]))
188         continue;
189      unreachable("Unsupported depth/stencil clear.");
190   }
191}
192
193static void
194destroy_color_clear_pipeline(VkDevice _device,
195                             uint64_t pipeline,
196                             VkAllocationCallbacks *alloc)
197{
198   struct v3dv_meta_color_clear_pipeline *p =
199      (struct v3dv_meta_color_clear_pipeline *) (uintptr_t) pipeline;
200   v3dv_DestroyPipeline(_device, p->pipeline, alloc);
201   if (p->cached)
202      v3dv_DestroyRenderPass(_device, p->pass, alloc);
203   vk_free(alloc, p);
204}
205
206static void
207destroy_depth_clear_pipeline(VkDevice _device,
208                             struct v3dv_meta_depth_clear_pipeline *p,
209                             VkAllocationCallbacks *alloc)
210{
211   v3dv_DestroyPipeline(_device, p->pipeline, alloc);
212   vk_free(alloc, p);
213}
214
215static VkResult
216create_color_clear_pipeline_layout(struct v3dv_device *device,
217                                   VkPipelineLayout *pipeline_layout)
218{
219   /* FIXME: this is abusing a bit the API, since not all of our clear
220    * pipelines have a geometry shader. We could create 2 different pipeline
221    * layouts, but this works for us for now.
222    */
223   VkPushConstantRange ranges[2] = {
224      { VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16 },
225      { VK_SHADER_STAGE_GEOMETRY_BIT, 16, 4 },
226   };
227
228   VkPipelineLayoutCreateInfo info = {
229      .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
230      .setLayoutCount = 0,
231      .pushConstantRangeCount = 2,
232      .pPushConstantRanges = ranges,
233   };
234
235   return v3dv_CreatePipelineLayout(v3dv_device_to_handle(device),
236                                    &info, &device->vk.alloc, pipeline_layout);
237}
238
239static VkResult
240create_depth_clear_pipeline_layout(struct v3dv_device *device,
241                                   VkPipelineLayout *pipeline_layout)
242{
243   /* FIXME: this is abusing a bit the API, since not all of our clear
244    * pipelines have a geometry shader. We could create 2 different pipeline
245    * layouts, but this works for us for now.
246    */
247   VkPushConstantRange ranges[2] = {
248      { VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4 },
249      { VK_SHADER_STAGE_GEOMETRY_BIT, 4, 4 },
250   };
251
252   VkPipelineLayoutCreateInfo info = {
253      .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
254      .setLayoutCount = 0,
255      .pushConstantRangeCount = 2,
256      .pPushConstantRanges = ranges
257   };
258
259   return v3dv_CreatePipelineLayout(v3dv_device_to_handle(device),
260                                    &info, &device->vk.alloc, pipeline_layout);
261}
262
263void
264v3dv_meta_clear_init(struct v3dv_device *device)
265{
266   device->meta.color_clear.cache =
267      _mesa_hash_table_create(NULL, u64_hash, u64_compare);
268
269   create_color_clear_pipeline_layout(device,
270                                      &device->meta.color_clear.p_layout);
271
272   device->meta.depth_clear.cache =
273      _mesa_hash_table_create(NULL, u64_hash, u64_compare);
274
275   create_depth_clear_pipeline_layout(device,
276                                      &device->meta.depth_clear.p_layout);
277}
278
279void
280v3dv_meta_clear_finish(struct v3dv_device *device)
281{
282   VkDevice _device = v3dv_device_to_handle(device);
283
284   hash_table_foreach(device->meta.color_clear.cache, entry) {
285      struct v3dv_meta_color_clear_pipeline *item = entry->data;
286      destroy_color_clear_pipeline(_device, (uintptr_t)item, &device->vk.alloc);
287   }
288   _mesa_hash_table_destroy(device->meta.color_clear.cache, NULL);
289
290   if (device->meta.color_clear.p_layout) {
291      v3dv_DestroyPipelineLayout(_device, device->meta.color_clear.p_layout,
292                                 &device->vk.alloc);
293   }
294
295   hash_table_foreach(device->meta.depth_clear.cache, entry) {
296      struct v3dv_meta_depth_clear_pipeline *item = entry->data;
297      destroy_depth_clear_pipeline(_device, item, &device->vk.alloc);
298   }
299   _mesa_hash_table_destroy(device->meta.depth_clear.cache, NULL);
300
301   if (device->meta.depth_clear.p_layout) {
302      v3dv_DestroyPipelineLayout(_device, device->meta.depth_clear.p_layout,
303                                 &device->vk.alloc);
304   }
305}
306
307static nir_ssa_def *
308gen_rect_vertices(nir_builder *b)
309{
310   nir_ssa_def *vertex_id = nir_load_vertex_id(b);
311
312   /* vertex 0: -1.0, -1.0
313    * vertex 1: -1.0,  1.0
314    * vertex 2:  1.0, -1.0
315    * vertex 3:  1.0,  1.0
316    *
317    * so:
318    *
319    * channel 0 is vertex_id < 2 ? -1.0 :  1.0
320    * channel 1 is vertex id & 1 ?  1.0 : -1.0
321    */
322
323   nir_ssa_def *one = nir_imm_int(b, 1);
324   nir_ssa_def *c0cmp = nir_ilt(b, vertex_id, nir_imm_int(b, 2));
325   nir_ssa_def *c1cmp = nir_ieq(b, nir_iand(b, vertex_id, one), one);
326
327   nir_ssa_def *comp[4];
328   comp[0] = nir_bcsel(b, c0cmp,
329                       nir_imm_float(b, -1.0f),
330                       nir_imm_float(b, 1.0f));
331
332   comp[1] = nir_bcsel(b, c1cmp,
333                       nir_imm_float(b, 1.0f),
334                       nir_imm_float(b, -1.0f));
335   comp[2] = nir_imm_float(b, 0.0f);
336   comp[3] = nir_imm_float(b, 1.0f);
337   return nir_vec(b, comp, 4);
338}
339
340static nir_shader *
341get_clear_rect_vs()
342{
343   const nir_shader_compiler_options *options = v3dv_pipeline_get_nir_options();
344   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_VERTEX, options,
345                                                  "meta clear vs");
346
347   const struct glsl_type *vec4 = glsl_vec4_type();
348   nir_variable *vs_out_pos =
349      nir_variable_create(b.shader, nir_var_shader_out, vec4, "gl_Position");
350   vs_out_pos->data.location = VARYING_SLOT_POS;
351
352   nir_ssa_def *pos = gen_rect_vertices(&b);
353   nir_store_var(&b, vs_out_pos, pos, 0xf);
354
355   return b.shader;
356}
357
358static nir_shader *
359get_clear_rect_gs(uint32_t push_constant_layer_base)
360{
361   /* FIXME: this creates a geometry shader that takes the index of a single
362    * layer to clear from push constants, so we need to emit a draw call for
363    * each layer that we want to clear. We could actually do better and have it
364    * take a range of layers and then emit one triangle per layer to clear,
365    * however, if we were to do this we would need to be careful not to exceed
366    * the maximum number of output vertices allowed in a geometry shader.
367    */
368   const nir_shader_compiler_options *options = v3dv_pipeline_get_nir_options();
369   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_GEOMETRY, options,
370                                                  "meta clear gs");
371   nir_shader *nir = b.shader;
372   nir->info.inputs_read = 1ull << VARYING_SLOT_POS;
373   nir->info.outputs_written = (1ull << VARYING_SLOT_POS) |
374                               (1ull << VARYING_SLOT_LAYER);
375   nir->info.gs.input_primitive = GL_TRIANGLES;
376   nir->info.gs.output_primitive = GL_TRIANGLE_STRIP;
377   nir->info.gs.vertices_in = 3;
378   nir->info.gs.vertices_out = 3;
379   nir->info.gs.invocations = 1;
380   nir->info.gs.active_stream_mask = 0x1;
381
382   /* in vec4 gl_Position[3] */
383   nir_variable *gs_in_pos =
384      nir_variable_create(b.shader, nir_var_shader_in,
385                          glsl_array_type(glsl_vec4_type(), 3, 0),
386                          "in_gl_Position");
387   gs_in_pos->data.location = VARYING_SLOT_POS;
388
389   /* out vec4 gl_Position */
390   nir_variable *gs_out_pos =
391      nir_variable_create(b.shader, nir_var_shader_out, glsl_vec4_type(),
392                          "out_gl_Position");
393   gs_out_pos->data.location = VARYING_SLOT_POS;
394
395   /* out float gl_Layer */
396   nir_variable *gs_out_layer =
397      nir_variable_create(b.shader, nir_var_shader_out, glsl_float_type(),
398                          "out_gl_Layer");
399   gs_out_layer->data.location = VARYING_SLOT_LAYER;
400
401   /* Emit output triangle */
402   for (uint32_t i = 0; i < 3; i++) {
403      /* gl_Position from shader input */
404      nir_deref_instr *in_pos_i =
405         nir_build_deref_array_imm(&b, nir_build_deref_var(&b, gs_in_pos), i);
406      nir_copy_deref(&b, nir_build_deref_var(&b, gs_out_pos), in_pos_i);
407
408      /* gl_Layer from push constants */
409      nir_ssa_def *layer =
410         nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 0),
411                                .base = push_constant_layer_base, .range = 4);
412      nir_store_var(&b, gs_out_layer, layer, 0x1);
413
414      nir_emit_vertex(&b, 0);
415   }
416
417   nir_end_primitive(&b, 0);
418
419   return nir;
420}
421
422static nir_shader *
423get_color_clear_rect_fs(uint32_t rt_idx, VkFormat format)
424{
425   const nir_shader_compiler_options *options = v3dv_pipeline_get_nir_options();
426   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, options,
427                                                  "meta clear fs");
428
429   enum pipe_format pformat = vk_format_to_pipe_format(format);
430   const struct glsl_type *fs_out_type =
431      util_format_is_float(pformat) ? glsl_vec4_type() : glsl_uvec4_type();
432
433   nir_variable *fs_out_color =
434      nir_variable_create(b.shader, nir_var_shader_out, fs_out_type, "out_color");
435   fs_out_color->data.location = FRAG_RESULT_DATA0 + rt_idx;
436
437   nir_ssa_def *color_load = nir_load_push_constant(&b, 4, 32, nir_imm_int(&b, 0), .base = 0, .range = 16);
438   nir_store_var(&b, fs_out_color, color_load, 0xf);
439
440   return b.shader;
441}
442
443static nir_shader *
444get_depth_clear_rect_fs()
445{
446   const nir_shader_compiler_options *options = v3dv_pipeline_get_nir_options();
447   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, options,
448                                                  "meta depth clear fs");
449
450   nir_variable *fs_out_depth =
451      nir_variable_create(b.shader, nir_var_shader_out, glsl_float_type(),
452                          "out_depth");
453   fs_out_depth->data.location = FRAG_RESULT_DEPTH;
454
455   nir_ssa_def *depth_load =
456      nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 0), .base = 0, .range = 4);
457
458   nir_store_var(&b, fs_out_depth, depth_load, 0x1);
459
460   return b.shader;
461}
462
463static VkResult
464create_pipeline(struct v3dv_device *device,
465                struct v3dv_render_pass *pass,
466                uint32_t subpass_idx,
467                uint32_t samples,
468                struct nir_shader *vs_nir,
469                struct nir_shader *gs_nir,
470                struct nir_shader *fs_nir,
471                const VkPipelineVertexInputStateCreateInfo *vi_state,
472                const VkPipelineDepthStencilStateCreateInfo *ds_state,
473                const VkPipelineColorBlendStateCreateInfo *cb_state,
474                const VkPipelineLayout layout,
475                VkPipeline *pipeline)
476{
477   VkPipelineShaderStageCreateInfo stages[3] = { 0 };
478   struct vk_shader_module vs_m;
479   struct vk_shader_module gs_m;
480   struct vk_shader_module fs_m;
481
482   uint32_t stage_count = 0;
483   v3dv_shader_module_internal_init(device, &vs_m, vs_nir);
484   stages[stage_count].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
485   stages[stage_count].stage = VK_SHADER_STAGE_VERTEX_BIT;
486   stages[stage_count].module = vk_shader_module_to_handle(&vs_m);
487   stages[stage_count].pName = "main";
488   stage_count++;
489
490   if (gs_nir) {
491      v3dv_shader_module_internal_init(device, &gs_m, gs_nir);
492      stages[stage_count].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
493      stages[stage_count].stage = VK_SHADER_STAGE_GEOMETRY_BIT;
494      stages[stage_count].module = vk_shader_module_to_handle(&gs_m);
495      stages[stage_count].pName = "main";
496      stage_count++;
497   }
498
499   if (fs_nir) {
500      v3dv_shader_module_internal_init(device, &fs_m, fs_nir);
501      stages[stage_count].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
502      stages[stage_count].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
503      stages[stage_count].module = vk_shader_module_to_handle(&fs_m);
504      stages[stage_count].pName = "main";
505      stage_count++;
506   }
507
508   VkGraphicsPipelineCreateInfo info = {
509      .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
510
511      .stageCount = stage_count,
512      .pStages = stages,
513
514      .pVertexInputState = vi_state,
515
516      .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) {
517         .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
518         .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
519         .primitiveRestartEnable = false,
520      },
521
522      .pViewportState = &(VkPipelineViewportStateCreateInfo) {
523         .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
524         .viewportCount = 1,
525         .scissorCount = 1,
526      },
527
528      .pRasterizationState = &(VkPipelineRasterizationStateCreateInfo) {
529         .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
530         .rasterizerDiscardEnable = false,
531         .polygonMode = VK_POLYGON_MODE_FILL,
532         .cullMode = VK_CULL_MODE_NONE,
533         .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
534         .depthBiasEnable = false,
535      },
536
537      .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
538         .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
539         .rasterizationSamples = samples,
540         .sampleShadingEnable = false,
541         .pSampleMask = NULL,
542         .alphaToCoverageEnable = false,
543         .alphaToOneEnable = false,
544      },
545
546      .pDepthStencilState = ds_state,
547
548      .pColorBlendState = cb_state,
549
550      /* The meta clear pipeline declares all state as dynamic.
551       * As a consequence, vkCmdBindPipeline writes no dynamic state
552       * to the cmd buffer. Therefore, at the end of the meta clear,
553       * we need only restore dynamic state that was vkCmdSet.
554       */
555      .pDynamicState = &(VkPipelineDynamicStateCreateInfo) {
556         .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
557         .dynamicStateCount = 6,
558         .pDynamicStates = (VkDynamicState[]) {
559            VK_DYNAMIC_STATE_VIEWPORT,
560            VK_DYNAMIC_STATE_SCISSOR,
561            VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
562            VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
563            VK_DYNAMIC_STATE_STENCIL_REFERENCE,
564            VK_DYNAMIC_STATE_BLEND_CONSTANTS,
565            VK_DYNAMIC_STATE_DEPTH_BIAS,
566            VK_DYNAMIC_STATE_LINE_WIDTH,
567         },
568      },
569
570      .flags = 0,
571      .layout = layout,
572      .renderPass = v3dv_render_pass_to_handle(pass),
573      .subpass = subpass_idx,
574   };
575
576   VkResult result =
577      v3dv_CreateGraphicsPipelines(v3dv_device_to_handle(device),
578                                   VK_NULL_HANDLE,
579                                   1, &info,
580                                   &device->vk.alloc,
581                                   pipeline);
582
583   ralloc_free(vs_nir);
584   ralloc_free(fs_nir);
585
586   return result;
587}
588
589static VkResult
590create_color_clear_pipeline(struct v3dv_device *device,
591                            struct v3dv_render_pass *pass,
592                            uint32_t subpass_idx,
593                            uint32_t rt_idx,
594                            VkFormat format,
595                            uint32_t samples,
596                            uint32_t components,
597                            bool is_layered,
598                            VkPipelineLayout pipeline_layout,
599                            VkPipeline *pipeline)
600{
601   nir_shader *vs_nir = get_clear_rect_vs();
602   nir_shader *fs_nir = get_color_clear_rect_fs(rt_idx, format);
603   nir_shader *gs_nir = is_layered ? get_clear_rect_gs(16) : NULL;
604
605   const VkPipelineVertexInputStateCreateInfo vi_state = {
606      .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
607      .vertexBindingDescriptionCount = 0,
608      .vertexAttributeDescriptionCount = 0,
609   };
610
611   const VkPipelineDepthStencilStateCreateInfo ds_state = {
612      .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
613      .depthTestEnable = false,
614      .depthWriteEnable = false,
615      .depthBoundsTestEnable = false,
616      .stencilTestEnable = false,
617   };
618
619   assert(subpass_idx < pass->subpass_count);
620   const uint32_t color_count = pass->subpasses[subpass_idx].color_count;
621   assert(rt_idx < color_count);
622
623   VkPipelineColorBlendAttachmentState blend_att_state[V3D_MAX_DRAW_BUFFERS];
624   for (uint32_t i = 0; i < color_count; i++) {
625      blend_att_state[i] = (VkPipelineColorBlendAttachmentState) {
626         .blendEnable = false,
627         .colorWriteMask = i == rt_idx ? components : 0,
628      };
629   }
630
631   const VkPipelineColorBlendStateCreateInfo cb_state = {
632      .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
633      .logicOpEnable = false,
634      .attachmentCount = color_count,
635      .pAttachments = blend_att_state
636   };
637
638   return create_pipeline(device,
639                          pass, subpass_idx,
640                          samples,
641                          vs_nir, gs_nir, fs_nir,
642                          &vi_state,
643                          &ds_state,
644                          &cb_state,
645                          pipeline_layout,
646                          pipeline);
647}
648
649static VkResult
650create_depth_clear_pipeline(struct v3dv_device *device,
651                            VkImageAspectFlags aspects,
652                            struct v3dv_render_pass *pass,
653                            uint32_t subpass_idx,
654                            uint32_t samples,
655                            bool is_layered,
656                            VkPipelineLayout pipeline_layout,
657                            VkPipeline *pipeline)
658{
659   const bool has_depth = aspects & VK_IMAGE_ASPECT_DEPTH_BIT;
660   const bool has_stencil = aspects & VK_IMAGE_ASPECT_STENCIL_BIT;
661   assert(has_depth || has_stencil);
662
663   nir_shader *vs_nir = get_clear_rect_vs();
664   nir_shader *fs_nir = has_depth ? get_depth_clear_rect_fs() : NULL;
665   nir_shader *gs_nir = is_layered ? get_clear_rect_gs(4) : NULL;
666
667   const VkPipelineVertexInputStateCreateInfo vi_state = {
668      .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
669      .vertexBindingDescriptionCount = 0,
670      .vertexAttributeDescriptionCount = 0,
671   };
672
673   const VkPipelineDepthStencilStateCreateInfo ds_state = {
674      .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
675      .depthTestEnable = has_depth,
676      .depthWriteEnable = has_depth,
677      .depthCompareOp = VK_COMPARE_OP_ALWAYS,
678      .depthBoundsTestEnable = false,
679      .stencilTestEnable = has_stencil,
680      .front = {
681         .passOp = VK_STENCIL_OP_REPLACE,
682         .compareOp = VK_COMPARE_OP_ALWAYS,
683         /* compareMask, writeMask and reference are dynamic state */
684      },
685      .back = { 0 },
686   };
687
688   assert(subpass_idx < pass->subpass_count);
689   VkPipelineColorBlendAttachmentState blend_att_state[V3D_MAX_DRAW_BUFFERS] = { 0 };
690   const VkPipelineColorBlendStateCreateInfo cb_state = {
691      .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
692      .logicOpEnable = false,
693      .attachmentCount = pass->subpasses[subpass_idx].color_count,
694      .pAttachments = blend_att_state,
695   };
696
697   return create_pipeline(device,
698                          pass, subpass_idx,
699                          samples,
700                          vs_nir, gs_nir, fs_nir,
701                          &vi_state,
702                          &ds_state,
703                          &cb_state,
704                          pipeline_layout,
705                          pipeline);
706}
707
708static VkResult
709create_color_clear_render_pass(struct v3dv_device *device,
710                               uint32_t rt_idx,
711                               VkFormat format,
712                               uint32_t samples,
713                               VkRenderPass *pass)
714{
715   VkAttachmentDescription att = {
716      .format = format,
717      .samples = samples,
718      .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
719      .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
720      .initialLayout = VK_IMAGE_LAYOUT_GENERAL,
721      .finalLayout = VK_IMAGE_LAYOUT_GENERAL,
722   };
723
724   VkAttachmentReference att_ref = {
725      .attachment = rt_idx,
726      .layout = VK_IMAGE_LAYOUT_GENERAL,
727   };
728
729   VkSubpassDescription subpass = {
730      .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
731      .inputAttachmentCount = 0,
732      .colorAttachmentCount = 1,
733      .pColorAttachments = &att_ref,
734      .pResolveAttachments = NULL,
735      .pDepthStencilAttachment = NULL,
736      .preserveAttachmentCount = 0,
737      .pPreserveAttachments = NULL,
738   };
739
740   VkRenderPassCreateInfo info = {
741      .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
742      .attachmentCount = 1,
743      .pAttachments = &att,
744      .subpassCount = 1,
745      .pSubpasses = &subpass,
746      .dependencyCount = 0,
747      .pDependencies = NULL,
748   };
749
750   return v3dv_CreateRenderPass(v3dv_device_to_handle(device),
751                                &info, &device->vk.alloc, pass);
752}
753
754static inline uint64_t
755get_color_clear_pipeline_cache_key(uint32_t rt_idx,
756                                   VkFormat format,
757                                   uint32_t samples,
758                                   uint32_t components,
759                                   bool is_layered)
760{
761   assert(rt_idx < V3D_MAX_DRAW_BUFFERS);
762
763   uint64_t key = 0;
764   uint32_t bit_offset = 0;
765
766   key |= rt_idx;
767   bit_offset += 2;
768
769   key |= ((uint64_t) format) << bit_offset;
770   bit_offset += 32;
771
772   key |= ((uint64_t) samples) << bit_offset;
773   bit_offset += 4;
774
775   key |= ((uint64_t) components) << bit_offset;
776   bit_offset += 4;
777
778   key |= (is_layered ? 1ull : 0ull) << bit_offset;
779   bit_offset += 1;
780
781   assert(bit_offset <= 64);
782   return key;
783}
784
785static inline uint64_t
786get_depth_clear_pipeline_cache_key(VkImageAspectFlags aspects,
787                                   VkFormat format,
788                                   uint32_t samples,
789                                   bool is_layered)
790{
791   uint64_t key = 0;
792   uint32_t bit_offset = 0;
793
794   key |= format;
795   bit_offset += 32;
796
797   key |= ((uint64_t) samples) << bit_offset;
798   bit_offset += 4;
799
800   const bool has_depth = (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) ? 1 : 0;
801   key |= ((uint64_t) has_depth) << bit_offset;
802   bit_offset++;
803
804   const bool has_stencil = (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) ? 1 : 0;
805   key |= ((uint64_t) has_stencil) << bit_offset;
806   bit_offset++;;
807
808   key |= (is_layered ? 1ull : 0ull) << bit_offset;
809   bit_offset += 1;
810
811   assert(bit_offset <= 64);
812   return key;
813}
814
815static VkResult
816get_color_clear_pipeline(struct v3dv_device *device,
817                         struct v3dv_render_pass *pass,
818                         uint32_t subpass_idx,
819                         uint32_t rt_idx,
820                         uint32_t attachment_idx,
821                         VkFormat format,
822                         uint32_t samples,
823                         uint32_t components,
824                         bool is_layered,
825                         struct v3dv_meta_color_clear_pipeline **pipeline)
826{
827   assert(vk_format_is_color(format));
828
829   VkResult result = VK_SUCCESS;
830
831   /* If pass != NULL it means that we are emitting the clear as a draw call
832    * in the current pass bound by the application. In that case, we can't
833    * cache the pipeline, since it will be referencing that pass and the
834    * application could be destroying it at any point. Hopefully, the perf
835    * impact is not too big since we still have the device pipeline cache
836    * around and we won't end up re-compiling the clear shader.
837    *
838    * FIXME: alternatively, we could refcount (or maybe clone) the render pass
839    * provided by the application and include it in the pipeline key setup
840    * to make caching safe in this scenario, however, based on tests with
841    * vkQuake3, the fact that we are not caching here doesn't seem to have
842    * any significant impact in performance, so it might not be worth it.
843    */
844   const bool can_cache_pipeline = (pass == NULL);
845
846   uint64_t key;
847   if (can_cache_pipeline) {
848      key = get_color_clear_pipeline_cache_key(rt_idx, format, samples,
849                                               components, is_layered);
850      mtx_lock(&device->meta.mtx);
851      struct hash_entry *entry =
852         _mesa_hash_table_search(device->meta.color_clear.cache, &key);
853      if (entry) {
854         mtx_unlock(&device->meta.mtx);
855         *pipeline = entry->data;
856         return VK_SUCCESS;
857      }
858   }
859
860   *pipeline = vk_zalloc2(&device->vk.alloc, NULL, sizeof(**pipeline), 8,
861                          VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
862
863   if (*pipeline == NULL) {
864      result = VK_ERROR_OUT_OF_HOST_MEMORY;
865      goto fail;
866   }
867
868   if (!pass) {
869      result = create_color_clear_render_pass(device,
870                                              rt_idx,
871                                              format,
872                                              samples,
873                                              &(*pipeline)->pass);
874      if (result != VK_SUCCESS)
875         goto fail;
876
877      pass = v3dv_render_pass_from_handle((*pipeline)->pass);
878   } else {
879      (*pipeline)->pass = v3dv_render_pass_to_handle(pass);
880   }
881
882   result = create_color_clear_pipeline(device,
883                                        pass,
884                                        subpass_idx,
885                                        rt_idx,
886                                        format,
887                                        samples,
888                                        components,
889                                        is_layered,
890                                        device->meta.color_clear.p_layout,
891                                        &(*pipeline)->pipeline);
892   if (result != VK_SUCCESS)
893      goto fail;
894
895   if (can_cache_pipeline) {
896      (*pipeline)->key = key;
897      (*pipeline)->cached = true;
898      _mesa_hash_table_insert(device->meta.color_clear.cache,
899                              &(*pipeline)->key, *pipeline);
900
901      mtx_unlock(&device->meta.mtx);
902   }
903
904   return VK_SUCCESS;
905
906fail:
907   if (can_cache_pipeline)
908      mtx_unlock(&device->meta.mtx);
909
910   VkDevice _device = v3dv_device_to_handle(device);
911   if (*pipeline) {
912      if ((*pipeline)->cached)
913         v3dv_DestroyRenderPass(_device, (*pipeline)->pass, &device->vk.alloc);
914      if ((*pipeline)->pipeline)
915         v3dv_DestroyPipeline(_device, (*pipeline)->pipeline, &device->vk.alloc);
916      vk_free(&device->vk.alloc, *pipeline);
917      *pipeline = NULL;
918   }
919
920   return result;
921}
922
923static VkResult
924get_depth_clear_pipeline(struct v3dv_device *device,
925                         VkImageAspectFlags aspects,
926                         struct v3dv_render_pass *pass,
927                         uint32_t subpass_idx,
928                         uint32_t attachment_idx,
929                         bool is_layered,
930                         struct v3dv_meta_depth_clear_pipeline **pipeline)
931{
932   assert(subpass_idx < pass->subpass_count);
933   assert(attachment_idx != VK_ATTACHMENT_UNUSED);
934   assert(attachment_idx < pass->attachment_count);
935
936   VkResult result = VK_SUCCESS;
937
938   const uint32_t samples = pass->attachments[attachment_idx].desc.samples;
939   const VkFormat format = pass->attachments[attachment_idx].desc.format;
940   assert(vk_format_is_depth_or_stencil(format));
941
942   const uint64_t key =
943      get_depth_clear_pipeline_cache_key(aspects, format, samples, is_layered);
944   mtx_lock(&device->meta.mtx);
945   struct hash_entry *entry =
946      _mesa_hash_table_search(device->meta.depth_clear.cache, &key);
947   if (entry) {
948      mtx_unlock(&device->meta.mtx);
949      *pipeline = entry->data;
950      return VK_SUCCESS;
951   }
952
953   *pipeline = vk_zalloc2(&device->vk.alloc, NULL, sizeof(**pipeline), 8,
954                          VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
955
956   if (*pipeline == NULL) {
957      result = VK_ERROR_OUT_OF_HOST_MEMORY;
958      goto fail;
959   }
960
961   result = create_depth_clear_pipeline(device,
962                                        aspects,
963                                        pass,
964                                        subpass_idx,
965                                        samples,
966                                        is_layered,
967                                        device->meta.depth_clear.p_layout,
968                                        &(*pipeline)->pipeline);
969   if (result != VK_SUCCESS)
970      goto fail;
971
972   (*pipeline)->key = key;
973   _mesa_hash_table_insert(device->meta.depth_clear.cache,
974                           &(*pipeline)->key, *pipeline);
975
976   mtx_unlock(&device->meta.mtx);
977   return VK_SUCCESS;
978
979fail:
980   mtx_unlock(&device->meta.mtx);
981
982   VkDevice _device = v3dv_device_to_handle(device);
983   if (*pipeline) {
984      if ((*pipeline)->pipeline)
985         v3dv_DestroyPipeline(_device, (*pipeline)->pipeline, &device->vk.alloc);
986      vk_free(&device->vk.alloc, *pipeline);
987      *pipeline = NULL;
988   }
989
990   return result;
991}
992
993/* Emits a scissored quad in the clear color */
994static void
995emit_subpass_color_clear_rects(struct v3dv_cmd_buffer *cmd_buffer,
996                               struct v3dv_render_pass *pass,
997                               struct v3dv_subpass *subpass,
998                               uint32_t rt_idx,
999                               const VkClearColorValue *clear_color,
1000                               bool is_layered,
1001                               bool all_rects_same_layers,
1002                               uint32_t rect_count,
1003                               const VkClearRect *rects)
1004{
1005   /* Skip if attachment is unused in the current subpass */
1006   assert(rt_idx < subpass->color_count);
1007   const uint32_t attachment_idx = subpass->color_attachments[rt_idx].attachment;
1008   if (attachment_idx == VK_ATTACHMENT_UNUSED)
1009      return;
1010
1011   /* Obtain a pipeline for this clear */
1012   assert(attachment_idx < cmd_buffer->state.pass->attachment_count);
1013   const VkFormat format =
1014      cmd_buffer->state.pass->attachments[attachment_idx].desc.format;
1015   const VkFormat samples =
1016      cmd_buffer->state.pass->attachments[attachment_idx].desc.samples;
1017   const uint32_t components = VK_COLOR_COMPONENT_R_BIT |
1018                               VK_COLOR_COMPONENT_G_BIT |
1019                               VK_COLOR_COMPONENT_B_BIT |
1020                               VK_COLOR_COMPONENT_A_BIT;
1021   struct v3dv_meta_color_clear_pipeline *pipeline = NULL;
1022   VkResult result = get_color_clear_pipeline(cmd_buffer->device,
1023                                              pass,
1024                                              cmd_buffer->state.subpass_idx,
1025                                              rt_idx,
1026                                              attachment_idx,
1027                                              format,
1028                                              samples,
1029                                              components,
1030                                              is_layered,
1031                                              &pipeline);
1032   if (result != VK_SUCCESS) {
1033      if (result == VK_ERROR_OUT_OF_HOST_MEMORY)
1034         v3dv_flag_oom(cmd_buffer, NULL);
1035      return;
1036   }
1037   assert(pipeline && pipeline->pipeline);
1038
1039   /* Emit clear rects */
1040   v3dv_cmd_buffer_meta_state_push(cmd_buffer, false);
1041
1042   VkCommandBuffer cmd_buffer_handle = v3dv_cmd_buffer_to_handle(cmd_buffer);
1043   v3dv_CmdPushConstants(cmd_buffer_handle,
1044                         cmd_buffer->device->meta.depth_clear.p_layout,
1045                         VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16,
1046                         clear_color->float32);
1047
1048   v3dv_CmdBindPipeline(cmd_buffer_handle,
1049                        VK_PIPELINE_BIND_POINT_GRAPHICS,
1050                        pipeline->pipeline);
1051
1052   uint32_t dynamic_states = V3DV_CMD_DIRTY_VIEWPORT | V3DV_CMD_DIRTY_SCISSOR;
1053
1054   for (uint32_t i = 0; i < rect_count; i++) {
1055      const VkViewport viewport = {
1056         .x = rects[i].rect.offset.x,
1057         .y = rects[i].rect.offset.y,
1058         .width = rects[i].rect.extent.width,
1059         .height = rects[i].rect.extent.height,
1060         .minDepth = 0.0f,
1061         .maxDepth = 1.0f
1062      };
1063      v3dv_CmdSetViewport(cmd_buffer_handle, 0, 1, &viewport);
1064      v3dv_CmdSetScissor(cmd_buffer_handle, 0, 1, &rects[i].rect);
1065
1066      if (is_layered) {
1067         for (uint32_t layer_offset = 0; layer_offset < rects[i].layerCount;
1068              layer_offset++) {
1069            uint32_t layer = rects[i].baseArrayLayer + layer_offset;
1070            v3dv_CmdPushConstants(cmd_buffer_handle,
1071                                  cmd_buffer->device->meta.depth_clear.p_layout,
1072                                  VK_SHADER_STAGE_GEOMETRY_BIT, 16, 4, &layer);
1073            v3dv_CmdDraw(cmd_buffer_handle, 4, 1, 0, 0);
1074         }
1075      } else {
1076         assert(rects[i].baseArrayLayer == 0 && rects[i].layerCount == 1);
1077         v3dv_CmdDraw(cmd_buffer_handle, 4, 1, 0, 0);
1078      }
1079   }
1080
1081   /* Subpass pipelines can't be cached because they include a reference to the
1082    * render pass currently bound by the application, which means that we need
1083    * to destroy them manually here.
1084    */
1085   assert(!pipeline->cached);
1086   v3dv_cmd_buffer_add_private_obj(
1087      cmd_buffer, (uintptr_t)pipeline,
1088      (v3dv_cmd_buffer_private_obj_destroy_cb) destroy_color_clear_pipeline);
1089
1090   v3dv_cmd_buffer_meta_state_pop(cmd_buffer, dynamic_states, false);
1091}
1092
1093/* Emits a scissored quad, clearing the depth aspect by writing to gl_FragDepth
1094 * and the stencil aspect by using stencil testing.
1095 */
1096static void
1097emit_subpass_ds_clear_rects(struct v3dv_cmd_buffer *cmd_buffer,
1098                            struct v3dv_render_pass *pass,
1099                            struct v3dv_subpass *subpass,
1100                            VkImageAspectFlags aspects,
1101                            const VkClearDepthStencilValue *clear_ds,
1102                            bool is_layered,
1103                            bool all_rects_same_layers,
1104                            uint32_t rect_count,
1105                            const VkClearRect *rects)
1106{
1107   /* Skip if attachment is unused in the current subpass */
1108   const uint32_t attachment_idx = subpass->ds_attachment.attachment;
1109   if (attachment_idx == VK_ATTACHMENT_UNUSED)
1110      return;
1111
1112   /* Obtain a pipeline for this clear */
1113   assert(attachment_idx < cmd_buffer->state.pass->attachment_count);
1114   struct v3dv_meta_depth_clear_pipeline *pipeline = NULL;
1115   VkResult result = get_depth_clear_pipeline(cmd_buffer->device,
1116                                              aspects,
1117                                              pass,
1118                                              cmd_buffer->state.subpass_idx,
1119                                              attachment_idx,
1120                                              is_layered,
1121                                              &pipeline);
1122   if (result != VK_SUCCESS) {
1123      if (result == VK_ERROR_OUT_OF_HOST_MEMORY)
1124         v3dv_flag_oom(cmd_buffer, NULL);
1125      return;
1126   }
1127   assert(pipeline && pipeline->pipeline);
1128
1129   /* Emit clear rects */
1130   v3dv_cmd_buffer_meta_state_push(cmd_buffer, false);
1131
1132   VkCommandBuffer cmd_buffer_handle = v3dv_cmd_buffer_to_handle(cmd_buffer);
1133   v3dv_CmdPushConstants(cmd_buffer_handle,
1134                         cmd_buffer->device->meta.depth_clear.p_layout,
1135                         VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4,
1136                         &clear_ds->depth);
1137
1138   v3dv_CmdBindPipeline(cmd_buffer_handle,
1139                        VK_PIPELINE_BIND_POINT_GRAPHICS,
1140                        pipeline->pipeline);
1141
1142   uint32_t dynamic_states = V3DV_CMD_DIRTY_VIEWPORT | V3DV_CMD_DIRTY_SCISSOR;
1143   if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
1144      v3dv_CmdSetStencilReference(cmd_buffer_handle,
1145                                  VK_STENCIL_FACE_FRONT_AND_BACK,
1146                                  clear_ds->stencil);
1147      v3dv_CmdSetStencilWriteMask(cmd_buffer_handle,
1148                                  VK_STENCIL_FACE_FRONT_AND_BACK, 0xff);
1149      v3dv_CmdSetStencilCompareMask(cmd_buffer_handle,
1150                                    VK_STENCIL_FACE_FRONT_AND_BACK, 0xff);
1151      dynamic_states |= VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK |
1152                        VK_DYNAMIC_STATE_STENCIL_WRITE_MASK |
1153                        VK_DYNAMIC_STATE_STENCIL_REFERENCE;
1154   }
1155
1156   for (uint32_t i = 0; i < rect_count; i++) {
1157      const VkViewport viewport = {
1158         .x = rects[i].rect.offset.x,
1159         .y = rects[i].rect.offset.y,
1160         .width = rects[i].rect.extent.width,
1161         .height = rects[i].rect.extent.height,
1162         .minDepth = 0.0f,
1163         .maxDepth = 1.0f
1164      };
1165      v3dv_CmdSetViewport(cmd_buffer_handle, 0, 1, &viewport);
1166      v3dv_CmdSetScissor(cmd_buffer_handle, 0, 1, &rects[i].rect);
1167      if (is_layered) {
1168         for (uint32_t layer_offset = 0; layer_offset < rects[i].layerCount;
1169              layer_offset++) {
1170            uint32_t layer = rects[i].baseArrayLayer + layer_offset;
1171            v3dv_CmdPushConstants(cmd_buffer_handle,
1172                                  cmd_buffer->device->meta.depth_clear.p_layout,
1173                                  VK_SHADER_STAGE_GEOMETRY_BIT, 4, 4, &layer);
1174            v3dv_CmdDraw(cmd_buffer_handle, 4, 1, 0, 0);
1175         }
1176      } else {
1177         assert(rects[i].baseArrayLayer == 0 && rects[i].layerCount == 1);
1178         v3dv_CmdDraw(cmd_buffer_handle, 4, 1, 0, 0);
1179      }
1180   }
1181
1182   v3dv_cmd_buffer_meta_state_pop(cmd_buffer, dynamic_states, false);
1183}
1184
1185static void
1186gather_layering_info(uint32_t rect_count, const VkClearRect *rects,
1187                     bool *is_layered, bool *all_rects_same_layers)
1188{
1189   *all_rects_same_layers = true;
1190
1191   uint32_t min_layer = rects[0].baseArrayLayer;
1192   uint32_t max_layer = rects[0].baseArrayLayer + rects[0].layerCount - 1;
1193   for (uint32_t i = 1; i < rect_count; i++) {
1194      if (rects[i].baseArrayLayer != rects[i - 1].baseArrayLayer ||
1195          rects[i].layerCount != rects[i - 1].layerCount) {
1196         *all_rects_same_layers = false;
1197         min_layer = MIN2(min_layer, rects[i].baseArrayLayer);
1198         max_layer = MAX2(max_layer, rects[i].baseArrayLayer +
1199                                     rects[i].layerCount - 1);
1200      }
1201   }
1202
1203   *is_layered = !(min_layer == 0 && max_layer == 0);
1204}
1205
1206VKAPI_ATTR void VKAPI_CALL
1207v3dv_CmdClearAttachments(VkCommandBuffer commandBuffer,
1208                         uint32_t attachmentCount,
1209                         const VkClearAttachment *pAttachments,
1210                         uint32_t rectCount,
1211                         const VkClearRect *pRects)
1212{
1213   V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
1214
1215   /* We can only clear attachments in the current subpass */
1216   assert(attachmentCount <= 5); /* 4 color + D/S */
1217
1218   struct v3dv_render_pass *pass = cmd_buffer->state.pass;
1219
1220   assert(cmd_buffer->state.subpass_idx < pass->subpass_count);
1221   struct v3dv_subpass *subpass =
1222      &cmd_buffer->state.pass->subpasses[cmd_buffer->state.subpass_idx];
1223
1224   /* Emit a clear rect inside the current job for this subpass. For layered
1225    * framebuffers, we use a geometry shader to redirect clears to the
1226    * appropriate layers.
1227    */
1228   bool is_layered, all_rects_same_layers;
1229   gather_layering_info(rectCount, pRects, &is_layered, &all_rects_same_layers);
1230   for (uint32_t i = 0; i < attachmentCount; i++) {
1231      if (pAttachments[i].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
1232         emit_subpass_color_clear_rects(cmd_buffer, pass, subpass,
1233                                        pAttachments[i].colorAttachment,
1234                                        &pAttachments[i].clearValue.color,
1235                                        is_layered, all_rects_same_layers,
1236                                        rectCount, pRects);
1237      } else {
1238         emit_subpass_ds_clear_rects(cmd_buffer, pass, subpass,
1239                                     pAttachments[i].aspectMask,
1240                                     &pAttachments[i].clearValue.depthStencil,
1241                                     is_layered, all_rects_same_layers,
1242                                     rectCount, pRects);
1243      }
1244   }
1245}
1246