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