101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2016 Intel Corporation 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2101e04c3fSmrg * IN THE SOFTWARE. 2201e04c3fSmrg */ 2301e04c3fSmrg 2401e04c3fSmrg#include <assert.h> 2501e04c3fSmrg#include <stdbool.h> 2601e04c3fSmrg 277ec681f3Smrg#include "nir/nir_builder.h" 2801e04c3fSmrg#include "radv_meta.h" 2901e04c3fSmrg#include "radv_private.h" 3001e04c3fSmrg#include "sid.h" 317ec681f3Smrg#include "vk_format.h" 3201e04c3fSmrg 3301e04c3fSmrg/* emit 0, 0, 0, 1 */ 3401e04c3fSmrgstatic nir_shader * 3501e04c3fSmrgbuild_nir_fs(void) 3601e04c3fSmrg{ 377ec681f3Smrg const struct glsl_type *vec4 = glsl_vec4_type(); 387ec681f3Smrg nir_variable *f_color; /* vec4, fragment output color */ 3901e04c3fSmrg 407ec681f3Smrg nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, NULL, "meta_resolve_fs"); 4101e04c3fSmrg 427ec681f3Smrg f_color = nir_variable_create(b.shader, nir_var_shader_out, vec4, "f_color"); 437ec681f3Smrg f_color->data.location = FRAG_RESULT_DATA0; 447ec681f3Smrg nir_store_var(&b, f_color, nir_imm_vec4(&b, 0.0, 0.0, 0.0, 1.0), 0xf); 4501e04c3fSmrg 467ec681f3Smrg return b.shader; 4701e04c3fSmrg} 4801e04c3fSmrg 4901e04c3fSmrgstatic VkResult 5001e04c3fSmrgcreate_pass(struct radv_device *device, VkFormat vk_format, VkRenderPass *pass) 5101e04c3fSmrg{ 527ec681f3Smrg VkResult result; 537ec681f3Smrg VkDevice device_h = radv_device_to_handle(device); 547ec681f3Smrg const VkAllocationCallbacks *alloc = &device->meta_state.alloc; 557ec681f3Smrg VkAttachmentDescription2 attachments[2]; 567ec681f3Smrg int i; 577ec681f3Smrg 587ec681f3Smrg for (i = 0; i < 2; i++) { 597ec681f3Smrg attachments[i].sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2; 607ec681f3Smrg attachments[i].pNext = NULL; 617ec681f3Smrg attachments[i].format = vk_format; 627ec681f3Smrg attachments[i].samples = 1; 637ec681f3Smrg attachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 647ec681f3Smrg attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE; 657ec681f3Smrg } 667ec681f3Smrg attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 677ec681f3Smrg attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 687ec681f3Smrg attachments[1].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 697ec681f3Smrg attachments[1].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 707ec681f3Smrg 717ec681f3Smrg result = radv_CreateRenderPass2( 727ec681f3Smrg device_h, 737ec681f3Smrg &(VkRenderPassCreateInfo2){ 747ec681f3Smrg .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, 757ec681f3Smrg .attachmentCount = 2, 767ec681f3Smrg .pAttachments = attachments, 777ec681f3Smrg .subpassCount = 1, 787ec681f3Smrg .pSubpasses = 797ec681f3Smrg &(VkSubpassDescription2){ 807ec681f3Smrg .sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, 817ec681f3Smrg .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, 827ec681f3Smrg .inputAttachmentCount = 0, 837ec681f3Smrg .colorAttachmentCount = 2, 847ec681f3Smrg .pColorAttachments = 857ec681f3Smrg (VkAttachmentReference2[]){ 867ec681f3Smrg { 877ec681f3Smrg .sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, 887ec681f3Smrg .attachment = 0, 897ec681f3Smrg .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 907ec681f3Smrg }, 917ec681f3Smrg { 927ec681f3Smrg .sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, 937ec681f3Smrg .attachment = 1, 947ec681f3Smrg .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 957ec681f3Smrg }, 967ec681f3Smrg }, 977ec681f3Smrg .pResolveAttachments = NULL, 987ec681f3Smrg .pDepthStencilAttachment = 997ec681f3Smrg &(VkAttachmentReference2){ 1007ec681f3Smrg .sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, 1017ec681f3Smrg .attachment = VK_ATTACHMENT_UNUSED, 1027ec681f3Smrg }, 1037ec681f3Smrg .preserveAttachmentCount = 0, 1047ec681f3Smrg .pPreserveAttachments = NULL, 1057ec681f3Smrg }, 1067ec681f3Smrg .dependencyCount = 2, 1077ec681f3Smrg .pDependencies = 1087ec681f3Smrg (VkSubpassDependency2[]){{.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, 1097ec681f3Smrg .srcSubpass = VK_SUBPASS_EXTERNAL, 1107ec681f3Smrg .dstSubpass = 0, 1117ec681f3Smrg .srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 1127ec681f3Smrg .dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 1137ec681f3Smrg .srcAccessMask = 0, 1147ec681f3Smrg .dstAccessMask = 0, 1157ec681f3Smrg .dependencyFlags = 0}, 1167ec681f3Smrg {.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, 1177ec681f3Smrg .srcSubpass = 0, 1187ec681f3Smrg .dstSubpass = VK_SUBPASS_EXTERNAL, 1197ec681f3Smrg .srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 1207ec681f3Smrg .dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 1217ec681f3Smrg .srcAccessMask = 0, 1227ec681f3Smrg .dstAccessMask = 0, 1237ec681f3Smrg .dependencyFlags = 0}}, 1247ec681f3Smrg }, 1257ec681f3Smrg alloc, pass); 1267ec681f3Smrg 1277ec681f3Smrg return result; 12801e04c3fSmrg} 12901e04c3fSmrg 13001e04c3fSmrgstatic VkResult 1317ec681f3Smrgcreate_pipeline(struct radv_device *device, VkShaderModule vs_module_h, VkPipeline *pipeline, 1327ec681f3Smrg VkRenderPass pass) 13301e04c3fSmrg{ 1347ec681f3Smrg VkResult result; 1357ec681f3Smrg VkDevice device_h = radv_device_to_handle(device); 1367ec681f3Smrg 1377ec681f3Smrg nir_shader *fs_module = build_nir_fs(); 1387ec681f3Smrg if (!fs_module) { 1397ec681f3Smrg /* XXX: Need more accurate error */ 1407ec681f3Smrg result = VK_ERROR_OUT_OF_HOST_MEMORY; 1417ec681f3Smrg goto cleanup; 1427ec681f3Smrg } 1437ec681f3Smrg 1447ec681f3Smrg VkPipelineLayoutCreateInfo pl_create_info = { 1457ec681f3Smrg .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 1467ec681f3Smrg .setLayoutCount = 0, 1477ec681f3Smrg .pSetLayouts = NULL, 1487ec681f3Smrg .pushConstantRangeCount = 0, 1497ec681f3Smrg .pPushConstantRanges = NULL, 1507ec681f3Smrg }; 1517ec681f3Smrg 1527ec681f3Smrg if (!device->meta_state.resolve.p_layout) { 1537ec681f3Smrg result = 1547ec681f3Smrg radv_CreatePipelineLayout(radv_device_to_handle(device), &pl_create_info, 1557ec681f3Smrg &device->meta_state.alloc, &device->meta_state.resolve.p_layout); 1567ec681f3Smrg if (result != VK_SUCCESS) 1577ec681f3Smrg goto cleanup; 1587ec681f3Smrg } 1597ec681f3Smrg 1607ec681f3Smrg result = radv_graphics_pipeline_create( 1617ec681f3Smrg device_h, radv_pipeline_cache_to_handle(&device->meta_state.cache), 1627ec681f3Smrg &(VkGraphicsPipelineCreateInfo){ 1637ec681f3Smrg .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 1647ec681f3Smrg .stageCount = 2, 1657ec681f3Smrg .pStages = 1667ec681f3Smrg (VkPipelineShaderStageCreateInfo[]){ 1677ec681f3Smrg { 1687ec681f3Smrg .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 1697ec681f3Smrg .stage = VK_SHADER_STAGE_VERTEX_BIT, 1707ec681f3Smrg .module = vs_module_h, 1717ec681f3Smrg .pName = "main", 1727ec681f3Smrg }, 1737ec681f3Smrg { 1747ec681f3Smrg .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 1757ec681f3Smrg .stage = VK_SHADER_STAGE_FRAGMENT_BIT, 1767ec681f3Smrg .module = vk_shader_module_handle_from_nir(fs_module), 1777ec681f3Smrg .pName = "main", 1787ec681f3Smrg }, 1797ec681f3Smrg }, 1807ec681f3Smrg .pVertexInputState = 1817ec681f3Smrg &(VkPipelineVertexInputStateCreateInfo){ 1827ec681f3Smrg .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 1837ec681f3Smrg .vertexBindingDescriptionCount = 0, 1847ec681f3Smrg .vertexAttributeDescriptionCount = 0, 1857ec681f3Smrg }, 1867ec681f3Smrg .pInputAssemblyState = 1877ec681f3Smrg &(VkPipelineInputAssemblyStateCreateInfo){ 1887ec681f3Smrg .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 1897ec681f3Smrg .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 1907ec681f3Smrg .primitiveRestartEnable = false, 1917ec681f3Smrg }, 1927ec681f3Smrg .pViewportState = 1937ec681f3Smrg &(VkPipelineViewportStateCreateInfo){ 1947ec681f3Smrg .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 1957ec681f3Smrg .viewportCount = 1, 1967ec681f3Smrg .scissorCount = 1, 1977ec681f3Smrg }, 1987ec681f3Smrg .pRasterizationState = 1997ec681f3Smrg &(VkPipelineRasterizationStateCreateInfo){ 2007ec681f3Smrg .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 2017ec681f3Smrg .depthClampEnable = false, 2027ec681f3Smrg .rasterizerDiscardEnable = false, 2037ec681f3Smrg .polygonMode = VK_POLYGON_MODE_FILL, 2047ec681f3Smrg .cullMode = VK_CULL_MODE_NONE, 2057ec681f3Smrg .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, 2067ec681f3Smrg }, 2077ec681f3Smrg .pMultisampleState = 2087ec681f3Smrg &(VkPipelineMultisampleStateCreateInfo){ 2097ec681f3Smrg .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 2107ec681f3Smrg .rasterizationSamples = 1, 2117ec681f3Smrg .sampleShadingEnable = false, 2127ec681f3Smrg .pSampleMask = NULL, 2137ec681f3Smrg .alphaToCoverageEnable = false, 2147ec681f3Smrg .alphaToOneEnable = false, 2157ec681f3Smrg }, 2167ec681f3Smrg .pColorBlendState = 2177ec681f3Smrg &(VkPipelineColorBlendStateCreateInfo){ 2187ec681f3Smrg .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 2197ec681f3Smrg .logicOpEnable = false, 2207ec681f3Smrg .attachmentCount = 2, 2217ec681f3Smrg .pAttachments = 2227ec681f3Smrg (VkPipelineColorBlendAttachmentState[]){ 2237ec681f3Smrg { 2247ec681f3Smrg .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | 2257ec681f3Smrg VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, 2267ec681f3Smrg }, 2277ec681f3Smrg { 2287ec681f3Smrg .colorWriteMask = 0, 2297ec681f3Smrg 2307ec681f3Smrg }}, 2317ec681f3Smrg }, 2327ec681f3Smrg .pDynamicState = 2337ec681f3Smrg &(VkPipelineDynamicStateCreateInfo){ 2347ec681f3Smrg .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, 2357ec681f3Smrg .dynamicStateCount = 2, 2367ec681f3Smrg .pDynamicStates = 2377ec681f3Smrg (VkDynamicState[]){ 2387ec681f3Smrg VK_DYNAMIC_STATE_VIEWPORT, 2397ec681f3Smrg VK_DYNAMIC_STATE_SCISSOR, 2407ec681f3Smrg }, 2417ec681f3Smrg }, 2427ec681f3Smrg .layout = device->meta_state.resolve.p_layout, 2437ec681f3Smrg .renderPass = pass, 2447ec681f3Smrg .subpass = 0, 2457ec681f3Smrg }, 2467ec681f3Smrg &(struct radv_graphics_pipeline_create_info){ 2477ec681f3Smrg .use_rectlist = true, 2487ec681f3Smrg .custom_blend_mode = V_028808_CB_RESOLVE, 2497ec681f3Smrg }, 2507ec681f3Smrg &device->meta_state.alloc, pipeline); 2517ec681f3Smrg if (result != VK_SUCCESS) 2527ec681f3Smrg goto cleanup; 2537ec681f3Smrg 2547ec681f3Smrg goto cleanup; 25501e04c3fSmrg 25601e04c3fSmrgcleanup: 2577ec681f3Smrg ralloc_free(fs_module); 2587ec681f3Smrg return result; 25901e04c3fSmrg} 26001e04c3fSmrg 26101e04c3fSmrgvoid 26201e04c3fSmrgradv_device_finish_meta_resolve_state(struct radv_device *device) 26301e04c3fSmrg{ 2647ec681f3Smrg struct radv_meta_state *state = &device->meta_state; 2657ec681f3Smrg 2667ec681f3Smrg for (uint32_t j = 0; j < NUM_META_FS_KEYS; j++) { 2677ec681f3Smrg radv_DestroyRenderPass(radv_device_to_handle(device), state->resolve.pass[j], &state->alloc); 2687ec681f3Smrg radv_DestroyPipeline(radv_device_to_handle(device), state->resolve.pipeline[j], 2697ec681f3Smrg &state->alloc); 2707ec681f3Smrg } 2717ec681f3Smrg radv_DestroyPipelineLayout(radv_device_to_handle(device), state->resolve.p_layout, 2727ec681f3Smrg &state->alloc); 27301e04c3fSmrg} 27401e04c3fSmrg 27501e04c3fSmrgVkResult 27601e04c3fSmrgradv_device_init_meta_resolve_state(struct radv_device *device, bool on_demand) 27701e04c3fSmrg{ 2787ec681f3Smrg if (on_demand) 2797ec681f3Smrg return VK_SUCCESS; 2807ec681f3Smrg 2817ec681f3Smrg VkResult res = VK_SUCCESS; 2827ec681f3Smrg struct radv_meta_state *state = &device->meta_state; 2837ec681f3Smrg nir_shader *vs_module = radv_meta_build_nir_vs_generate_vertices(); 2847ec681f3Smrg if (!vs_module) { 2857ec681f3Smrg /* XXX: Need more accurate error */ 2867ec681f3Smrg res = VK_ERROR_OUT_OF_HOST_MEMORY; 2877ec681f3Smrg goto fail; 2887ec681f3Smrg } 2897ec681f3Smrg 2907ec681f3Smrg for (uint32_t i = 0; i < NUM_META_FS_KEYS; ++i) { 2917ec681f3Smrg VkFormat format = radv_fs_key_format_exemplars[i]; 2927ec681f3Smrg unsigned fs_key = radv_format_meta_fs_key(device, format); 2937ec681f3Smrg res = create_pass(device, format, &state->resolve.pass[fs_key]); 2947ec681f3Smrg if (res != VK_SUCCESS) 2957ec681f3Smrg goto fail; 2967ec681f3Smrg 2977ec681f3Smrg VkShaderModule vs_module_h = vk_shader_module_handle_from_nir(vs_module); 2987ec681f3Smrg res = create_pipeline(device, vs_module_h, &state->resolve.pipeline[fs_key], 2997ec681f3Smrg state->resolve.pass[fs_key]); 3007ec681f3Smrg if (res != VK_SUCCESS) 3017ec681f3Smrg goto fail; 3027ec681f3Smrg } 3037ec681f3Smrg 3047ec681f3Smrg goto cleanup; 30501e04c3fSmrg 30601e04c3fSmrgfail: 3077ec681f3Smrg radv_device_finish_meta_resolve_state(device); 30801e04c3fSmrg 30901e04c3fSmrgcleanup: 3107ec681f3Smrg ralloc_free(vs_module); 31101e04c3fSmrg 3127ec681f3Smrg return res; 31301e04c3fSmrg} 31401e04c3fSmrg 31501e04c3fSmrgstatic void 3167ec681f3Smrgemit_resolve(struct radv_cmd_buffer *cmd_buffer, const struct radv_image *src_image, 3177ec681f3Smrg const struct radv_image *dst_image, VkFormat vk_format, const VkOffset2D *dest_offset, 31801e04c3fSmrg const VkExtent2D *resolve_extent) 31901e04c3fSmrg{ 3207ec681f3Smrg struct radv_device *device = cmd_buffer->device; 3217ec681f3Smrg VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer); 3227ec681f3Smrg unsigned fs_key = radv_format_meta_fs_key(device, vk_format); 3237ec681f3Smrg 3247ec681f3Smrg cmd_buffer->state.flush_bits |= 3257ec681f3Smrg radv_src_access_flush(cmd_buffer, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, src_image) | 3267ec681f3Smrg radv_dst_access_flush(cmd_buffer, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, src_image) | 3277ec681f3Smrg radv_dst_access_flush(cmd_buffer, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, dst_image); 3287ec681f3Smrg 3297ec681f3Smrg radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS, 3307ec681f3Smrg device->meta_state.resolve.pipeline[fs_key]); 3317ec681f3Smrg 3327ec681f3Smrg radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, 3337ec681f3Smrg &(VkViewport){.x = dest_offset->x, 3347ec681f3Smrg .y = dest_offset->y, 3357ec681f3Smrg .width = resolve_extent->width, 3367ec681f3Smrg .height = resolve_extent->height, 3377ec681f3Smrg .minDepth = 0.0f, 3387ec681f3Smrg .maxDepth = 1.0f}); 3397ec681f3Smrg 3407ec681f3Smrg radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, 3417ec681f3Smrg &(VkRect2D){ 3427ec681f3Smrg .offset = *dest_offset, 3437ec681f3Smrg .extent = *resolve_extent, 3447ec681f3Smrg }); 3457ec681f3Smrg 3467ec681f3Smrg radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0); 3477ec681f3Smrg cmd_buffer->state.flush_bits |= 3487ec681f3Smrg radv_src_access_flush(cmd_buffer, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, dst_image); 34901e04c3fSmrg} 35001e04c3fSmrg 35101e04c3fSmrgenum radv_resolve_method { 3527ec681f3Smrg RESOLVE_HW, 3537ec681f3Smrg RESOLVE_COMPUTE, 3547ec681f3Smrg RESOLVE_FRAGMENT, 35501e04c3fSmrg}; 35601e04c3fSmrg 3577ec681f3Smrgstatic bool 3587ec681f3Smrgimage_hw_resolve_compat(const struct radv_device *device, struct radv_image *src_image, 3597ec681f3Smrg struct radv_image *dst_image) 3607ec681f3Smrg{ 3617ec681f3Smrg if (device->physical_device->rad_info.chip_class >= GFX9) { 3627ec681f3Smrg return dst_image->planes[0].surface.u.gfx9.swizzle_mode == 3637ec681f3Smrg src_image->planes[0].surface.u.gfx9.swizzle_mode; 3647ec681f3Smrg } else { 3657ec681f3Smrg return dst_image->planes[0].surface.micro_tile_mode == 3667ec681f3Smrg src_image->planes[0].surface.micro_tile_mode; 3677ec681f3Smrg } 3687ec681f3Smrg} 3697ec681f3Smrg 3707ec681f3Smrgstatic void 3717ec681f3Smrgradv_pick_resolve_method_images(struct radv_device *device, struct radv_image *src_image, 3727ec681f3Smrg VkFormat src_format, struct radv_image *dest_image, 3737ec681f3Smrg unsigned dest_level, VkImageLayout dest_image_layout, 3747ec681f3Smrg bool dest_render_loop, struct radv_cmd_buffer *cmd_buffer, 3757ec681f3Smrg enum radv_resolve_method *method) 37601e04c3fSmrg 37701e04c3fSmrg{ 3787ec681f3Smrg uint32_t queue_mask = radv_image_queue_family_mask(dest_image, cmd_buffer->queue_family_index, 3797ec681f3Smrg cmd_buffer->queue_family_index); 3807ec681f3Smrg 3817ec681f3Smrg if (vk_format_is_color(src_format)) { 3827ec681f3Smrg /* Using the fragment resolve path is currently a hint to 3837ec681f3Smrg * avoid decompressing DCC for partial resolves and 3847ec681f3Smrg * re-initialize it after resolving using compute. 3857ec681f3Smrg * TODO: Add support for layered and int to the fragment path. 3867ec681f3Smrg */ 3877ec681f3Smrg if (radv_layout_dcc_compressed(device, dest_image, dest_level, dest_image_layout, 3887ec681f3Smrg dest_render_loop, queue_mask)) { 3897ec681f3Smrg *method = RESOLVE_FRAGMENT; 3907ec681f3Smrg } else if (!image_hw_resolve_compat(device, src_image, dest_image)) { 3917ec681f3Smrg /* The micro tile mode only needs to match for the HW 3927ec681f3Smrg * resolve path which is the default path for non-DCC 3937ec681f3Smrg * resolves. 3947ec681f3Smrg */ 3957ec681f3Smrg *method = RESOLVE_COMPUTE; 3967ec681f3Smrg } 3977ec681f3Smrg 3987ec681f3Smrg if (src_format == VK_FORMAT_R16G16_UNORM || src_format == VK_FORMAT_R16G16_SNORM) 3997ec681f3Smrg *method = RESOLVE_COMPUTE; 4007ec681f3Smrg else if (vk_format_is_int(src_format)) 4017ec681f3Smrg *method = RESOLVE_COMPUTE; 4027ec681f3Smrg else if (src_image->info.array_size > 1 || dest_image->info.array_size > 1) 4037ec681f3Smrg *method = RESOLVE_COMPUTE; 4047ec681f3Smrg } else { 4057ec681f3Smrg if (src_image->info.array_size > 1 || dest_image->info.array_size > 1) 4067ec681f3Smrg *method = RESOLVE_COMPUTE; 4077ec681f3Smrg else 4087ec681f3Smrg *method = RESOLVE_FRAGMENT; 4097ec681f3Smrg } 41001e04c3fSmrg} 41101e04c3fSmrg 41201e04c3fSmrgstatic VkResult 4137ec681f3Smrgbuild_resolve_pipeline(struct radv_device *device, unsigned fs_key) 41401e04c3fSmrg{ 4157ec681f3Smrg VkResult result = VK_SUCCESS; 41601e04c3fSmrg 4177ec681f3Smrg if (device->meta_state.resolve.pipeline[fs_key]) 4187ec681f3Smrg return result; 41901e04c3fSmrg 4207ec681f3Smrg mtx_lock(&device->meta_state.mtx); 4217ec681f3Smrg if (device->meta_state.resolve.pipeline[fs_key]) { 4227ec681f3Smrg mtx_unlock(&device->meta_state.mtx); 4237ec681f3Smrg return result; 4247ec681f3Smrg } 42501e04c3fSmrg 4267ec681f3Smrg nir_shader *vs_module = radv_meta_build_nir_vs_generate_vertices(); 42701e04c3fSmrg 4287ec681f3Smrg result = create_pass(device, radv_fs_key_format_exemplars[fs_key], 4297ec681f3Smrg &device->meta_state.resolve.pass[fs_key]); 4307ec681f3Smrg if (result != VK_SUCCESS) 4317ec681f3Smrg goto fail; 43201e04c3fSmrg 4337ec681f3Smrg VkShaderModule vs_module_h = vk_shader_module_handle_from_nir(vs_module); 4347ec681f3Smrg result = create_pipeline(device, vs_module_h, &device->meta_state.resolve.pipeline[fs_key], 4357ec681f3Smrg device->meta_state.resolve.pass[fs_key]); 43601e04c3fSmrg 43701e04c3fSmrgfail: 4387ec681f3Smrg ralloc_free(vs_module); 4397ec681f3Smrg mtx_unlock(&device->meta_state.mtx); 4407ec681f3Smrg return result; 44101e04c3fSmrg} 44201e04c3fSmrg 4437ec681f3Smrgstatic void 4447ec681f3Smrgradv_meta_resolve_hardware_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image, 4457ec681f3Smrg VkImageLayout src_image_layout, struct radv_image *dst_image, 4467ec681f3Smrg VkImageLayout dst_image_layout, const VkImageResolve2KHR *region) 4477ec681f3Smrg{ 4487ec681f3Smrg struct radv_device *device = cmd_buffer->device; 4497ec681f3Smrg struct radv_meta_saved_state saved_state; 4507ec681f3Smrg 4517ec681f3Smrg radv_meta_save(&saved_state, cmd_buffer, RADV_META_SAVE_GRAPHICS_PIPELINE); 4527ec681f3Smrg 4537ec681f3Smrg assert(src_image->info.samples > 1); 4547ec681f3Smrg assert(dst_image->info.samples == 1); 4557ec681f3Smrg 4567ec681f3Smrg unsigned fs_key = radv_format_meta_fs_key(device, dst_image->vk_format); 4577ec681f3Smrg 4587ec681f3Smrg /* From the Vulkan 1.0 spec: 4597ec681f3Smrg * 4607ec681f3Smrg * - The aspectMask member of srcSubresource and dstSubresource must 4617ec681f3Smrg * only contain VK_IMAGE_ASPECT_COLOR_BIT 4627ec681f3Smrg * 4637ec681f3Smrg * - The layerCount member of srcSubresource and dstSubresource must 4647ec681f3Smrg * match 4657ec681f3Smrg */ 4667ec681f3Smrg assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); 4677ec681f3Smrg assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); 4687ec681f3Smrg assert(region->srcSubresource.layerCount == region->dstSubresource.layerCount); 4697ec681f3Smrg 4707ec681f3Smrg const uint32_t src_base_layer = 4717ec681f3Smrg radv_meta_get_iview_layer(src_image, ®ion->srcSubresource, ®ion->srcOffset); 4727ec681f3Smrg 4737ec681f3Smrg const uint32_t dst_base_layer = 4747ec681f3Smrg radv_meta_get_iview_layer(dst_image, ®ion->dstSubresource, ®ion->dstOffset); 4757ec681f3Smrg 4767ec681f3Smrg /** 4777ec681f3Smrg * From Vulkan 1.0.6 spec: 18.6 Resolving Multisample Images 4787ec681f3Smrg * 4797ec681f3Smrg * extent is the size in texels of the source image to resolve in width, 4807ec681f3Smrg * height and depth. 1D images use only x and width. 2D images use x, y, 4817ec681f3Smrg * width and height. 3D images use x, y, z, width, height and depth. 4827ec681f3Smrg * 4837ec681f3Smrg * srcOffset and dstOffset select the initial x, y, and z offsets in 4847ec681f3Smrg * texels of the sub-regions of the source and destination image data. 4857ec681f3Smrg * extent is the size in texels of the source image to resolve in width, 4867ec681f3Smrg * height and depth. 1D images use only x and width. 2D images use x, y, 4877ec681f3Smrg * width and height. 3D images use x, y, z, width, height and depth. 4887ec681f3Smrg */ 4897ec681f3Smrg const struct VkExtent3D extent = radv_sanitize_image_extent(src_image->type, region->extent); 4907ec681f3Smrg const struct VkOffset3D dstOffset = 4917ec681f3Smrg radv_sanitize_image_offset(dst_image->type, region->dstOffset); 4927ec681f3Smrg 4937ec681f3Smrg uint32_t queue_mask = radv_image_queue_family_mask(dst_image, cmd_buffer->queue_family_index, 4947ec681f3Smrg cmd_buffer->queue_family_index); 4957ec681f3Smrg 4967ec681f3Smrg if (radv_layout_dcc_compressed(cmd_buffer->device, dst_image, region->dstSubresource.mipLevel, 4977ec681f3Smrg dst_image_layout, false, queue_mask)) { 4987ec681f3Smrg VkImageSubresourceRange range = { 4997ec681f3Smrg .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 5007ec681f3Smrg .baseMipLevel = region->dstSubresource.mipLevel, 5017ec681f3Smrg .levelCount = 1, 5027ec681f3Smrg .baseArrayLayer = dst_base_layer, 5037ec681f3Smrg .layerCount = region->dstSubresource.layerCount, 5047ec681f3Smrg }; 5057ec681f3Smrg 5067ec681f3Smrg cmd_buffer->state.flush_bits |= radv_init_dcc(cmd_buffer, dst_image, &range, 0xffffffff); 5077ec681f3Smrg } 5087ec681f3Smrg 5097ec681f3Smrg for (uint32_t layer = 0; layer < region->srcSubresource.layerCount; ++layer) { 5107ec681f3Smrg 5117ec681f3Smrg VkResult ret = build_resolve_pipeline(device, fs_key); 5127ec681f3Smrg if (ret != VK_SUCCESS) { 5137ec681f3Smrg cmd_buffer->record_result = ret; 5147ec681f3Smrg break; 5157ec681f3Smrg } 5167ec681f3Smrg 5177ec681f3Smrg struct radv_image_view src_iview; 5187ec681f3Smrg radv_image_view_init(&src_iview, cmd_buffer->device, 5197ec681f3Smrg &(VkImageViewCreateInfo){ 5207ec681f3Smrg .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 5217ec681f3Smrg .image = radv_image_to_handle(src_image), 5227ec681f3Smrg .viewType = radv_meta_get_view_type(src_image), 5237ec681f3Smrg .format = src_image->vk_format, 5247ec681f3Smrg .subresourceRange = 5257ec681f3Smrg { 5267ec681f3Smrg .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 5277ec681f3Smrg .baseMipLevel = region->srcSubresource.mipLevel, 5287ec681f3Smrg .levelCount = 1, 5297ec681f3Smrg .baseArrayLayer = src_base_layer + layer, 5307ec681f3Smrg .layerCount = 1, 5317ec681f3Smrg }, 5327ec681f3Smrg }, 5337ec681f3Smrg NULL); 5347ec681f3Smrg 5357ec681f3Smrg struct radv_image_view dst_iview; 5367ec681f3Smrg radv_image_view_init(&dst_iview, cmd_buffer->device, 5377ec681f3Smrg &(VkImageViewCreateInfo){ 5387ec681f3Smrg .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 5397ec681f3Smrg .image = radv_image_to_handle(dst_image), 5407ec681f3Smrg .viewType = radv_meta_get_view_type(dst_image), 5417ec681f3Smrg .format = dst_image->vk_format, 5427ec681f3Smrg .subresourceRange = 5437ec681f3Smrg { 5447ec681f3Smrg .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 5457ec681f3Smrg .baseMipLevel = region->dstSubresource.mipLevel, 5467ec681f3Smrg .levelCount = 1, 5477ec681f3Smrg .baseArrayLayer = dst_base_layer + layer, 5487ec681f3Smrg .layerCount = 1, 5497ec681f3Smrg }, 5507ec681f3Smrg }, 5517ec681f3Smrg NULL); 5527ec681f3Smrg 5537ec681f3Smrg VkFramebuffer fb_h; 5547ec681f3Smrg radv_CreateFramebuffer( 5557ec681f3Smrg radv_device_to_handle(device), 5567ec681f3Smrg &(VkFramebufferCreateInfo){ 5577ec681f3Smrg .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 5587ec681f3Smrg .attachmentCount = 2, 5597ec681f3Smrg .pAttachments = 5607ec681f3Smrg (VkImageView[]){ 5617ec681f3Smrg radv_image_view_to_handle(&src_iview), 5627ec681f3Smrg radv_image_view_to_handle(&dst_iview), 5637ec681f3Smrg }, 5647ec681f3Smrg .width = radv_minify(dst_image->info.width, region->dstSubresource.mipLevel), 5657ec681f3Smrg .height = radv_minify(dst_image->info.height, region->dstSubresource.mipLevel), 5667ec681f3Smrg .layers = 1}, 5677ec681f3Smrg &cmd_buffer->pool->alloc, &fb_h); 5687ec681f3Smrg 5697ec681f3Smrg radv_cmd_buffer_begin_render_pass(cmd_buffer, 5707ec681f3Smrg &(VkRenderPassBeginInfo){ 5717ec681f3Smrg .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 5727ec681f3Smrg .renderPass = device->meta_state.resolve.pass[fs_key], 5737ec681f3Smrg .framebuffer = fb_h, 5747ec681f3Smrg .renderArea = {.offset = 5757ec681f3Smrg { 5767ec681f3Smrg dstOffset.x, 5777ec681f3Smrg dstOffset.y, 5787ec681f3Smrg }, 5797ec681f3Smrg .extent = 5807ec681f3Smrg { 5817ec681f3Smrg extent.width, 5827ec681f3Smrg extent.height, 5837ec681f3Smrg }}, 5847ec681f3Smrg .clearValueCount = 0, 5857ec681f3Smrg .pClearValues = NULL, 5867ec681f3Smrg }, 5877ec681f3Smrg NULL); 5887ec681f3Smrg 5897ec681f3Smrg radv_cmd_buffer_set_subpass(cmd_buffer, &cmd_buffer->state.pass->subpasses[0]); 5907ec681f3Smrg 5917ec681f3Smrg emit_resolve(cmd_buffer, src_image, dst_image, dst_iview.vk_format, 5927ec681f3Smrg &(VkOffset2D){ 5937ec681f3Smrg .x = dstOffset.x, 5947ec681f3Smrg .y = dstOffset.y, 5957ec681f3Smrg }, 5967ec681f3Smrg &(VkExtent2D){ 5977ec681f3Smrg .width = extent.width, 5987ec681f3Smrg .height = extent.height, 5997ec681f3Smrg }); 6007ec681f3Smrg 6017ec681f3Smrg radv_cmd_buffer_end_render_pass(cmd_buffer); 6027ec681f3Smrg 6037ec681f3Smrg radv_image_view_finish(&src_iview); 6047ec681f3Smrg radv_image_view_finish(&dst_iview); 6057ec681f3Smrg radv_DestroyFramebuffer(radv_device_to_handle(device), fb_h, &cmd_buffer->pool->alloc); 6067ec681f3Smrg } 6077ec681f3Smrg 6087ec681f3Smrg radv_meta_restore(&saved_state, cmd_buffer); 6097ec681f3Smrg} 6107ec681f3Smrg 6117ec681f3Smrgstatic void 6127ec681f3Smrgresolve_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image, 6137ec681f3Smrg VkImageLayout src_image_layout, struct radv_image *dst_image, 6147ec681f3Smrg VkImageLayout dst_image_layout, const VkImageResolve2KHR *region, 6157ec681f3Smrg enum radv_resolve_method resolve_method) 61601e04c3fSmrg{ 6177ec681f3Smrg switch (resolve_method) { 6187ec681f3Smrg case RESOLVE_HW: 6197ec681f3Smrg radv_meta_resolve_hardware_image(cmd_buffer, src_image, src_image_layout, dst_image, 6207ec681f3Smrg dst_image_layout, region); 6217ec681f3Smrg break; 6227ec681f3Smrg case RESOLVE_FRAGMENT: 6237ec681f3Smrg radv_meta_resolve_fragment_image(cmd_buffer, src_image, src_image_layout, dst_image, 6247ec681f3Smrg dst_image_layout, region); 6257ec681f3Smrg break; 6267ec681f3Smrg case RESOLVE_COMPUTE: 6277ec681f3Smrg radv_meta_resolve_compute_image(cmd_buffer, src_image, src_image->vk_format, src_image_layout, 6287ec681f3Smrg dst_image, dst_image->vk_format, dst_image_layout, region); 6297ec681f3Smrg break; 6307ec681f3Smrg default: 6317ec681f3Smrg assert(!"Invalid resolve method selected"); 6327ec681f3Smrg } 6337ec681f3Smrg} 6347ec681f3Smrg 6357ec681f3Smrgvoid 6367ec681f3Smrgradv_CmdResolveImage2KHR(VkCommandBuffer commandBuffer, 6377ec681f3Smrg const VkResolveImageInfo2KHR *pResolveImageInfo) 6387ec681f3Smrg{ 6397ec681f3Smrg RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); 6407ec681f3Smrg RADV_FROM_HANDLE(radv_image, src_image, pResolveImageInfo->srcImage); 6417ec681f3Smrg RADV_FROM_HANDLE(radv_image, dst_image, pResolveImageInfo->dstImage); 6427ec681f3Smrg VkImageLayout src_image_layout = pResolveImageInfo->srcImageLayout; 6437ec681f3Smrg VkImageLayout dst_image_layout = pResolveImageInfo->dstImageLayout; 6447ec681f3Smrg enum radv_resolve_method resolve_method = RESOLVE_HW; 6457ec681f3Smrg /* we can use the hw resolve only for single full resolves */ 6467ec681f3Smrg if (pResolveImageInfo->regionCount == 1) { 6477ec681f3Smrg if (pResolveImageInfo->pRegions[0].srcOffset.x || 6487ec681f3Smrg pResolveImageInfo->pRegions[0].srcOffset.y || pResolveImageInfo->pRegions[0].srcOffset.z) 6497ec681f3Smrg resolve_method = RESOLVE_COMPUTE; 6507ec681f3Smrg if (pResolveImageInfo->pRegions[0].dstOffset.x || 6517ec681f3Smrg pResolveImageInfo->pRegions[0].dstOffset.y || pResolveImageInfo->pRegions[0].dstOffset.z) 6527ec681f3Smrg resolve_method = RESOLVE_COMPUTE; 6537ec681f3Smrg 6547ec681f3Smrg if (pResolveImageInfo->pRegions[0].extent.width != src_image->info.width || 6557ec681f3Smrg pResolveImageInfo->pRegions[0].extent.height != src_image->info.height || 6567ec681f3Smrg pResolveImageInfo->pRegions[0].extent.depth != src_image->info.depth) 6577ec681f3Smrg resolve_method = RESOLVE_COMPUTE; 6587ec681f3Smrg } else 6597ec681f3Smrg resolve_method = RESOLVE_COMPUTE; 6607ec681f3Smrg 6617ec681f3Smrg for (uint32_t r = 0; r < pResolveImageInfo->regionCount; r++) { 6627ec681f3Smrg const VkImageResolve2KHR *region = &pResolveImageInfo->pRegions[r]; 6637ec681f3Smrg 6647ec681f3Smrg radv_pick_resolve_method_images(cmd_buffer->device, src_image, src_image->vk_format, dst_image, 6657ec681f3Smrg region->dstSubresource.mipLevel, dst_image_layout, false, 6667ec681f3Smrg cmd_buffer, &resolve_method); 6677ec681f3Smrg 6687ec681f3Smrg resolve_image(cmd_buffer, src_image, src_image_layout, dst_image, dst_image_layout, region, 6697ec681f3Smrg resolve_method); 6707ec681f3Smrg } 6717ec681f3Smrg} 6727ec681f3Smrg 6737ec681f3Smrgstatic void 6747ec681f3Smrgradv_cmd_buffer_resolve_subpass_hw(struct radv_cmd_buffer *cmd_buffer) 6757ec681f3Smrg{ 6767ec681f3Smrg struct radv_framebuffer *fb = cmd_buffer->state.framebuffer; 6777ec681f3Smrg const struct radv_subpass *subpass = cmd_buffer->state.subpass; 6787ec681f3Smrg struct radv_meta_saved_state saved_state; 6797ec681f3Smrg 6807ec681f3Smrg radv_meta_save(&saved_state, cmd_buffer, RADV_META_SAVE_GRAPHICS_PIPELINE); 6817ec681f3Smrg 6827ec681f3Smrg for (uint32_t i = 0; i < subpass->color_count; ++i) { 6837ec681f3Smrg struct radv_subpass_attachment src_att = subpass->color_attachments[i]; 6847ec681f3Smrg struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i]; 6857ec681f3Smrg 6867ec681f3Smrg if (dest_att.attachment == VK_ATTACHMENT_UNUSED) 6877ec681f3Smrg continue; 6887ec681f3Smrg 6897ec681f3Smrg struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview; 6907ec681f3Smrg struct radv_image *src_img = src_iview->image; 6917ec681f3Smrg 6927ec681f3Smrg struct radv_image_view *dest_iview = cmd_buffer->state.attachments[dest_att.attachment].iview; 6937ec681f3Smrg struct radv_image *dst_img = dest_iview->image; 6947ec681f3Smrg VkImageLayout dst_image_layout = cmd_buffer->state.attachments[dest_att.attachment].current_layout; 6957ec681f3Smrg 6967ec681f3Smrg uint32_t queue_mask = radv_image_queue_family_mask(dst_img, cmd_buffer->queue_family_index, 6977ec681f3Smrg cmd_buffer->queue_family_index); 6987ec681f3Smrg 6997ec681f3Smrg if (radv_layout_dcc_compressed(cmd_buffer->device, dst_img, dest_iview->base_mip, 7007ec681f3Smrg dst_image_layout, false, queue_mask)) { 7017ec681f3Smrg VkImageSubresourceRange range = { 7027ec681f3Smrg .aspectMask = dest_iview->aspect_mask, 7037ec681f3Smrg .baseMipLevel = dest_iview->base_mip, 7047ec681f3Smrg .levelCount = dest_iview->level_count, 7057ec681f3Smrg .baseArrayLayer = dest_iview->base_layer, 7067ec681f3Smrg .layerCount = dest_iview->layer_count, 7077ec681f3Smrg }; 7087ec681f3Smrg 7097ec681f3Smrg cmd_buffer->state.flush_bits |= radv_init_dcc(cmd_buffer, dst_img, &range, 0xffffffff); 7107ec681f3Smrg cmd_buffer->state.attachments[dest_att.attachment].current_layout = 7117ec681f3Smrg VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 7127ec681f3Smrg } 7137ec681f3Smrg 7147ec681f3Smrg struct radv_subpass resolve_subpass = { 7157ec681f3Smrg .color_count = 2, 7167ec681f3Smrg .color_attachments = (struct radv_subpass_attachment[]){src_att, dest_att}, 7177ec681f3Smrg .depth_stencil_attachment = NULL, 7187ec681f3Smrg }; 7197ec681f3Smrg 7207ec681f3Smrg radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass); 7217ec681f3Smrg 7227ec681f3Smrg VkResult ret = build_resolve_pipeline( 7237ec681f3Smrg cmd_buffer->device, radv_format_meta_fs_key(cmd_buffer->device, dest_iview->vk_format)); 7247ec681f3Smrg if (ret != VK_SUCCESS) { 7257ec681f3Smrg cmd_buffer->record_result = ret; 7267ec681f3Smrg continue; 7277ec681f3Smrg } 7287ec681f3Smrg 7297ec681f3Smrg emit_resolve(cmd_buffer, src_img, dst_img, dest_iview->vk_format, &(VkOffset2D){0, 0}, 7307ec681f3Smrg &(VkExtent2D){fb->width, fb->height}); 7317ec681f3Smrg } 7327ec681f3Smrg 7337ec681f3Smrg radv_cmd_buffer_restore_subpass(cmd_buffer, subpass); 7347ec681f3Smrg 7357ec681f3Smrg radv_meta_restore(&saved_state, cmd_buffer); 73601e04c3fSmrg} 73701e04c3fSmrg 73801e04c3fSmrg/** 73901e04c3fSmrg * Emit any needed resolves for the current subpass. 74001e04c3fSmrg */ 74101e04c3fSmrgvoid 74201e04c3fSmrgradv_cmd_buffer_resolve_subpass(struct radv_cmd_buffer *cmd_buffer) 74301e04c3fSmrg{ 7447ec681f3Smrg const struct radv_subpass *subpass = cmd_buffer->state.subpass; 7457ec681f3Smrg enum radv_resolve_method resolve_method = RESOLVE_HW; 7467ec681f3Smrg 7477ec681f3Smrg if (!subpass->has_color_resolve && !subpass->ds_resolve_attachment) 7487ec681f3Smrg return; 7497ec681f3Smrg 7507ec681f3Smrg radv_describe_begin_render_pass_resolve(cmd_buffer); 7517ec681f3Smrg 7527ec681f3Smrg if (subpass->ds_resolve_attachment) { 7537ec681f3Smrg struct radv_subpass_attachment src_att = *subpass->depth_stencil_attachment; 7547ec681f3Smrg struct radv_subpass_attachment dst_att = *subpass->ds_resolve_attachment; 7557ec681f3Smrg struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview; 7567ec681f3Smrg struct radv_image_view *dst_iview = cmd_buffer->state.attachments[dst_att.attachment].iview; 7577ec681f3Smrg 7587ec681f3Smrg /* Make sure to not clear the depth/stencil attachment after resolves. */ 7597ec681f3Smrg cmd_buffer->state.attachments[dst_att.attachment].pending_clear_aspects = 0; 7607ec681f3Smrg 7617ec681f3Smrg radv_pick_resolve_method_images(cmd_buffer->device, src_iview->image, src_iview->vk_format, 7627ec681f3Smrg dst_iview->image, dst_iview->base_mip, dst_att.layout, 7637ec681f3Smrg dst_att.in_render_loop, cmd_buffer, &resolve_method); 7647ec681f3Smrg 7657ec681f3Smrg if ((src_iview->aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) && 7667ec681f3Smrg subpass->depth_resolve_mode != VK_RESOLVE_MODE_NONE_KHR) { 7677ec681f3Smrg if (resolve_method == RESOLVE_FRAGMENT) { 7687ec681f3Smrg radv_depth_stencil_resolve_subpass_fs(cmd_buffer, VK_IMAGE_ASPECT_DEPTH_BIT, 7697ec681f3Smrg subpass->depth_resolve_mode); 7707ec681f3Smrg } else { 7717ec681f3Smrg assert(resolve_method == RESOLVE_COMPUTE); 7727ec681f3Smrg radv_depth_stencil_resolve_subpass_cs(cmd_buffer, VK_IMAGE_ASPECT_DEPTH_BIT, 7737ec681f3Smrg subpass->depth_resolve_mode); 7747ec681f3Smrg } 7757ec681f3Smrg } 7767ec681f3Smrg 7777ec681f3Smrg if ((src_iview->aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) && 7787ec681f3Smrg subpass->stencil_resolve_mode != VK_RESOLVE_MODE_NONE_KHR) { 7797ec681f3Smrg if (resolve_method == RESOLVE_FRAGMENT) { 7807ec681f3Smrg radv_depth_stencil_resolve_subpass_fs(cmd_buffer, VK_IMAGE_ASPECT_STENCIL_BIT, 7817ec681f3Smrg subpass->stencil_resolve_mode); 7827ec681f3Smrg } else { 7837ec681f3Smrg assert(resolve_method == RESOLVE_COMPUTE); 7847ec681f3Smrg radv_depth_stencil_resolve_subpass_cs(cmd_buffer, VK_IMAGE_ASPECT_STENCIL_BIT, 7857ec681f3Smrg subpass->stencil_resolve_mode); 7867ec681f3Smrg } 7877ec681f3Smrg } 7887ec681f3Smrg 7897ec681f3Smrg /* From the Vulkan spec 1.2.165: 7907ec681f3Smrg * 7917ec681f3Smrg * "VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT specifies 7927ec681f3Smrg * write access to a color, resolve, or depth/stencil 7937ec681f3Smrg * resolve attachment during a render pass or via 7947ec681f3Smrg * certain subpass load and store operations." 7957ec681f3Smrg * 7967ec681f3Smrg * Yes, it's counterintuitive but it makes sense because ds 7977ec681f3Smrg * resolve operations happen late at the end of the subpass. 7987ec681f3Smrg * 7997ec681f3Smrg * That said, RADV is wrong because it executes the subpass 8007ec681f3Smrg * end barrier *before* any subpass resolves instead of after. 8017ec681f3Smrg * 8027ec681f3Smrg * TODO: Fix this properly by executing subpass end barriers 8037ec681f3Smrg * after subpass resolves. 8047ec681f3Smrg */ 8057ec681f3Smrg cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_DB; 8067ec681f3Smrg if (radv_image_has_htile(dst_iview->image)) 8077ec681f3Smrg cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_DB_META; 8087ec681f3Smrg } 8097ec681f3Smrg 8107ec681f3Smrg if (subpass->has_color_resolve) { 8117ec681f3Smrg for (uint32_t i = 0; i < subpass->color_count; ++i) { 8127ec681f3Smrg struct radv_subpass_attachment src_att = subpass->color_attachments[i]; 8137ec681f3Smrg struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i]; 8147ec681f3Smrg 8157ec681f3Smrg if (dest_att.attachment == VK_ATTACHMENT_UNUSED) 8167ec681f3Smrg continue; 8177ec681f3Smrg 8187ec681f3Smrg /* Make sure to not clear color attachments after resolves. */ 8197ec681f3Smrg cmd_buffer->state.attachments[dest_att.attachment].pending_clear_aspects = 0; 8207ec681f3Smrg 8217ec681f3Smrg struct radv_image_view *dst_iview = 8227ec681f3Smrg cmd_buffer->state.attachments[dest_att.attachment].iview; 8237ec681f3Smrg struct radv_image *dst_img = dst_iview->image; 8247ec681f3Smrg struct radv_image_view *src_iview = 8257ec681f3Smrg cmd_buffer->state.attachments[src_att.attachment].iview; 8267ec681f3Smrg struct radv_image *src_img = src_iview->image; 8277ec681f3Smrg 8287ec681f3Smrg radv_pick_resolve_method_images(cmd_buffer->device, src_img, src_iview->vk_format, dst_img, 8297ec681f3Smrg dst_iview->base_mip, dest_att.layout, 8307ec681f3Smrg dest_att.in_render_loop, cmd_buffer, &resolve_method); 8317ec681f3Smrg 8327ec681f3Smrg if (resolve_method == RESOLVE_FRAGMENT) { 8337ec681f3Smrg break; 8347ec681f3Smrg } 8357ec681f3Smrg } 8367ec681f3Smrg 8377ec681f3Smrg switch (resolve_method) { 8387ec681f3Smrg case RESOLVE_HW: 8397ec681f3Smrg radv_cmd_buffer_resolve_subpass_hw(cmd_buffer); 8407ec681f3Smrg break; 8417ec681f3Smrg case RESOLVE_COMPUTE: 8427ec681f3Smrg radv_cmd_buffer_resolve_subpass_cs(cmd_buffer); 8437ec681f3Smrg break; 8447ec681f3Smrg case RESOLVE_FRAGMENT: 8457ec681f3Smrg radv_cmd_buffer_resolve_subpass_fs(cmd_buffer); 8467ec681f3Smrg break; 8477ec681f3Smrg default: 8487ec681f3Smrg unreachable("Invalid resolve method"); 8497ec681f3Smrg } 8507ec681f3Smrg } 8517ec681f3Smrg 8527ec681f3Smrg radv_describe_end_render_pass_resolve(cmd_buffer); 85301e04c3fSmrg} 85401e04c3fSmrg 85501e04c3fSmrg/** 85601e04c3fSmrg * Decompress CMask/FMask before resolving a multisampled source image inside a 85701e04c3fSmrg * subpass. 85801e04c3fSmrg */ 85901e04c3fSmrgvoid 86001e04c3fSmrgradv_decompress_resolve_subpass_src(struct radv_cmd_buffer *cmd_buffer) 86101e04c3fSmrg{ 8627ec681f3Smrg const struct radv_subpass *subpass = cmd_buffer->state.subpass; 8637ec681f3Smrg struct radv_framebuffer *fb = cmd_buffer->state.framebuffer; 8647ec681f3Smrg uint32_t layer_count = fb->layers; 8657ec681f3Smrg 8667ec681f3Smrg if (subpass->view_mask) 8677ec681f3Smrg layer_count = util_last_bit(subpass->view_mask); 8687ec681f3Smrg 8697ec681f3Smrg for (uint32_t i = 0; i < subpass->color_count; ++i) { 8707ec681f3Smrg struct radv_subpass_attachment src_att = subpass->color_attachments[i]; 8717ec681f3Smrg struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i]; 8727ec681f3Smrg 8737ec681f3Smrg if (dest_att.attachment == VK_ATTACHMENT_UNUSED) 8747ec681f3Smrg continue; 87501e04c3fSmrg 8767ec681f3Smrg struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview; 8777ec681f3Smrg struct radv_image *src_image = src_iview->image; 87801e04c3fSmrg 8797ec681f3Smrg VkImageResolve2KHR region = {0}; 8807ec681f3Smrg region.sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR; 8817ec681f3Smrg region.srcSubresource.aspectMask = src_iview->aspect_mask; 8827ec681f3Smrg region.srcSubresource.mipLevel = 0; 8837ec681f3Smrg region.srcSubresource.baseArrayLayer = src_iview->base_layer; 8847ec681f3Smrg region.srcSubresource.layerCount = layer_count; 88501e04c3fSmrg 8867ec681f3Smrg radv_decompress_resolve_src(cmd_buffer, src_image, src_att.layout, ®ion); 8877ec681f3Smrg } 8887ec681f3Smrg} 8897ec681f3Smrg 8907ec681f3Smrgstatic struct radv_sample_locations_state * 8917ec681f3Smrgradv_get_resolve_sample_locations(struct radv_cmd_buffer *cmd_buffer) 8927ec681f3Smrg{ 8937ec681f3Smrg struct radv_cmd_state *state = &cmd_buffer->state; 8947ec681f3Smrg uint32_t subpass_id = radv_get_subpass_id(cmd_buffer); 89501e04c3fSmrg 8967ec681f3Smrg for (uint32_t i = 0; i < state->num_subpass_sample_locs; i++) { 8977ec681f3Smrg if (state->subpass_sample_locs[i].subpass_idx == subpass_id) 8987ec681f3Smrg return &state->subpass_sample_locs[i].sample_location; 8997ec681f3Smrg } 90001e04c3fSmrg 9017ec681f3Smrg return NULL; 90201e04c3fSmrg} 90301e04c3fSmrg 90401e04c3fSmrg/** 90501e04c3fSmrg * Decompress CMask/FMask before resolving a multisampled source image. 90601e04c3fSmrg */ 90701e04c3fSmrgvoid 9087ec681f3Smrgradv_decompress_resolve_src(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image, 9097ec681f3Smrg VkImageLayout src_image_layout, const VkImageResolve2KHR *region) 91001e04c3fSmrg{ 9117ec681f3Smrg const uint32_t src_base_layer = 9127ec681f3Smrg radv_meta_get_iview_layer(src_image, ®ion->srcSubresource, ®ion->srcOffset); 9137ec681f3Smrg 9147ec681f3Smrg VkImageMemoryBarrier barrier = {0}; 9157ec681f3Smrg barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 9167ec681f3Smrg barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 9177ec681f3Smrg barrier.oldLayout = src_image_layout; 9187ec681f3Smrg barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; 9197ec681f3Smrg barrier.image = radv_image_to_handle(src_image); 9207ec681f3Smrg barrier.subresourceRange = (VkImageSubresourceRange){ 9217ec681f3Smrg .aspectMask = region->srcSubresource.aspectMask, 9227ec681f3Smrg .baseMipLevel = region->srcSubresource.mipLevel, 9237ec681f3Smrg .levelCount = 1, 9247ec681f3Smrg .baseArrayLayer = src_base_layer, 9257ec681f3Smrg .layerCount = region->srcSubresource.layerCount, 9267ec681f3Smrg }; 9277ec681f3Smrg 9287ec681f3Smrg if (src_image->flags & VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT) { 9297ec681f3Smrg /* If the depth/stencil image uses different sample 9307ec681f3Smrg * locations, we need them during HTILE decompressions. 9317ec681f3Smrg */ 9327ec681f3Smrg struct radv_sample_locations_state *sample_locs = 9337ec681f3Smrg radv_get_resolve_sample_locations(cmd_buffer); 9347ec681f3Smrg 9357ec681f3Smrg barrier.pNext = &(VkSampleLocationsInfoEXT){ 9367ec681f3Smrg .sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT, 9377ec681f3Smrg .sampleLocationsPerPixel = sample_locs->per_pixel, 9387ec681f3Smrg .sampleLocationGridSize = sample_locs->grid_size, 9397ec681f3Smrg .sampleLocationsCount = sample_locs->count, 9407ec681f3Smrg .pSampleLocations = sample_locs->locations, 9417ec681f3Smrg }; 9427ec681f3Smrg } 9437ec681f3Smrg 9447ec681f3Smrg radv_CmdPipelineBarrier(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 9457ec681f3Smrg VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, false, 0, NULL, 0, NULL, 1, 9467ec681f3Smrg &barrier); 94701e04c3fSmrg} 948