1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2019 Raspberry Pi Ltd 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 "v3dv_private.h" 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_cistatic uint32_t 27bf215546Sopenharmony_cinum_subpass_attachments(const VkSubpassDescription2 *desc) 28bf215546Sopenharmony_ci{ 29bf215546Sopenharmony_ci return desc->inputAttachmentCount + 30bf215546Sopenharmony_ci desc->colorAttachmentCount + 31bf215546Sopenharmony_ci (desc->pResolveAttachments ? desc->colorAttachmentCount : 0) + 32bf215546Sopenharmony_ci (desc->pDepthStencilAttachment != NULL); 33bf215546Sopenharmony_ci} 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_cistatic void 36bf215546Sopenharmony_ciset_try_tlb_resolve(struct v3dv_device *device, 37bf215546Sopenharmony_ci struct v3dv_render_pass_attachment *att) 38bf215546Sopenharmony_ci{ 39bf215546Sopenharmony_ci const struct v3dv_format *format = v3dv_X(device, get_format)(att->desc.format); 40bf215546Sopenharmony_ci att->try_tlb_resolve = v3dv_X(device, format_supports_tlb_resolve)(format); 41bf215546Sopenharmony_ci} 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_cistatic void 44bf215546Sopenharmony_cipass_find_subpass_range_for_attachments(struct v3dv_device *device, 45bf215546Sopenharmony_ci struct v3dv_render_pass *pass) 46bf215546Sopenharmony_ci{ 47bf215546Sopenharmony_ci for (uint32_t i = 0; i < pass->attachment_count; i++) { 48bf215546Sopenharmony_ci pass->attachments[i].first_subpass = pass->subpass_count - 1; 49bf215546Sopenharmony_ci pass->attachments[i].last_subpass = 0; 50bf215546Sopenharmony_ci if (pass->multiview_enabled) { 51bf215546Sopenharmony_ci for (uint32_t j = 0; j < MAX_MULTIVIEW_VIEW_COUNT; j++) { 52bf215546Sopenharmony_ci pass->attachments[i].views[j].first_subpass = pass->subpass_count - 1; 53bf215546Sopenharmony_ci pass->attachments[i].views[j].last_subpass = 0; 54bf215546Sopenharmony_ci } 55bf215546Sopenharmony_ci } 56bf215546Sopenharmony_ci } 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci for (uint32_t i = 0; i < pass->subpass_count; i++) { 59bf215546Sopenharmony_ci const struct v3dv_subpass *subpass = &pass->subpasses[i]; 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci for (uint32_t j = 0; j < subpass->color_count; j++) { 62bf215546Sopenharmony_ci uint32_t attachment_idx = subpass->color_attachments[j].attachment; 63bf215546Sopenharmony_ci if (attachment_idx == VK_ATTACHMENT_UNUSED) 64bf215546Sopenharmony_ci continue; 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci struct v3dv_render_pass_attachment *att = 67bf215546Sopenharmony_ci &pass->attachments[attachment_idx]; 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci if (i < att->first_subpass) 70bf215546Sopenharmony_ci att->first_subpass = i; 71bf215546Sopenharmony_ci if (i > att->last_subpass) 72bf215546Sopenharmony_ci att->last_subpass = i; 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci uint32_t view_mask = subpass->view_mask; 75bf215546Sopenharmony_ci while (view_mask) { 76bf215546Sopenharmony_ci uint32_t view_index = u_bit_scan(&view_mask); 77bf215546Sopenharmony_ci if (i < att->views[view_index].first_subpass) 78bf215546Sopenharmony_ci att->views[view_index].first_subpass = i; 79bf215546Sopenharmony_ci if (i > att->views[view_index].last_subpass) 80bf215546Sopenharmony_ci att->views[view_index].last_subpass = i; 81bf215546Sopenharmony_ci } 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci if (subpass->resolve_attachments && 84bf215546Sopenharmony_ci subpass->resolve_attachments[j].attachment != VK_ATTACHMENT_UNUSED) { 85bf215546Sopenharmony_ci set_try_tlb_resolve(device, att); 86bf215546Sopenharmony_ci } 87bf215546Sopenharmony_ci } 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci uint32_t ds_attachment_idx = subpass->ds_attachment.attachment; 90bf215546Sopenharmony_ci if (ds_attachment_idx != VK_ATTACHMENT_UNUSED) { 91bf215546Sopenharmony_ci if (i < pass->attachments[ds_attachment_idx].first_subpass) 92bf215546Sopenharmony_ci pass->attachments[ds_attachment_idx].first_subpass = i; 93bf215546Sopenharmony_ci if (i > pass->attachments[ds_attachment_idx].last_subpass) 94bf215546Sopenharmony_ci pass->attachments[ds_attachment_idx].last_subpass = i; 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci if (subpass->ds_resolve_attachment.attachment != VK_ATTACHMENT_UNUSED) 97bf215546Sopenharmony_ci set_try_tlb_resolve(device, &pass->attachments[ds_attachment_idx]); 98bf215546Sopenharmony_ci } 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci for (uint32_t j = 0; j < subpass->input_count; j++) { 101bf215546Sopenharmony_ci uint32_t input_attachment_idx = subpass->input_attachments[j].attachment; 102bf215546Sopenharmony_ci if (input_attachment_idx == VK_ATTACHMENT_UNUSED) 103bf215546Sopenharmony_ci continue; 104bf215546Sopenharmony_ci if (i < pass->attachments[input_attachment_idx].first_subpass) 105bf215546Sopenharmony_ci pass->attachments[input_attachment_idx].first_subpass = i; 106bf215546Sopenharmony_ci if (i > pass->attachments[input_attachment_idx].last_subpass) 107bf215546Sopenharmony_ci pass->attachments[input_attachment_idx].last_subpass = i; 108bf215546Sopenharmony_ci } 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci if (subpass->resolve_attachments) { 111bf215546Sopenharmony_ci for (uint32_t j = 0; j < subpass->color_count; j++) { 112bf215546Sopenharmony_ci uint32_t attachment_idx = subpass->resolve_attachments[j].attachment; 113bf215546Sopenharmony_ci if (attachment_idx == VK_ATTACHMENT_UNUSED) 114bf215546Sopenharmony_ci continue; 115bf215546Sopenharmony_ci if (i < pass->attachments[attachment_idx].first_subpass) 116bf215546Sopenharmony_ci pass->attachments[attachment_idx].first_subpass = i; 117bf215546Sopenharmony_ci if (i > pass->attachments[attachment_idx].last_subpass) 118bf215546Sopenharmony_ci pass->attachments[attachment_idx].last_subpass = i; 119bf215546Sopenharmony_ci } 120bf215546Sopenharmony_ci } 121bf215546Sopenharmony_ci } 122bf215546Sopenharmony_ci} 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 126bf215546Sopenharmony_civ3dv_CreateRenderPass2(VkDevice _device, 127bf215546Sopenharmony_ci const VkRenderPassCreateInfo2 *pCreateInfo, 128bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 129bf215546Sopenharmony_ci VkRenderPass *pRenderPass) 130bf215546Sopenharmony_ci{ 131bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 132bf215546Sopenharmony_ci struct v3dv_render_pass *pass; 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2); 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci /* From the VK_KHR_multiview spec: 137bf215546Sopenharmony_ci * 138bf215546Sopenharmony_ci * When a subpass uses a non-zero view mask, multiview functionality is 139bf215546Sopenharmony_ci * considered to be enabled. Multiview is all-or-nothing for a render 140bf215546Sopenharmony_ci * pass - that is, either all subpasses must have a non-zero view mask 141bf215546Sopenharmony_ci * (though some subpasses may have only one view) or all must be zero. 142bf215546Sopenharmony_ci */ 143bf215546Sopenharmony_ci bool multiview_enabled = pCreateInfo->subpassCount && 144bf215546Sopenharmony_ci pCreateInfo->pSubpasses[0].viewMask; 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci size_t size = sizeof(*pass); 147bf215546Sopenharmony_ci size_t subpasses_offset = size; 148bf215546Sopenharmony_ci size += pCreateInfo->subpassCount * sizeof(pass->subpasses[0]); 149bf215546Sopenharmony_ci size_t attachments_offset = size; 150bf215546Sopenharmony_ci size += pCreateInfo->attachmentCount * sizeof(pass->attachments[0]); 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci pass = vk_object_zalloc(&device->vk, pAllocator, size, 153bf215546Sopenharmony_ci VK_OBJECT_TYPE_RENDER_PASS); 154bf215546Sopenharmony_ci if (pass == NULL) 155bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci pass->multiview_enabled = multiview_enabled; 158bf215546Sopenharmony_ci pass->attachment_count = pCreateInfo->attachmentCount; 159bf215546Sopenharmony_ci pass->attachments = (void *) pass + attachments_offset; 160bf215546Sopenharmony_ci pass->subpass_count = pCreateInfo->subpassCount; 161bf215546Sopenharmony_ci pass->subpasses = (void *) pass + subpasses_offset; 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) 164bf215546Sopenharmony_ci pass->attachments[i].desc = pCreateInfo->pAttachments[i]; 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci uint32_t subpass_attachment_count = 0; 167bf215546Sopenharmony_ci for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) { 168bf215546Sopenharmony_ci const VkSubpassDescription2 *desc = &pCreateInfo->pSubpasses[i]; 169bf215546Sopenharmony_ci subpass_attachment_count += num_subpass_attachments(desc); 170bf215546Sopenharmony_ci } 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci if (subpass_attachment_count) { 173bf215546Sopenharmony_ci const size_t subpass_attachment_bytes = 174bf215546Sopenharmony_ci subpass_attachment_count * sizeof(struct v3dv_subpass_attachment); 175bf215546Sopenharmony_ci pass->subpass_attachments = 176bf215546Sopenharmony_ci vk_alloc2(&device->vk.alloc, pAllocator, subpass_attachment_bytes, 8, 177bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 178bf215546Sopenharmony_ci if (pass->subpass_attachments == NULL) { 179bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, pass); 180bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 181bf215546Sopenharmony_ci } 182bf215546Sopenharmony_ci } else { 183bf215546Sopenharmony_ci pass->subpass_attachments = NULL; 184bf215546Sopenharmony_ci } 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci struct v3dv_subpass_attachment *p = pass->subpass_attachments; 187bf215546Sopenharmony_ci for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) { 188bf215546Sopenharmony_ci const VkSubpassDescription2 *desc = &pCreateInfo->pSubpasses[i]; 189bf215546Sopenharmony_ci struct v3dv_subpass *subpass = &pass->subpasses[i]; 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci subpass->input_count = desc->inputAttachmentCount; 192bf215546Sopenharmony_ci subpass->color_count = desc->colorAttachmentCount; 193bf215546Sopenharmony_ci subpass->view_mask = desc->viewMask; 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci if (desc->inputAttachmentCount > 0) { 196bf215546Sopenharmony_ci subpass->input_attachments = p; 197bf215546Sopenharmony_ci p += desc->inputAttachmentCount; 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci for (uint32_t j = 0; j < desc->inputAttachmentCount; j++) { 200bf215546Sopenharmony_ci subpass->input_attachments[j] = (struct v3dv_subpass_attachment) { 201bf215546Sopenharmony_ci .attachment = desc->pInputAttachments[j].attachment, 202bf215546Sopenharmony_ci .layout = desc->pInputAttachments[j].layout, 203bf215546Sopenharmony_ci }; 204bf215546Sopenharmony_ci } 205bf215546Sopenharmony_ci } 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci if (desc->colorAttachmentCount > 0) { 208bf215546Sopenharmony_ci subpass->color_attachments = p; 209bf215546Sopenharmony_ci p += desc->colorAttachmentCount; 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) { 212bf215546Sopenharmony_ci subpass->color_attachments[j] = (struct v3dv_subpass_attachment) { 213bf215546Sopenharmony_ci .attachment = desc->pColorAttachments[j].attachment, 214bf215546Sopenharmony_ci .layout = desc->pColorAttachments[j].layout, 215bf215546Sopenharmony_ci }; 216bf215546Sopenharmony_ci } 217bf215546Sopenharmony_ci } 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci if (desc->pResolveAttachments) { 220bf215546Sopenharmony_ci subpass->resolve_attachments = p; 221bf215546Sopenharmony_ci p += desc->colorAttachmentCount; 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) { 224bf215546Sopenharmony_ci subpass->resolve_attachments[j] = (struct v3dv_subpass_attachment) { 225bf215546Sopenharmony_ci .attachment = desc->pResolveAttachments[j].attachment, 226bf215546Sopenharmony_ci .layout = desc->pResolveAttachments[j].layout, 227bf215546Sopenharmony_ci }; 228bf215546Sopenharmony_ci } 229bf215546Sopenharmony_ci } 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci if (desc->pDepthStencilAttachment) { 232bf215546Sopenharmony_ci subpass->ds_attachment = (struct v3dv_subpass_attachment) { 233bf215546Sopenharmony_ci .attachment = desc->pDepthStencilAttachment->attachment, 234bf215546Sopenharmony_ci .layout = desc->pDepthStencilAttachment->layout, 235bf215546Sopenharmony_ci }; 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci /* GFXH-1461: if depth is cleared but stencil is loaded (or viceversa), 238bf215546Sopenharmony_ci * the clear might get lost. If a subpass has this then we can't emit 239bf215546Sopenharmony_ci * the clear using the TLB and we have to do it as a draw call. 240bf215546Sopenharmony_ci * 241bf215546Sopenharmony_ci * FIXME: separate stencil. 242bf215546Sopenharmony_ci */ 243bf215546Sopenharmony_ci if (subpass->ds_attachment.attachment != VK_ATTACHMENT_UNUSED) { 244bf215546Sopenharmony_ci struct v3dv_render_pass_attachment *att = 245bf215546Sopenharmony_ci &pass->attachments[subpass->ds_attachment.attachment]; 246bf215546Sopenharmony_ci if (att->desc.format == VK_FORMAT_D24_UNORM_S8_UINT) { 247bf215546Sopenharmony_ci if (att->desc.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR && 248bf215546Sopenharmony_ci att->desc.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD) { 249bf215546Sopenharmony_ci subpass->do_depth_clear_with_draw = true; 250bf215546Sopenharmony_ci } else if (att->desc.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD && 251bf215546Sopenharmony_ci att->desc.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) { 252bf215546Sopenharmony_ci subpass->do_stencil_clear_with_draw = true; 253bf215546Sopenharmony_ci } 254bf215546Sopenharmony_ci } 255bf215546Sopenharmony_ci } 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci /* VK_KHR_depth_stencil_resolve */ 258bf215546Sopenharmony_ci const VkSubpassDescriptionDepthStencilResolve *resolve_desc = 259bf215546Sopenharmony_ci vk_find_struct_const(desc->pNext, SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE); 260bf215546Sopenharmony_ci const VkAttachmentReference2 *resolve_att = 261bf215546Sopenharmony_ci resolve_desc && resolve_desc->pDepthStencilResolveAttachment && 262bf215546Sopenharmony_ci resolve_desc->pDepthStencilResolveAttachment->attachment != VK_ATTACHMENT_UNUSED ? 263bf215546Sopenharmony_ci resolve_desc->pDepthStencilResolveAttachment : NULL; 264bf215546Sopenharmony_ci if (resolve_att) { 265bf215546Sopenharmony_ci subpass->ds_resolve_attachment = (struct v3dv_subpass_attachment) { 266bf215546Sopenharmony_ci .attachment = resolve_att->attachment, 267bf215546Sopenharmony_ci .layout = resolve_att->layout, 268bf215546Sopenharmony_ci }; 269bf215546Sopenharmony_ci assert(resolve_desc->depthResolveMode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT || 270bf215546Sopenharmony_ci resolve_desc->stencilResolveMode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT); 271bf215546Sopenharmony_ci subpass->resolve_depth = 272bf215546Sopenharmony_ci resolve_desc->depthResolveMode != VK_RESOLVE_MODE_NONE && 273bf215546Sopenharmony_ci resolve_att->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT; 274bf215546Sopenharmony_ci subpass->resolve_stencil = 275bf215546Sopenharmony_ci resolve_desc->stencilResolveMode != VK_RESOLVE_MODE_NONE && 276bf215546Sopenharmony_ci resolve_att->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT; 277bf215546Sopenharmony_ci } else { 278bf215546Sopenharmony_ci subpass->ds_resolve_attachment.attachment = VK_ATTACHMENT_UNUSED; 279bf215546Sopenharmony_ci subpass->resolve_depth = false; 280bf215546Sopenharmony_ci subpass->resolve_stencil = false; 281bf215546Sopenharmony_ci } 282bf215546Sopenharmony_ci } else { 283bf215546Sopenharmony_ci subpass->ds_attachment.attachment = VK_ATTACHMENT_UNUSED; 284bf215546Sopenharmony_ci subpass->ds_resolve_attachment.attachment = VK_ATTACHMENT_UNUSED; 285bf215546Sopenharmony_ci subpass->resolve_depth = false; 286bf215546Sopenharmony_ci subpass->resolve_stencil = false; 287bf215546Sopenharmony_ci } 288bf215546Sopenharmony_ci } 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ci pass_find_subpass_range_for_attachments(device, pass); 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci /* FIXME: handle subpass dependencies */ 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci *pRenderPass = v3dv_render_pass_to_handle(pass); 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci return VK_SUCCESS; 297bf215546Sopenharmony_ci} 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 300bf215546Sopenharmony_civ3dv_DestroyRenderPass(VkDevice _device, 301bf215546Sopenharmony_ci VkRenderPass _pass, 302bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 303bf215546Sopenharmony_ci{ 304bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 305bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_render_pass, pass, _pass); 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci if (!_pass) 308bf215546Sopenharmony_ci return; 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci vk_free2(&device->vk.alloc, pAllocator, pass->subpass_attachments); 311bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, pass); 312bf215546Sopenharmony_ci} 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_cistatic void 315bf215546Sopenharmony_cisubpass_get_granularity(struct v3dv_device *device, 316bf215546Sopenharmony_ci struct v3dv_render_pass *pass, 317bf215546Sopenharmony_ci uint32_t subpass_idx, 318bf215546Sopenharmony_ci VkExtent2D *granularity) 319bf215546Sopenharmony_ci{ 320bf215546Sopenharmony_ci /* Granularity is defined by the tile size */ 321bf215546Sopenharmony_ci assert(subpass_idx < pass->subpass_count); 322bf215546Sopenharmony_ci struct v3dv_subpass *subpass = &pass->subpasses[subpass_idx]; 323bf215546Sopenharmony_ci const uint32_t color_attachment_count = subpass->color_count; 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci bool msaa = false; 326bf215546Sopenharmony_ci uint32_t max_bpp = 0; 327bf215546Sopenharmony_ci for (uint32_t i = 0; i < color_attachment_count; i++) { 328bf215546Sopenharmony_ci uint32_t attachment_idx = subpass->color_attachments[i].attachment; 329bf215546Sopenharmony_ci if (attachment_idx == VK_ATTACHMENT_UNUSED) 330bf215546Sopenharmony_ci continue; 331bf215546Sopenharmony_ci const VkAttachmentDescription2 *desc = 332bf215546Sopenharmony_ci &pass->attachments[attachment_idx].desc; 333bf215546Sopenharmony_ci const struct v3dv_format *format = v3dv_X(device, get_format)(desc->format); 334bf215546Sopenharmony_ci uint32_t internal_type, internal_bpp; 335bf215546Sopenharmony_ci v3dv_X(device, get_internal_type_bpp_for_output_format) 336bf215546Sopenharmony_ci (format->rt_type, &internal_type, &internal_bpp); 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci max_bpp = MAX2(max_bpp, internal_bpp); 339bf215546Sopenharmony_ci 340bf215546Sopenharmony_ci if (desc->samples > VK_SAMPLE_COUNT_1_BIT) 341bf215546Sopenharmony_ci msaa = true; 342bf215546Sopenharmony_ci } 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci uint32_t width, height; 345bf215546Sopenharmony_ci bool double_buffer = (V3D_DEBUG & V3D_DEBUG_DOUBLE_BUFFER) && !msaa; 346bf215546Sopenharmony_ci v3d_choose_tile_size(color_attachment_count, max_bpp, msaa, 347bf215546Sopenharmony_ci double_buffer, &width, &height); 348bf215546Sopenharmony_ci *granularity = (VkExtent2D) { 349bf215546Sopenharmony_ci .width = width, 350bf215546Sopenharmony_ci .height = height 351bf215546Sopenharmony_ci }; 352bf215546Sopenharmony_ci} 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 355bf215546Sopenharmony_civ3dv_GetRenderAreaGranularity(VkDevice _device, 356bf215546Sopenharmony_ci VkRenderPass renderPass, 357bf215546Sopenharmony_ci VkExtent2D *pGranularity) 358bf215546Sopenharmony_ci{ 359bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_render_pass, pass, renderPass); 360bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ci *pGranularity = (VkExtent2D) { 363bf215546Sopenharmony_ci .width = 64, 364bf215546Sopenharmony_ci .height = 64, 365bf215546Sopenharmony_ci }; 366bf215546Sopenharmony_ci 367bf215546Sopenharmony_ci for (uint32_t i = 0; i < pass->subpass_count; i++) { 368bf215546Sopenharmony_ci VkExtent2D sg; 369bf215546Sopenharmony_ci subpass_get_granularity(device, pass, i, &sg); 370bf215546Sopenharmony_ci pGranularity->width = MIN2(pGranularity->width, sg.width); 371bf215546Sopenharmony_ci pGranularity->height = MIN2(pGranularity->height, sg.height); 372bf215546Sopenharmony_ci } 373bf215546Sopenharmony_ci} 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci/* Checks whether the render area rectangle covers a region that is aligned to 376bf215546Sopenharmony_ci * tile boundaries. This means that we are writing to all pixels covered by 377bf215546Sopenharmony_ci * all tiles in that area (except for pixels on edge tiles that are outside 378bf215546Sopenharmony_ci * the framebuffer dimensions). 379bf215546Sopenharmony_ci * 380bf215546Sopenharmony_ci * When our framebuffer is aligned to tile boundaries we know we are writing 381bf215546Sopenharmony_ci * valid data to all all pixels in each tile and we can apply certain 382bf215546Sopenharmony_ci * optimizations, like avoiding tile loads, since we know that none of the 383bf215546Sopenharmony_ci * original pixel values in each tile for that area need to be preserved. 384bf215546Sopenharmony_ci * We also use this to decide if we can use TLB clears, as these clear whole 385bf215546Sopenharmony_ci * tiles so we can't use them if the render area is not aligned. 386bf215546Sopenharmony_ci * 387bf215546Sopenharmony_ci * Note that when an image is created it will possibly include padding blocks 388bf215546Sopenharmony_ci * depending on its tiling layout. When the framebuffer dimensions are not 389bf215546Sopenharmony_ci * aligned to tile boundaries then edge tiles are only partially covered by the 390bf215546Sopenharmony_ci * framebuffer pixels, but tile stores still seem to store full tiles 391bf215546Sopenharmony_ci * writing to the padded sections. This is important when the framebuffer 392bf215546Sopenharmony_ci * is aliasing a smaller section of a larger image, as in that case the edge 393bf215546Sopenharmony_ci * tiles of the framebuffer would overwrite valid pixels in the larger image. 394bf215546Sopenharmony_ci * In that case, we can't flag the area as being aligned. 395bf215546Sopenharmony_ci */ 396bf215546Sopenharmony_cibool 397bf215546Sopenharmony_civ3dv_subpass_area_is_tile_aligned(struct v3dv_device *device, 398bf215546Sopenharmony_ci const VkRect2D *area, 399bf215546Sopenharmony_ci struct v3dv_framebuffer *fb, 400bf215546Sopenharmony_ci struct v3dv_render_pass *pass, 401bf215546Sopenharmony_ci uint32_t subpass_idx) 402bf215546Sopenharmony_ci{ 403bf215546Sopenharmony_ci assert(subpass_idx < pass->subpass_count); 404bf215546Sopenharmony_ci 405bf215546Sopenharmony_ci VkExtent2D granularity; 406bf215546Sopenharmony_ci subpass_get_granularity(device, pass, subpass_idx, &granularity); 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_ci return area->offset.x % granularity.width == 0 && 409bf215546Sopenharmony_ci area->offset.y % granularity.height == 0 && 410bf215546Sopenharmony_ci (area->extent.width % granularity.width == 0 || 411bf215546Sopenharmony_ci (fb->has_edge_padding && 412bf215546Sopenharmony_ci area->offset.x + area->extent.width >= fb->width)) && 413bf215546Sopenharmony_ci (area->extent.height % granularity.height == 0 || 414bf215546Sopenharmony_ci (fb->has_edge_padding && 415bf215546Sopenharmony_ci area->offset.y + area->extent.height >= fb->height)); 416bf215546Sopenharmony_ci} 417