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 34 static nir_shader * 35 build_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 53 static nir_shader * 54 build_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 104 static VkResult 105 create_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; 149 fail: 150 return result; 151 } 152 153 static 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 159 static VkFormat pipeline_formats[] = { 160 VK_FORMAT_R8G8B8A8_UNORM, 161 VK_FORMAT_R8G8B8A8_UINT, 162 VK_FORMAT_R8G8B8A8_SINT, 163 VK_FORMAT_A2R10G10B10_UINT_PACK32, 164 VK_FORMAT_A2R10G10B10_SINT_PACK32, 165 VK_FORMAT_R16G16B16A16_UNORM, 166 VK_FORMAT_R16G16B16A16_SNORM, 167 VK_FORMAT_R16G16B16A16_UINT, 168 VK_FORMAT_R16G16B16A16_SINT, 169 VK_FORMAT_R32_SFLOAT, 170 VK_FORMAT_R32G32_SFLOAT, 171 VK_FORMAT_R32G32B32A32_SFLOAT 172 }; 173 174 static VkResult 175 create_resolve_pipeline(struct radv_device *device, 176 int samples_log2, 177 VkFormat format) 178 { 179 VkResult result; 180 bool is_integer = false; 181 uint32_t samples = 1 << samples_log2; 182 unsigned fs_key = radv_format_meta_fs_key(format); 183 const VkPipelineVertexInputStateCreateInfo *vi_create_info; 184 vi_create_info = &normal_vi_create_info; 185 if (vk_format_is_int(format)) 186 is_integer = true; 187 188 struct radv_shader_module fs = { .nir = NULL }; 189 fs.nir = build_resolve_fragment_shader(device, is_integer, samples); 190 struct radv_shader_module vs = { 191 .nir = build_nir_vertex_shader(), 192 }; 193 194 VkRenderPass *rp = &device->meta_state.resolve_fragment.rc[samples_log2].render_pass[fs_key][0]; 195 196 assert(!*rp); 197 198 VkPipeline *pipeline = &device->meta_state.resolve_fragment.rc[samples_log2].pipeline[fs_key]; 199 assert(!*pipeline); 200 201 VkPipelineShaderStageCreateInfo pipeline_shader_stages[] = { 202 { 203 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 204 .stage = VK_SHADER_STAGE_VERTEX_BIT, 205 .module = radv_shader_module_to_handle(&vs), 206 .pName = "main", 207 .pSpecializationInfo = NULL 208 }, { 209 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 210 .stage = VK_SHADER_STAGE_FRAGMENT_BIT, 211 .module = radv_shader_module_to_handle(&fs), 212 .pName = "main", 213 .pSpecializationInfo = NULL 214 }, 215 }; 216 217 218 for (unsigned dst_layout = 0; dst_layout < RADV_META_DST_LAYOUT_COUNT; ++dst_layout) { 219 VkImageLayout layout = radv_meta_dst_layout_to_layout(dst_layout); 220 result = radv_CreateRenderPass(radv_device_to_handle(device), 221 &(VkRenderPassCreateInfo) { 222 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 223 .attachmentCount = 1, 224 .pAttachments = &(VkAttachmentDescription) { 225 .format = format, 226 .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, 227 .storeOp = VK_ATTACHMENT_STORE_OP_STORE, 228 .initialLayout = layout, 229 .finalLayout = layout, 230 }, 231 .subpassCount = 1, 232 .pSubpasses = &(VkSubpassDescription) { 233 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, 234 .inputAttachmentCount = 0, 235 .colorAttachmentCount = 1, 236 .pColorAttachments = &(VkAttachmentReference) { 237 .attachment = 0, 238 .layout = layout, 239 }, 240 .pResolveAttachments = NULL, 241 .pDepthStencilAttachment = &(VkAttachmentReference) { 242 .attachment = VK_ATTACHMENT_UNUSED, 243 .layout = VK_IMAGE_LAYOUT_GENERAL, 244 }, 245 .preserveAttachmentCount = 1, 246 .pPreserveAttachments = (uint32_t[]) { 0 }, 247 }, 248 .dependencyCount = 0, 249 }, &device->meta_state.alloc, rp + dst_layout); 250 } 251 252 253 const VkGraphicsPipelineCreateInfo vk_pipeline_info = { 254 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 255 .stageCount = ARRAY_SIZE(pipeline_shader_stages), 256 .pStages = pipeline_shader_stages, 257 .pVertexInputState = vi_create_info, 258 .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) { 259 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 260 .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 261 .primitiveRestartEnable = false, 262 }, 263 .pViewportState = &(VkPipelineViewportStateCreateInfo) { 264 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 265 .viewportCount = 1, 266 .scissorCount = 1, 267 }, 268 .pRasterizationState = &(VkPipelineRasterizationStateCreateInfo) { 269 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 270 .rasterizerDiscardEnable = false, 271 .polygonMode = VK_POLYGON_MODE_FILL, 272 .cullMode = VK_CULL_MODE_NONE, 273 .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE 274 }, 275 .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) { 276 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 277 .rasterizationSamples = 1, 278 .sampleShadingEnable = false, 279 .pSampleMask = (VkSampleMask[]) { UINT32_MAX }, 280 }, 281 .pColorBlendState = &(VkPipelineColorBlendStateCreateInfo) { 282 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 283 .attachmentCount = 1, 284 .pAttachments = (VkPipelineColorBlendAttachmentState []) { 285 { .colorWriteMask = 286 VK_COLOR_COMPONENT_A_BIT | 287 VK_COLOR_COMPONENT_R_BIT | 288 VK_COLOR_COMPONENT_G_BIT | 289 VK_COLOR_COMPONENT_B_BIT }, 290 } 291 }, 292 .pDynamicState = &(VkPipelineDynamicStateCreateInfo) { 293 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, 294 .dynamicStateCount = 9, 295 .pDynamicStates = (VkDynamicState[]) { 296 VK_DYNAMIC_STATE_VIEWPORT, 297 VK_DYNAMIC_STATE_SCISSOR, 298 VK_DYNAMIC_STATE_LINE_WIDTH, 299 VK_DYNAMIC_STATE_DEPTH_BIAS, 300 VK_DYNAMIC_STATE_BLEND_CONSTANTS, 301 VK_DYNAMIC_STATE_DEPTH_BOUNDS, 302 VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, 303 VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, 304 VK_DYNAMIC_STATE_STENCIL_REFERENCE, 305 }, 306 }, 307 .flags = 0, 308 .layout = device->meta_state.resolve_fragment.p_layout, 309 .renderPass = *rp, 310 .subpass = 0, 311 }; 312 313 const struct radv_graphics_pipeline_create_info radv_pipeline_info = { 314 .use_rectlist = true 315 }; 316 317 result = radv_graphics_pipeline_create(radv_device_to_handle(device), 318 radv_pipeline_cache_to_handle(&device->meta_state.cache), 319 &vk_pipeline_info, &radv_pipeline_info, 320 &device->meta_state.alloc, 321 pipeline); 322 ralloc_free(vs.nir); 323 ralloc_free(fs.nir); 324 325 return result; 326 } 327 328 VkResult 329 radv_device_init_meta_resolve_fragment_state(struct radv_device *device) 330 { 331 VkResult res; 332 333 res = create_layout(device); 334 if (res != VK_SUCCESS) 335 goto fail; 336 337 for (uint32_t i = 0; i < MAX_SAMPLES_LOG2; ++i) { 338 for (unsigned j = 0; j < ARRAY_SIZE(pipeline_formats); ++j) { 339 res = create_resolve_pipeline(device, i, pipeline_formats[j]); 340 if (res != VK_SUCCESS) 341 goto fail; 342 } 343 } 344 345 return VK_SUCCESS; 346 fail: 347 radv_device_finish_meta_resolve_fragment_state(device); 348 return res; 349 } 350 351 void 352 radv_device_finish_meta_resolve_fragment_state(struct radv_device *device) 353 { 354 struct radv_meta_state *state = &device->meta_state; 355 for (uint32_t i = 0; i < MAX_SAMPLES_LOG2; ++i) { 356 for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) { 357 for(unsigned k =0; k < RADV_META_DST_LAYOUT_COUNT; ++k) { 358 radv_DestroyRenderPass(radv_device_to_handle(device), 359 state->resolve_fragment.rc[i].render_pass[j][k], 360 &state->alloc); 361 } 362 radv_DestroyPipeline(radv_device_to_handle(device), 363 state->resolve_fragment.rc[i].pipeline[j], 364 &state->alloc); 365 } 366 } 367 368 radv_DestroyDescriptorSetLayout(radv_device_to_handle(device), 369 state->resolve_fragment.ds_layout, 370 &state->alloc); 371 radv_DestroyPipelineLayout(radv_device_to_handle(device), 372 state->resolve_fragment.p_layout, 373 &state->alloc); 374 } 375 376 static void 377 emit_resolve(struct radv_cmd_buffer *cmd_buffer, 378 struct radv_image_view *src_iview, 379 struct radv_image_view *dest_iview, 380 const VkOffset2D *src_offset, 381 const VkOffset2D *dest_offset, 382 const VkExtent2D *resolve_extent) 383 { 384 struct radv_device *device = cmd_buffer->device; 385 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer); 386 const uint32_t samples = src_iview->image->info.samples; 387 const uint32_t samples_log2 = ffs(samples) - 1; 388 radv_meta_push_descriptor_set(cmd_buffer, 389 VK_PIPELINE_BIND_POINT_GRAPHICS, 390 cmd_buffer->device->meta_state.resolve_fragment.p_layout, 391 0, /* set */ 392 1, /* descriptorWriteCount */ 393 (VkWriteDescriptorSet[]) { 394 { 395 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 396 .dstBinding = 0, 397 .dstArrayElement = 0, 398 .descriptorCount = 1, 399 .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 400 .pImageInfo = (VkDescriptorImageInfo[]) { 401 { 402 .sampler = VK_NULL_HANDLE, 403 .imageView = radv_image_view_to_handle(src_iview), 404 .imageLayout = VK_IMAGE_LAYOUT_GENERAL, 405 }, 406 } 407 }, 408 }); 409 410 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB; 411 412 unsigned push_constants[2] = { 413 src_offset->x - dest_offset->x, 414 src_offset->y - dest_offset->y, 415 }; 416 radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer), 417 device->meta_state.resolve_fragment.p_layout, 418 VK_SHADER_STAGE_FRAGMENT_BIT, 0, 8, 419 push_constants); 420 421 unsigned fs_key = radv_format_meta_fs_key(dest_iview->vk_format); 422 VkPipeline pipeline_h = device->meta_state.resolve_fragment.rc[samples_log2].pipeline[fs_key]; 423 424 radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS, 425 pipeline_h); 426 427 radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkViewport) { 428 .x = dest_offset->x, 429 .y = dest_offset->y, 430 .width = resolve_extent->width, 431 .height = resolve_extent->height, 432 .minDepth = 0.0f, 433 .maxDepth = 1.0f 434 }); 435 436 radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkRect2D) { 437 .offset = *dest_offset, 438 .extent = *resolve_extent, 439 }); 440 441 radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0); 442 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB; 443 } 444 445 void radv_meta_resolve_fragment_image(struct radv_cmd_buffer *cmd_buffer, 446 struct radv_image *src_image, 447 VkImageLayout src_image_layout, 448 struct radv_image *dest_image, 449 VkImageLayout dest_image_layout, 450 uint32_t region_count, 451 const VkImageResolve *regions) 452 { 453 struct radv_device *device = cmd_buffer->device; 454 struct radv_meta_saved_state saved_state; 455 const uint32_t samples = src_image->info.samples; 456 const uint32_t samples_log2 = ffs(samples) - 1; 457 unsigned fs_key = radv_format_meta_fs_key(dest_image->vk_format); 458 unsigned dst_layout = radv_meta_dst_layout_from_layout(dest_image_layout); 459 VkRenderPass rp; 460 for (uint32_t r = 0; r < region_count; ++r) { 461 const VkImageResolve *region = ®ions[r]; 462 const uint32_t src_base_layer = 463 radv_meta_get_iview_layer(src_image, ®ion->srcSubresource, 464 ®ion->srcOffset); 465 VkImageSubresourceRange range; 466 range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 467 range.baseMipLevel = region->srcSubresource.mipLevel; 468 range.levelCount = 1; 469 range.baseArrayLayer = src_base_layer; 470 range.layerCount = region->srcSubresource.layerCount; 471 radv_fast_clear_flush_image_inplace(cmd_buffer, src_image, &range); 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 */ 587 void 588 radv_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 594 /* FINISHME(perf): Skip clears for resolve attachments. 595 * 596 * From the Vulkan 1.0 spec: 597 * 598 * If the first use of an attachment in a render pass is as a resolve 599 * attachment, then the loadOp is effectively ignored as the resolve is 600 * guaranteed to overwrite all pixels in the render area. 601 */ 602 603 if (!subpass->has_resolve) 604 return; 605 606 radv_meta_save(&saved_state, cmd_buffer, 607 RADV_META_SAVE_GRAPHICS_PIPELINE | 608 RADV_META_SAVE_CONSTANTS | 609 RADV_META_SAVE_DESCRIPTORS); 610 611 /* Resolves happen before the end-of-subpass barriers get executed, 612 * so we have to make the attachment shader-readable */ 613 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_PS_PARTIAL_FLUSH | 614 RADV_CMD_FLAG_FLUSH_AND_INV_CB | 615 RADV_CMD_FLAG_FLUSH_AND_INV_CB_META | 616 RADV_CMD_FLAG_FLUSH_AND_INV_DB | 617 RADV_CMD_FLAG_FLUSH_AND_INV_DB_META | 618 RADV_CMD_FLAG_INV_GLOBAL_L2 | 619 RADV_CMD_FLAG_INV_VMEM_L1; 620 621 for (uint32_t i = 0; i < subpass->color_count; ++i) { 622 VkAttachmentReference src_att = subpass->color_attachments[i]; 623 VkAttachmentReference dest_att = subpass->resolve_attachments[i]; 624 625 if (src_att.attachment == VK_ATTACHMENT_UNUSED || 626 dest_att.attachment == VK_ATTACHMENT_UNUSED) 627 continue; 628 629 struct radv_image_view *dest_iview = cmd_buffer->state.framebuffer->attachments[dest_att.attachment].attachment; 630 struct radv_image_view *src_iview = cmd_buffer->state.framebuffer->attachments[src_att.attachment].attachment; 631 632 { 633 VkImageSubresourceRange range; 634 range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 635 range.baseMipLevel = 0; 636 range.levelCount = 1; 637 range.baseArrayLayer = 0; 638 range.layerCount = 1; 639 radv_fast_clear_flush_image_inplace(cmd_buffer, src_iview->image, &range); 640 } 641 642 struct radv_subpass resolve_subpass = { 643 .color_count = 1, 644 .color_attachments = (VkAttachmentReference[]) { dest_att }, 645 .depth_stencil_attachment = { .attachment = VK_ATTACHMENT_UNUSED }, 646 }; 647 648 radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass, false); 649 650 emit_resolve(cmd_buffer, 651 src_iview, 652 dest_iview, 653 &(VkOffset2D) { 0, 0 }, 654 &(VkOffset2D) { 0, 0 }, 655 &(VkExtent2D) { fb->width, fb->height }); 656 } 657 658 cmd_buffer->state.subpass = subpass; 659 radv_meta_restore(&saved_state, cmd_buffer); 660 } 661