1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2016 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include <assert.h> 25bf215546Sopenharmony_ci#include <stdbool.h> 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "nir/nir_builder.h" 28bf215546Sopenharmony_ci#include "radv_meta.h" 29bf215546Sopenharmony_ci#include "radv_private.h" 30bf215546Sopenharmony_ci#include "sid.h" 31bf215546Sopenharmony_ci#include "vk_format.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci/* emit 0, 0, 0, 1 */ 34bf215546Sopenharmony_cistatic nir_shader * 35bf215546Sopenharmony_cibuild_nir_fs(struct radv_device *dev) 36bf215546Sopenharmony_ci{ 37bf215546Sopenharmony_ci const struct glsl_type *vec4 = glsl_vec4_type(); 38bf215546Sopenharmony_ci nir_variable *f_color; /* vec4, fragment output color */ 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_FRAGMENT, "meta_resolve_fs"); 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci f_color = nir_variable_create(b.shader, nir_var_shader_out, vec4, "f_color"); 43bf215546Sopenharmony_ci f_color->data.location = FRAG_RESULT_DATA0; 44bf215546Sopenharmony_ci nir_store_var(&b, f_color, nir_imm_vec4(&b, 0.0, 0.0, 0.0, 1.0), 0xf); 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci return b.shader; 47bf215546Sopenharmony_ci} 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_cistatic VkResult 50bf215546Sopenharmony_cicreate_pipeline(struct radv_device *device, VkShaderModule vs_module_h, VkFormat format, 51bf215546Sopenharmony_ci VkPipeline *pipeline) 52bf215546Sopenharmony_ci{ 53bf215546Sopenharmony_ci VkResult result; 54bf215546Sopenharmony_ci VkDevice device_h = radv_device_to_handle(device); 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci nir_shader *fs_module = build_nir_fs(device); 57bf215546Sopenharmony_ci if (!fs_module) { 58bf215546Sopenharmony_ci /* XXX: Need more accurate error */ 59bf215546Sopenharmony_ci result = VK_ERROR_OUT_OF_HOST_MEMORY; 60bf215546Sopenharmony_ci goto cleanup; 61bf215546Sopenharmony_ci } 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci VkPipelineLayoutCreateInfo pl_create_info = { 64bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 65bf215546Sopenharmony_ci .setLayoutCount = 0, 66bf215546Sopenharmony_ci .pSetLayouts = NULL, 67bf215546Sopenharmony_ci .pushConstantRangeCount = 0, 68bf215546Sopenharmony_ci .pPushConstantRanges = NULL, 69bf215546Sopenharmony_ci }; 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci if (!device->meta_state.resolve.p_layout) { 72bf215546Sopenharmony_ci result = 73bf215546Sopenharmony_ci radv_CreatePipelineLayout(radv_device_to_handle(device), &pl_create_info, 74bf215546Sopenharmony_ci &device->meta_state.alloc, &device->meta_state.resolve.p_layout); 75bf215546Sopenharmony_ci if (result != VK_SUCCESS) 76bf215546Sopenharmony_ci goto cleanup; 77bf215546Sopenharmony_ci } 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci VkFormat color_formats[2] = { format, format }; 80bf215546Sopenharmony_ci const VkPipelineRenderingCreateInfo rendering_create_info = { 81bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, 82bf215546Sopenharmony_ci .colorAttachmentCount = 2, 83bf215546Sopenharmony_ci .pColorAttachmentFormats = color_formats, 84bf215546Sopenharmony_ci }; 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci result = radv_graphics_pipeline_create( 87bf215546Sopenharmony_ci device_h, radv_pipeline_cache_to_handle(&device->meta_state.cache), 88bf215546Sopenharmony_ci &(VkGraphicsPipelineCreateInfo){ 89bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 90bf215546Sopenharmony_ci .pNext = &rendering_create_info, 91bf215546Sopenharmony_ci .stageCount = 2, 92bf215546Sopenharmony_ci .pStages = 93bf215546Sopenharmony_ci (VkPipelineShaderStageCreateInfo[]){ 94bf215546Sopenharmony_ci { 95bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 96bf215546Sopenharmony_ci .stage = VK_SHADER_STAGE_VERTEX_BIT, 97bf215546Sopenharmony_ci .module = vs_module_h, 98bf215546Sopenharmony_ci .pName = "main", 99bf215546Sopenharmony_ci }, 100bf215546Sopenharmony_ci { 101bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 102bf215546Sopenharmony_ci .stage = VK_SHADER_STAGE_FRAGMENT_BIT, 103bf215546Sopenharmony_ci .module = vk_shader_module_handle_from_nir(fs_module), 104bf215546Sopenharmony_ci .pName = "main", 105bf215546Sopenharmony_ci }, 106bf215546Sopenharmony_ci }, 107bf215546Sopenharmony_ci .pVertexInputState = 108bf215546Sopenharmony_ci &(VkPipelineVertexInputStateCreateInfo){ 109bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 110bf215546Sopenharmony_ci .vertexBindingDescriptionCount = 0, 111bf215546Sopenharmony_ci .vertexAttributeDescriptionCount = 0, 112bf215546Sopenharmony_ci }, 113bf215546Sopenharmony_ci .pInputAssemblyState = 114bf215546Sopenharmony_ci &(VkPipelineInputAssemblyStateCreateInfo){ 115bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 116bf215546Sopenharmony_ci .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 117bf215546Sopenharmony_ci .primitiveRestartEnable = false, 118bf215546Sopenharmony_ci }, 119bf215546Sopenharmony_ci .pViewportState = 120bf215546Sopenharmony_ci &(VkPipelineViewportStateCreateInfo){ 121bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 122bf215546Sopenharmony_ci .viewportCount = 1, 123bf215546Sopenharmony_ci .scissorCount = 1, 124bf215546Sopenharmony_ci }, 125bf215546Sopenharmony_ci .pRasterizationState = 126bf215546Sopenharmony_ci &(VkPipelineRasterizationStateCreateInfo){ 127bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 128bf215546Sopenharmony_ci .depthClampEnable = false, 129bf215546Sopenharmony_ci .rasterizerDiscardEnable = false, 130bf215546Sopenharmony_ci .polygonMode = VK_POLYGON_MODE_FILL, 131bf215546Sopenharmony_ci .cullMode = VK_CULL_MODE_NONE, 132bf215546Sopenharmony_ci .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, 133bf215546Sopenharmony_ci }, 134bf215546Sopenharmony_ci .pMultisampleState = 135bf215546Sopenharmony_ci &(VkPipelineMultisampleStateCreateInfo){ 136bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 137bf215546Sopenharmony_ci .rasterizationSamples = 1, 138bf215546Sopenharmony_ci .sampleShadingEnable = false, 139bf215546Sopenharmony_ci .pSampleMask = NULL, 140bf215546Sopenharmony_ci .alphaToCoverageEnable = false, 141bf215546Sopenharmony_ci .alphaToOneEnable = false, 142bf215546Sopenharmony_ci }, 143bf215546Sopenharmony_ci .pColorBlendState = 144bf215546Sopenharmony_ci &(VkPipelineColorBlendStateCreateInfo){ 145bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 146bf215546Sopenharmony_ci .logicOpEnable = false, 147bf215546Sopenharmony_ci .attachmentCount = 2, 148bf215546Sopenharmony_ci .pAttachments = 149bf215546Sopenharmony_ci (VkPipelineColorBlendAttachmentState[]){ 150bf215546Sopenharmony_ci { 151bf215546Sopenharmony_ci .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | 152bf215546Sopenharmony_ci VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, 153bf215546Sopenharmony_ci }, 154bf215546Sopenharmony_ci { 155bf215546Sopenharmony_ci .colorWriteMask = 0, 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci }}, 158bf215546Sopenharmony_ci }, 159bf215546Sopenharmony_ci .pDynamicState = 160bf215546Sopenharmony_ci &(VkPipelineDynamicStateCreateInfo){ 161bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, 162bf215546Sopenharmony_ci .dynamicStateCount = 2, 163bf215546Sopenharmony_ci .pDynamicStates = 164bf215546Sopenharmony_ci (VkDynamicState[]){ 165bf215546Sopenharmony_ci VK_DYNAMIC_STATE_VIEWPORT, 166bf215546Sopenharmony_ci VK_DYNAMIC_STATE_SCISSOR, 167bf215546Sopenharmony_ci }, 168bf215546Sopenharmony_ci }, 169bf215546Sopenharmony_ci .layout = device->meta_state.resolve.p_layout, 170bf215546Sopenharmony_ci .renderPass = VK_NULL_HANDLE, 171bf215546Sopenharmony_ci .subpass = 0, 172bf215546Sopenharmony_ci }, 173bf215546Sopenharmony_ci &(struct radv_graphics_pipeline_create_info){ 174bf215546Sopenharmony_ci .use_rectlist = true, 175bf215546Sopenharmony_ci .custom_blend_mode = V_028808_CB_RESOLVE, 176bf215546Sopenharmony_ci }, 177bf215546Sopenharmony_ci &device->meta_state.alloc, pipeline); 178bf215546Sopenharmony_ci if (result != VK_SUCCESS) 179bf215546Sopenharmony_ci goto cleanup; 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci goto cleanup; 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_cicleanup: 184bf215546Sopenharmony_ci ralloc_free(fs_module); 185bf215546Sopenharmony_ci return result; 186bf215546Sopenharmony_ci} 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_civoid 189bf215546Sopenharmony_ciradv_device_finish_meta_resolve_state(struct radv_device *device) 190bf215546Sopenharmony_ci{ 191bf215546Sopenharmony_ci struct radv_meta_state *state = &device->meta_state; 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci for (uint32_t j = 0; j < NUM_META_FS_KEYS; j++) { 194bf215546Sopenharmony_ci radv_DestroyPipeline(radv_device_to_handle(device), state->resolve.pipeline[j], 195bf215546Sopenharmony_ci &state->alloc); 196bf215546Sopenharmony_ci } 197bf215546Sopenharmony_ci radv_DestroyPipelineLayout(radv_device_to_handle(device), state->resolve.p_layout, 198bf215546Sopenharmony_ci &state->alloc); 199bf215546Sopenharmony_ci} 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ciVkResult 202bf215546Sopenharmony_ciradv_device_init_meta_resolve_state(struct radv_device *device, bool on_demand) 203bf215546Sopenharmony_ci{ 204bf215546Sopenharmony_ci if (on_demand) 205bf215546Sopenharmony_ci return VK_SUCCESS; 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci VkResult res = VK_SUCCESS; 208bf215546Sopenharmony_ci struct radv_meta_state *state = &device->meta_state; 209bf215546Sopenharmony_ci nir_shader *vs_module = radv_meta_build_nir_vs_generate_vertices(device); 210bf215546Sopenharmony_ci if (!vs_module) { 211bf215546Sopenharmony_ci /* XXX: Need more accurate error */ 212bf215546Sopenharmony_ci res = VK_ERROR_OUT_OF_HOST_MEMORY; 213bf215546Sopenharmony_ci goto cleanup; 214bf215546Sopenharmony_ci } 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci for (uint32_t i = 0; i < NUM_META_FS_KEYS; ++i) { 217bf215546Sopenharmony_ci VkFormat format = radv_fs_key_format_exemplars[i]; 218bf215546Sopenharmony_ci unsigned fs_key = radv_format_meta_fs_key(device, format); 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci VkShaderModule vs_module_h = vk_shader_module_handle_from_nir(vs_module); 221bf215546Sopenharmony_ci res = create_pipeline(device, vs_module_h, format, &state->resolve.pipeline[fs_key]); 222bf215546Sopenharmony_ci if (res != VK_SUCCESS) 223bf215546Sopenharmony_ci goto cleanup; 224bf215546Sopenharmony_ci } 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_cicleanup: 227bf215546Sopenharmony_ci ralloc_free(vs_module); 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci return res; 230bf215546Sopenharmony_ci} 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_cistatic void 233bf215546Sopenharmony_ciemit_resolve(struct radv_cmd_buffer *cmd_buffer, const struct radv_image *src_image, 234bf215546Sopenharmony_ci const struct radv_image *dst_image, VkFormat vk_format, const VkOffset2D *dest_offset, 235bf215546Sopenharmony_ci const VkExtent2D *resolve_extent) 236bf215546Sopenharmony_ci{ 237bf215546Sopenharmony_ci struct radv_device *device = cmd_buffer->device; 238bf215546Sopenharmony_ci VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer); 239bf215546Sopenharmony_ci unsigned fs_key = radv_format_meta_fs_key(device, vk_format); 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci cmd_buffer->state.flush_bits |= 242bf215546Sopenharmony_ci radv_src_access_flush(cmd_buffer, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, src_image) | 243bf215546Sopenharmony_ci radv_dst_access_flush(cmd_buffer, VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT, src_image) | 244bf215546Sopenharmony_ci radv_dst_access_flush(cmd_buffer, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, dst_image); 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS, 247bf215546Sopenharmony_ci device->meta_state.resolve.pipeline[fs_key]); 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, 250bf215546Sopenharmony_ci &(VkViewport){.x = dest_offset->x, 251bf215546Sopenharmony_ci .y = dest_offset->y, 252bf215546Sopenharmony_ci .width = resolve_extent->width, 253bf215546Sopenharmony_ci .height = resolve_extent->height, 254bf215546Sopenharmony_ci .minDepth = 0.0f, 255bf215546Sopenharmony_ci .maxDepth = 1.0f}); 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, 258bf215546Sopenharmony_ci &(VkRect2D){ 259bf215546Sopenharmony_ci .offset = *dest_offset, 260bf215546Sopenharmony_ci .extent = *resolve_extent, 261bf215546Sopenharmony_ci }); 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0); 264bf215546Sopenharmony_ci cmd_buffer->state.flush_bits |= 265bf215546Sopenharmony_ci radv_src_access_flush(cmd_buffer, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, dst_image); 266bf215546Sopenharmony_ci} 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_cienum radv_resolve_method { 269bf215546Sopenharmony_ci RESOLVE_HW, 270bf215546Sopenharmony_ci RESOLVE_COMPUTE, 271bf215546Sopenharmony_ci RESOLVE_FRAGMENT, 272bf215546Sopenharmony_ci}; 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_cistatic bool 275bf215546Sopenharmony_ciimage_hw_resolve_compat(const struct radv_device *device, struct radv_image *src_image, 276bf215546Sopenharmony_ci struct radv_image *dst_image) 277bf215546Sopenharmony_ci{ 278bf215546Sopenharmony_ci if (device->physical_device->rad_info.gfx_level >= GFX9) { 279bf215546Sopenharmony_ci return dst_image->planes[0].surface.u.gfx9.swizzle_mode == 280bf215546Sopenharmony_ci src_image->planes[0].surface.u.gfx9.swizzle_mode; 281bf215546Sopenharmony_ci } else { 282bf215546Sopenharmony_ci return dst_image->planes[0].surface.micro_tile_mode == 283bf215546Sopenharmony_ci src_image->planes[0].surface.micro_tile_mode; 284bf215546Sopenharmony_ci } 285bf215546Sopenharmony_ci} 286bf215546Sopenharmony_ci 287bf215546Sopenharmony_cistatic void 288bf215546Sopenharmony_ciradv_pick_resolve_method_images(struct radv_device *device, struct radv_image *src_image, 289bf215546Sopenharmony_ci VkFormat src_format, struct radv_image *dest_image, 290bf215546Sopenharmony_ci unsigned dest_level, VkImageLayout dest_image_layout, 291bf215546Sopenharmony_ci bool dest_render_loop, struct radv_cmd_buffer *cmd_buffer, 292bf215546Sopenharmony_ci enum radv_resolve_method *method) 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci{ 295bf215546Sopenharmony_ci uint32_t queue_mask = radv_image_queue_family_mask(dest_image, cmd_buffer->qf, 296bf215546Sopenharmony_ci cmd_buffer->qf); 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci if (vk_format_is_color(src_format)) { 299bf215546Sopenharmony_ci /* Using the fragment resolve path is currently a hint to 300bf215546Sopenharmony_ci * avoid decompressing DCC for partial resolves and 301bf215546Sopenharmony_ci * re-initialize it after resolving using compute. 302bf215546Sopenharmony_ci * TODO: Add support for layered and int to the fragment path. 303bf215546Sopenharmony_ci */ 304bf215546Sopenharmony_ci if (radv_layout_dcc_compressed(device, dest_image, dest_level, dest_image_layout, 305bf215546Sopenharmony_ci dest_render_loop, queue_mask)) { 306bf215546Sopenharmony_ci *method = RESOLVE_FRAGMENT; 307bf215546Sopenharmony_ci } else if (!image_hw_resolve_compat(device, src_image, dest_image)) { 308bf215546Sopenharmony_ci /* The micro tile mode only needs to match for the HW 309bf215546Sopenharmony_ci * resolve path which is the default path for non-DCC 310bf215546Sopenharmony_ci * resolves. 311bf215546Sopenharmony_ci */ 312bf215546Sopenharmony_ci *method = RESOLVE_COMPUTE; 313bf215546Sopenharmony_ci } 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci if (src_format == VK_FORMAT_R16G16_UNORM || src_format == VK_FORMAT_R16G16_SNORM) 316bf215546Sopenharmony_ci *method = RESOLVE_COMPUTE; 317bf215546Sopenharmony_ci else if (vk_format_is_int(src_format)) 318bf215546Sopenharmony_ci *method = RESOLVE_COMPUTE; 319bf215546Sopenharmony_ci else if (src_image->info.array_size > 1 || dest_image->info.array_size > 1) 320bf215546Sopenharmony_ci *method = RESOLVE_COMPUTE; 321bf215546Sopenharmony_ci } else { 322bf215546Sopenharmony_ci if (src_image->info.array_size > 1 || dest_image->info.array_size > 1) 323bf215546Sopenharmony_ci *method = RESOLVE_COMPUTE; 324bf215546Sopenharmony_ci else 325bf215546Sopenharmony_ci *method = RESOLVE_FRAGMENT; 326bf215546Sopenharmony_ci } 327bf215546Sopenharmony_ci} 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_cistatic VkResult 330bf215546Sopenharmony_cibuild_resolve_pipeline(struct radv_device *device, unsigned fs_key) 331bf215546Sopenharmony_ci{ 332bf215546Sopenharmony_ci VkResult result = VK_SUCCESS; 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci if (device->meta_state.resolve.pipeline[fs_key]) 335bf215546Sopenharmony_ci return result; 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci mtx_lock(&device->meta_state.mtx); 338bf215546Sopenharmony_ci if (device->meta_state.resolve.pipeline[fs_key]) { 339bf215546Sopenharmony_ci mtx_unlock(&device->meta_state.mtx); 340bf215546Sopenharmony_ci return result; 341bf215546Sopenharmony_ci } 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci nir_shader *vs_module = radv_meta_build_nir_vs_generate_vertices(device); 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci VkShaderModule vs_module_h = vk_shader_module_handle_from_nir(vs_module); 346bf215546Sopenharmony_ci result = create_pipeline(device, vs_module_h, radv_fs_key_format_exemplars[fs_key], 347bf215546Sopenharmony_ci &device->meta_state.resolve.pipeline[fs_key]); 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_ci ralloc_free(vs_module); 350bf215546Sopenharmony_ci mtx_unlock(&device->meta_state.mtx); 351bf215546Sopenharmony_ci return result; 352bf215546Sopenharmony_ci} 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_cistatic void 355bf215546Sopenharmony_ciradv_meta_resolve_hardware_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image, 356bf215546Sopenharmony_ci VkImageLayout src_image_layout, struct radv_image *dst_image, 357bf215546Sopenharmony_ci VkImageLayout dst_image_layout, const VkImageResolve2 *region) 358bf215546Sopenharmony_ci{ 359bf215546Sopenharmony_ci struct radv_device *device = cmd_buffer->device; 360bf215546Sopenharmony_ci struct radv_meta_saved_state saved_state; 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ci radv_meta_save(&saved_state, cmd_buffer, RADV_META_SAVE_GRAPHICS_PIPELINE); 363bf215546Sopenharmony_ci 364bf215546Sopenharmony_ci assert(src_image->info.samples > 1); 365bf215546Sopenharmony_ci assert(dst_image->info.samples == 1); 366bf215546Sopenharmony_ci 367bf215546Sopenharmony_ci unsigned fs_key = radv_format_meta_fs_key(device, dst_image->vk.format); 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_ci /* From the Vulkan 1.0 spec: 370bf215546Sopenharmony_ci * 371bf215546Sopenharmony_ci * - The aspectMask member of srcSubresource and dstSubresource must 372bf215546Sopenharmony_ci * only contain VK_IMAGE_ASPECT_COLOR_BIT 373bf215546Sopenharmony_ci * 374bf215546Sopenharmony_ci * - The layerCount member of srcSubresource and dstSubresource must 375bf215546Sopenharmony_ci * match 376bf215546Sopenharmony_ci */ 377bf215546Sopenharmony_ci assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); 378bf215546Sopenharmony_ci assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); 379bf215546Sopenharmony_ci assert(region->srcSubresource.layerCount == region->dstSubresource.layerCount); 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ci const uint32_t src_base_layer = 382bf215546Sopenharmony_ci radv_meta_get_iview_layer(src_image, ®ion->srcSubresource, ®ion->srcOffset); 383bf215546Sopenharmony_ci 384bf215546Sopenharmony_ci const uint32_t dst_base_layer = 385bf215546Sopenharmony_ci radv_meta_get_iview_layer(dst_image, ®ion->dstSubresource, ®ion->dstOffset); 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_ci /** 388bf215546Sopenharmony_ci * From Vulkan 1.0.6 spec: 18.6 Resolving Multisample Images 389bf215546Sopenharmony_ci * 390bf215546Sopenharmony_ci * extent is the size in texels of the source image to resolve in width, 391bf215546Sopenharmony_ci * height and depth. 1D images use only x and width. 2D images use x, y, 392bf215546Sopenharmony_ci * width and height. 3D images use x, y, z, width, height and depth. 393bf215546Sopenharmony_ci * 394bf215546Sopenharmony_ci * srcOffset and dstOffset select the initial x, y, and z offsets in 395bf215546Sopenharmony_ci * texels of the sub-regions of the source and destination image data. 396bf215546Sopenharmony_ci * extent is the size in texels of the source image to resolve in width, 397bf215546Sopenharmony_ci * height and depth. 1D images use only x and width. 2D images use x, y, 398bf215546Sopenharmony_ci * width and height. 3D images use x, y, z, width, height and depth. 399bf215546Sopenharmony_ci */ 400bf215546Sopenharmony_ci const struct VkExtent3D extent = vk_image_sanitize_extent(&src_image->vk, region->extent); 401bf215546Sopenharmony_ci const struct VkOffset3D dstOffset = vk_image_sanitize_offset(&dst_image->vk, region->dstOffset); 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ci uint32_t queue_mask = radv_image_queue_family_mask(dst_image, cmd_buffer->qf, 404bf215546Sopenharmony_ci cmd_buffer->qf); 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_ci if (radv_layout_dcc_compressed(cmd_buffer->device, dst_image, region->dstSubresource.mipLevel, 407bf215546Sopenharmony_ci dst_image_layout, false, queue_mask)) { 408bf215546Sopenharmony_ci VkImageSubresourceRange range = { 409bf215546Sopenharmony_ci .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 410bf215546Sopenharmony_ci .baseMipLevel = region->dstSubresource.mipLevel, 411bf215546Sopenharmony_ci .levelCount = 1, 412bf215546Sopenharmony_ci .baseArrayLayer = dst_base_layer, 413bf215546Sopenharmony_ci .layerCount = region->dstSubresource.layerCount, 414bf215546Sopenharmony_ci }; 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci cmd_buffer->state.flush_bits |= radv_init_dcc(cmd_buffer, dst_image, &range, 0xffffffff); 417bf215546Sopenharmony_ci } 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci for (uint32_t layer = 0; layer < region->srcSubresource.layerCount; ++layer) { 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_ci VkResult ret = build_resolve_pipeline(device, fs_key); 422bf215546Sopenharmony_ci if (ret != VK_SUCCESS) { 423bf215546Sopenharmony_ci cmd_buffer->record_result = ret; 424bf215546Sopenharmony_ci break; 425bf215546Sopenharmony_ci } 426bf215546Sopenharmony_ci 427bf215546Sopenharmony_ci struct radv_image_view src_iview; 428bf215546Sopenharmony_ci radv_image_view_init(&src_iview, cmd_buffer->device, 429bf215546Sopenharmony_ci &(VkImageViewCreateInfo){ 430bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 431bf215546Sopenharmony_ci .image = radv_image_to_handle(src_image), 432bf215546Sopenharmony_ci .viewType = radv_meta_get_view_type(src_image), 433bf215546Sopenharmony_ci .format = src_image->vk.format, 434bf215546Sopenharmony_ci .subresourceRange = 435bf215546Sopenharmony_ci { 436bf215546Sopenharmony_ci .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 437bf215546Sopenharmony_ci .baseMipLevel = region->srcSubresource.mipLevel, 438bf215546Sopenharmony_ci .levelCount = 1, 439bf215546Sopenharmony_ci .baseArrayLayer = src_base_layer + layer, 440bf215546Sopenharmony_ci .layerCount = 1, 441bf215546Sopenharmony_ci }, 442bf215546Sopenharmony_ci }, 443bf215546Sopenharmony_ci 0, NULL); 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci struct radv_image_view dst_iview; 446bf215546Sopenharmony_ci radv_image_view_init(&dst_iview, cmd_buffer->device, 447bf215546Sopenharmony_ci &(VkImageViewCreateInfo){ 448bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 449bf215546Sopenharmony_ci .image = radv_image_to_handle(dst_image), 450bf215546Sopenharmony_ci .viewType = radv_meta_get_view_type(dst_image), 451bf215546Sopenharmony_ci .format = dst_image->vk.format, 452bf215546Sopenharmony_ci .subresourceRange = 453bf215546Sopenharmony_ci { 454bf215546Sopenharmony_ci .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 455bf215546Sopenharmony_ci .baseMipLevel = region->dstSubresource.mipLevel, 456bf215546Sopenharmony_ci .levelCount = 1, 457bf215546Sopenharmony_ci .baseArrayLayer = dst_base_layer + layer, 458bf215546Sopenharmony_ci .layerCount = 1, 459bf215546Sopenharmony_ci }, 460bf215546Sopenharmony_ci }, 461bf215546Sopenharmony_ci 0, NULL); 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_ci const VkRenderingAttachmentInfo color_atts[2] = { 464bf215546Sopenharmony_ci { 465bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, 466bf215546Sopenharmony_ci .imageView = radv_image_view_to_handle(&src_iview), 467bf215546Sopenharmony_ci .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 468bf215546Sopenharmony_ci .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, 469bf215546Sopenharmony_ci .storeOp = VK_ATTACHMENT_STORE_OP_STORE, 470bf215546Sopenharmony_ci }, 471bf215546Sopenharmony_ci { 472bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, 473bf215546Sopenharmony_ci .imageView = radv_image_view_to_handle(&dst_iview), 474bf215546Sopenharmony_ci .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 475bf215546Sopenharmony_ci .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, 476bf215546Sopenharmony_ci .storeOp = VK_ATTACHMENT_STORE_OP_STORE, 477bf215546Sopenharmony_ci }, 478bf215546Sopenharmony_ci }; 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_ci const VkRenderingInfo rendering_info = { 481bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_RENDERING_INFO, 482bf215546Sopenharmony_ci .renderArea = { 483bf215546Sopenharmony_ci .offset = { dstOffset.x, dstOffset.y }, 484bf215546Sopenharmony_ci .extent = { extent.width, extent.height }, 485bf215546Sopenharmony_ci }, 486bf215546Sopenharmony_ci .layerCount = 1, 487bf215546Sopenharmony_ci .colorAttachmentCount = 2, 488bf215546Sopenharmony_ci .pColorAttachments = color_atts, 489bf215546Sopenharmony_ci }; 490bf215546Sopenharmony_ci 491bf215546Sopenharmony_ci radv_CmdBeginRendering(radv_cmd_buffer_to_handle(cmd_buffer), &rendering_info); 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci emit_resolve(cmd_buffer, src_image, dst_image, dst_iview.vk.format, 494bf215546Sopenharmony_ci &(VkOffset2D){ 495bf215546Sopenharmony_ci .x = dstOffset.x, 496bf215546Sopenharmony_ci .y = dstOffset.y, 497bf215546Sopenharmony_ci }, 498bf215546Sopenharmony_ci &(VkExtent2D){ 499bf215546Sopenharmony_ci .width = extent.width, 500bf215546Sopenharmony_ci .height = extent.height, 501bf215546Sopenharmony_ci }); 502bf215546Sopenharmony_ci 503bf215546Sopenharmony_ci radv_CmdEndRendering(radv_cmd_buffer_to_handle(cmd_buffer)); 504bf215546Sopenharmony_ci 505bf215546Sopenharmony_ci radv_image_view_finish(&src_iview); 506bf215546Sopenharmony_ci radv_image_view_finish(&dst_iview); 507bf215546Sopenharmony_ci } 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci radv_meta_restore(&saved_state, cmd_buffer); 510bf215546Sopenharmony_ci} 511bf215546Sopenharmony_ci 512bf215546Sopenharmony_cistatic void 513bf215546Sopenharmony_ciresolve_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image, 514bf215546Sopenharmony_ci VkImageLayout src_image_layout, struct radv_image *dst_image, 515bf215546Sopenharmony_ci VkImageLayout dst_image_layout, const VkImageResolve2 *region, 516bf215546Sopenharmony_ci enum radv_resolve_method resolve_method) 517bf215546Sopenharmony_ci{ 518bf215546Sopenharmony_ci switch (resolve_method) { 519bf215546Sopenharmony_ci case RESOLVE_HW: 520bf215546Sopenharmony_ci radv_meta_resolve_hardware_image(cmd_buffer, src_image, src_image_layout, dst_image, 521bf215546Sopenharmony_ci dst_image_layout, region); 522bf215546Sopenharmony_ci break; 523bf215546Sopenharmony_ci case RESOLVE_FRAGMENT: 524bf215546Sopenharmony_ci radv_meta_resolve_fragment_image(cmd_buffer, src_image, src_image_layout, dst_image, 525bf215546Sopenharmony_ci dst_image_layout, region); 526bf215546Sopenharmony_ci break; 527bf215546Sopenharmony_ci case RESOLVE_COMPUTE: 528bf215546Sopenharmony_ci radv_meta_resolve_compute_image(cmd_buffer, src_image, src_image->vk.format, src_image_layout, 529bf215546Sopenharmony_ci dst_image, dst_image->vk.format, dst_image_layout, region); 530bf215546Sopenharmony_ci break; 531bf215546Sopenharmony_ci default: 532bf215546Sopenharmony_ci assert(!"Invalid resolve method selected"); 533bf215546Sopenharmony_ci } 534bf215546Sopenharmony_ci} 535bf215546Sopenharmony_ci 536bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 537bf215546Sopenharmony_ciradv_CmdResolveImage2(VkCommandBuffer commandBuffer, 538bf215546Sopenharmony_ci const VkResolveImageInfo2 *pResolveImageInfo) 539bf215546Sopenharmony_ci{ 540bf215546Sopenharmony_ci RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); 541bf215546Sopenharmony_ci RADV_FROM_HANDLE(radv_image, src_image, pResolveImageInfo->srcImage); 542bf215546Sopenharmony_ci RADV_FROM_HANDLE(radv_image, dst_image, pResolveImageInfo->dstImage); 543bf215546Sopenharmony_ci VkImageLayout src_image_layout = pResolveImageInfo->srcImageLayout; 544bf215546Sopenharmony_ci VkImageLayout dst_image_layout = pResolveImageInfo->dstImageLayout; 545bf215546Sopenharmony_ci const struct radv_physical_device *pdevice = cmd_buffer->device->physical_device; 546bf215546Sopenharmony_ci enum radv_resolve_method resolve_method = 547bf215546Sopenharmony_ci pdevice->rad_info.gfx_level >= GFX11 ? RESOLVE_FRAGMENT : RESOLVE_HW; 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci /* we can use the hw resolve only for single full resolves */ 550bf215546Sopenharmony_ci if (pResolveImageInfo->regionCount == 1) { 551bf215546Sopenharmony_ci if (pResolveImageInfo->pRegions[0].srcOffset.x || 552bf215546Sopenharmony_ci pResolveImageInfo->pRegions[0].srcOffset.y || pResolveImageInfo->pRegions[0].srcOffset.z) 553bf215546Sopenharmony_ci resolve_method = RESOLVE_COMPUTE; 554bf215546Sopenharmony_ci if (pResolveImageInfo->pRegions[0].dstOffset.x || 555bf215546Sopenharmony_ci pResolveImageInfo->pRegions[0].dstOffset.y || pResolveImageInfo->pRegions[0].dstOffset.z) 556bf215546Sopenharmony_ci resolve_method = RESOLVE_COMPUTE; 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci if (pResolveImageInfo->pRegions[0].extent.width != src_image->info.width || 559bf215546Sopenharmony_ci pResolveImageInfo->pRegions[0].extent.height != src_image->info.height || 560bf215546Sopenharmony_ci pResolveImageInfo->pRegions[0].extent.depth != src_image->info.depth) 561bf215546Sopenharmony_ci resolve_method = RESOLVE_COMPUTE; 562bf215546Sopenharmony_ci } else 563bf215546Sopenharmony_ci resolve_method = RESOLVE_COMPUTE; 564bf215546Sopenharmony_ci 565bf215546Sopenharmony_ci for (uint32_t r = 0; r < pResolveImageInfo->regionCount; r++) { 566bf215546Sopenharmony_ci const VkImageResolve2 *region = &pResolveImageInfo->pRegions[r]; 567bf215546Sopenharmony_ci 568bf215546Sopenharmony_ci radv_pick_resolve_method_images(cmd_buffer->device, src_image, src_image->vk.format, dst_image, 569bf215546Sopenharmony_ci region->dstSubresource.mipLevel, dst_image_layout, false, 570bf215546Sopenharmony_ci cmd_buffer, &resolve_method); 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci resolve_image(cmd_buffer, src_image, src_image_layout, dst_image, dst_image_layout, region, 573bf215546Sopenharmony_ci resolve_method); 574bf215546Sopenharmony_ci } 575bf215546Sopenharmony_ci} 576bf215546Sopenharmony_ci 577bf215546Sopenharmony_cistatic void 578bf215546Sopenharmony_ciradv_cmd_buffer_resolve_subpass_hw(struct radv_cmd_buffer *cmd_buffer) 579bf215546Sopenharmony_ci{ 580bf215546Sopenharmony_ci struct vk_framebuffer *fb = cmd_buffer->state.framebuffer; 581bf215546Sopenharmony_ci const struct radv_subpass *subpass = cmd_buffer->state.subpass; 582bf215546Sopenharmony_ci struct radv_meta_saved_state saved_state; 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_ci radv_meta_save(&saved_state, cmd_buffer, RADV_META_SAVE_GRAPHICS_PIPELINE); 585bf215546Sopenharmony_ci 586bf215546Sopenharmony_ci for (uint32_t i = 0; i < subpass->color_count; ++i) { 587bf215546Sopenharmony_ci struct radv_subpass_attachment src_att = subpass->color_attachments[i]; 588bf215546Sopenharmony_ci struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i]; 589bf215546Sopenharmony_ci 590bf215546Sopenharmony_ci if (dest_att.attachment == VK_ATTACHMENT_UNUSED) 591bf215546Sopenharmony_ci continue; 592bf215546Sopenharmony_ci 593bf215546Sopenharmony_ci struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview; 594bf215546Sopenharmony_ci struct radv_image *src_img = src_iview->image; 595bf215546Sopenharmony_ci 596bf215546Sopenharmony_ci struct radv_image_view *dest_iview = cmd_buffer->state.attachments[dest_att.attachment].iview; 597bf215546Sopenharmony_ci struct radv_image *dst_img = dest_iview->image; 598bf215546Sopenharmony_ci VkImageLayout dst_image_layout = cmd_buffer->state.attachments[dest_att.attachment].current_layout; 599bf215546Sopenharmony_ci 600bf215546Sopenharmony_ci uint32_t queue_mask = radv_image_queue_family_mask(dst_img, cmd_buffer->qf, 601bf215546Sopenharmony_ci cmd_buffer->qf); 602bf215546Sopenharmony_ci 603bf215546Sopenharmony_ci if (radv_layout_dcc_compressed(cmd_buffer->device, dst_img, dest_iview->vk.base_mip_level, 604bf215546Sopenharmony_ci dst_image_layout, false, queue_mask)) { 605bf215546Sopenharmony_ci VkImageSubresourceRange range = { 606bf215546Sopenharmony_ci .aspectMask = dest_iview->vk.aspects, 607bf215546Sopenharmony_ci .baseMipLevel = dest_iview->vk.base_mip_level, 608bf215546Sopenharmony_ci .levelCount = dest_iview->vk.level_count, 609bf215546Sopenharmony_ci .baseArrayLayer = dest_iview->vk.base_array_layer, 610bf215546Sopenharmony_ci .layerCount = dest_iview->vk.layer_count, 611bf215546Sopenharmony_ci }; 612bf215546Sopenharmony_ci 613bf215546Sopenharmony_ci cmd_buffer->state.flush_bits |= radv_init_dcc(cmd_buffer, dst_img, &range, 0xffffffff); 614bf215546Sopenharmony_ci cmd_buffer->state.attachments[dest_att.attachment].current_layout = 615bf215546Sopenharmony_ci VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 616bf215546Sopenharmony_ci } 617bf215546Sopenharmony_ci 618bf215546Sopenharmony_ci struct radv_subpass resolve_subpass = { 619bf215546Sopenharmony_ci .color_count = 2, 620bf215546Sopenharmony_ci .color_attachments = (struct radv_subpass_attachment[]){src_att, dest_att}, 621bf215546Sopenharmony_ci .depth_stencil_attachment = NULL, 622bf215546Sopenharmony_ci }; 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_ci radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass); 625bf215546Sopenharmony_ci 626bf215546Sopenharmony_ci VkResult ret = build_resolve_pipeline( 627bf215546Sopenharmony_ci cmd_buffer->device, radv_format_meta_fs_key(cmd_buffer->device, dest_iview->vk.format)); 628bf215546Sopenharmony_ci if (ret != VK_SUCCESS) { 629bf215546Sopenharmony_ci cmd_buffer->record_result = ret; 630bf215546Sopenharmony_ci continue; 631bf215546Sopenharmony_ci } 632bf215546Sopenharmony_ci 633bf215546Sopenharmony_ci emit_resolve(cmd_buffer, src_img, dst_img, dest_iview->vk.format, &(VkOffset2D){0, 0}, 634bf215546Sopenharmony_ci &(VkExtent2D){fb->width, fb->height}); 635bf215546Sopenharmony_ci 636bf215546Sopenharmony_ci radv_cmd_buffer_restore_subpass(cmd_buffer, subpass); 637bf215546Sopenharmony_ci } 638bf215546Sopenharmony_ci 639bf215546Sopenharmony_ci radv_meta_restore(&saved_state, cmd_buffer); 640bf215546Sopenharmony_ci} 641bf215546Sopenharmony_ci 642bf215546Sopenharmony_ci/** 643bf215546Sopenharmony_ci * Emit any needed resolves for the current subpass. 644bf215546Sopenharmony_ci */ 645bf215546Sopenharmony_civoid 646bf215546Sopenharmony_ciradv_cmd_buffer_resolve_subpass(struct radv_cmd_buffer *cmd_buffer) 647bf215546Sopenharmony_ci{ 648bf215546Sopenharmony_ci const struct radv_physical_device *pdevice = cmd_buffer->device->physical_device; 649bf215546Sopenharmony_ci const struct radv_subpass *subpass = cmd_buffer->state.subpass; 650bf215546Sopenharmony_ci enum radv_resolve_method resolve_method = 651bf215546Sopenharmony_ci pdevice->rad_info.gfx_level >= GFX11 ? RESOLVE_FRAGMENT : RESOLVE_HW; 652bf215546Sopenharmony_ci 653bf215546Sopenharmony_ci if (!subpass->has_color_resolve && !subpass->ds_resolve_attachment) 654bf215546Sopenharmony_ci return; 655bf215546Sopenharmony_ci 656bf215546Sopenharmony_ci radv_describe_begin_render_pass_resolve(cmd_buffer); 657bf215546Sopenharmony_ci 658bf215546Sopenharmony_ci if (subpass->ds_resolve_attachment) { 659bf215546Sopenharmony_ci struct radv_subpass_attachment src_att = *subpass->depth_stencil_attachment; 660bf215546Sopenharmony_ci struct radv_subpass_attachment dst_att = *subpass->ds_resolve_attachment; 661bf215546Sopenharmony_ci struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview; 662bf215546Sopenharmony_ci struct radv_image_view *dst_iview = cmd_buffer->state.attachments[dst_att.attachment].iview; 663bf215546Sopenharmony_ci 664bf215546Sopenharmony_ci /* Make sure to not clear the depth/stencil attachment after resolves. */ 665bf215546Sopenharmony_ci cmd_buffer->state.attachments[dst_att.attachment].pending_clear_aspects = 0; 666bf215546Sopenharmony_ci 667bf215546Sopenharmony_ci radv_pick_resolve_method_images(cmd_buffer->device, src_iview->image, src_iview->vk.format, 668bf215546Sopenharmony_ci dst_iview->image, dst_iview->vk.base_mip_level, dst_att.layout, 669bf215546Sopenharmony_ci dst_att.in_render_loop, cmd_buffer, &resolve_method); 670bf215546Sopenharmony_ci 671bf215546Sopenharmony_ci if ((src_iview->vk.aspects & VK_IMAGE_ASPECT_DEPTH_BIT) && 672bf215546Sopenharmony_ci subpass->depth_resolve_mode != VK_RESOLVE_MODE_NONE) { 673bf215546Sopenharmony_ci if (resolve_method == RESOLVE_FRAGMENT) { 674bf215546Sopenharmony_ci radv_depth_stencil_resolve_subpass_fs(cmd_buffer, VK_IMAGE_ASPECT_DEPTH_BIT, 675bf215546Sopenharmony_ci subpass->depth_resolve_mode); 676bf215546Sopenharmony_ci } else { 677bf215546Sopenharmony_ci assert(resolve_method == RESOLVE_COMPUTE); 678bf215546Sopenharmony_ci radv_depth_stencil_resolve_subpass_cs(cmd_buffer, VK_IMAGE_ASPECT_DEPTH_BIT, 679bf215546Sopenharmony_ci subpass->depth_resolve_mode); 680bf215546Sopenharmony_ci } 681bf215546Sopenharmony_ci } 682bf215546Sopenharmony_ci 683bf215546Sopenharmony_ci if ((src_iview->vk.aspects & VK_IMAGE_ASPECT_STENCIL_BIT) && 684bf215546Sopenharmony_ci subpass->stencil_resolve_mode != VK_RESOLVE_MODE_NONE) { 685bf215546Sopenharmony_ci if (resolve_method == RESOLVE_FRAGMENT) { 686bf215546Sopenharmony_ci radv_depth_stencil_resolve_subpass_fs(cmd_buffer, VK_IMAGE_ASPECT_STENCIL_BIT, 687bf215546Sopenharmony_ci subpass->stencil_resolve_mode); 688bf215546Sopenharmony_ci } else { 689bf215546Sopenharmony_ci assert(resolve_method == RESOLVE_COMPUTE); 690bf215546Sopenharmony_ci radv_depth_stencil_resolve_subpass_cs(cmd_buffer, VK_IMAGE_ASPECT_STENCIL_BIT, 691bf215546Sopenharmony_ci subpass->stencil_resolve_mode); 692bf215546Sopenharmony_ci } 693bf215546Sopenharmony_ci } 694bf215546Sopenharmony_ci 695bf215546Sopenharmony_ci /* From the Vulkan spec 1.2.165: 696bf215546Sopenharmony_ci * 697bf215546Sopenharmony_ci * "VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT specifies 698bf215546Sopenharmony_ci * write access to a color, resolve, or depth/stencil 699bf215546Sopenharmony_ci * resolve attachment during a render pass or via 700bf215546Sopenharmony_ci * certain subpass load and store operations." 701bf215546Sopenharmony_ci * 702bf215546Sopenharmony_ci * Yes, it's counterintuitive but it makes sense because ds 703bf215546Sopenharmony_ci * resolve operations happen late at the end of the subpass. 704bf215546Sopenharmony_ci * 705bf215546Sopenharmony_ci * That said, RADV is wrong because it executes the subpass 706bf215546Sopenharmony_ci * end barrier *before* any subpass resolves instead of after. 707bf215546Sopenharmony_ci * 708bf215546Sopenharmony_ci * TODO: Fix this properly by executing subpass end barriers 709bf215546Sopenharmony_ci * after subpass resolves. 710bf215546Sopenharmony_ci */ 711bf215546Sopenharmony_ci cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_DB; 712bf215546Sopenharmony_ci if (radv_image_has_htile(dst_iview->image)) 713bf215546Sopenharmony_ci cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_DB_META; 714bf215546Sopenharmony_ci } 715bf215546Sopenharmony_ci 716bf215546Sopenharmony_ci if (subpass->has_color_resolve) { 717bf215546Sopenharmony_ci for (uint32_t i = 0; i < subpass->color_count; ++i) { 718bf215546Sopenharmony_ci struct radv_subpass_attachment src_att = subpass->color_attachments[i]; 719bf215546Sopenharmony_ci struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i]; 720bf215546Sopenharmony_ci 721bf215546Sopenharmony_ci if (dest_att.attachment == VK_ATTACHMENT_UNUSED) 722bf215546Sopenharmony_ci continue; 723bf215546Sopenharmony_ci 724bf215546Sopenharmony_ci /* Make sure to not clear color attachments after resolves. */ 725bf215546Sopenharmony_ci cmd_buffer->state.attachments[dest_att.attachment].pending_clear_aspects = 0; 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_ci struct radv_image_view *dst_iview = 728bf215546Sopenharmony_ci cmd_buffer->state.attachments[dest_att.attachment].iview; 729bf215546Sopenharmony_ci struct radv_image *dst_img = dst_iview->image; 730bf215546Sopenharmony_ci struct radv_image_view *src_iview = 731bf215546Sopenharmony_ci cmd_buffer->state.attachments[src_att.attachment].iview; 732bf215546Sopenharmony_ci struct radv_image *src_img = src_iview->image; 733bf215546Sopenharmony_ci 734bf215546Sopenharmony_ci radv_pick_resolve_method_images(cmd_buffer->device, src_img, src_iview->vk.format, dst_img, 735bf215546Sopenharmony_ci dst_iview->vk.base_mip_level, dest_att.layout, 736bf215546Sopenharmony_ci dest_att.in_render_loop, cmd_buffer, &resolve_method); 737bf215546Sopenharmony_ci 738bf215546Sopenharmony_ci if (resolve_method == RESOLVE_FRAGMENT) { 739bf215546Sopenharmony_ci break; 740bf215546Sopenharmony_ci } 741bf215546Sopenharmony_ci } 742bf215546Sopenharmony_ci 743bf215546Sopenharmony_ci switch (resolve_method) { 744bf215546Sopenharmony_ci case RESOLVE_HW: 745bf215546Sopenharmony_ci radv_cmd_buffer_resolve_subpass_hw(cmd_buffer); 746bf215546Sopenharmony_ci break; 747bf215546Sopenharmony_ci case RESOLVE_COMPUTE: 748bf215546Sopenharmony_ci radv_cmd_buffer_resolve_subpass_cs(cmd_buffer); 749bf215546Sopenharmony_ci break; 750bf215546Sopenharmony_ci case RESOLVE_FRAGMENT: 751bf215546Sopenharmony_ci radv_cmd_buffer_resolve_subpass_fs(cmd_buffer); 752bf215546Sopenharmony_ci break; 753bf215546Sopenharmony_ci default: 754bf215546Sopenharmony_ci unreachable("Invalid resolve method"); 755bf215546Sopenharmony_ci } 756bf215546Sopenharmony_ci } 757bf215546Sopenharmony_ci 758bf215546Sopenharmony_ci radv_describe_end_render_pass_resolve(cmd_buffer); 759bf215546Sopenharmony_ci} 760bf215546Sopenharmony_ci 761bf215546Sopenharmony_ci/** 762bf215546Sopenharmony_ci * Decompress CMask/FMask before resolving a multisampled source image inside a 763bf215546Sopenharmony_ci * subpass. 764bf215546Sopenharmony_ci */ 765bf215546Sopenharmony_civoid 766bf215546Sopenharmony_ciradv_decompress_resolve_subpass_src(struct radv_cmd_buffer *cmd_buffer) 767bf215546Sopenharmony_ci{ 768bf215546Sopenharmony_ci const struct radv_subpass *subpass = cmd_buffer->state.subpass; 769bf215546Sopenharmony_ci struct vk_framebuffer *fb = cmd_buffer->state.framebuffer; 770bf215546Sopenharmony_ci uint32_t layer_count = fb->layers; 771bf215546Sopenharmony_ci 772bf215546Sopenharmony_ci if (subpass->view_mask) 773bf215546Sopenharmony_ci layer_count = util_last_bit(subpass->view_mask); 774bf215546Sopenharmony_ci 775bf215546Sopenharmony_ci for (uint32_t i = 0; i < subpass->color_count; ++i) { 776bf215546Sopenharmony_ci struct radv_subpass_attachment src_att = subpass->color_attachments[i]; 777bf215546Sopenharmony_ci struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i]; 778bf215546Sopenharmony_ci 779bf215546Sopenharmony_ci if (dest_att.attachment == VK_ATTACHMENT_UNUSED) 780bf215546Sopenharmony_ci continue; 781bf215546Sopenharmony_ci 782bf215546Sopenharmony_ci struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview; 783bf215546Sopenharmony_ci struct radv_image *src_image = src_iview->image; 784bf215546Sopenharmony_ci 785bf215546Sopenharmony_ci VkImageResolve2 region = {0}; 786bf215546Sopenharmony_ci region.sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2; 787bf215546Sopenharmony_ci region.srcSubresource.aspectMask = src_iview->vk.aspects; 788bf215546Sopenharmony_ci region.srcSubresource.mipLevel = 0; 789bf215546Sopenharmony_ci region.srcSubresource.baseArrayLayer = src_iview->vk.base_array_layer; 790bf215546Sopenharmony_ci region.srcSubresource.layerCount = layer_count; 791bf215546Sopenharmony_ci 792bf215546Sopenharmony_ci radv_decompress_resolve_src(cmd_buffer, src_image, src_att.layout, ®ion); 793bf215546Sopenharmony_ci } 794bf215546Sopenharmony_ci} 795bf215546Sopenharmony_ci 796bf215546Sopenharmony_cistatic struct radv_sample_locations_state * 797bf215546Sopenharmony_ciradv_get_resolve_sample_locations(struct radv_cmd_buffer *cmd_buffer) 798bf215546Sopenharmony_ci{ 799bf215546Sopenharmony_ci struct radv_cmd_state *state = &cmd_buffer->state; 800bf215546Sopenharmony_ci uint32_t subpass_id = radv_get_subpass_id(cmd_buffer); 801bf215546Sopenharmony_ci 802bf215546Sopenharmony_ci for (uint32_t i = 0; i < state->num_subpass_sample_locs; i++) { 803bf215546Sopenharmony_ci if (state->subpass_sample_locs[i].subpass_idx == subpass_id) 804bf215546Sopenharmony_ci return &state->subpass_sample_locs[i].sample_location; 805bf215546Sopenharmony_ci } 806bf215546Sopenharmony_ci 807bf215546Sopenharmony_ci return NULL; 808bf215546Sopenharmony_ci} 809bf215546Sopenharmony_ci 810bf215546Sopenharmony_ci/** 811bf215546Sopenharmony_ci * Decompress CMask/FMask before resolving a multisampled source image. 812bf215546Sopenharmony_ci */ 813bf215546Sopenharmony_civoid 814bf215546Sopenharmony_ciradv_decompress_resolve_src(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image, 815bf215546Sopenharmony_ci VkImageLayout src_image_layout, const VkImageResolve2 *region) 816bf215546Sopenharmony_ci{ 817bf215546Sopenharmony_ci const uint32_t src_base_layer = 818bf215546Sopenharmony_ci radv_meta_get_iview_layer(src_image, ®ion->srcSubresource, ®ion->srcOffset); 819bf215546Sopenharmony_ci 820bf215546Sopenharmony_ci VkImageMemoryBarrier2 barrier = { 821bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, 822bf215546Sopenharmony_ci .srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, 823bf215546Sopenharmony_ci .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, 824bf215546Sopenharmony_ci .dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, 825bf215546Sopenharmony_ci .dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT, 826bf215546Sopenharmony_ci .oldLayout = src_image_layout, 827bf215546Sopenharmony_ci .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 828bf215546Sopenharmony_ci .image = radv_image_to_handle(src_image), 829bf215546Sopenharmony_ci .subresourceRange = (VkImageSubresourceRange){ 830bf215546Sopenharmony_ci .aspectMask = region->srcSubresource.aspectMask, 831bf215546Sopenharmony_ci .baseMipLevel = region->srcSubresource.mipLevel, 832bf215546Sopenharmony_ci .levelCount = 1, 833bf215546Sopenharmony_ci .baseArrayLayer = src_base_layer, 834bf215546Sopenharmony_ci .layerCount = region->srcSubresource.layerCount, 835bf215546Sopenharmony_ci } 836bf215546Sopenharmony_ci }; 837bf215546Sopenharmony_ci 838bf215546Sopenharmony_ci if (src_image->vk.create_flags & VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT) { 839bf215546Sopenharmony_ci /* If the depth/stencil image uses different sample 840bf215546Sopenharmony_ci * locations, we need them during HTILE decompressions. 841bf215546Sopenharmony_ci */ 842bf215546Sopenharmony_ci struct radv_sample_locations_state *sample_locs = 843bf215546Sopenharmony_ci radv_get_resolve_sample_locations(cmd_buffer); 844bf215546Sopenharmony_ci 845bf215546Sopenharmony_ci barrier.pNext = &(VkSampleLocationsInfoEXT){ 846bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT, 847bf215546Sopenharmony_ci .sampleLocationsPerPixel = sample_locs->per_pixel, 848bf215546Sopenharmony_ci .sampleLocationGridSize = sample_locs->grid_size, 849bf215546Sopenharmony_ci .sampleLocationsCount = sample_locs->count, 850bf215546Sopenharmony_ci .pSampleLocations = sample_locs->locations, 851bf215546Sopenharmony_ci }; 852bf215546Sopenharmony_ci } 853bf215546Sopenharmony_ci 854bf215546Sopenharmony_ci VkDependencyInfo dep_info = { 855bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, 856bf215546Sopenharmony_ci .imageMemoryBarrierCount = 1, 857bf215546Sopenharmony_ci .pImageMemoryBarriers = &barrier, 858bf215546Sopenharmony_ci }; 859bf215546Sopenharmony_ci 860bf215546Sopenharmony_ci radv_CmdPipelineBarrier2(radv_cmd_buffer_to_handle(cmd_buffer), &dep_info); 861bf215546Sopenharmony_ci} 862