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 25#include <assert.h> 26#include <stdbool.h> 27 28#include "radv_meta.h" 29#include "radv_private.h" 30#include "nir/nir_builder.h" 31#include "sid.h" 32#include "vk_format.h" 33 34static nir_shader * 35build_nir_vertex_shader(void) 36{ 37 const struct glsl_type *vec4 = glsl_vec4_type(); 38 nir_builder b; 39 40 nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_VERTEX, NULL); 41 b.shader->info.name = ralloc_strdup(b.shader, "meta_resolve_vs"); 42 43 nir_variable *pos_out = nir_variable_create(b.shader, nir_var_shader_out, 44 vec4, "gl_Position"); 45 pos_out->data.location = VARYING_SLOT_POS; 46 47 nir_ssa_def *outvec = radv_meta_gen_rect_vertices(&b); 48 49 nir_store_var(&b, pos_out, outvec, 0xf); 50 return b.shader; 51} 52 53static nir_shader * 54build_resolve_fragment_shader(struct radv_device *dev, bool is_integer, int samples) 55{ 56 nir_builder b; 57 char name[64]; 58 const struct glsl_type *vec2 = glsl_vector_type(GLSL_TYPE_FLOAT, 2); 59 const struct glsl_type *vec4 = glsl_vec4_type(); 60 const struct glsl_type *sampler_type = glsl_sampler_type(GLSL_SAMPLER_DIM_MS, 61 false, 62 false, 63 GLSL_TYPE_FLOAT); 64 65 snprintf(name, 64, "meta_resolve_fs-%d-%s", samples, is_integer ? "int" : "float"); 66 nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_FRAGMENT, NULL); 67 b.shader->info.name = ralloc_strdup(b.shader, name); 68 69 nir_variable *input_img = nir_variable_create(b.shader, nir_var_uniform, 70 sampler_type, "s_tex"); 71 input_img->data.descriptor_set = 0; 72 input_img->data.binding = 0; 73 74 nir_variable *fs_pos_in = nir_variable_create(b.shader, nir_var_shader_in, vec2, "fs_pos_in"); 75 fs_pos_in->data.location = VARYING_SLOT_POS; 76 77 nir_variable *color_out = nir_variable_create(b.shader, nir_var_shader_out, 78 vec4, "f_color"); 79 color_out->data.location = FRAG_RESULT_DATA0; 80 81 nir_ssa_def *pos_in = nir_load_var(&b, fs_pos_in); 82 nir_intrinsic_instr *src_offset = nir_intrinsic_instr_create(b.shader, nir_intrinsic_load_push_constant); 83 nir_intrinsic_set_base(src_offset, 0); 84 nir_intrinsic_set_range(src_offset, 8); 85 src_offset->src[0] = nir_src_for_ssa(nir_imm_int(&b, 0)); 86 src_offset->num_components = 2; 87 nir_ssa_dest_init(&src_offset->instr, &src_offset->dest, 2, 32, "src_offset"); 88 nir_builder_instr_insert(&b, &src_offset->instr); 89 90 nir_ssa_def *pos_int = nir_f2i32(&b, pos_in); 91 92 nir_ssa_def *img_coord = nir_channels(&b, nir_iadd(&b, pos_int, &src_offset->dest.ssa), 0x3); 93 nir_variable *color = nir_local_variable_create(b.impl, glsl_vec4_type(), "color"); 94 95 radv_meta_build_resolve_shader_core(&b, is_integer, samples, input_img, 96 color, img_coord); 97 98 nir_ssa_def *outval = nir_load_var(&b, color); 99 nir_store_var(&b, color_out, outval, 0xf); 100 return b.shader; 101} 102 103 104static VkResult 105create_layout(struct radv_device *device) 106{ 107 VkResult result; 108 /* 109 * one descriptors for the image being sampled 110 */ 111 VkDescriptorSetLayoutCreateInfo ds_create_info = { 112 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, 113 .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, 114 .bindingCount = 1, 115 .pBindings = (VkDescriptorSetLayoutBinding[]) { 116 { 117 .binding = 0, 118 .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 119 .descriptorCount = 1, 120 .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, 121 .pImmutableSamplers = NULL 122 }, 123 } 124 }; 125 126 result = radv_CreateDescriptorSetLayout(radv_device_to_handle(device), 127 &ds_create_info, 128 &device->meta_state.alloc, 129 &device->meta_state.resolve_fragment.ds_layout); 130 if (result != VK_SUCCESS) 131 goto fail; 132 133 134 VkPipelineLayoutCreateInfo pl_create_info = { 135 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 136 .setLayoutCount = 1, 137 .pSetLayouts = &device->meta_state.resolve_fragment.ds_layout, 138 .pushConstantRangeCount = 1, 139 .pPushConstantRanges = &(VkPushConstantRange){VK_SHADER_STAGE_FRAGMENT_BIT, 0, 8}, 140 }; 141 142 result = radv_CreatePipelineLayout(radv_device_to_handle(device), 143 &pl_create_info, 144 &device->meta_state.alloc, 145 &device->meta_state.resolve_fragment.p_layout); 146 if (result != VK_SUCCESS) 147 goto fail; 148 return VK_SUCCESS; 149fail: 150 return result; 151} 152 153static const VkPipelineVertexInputStateCreateInfo normal_vi_create_info = { 154 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 155 .vertexBindingDescriptionCount = 0, 156 .vertexAttributeDescriptionCount = 0, 157}; 158 159static VkResult 160create_resolve_pipeline(struct radv_device *device, 161 int samples_log2, 162 VkFormat format) 163{ 164 mtx_lock(&device->meta_state.mtx); 165 166 unsigned fs_key = radv_format_meta_fs_key(format); 167 VkPipeline *pipeline = &device->meta_state.resolve_fragment.rc[samples_log2].pipeline[fs_key]; 168 if (*pipeline) { 169 mtx_unlock(&device->meta_state.mtx); 170 return VK_SUCCESS; 171 } 172 173 VkResult result; 174 bool is_integer = false; 175 uint32_t samples = 1 << samples_log2; 176 const VkPipelineVertexInputStateCreateInfo *vi_create_info; 177 vi_create_info = &normal_vi_create_info; 178 if (vk_format_is_int(format)) 179 is_integer = true; 180 181 struct radv_shader_module fs = { .nir = NULL }; 182 fs.nir = build_resolve_fragment_shader(device, is_integer, samples); 183 struct radv_shader_module vs = { 184 .nir = build_nir_vertex_shader(), 185 }; 186 187 VkRenderPass *rp = &device->meta_state.resolve_fragment.rc[samples_log2].render_pass[fs_key][0]; 188 189 assert(!*rp); 190 191 VkPipelineShaderStageCreateInfo pipeline_shader_stages[] = { 192 { 193 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 194 .stage = VK_SHADER_STAGE_VERTEX_BIT, 195 .module = radv_shader_module_to_handle(&vs), 196 .pName = "main", 197 .pSpecializationInfo = NULL 198 }, { 199 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 200 .stage = VK_SHADER_STAGE_FRAGMENT_BIT, 201 .module = radv_shader_module_to_handle(&fs), 202 .pName = "main", 203 .pSpecializationInfo = NULL 204 }, 205 }; 206 207 208 for (unsigned dst_layout = 0; dst_layout < RADV_META_DST_LAYOUT_COUNT; ++dst_layout) { 209 VkImageLayout layout = radv_meta_dst_layout_to_layout(dst_layout); 210 result = radv_CreateRenderPass(radv_device_to_handle(device), 211 &(VkRenderPassCreateInfo) { 212 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 213 .attachmentCount = 1, 214 .pAttachments = &(VkAttachmentDescription) { 215 .format = format, 216 .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, 217 .storeOp = VK_ATTACHMENT_STORE_OP_STORE, 218 .initialLayout = layout, 219 .finalLayout = layout, 220 }, 221 .subpassCount = 1, 222 .pSubpasses = &(VkSubpassDescription) { 223 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, 224 .inputAttachmentCount = 0, 225 .colorAttachmentCount = 1, 226 .pColorAttachments = &(VkAttachmentReference) { 227 .attachment = 0, 228 .layout = layout, 229 }, 230 .pResolveAttachments = NULL, 231 .pDepthStencilAttachment = &(VkAttachmentReference) { 232 .attachment = VK_ATTACHMENT_UNUSED, 233 .layout = VK_IMAGE_LAYOUT_GENERAL, 234 }, 235 .preserveAttachmentCount = 0, 236 .pPreserveAttachments = NULL, 237 }, 238 .dependencyCount = 0, 239 }, &device->meta_state.alloc, rp + dst_layout); 240 } 241 242 243 const VkGraphicsPipelineCreateInfo vk_pipeline_info = { 244 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 245 .stageCount = ARRAY_SIZE(pipeline_shader_stages), 246 .pStages = pipeline_shader_stages, 247 .pVertexInputState = vi_create_info, 248 .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) { 249 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 250 .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 251 .primitiveRestartEnable = false, 252 }, 253 .pViewportState = &(VkPipelineViewportStateCreateInfo) { 254 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 255 .viewportCount = 1, 256 .scissorCount = 1, 257 }, 258 .pRasterizationState = &(VkPipelineRasterizationStateCreateInfo) { 259 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 260 .rasterizerDiscardEnable = false, 261 .polygonMode = VK_POLYGON_MODE_FILL, 262 .cullMode = VK_CULL_MODE_NONE, 263 .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE 264 }, 265 .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) { 266 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 267 .rasterizationSamples = 1, 268 .sampleShadingEnable = false, 269 .pSampleMask = (VkSampleMask[]) { UINT32_MAX }, 270 }, 271 .pColorBlendState = &(VkPipelineColorBlendStateCreateInfo) { 272 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 273 .attachmentCount = 1, 274 .pAttachments = (VkPipelineColorBlendAttachmentState []) { 275 { .colorWriteMask = 276 VK_COLOR_COMPONENT_A_BIT | 277 VK_COLOR_COMPONENT_R_BIT | 278 VK_COLOR_COMPONENT_G_BIT | 279 VK_COLOR_COMPONENT_B_BIT }, 280 } 281 }, 282 .pDynamicState = &(VkPipelineDynamicStateCreateInfo) { 283 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, 284 .dynamicStateCount = 9, 285 .pDynamicStates = (VkDynamicState[]) { 286 VK_DYNAMIC_STATE_VIEWPORT, 287 VK_DYNAMIC_STATE_SCISSOR, 288 VK_DYNAMIC_STATE_LINE_WIDTH, 289 VK_DYNAMIC_STATE_DEPTH_BIAS, 290 VK_DYNAMIC_STATE_BLEND_CONSTANTS, 291 VK_DYNAMIC_STATE_DEPTH_BOUNDS, 292 VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, 293 VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, 294 VK_DYNAMIC_STATE_STENCIL_REFERENCE, 295 }, 296 }, 297 .flags = 0, 298 .layout = device->meta_state.resolve_fragment.p_layout, 299 .renderPass = *rp, 300 .subpass = 0, 301 }; 302 303 const struct radv_graphics_pipeline_create_info radv_pipeline_info = { 304 .use_rectlist = true 305 }; 306 307 result = radv_graphics_pipeline_create(radv_device_to_handle(device), 308 radv_pipeline_cache_to_handle(&device->meta_state.cache), 309 &vk_pipeline_info, &radv_pipeline_info, 310 &device->meta_state.alloc, 311 pipeline); 312 ralloc_free(vs.nir); 313 ralloc_free(fs.nir); 314 315 mtx_unlock(&device->meta_state.mtx); 316 return result; 317} 318 319VkResult 320radv_device_init_meta_resolve_fragment_state(struct radv_device *device, bool on_demand) 321{ 322 VkResult res; 323 324 res = create_layout(device); 325 if (res != VK_SUCCESS) 326 goto fail; 327 328 if (on_demand) 329 return VK_SUCCESS; 330 331 for (uint32_t i = 0; i < MAX_SAMPLES_LOG2; ++i) { 332 for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) { 333 res = create_resolve_pipeline(device, i, radv_fs_key_format_exemplars[j]); 334 if (res != VK_SUCCESS) 335 goto fail; 336 } 337 } 338 339 return VK_SUCCESS; 340fail: 341 radv_device_finish_meta_resolve_fragment_state(device); 342 return res; 343} 344 345void 346radv_device_finish_meta_resolve_fragment_state(struct radv_device *device) 347{ 348 struct radv_meta_state *state = &device->meta_state; 349 for (uint32_t i = 0; i < MAX_SAMPLES_LOG2; ++i) { 350 for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) { 351 for(unsigned k =0; k < RADV_META_DST_LAYOUT_COUNT; ++k) { 352 radv_DestroyRenderPass(radv_device_to_handle(device), 353 state->resolve_fragment.rc[i].render_pass[j][k], 354 &state->alloc); 355 } 356 radv_DestroyPipeline(radv_device_to_handle(device), 357 state->resolve_fragment.rc[i].pipeline[j], 358 &state->alloc); 359 } 360 } 361 362 radv_DestroyDescriptorSetLayout(radv_device_to_handle(device), 363 state->resolve_fragment.ds_layout, 364 &state->alloc); 365 radv_DestroyPipelineLayout(radv_device_to_handle(device), 366 state->resolve_fragment.p_layout, 367 &state->alloc); 368} 369 370static void 371emit_resolve(struct radv_cmd_buffer *cmd_buffer, 372 struct radv_image_view *src_iview, 373 struct radv_image_view *dest_iview, 374 const VkOffset2D *src_offset, 375 const VkOffset2D *dest_offset, 376 const VkExtent2D *resolve_extent) 377{ 378 struct radv_device *device = cmd_buffer->device; 379 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer); 380 const uint32_t samples = src_iview->image->info.samples; 381 const uint32_t samples_log2 = ffs(samples) - 1; 382 radv_meta_push_descriptor_set(cmd_buffer, 383 VK_PIPELINE_BIND_POINT_GRAPHICS, 384 cmd_buffer->device->meta_state.resolve_fragment.p_layout, 385 0, /* set */ 386 1, /* descriptorWriteCount */ 387 (VkWriteDescriptorSet[]) { 388 { 389 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 390 .dstBinding = 0, 391 .dstArrayElement = 0, 392 .descriptorCount = 1, 393 .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 394 .pImageInfo = (VkDescriptorImageInfo[]) { 395 { 396 .sampler = VK_NULL_HANDLE, 397 .imageView = radv_image_view_to_handle(src_iview), 398 .imageLayout = VK_IMAGE_LAYOUT_GENERAL, 399 }, 400 } 401 }, 402 }); 403 404 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB; 405 406 unsigned push_constants[2] = { 407 src_offset->x - dest_offset->x, 408 src_offset->y - dest_offset->y, 409 }; 410 radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer), 411 device->meta_state.resolve_fragment.p_layout, 412 VK_SHADER_STAGE_FRAGMENT_BIT, 0, 8, 413 push_constants); 414 415 unsigned fs_key = radv_format_meta_fs_key(dest_iview->vk_format); 416 VkPipeline* pipeline = &device->meta_state.resolve_fragment.rc[samples_log2].pipeline[fs_key]; 417 418 if (*pipeline == VK_NULL_HANDLE) { 419 VkResult ret = create_resolve_pipeline(device, samples_log2, radv_fs_key_format_exemplars[fs_key]); 420 if (ret != VK_SUCCESS) { 421 cmd_buffer->record_result = ret; 422 return; 423 } 424 } 425 426 radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS, 427 *pipeline); 428 429 radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkViewport) { 430 .x = dest_offset->x, 431 .y = dest_offset->y, 432 .width = resolve_extent->width, 433 .height = resolve_extent->height, 434 .minDepth = 0.0f, 435 .maxDepth = 1.0f 436 }); 437 438 radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkRect2D) { 439 .offset = *dest_offset, 440 .extent = *resolve_extent, 441 }); 442 443 radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0); 444 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB; 445} 446 447void radv_meta_resolve_fragment_image(struct radv_cmd_buffer *cmd_buffer, 448 struct radv_image *src_image, 449 VkImageLayout src_image_layout, 450 struct radv_image *dest_image, 451 VkImageLayout dest_image_layout, 452 uint32_t region_count, 453 const VkImageResolve *regions) 454{ 455 struct radv_device *device = cmd_buffer->device; 456 struct radv_meta_saved_state saved_state; 457 const uint32_t samples = src_image->info.samples; 458 const uint32_t samples_log2 = ffs(samples) - 1; 459 unsigned fs_key = radv_format_meta_fs_key(dest_image->vk_format); 460 unsigned dst_layout = radv_meta_dst_layout_from_layout(dest_image_layout); 461 VkRenderPass rp; 462 463 radv_decompress_resolve_src(cmd_buffer, src_image, src_image_layout, 464 region_count, regions); 465 466 if (!device->meta_state.resolve_fragment.rc[samples_log2].render_pass[fs_key][dst_layout]) { 467 VkResult ret = create_resolve_pipeline(device, samples_log2, radv_fs_key_format_exemplars[fs_key]); 468 if (ret != VK_SUCCESS) { 469 cmd_buffer->record_result = ret; 470 return; 471 } 472 } 473 474 rp = device->meta_state.resolve_fragment.rc[samples_log2].render_pass[fs_key][dst_layout]; 475 476 radv_meta_save(&saved_state, cmd_buffer, 477 RADV_META_SAVE_GRAPHICS_PIPELINE | 478 RADV_META_SAVE_CONSTANTS | 479 RADV_META_SAVE_DESCRIPTORS); 480 481 for (uint32_t r = 0; r < region_count; ++r) { 482 const VkImageResolve *region = ®ions[r]; 483 484 assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); 485 assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); 486 assert(region->srcSubresource.layerCount == region->dstSubresource.layerCount); 487 488 const uint32_t src_base_layer = 489 radv_meta_get_iview_layer(src_image, ®ion->srcSubresource, 490 ®ion->srcOffset); 491 492 const uint32_t dest_base_layer = 493 radv_meta_get_iview_layer(dest_image, ®ion->dstSubresource, 494 ®ion->dstOffset); 495 496 const struct VkExtent3D extent = 497 radv_sanitize_image_extent(src_image->type, region->extent); 498 const struct VkOffset3D srcOffset = 499 radv_sanitize_image_offset(src_image->type, region->srcOffset); 500 const struct VkOffset3D dstOffset = 501 radv_sanitize_image_offset(dest_image->type, region->dstOffset); 502 503 for (uint32_t layer = 0; layer < region->srcSubresource.layerCount; 504 ++layer) { 505 506 struct radv_image_view src_iview; 507 radv_image_view_init(&src_iview, cmd_buffer->device, 508 &(VkImageViewCreateInfo) { 509 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 510 .image = radv_image_to_handle(src_image), 511 .viewType = radv_meta_get_view_type(src_image), 512 .format = src_image->vk_format, 513 .subresourceRange = { 514 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 515 .baseMipLevel = region->srcSubresource.mipLevel, 516 .levelCount = 1, 517 .baseArrayLayer = src_base_layer + layer, 518 .layerCount = 1, 519 }, 520 }); 521 522 struct radv_image_view dest_iview; 523 radv_image_view_init(&dest_iview, cmd_buffer->device, 524 &(VkImageViewCreateInfo) { 525 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 526 .image = radv_image_to_handle(dest_image), 527 .viewType = radv_meta_get_view_type(dest_image), 528 .format = dest_image->vk_format, 529 .subresourceRange = { 530 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 531 .baseMipLevel = region->dstSubresource.mipLevel, 532 .levelCount = 1, 533 .baseArrayLayer = dest_base_layer + layer, 534 .layerCount = 1, 535 }, 536 }); 537 538 539 VkFramebuffer fb; 540 radv_CreateFramebuffer(radv_device_to_handle(cmd_buffer->device), 541 &(VkFramebufferCreateInfo) { 542 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 543 .attachmentCount = 1, 544 .pAttachments = (VkImageView[]) { 545 radv_image_view_to_handle(&dest_iview), 546 }, 547 .width = extent.width + dstOffset.x, 548 .height = extent.height + dstOffset.y, 549 .layers = 1 550 }, &cmd_buffer->pool->alloc, &fb); 551 552 radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer), 553 &(VkRenderPassBeginInfo) { 554 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 555 .renderPass = rp, 556 .framebuffer = fb, 557 .renderArea = { 558 .offset = { dstOffset.x, dstOffset.y, }, 559 .extent = { extent.width, extent.height }, 560 }, 561 .clearValueCount = 0, 562 .pClearValues = NULL, 563 }, VK_SUBPASS_CONTENTS_INLINE); 564 565 566 567 emit_resolve(cmd_buffer, 568 &src_iview, 569 &dest_iview, 570 &(VkOffset2D) { srcOffset.x, srcOffset.y }, 571 &(VkOffset2D) { dstOffset.x, dstOffset.y }, 572 &(VkExtent2D) { extent.width, extent.height }); 573 574 radv_CmdEndRenderPass(radv_cmd_buffer_to_handle(cmd_buffer)); 575 576 radv_DestroyFramebuffer(radv_device_to_handle(cmd_buffer->device), fb, &cmd_buffer->pool->alloc); 577 } 578 } 579 580 radv_meta_restore(&saved_state, cmd_buffer); 581} 582 583 584/** 585 * Emit any needed resolves for the current subpass. 586 */ 587void 588radv_cmd_buffer_resolve_subpass_fs(struct radv_cmd_buffer *cmd_buffer) 589{ 590 struct radv_framebuffer *fb = cmd_buffer->state.framebuffer; 591 const struct radv_subpass *subpass = cmd_buffer->state.subpass; 592 struct radv_meta_saved_state saved_state; 593 struct radv_subpass_barrier barrier; 594 595 /* Resolves happen before the end-of-subpass barriers get executed, 596 * so we have to make the attachment shader-readable */ 597 barrier.src_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 598 barrier.src_access_mask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 599 barrier.dst_access_mask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; 600 radv_subpass_barrier(cmd_buffer, &barrier); 601 602 radv_decompress_resolve_subpass_src(cmd_buffer); 603 604 radv_meta_save(&saved_state, cmd_buffer, 605 RADV_META_SAVE_GRAPHICS_PIPELINE | 606 RADV_META_SAVE_CONSTANTS | 607 RADV_META_SAVE_DESCRIPTORS); 608 609 for (uint32_t i = 0; i < subpass->color_count; ++i) { 610 struct radv_subpass_attachment src_att = subpass->color_attachments[i]; 611 struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i]; 612 613 if (dest_att.attachment == VK_ATTACHMENT_UNUSED) 614 continue; 615 616 struct radv_image_view *dest_iview = cmd_buffer->state.framebuffer->attachments[dest_att.attachment].attachment; 617 struct radv_image_view *src_iview = cmd_buffer->state.framebuffer->attachments[src_att.attachment].attachment; 618 619 struct radv_subpass resolve_subpass = { 620 .color_count = 1, 621 .color_attachments = (struct radv_subpass_attachment[]) { dest_att }, 622 .depth_stencil_attachment = NULL, 623 }; 624 625 radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass); 626 627 emit_resolve(cmd_buffer, 628 src_iview, 629 dest_iview, 630 &(VkOffset2D) { 0, 0 }, 631 &(VkOffset2D) { 0, 0 }, 632 &(VkExtent2D) { fb->width, fb->height }); 633 } 634 635 cmd_buffer->state.subpass = subpass; 636 radv_meta_restore(&saved_state, cmd_buffer); 637} 638