radv/pipeline: Don't dereference NULL dynamic state pointers
[mesa.git] / src / amd / vulkan / radv_meta_resolve.c
1 /*
2 * Copyright © 2016 Intel Corporation
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 "radv_meta.h"
28 #include "radv_private.h"
29 #include "nir/nir_builder.h"
30 #include "sid.h"
31 /**
32 * Vertex attributes used by all pipelines.
33 */
34 struct vertex_attrs {
35 float position[2]; /**< 3DPRIM_RECTLIST */
36 float tex_position[2];
37 };
38
39 /* passthrough vertex shader */
40 static nir_shader *
41 build_nir_vs(void)
42 {
43 const struct glsl_type *vec4 = glsl_vec4_type();
44
45 nir_builder b;
46 nir_variable *a_position;
47 nir_variable *v_position;
48 nir_variable *a_tex_position;
49 nir_variable *v_tex_position;
50
51 nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_VERTEX, NULL);
52 b.shader->info->name = ralloc_strdup(b.shader, "meta_resolve_vs");
53
54 a_position = nir_variable_create(b.shader, nir_var_shader_in, vec4,
55 "a_position");
56 a_position->data.location = VERT_ATTRIB_GENERIC0;
57
58 v_position = nir_variable_create(b.shader, nir_var_shader_out, vec4,
59 "gl_Position");
60 v_position->data.location = VARYING_SLOT_POS;
61
62 a_tex_position = nir_variable_create(b.shader, nir_var_shader_in, vec4,
63 "a_tex_position");
64 a_tex_position->data.location = VERT_ATTRIB_GENERIC1;
65
66 v_tex_position = nir_variable_create(b.shader, nir_var_shader_out, vec4,
67 "v_tex_position");
68 v_tex_position->data.location = VARYING_SLOT_VAR0;
69
70 nir_copy_var(&b, v_position, a_position);
71 nir_copy_var(&b, v_tex_position, a_tex_position);
72
73 return b.shader;
74 }
75
76 /* simple passthrough shader */
77 static nir_shader *
78 build_nir_fs(void)
79 {
80 const struct glsl_type *vec4 = glsl_vec4_type();
81 nir_builder b;
82 nir_variable *v_tex_position; /* vec4, varying texture coordinate */
83 nir_variable *f_color; /* vec4, fragment output color */
84
85 nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_FRAGMENT, NULL);
86 b.shader->info->name = ralloc_asprintf(b.shader,
87 "meta_resolve_fs");
88
89 v_tex_position = nir_variable_create(b.shader, nir_var_shader_in, vec4,
90 "v_tex_position");
91 v_tex_position->data.location = VARYING_SLOT_VAR0;
92
93 f_color = nir_variable_create(b.shader, nir_var_shader_out, vec4,
94 "f_color");
95 f_color->data.location = FRAG_RESULT_DATA0;
96
97 nir_copy_var(&b, f_color, v_tex_position);
98
99 return b.shader;
100 }
101
102 static VkResult
103 create_pass(struct radv_device *device)
104 {
105 VkResult result;
106 VkDevice device_h = radv_device_to_handle(device);
107 const VkAllocationCallbacks *alloc = &device->meta_state.alloc;
108 VkAttachmentDescription attachments[2];
109 int i;
110
111 for (i = 0; i < 2; i++) {
112 attachments[i].format = VK_FORMAT_UNDEFINED;
113 attachments[i].samples = 1;
114 attachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
115 attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
116 attachments[i].initialLayout = VK_IMAGE_LAYOUT_GENERAL;
117 attachments[i].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
118 }
119
120 result = radv_CreateRenderPass(device_h,
121 &(VkRenderPassCreateInfo) {
122 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
123 .attachmentCount = 2,
124 .pAttachments = attachments,
125 .subpassCount = 1,
126 .pSubpasses = &(VkSubpassDescription) {
127 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
128 .inputAttachmentCount = 0,
129 .colorAttachmentCount = 2,
130 .pColorAttachments = (VkAttachmentReference[]) {
131 {
132 .attachment = 0,
133 .layout = VK_IMAGE_LAYOUT_GENERAL,
134 },
135 {
136 .attachment = 1,
137 .layout = VK_IMAGE_LAYOUT_GENERAL,
138 },
139 },
140 .pResolveAttachments = NULL,
141 .pDepthStencilAttachment = &(VkAttachmentReference) {
142 .attachment = VK_ATTACHMENT_UNUSED,
143 },
144 .preserveAttachmentCount = 0,
145 .pPreserveAttachments = NULL,
146 },
147 .dependencyCount = 0,
148 },
149 alloc,
150 &device->meta_state.resolve.pass);
151
152 return result;
153 }
154
155 static VkResult
156 create_pipeline(struct radv_device *device,
157 VkShaderModule vs_module_h)
158 {
159 VkResult result;
160 VkDevice device_h = radv_device_to_handle(device);
161
162 struct radv_shader_module fs_module = {
163 .nir = build_nir_fs(),
164 };
165
166 if (!fs_module.nir) {
167 /* XXX: Need more accurate error */
168 result = VK_ERROR_OUT_OF_HOST_MEMORY;
169 goto cleanup;
170 }
171
172 result = radv_graphics_pipeline_create(device_h,
173 radv_pipeline_cache_to_handle(&device->meta_state.cache),
174 &(VkGraphicsPipelineCreateInfo) {
175 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
176 .stageCount = 2,
177 .pStages = (VkPipelineShaderStageCreateInfo[]) {
178 {
179 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
180 .stage = VK_SHADER_STAGE_VERTEX_BIT,
181 .module = vs_module_h,
182 .pName = "main",
183 },
184 {
185 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
186 .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
187 .module = radv_shader_module_to_handle(&fs_module),
188 .pName = "main",
189 },
190 },
191 .pVertexInputState = &(VkPipelineVertexInputStateCreateInfo) {
192 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
193 .vertexBindingDescriptionCount = 1,
194 .pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
195 {
196 .binding = 0,
197 .stride = sizeof(struct vertex_attrs),
198 .inputRate = VK_VERTEX_INPUT_RATE_VERTEX
199 },
200 },
201 .vertexAttributeDescriptionCount = 2,
202 .pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
203 {
204 /* Position */
205 .location = 0,
206 .binding = 0,
207 .format = VK_FORMAT_R32G32_SFLOAT,
208 .offset = offsetof(struct vertex_attrs, position),
209 },
210 {
211 /* Texture Coordinate */
212 .location = 1,
213 .binding = 0,
214 .format = VK_FORMAT_R32G32_SFLOAT,
215 .offset = offsetof(struct vertex_attrs, tex_position),
216 },
217 },
218 },
219 .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) {
220 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
221 .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
222 .primitiveRestartEnable = false,
223 },
224 .pViewportState = &(VkPipelineViewportStateCreateInfo) {
225 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
226 .viewportCount = 0,
227 .scissorCount = 0,
228 },
229 .pRasterizationState = &(VkPipelineRasterizationStateCreateInfo) {
230 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
231 .depthClampEnable = false,
232 .rasterizerDiscardEnable = false,
233 .polygonMode = VK_POLYGON_MODE_FILL,
234 .cullMode = VK_CULL_MODE_NONE,
235 .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
236 },
237 .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
238 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
239 .rasterizationSamples = 1,
240 .sampleShadingEnable = false,
241 .pSampleMask = NULL,
242 .alphaToCoverageEnable = false,
243 .alphaToOneEnable = false,
244 },
245 .pColorBlendState = &(VkPipelineColorBlendStateCreateInfo) {
246 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
247 .logicOpEnable = false,
248 .attachmentCount = 2,
249 .pAttachments = (VkPipelineColorBlendAttachmentState []) {
250 {
251 .colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
252 VK_COLOR_COMPONENT_G_BIT |
253 VK_COLOR_COMPONENT_B_BIT |
254 VK_COLOR_COMPONENT_A_BIT,
255 },
256 {
257 .colorWriteMask = 0,
258
259 }
260 },
261 },
262 .pDynamicState = NULL,
263 .renderPass = device->meta_state.resolve.pass,
264 .subpass = 0,
265 },
266 &(struct radv_graphics_pipeline_create_info) {
267 .use_rectlist = true,
268 .custom_blend_mode = V_028808_CB_RESOLVE,
269 },
270 &device->meta_state.alloc,
271 &device->meta_state.resolve.pipeline);
272 if (result != VK_SUCCESS)
273 goto cleanup;
274
275 goto cleanup;
276
277 cleanup:
278 ralloc_free(fs_module.nir);
279 return result;
280 }
281
282 void
283 radv_device_finish_meta_resolve_state(struct radv_device *device)
284 {
285 struct radv_meta_state *state = &device->meta_state;
286 VkDevice device_h = radv_device_to_handle(device);
287 VkRenderPass pass_h = device->meta_state.resolve.pass;
288 const VkAllocationCallbacks *alloc = &device->meta_state.alloc;
289
290 if (pass_h)
291 radv_DestroyRenderPass(device_h, pass_h,
292 &device->meta_state.alloc);
293
294 VkPipeline pipeline_h = state->resolve.pipeline;
295 if (pipeline_h) {
296 radv_DestroyPipeline(device_h, pipeline_h, alloc);
297 }
298 }
299
300 VkResult
301 radv_device_init_meta_resolve_state(struct radv_device *device)
302 {
303 VkResult res = VK_SUCCESS;
304
305 zero(device->meta_state.resolve);
306
307 struct radv_shader_module vs_module = { .nir = build_nir_vs() };
308 if (!vs_module.nir) {
309 /* XXX: Need more accurate error */
310 res = VK_ERROR_OUT_OF_HOST_MEMORY;
311 goto fail;
312 }
313
314 res = create_pass(device);
315 if (res != VK_SUCCESS)
316 goto fail;
317
318 VkShaderModule vs_module_h = radv_shader_module_to_handle(&vs_module);
319 res = create_pipeline(device, vs_module_h);
320 if (res != VK_SUCCESS)
321 goto fail;
322
323 goto cleanup;
324
325 fail:
326 radv_device_finish_meta_resolve_state(device);
327
328 cleanup:
329 ralloc_free(vs_module.nir);
330
331 return res;
332 }
333
334 static void
335 emit_resolve(struct radv_cmd_buffer *cmd_buffer,
336 const VkOffset2D *src_offset,
337 const VkOffset2D *dest_offset,
338 const VkExtent2D *resolve_extent)
339 {
340 struct radv_device *device = cmd_buffer->device;
341 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
342 uint32_t offset;
343 const struct vertex_attrs vertex_data[3] = {
344 {
345 .position = {
346 dest_offset->x,
347 dest_offset->y,
348 },
349 .tex_position = {
350 src_offset->x,
351 src_offset->y,
352 },
353 },
354 {
355 .position = {
356 dest_offset->x,
357 dest_offset->y + resolve_extent->height,
358 },
359 .tex_position = {
360 src_offset->x,
361 src_offset->y + resolve_extent->height,
362 },
363 },
364 {
365 .position = {
366 dest_offset->x + resolve_extent->width,
367 dest_offset->y,
368 },
369 .tex_position = {
370 src_offset->x + resolve_extent->width,
371 src_offset->y,
372 },
373 },
374 };
375
376 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB;
377 radv_cmd_buffer_upload_data(cmd_buffer, sizeof(vertex_data), 16, vertex_data, &offset);
378 struct radv_buffer vertex_buffer = {
379 .device = device,
380 .size = sizeof(vertex_data),
381 .bo = cmd_buffer->upload.upload_bo,
382 .offset = offset,
383 };
384
385 VkBuffer vertex_buffer_h = radv_buffer_to_handle(&vertex_buffer);
386
387 radv_CmdBindVertexBuffers(cmd_buffer_h,
388 /*firstBinding*/ 0,
389 /*bindingCount*/ 1,
390 (VkBuffer[]) { vertex_buffer_h },
391 (VkDeviceSize[]) { 0 });
392
393 VkPipeline pipeline_h = device->meta_state.resolve.pipeline;
394 RADV_FROM_HANDLE(radv_pipeline, pipeline, pipeline_h);
395
396 if (cmd_buffer->state.pipeline != pipeline) {
397 radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
398 pipeline_h);
399 }
400
401 radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0);
402 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB;
403 si_emit_cache_flush(cmd_buffer);
404 }
405
406 void radv_CmdResolveImage(
407 VkCommandBuffer cmd_buffer_h,
408 VkImage src_image_h,
409 VkImageLayout src_image_layout,
410 VkImage dest_image_h,
411 VkImageLayout dest_image_layout,
412 uint32_t region_count,
413 const VkImageResolve* regions)
414 {
415 RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, cmd_buffer_h);
416 RADV_FROM_HANDLE(radv_image, src_image, src_image_h);
417 RADV_FROM_HANDLE(radv_image, dest_image, dest_image_h);
418 struct radv_device *device = cmd_buffer->device;
419 struct radv_meta_saved_state saved_state;
420 VkDevice device_h = radv_device_to_handle(device);
421 bool use_compute_resolve = false;
422
423 /* we can use the hw resolve only for single full resolves */
424 if (region_count == 1) {
425 if (regions[0].srcOffset.x ||
426 regions[0].srcOffset.y ||
427 regions[0].srcOffset.z)
428 use_compute_resolve = true;
429 if (regions[0].dstOffset.x ||
430 regions[0].dstOffset.y ||
431 regions[0].dstOffset.z)
432 use_compute_resolve = true;
433
434 if (regions[0].extent.width != src_image->extent.width ||
435 regions[0].extent.height != src_image->extent.height ||
436 regions[0].extent.depth != src_image->extent.depth)
437 use_compute_resolve = true;
438 } else
439 use_compute_resolve = true;
440
441 if (use_compute_resolve) {
442
443 radv_fast_clear_flush_image_inplace(cmd_buffer, src_image);
444 radv_meta_resolve_compute_image(cmd_buffer,
445 src_image,
446 src_image_layout,
447 dest_image,
448 dest_image_layout,
449 region_count, regions);
450 return;
451 }
452
453 radv_meta_save_graphics_reset_vport_scissor(&saved_state, cmd_buffer);
454
455 assert(src_image->samples > 1);
456 assert(dest_image->samples == 1);
457
458 if (src_image->samples >= 16) {
459 /* See commit aa3f9aaf31e9056a255f9e0472ebdfdaa60abe54 for the
460 * glBlitFramebuffer workaround for samples >= 16.
461 */
462 radv_finishme("vkCmdResolveImage: need interpolation workaround when "
463 "samples >= 16");
464 }
465
466 if (src_image->array_size > 1)
467 radv_finishme("vkCmdResolveImage: multisample array images");
468
469 for (uint32_t r = 0; r < region_count; ++r) {
470 const VkImageResolve *region = &regions[r];
471
472 /* From the Vulkan 1.0 spec:
473 *
474 * - The aspectMask member of srcSubresource and dstSubresource must
475 * only contain VK_IMAGE_ASPECT_COLOR_BIT
476 *
477 * - The layerCount member of srcSubresource and dstSubresource must
478 * match
479 */
480 assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
481 assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
482 assert(region->srcSubresource.layerCount ==
483 region->dstSubresource.layerCount);
484
485 const uint32_t src_base_layer =
486 radv_meta_get_iview_layer(src_image, &region->srcSubresource,
487 &region->srcOffset);
488
489 const uint32_t dest_base_layer =
490 radv_meta_get_iview_layer(dest_image, &region->dstSubresource,
491 &region->dstOffset);
492
493 /**
494 * From Vulkan 1.0.6 spec: 18.6 Resolving Multisample Images
495 *
496 * extent is the size in texels of the source image to resolve in width,
497 * height and depth. 1D images use only x and width. 2D images use x, y,
498 * width and height. 3D images use x, y, z, width, height and depth.
499 *
500 * srcOffset and dstOffset select the initial x, y, and z offsets in
501 * texels of the sub-regions of the source and destination image data.
502 * extent is the size in texels of the source image to resolve in width,
503 * height and depth. 1D images use only x and width. 2D images use x, y,
504 * width and height. 3D images use x, y, z, width, height and depth.
505 */
506 const struct VkExtent3D extent =
507 radv_sanitize_image_extent(src_image->type, region->extent);
508 const struct VkOffset3D srcOffset =
509 radv_sanitize_image_offset(src_image->type, region->srcOffset);
510 const struct VkOffset3D dstOffset =
511 radv_sanitize_image_offset(dest_image->type, region->dstOffset);
512
513
514 for (uint32_t layer = 0; layer < region->srcSubresource.layerCount;
515 ++layer) {
516
517 struct radv_image_view src_iview;
518 radv_image_view_init(&src_iview, cmd_buffer->device,
519 &(VkImageViewCreateInfo) {
520 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
521 .image = src_image_h,
522 .viewType = radv_meta_get_view_type(src_image),
523 .format = src_image->vk_format,
524 .subresourceRange = {
525 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
526 .baseMipLevel = region->srcSubresource.mipLevel,
527 .levelCount = 1,
528 .baseArrayLayer = src_base_layer + layer,
529 .layerCount = 1,
530 },
531 },
532 cmd_buffer, VK_IMAGE_USAGE_SAMPLED_BIT);
533
534 struct radv_image_view dest_iview;
535 radv_image_view_init(&dest_iview, cmd_buffer->device,
536 &(VkImageViewCreateInfo) {
537 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
538 .image = dest_image_h,
539 .viewType = radv_meta_get_view_type(dest_image),
540 .format = dest_image->vk_format,
541 .subresourceRange = {
542 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
543 .baseMipLevel = region->dstSubresource.mipLevel,
544 .levelCount = 1,
545 .baseArrayLayer = dest_base_layer + layer,
546 .layerCount = 1,
547 },
548 },
549 cmd_buffer, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
550
551 VkFramebuffer fb_h;
552 radv_CreateFramebuffer(device_h,
553 &(VkFramebufferCreateInfo) {
554 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
555 .attachmentCount = 2,
556 .pAttachments = (VkImageView[]) {
557 radv_image_view_to_handle(&src_iview),
558 radv_image_view_to_handle(&dest_iview),
559 },
560 .width = radv_minify(dest_image->extent.width,
561 region->dstSubresource.mipLevel),
562 .height = radv_minify(dest_image->extent.height,
563 region->dstSubresource.mipLevel),
564 .layers = 1
565 },
566 &cmd_buffer->pool->alloc,
567 &fb_h);
568
569 radv_CmdBeginRenderPass(cmd_buffer_h,
570 &(VkRenderPassBeginInfo) {
571 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
572 .renderPass = device->meta_state.resolve.pass,
573 .framebuffer = fb_h,
574 .renderArea = {
575 .offset = {
576 dstOffset.x,
577 dstOffset.y,
578 },
579 .extent = {
580 extent.width,
581 extent.height,
582 }
583 },
584 .clearValueCount = 0,
585 .pClearValues = NULL,
586 },
587 VK_SUBPASS_CONTENTS_INLINE);
588
589 emit_resolve(cmd_buffer,
590 &(VkOffset2D) {
591 .x = srcOffset.x,
592 .y = srcOffset.y,
593 },
594 &(VkOffset2D) {
595 .x = dstOffset.x,
596 .y = dstOffset.y,
597 },
598 &(VkExtent2D) {
599 .width = extent.width,
600 .height = extent.height,
601 });
602
603 radv_CmdEndRenderPass(cmd_buffer_h);
604
605 radv_DestroyFramebuffer(device_h, fb_h,
606 &cmd_buffer->pool->alloc);
607 }
608 }
609
610 radv_meta_restore(&saved_state, cmd_buffer);
611 }
612
613 /**
614 * Emit any needed resolves for the current subpass.
615 */
616 void
617 radv_cmd_buffer_resolve_subpass(struct radv_cmd_buffer *cmd_buffer)
618 {
619 struct radv_framebuffer *fb = cmd_buffer->state.framebuffer;
620 const struct radv_subpass *subpass = cmd_buffer->state.subpass;
621 struct radv_meta_saved_state saved_state;
622
623 /* FINISHME(perf): Skip clears for resolve attachments.
624 *
625 * From the Vulkan 1.0 spec:
626 *
627 * If the first use of an attachment in a render pass is as a resolve
628 * attachment, then the loadOp is effectively ignored as the resolve is
629 * guaranteed to overwrite all pixels in the render area.
630 */
631
632 if (!subpass->has_resolve)
633 return;
634
635 radv_meta_save_graphics_reset_vport_scissor(&saved_state, cmd_buffer);
636
637 for (uint32_t i = 0; i < subpass->color_count; ++i) {
638 VkAttachmentReference src_att = subpass->color_attachments[i];
639 VkAttachmentReference dest_att = subpass->resolve_attachments[i];
640 struct radv_image *dst_img = cmd_buffer->state.framebuffer->attachments[dest_att.attachment].attachment->image;
641 if (dest_att.attachment == VK_ATTACHMENT_UNUSED)
642 continue;
643
644 if (dst_img->surface.dcc_size) {
645 radv_initialize_dcc(cmd_buffer, dst_img, 0xffffffff);
646 cmd_buffer->state.attachments[dest_att.attachment].current_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
647 }
648
649 struct radv_subpass resolve_subpass = {
650 .color_count = 2,
651 .color_attachments = (VkAttachmentReference[]) { src_att, dest_att },
652 .depth_stencil_attachment = { .attachment = VK_ATTACHMENT_UNUSED },
653 };
654
655 radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass, false);
656
657 /* Subpass resolves must respect the render area. We can ignore the
658 * render area here because vkCmdBeginRenderPass set the render area
659 * with 3DSTATE_DRAWING_RECTANGLE.
660 *
661 * XXX(chadv): Does the hardware really respect
662 * 3DSTATE_DRAWING_RECTANGLE when draing a 3DPRIM_RECTLIST?
663 */
664 emit_resolve(cmd_buffer,
665 &(VkOffset2D) { 0, 0 },
666 &(VkOffset2D) { 0, 0 },
667 &(VkExtent2D) { fb->width, fb->height });
668 }
669
670 cmd_buffer->state.subpass = subpass;
671 radv_meta_restore(&saved_state, cmd_buffer);
672 }