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, ®ion->srcSubresource, ®ion->srcOffset); 809 810 const uint32_t dest_base_layer = 811 radv_meta_get_iview_layer(dest_image, ®ion->dstSubresource, ®ion->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, ®ion); 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