1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2022 Imagination Technologies Ltd. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 5bf215546Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal 6bf215546Sopenharmony_ci * in the Software without restriction, including without limitation the rights 7bf215546Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8bf215546Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is 9bf215546Sopenharmony_ci * 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 THE 18bf215546Sopenharmony_ci * 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 FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include <stdbool.h> 25bf215546Sopenharmony_ci#include <stdint.h> 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "hwdef/rogue_hw_utils.h" 28bf215546Sopenharmony_ci#include "pvr_bo.h" 29bf215546Sopenharmony_ci#include "pvr_device_info.h" 30bf215546Sopenharmony_ci#include "pvr_formats.h" 31bf215546Sopenharmony_ci#include "pvr_hw_pass.h" 32bf215546Sopenharmony_ci#include "pvr_pds.h" 33bf215546Sopenharmony_ci#include "pvr_private.h" 34bf215546Sopenharmony_ci#include "pvr_usc_fragment_shader.h" 35bf215546Sopenharmony_ci#include "rogue/rogue.h" 36bf215546Sopenharmony_ci#include "vk_alloc.h" 37bf215546Sopenharmony_ci#include "vk_format.h" 38bf215546Sopenharmony_ci#include "vk_log.h" 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci/***************************************************************************** 41bf215546Sopenharmony_ci PDS pre-baked program generation parameters and variables. 42bf215546Sopenharmony_ci*****************************************************************************/ 43bf215546Sopenharmony_ci/* These would normally be produced by the compiler or other code. We're using 44bf215546Sopenharmony_ci * them for now just to speed up things. All of these should eventually be 45bf215546Sopenharmony_ci * removed. 46bf215546Sopenharmony_ci */ 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_cistatic const struct { 49bf215546Sopenharmony_ci /* Indicates the amount of temporaries for the shader. */ 50bf215546Sopenharmony_ci uint32_t temp_count; 51bf215546Sopenharmony_ci enum rogue_msaa_mode msaa_mode; 52bf215546Sopenharmony_ci /* Indicates the presence of PHAS instruction. */ 53bf215546Sopenharmony_ci bool has_phase_rate_change; 54bf215546Sopenharmony_ci} pvr_pds_fragment_program_params = { 55bf215546Sopenharmony_ci .temp_count = 0, 56bf215546Sopenharmony_ci .msaa_mode = ROGUE_MSAA_MODE_PIXEL, 57bf215546Sopenharmony_ci .has_phase_rate_change = false, 58bf215546Sopenharmony_ci}; 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_cistatic inline bool pvr_subpass_has_msaa_input_attachment( 61bf215546Sopenharmony_ci struct pvr_render_subpass *subpass, 62bf215546Sopenharmony_ci const VkRenderPassCreateInfo2 *pCreateInfo) 63bf215546Sopenharmony_ci{ 64bf215546Sopenharmony_ci for (uint32_t i = 0; i < subpass->input_count; i++) { 65bf215546Sopenharmony_ci const uint32_t attachment = subpass->input_attachments[i]; 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci if (pCreateInfo->pAttachments[attachment].samples > 1) 68bf215546Sopenharmony_ci return true; 69bf215546Sopenharmony_ci } 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci return false; 72bf215546Sopenharmony_ci} 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_cistatic inline size_t 75bf215546Sopenharmony_cipvr_num_subpass_attachments(const VkSubpassDescription2 *desc) 76bf215546Sopenharmony_ci{ 77bf215546Sopenharmony_ci return desc->inputAttachmentCount + desc->colorAttachmentCount + 78bf215546Sopenharmony_ci (desc->pResolveAttachments ? desc->colorAttachmentCount : 0) + 79bf215546Sopenharmony_ci (desc->pDepthStencilAttachment != NULL); 80bf215546Sopenharmony_ci} 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_cistatic bool pvr_is_subpass_initops_flush_needed( 83bf215546Sopenharmony_ci const struct pvr_render_pass *pass, 84bf215546Sopenharmony_ci const struct pvr_renderpass_hwsetup_render *hw_render) 85bf215546Sopenharmony_ci{ 86bf215546Sopenharmony_ci struct pvr_render_subpass *subpass = &pass->subpasses[0]; 87bf215546Sopenharmony_ci uint32_t render_loadop_mask = 0; 88bf215546Sopenharmony_ci uint32_t color_attachment_mask; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci for (uint32_t i = 0; i < hw_render->color_init_count; i++) { 91bf215546Sopenharmony_ci if (hw_render->color_init[i].op != RENDERPASS_SURFACE_INITOP_NOP) 92bf215546Sopenharmony_ci render_loadop_mask |= (1 << hw_render->color_init[i].driver_id); 93bf215546Sopenharmony_ci } 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci /* If there are no load ops then there's nothing to flush. */ 96bf215546Sopenharmony_ci if (render_loadop_mask == 0) 97bf215546Sopenharmony_ci return false; 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci /* If the first subpass has any input attachments, they need to be 100bf215546Sopenharmony_ci * initialized with the result of the load op. Since the input attachment 101bf215546Sopenharmony_ci * may be read from fragments with an opaque pass type, the load ops must be 102bf215546Sopenharmony_ci * flushed or else they would be obscured and eliminated by HSR. 103bf215546Sopenharmony_ci */ 104bf215546Sopenharmony_ci if (subpass->input_count != 0) 105bf215546Sopenharmony_ci return true; 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci color_attachment_mask = 0; 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci for (uint32_t i = 0; i < subpass->color_count; i++) { 110bf215546Sopenharmony_ci const int32_t color_idx = subpass->color_attachments[i]; 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci if (color_idx != -1) 113bf215546Sopenharmony_ci color_attachment_mask |= (1 << pass->attachments[color_idx].index); 114bf215546Sopenharmony_ci } 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci /* If the first subpass does not write to all attachments which have a load 117bf215546Sopenharmony_ci * op then the load ops need to be flushed to ensure they don't get obscured 118bf215546Sopenharmony_ci * and removed by HSR. 119bf215546Sopenharmony_ci */ 120bf215546Sopenharmony_ci return (render_loadop_mask & color_attachment_mask) != render_loadop_mask; 121bf215546Sopenharmony_ci} 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_cistatic void 124bf215546Sopenharmony_cipvr_init_subpass_userpass_spawn(struct pvr_renderpass_hwsetup *hw_setup, 125bf215546Sopenharmony_ci struct pvr_render_pass *pass, 126bf215546Sopenharmony_ci struct pvr_render_subpass *subpasses) 127bf215546Sopenharmony_ci{ 128bf215546Sopenharmony_ci uint32_t subpass_idx = 0; 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci for (uint32_t i = 0; i < hw_setup->render_count; i++) { 131bf215546Sopenharmony_ci struct pvr_renderpass_hwsetup_render *hw_render = &hw_setup->renders[i]; 132bf215546Sopenharmony_ci uint32_t initial_userpass_spawn = 133bf215546Sopenharmony_ci (uint32_t)pvr_is_subpass_initops_flush_needed(pass, hw_render); 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci for (uint32_t j = 0; j < hw_render->subpass_count; j++) { 136bf215546Sopenharmony_ci subpasses[subpass_idx].userpass_spawn = (j + initial_userpass_spawn); 137bf215546Sopenharmony_ci subpass_idx++; 138bf215546Sopenharmony_ci } 139bf215546Sopenharmony_ci } 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci assert(subpass_idx == pass->subpass_count); 142bf215546Sopenharmony_ci} 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_cistatic inline bool pvr_has_output_register_writes( 145bf215546Sopenharmony_ci const struct pvr_renderpass_hwsetup_render *hw_render) 146bf215546Sopenharmony_ci{ 147bf215546Sopenharmony_ci for (uint32_t i = 0; i < hw_render->init_setup.render_targets_count; i++) { 148bf215546Sopenharmony_ci struct usc_mrt_resource *mrt_resource = 149bf215546Sopenharmony_ci &hw_render->init_setup.mrt_resources[i]; 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci if (mrt_resource->type == USC_MRT_RESOURCE_TYPE_OUTPUT_REGISTER) 152bf215546Sopenharmony_ci return true; 153bf215546Sopenharmony_ci } 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci return false; 156bf215546Sopenharmony_ci} 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ciVkResult pvr_pds_unitex_state_program_create_and_upload( 159bf215546Sopenharmony_ci struct pvr_device *device, 160bf215546Sopenharmony_ci const VkAllocationCallbacks *allocator, 161bf215546Sopenharmony_ci uint32_t texture_kicks, 162bf215546Sopenharmony_ci uint32_t uniform_kicks, 163bf215546Sopenharmony_ci struct pvr_pds_upload *const pds_upload_out) 164bf215546Sopenharmony_ci{ 165bf215546Sopenharmony_ci struct pvr_pds_pixel_shader_sa_program program = { 166bf215546Sopenharmony_ci .num_texture_dma_kicks = texture_kicks, 167bf215546Sopenharmony_ci .num_uniform_dma_kicks = uniform_kicks, 168bf215546Sopenharmony_ci }; 169bf215546Sopenharmony_ci uint32_t staging_buffer_size; 170bf215546Sopenharmony_ci uint32_t *staging_buffer; 171bf215546Sopenharmony_ci VkResult result; 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci pvr_pds_set_sizes_pixel_shader_uniform_texture_code(&program); 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci staging_buffer_size = program.code_size * sizeof(*staging_buffer); 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci staging_buffer = vk_alloc2(&device->vk.alloc, 178bf215546Sopenharmony_ci allocator, 179bf215546Sopenharmony_ci staging_buffer_size, 180bf215546Sopenharmony_ci 8U, 181bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 182bf215546Sopenharmony_ci if (!staging_buffer) 183bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci pvr_pds_generate_pixel_shader_sa_code_segment(&program, staging_buffer); 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci /* FIXME: Figure out the define for alignment of 16. */ 188bf215546Sopenharmony_ci result = pvr_gpu_upload_pds(device, 189bf215546Sopenharmony_ci NULL, 190bf215546Sopenharmony_ci 0U, 191bf215546Sopenharmony_ci 0U, 192bf215546Sopenharmony_ci staging_buffer, 193bf215546Sopenharmony_ci program.code_size, 194bf215546Sopenharmony_ci 16U, 195bf215546Sopenharmony_ci 16U, 196bf215546Sopenharmony_ci pds_upload_out); 197bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 198bf215546Sopenharmony_ci vk_free2(&device->vk.alloc, allocator, staging_buffer); 199bf215546Sopenharmony_ci return result; 200bf215546Sopenharmony_ci } 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci vk_free2(&device->vk.alloc, allocator, staging_buffer); 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci return VK_SUCCESS; 205bf215546Sopenharmony_ci} 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_cistatic VkResult 208bf215546Sopenharmony_cipvr_load_op_create(struct pvr_device *device, 209bf215546Sopenharmony_ci const VkAllocationCallbacks *allocator, 210bf215546Sopenharmony_ci struct pvr_renderpass_hwsetup_render *hw_render, 211bf215546Sopenharmony_ci struct pvr_load_op **const load_op_out) 212bf215546Sopenharmony_ci{ 213bf215546Sopenharmony_ci const struct pvr_device_info *dev_info = &device->pdevice->dev_info; 214bf215546Sopenharmony_ci const uint32_t cache_line_size = rogue_get_slc_cache_line_size(dev_info); 215bf215546Sopenharmony_ci struct pvr_load_op *load_op; 216bf215546Sopenharmony_ci VkResult result; 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci load_op = vk_zalloc2(&device->vk.alloc, 219bf215546Sopenharmony_ci allocator, 220bf215546Sopenharmony_ci sizeof(*load_op), 221bf215546Sopenharmony_ci 8, 222bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 223bf215546Sopenharmony_ci if (!load_op) 224bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_ci for (uint32_t i = 0; i < hw_render->color_init_count; i++) { 227bf215546Sopenharmony_ci struct pvr_renderpass_colorinit *color_init = &hw_render->color_init[i]; 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci if (color_init->op == RENDERPASS_SURFACE_INITOP_CLEAR) 230bf215546Sopenharmony_ci load_op->clear_mask |= 1U << i; 231bf215546Sopenharmony_ci else if (color_init->op == RENDERPASS_SURFACE_INITOP_LOAD) 232bf215546Sopenharmony_ci pvr_finishme("Missing 'load' load op"); 233bf215546Sopenharmony_ci } 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci result = pvr_gpu_upload_usc(device, 236bf215546Sopenharmony_ci pvr_usc_fragment_shader, 237bf215546Sopenharmony_ci sizeof(pvr_usc_fragment_shader), 238bf215546Sopenharmony_ci cache_line_size, 239bf215546Sopenharmony_ci &load_op->usc_frag_prog_bo); 240bf215546Sopenharmony_ci if (result != VK_SUCCESS) 241bf215546Sopenharmony_ci goto err_free_load_op; 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci result = pvr_pds_fragment_program_create_and_upload( 244bf215546Sopenharmony_ci device, 245bf215546Sopenharmony_ci allocator, 246bf215546Sopenharmony_ci load_op->usc_frag_prog_bo, 247bf215546Sopenharmony_ci pvr_pds_fragment_program_params.temp_count, 248bf215546Sopenharmony_ci pvr_pds_fragment_program_params.msaa_mode, 249bf215546Sopenharmony_ci pvr_pds_fragment_program_params.has_phase_rate_change, 250bf215546Sopenharmony_ci &load_op->pds_frag_prog); 251bf215546Sopenharmony_ci if (result != VK_SUCCESS) 252bf215546Sopenharmony_ci goto err_free_usc_frag_prog_bo; 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci result = pvr_pds_unitex_state_program_create_and_upload( 255bf215546Sopenharmony_ci device, 256bf215546Sopenharmony_ci allocator, 257bf215546Sopenharmony_ci 1U, 258bf215546Sopenharmony_ci 0U, 259bf215546Sopenharmony_ci &load_op->pds_tex_state_prog); 260bf215546Sopenharmony_ci if (result != VK_SUCCESS) 261bf215546Sopenharmony_ci goto err_free_pds_frag_prog; 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci load_op->is_hw_object = true; 264bf215546Sopenharmony_ci /* FIXME: These should be based on the USC and PDS programs, but are hard 265bf215546Sopenharmony_ci * coded for now. 266bf215546Sopenharmony_ci */ 267bf215546Sopenharmony_ci load_op->const_shareds_count = 1; 268bf215546Sopenharmony_ci load_op->shareds_dest_offset = 0; 269bf215546Sopenharmony_ci load_op->shareds_count = 1; 270bf215546Sopenharmony_ci load_op->temps_count = 1; 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci *load_op_out = load_op; 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci return VK_SUCCESS; 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_cierr_free_pds_frag_prog: 277bf215546Sopenharmony_ci pvr_bo_free(device, load_op->pds_frag_prog.pvr_bo); 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_cierr_free_usc_frag_prog_bo: 280bf215546Sopenharmony_ci pvr_bo_free(device, load_op->usc_frag_prog_bo); 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_cierr_free_load_op: 283bf215546Sopenharmony_ci vk_free2(&device->vk.alloc, allocator, load_op); 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci return result; 286bf215546Sopenharmony_ci} 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_cistatic void pvr_load_op_destroy(struct pvr_device *device, 289bf215546Sopenharmony_ci const VkAllocationCallbacks *allocator, 290bf215546Sopenharmony_ci struct pvr_load_op *load_op) 291bf215546Sopenharmony_ci{ 292bf215546Sopenharmony_ci pvr_bo_free(device, load_op->pds_tex_state_prog.pvr_bo); 293bf215546Sopenharmony_ci pvr_bo_free(device, load_op->pds_frag_prog.pvr_bo); 294bf215546Sopenharmony_ci pvr_bo_free(device, load_op->usc_frag_prog_bo); 295bf215546Sopenharmony_ci vk_free2(&device->vk.alloc, allocator, load_op); 296bf215546Sopenharmony_ci} 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci#define PVR_SPM_LOAD_IN_BUFFERS_COUNT(dev_info) \ 299bf215546Sopenharmony_ci ({ \ 300bf215546Sopenharmony_ci int __ret = 7U; \ 301bf215546Sopenharmony_ci if (PVR_HAS_FEATURE(dev_info, eight_output_registers)) \ 302bf215546Sopenharmony_ci __ret = 3U; \ 303bf215546Sopenharmony_ci __ret; \ 304bf215546Sopenharmony_ci }) 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ciVkResult pvr_CreateRenderPass2(VkDevice _device, 307bf215546Sopenharmony_ci const VkRenderPassCreateInfo2 *pCreateInfo, 308bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 309bf215546Sopenharmony_ci VkRenderPass *pRenderPass) 310bf215546Sopenharmony_ci{ 311bf215546Sopenharmony_ci struct pvr_render_pass_attachment *attachments; 312bf215546Sopenharmony_ci PVR_FROM_HANDLE(pvr_device, device, _device); 313bf215546Sopenharmony_ci struct pvr_render_subpass *subpasses; 314bf215546Sopenharmony_ci size_t subpass_attachment_count; 315bf215546Sopenharmony_ci uint32_t *subpass_attachments; 316bf215546Sopenharmony_ci struct pvr_render_pass *pass; 317bf215546Sopenharmony_ci uint32_t *dep_list; 318bf215546Sopenharmony_ci bool *flush_on_dep; 319bf215546Sopenharmony_ci VkResult result; 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci VK_MULTIALLOC(ma); 322bf215546Sopenharmony_ci vk_multialloc_add(&ma, &pass, __typeof__(*pass), 1); 323bf215546Sopenharmony_ci vk_multialloc_add(&ma, 324bf215546Sopenharmony_ci &attachments, 325bf215546Sopenharmony_ci __typeof__(*attachments), 326bf215546Sopenharmony_ci pCreateInfo->attachmentCount); 327bf215546Sopenharmony_ci vk_multialloc_add(&ma, 328bf215546Sopenharmony_ci &subpasses, 329bf215546Sopenharmony_ci __typeof__(*subpasses), 330bf215546Sopenharmony_ci pCreateInfo->subpassCount); 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci subpass_attachment_count = 0; 333bf215546Sopenharmony_ci for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) { 334bf215546Sopenharmony_ci subpass_attachment_count += 335bf215546Sopenharmony_ci pvr_num_subpass_attachments(&pCreateInfo->pSubpasses[i]); 336bf215546Sopenharmony_ci } 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci vk_multialloc_add(&ma, 339bf215546Sopenharmony_ci &subpass_attachments, 340bf215546Sopenharmony_ci __typeof__(*subpass_attachments), 341bf215546Sopenharmony_ci subpass_attachment_count); 342bf215546Sopenharmony_ci vk_multialloc_add(&ma, 343bf215546Sopenharmony_ci &dep_list, 344bf215546Sopenharmony_ci __typeof__(*dep_list), 345bf215546Sopenharmony_ci pCreateInfo->dependencyCount); 346bf215546Sopenharmony_ci vk_multialloc_add(&ma, 347bf215546Sopenharmony_ci &flush_on_dep, 348bf215546Sopenharmony_ci __typeof__(*flush_on_dep), 349bf215546Sopenharmony_ci pCreateInfo->dependencyCount); 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_ci if (!vk_multialloc_zalloc2(&ma, 352bf215546Sopenharmony_ci &device->vk.alloc, 353bf215546Sopenharmony_ci pAllocator, 354bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)) { 355bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 356bf215546Sopenharmony_ci } 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci vk_object_base_init(&device->vk, &pass->base, VK_OBJECT_TYPE_RENDER_PASS); 359bf215546Sopenharmony_ci pass->attachment_count = pCreateInfo->attachmentCount; 360bf215546Sopenharmony_ci pass->attachments = attachments; 361bf215546Sopenharmony_ci pass->subpass_count = pCreateInfo->subpassCount; 362bf215546Sopenharmony_ci pass->subpasses = subpasses; 363bf215546Sopenharmony_ci pass->max_sample_count = 1; 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci /* Copy attachment descriptions. */ 366bf215546Sopenharmony_ci for (uint32_t i = 0; i < pass->attachment_count; i++) { 367bf215546Sopenharmony_ci const VkAttachmentDescription2 *desc = &pCreateInfo->pAttachments[i]; 368bf215546Sopenharmony_ci struct pvr_render_pass_attachment *attachment = &pass->attachments[i]; 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci pvr_assert(!(desc->flags & ~VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)); 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci attachment->load_op = desc->loadOp; 373bf215546Sopenharmony_ci attachment->store_op = desc->storeOp; 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci attachment->has_stencil = vk_format_has_stencil(attachment->vk_format); 376bf215546Sopenharmony_ci if (attachment->has_stencil) { 377bf215546Sopenharmony_ci attachment->stencil_load_op = desc->stencilLoadOp; 378bf215546Sopenharmony_ci attachment->stencil_store_op = desc->stencilStoreOp; 379bf215546Sopenharmony_ci } 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ci attachment->vk_format = desc->format; 382bf215546Sopenharmony_ci attachment->sample_count = desc->samples; 383bf215546Sopenharmony_ci attachment->initial_layout = desc->initialLayout; 384bf215546Sopenharmony_ci attachment->is_pbe_downscalable = 385bf215546Sopenharmony_ci pvr_format_is_pbe_downscalable(attachment->vk_format); 386bf215546Sopenharmony_ci attachment->index = i; 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci if (attachment->sample_count > pass->max_sample_count) 389bf215546Sopenharmony_ci pass->max_sample_count = attachment->sample_count; 390bf215546Sopenharmony_ci } 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci /* Count how many dependencies each subpass has. */ 393bf215546Sopenharmony_ci for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) { 394bf215546Sopenharmony_ci const VkSubpassDependency2 *dep = &pCreateInfo->pDependencies[i]; 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci if (dep->srcSubpass != VK_SUBPASS_EXTERNAL && 397bf215546Sopenharmony_ci dep->dstSubpass != VK_SUBPASS_EXTERNAL && 398bf215546Sopenharmony_ci dep->srcSubpass != dep->dstSubpass) { 399bf215546Sopenharmony_ci pass->subpasses[dep->dstSubpass].dep_count++; 400bf215546Sopenharmony_ci } 401bf215546Sopenharmony_ci } 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ci /* Assign reference pointers to lists, and fill in the attachments list, we 404bf215546Sopenharmony_ci * need to re-walk the dependencies array later to fill the per-subpass 405bf215546Sopenharmony_ci * dependencies lists in. 406bf215546Sopenharmony_ci */ 407bf215546Sopenharmony_ci for (uint32_t i = 0; i < pass->subpass_count; i++) { 408bf215546Sopenharmony_ci const VkSubpassDescription2 *desc = &pCreateInfo->pSubpasses[i]; 409bf215546Sopenharmony_ci struct pvr_render_subpass *subpass = &pass->subpasses[i]; 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci subpass->pipeline_bind_point = desc->pipelineBindPoint; 412bf215546Sopenharmony_ci subpass->sample_count = 1; 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci subpass->color_count = desc->colorAttachmentCount; 415bf215546Sopenharmony_ci if (subpass->color_count > 0) { 416bf215546Sopenharmony_ci bool has_used_color_attachment = false; 417bf215546Sopenharmony_ci uint32_t index; 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci subpass->color_attachments = subpass_attachments; 420bf215546Sopenharmony_ci subpass_attachments += subpass->color_count; 421bf215546Sopenharmony_ci 422bf215546Sopenharmony_ci for (uint32_t j = 0; j < subpass->color_count; j++) { 423bf215546Sopenharmony_ci subpass->color_attachments[j] = 424bf215546Sopenharmony_ci desc->pColorAttachments[j].attachment; 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ci if (subpass->color_attachments[j] == VK_ATTACHMENT_UNUSED) 427bf215546Sopenharmony_ci continue; 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci index = subpass->color_attachments[j]; 430bf215546Sopenharmony_ci subpass->sample_count = pass->attachments[index].sample_count; 431bf215546Sopenharmony_ci has_used_color_attachment = true; 432bf215546Sopenharmony_ci } 433bf215546Sopenharmony_ci 434bf215546Sopenharmony_ci if (!has_used_color_attachment && desc->pDepthStencilAttachment && 435bf215546Sopenharmony_ci desc->pDepthStencilAttachment->attachment != 436bf215546Sopenharmony_ci VK_ATTACHMENT_UNUSED) { 437bf215546Sopenharmony_ci index = desc->pDepthStencilAttachment->attachment; 438bf215546Sopenharmony_ci subpass->sample_count = pass->attachments[index].sample_count; 439bf215546Sopenharmony_ci } 440bf215546Sopenharmony_ci } 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_ci if (desc->pResolveAttachments) { 443bf215546Sopenharmony_ci subpass->resolve_attachments = subpass_attachments; 444bf215546Sopenharmony_ci subpass_attachments += subpass->color_count; 445bf215546Sopenharmony_ci 446bf215546Sopenharmony_ci for (uint32_t j = 0; j < subpass->color_count; j++) { 447bf215546Sopenharmony_ci subpass->resolve_attachments[j] = 448bf215546Sopenharmony_ci desc->pResolveAttachments[j].attachment; 449bf215546Sopenharmony_ci } 450bf215546Sopenharmony_ci } 451bf215546Sopenharmony_ci 452bf215546Sopenharmony_ci subpass->input_count = desc->inputAttachmentCount; 453bf215546Sopenharmony_ci if (subpass->input_count > 0) { 454bf215546Sopenharmony_ci subpass->input_attachments = subpass_attachments; 455bf215546Sopenharmony_ci subpass_attachments += subpass->input_count; 456bf215546Sopenharmony_ci 457bf215546Sopenharmony_ci for (uint32_t j = 0; j < subpass->input_count; j++) { 458bf215546Sopenharmony_ci subpass->input_attachments[j] = 459bf215546Sopenharmony_ci desc->pInputAttachments[j].attachment; 460bf215546Sopenharmony_ci } 461bf215546Sopenharmony_ci } 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_ci if (desc->pDepthStencilAttachment) { 464bf215546Sopenharmony_ci subpass->depth_stencil_attachment = subpass_attachments++; 465bf215546Sopenharmony_ci *subpass->depth_stencil_attachment = 466bf215546Sopenharmony_ci desc->pDepthStencilAttachment->attachment; 467bf215546Sopenharmony_ci } 468bf215546Sopenharmony_ci 469bf215546Sopenharmony_ci /* Give the dependencies a slice of the subpass_attachments array. */ 470bf215546Sopenharmony_ci subpass->dep_list = dep_list; 471bf215546Sopenharmony_ci dep_list += subpass->dep_count; 472bf215546Sopenharmony_ci subpass->flush_on_dep = flush_on_dep; 473bf215546Sopenharmony_ci flush_on_dep += subpass->dep_count; 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_ci /* Reset the dependencies count so we can start from 0 and index into 476bf215546Sopenharmony_ci * the dependencies array. 477bf215546Sopenharmony_ci */ 478bf215546Sopenharmony_ci subpass->dep_count = 0; 479bf215546Sopenharmony_ci subpass->index = i; 480bf215546Sopenharmony_ci } 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci /* Compute dependencies and populate dep_list and flush_on_dep. */ 483bf215546Sopenharmony_ci for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) { 484bf215546Sopenharmony_ci const VkSubpassDependency2 *dep = &pCreateInfo->pDependencies[i]; 485bf215546Sopenharmony_ci 486bf215546Sopenharmony_ci if (dep->srcSubpass != VK_SUBPASS_EXTERNAL && 487bf215546Sopenharmony_ci dep->dstSubpass != VK_SUBPASS_EXTERNAL && 488bf215546Sopenharmony_ci dep->srcSubpass != dep->dstSubpass) { 489bf215546Sopenharmony_ci struct pvr_render_subpass *subpass = &pass->subpasses[dep->dstSubpass]; 490bf215546Sopenharmony_ci 491bf215546Sopenharmony_ci subpass->dep_list[subpass->dep_count] = dep->srcSubpass; 492bf215546Sopenharmony_ci if (pvr_subpass_has_msaa_input_attachment(subpass, pCreateInfo)) 493bf215546Sopenharmony_ci subpass->flush_on_dep[subpass->dep_count] = true; 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_ci subpass->dep_count++; 496bf215546Sopenharmony_ci } 497bf215546Sopenharmony_ci } 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_ci pass->max_tilebuffer_count = 500bf215546Sopenharmony_ci PVR_SPM_LOAD_IN_BUFFERS_COUNT(&device->pdevice->dev_info); 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_ci pass->hw_setup = pvr_create_renderpass_hwsetup(device, pass, false); 503bf215546Sopenharmony_ci if (!pass->hw_setup) { 504bf215546Sopenharmony_ci result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 505bf215546Sopenharmony_ci goto err_free_pass; 506bf215546Sopenharmony_ci } 507bf215546Sopenharmony_ci 508bf215546Sopenharmony_ci pvr_init_subpass_userpass_spawn(pass->hw_setup, pass, pass->subpasses); 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_ci for (uint32_t i = 0; i < pass->hw_setup->render_count; i++) { 511bf215546Sopenharmony_ci struct pvr_renderpass_hwsetup_render *hw_render = 512bf215546Sopenharmony_ci &pass->hw_setup->renders[i]; 513bf215546Sopenharmony_ci struct pvr_load_op *load_op = NULL; 514bf215546Sopenharmony_ci 515bf215546Sopenharmony_ci if (hw_render->tile_buffers_count) 516bf215546Sopenharmony_ci pvr_finishme("Set up tile buffer table"); 517bf215546Sopenharmony_ci 518bf215546Sopenharmony_ci if (!hw_render->color_init_count) { 519bf215546Sopenharmony_ci assert(!hw_render->client_data); 520bf215546Sopenharmony_ci continue; 521bf215546Sopenharmony_ci } 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_ci if (!pvr_has_output_register_writes(hw_render)) 524bf215546Sopenharmony_ci pvr_finishme("Add output register write"); 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ci result = pvr_load_op_create(device, pAllocator, hw_render, &load_op); 527bf215546Sopenharmony_ci if (result != VK_SUCCESS) 528bf215546Sopenharmony_ci goto err_load_op_destroy; 529bf215546Sopenharmony_ci 530bf215546Sopenharmony_ci hw_render->client_data = load_op; 531bf215546Sopenharmony_ci } 532bf215546Sopenharmony_ci 533bf215546Sopenharmony_ci *pRenderPass = pvr_render_pass_to_handle(pass); 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci return VK_SUCCESS; 536bf215546Sopenharmony_ci 537bf215546Sopenharmony_cierr_load_op_destroy: 538bf215546Sopenharmony_ci for (uint32_t i = 0; i < pass->hw_setup->render_count; i++) { 539bf215546Sopenharmony_ci struct pvr_renderpass_hwsetup_render *hw_render = 540bf215546Sopenharmony_ci &pass->hw_setup->renders[i]; 541bf215546Sopenharmony_ci 542bf215546Sopenharmony_ci if (hw_render->client_data) 543bf215546Sopenharmony_ci pvr_load_op_destroy(device, pAllocator, hw_render->client_data); 544bf215546Sopenharmony_ci } 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_ci pvr_destroy_renderpass_hwsetup(device, pass->hw_setup); 547bf215546Sopenharmony_ci 548bf215546Sopenharmony_cierr_free_pass: 549bf215546Sopenharmony_ci vk_object_base_finish(&pass->base); 550bf215546Sopenharmony_ci vk_free2(&device->vk.alloc, pAllocator, pass); 551bf215546Sopenharmony_ci 552bf215546Sopenharmony_ci return result; 553bf215546Sopenharmony_ci} 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_civoid pvr_DestroyRenderPass(VkDevice _device, 556bf215546Sopenharmony_ci VkRenderPass _pass, 557bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 558bf215546Sopenharmony_ci{ 559bf215546Sopenharmony_ci PVR_FROM_HANDLE(pvr_device, device, _device); 560bf215546Sopenharmony_ci PVR_FROM_HANDLE(pvr_render_pass, pass, _pass); 561bf215546Sopenharmony_ci 562bf215546Sopenharmony_ci if (!pass) 563bf215546Sopenharmony_ci return; 564bf215546Sopenharmony_ci 565bf215546Sopenharmony_ci for (uint32_t i = 0; i < pass->hw_setup->render_count; i++) { 566bf215546Sopenharmony_ci struct pvr_renderpass_hwsetup_render *hw_render = 567bf215546Sopenharmony_ci &pass->hw_setup->renders[i]; 568bf215546Sopenharmony_ci 569bf215546Sopenharmony_ci pvr_load_op_destroy(device, pAllocator, hw_render->client_data); 570bf215546Sopenharmony_ci } 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci pvr_destroy_renderpass_hwsetup(device, pass->hw_setup); 573bf215546Sopenharmony_ci vk_object_base_finish(&pass->base); 574bf215546Sopenharmony_ci vk_free2(&device->vk.alloc, pAllocator, pass); 575bf215546Sopenharmony_ci} 576bf215546Sopenharmony_ci 577bf215546Sopenharmony_civoid pvr_GetRenderAreaGranularity(VkDevice _device, 578bf215546Sopenharmony_ci VkRenderPass renderPass, 579bf215546Sopenharmony_ci VkExtent2D *pGranularity) 580bf215546Sopenharmony_ci{ 581bf215546Sopenharmony_ci PVR_FROM_HANDLE(pvr_device, device, _device); 582bf215546Sopenharmony_ci const struct pvr_device_info *dev_info = &device->pdevice->dev_info; 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_ci /* Granularity does not depend on any settings in the render pass, so return 585bf215546Sopenharmony_ci * the tile granularity. 586bf215546Sopenharmony_ci * 587bf215546Sopenharmony_ci * The default value is based on the minimum value found in all existing 588bf215546Sopenharmony_ci * cores. 589bf215546Sopenharmony_ci */ 590bf215546Sopenharmony_ci pGranularity->width = PVR_GET_FEATURE_VALUE(dev_info, tile_size_x, 16); 591bf215546Sopenharmony_ci pGranularity->height = PVR_GET_FEATURE_VALUE(dev_info, tile_size_y, 16); 592bf215546Sopenharmony_ci} 593