1/*
2 * Copyright © 2016 Dave Airlie
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 <assert.h>
25#include <stdbool.h>
26
27#include "nir/nir_builder.h"
28#include "radv_meta.h"
29#include "radv_private.h"
30#include "sid.h"
31#include "vk_format.h"
32
33static nir_shader *
34build_resolve_fragment_shader(struct radv_device *dev, bool is_integer, int samples)
35{
36   enum glsl_base_type img_base_type = is_integer ? GLSL_TYPE_UINT : GLSL_TYPE_FLOAT;
37   const struct glsl_type *vec4 = glsl_vec4_type();
38   const struct glsl_type *sampler_type =
39      glsl_sampler_type(GLSL_SAMPLER_DIM_MS, false, false, img_base_type);
40
41   nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_FRAGMENT, "meta_resolve_fs-%d-%s",
42                                         samples, is_integer ? "int" : "float");
43
44   nir_variable *input_img = nir_variable_create(b.shader, nir_var_uniform, sampler_type, "s_tex");
45   input_img->data.descriptor_set = 0;
46   input_img->data.binding = 0;
47
48   nir_variable *color_out = nir_variable_create(b.shader, nir_var_shader_out, vec4, "f_color");
49   color_out->data.location = FRAG_RESULT_DATA0;
50
51   nir_ssa_def *pos_in = nir_channels(&b, nir_load_frag_coord(&b), 0x3);
52   nir_ssa_def *src_offset = nir_load_push_constant(&b, 2, 32, nir_imm_int(&b, 0), .range = 8);
53
54   nir_ssa_def *pos_int = nir_f2i32(&b, pos_in);
55
56   nir_ssa_def *img_coord = nir_channels(&b, nir_iadd(&b, pos_int, src_offset), 0x3);
57   nir_variable *color = nir_local_variable_create(b.impl, glsl_vec4_type(), "color");
58
59   radv_meta_build_resolve_shader_core(&b, is_integer, samples, input_img, color, img_coord);
60
61   nir_ssa_def *outval = nir_load_var(&b, color);
62   nir_store_var(&b, color_out, outval, 0xf);
63   return b.shader;
64}
65
66static VkResult
67create_layout(struct radv_device *device)
68{
69   VkResult result;
70   /*
71    * one descriptors for the image being sampled
72    */
73   VkDescriptorSetLayoutCreateInfo ds_create_info = {
74      .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
75      .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,
76      .bindingCount = 1,
77      .pBindings = (VkDescriptorSetLayoutBinding[]){
78         {.binding = 0,
79          .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
80          .descriptorCount = 1,
81          .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
82          .pImmutableSamplers = NULL},
83      }};
84
85   result = radv_CreateDescriptorSetLayout(radv_device_to_handle(device), &ds_create_info,
86                                           &device->meta_state.alloc,
87                                           &device->meta_state.resolve_fragment.ds_layout);
88   if (result != VK_SUCCESS)
89      goto fail;
90
91   VkPipelineLayoutCreateInfo pl_create_info = {
92      .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
93      .setLayoutCount = 1,
94      .pSetLayouts = &device->meta_state.resolve_fragment.ds_layout,
95      .pushConstantRangeCount = 1,
96      .pPushConstantRanges = &(VkPushConstantRange){VK_SHADER_STAGE_FRAGMENT_BIT, 0, 8},
97   };
98
99   result = radv_CreatePipelineLayout(radv_device_to_handle(device), &pl_create_info,
100                                      &device->meta_state.alloc,
101                                      &device->meta_state.resolve_fragment.p_layout);
102   if (result != VK_SUCCESS)
103      goto fail;
104   return VK_SUCCESS;
105fail:
106   return result;
107}
108
109static const VkPipelineVertexInputStateCreateInfo normal_vi_create_info = {
110   .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
111   .vertexBindingDescriptionCount = 0,
112   .vertexAttributeDescriptionCount = 0,
113};
114
115static VkResult
116create_resolve_pipeline(struct radv_device *device, int samples_log2, VkFormat format)
117{
118   mtx_lock(&device->meta_state.mtx);
119
120   unsigned fs_key = radv_format_meta_fs_key(device, format);
121   VkPipeline *pipeline = &device->meta_state.resolve_fragment.rc[samples_log2].pipeline[fs_key];
122   if (*pipeline) {
123      mtx_unlock(&device->meta_state.mtx);
124      return VK_SUCCESS;
125   }
126
127   VkResult result;
128   bool is_integer = false;
129   uint32_t samples = 1 << samples_log2;
130   const VkPipelineVertexInputStateCreateInfo *vi_create_info;
131   vi_create_info = &normal_vi_create_info;
132   if (vk_format_is_int(format))
133      is_integer = true;
134
135   nir_shader *fs = build_resolve_fragment_shader(device, is_integer, samples);
136   nir_shader *vs = radv_meta_build_nir_vs_generate_vertices(device);
137
138   VkPipelineShaderStageCreateInfo pipeline_shader_stages[] = {
139      {.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
140       .stage = VK_SHADER_STAGE_VERTEX_BIT,
141       .module = vk_shader_module_handle_from_nir(vs),
142       .pName = "main",
143       .pSpecializationInfo = NULL},
144      {.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
145       .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
146       .module = vk_shader_module_handle_from_nir(fs),
147       .pName = "main",
148       .pSpecializationInfo = NULL},
149   };
150
151   const VkPipelineRenderingCreateInfo rendering_create_info = {
152      .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
153      .colorAttachmentCount = 1,
154      .pColorAttachmentFormats = &format,
155   };
156
157   const VkGraphicsPipelineCreateInfo vk_pipeline_info = {
158      .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
159      .pNext = &rendering_create_info,
160      .stageCount = ARRAY_SIZE(pipeline_shader_stages),
161      .pStages = pipeline_shader_stages,
162      .pVertexInputState = vi_create_info,
163      .pInputAssemblyState =
164         &(VkPipelineInputAssemblyStateCreateInfo){
165            .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
166            .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
167            .primitiveRestartEnable = false,
168         },
169      .pViewportState =
170         &(VkPipelineViewportStateCreateInfo){
171            .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
172            .viewportCount = 1,
173            .scissorCount = 1,
174         },
175      .pRasterizationState =
176         &(VkPipelineRasterizationStateCreateInfo){
177            .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
178            .rasterizerDiscardEnable = false,
179            .polygonMode = VK_POLYGON_MODE_FILL,
180            .cullMode = VK_CULL_MODE_NONE,
181            .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
182            .depthBiasConstantFactor = 0.0f,
183            .depthBiasClamp = 0.0f,
184            .depthBiasSlopeFactor = 0.0f,
185            .lineWidth = 1.0f},
186      .pMultisampleState =
187         &(VkPipelineMultisampleStateCreateInfo){
188            .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
189            .rasterizationSamples = 1,
190            .sampleShadingEnable = false,
191            .pSampleMask = (VkSampleMask[]){UINT32_MAX},
192         },
193      .pColorBlendState =
194         &(VkPipelineColorBlendStateCreateInfo){
195            .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
196            .attachmentCount = 1,
197            .pAttachments =
198               (VkPipelineColorBlendAttachmentState[]){
199                  {.colorWriteMask = VK_COLOR_COMPONENT_A_BIT | VK_COLOR_COMPONENT_R_BIT |
200                                     VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT},
201               },
202            .blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f }},
203      .pDynamicState =
204         &(VkPipelineDynamicStateCreateInfo){
205            .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
206            .dynamicStateCount = 2,
207            .pDynamicStates =
208               (VkDynamicState[]){
209                  VK_DYNAMIC_STATE_VIEWPORT,
210                  VK_DYNAMIC_STATE_SCISSOR,
211               },
212         },
213      .flags = 0,
214      .layout = device->meta_state.resolve_fragment.p_layout,
215      .renderPass = VK_NULL_HANDLE,
216      .subpass = 0,
217   };
218
219   const struct radv_graphics_pipeline_create_info radv_pipeline_info = {.use_rectlist = true};
220
221   result = radv_graphics_pipeline_create(
222      radv_device_to_handle(device), radv_pipeline_cache_to_handle(&device->meta_state.cache),
223      &vk_pipeline_info, &radv_pipeline_info, &device->meta_state.alloc, pipeline);
224   ralloc_free(vs);
225   ralloc_free(fs);
226
227   mtx_unlock(&device->meta_state.mtx);
228   return result;
229}
230
231enum { DEPTH_RESOLVE, STENCIL_RESOLVE };
232
233static const char *
234get_resolve_mode_str(VkResolveModeFlagBits resolve_mode)
235{
236   switch (resolve_mode) {
237   case VK_RESOLVE_MODE_SAMPLE_ZERO_BIT:
238      return "zero";
239   case VK_RESOLVE_MODE_AVERAGE_BIT:
240      return "average";
241   case VK_RESOLVE_MODE_MIN_BIT:
242      return "min";
243   case VK_RESOLVE_MODE_MAX_BIT:
244      return "max";
245   default:
246      unreachable("invalid resolve mode");
247   }
248}
249
250static nir_shader *
251build_depth_stencil_resolve_fragment_shader(struct radv_device *dev, int samples, int index,
252                                            VkResolveModeFlagBits resolve_mode)
253{
254   enum glsl_base_type img_base_type = index == DEPTH_RESOLVE ? GLSL_TYPE_FLOAT : GLSL_TYPE_UINT;
255   const struct glsl_type *vec4 = glsl_vec4_type();
256   const struct glsl_type *sampler_type =
257      glsl_sampler_type(GLSL_SAMPLER_DIM_2D, false, false, img_base_type);
258
259   nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_FRAGMENT, "meta_resolve_fs_%s-%s-%d",
260                                         index == DEPTH_RESOLVE ? "depth" : "stencil",
261                                         get_resolve_mode_str(resolve_mode), samples);
262
263   nir_variable *input_img = nir_variable_create(b.shader, nir_var_uniform, sampler_type, "s_tex");
264   input_img->data.descriptor_set = 0;
265   input_img->data.binding = 0;
266
267   nir_variable *fs_out = nir_variable_create(b.shader, nir_var_shader_out, vec4, "f_out");
268   fs_out->data.location = index == DEPTH_RESOLVE ? FRAG_RESULT_DEPTH : FRAG_RESULT_STENCIL;
269
270   nir_ssa_def *pos_in = nir_channels(&b, nir_load_frag_coord(&b), 0x3);
271
272   nir_ssa_def *pos_int = nir_f2i32(&b, pos_in);
273
274   nir_ssa_def *img_coord = nir_channels(&b, pos_int, 0x3);
275
276   nir_ssa_def *input_img_deref = &nir_build_deref_var(&b, input_img)->dest.ssa;
277
278   nir_alu_type type = index == DEPTH_RESOLVE ? nir_type_float32 : nir_type_uint32;
279
280   nir_tex_instr *tex = nir_tex_instr_create(b.shader, 3);
281   tex->sampler_dim = GLSL_SAMPLER_DIM_MS;
282   tex->op = nir_texop_txf_ms;
283   tex->src[0].src_type = nir_tex_src_coord;
284   tex->src[0].src = nir_src_for_ssa(img_coord);
285   tex->src[1].src_type = nir_tex_src_ms_index;
286   tex->src[1].src = nir_src_for_ssa(nir_imm_int(&b, 0));
287   tex->src[2].src_type = nir_tex_src_texture_deref;
288   tex->src[2].src = nir_src_for_ssa(input_img_deref);
289   tex->dest_type = type;
290   tex->is_array = false;
291   tex->coord_components = 2;
292
293   nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, "tex");
294   nir_builder_instr_insert(&b, &tex->instr);
295
296   nir_ssa_def *outval = &tex->dest.ssa;
297
298   if (resolve_mode != VK_RESOLVE_MODE_SAMPLE_ZERO_BIT) {
299      for (int i = 1; i < samples; i++) {
300         nir_tex_instr *tex_add = nir_tex_instr_create(b.shader, 3);
301         tex_add->sampler_dim = GLSL_SAMPLER_DIM_MS;
302         tex_add->op = nir_texop_txf_ms;
303         tex_add->src[0].src_type = nir_tex_src_coord;
304         tex_add->src[0].src = nir_src_for_ssa(img_coord);
305         tex_add->src[1].src_type = nir_tex_src_ms_index;
306         tex_add->src[1].src = nir_src_for_ssa(nir_imm_int(&b, i));
307         tex_add->src[2].src_type = nir_tex_src_texture_deref;
308         tex_add->src[2].src = nir_src_for_ssa(input_img_deref);
309         tex_add->dest_type = type;
310         tex_add->is_array = false;
311         tex_add->coord_components = 2;
312
313         nir_ssa_dest_init(&tex_add->instr, &tex_add->dest, 4, 32, "tex");
314         nir_builder_instr_insert(&b, &tex_add->instr);
315
316         switch (resolve_mode) {
317         case VK_RESOLVE_MODE_AVERAGE_BIT:
318            assert(index == DEPTH_RESOLVE);
319            outval = nir_fadd(&b, outval, &tex_add->dest.ssa);
320            break;
321         case VK_RESOLVE_MODE_MIN_BIT:
322            if (index == DEPTH_RESOLVE)
323               outval = nir_fmin(&b, outval, &tex_add->dest.ssa);
324            else
325               outval = nir_umin(&b, outval, &tex_add->dest.ssa);
326            break;
327         case VK_RESOLVE_MODE_MAX_BIT:
328            if (index == DEPTH_RESOLVE)
329               outval = nir_fmax(&b, outval, &tex_add->dest.ssa);
330            else
331               outval = nir_umax(&b, outval, &tex_add->dest.ssa);
332            break;
333         default:
334            unreachable("invalid resolve mode");
335         }
336      }
337
338      if (resolve_mode == VK_RESOLVE_MODE_AVERAGE_BIT)
339         outval = nir_fdiv(&b, outval, nir_imm_float(&b, samples));
340   }
341
342   nir_store_var(&b, fs_out, outval, 0x1);
343
344   return b.shader;
345}
346
347static VkResult
348create_depth_stencil_resolve_pipeline(struct radv_device *device, int samples_log2, int index,
349                                      VkResolveModeFlagBits resolve_mode)
350{
351   VkPipeline *pipeline;
352   VkResult result;
353
354   mtx_lock(&device->meta_state.mtx);
355
356   switch (resolve_mode) {
357   case VK_RESOLVE_MODE_SAMPLE_ZERO_BIT:
358      if (index == DEPTH_RESOLVE)
359         pipeline = &device->meta_state.resolve_fragment.depth_zero_pipeline;
360      else
361         pipeline = &device->meta_state.resolve_fragment.stencil_zero_pipeline;
362      break;
363   case VK_RESOLVE_MODE_AVERAGE_BIT:
364      assert(index == DEPTH_RESOLVE);
365      pipeline = &device->meta_state.resolve_fragment.depth[samples_log2].average_pipeline;
366      break;
367   case VK_RESOLVE_MODE_MIN_BIT:
368      if (index == DEPTH_RESOLVE)
369         pipeline = &device->meta_state.resolve_fragment.depth[samples_log2].min_pipeline;
370      else
371         pipeline = &device->meta_state.resolve_fragment.stencil[samples_log2].min_pipeline;
372      break;
373   case VK_RESOLVE_MODE_MAX_BIT:
374      if (index == DEPTH_RESOLVE)
375         pipeline = &device->meta_state.resolve_fragment.depth[samples_log2].max_pipeline;
376      else
377         pipeline = &device->meta_state.resolve_fragment.stencil[samples_log2].max_pipeline;
378      break;
379   default:
380      unreachable("invalid resolve mode");
381   }
382
383   if (*pipeline) {
384      mtx_unlock(&device->meta_state.mtx);
385      return VK_SUCCESS;
386   }
387
388   uint32_t samples = 1 << samples_log2;
389   nir_shader *fs =
390      build_depth_stencil_resolve_fragment_shader(device, samples, index, resolve_mode);
391   nir_shader *vs = radv_meta_build_nir_vs_generate_vertices(device);
392
393   VkPipelineShaderStageCreateInfo pipeline_shader_stages[] = {
394      {.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
395       .stage = VK_SHADER_STAGE_VERTEX_BIT,
396       .module = vk_shader_module_handle_from_nir(vs),
397       .pName = "main",
398       .pSpecializationInfo = NULL},
399      {.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
400       .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
401       .module = vk_shader_module_handle_from_nir(fs),
402       .pName = "main",
403       .pSpecializationInfo = NULL},
404   };
405
406   VkStencilOp stencil_op = index == DEPTH_RESOLVE ? VK_STENCIL_OP_KEEP : VK_STENCIL_OP_REPLACE;
407
408   VkPipelineDepthStencilStateCreateInfo depth_stencil_state = {
409      .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
410      .depthTestEnable = true,
411      .depthWriteEnable = index == DEPTH_RESOLVE,
412      .stencilTestEnable = index == STENCIL_RESOLVE,
413      .depthCompareOp = VK_COMPARE_OP_ALWAYS,
414      .front =
415         {
416            .failOp = stencil_op,
417            .passOp = stencil_op,
418            .depthFailOp = stencil_op,
419            .compareOp = VK_COMPARE_OP_ALWAYS,
420            .compareMask = UINT32_MAX,
421            .writeMask = UINT32_MAX,
422            .reference = 0u,
423         },
424      .back = {
425         .failOp = stencil_op,
426         .passOp = stencil_op,
427         .depthFailOp = stencil_op,
428         .compareOp = VK_COMPARE_OP_ALWAYS,
429         .compareMask = UINT32_MAX,
430         .writeMask = UINT32_MAX,
431         .reference = 0u,
432      },
433      .minDepthBounds = 0.0f,
434      .maxDepthBounds = 1.0f};
435
436   const VkPipelineVertexInputStateCreateInfo *vi_create_info;
437   vi_create_info = &normal_vi_create_info;
438
439   const VkPipelineRenderingCreateInfo rendering_create_info = {
440      .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
441      .depthAttachmentFormat = index == DEPTH_RESOLVE ? VK_FORMAT_D32_SFLOAT : VK_FORMAT_UNDEFINED,
442      .stencilAttachmentFormat = index == STENCIL_RESOLVE ? VK_FORMAT_S8_UINT : VK_FORMAT_UNDEFINED,
443   };
444
445   const VkGraphicsPipelineCreateInfo vk_pipeline_info = {
446      .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
447      .pNext = &rendering_create_info,
448      .stageCount = ARRAY_SIZE(pipeline_shader_stages),
449      .pStages = pipeline_shader_stages,
450      .pVertexInputState = vi_create_info,
451      .pInputAssemblyState =
452         &(VkPipelineInputAssemblyStateCreateInfo){
453            .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
454            .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
455            .primitiveRestartEnable = false,
456         },
457      .pViewportState =
458         &(VkPipelineViewportStateCreateInfo){
459            .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
460            .viewportCount = 1,
461            .scissorCount = 1,
462         },
463      .pDepthStencilState = &depth_stencil_state,
464      .pRasterizationState =
465         &(VkPipelineRasterizationStateCreateInfo){
466            .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
467            .rasterizerDiscardEnable = false,
468            .polygonMode = VK_POLYGON_MODE_FILL,
469            .cullMode = VK_CULL_MODE_NONE,
470            .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
471            .depthBiasConstantFactor = 0.0f,
472            .depthBiasClamp = 0.0f,
473            .depthBiasSlopeFactor = 0.0f,
474            .lineWidth = 1.0f},
475      .pMultisampleState =
476         &(VkPipelineMultisampleStateCreateInfo){
477            .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
478            .rasterizationSamples = 1,
479            .sampleShadingEnable = false,
480            .pSampleMask = (VkSampleMask[]){UINT32_MAX},
481         },
482      .pColorBlendState =
483         &(VkPipelineColorBlendStateCreateInfo){
484            .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
485            .attachmentCount = 0,
486            .pAttachments =
487               (VkPipelineColorBlendAttachmentState[]){
488                  {.colorWriteMask = VK_COLOR_COMPONENT_A_BIT | VK_COLOR_COMPONENT_R_BIT |
489                                     VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT},
490               },
491            .blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f }},
492      .pDynamicState =
493         &(VkPipelineDynamicStateCreateInfo){
494            .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
495            .dynamicStateCount = 2,
496            .pDynamicStates =
497               (VkDynamicState[]){
498                  VK_DYNAMIC_STATE_VIEWPORT,
499                  VK_DYNAMIC_STATE_SCISSOR,
500               },
501         },
502      .flags = 0,
503      .layout = device->meta_state.resolve_fragment.p_layout,
504      .renderPass = VK_NULL_HANDLE,
505      .subpass = 0,
506   };
507
508   const struct radv_graphics_pipeline_create_info radv_pipeline_info = {.use_rectlist = true};
509
510   result = radv_graphics_pipeline_create(
511      radv_device_to_handle(device), radv_pipeline_cache_to_handle(&device->meta_state.cache),
512      &vk_pipeline_info, &radv_pipeline_info, &device->meta_state.alloc, pipeline);
513
514   ralloc_free(vs);
515   ralloc_free(fs);
516
517   mtx_unlock(&device->meta_state.mtx);
518   return result;
519}
520
521VkResult
522radv_device_init_meta_resolve_fragment_state(struct radv_device *device, bool on_demand)
523{
524   VkResult res;
525
526   res = create_layout(device);
527   if (res != VK_SUCCESS)
528      return res;
529
530   if (on_demand)
531      return VK_SUCCESS;
532
533   for (uint32_t i = 0; i < MAX_SAMPLES_LOG2; ++i) {
534      for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
535         res = create_resolve_pipeline(device, i, radv_fs_key_format_exemplars[j]);
536         if (res != VK_SUCCESS)
537            return res;
538      }
539
540      res = create_depth_stencil_resolve_pipeline(device, i, DEPTH_RESOLVE,
541                                                  VK_RESOLVE_MODE_AVERAGE_BIT);
542      if (res != VK_SUCCESS)
543         return res;
544
545      res = create_depth_stencil_resolve_pipeline(device, i, DEPTH_RESOLVE,
546                                                  VK_RESOLVE_MODE_MIN_BIT);
547      if (res != VK_SUCCESS)
548         return res;
549
550      res = create_depth_stencil_resolve_pipeline(device, i, DEPTH_RESOLVE,
551                                                  VK_RESOLVE_MODE_MAX_BIT);
552      if (res != VK_SUCCESS)
553         return res;
554
555      res = create_depth_stencil_resolve_pipeline(device, i, STENCIL_RESOLVE,
556                                                  VK_RESOLVE_MODE_MIN_BIT);
557      if (res != VK_SUCCESS)
558         return res;
559
560      res = create_depth_stencil_resolve_pipeline(device, i, STENCIL_RESOLVE,
561                                                  VK_RESOLVE_MODE_MAX_BIT);
562      if (res != VK_SUCCESS)
563         return res;
564   }
565
566   res = create_depth_stencil_resolve_pipeline(device, 0, DEPTH_RESOLVE,
567                                               VK_RESOLVE_MODE_SAMPLE_ZERO_BIT);
568   if (res != VK_SUCCESS)
569      return res;
570
571   return create_depth_stencil_resolve_pipeline(device, 0, STENCIL_RESOLVE,
572                                                VK_RESOLVE_MODE_SAMPLE_ZERO_BIT);
573}
574
575void
576radv_device_finish_meta_resolve_fragment_state(struct radv_device *device)
577{
578   struct radv_meta_state *state = &device->meta_state;
579   for (uint32_t i = 0; i < MAX_SAMPLES_LOG2; ++i) {
580      for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
581         radv_DestroyPipeline(radv_device_to_handle(device),
582                              state->resolve_fragment.rc[i].pipeline[j], &state->alloc);
583      }
584
585      radv_DestroyPipeline(radv_device_to_handle(device),
586                           state->resolve_fragment.depth[i].average_pipeline, &state->alloc);
587
588      radv_DestroyPipeline(radv_device_to_handle(device),
589                           state->resolve_fragment.depth[i].max_pipeline, &state->alloc);
590
591      radv_DestroyPipeline(radv_device_to_handle(device),
592                           state->resolve_fragment.depth[i].min_pipeline, &state->alloc);
593
594      radv_DestroyPipeline(radv_device_to_handle(device),
595                           state->resolve_fragment.stencil[i].max_pipeline, &state->alloc);
596
597      radv_DestroyPipeline(radv_device_to_handle(device),
598                           state->resolve_fragment.stencil[i].min_pipeline, &state->alloc);
599   }
600
601   radv_DestroyPipeline(radv_device_to_handle(device), state->resolve_fragment.depth_zero_pipeline,
602                        &state->alloc);
603   radv_DestroyPipeline(radv_device_to_handle(device),
604                        state->resolve_fragment.stencil_zero_pipeline, &state->alloc);
605
606   device->vk.dispatch_table.DestroyDescriptorSetLayout(
607      radv_device_to_handle(device), state->resolve_fragment.ds_layout, &state->alloc);
608   radv_DestroyPipelineLayout(radv_device_to_handle(device), state->resolve_fragment.p_layout,
609                              &state->alloc);
610}
611
612static VkPipeline *
613radv_get_resolve_pipeline(struct radv_cmd_buffer *cmd_buffer, struct radv_image_view *src_iview,
614                          struct radv_image_view *dst_iview)
615{
616   struct radv_device *device = cmd_buffer->device;
617   unsigned fs_key = radv_format_meta_fs_key(cmd_buffer->device, dst_iview->vk.format);
618   const uint32_t samples = src_iview->image->info.samples;
619   const uint32_t samples_log2 = ffs(samples) - 1;
620   VkPipeline *pipeline;
621
622   pipeline = &device->meta_state.resolve_fragment.rc[samples_log2].pipeline[fs_key];
623   if (!*pipeline) {
624      VkResult ret;
625
626      ret = create_resolve_pipeline(device, samples_log2, radv_fs_key_format_exemplars[fs_key]);
627      if (ret != VK_SUCCESS) {
628         cmd_buffer->record_result = ret;
629         return NULL;
630      }
631   }
632
633   return pipeline;
634}
635
636static void
637emit_resolve(struct radv_cmd_buffer *cmd_buffer, struct radv_image_view *src_iview,
638             struct radv_image_view *dest_iview, const VkOffset2D *src_offset,
639             const VkOffset2D *dest_offset, const VkExtent2D *resolve_extent)
640{
641   struct radv_device *device = cmd_buffer->device;
642   VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
643   VkPipeline *pipeline;
644
645   radv_meta_push_descriptor_set(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
646                                 cmd_buffer->device->meta_state.resolve_fragment.p_layout,
647                                 0, /* set */
648                                 1, /* descriptorWriteCount */
649                                 (VkWriteDescriptorSet[]){
650                                    {.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
651                                     .dstBinding = 0,
652                                     .dstArrayElement = 0,
653                                     .descriptorCount = 1,
654                                     .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
655                                     .pImageInfo =
656                                        (VkDescriptorImageInfo[]){
657                                           {
658                                              .sampler = VK_NULL_HANDLE,
659                                              .imageView = radv_image_view_to_handle(src_iview),
660                                              .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
661                                           },
662                                        }},
663                                 });
664
665   cmd_buffer->state.flush_bits |=
666      radv_dst_access_flush(cmd_buffer, VK_ACCESS_2_SHADER_READ_BIT, src_iview->image) |
667      radv_dst_access_flush(cmd_buffer, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, dest_iview->image);
668
669   unsigned push_constants[2] = {
670      src_offset->x - dest_offset->x,
671      src_offset->y - dest_offset->y,
672   };
673   radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
674                         device->meta_state.resolve_fragment.p_layout, VK_SHADER_STAGE_FRAGMENT_BIT,
675                         0, 8, push_constants);
676
677   pipeline = radv_get_resolve_pipeline(cmd_buffer, src_iview, dest_iview);
678
679   radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
680
681   radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
682                       &(VkViewport){.x = dest_offset->x,
683                                     .y = dest_offset->y,
684                                     .width = resolve_extent->width,
685                                     .height = resolve_extent->height,
686                                     .minDepth = 0.0f,
687                                     .maxDepth = 1.0f});
688
689   radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
690                      &(VkRect2D){
691                         .offset = *dest_offset,
692                         .extent = *resolve_extent,
693                      });
694
695   radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0);
696   cmd_buffer->state.flush_bits |=
697      radv_src_access_flush(cmd_buffer, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, dest_iview->image);
698}
699
700static void
701emit_depth_stencil_resolve(struct radv_cmd_buffer *cmd_buffer, struct radv_image_view *src_iview,
702                           struct radv_image_view *dst_iview, const VkExtent2D *resolve_extent,
703                           VkImageAspectFlags aspects, VkResolveModeFlagBits resolve_mode)
704{
705   struct radv_device *device = cmd_buffer->device;
706   const uint32_t samples = src_iview->image->info.samples;
707   const uint32_t samples_log2 = ffs(samples) - 1;
708   VkPipeline *pipeline;
709
710   radv_meta_push_descriptor_set(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
711                                 cmd_buffer->device->meta_state.resolve_fragment.p_layout,
712                                 0, /* set */
713                                 1, /* descriptorWriteCount */
714                                 (VkWriteDescriptorSet[]){
715                                    {.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
716                                     .dstBinding = 0,
717                                     .dstArrayElement = 0,
718                                     .descriptorCount = 1,
719                                     .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
720                                     .pImageInfo =
721                                        (VkDescriptorImageInfo[]){
722                                           {
723                                              .sampler = VK_NULL_HANDLE,
724                                              .imageView = radv_image_view_to_handle(src_iview),
725                                              .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
726                                           },
727                                        }},
728                                 });
729
730   switch (resolve_mode) {
731   case VK_RESOLVE_MODE_SAMPLE_ZERO_BIT:
732      if (aspects == VK_IMAGE_ASPECT_DEPTH_BIT)
733         pipeline = &device->meta_state.resolve_fragment.depth_zero_pipeline;
734      else
735         pipeline = &device->meta_state.resolve_fragment.stencil_zero_pipeline;
736      break;
737   case VK_RESOLVE_MODE_AVERAGE_BIT:
738      assert(aspects == VK_IMAGE_ASPECT_DEPTH_BIT);
739      pipeline = &device->meta_state.resolve_fragment.depth[samples_log2].average_pipeline;
740      break;
741   case VK_RESOLVE_MODE_MIN_BIT:
742      if (aspects == VK_IMAGE_ASPECT_DEPTH_BIT)
743         pipeline = &device->meta_state.resolve_fragment.depth[samples_log2].min_pipeline;
744      else
745         pipeline = &device->meta_state.resolve_fragment.stencil[samples_log2].min_pipeline;
746      break;
747   case VK_RESOLVE_MODE_MAX_BIT:
748      if (aspects == VK_IMAGE_ASPECT_DEPTH_BIT)
749         pipeline = &device->meta_state.resolve_fragment.depth[samples_log2].max_pipeline;
750      else
751         pipeline = &device->meta_state.resolve_fragment.stencil[samples_log2].max_pipeline;
752      break;
753   default:
754      unreachable("invalid resolve mode");
755   }
756
757   if (!*pipeline) {
758      int index = aspects == VK_IMAGE_ASPECT_DEPTH_BIT ? DEPTH_RESOLVE : STENCIL_RESOLVE;
759      VkResult ret;
760
761      ret = create_depth_stencil_resolve_pipeline(device, samples_log2, index, resolve_mode);
762      if (ret != VK_SUCCESS) {
763         cmd_buffer->record_result = ret;
764         return;
765      }
766   }
767
768   radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_GRAPHICS,
769                        *pipeline);
770
771   radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
772                       &(VkViewport){.x = 0,
773                                     .y = 0,
774                                     .width = resolve_extent->width,
775                                     .height = resolve_extent->height,
776                                     .minDepth = 0.0f,
777                                     .maxDepth = 1.0f});
778
779   radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
780                      &(VkRect2D){
781                         .offset = (VkOffset2D){0, 0},
782                         .extent = *resolve_extent,
783                      });
784
785   radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
786}
787
788void
789radv_meta_resolve_fragment_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image,
790                                 VkImageLayout src_image_layout, struct radv_image *dest_image,
791                                 VkImageLayout dest_image_layout, const VkImageResolve2 *region)
792{
793   struct radv_meta_saved_state saved_state;
794   unsigned dst_layout = radv_meta_dst_layout_from_layout(dest_image_layout);
795   VkImageLayout layout = radv_meta_dst_layout_to_layout(dst_layout);
796
797   radv_decompress_resolve_src(cmd_buffer, src_image, src_image_layout, region);
798
799   radv_meta_save(
800      &saved_state, cmd_buffer,
801      RADV_META_SAVE_GRAPHICS_PIPELINE | RADV_META_SAVE_CONSTANTS | RADV_META_SAVE_DESCRIPTORS);
802
803   assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
804   assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
805   assert(region->srcSubresource.layerCount == region->dstSubresource.layerCount);
806
807   const uint32_t src_base_layer =
808      radv_meta_get_iview_layer(src_image, &region->srcSubresource, &region->srcOffset);
809
810   const uint32_t dest_base_layer =
811      radv_meta_get_iview_layer(dest_image, &region->dstSubresource, &region->dstOffset);
812
813   const struct VkExtent3D extent = vk_image_sanitize_extent(&src_image->vk, region->extent);
814   const struct VkOffset3D srcOffset = vk_image_sanitize_offset(&src_image->vk, region->srcOffset);
815   const struct VkOffset3D dstOffset = vk_image_sanitize_offset(&dest_image->vk, region->dstOffset);
816
817   for (uint32_t layer = 0; layer < region->srcSubresource.layerCount; ++layer) {
818
819      struct radv_image_view src_iview;
820      radv_image_view_init(&src_iview, cmd_buffer->device,
821                           &(VkImageViewCreateInfo){
822                              .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
823                              .image = radv_image_to_handle(src_image),
824                              .viewType = radv_meta_get_view_type(src_image),
825                              .format = src_image->vk.format,
826                              .subresourceRange =
827                                 {
828                                    .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
829                                    .baseMipLevel = region->srcSubresource.mipLevel,
830                                    .levelCount = 1,
831                                    .baseArrayLayer = src_base_layer + layer,
832                                    .layerCount = 1,
833                                 },
834                           },
835                           0, NULL);
836
837      struct radv_image_view dest_iview;
838      radv_image_view_init(&dest_iview, cmd_buffer->device,
839                           &(VkImageViewCreateInfo){
840                              .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
841                              .image = radv_image_to_handle(dest_image),
842                              .viewType = radv_meta_get_view_type(dest_image),
843                              .format = dest_image->vk.format,
844                              .subresourceRange =
845                                 {
846                                    .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
847                                    .baseMipLevel = region->dstSubresource.mipLevel,
848                                    .levelCount = 1,
849                                    .baseArrayLayer = dest_base_layer + layer,
850                                    .layerCount = 1,
851                                 },
852                           },
853                           0, NULL);
854
855      const VkRenderingAttachmentInfo color_att = {
856         .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
857         .imageView = radv_image_view_to_handle(&dest_iview),
858         .imageLayout = layout,
859         .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
860         .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
861      };
862
863      const VkRenderingInfo rendering_info = {
864         .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
865         .renderArea = {
866            .offset = { dstOffset.x, dstOffset.y },
867            .extent = { extent.width, extent.height }
868         },
869         .layerCount = 1,
870         .colorAttachmentCount = 1,
871         .pColorAttachments = &color_att,
872      };
873
874      radv_CmdBeginRendering(radv_cmd_buffer_to_handle(cmd_buffer), &rendering_info);
875
876      emit_resolve(cmd_buffer, &src_iview, &dest_iview, &(VkOffset2D){srcOffset.x, srcOffset.y},
877                   &(VkOffset2D){dstOffset.x, dstOffset.y},
878                   &(VkExtent2D){extent.width, extent.height});
879
880      radv_CmdEndRendering(radv_cmd_buffer_to_handle(cmd_buffer));
881
882      radv_image_view_finish(&src_iview);
883      radv_image_view_finish(&dest_iview);
884   }
885
886   radv_meta_restore(&saved_state, cmd_buffer);
887}
888
889/**
890 * Emit any needed resolves for the current subpass.
891 */
892void
893radv_cmd_buffer_resolve_subpass_fs(struct radv_cmd_buffer *cmd_buffer)
894{
895   struct vk_framebuffer *fb = cmd_buffer->state.framebuffer;
896   const struct radv_subpass *subpass = cmd_buffer->state.subpass;
897   struct radv_meta_saved_state saved_state;
898   struct radv_subpass_barrier barrier;
899
900   /* Resolves happen before the end-of-subpass barriers get executed,
901    * so we have to make the attachment shader-readable */
902   barrier.src_stage_mask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
903   barrier.src_access_mask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
904   barrier.dst_access_mask = VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT;
905   radv_emit_subpass_barrier(cmd_buffer, &barrier);
906
907   radv_decompress_resolve_subpass_src(cmd_buffer);
908
909   radv_meta_save(
910      &saved_state, cmd_buffer,
911      RADV_META_SAVE_GRAPHICS_PIPELINE | RADV_META_SAVE_CONSTANTS | RADV_META_SAVE_DESCRIPTORS);
912
913   for (uint32_t i = 0; i < subpass->color_count; ++i) {
914      struct radv_subpass_attachment src_att = subpass->color_attachments[i];
915      struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i];
916
917      if (dest_att.attachment == VK_ATTACHMENT_UNUSED)
918         continue;
919
920      struct radv_image_view *dest_iview = cmd_buffer->state.attachments[dest_att.attachment].iview;
921      struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview;
922
923      struct radv_subpass resolve_subpass = {
924         .color_count = 1,
925         .color_attachments = (struct radv_subpass_attachment[]){dest_att},
926         .depth_stencil_attachment = NULL,
927      };
928
929      radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass);
930
931      emit_resolve(cmd_buffer, src_iview, dest_iview, &(VkOffset2D){0, 0}, &(VkOffset2D){0, 0},
932                   &(VkExtent2D){fb->width, fb->height});
933
934      radv_cmd_buffer_restore_subpass(cmd_buffer, subpass);
935   }
936
937   radv_meta_restore(&saved_state, cmd_buffer);
938}
939
940/**
941 * Depth/stencil resolves for the current subpass.
942 */
943void
944radv_depth_stencil_resolve_subpass_fs(struct radv_cmd_buffer *cmd_buffer,
945                                      VkImageAspectFlags aspects,
946                                      VkResolveModeFlagBits resolve_mode)
947{
948   struct vk_framebuffer *fb = cmd_buffer->state.framebuffer;
949   const struct radv_subpass *subpass = cmd_buffer->state.subpass;
950   struct radv_meta_saved_state saved_state;
951   struct radv_subpass_barrier barrier;
952
953   /* Resolves happen before the end-of-subpass barriers get executed,
954    * so we have to make the attachment shader-readable */
955   barrier.src_stage_mask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
956   barrier.src_access_mask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
957   barrier.dst_access_mask = VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT;
958   radv_emit_subpass_barrier(cmd_buffer, &barrier);
959
960   struct radv_subpass_attachment src_att = *subpass->depth_stencil_attachment;
961   struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview;
962   struct radv_image *src_image = src_iview->image;
963
964   VkImageResolve2 region = {0};
965   region.sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2;
966   region.srcSubresource.aspectMask = aspects;
967   region.srcSubresource.mipLevel = 0;
968   region.srcSubresource.baseArrayLayer = 0;
969   region.srcSubresource.layerCount = 1;
970
971   radv_decompress_resolve_src(cmd_buffer, src_image, src_att.layout, &region);
972
973   radv_meta_save(&saved_state, cmd_buffer,
974                  RADV_META_SAVE_GRAPHICS_PIPELINE | RADV_META_SAVE_DESCRIPTORS);
975
976   struct radv_subpass_attachment dst_att = *subpass->ds_resolve_attachment;
977   struct radv_image_view *dst_iview = cmd_buffer->state.attachments[dst_att.attachment].iview;
978
979   struct radv_subpass resolve_subpass = {
980      .color_count = 0,
981      .color_attachments = NULL,
982      .depth_stencil_attachment = (struct radv_subpass_attachment *){&dst_att},
983   };
984
985   radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass);
986
987   struct radv_image_view tsrc_iview;
988   radv_image_view_init(&tsrc_iview, cmd_buffer->device,
989                        &(VkImageViewCreateInfo){
990                           .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
991                           .image = radv_image_to_handle(src_image),
992                           .viewType = radv_meta_get_view_type(src_image),
993                           .format = src_iview->vk.format,
994                           .subresourceRange =
995                              {
996                                 .aspectMask = aspects,
997                                 .baseMipLevel = 0,
998                                 .levelCount = 1,
999                                 .baseArrayLayer = 0,
1000                                 .layerCount = 1,
1001                              },
1002                        },
1003                        0, NULL);
1004
1005   emit_depth_stencil_resolve(cmd_buffer, &tsrc_iview, dst_iview,
1006                              &(VkExtent2D){fb->width, fb->height}, aspects, resolve_mode);
1007
1008   radv_cmd_buffer_restore_subpass(cmd_buffer, subpass);
1009
1010   radv_image_view_finish(&tsrc_iview);
1011
1012   radv_meta_restore(&saved_state, cmd_buffer);
1013}
1014