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 <assert.h> 25bf215546Sopenharmony_ci#include <stdbool.h> 26bf215546Sopenharmony_ci#include <stdint.h> 27bf215546Sopenharmony_ci#include <vulkan/vulkan.h> 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "hwdef/rogue_hw_defs.h" 30bf215546Sopenharmony_ci#include "hwdef/rogue_hw_utils.h" 31bf215546Sopenharmony_ci#include "pvr_bo.h" 32bf215546Sopenharmony_ci#include "pvr_csb.h" 33bf215546Sopenharmony_ci#include "pvr_csb_enum_helpers.h" 34bf215546Sopenharmony_ci#include "pvr_debug.h" 35bf215546Sopenharmony_ci#include "pvr_job_common.h" 36bf215546Sopenharmony_ci#include "pvr_job_context.h" 37bf215546Sopenharmony_ci#include "pvr_job_render.h" 38bf215546Sopenharmony_ci#include "pvr_pds.h" 39bf215546Sopenharmony_ci#include "pvr_private.h" 40bf215546Sopenharmony_ci#include "pvr_rogue_fw.h" 41bf215546Sopenharmony_ci#include "pvr_types.h" 42bf215546Sopenharmony_ci#include "pvr_winsys.h" 43bf215546Sopenharmony_ci#include "util/compiler.h" 44bf215546Sopenharmony_ci#include "util/macros.h" 45bf215546Sopenharmony_ci#include "util/u_math.h" 46bf215546Sopenharmony_ci#include "vk_alloc.h" 47bf215546Sopenharmony_ci#include "vk_log.h" 48bf215546Sopenharmony_ci#include "vk_util.h" 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci#define ROGUE_BIF_PM_FREELIST_BASE_ADDR_ALIGNSIZE 16U 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci/* FIXME: Is there a hardware define we can use instead? */ 53bf215546Sopenharmony_ci/* 1 DWord per PM physical page stored in the free list */ 54bf215546Sopenharmony_ci#define ROGUE_FREE_LIST_ENTRY_SIZE ((uint32_t)sizeof(uint32_t)) 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci/* FIXME: The three defines below, for the number of PC, PD and PT entries in a 57bf215546Sopenharmony_ci * 4KB page, come from rgxmmudefs_km.h (meaning they're part of the 58bf215546Sopenharmony_ci * auto-generated hwdefs). Should these be defined in rogue_mmu.xml? Keeping in 59bf215546Sopenharmony_ci * mind that we probably only need these three values. */ 60bf215546Sopenharmony_ci#define ROGUE_NUM_PC_ENTRIES_PER_PAGE 0x400U 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci#define ROGUE_NUM_PD_ENTRIES_PER_PAGE 0x200U 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci#define ROGUE_NUM_PT_ENTRIES_PER_PAGE 0x200U 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_cistruct pvr_free_list { 67bf215546Sopenharmony_ci struct pvr_device *device; 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci uint64_t size; 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci struct pvr_bo *bo; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci struct pvr_winsys_free_list *ws_free_list; 74bf215546Sopenharmony_ci}; 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci/* Macrotile information. */ 77bf215546Sopenharmony_cistruct pvr_rt_mtile_info { 78bf215546Sopenharmony_ci uint32_t tile_size_x; 79bf215546Sopenharmony_ci uint32_t tile_size_y; 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci uint32_t num_tiles_x; 82bf215546Sopenharmony_ci uint32_t num_tiles_y; 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci uint32_t tiles_per_mtile_x; 85bf215546Sopenharmony_ci uint32_t tiles_per_mtile_y; 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci uint32_t x_tile_max; 88bf215546Sopenharmony_ci uint32_t y_tile_max; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci uint32_t mtiles_x; 91bf215546Sopenharmony_ci uint32_t mtiles_y; 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_ci uint32_t mtile_x1; 94bf215546Sopenharmony_ci uint32_t mtile_y1; 95bf215546Sopenharmony_ci uint32_t mtile_x2; 96bf215546Sopenharmony_ci uint32_t mtile_y2; 97bf215546Sopenharmony_ci uint32_t mtile_x3; 98bf215546Sopenharmony_ci uint32_t mtile_y3; 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci uint32_t mtile_stride; 101bf215546Sopenharmony_ci}; 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_cistruct pvr_rt_dataset { 104bf215546Sopenharmony_ci struct pvr_device *device; 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci /* RT dataset information */ 107bf215546Sopenharmony_ci uint32_t width; 108bf215546Sopenharmony_ci uint32_t height; 109bf215546Sopenharmony_ci uint32_t samples; 110bf215546Sopenharmony_ci uint32_t layers; 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci struct pvr_free_list *global_free_list; 113bf215546Sopenharmony_ci struct pvr_free_list *local_free_list; 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci struct pvr_bo *vheap_rtc_bo; 116bf215546Sopenharmony_ci pvr_dev_addr_t vheap_dev_addr; 117bf215546Sopenharmony_ci pvr_dev_addr_t rtc_dev_addr; 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci struct pvr_bo *tpc_bo; 120bf215546Sopenharmony_ci uint64_t tpc_stride; 121bf215546Sopenharmony_ci uint64_t tpc_size; 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci struct pvr_winsys_rt_dataset *ws_rt_dataset; 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci /* RT data information */ 126bf215546Sopenharmony_ci struct pvr_bo *mta_mlist_bo; 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci struct pvr_bo *rgn_headers_bo; 129bf215546Sopenharmony_ci uint64_t rgn_headers_stride; 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci bool need_frag; 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci uint8_t rt_data_idx; 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci struct { 136bf215546Sopenharmony_ci pvr_dev_addr_t mta_dev_addr; 137bf215546Sopenharmony_ci pvr_dev_addr_t mlist_dev_addr; 138bf215546Sopenharmony_ci pvr_dev_addr_t rgn_headers_dev_addr; 139bf215546Sopenharmony_ci } rt_datas[ROGUE_NUM_RTDATAS]; 140bf215546Sopenharmony_ci}; 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ciVkResult pvr_free_list_create(struct pvr_device *device, 143bf215546Sopenharmony_ci uint32_t initial_size, 144bf215546Sopenharmony_ci uint32_t max_size, 145bf215546Sopenharmony_ci uint32_t grow_size, 146bf215546Sopenharmony_ci uint32_t grow_threshold, 147bf215546Sopenharmony_ci struct pvr_free_list *parent_free_list, 148bf215546Sopenharmony_ci struct pvr_free_list **const free_list_out) 149bf215546Sopenharmony_ci{ 150bf215546Sopenharmony_ci struct pvr_winsys_free_list *parent_ws_free_list = 151bf215546Sopenharmony_ci parent_free_list ? parent_free_list->ws_free_list : NULL; 152bf215546Sopenharmony_ci const uint64_t bo_flags = PVR_BO_ALLOC_FLAG_GPU_UNCACHED | 153bf215546Sopenharmony_ci PVR_BO_ALLOC_FLAG_PM_FW_PROTECT; 154bf215546Sopenharmony_ci struct pvr_free_list *free_list; 155bf215546Sopenharmony_ci uint32_t cache_line_size; 156bf215546Sopenharmony_ci uint32_t initial_num_pages; 157bf215546Sopenharmony_ci uint32_t grow_num_pages; 158bf215546Sopenharmony_ci uint32_t max_num_pages; 159bf215546Sopenharmony_ci uint64_t addr_alignment; 160bf215546Sopenharmony_ci uint64_t size_alignment; 161bf215546Sopenharmony_ci uint64_t size; 162bf215546Sopenharmony_ci VkResult result; 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci assert((initial_size + grow_size) <= max_size); 165bf215546Sopenharmony_ci assert(max_size != 0); 166bf215546Sopenharmony_ci assert(grow_threshold <= 100); 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci /* Make sure the free list is created with at least a single page. */ 169bf215546Sopenharmony_ci if (initial_size == 0) 170bf215546Sopenharmony_ci initial_size = ROGUE_BIF_PM_PHYSICAL_PAGE_SIZE; 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci /* The freelists sizes must respect the PM freelist base address alignment 173bf215546Sopenharmony_ci * requirement. As the freelist entries are cached by the SLC, it's also 174bf215546Sopenharmony_ci * necessary to ensure the sizes respect the SLC cache line size to avoid 175bf215546Sopenharmony_ci * invalid entries appearing in the cache, which would be problematic after 176bf215546Sopenharmony_ci * a grow operation, as the SLC entries aren't invalidated. We do this by 177bf215546Sopenharmony_ci * making sure the freelist values are appropriately aligned. 178bf215546Sopenharmony_ci * 179bf215546Sopenharmony_ci * To calculate the alignment, we first take the largest of the freelist 180bf215546Sopenharmony_ci * base address alignment and the SLC cache line size. We then divide this 181bf215546Sopenharmony_ci * by the freelist entry size to determine the number of freelist entries 182bf215546Sopenharmony_ci * required by the PM. Finally, as each entry holds a single PM physical 183bf215546Sopenharmony_ci * page, we multiple the number of entries by the page size. 184bf215546Sopenharmony_ci * 185bf215546Sopenharmony_ci * As an example, if the base address alignment is 16 bytes, the SLC cache 186bf215546Sopenharmony_ci * line size is 64 bytes and the freelist entry size is 4 bytes then 16 187bf215546Sopenharmony_ci * entries are required, as we take the SLC cacheline size (being the larger 188bf215546Sopenharmony_ci * of the two values) and divide this by 4. If the PM page size is 4096 189bf215546Sopenharmony_ci * bytes then we end up with an alignment of 65536 bytes. 190bf215546Sopenharmony_ci */ 191bf215546Sopenharmony_ci cache_line_size = rogue_get_slc_cache_line_size(&device->pdevice->dev_info); 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci addr_alignment = 194bf215546Sopenharmony_ci MAX2(ROGUE_BIF_PM_FREELIST_BASE_ADDR_ALIGNSIZE, cache_line_size); 195bf215546Sopenharmony_ci size_alignment = (addr_alignment / ROGUE_FREE_LIST_ENTRY_SIZE) * 196bf215546Sopenharmony_ci ROGUE_BIF_PM_PHYSICAL_PAGE_SIZE; 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci assert(util_is_power_of_two_nonzero(size_alignment)); 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci initial_size = align64(initial_size, size_alignment); 201bf215546Sopenharmony_ci max_size = align64(max_size, size_alignment); 202bf215546Sopenharmony_ci grow_size = align64(grow_size, size_alignment); 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci /* Make sure the 'max' size doesn't exceed what the firmware supports and 205bf215546Sopenharmony_ci * adjust the other sizes accordingly. 206bf215546Sopenharmony_ci */ 207bf215546Sopenharmony_ci if (max_size > ROGUE_FREE_LIST_MAX_SIZE) { 208bf215546Sopenharmony_ci max_size = ROGUE_FREE_LIST_MAX_SIZE; 209bf215546Sopenharmony_ci assert(align64(max_size, size_alignment) == max_size); 210bf215546Sopenharmony_ci } 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci if (initial_size > max_size) 213bf215546Sopenharmony_ci initial_size = max_size; 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci if (initial_size == max_size) 216bf215546Sopenharmony_ci grow_size = 0; 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci initial_num_pages = initial_size >> ROGUE_BIF_PM_PHYSICAL_PAGE_SHIFT; 219bf215546Sopenharmony_ci max_num_pages = max_size >> ROGUE_BIF_PM_PHYSICAL_PAGE_SHIFT; 220bf215546Sopenharmony_ci grow_num_pages = grow_size >> ROGUE_BIF_PM_PHYSICAL_PAGE_SHIFT; 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci /* Calculate the size of the buffer needed to store the free list entries 223bf215546Sopenharmony_ci * based on the maximum number of pages we can have. 224bf215546Sopenharmony_ci */ 225bf215546Sopenharmony_ci size = max_num_pages * ROGUE_FREE_LIST_ENTRY_SIZE; 226bf215546Sopenharmony_ci assert(align64(size, addr_alignment) == size); 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci free_list = vk_alloc(&device->vk.alloc, 229bf215546Sopenharmony_ci sizeof(*free_list), 230bf215546Sopenharmony_ci 8, 231bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 232bf215546Sopenharmony_ci if (!free_list) 233bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci /* FIXME: The memory is mapped GPU uncached, but this seems to contradict 236bf215546Sopenharmony_ci * the comment above about aligning to the SLC cache line size. 237bf215546Sopenharmony_ci */ 238bf215546Sopenharmony_ci result = pvr_bo_alloc(device, 239bf215546Sopenharmony_ci device->heaps.general_heap, 240bf215546Sopenharmony_ci size, 241bf215546Sopenharmony_ci addr_alignment, 242bf215546Sopenharmony_ci bo_flags, 243bf215546Sopenharmony_ci &free_list->bo); 244bf215546Sopenharmony_ci if (result != VK_SUCCESS) 245bf215546Sopenharmony_ci goto err_vk_free_free_list; 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci result = device->ws->ops->free_list_create(device->ws, 248bf215546Sopenharmony_ci free_list->bo->vma, 249bf215546Sopenharmony_ci initial_num_pages, 250bf215546Sopenharmony_ci max_num_pages, 251bf215546Sopenharmony_ci grow_num_pages, 252bf215546Sopenharmony_ci grow_threshold, 253bf215546Sopenharmony_ci parent_ws_free_list, 254bf215546Sopenharmony_ci &free_list->ws_free_list); 255bf215546Sopenharmony_ci if (result != VK_SUCCESS) 256bf215546Sopenharmony_ci goto err_pvr_bo_free_bo; 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci free_list->device = device; 259bf215546Sopenharmony_ci free_list->size = size; 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci *free_list_out = free_list; 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci return VK_SUCCESS; 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_cierr_pvr_bo_free_bo: 266bf215546Sopenharmony_ci pvr_bo_free(device, free_list->bo); 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_cierr_vk_free_free_list: 269bf215546Sopenharmony_ci vk_free(&device->vk.alloc, free_list); 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_ci return result; 272bf215546Sopenharmony_ci} 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_civoid pvr_free_list_destroy(struct pvr_free_list *free_list) 275bf215546Sopenharmony_ci{ 276bf215546Sopenharmony_ci struct pvr_device *device = free_list->device; 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci device->ws->ops->free_list_destroy(free_list->ws_free_list); 279bf215546Sopenharmony_ci pvr_bo_free(device, free_list->bo); 280bf215546Sopenharmony_ci vk_free(&device->vk.alloc, free_list); 281bf215546Sopenharmony_ci} 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_cistatic inline void pvr_get_samples_in_xy(uint32_t samples, 284bf215546Sopenharmony_ci uint32_t *const x_out, 285bf215546Sopenharmony_ci uint32_t *const y_out) 286bf215546Sopenharmony_ci{ 287bf215546Sopenharmony_ci switch (samples) { 288bf215546Sopenharmony_ci case 1: 289bf215546Sopenharmony_ci *x_out = 1; 290bf215546Sopenharmony_ci *y_out = 1; 291bf215546Sopenharmony_ci break; 292bf215546Sopenharmony_ci case 2: 293bf215546Sopenharmony_ci *x_out = 1; 294bf215546Sopenharmony_ci *y_out = 2; 295bf215546Sopenharmony_ci break; 296bf215546Sopenharmony_ci case 4: 297bf215546Sopenharmony_ci *x_out = 2; 298bf215546Sopenharmony_ci *y_out = 2; 299bf215546Sopenharmony_ci break; 300bf215546Sopenharmony_ci case 8: 301bf215546Sopenharmony_ci *x_out = 2; 302bf215546Sopenharmony_ci *y_out = 4; 303bf215546Sopenharmony_ci break; 304bf215546Sopenharmony_ci default: 305bf215546Sopenharmony_ci unreachable("Unsupported number of samples"); 306bf215546Sopenharmony_ci } 307bf215546Sopenharmony_ci} 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_cistatic void pvr_rt_mtile_info_init(struct pvr_device *device, 310bf215546Sopenharmony_ci struct pvr_rt_mtile_info *info, 311bf215546Sopenharmony_ci uint32_t width, 312bf215546Sopenharmony_ci uint32_t height, 313bf215546Sopenharmony_ci uint32_t samples) 314bf215546Sopenharmony_ci{ 315bf215546Sopenharmony_ci const struct pvr_device_info *dev_info = &device->pdevice->dev_info; 316bf215546Sopenharmony_ci uint32_t samples_in_x; 317bf215546Sopenharmony_ci uint32_t samples_in_y; 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci pvr_get_samples_in_xy(samples, &samples_in_x, &samples_in_y); 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci info->tile_size_x = PVR_GET_FEATURE_VALUE(dev_info, tile_size_x, 1); 322bf215546Sopenharmony_ci info->tile_size_y = PVR_GET_FEATURE_VALUE(dev_info, tile_size_y, 1); 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci info->num_tiles_x = DIV_ROUND_UP(width, info->tile_size_x); 325bf215546Sopenharmony_ci info->num_tiles_y = DIV_ROUND_UP(height, info->tile_size_y); 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci rogue_get_num_macrotiles_xy(dev_info, &info->mtiles_x, &info->mtiles_y); 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_ci if (PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format)) { 330bf215546Sopenharmony_ci assert(PVR_GET_FEATURE_VALUE(dev_info, 331bf215546Sopenharmony_ci simple_parameter_format_version, 332bf215546Sopenharmony_ci 0) == 2); 333bf215546Sopenharmony_ci /* Set up 16 macrotiles with a multiple of 2x2 tiles per macrotile, 334bf215546Sopenharmony_ci * which is aligned to a tile group. 335bf215546Sopenharmony_ci */ 336bf215546Sopenharmony_ci info->mtile_x1 = DIV_ROUND_UP(info->num_tiles_x, 8) * 2; 337bf215546Sopenharmony_ci info->mtile_y1 = DIV_ROUND_UP(info->num_tiles_y, 8) * 2; 338bf215546Sopenharmony_ci info->mtile_x2 = 0; 339bf215546Sopenharmony_ci info->mtile_y2 = 0; 340bf215546Sopenharmony_ci info->mtile_x3 = 0; 341bf215546Sopenharmony_ci info->mtile_y3 = 0; 342bf215546Sopenharmony_ci info->x_tile_max = ALIGN_POT(info->num_tiles_x, 2) - 1; 343bf215546Sopenharmony_ci info->y_tile_max = ALIGN_POT(info->num_tiles_y, 2) - 1; 344bf215546Sopenharmony_ci } else { 345bf215546Sopenharmony_ci /* Set up 16 macrotiles with a multiple of 4x4 tiles per macrotile. */ 346bf215546Sopenharmony_ci info->mtile_x1 = ALIGN_POT(DIV_ROUND_UP(info->num_tiles_x, 4), 4); 347bf215546Sopenharmony_ci info->mtile_y1 = ALIGN_POT(DIV_ROUND_UP(info->num_tiles_y, 4), 4); 348bf215546Sopenharmony_ci info->mtile_x2 = info->mtile_x1 * 2; 349bf215546Sopenharmony_ci info->mtile_y2 = info->mtile_y1 * 2; 350bf215546Sopenharmony_ci info->mtile_x3 = info->mtile_x1 * 3; 351bf215546Sopenharmony_ci info->mtile_y3 = info->mtile_y1 * 3; 352bf215546Sopenharmony_ci info->x_tile_max = info->num_tiles_x - 1; 353bf215546Sopenharmony_ci info->y_tile_max = info->num_tiles_y - 1; 354bf215546Sopenharmony_ci } 355bf215546Sopenharmony_ci 356bf215546Sopenharmony_ci info->tiles_per_mtile_x = info->mtile_x1 * samples_in_x; 357bf215546Sopenharmony_ci info->tiles_per_mtile_y = info->mtile_y1 * samples_in_y; 358bf215546Sopenharmony_ci 359bf215546Sopenharmony_ci info->mtile_stride = info->mtile_x1 * info->mtile_y1; 360bf215546Sopenharmony_ci} 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ci/* Note that the unit of the return value depends on the GPU. For cores with the 363bf215546Sopenharmony_ci * simple_internal_parameter_format feature the returned size is interpreted as 364bf215546Sopenharmony_ci * the number of region headers. For cores without this feature its interpreted 365bf215546Sopenharmony_ci * as the size in dwords. 366bf215546Sopenharmony_ci */ 367bf215546Sopenharmony_cistatic uint64_t 368bf215546Sopenharmony_cipvr_rt_get_isp_region_size(struct pvr_device *device, 369bf215546Sopenharmony_ci const struct pvr_rt_mtile_info *mtile_info) 370bf215546Sopenharmony_ci{ 371bf215546Sopenharmony_ci const struct pvr_device_info *dev_info = &device->pdevice->dev_info; 372bf215546Sopenharmony_ci uint64_t rgn_size = 373bf215546Sopenharmony_ci mtile_info->tiles_per_mtile_x * mtile_info->tiles_per_mtile_y; 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci if (PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format)) { 376bf215546Sopenharmony_ci uint32_t version; 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_ci rgn_size *= mtile_info->mtiles_x * mtile_info->mtiles_y; 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci if (PVR_FEATURE_VALUE(dev_info, 381bf215546Sopenharmony_ci simple_parameter_format_version, 382bf215546Sopenharmony_ci &version)) { 383bf215546Sopenharmony_ci version = 0; 384bf215546Sopenharmony_ci } 385bf215546Sopenharmony_ci 386bf215546Sopenharmony_ci if (version == 2) { 387bf215546Sopenharmony_ci /* One region header per 2x2 tile group. */ 388bf215546Sopenharmony_ci rgn_size /= (2U * 2U); 389bf215546Sopenharmony_ci } 390bf215546Sopenharmony_ci } else { 391bf215546Sopenharmony_ci const uint64_t rgn_header_size = rogue_get_region_header_size(dev_info); 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_ci /* Round up to next dword to prevent IPF overrun and convert to bytes. 394bf215546Sopenharmony_ci */ 395bf215546Sopenharmony_ci rgn_size = DIV_ROUND_UP(rgn_size * rgn_header_size, 4); 396bf215546Sopenharmony_ci } 397bf215546Sopenharmony_ci 398bf215546Sopenharmony_ci return rgn_size; 399bf215546Sopenharmony_ci} 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_cistatic VkResult pvr_rt_vheap_rtc_data_init(struct pvr_device *device, 402bf215546Sopenharmony_ci struct pvr_rt_dataset *rt_dataset, 403bf215546Sopenharmony_ci uint32_t layers) 404bf215546Sopenharmony_ci{ 405bf215546Sopenharmony_ci const uint64_t bo_flags = PVR_BO_ALLOC_FLAG_GPU_UNCACHED | 406bf215546Sopenharmony_ci PVR_BO_ALLOC_FLAG_ZERO_ON_ALLOC; 407bf215546Sopenharmony_ci uint64_t vheap_size; 408bf215546Sopenharmony_ci uint32_t alignment; 409bf215546Sopenharmony_ci uint64_t rtc_size; 410bf215546Sopenharmony_ci VkResult result; 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci vheap_size = ROGUE_CR_PM_VHEAP_TABLE_SIZE * ROGUE_PM_VHEAP_ENTRY_SIZE; 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci if (layers > 1) { 415bf215546Sopenharmony_ci uint64_t rtc_entries; 416bf215546Sopenharmony_ci 417bf215546Sopenharmony_ci vheap_size = ALIGN_POT(vheap_size, PVRX(CR_TA_RTC_ADDR_BASE_ALIGNMENT)); 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci rtc_entries = ROGUE_NUM_TEAC + ROGUE_NUM_TE + ROGUE_NUM_VCE; 420bf215546Sopenharmony_ci if (PVR_HAS_QUIRK(&device->pdevice->dev_info, 48545)) 421bf215546Sopenharmony_ci rtc_entries += ROGUE_NUM_TE; 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci rtc_size = rtc_entries * ROGUE_RTC_SIZE_IN_BYTES; 424bf215546Sopenharmony_ci } else { 425bf215546Sopenharmony_ci rtc_size = 0; 426bf215546Sopenharmony_ci } 427bf215546Sopenharmony_ci 428bf215546Sopenharmony_ci alignment = MAX2(PVRX(CR_PM_VHEAP_TABLE_BASE_ADDR_ALIGNMENT), 429bf215546Sopenharmony_ci PVRX(CR_TA_RTC_ADDR_BASE_ALIGNMENT)); 430bf215546Sopenharmony_ci 431bf215546Sopenharmony_ci result = pvr_bo_alloc(device, 432bf215546Sopenharmony_ci device->heaps.general_heap, 433bf215546Sopenharmony_ci vheap_size + rtc_size, 434bf215546Sopenharmony_ci alignment, 435bf215546Sopenharmony_ci bo_flags, 436bf215546Sopenharmony_ci &rt_dataset->vheap_rtc_bo); 437bf215546Sopenharmony_ci if (result != VK_SUCCESS) 438bf215546Sopenharmony_ci return result; 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_ci rt_dataset->vheap_dev_addr = rt_dataset->vheap_rtc_bo->vma->dev_addr; 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_ci if (rtc_size > 0) { 443bf215546Sopenharmony_ci rt_dataset->rtc_dev_addr = 444bf215546Sopenharmony_ci PVR_DEV_ADDR_OFFSET(rt_dataset->vheap_dev_addr, vheap_size); 445bf215546Sopenharmony_ci } else { 446bf215546Sopenharmony_ci rt_dataset->rtc_dev_addr = PVR_DEV_ADDR_INVALID; 447bf215546Sopenharmony_ci } 448bf215546Sopenharmony_ci 449bf215546Sopenharmony_ci return VK_SUCCESS; 450bf215546Sopenharmony_ci} 451bf215546Sopenharmony_ci 452bf215546Sopenharmony_cistatic void pvr_rt_vheap_rtc_data_fini(struct pvr_rt_dataset *rt_dataset) 453bf215546Sopenharmony_ci{ 454bf215546Sopenharmony_ci rt_dataset->rtc_dev_addr = PVR_DEV_ADDR_INVALID; 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci pvr_bo_free(rt_dataset->device, rt_dataset->vheap_rtc_bo); 457bf215546Sopenharmony_ci rt_dataset->vheap_rtc_bo = NULL; 458bf215546Sopenharmony_ci} 459bf215546Sopenharmony_ci 460bf215546Sopenharmony_cistatic void 461bf215546Sopenharmony_cipvr_rt_get_tail_ptr_stride_size(const struct pvr_device *device, 462bf215546Sopenharmony_ci const struct pvr_rt_mtile_info *mtile_info, 463bf215546Sopenharmony_ci uint32_t layers, 464bf215546Sopenharmony_ci uint64_t *const stride_out, 465bf215546Sopenharmony_ci uint64_t *const size_out) 466bf215546Sopenharmony_ci{ 467bf215546Sopenharmony_ci uint32_t max_num_mtiles; 468bf215546Sopenharmony_ci uint32_t num_mtiles_x; 469bf215546Sopenharmony_ci uint32_t num_mtiles_y; 470bf215546Sopenharmony_ci uint32_t version; 471bf215546Sopenharmony_ci uint64_t size; 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci num_mtiles_x = mtile_info->mtiles_x * mtile_info->tiles_per_mtile_x; 474bf215546Sopenharmony_ci num_mtiles_y = mtile_info->mtiles_y * mtile_info->tiles_per_mtile_y; 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ci max_num_mtiles = MAX2(util_next_power_of_two64(num_mtiles_x), 477bf215546Sopenharmony_ci util_next_power_of_two64(num_mtiles_y)); 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_ci size = max_num_mtiles * max_num_mtiles; 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci if (PVR_FEATURE_VALUE(&device->pdevice->dev_info, 482bf215546Sopenharmony_ci simple_parameter_format_version, 483bf215546Sopenharmony_ci &version)) { 484bf215546Sopenharmony_ci version = 0; 485bf215546Sopenharmony_ci } 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_ci if (version == 2) { 488bf215546Sopenharmony_ci /* One tail pointer cache entry per 2x2 tile group. */ 489bf215546Sopenharmony_ci size /= (2U * 2U); 490bf215546Sopenharmony_ci } 491bf215546Sopenharmony_ci 492bf215546Sopenharmony_ci size *= ROGUE_TAIL_POINTER_SIZE; 493bf215546Sopenharmony_ci 494bf215546Sopenharmony_ci if (layers > 1) { 495bf215546Sopenharmony_ci size = ALIGN_POT(size, ROGUE_BIF_PM_PHYSICAL_PAGE_SIZE); 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci *stride_out = size / ROGUE_BIF_PM_PHYSICAL_PAGE_SIZE; 498bf215546Sopenharmony_ci *size_out = size * layers; 499bf215546Sopenharmony_ci } else { 500bf215546Sopenharmony_ci *stride_out = 0; 501bf215546Sopenharmony_ci *size_out = size; 502bf215546Sopenharmony_ci } 503bf215546Sopenharmony_ci} 504bf215546Sopenharmony_ci 505bf215546Sopenharmony_cistatic VkResult pvr_rt_tpc_data_init(struct pvr_device *device, 506bf215546Sopenharmony_ci struct pvr_rt_dataset *rt_dataset, 507bf215546Sopenharmony_ci const struct pvr_rt_mtile_info *mtile_info, 508bf215546Sopenharmony_ci uint32_t layers) 509bf215546Sopenharmony_ci{ 510bf215546Sopenharmony_ci const uint64_t bo_flags = PVR_BO_ALLOC_FLAG_GPU_UNCACHED | 511bf215546Sopenharmony_ci PVR_BO_ALLOC_FLAG_ZERO_ON_ALLOC; 512bf215546Sopenharmony_ci uint64_t tpc_size; 513bf215546Sopenharmony_ci 514bf215546Sopenharmony_ci pvr_rt_get_tail_ptr_stride_size(device, 515bf215546Sopenharmony_ci mtile_info, 516bf215546Sopenharmony_ci layers, 517bf215546Sopenharmony_ci &rt_dataset->tpc_stride, 518bf215546Sopenharmony_ci &rt_dataset->tpc_size); 519bf215546Sopenharmony_ci tpc_size = ALIGN_POT(rt_dataset->tpc_size, ROGUE_TE_TPC_CACHE_LINE_SIZE); 520bf215546Sopenharmony_ci 521bf215546Sopenharmony_ci return pvr_bo_alloc(device, 522bf215546Sopenharmony_ci device->heaps.general_heap, 523bf215546Sopenharmony_ci tpc_size, 524bf215546Sopenharmony_ci PVRX(CR_TE_TPC_ADDR_BASE_ALIGNMENT), 525bf215546Sopenharmony_ci bo_flags, 526bf215546Sopenharmony_ci &rt_dataset->tpc_bo); 527bf215546Sopenharmony_ci} 528bf215546Sopenharmony_ci 529bf215546Sopenharmony_cistatic void pvr_rt_tpc_data_fini(struct pvr_rt_dataset *rt_dataset) 530bf215546Sopenharmony_ci{ 531bf215546Sopenharmony_ci pvr_bo_free(rt_dataset->device, rt_dataset->tpc_bo); 532bf215546Sopenharmony_ci rt_dataset->tpc_bo = NULL; 533bf215546Sopenharmony_ci} 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_cistatic uint32_t 536bf215546Sopenharmony_cipvr_rt_get_mlist_size(const struct pvr_free_list *global_free_list, 537bf215546Sopenharmony_ci const struct pvr_free_list *local_free_list) 538bf215546Sopenharmony_ci{ 539bf215546Sopenharmony_ci uint32_t num_pte_pages; 540bf215546Sopenharmony_ci uint32_t num_pde_pages; 541bf215546Sopenharmony_ci uint32_t num_pce_pages; 542bf215546Sopenharmony_ci uint64_t total_pages; 543bf215546Sopenharmony_ci uint32_t mlist_size; 544bf215546Sopenharmony_ci 545bf215546Sopenharmony_ci assert(global_free_list->size + local_free_list->size <= 546bf215546Sopenharmony_ci ROGUE_PM_MAX_PB_VIRT_ADDR_SPACE); 547bf215546Sopenharmony_ci 548bf215546Sopenharmony_ci total_pages = (global_free_list->size + local_free_list->size) >> 549bf215546Sopenharmony_ci ROGUE_BIF_PM_PHYSICAL_PAGE_SHIFT; 550bf215546Sopenharmony_ci 551bf215546Sopenharmony_ci /* Calculate the total number of physical pages required to hold the page 552bf215546Sopenharmony_ci * table, directory and catalog entries for the freelist pages. 553bf215546Sopenharmony_ci */ 554bf215546Sopenharmony_ci num_pte_pages = DIV_ROUND_UP(total_pages, ROGUE_NUM_PT_ENTRIES_PER_PAGE); 555bf215546Sopenharmony_ci num_pde_pages = DIV_ROUND_UP(num_pte_pages, ROGUE_NUM_PD_ENTRIES_PER_PAGE); 556bf215546Sopenharmony_ci num_pce_pages = DIV_ROUND_UP(num_pde_pages, ROGUE_NUM_PC_ENTRIES_PER_PAGE); 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci /* Calculate the MList size considering the total number of pages in the PB 559bf215546Sopenharmony_ci * are shared among all the PM address spaces. 560bf215546Sopenharmony_ci */ 561bf215546Sopenharmony_ci mlist_size = (num_pce_pages + num_pde_pages + num_pte_pages) * 562bf215546Sopenharmony_ci ROGUE_NUM_PM_ADDRESS_SPACES * ROGUE_MLIST_ENTRY_STRIDE; 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_ci return ALIGN_POT(mlist_size, ROGUE_BIF_PM_PHYSICAL_PAGE_SIZE); 565bf215546Sopenharmony_ci} 566bf215546Sopenharmony_ci 567bf215546Sopenharmony_cistatic void pvr_rt_get_region_headers_stride_size( 568bf215546Sopenharmony_ci const struct pvr_device *device, 569bf215546Sopenharmony_ci const struct pvr_rt_mtile_info *mtile_info, 570bf215546Sopenharmony_ci uint32_t layers, 571bf215546Sopenharmony_ci uint64_t *const stride_out, 572bf215546Sopenharmony_ci uint64_t *const size_out) 573bf215546Sopenharmony_ci{ 574bf215546Sopenharmony_ci const struct pvr_device_info *dev_info = &device->pdevice->dev_info; 575bf215546Sopenharmony_ci const uint32_t rgn_header_size = rogue_get_region_header_size(dev_info); 576bf215546Sopenharmony_ci uint32_t rgn_headers_size; 577bf215546Sopenharmony_ci uint32_t num_tiles_x; 578bf215546Sopenharmony_ci uint32_t num_tiles_y; 579bf215546Sopenharmony_ci uint32_t group_size; 580bf215546Sopenharmony_ci uint32_t version; 581bf215546Sopenharmony_ci 582bf215546Sopenharmony_ci if (PVR_FEATURE_VALUE(dev_info, simple_parameter_format_version, &version)) 583bf215546Sopenharmony_ci version = 0; 584bf215546Sopenharmony_ci 585bf215546Sopenharmony_ci group_size = version == 2 ? 2 : 1; 586bf215546Sopenharmony_ci 587bf215546Sopenharmony_ci num_tiles_x = mtile_info->mtiles_x * mtile_info->tiles_per_mtile_x; 588bf215546Sopenharmony_ci num_tiles_y = mtile_info->mtiles_y * mtile_info->tiles_per_mtile_y; 589bf215546Sopenharmony_ci 590bf215546Sopenharmony_ci rgn_headers_size = 591bf215546Sopenharmony_ci (num_tiles_x / group_size) * (num_tiles_y / group_size) * rgn_header_size; 592bf215546Sopenharmony_ci 593bf215546Sopenharmony_ci if (PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format)) { 594bf215546Sopenharmony_ci rgn_headers_size = 595bf215546Sopenharmony_ci ALIGN_POT(rgn_headers_size, PVRX(CR_TE_PSGREGION_ADDR_BASE_ALIGNMENT)); 596bf215546Sopenharmony_ci } 597bf215546Sopenharmony_ci 598bf215546Sopenharmony_ci if (layers > 1) { 599bf215546Sopenharmony_ci rgn_headers_size = 600bf215546Sopenharmony_ci ALIGN_POT(rgn_headers_size, PVRX(CR_TE_PSG_REGION_STRIDE_UNIT_SIZE)); 601bf215546Sopenharmony_ci } 602bf215546Sopenharmony_ci 603bf215546Sopenharmony_ci *stride_out = rgn_header_size; 604bf215546Sopenharmony_ci *size_out = rgn_headers_size * layers; 605bf215546Sopenharmony_ci} 606bf215546Sopenharmony_ci 607bf215546Sopenharmony_cistatic VkResult 608bf215546Sopenharmony_cipvr_rt_mta_mlist_data_init(struct pvr_device *device, 609bf215546Sopenharmony_ci struct pvr_rt_dataset *rt_dataset, 610bf215546Sopenharmony_ci const struct pvr_free_list *global_free_list, 611bf215546Sopenharmony_ci const struct pvr_free_list *local_free_list, 612bf215546Sopenharmony_ci const struct pvr_rt_mtile_info *mtile_info) 613bf215546Sopenharmony_ci{ 614bf215546Sopenharmony_ci const struct pvr_device_info *dev_info = &device->pdevice->dev_info; 615bf215546Sopenharmony_ci const uint32_t mlist_size = 616bf215546Sopenharmony_ci pvr_rt_get_mlist_size(global_free_list, local_free_list); 617bf215546Sopenharmony_ci uint32_t mta_size = rogue_get_macrotile_array_size(dev_info); 618bf215546Sopenharmony_ci const uint32_t num_rt_datas = ARRAY_SIZE(rt_dataset->rt_datas); 619bf215546Sopenharmony_ci uint32_t rt_datas_mlist_size; 620bf215546Sopenharmony_ci uint32_t rt_datas_mta_size; 621bf215546Sopenharmony_ci pvr_dev_addr_t dev_addr; 622bf215546Sopenharmony_ci VkResult result; 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_ci /* Allocate memory for macrotile array and Mlist for all RT datas. 625bf215546Sopenharmony_ci * 626bf215546Sopenharmony_ci * Allocation layout: MTA[0..N] + Mlist alignment padding + Mlist[0..N]. 627bf215546Sopenharmony_ci * 628bf215546Sopenharmony_ci * N is number of RT datas. 629bf215546Sopenharmony_ci */ 630bf215546Sopenharmony_ci rt_datas_mta_size = ALIGN_POT(mta_size * num_rt_datas, 631bf215546Sopenharmony_ci PVRX(CR_PM_MLIST0_BASE_ADDR_ALIGNMENT)); 632bf215546Sopenharmony_ci rt_datas_mlist_size = mlist_size * num_rt_datas; 633bf215546Sopenharmony_ci 634bf215546Sopenharmony_ci result = pvr_bo_alloc(device, 635bf215546Sopenharmony_ci device->heaps.general_heap, 636bf215546Sopenharmony_ci rt_datas_mta_size + rt_datas_mlist_size, 637bf215546Sopenharmony_ci PVRX(CR_PM_MTILE_ARRAY_BASE_ADDR_ALIGNMENT), 638bf215546Sopenharmony_ci PVR_BO_ALLOC_FLAG_GPU_UNCACHED, 639bf215546Sopenharmony_ci &rt_dataset->mta_mlist_bo); 640bf215546Sopenharmony_ci if (result != VK_SUCCESS) 641bf215546Sopenharmony_ci return result; 642bf215546Sopenharmony_ci 643bf215546Sopenharmony_ci dev_addr = rt_dataset->mta_mlist_bo->vma->dev_addr; 644bf215546Sopenharmony_ci 645bf215546Sopenharmony_ci for (uint32_t i = 0; i < num_rt_datas; i++) { 646bf215546Sopenharmony_ci if (mta_size != 0) { 647bf215546Sopenharmony_ci rt_dataset->rt_datas[i].mta_dev_addr = dev_addr; 648bf215546Sopenharmony_ci dev_addr = PVR_DEV_ADDR_OFFSET(dev_addr, mta_size); 649bf215546Sopenharmony_ci } else { 650bf215546Sopenharmony_ci rt_dataset->rt_datas[i].mta_dev_addr = PVR_DEV_ADDR_INVALID; 651bf215546Sopenharmony_ci } 652bf215546Sopenharmony_ci } 653bf215546Sopenharmony_ci 654bf215546Sopenharmony_ci dev_addr = PVR_DEV_ADDR_OFFSET(rt_dataset->mta_mlist_bo->vma->dev_addr, 655bf215546Sopenharmony_ci rt_datas_mta_size); 656bf215546Sopenharmony_ci 657bf215546Sopenharmony_ci for (uint32_t i = 0; i < num_rt_datas; i++) { 658bf215546Sopenharmony_ci if (mlist_size != 0) { 659bf215546Sopenharmony_ci rt_dataset->rt_datas[i].mlist_dev_addr = dev_addr; 660bf215546Sopenharmony_ci dev_addr = PVR_DEV_ADDR_OFFSET(dev_addr, mlist_size); 661bf215546Sopenharmony_ci } else { 662bf215546Sopenharmony_ci rt_dataset->rt_datas[i].mlist_dev_addr = PVR_DEV_ADDR_INVALID; 663bf215546Sopenharmony_ci } 664bf215546Sopenharmony_ci } 665bf215546Sopenharmony_ci 666bf215546Sopenharmony_ci return VK_SUCCESS; 667bf215546Sopenharmony_ci} 668bf215546Sopenharmony_ci 669bf215546Sopenharmony_cistatic void pvr_rt_mta_mlist_data_fini(struct pvr_rt_dataset *rt_dataset) 670bf215546Sopenharmony_ci{ 671bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(rt_dataset->rt_datas); i++) { 672bf215546Sopenharmony_ci rt_dataset->rt_datas[i].mlist_dev_addr = PVR_DEV_ADDR_INVALID; 673bf215546Sopenharmony_ci rt_dataset->rt_datas[i].mta_dev_addr = PVR_DEV_ADDR_INVALID; 674bf215546Sopenharmony_ci } 675bf215546Sopenharmony_ci 676bf215546Sopenharmony_ci pvr_bo_free(rt_dataset->device, rt_dataset->mta_mlist_bo); 677bf215546Sopenharmony_ci rt_dataset->mta_mlist_bo = NULL; 678bf215546Sopenharmony_ci} 679bf215546Sopenharmony_ci 680bf215546Sopenharmony_cistatic VkResult 681bf215546Sopenharmony_cipvr_rt_rgn_headers_data_init(struct pvr_device *device, 682bf215546Sopenharmony_ci struct pvr_rt_dataset *rt_dataset, 683bf215546Sopenharmony_ci const struct pvr_rt_mtile_info *mtile_info, 684bf215546Sopenharmony_ci uint32_t layers) 685bf215546Sopenharmony_ci{ 686bf215546Sopenharmony_ci const uint32_t num_rt_datas = ARRAY_SIZE(rt_dataset->rt_datas); 687bf215546Sopenharmony_ci uint64_t rgn_headers_size; 688bf215546Sopenharmony_ci pvr_dev_addr_t dev_addr; 689bf215546Sopenharmony_ci VkResult result; 690bf215546Sopenharmony_ci 691bf215546Sopenharmony_ci pvr_rt_get_region_headers_stride_size(device, 692bf215546Sopenharmony_ci mtile_info, 693bf215546Sopenharmony_ci layers, 694bf215546Sopenharmony_ci &rt_dataset->rgn_headers_stride, 695bf215546Sopenharmony_ci &rgn_headers_size); 696bf215546Sopenharmony_ci 697bf215546Sopenharmony_ci result = pvr_bo_alloc(device, 698bf215546Sopenharmony_ci device->heaps.rgn_hdr_heap, 699bf215546Sopenharmony_ci rgn_headers_size * num_rt_datas, 700bf215546Sopenharmony_ci PVRX(CR_TE_PSGREGION_ADDR_BASE_ALIGNMENT), 701bf215546Sopenharmony_ci PVR_BO_ALLOC_FLAG_GPU_UNCACHED, 702bf215546Sopenharmony_ci &rt_dataset->rgn_headers_bo); 703bf215546Sopenharmony_ci if (result != VK_SUCCESS) 704bf215546Sopenharmony_ci return result; 705bf215546Sopenharmony_ci 706bf215546Sopenharmony_ci dev_addr = rt_dataset->rgn_headers_bo->vma->dev_addr; 707bf215546Sopenharmony_ci 708bf215546Sopenharmony_ci for (uint32_t i = 0; i < num_rt_datas; i++) { 709bf215546Sopenharmony_ci rt_dataset->rt_datas[i].rgn_headers_dev_addr = dev_addr; 710bf215546Sopenharmony_ci dev_addr = PVR_DEV_ADDR_OFFSET(dev_addr, rgn_headers_size); 711bf215546Sopenharmony_ci } 712bf215546Sopenharmony_ci 713bf215546Sopenharmony_ci return VK_SUCCESS; 714bf215546Sopenharmony_ci} 715bf215546Sopenharmony_ci 716bf215546Sopenharmony_cistatic void pvr_rt_rgn_headers_data_fini(struct pvr_rt_dataset *rt_dataset) 717bf215546Sopenharmony_ci{ 718bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(rt_dataset->rt_datas); i++) 719bf215546Sopenharmony_ci rt_dataset->rt_datas[i].rgn_headers_dev_addr = PVR_DEV_ADDR_INVALID; 720bf215546Sopenharmony_ci 721bf215546Sopenharmony_ci pvr_bo_free(rt_dataset->device, rt_dataset->rgn_headers_bo); 722bf215546Sopenharmony_ci rt_dataset->rgn_headers_bo = NULL; 723bf215546Sopenharmony_ci} 724bf215546Sopenharmony_ci 725bf215546Sopenharmony_cistatic VkResult pvr_rt_datas_init(struct pvr_device *device, 726bf215546Sopenharmony_ci struct pvr_rt_dataset *rt_dataset, 727bf215546Sopenharmony_ci const struct pvr_free_list *global_free_list, 728bf215546Sopenharmony_ci const struct pvr_free_list *local_free_list, 729bf215546Sopenharmony_ci const struct pvr_rt_mtile_info *mtile_info, 730bf215546Sopenharmony_ci uint32_t layers) 731bf215546Sopenharmony_ci{ 732bf215546Sopenharmony_ci VkResult result; 733bf215546Sopenharmony_ci 734bf215546Sopenharmony_ci result = pvr_rt_mta_mlist_data_init(device, 735bf215546Sopenharmony_ci rt_dataset, 736bf215546Sopenharmony_ci global_free_list, 737bf215546Sopenharmony_ci local_free_list, 738bf215546Sopenharmony_ci mtile_info); 739bf215546Sopenharmony_ci if (result != VK_SUCCESS) 740bf215546Sopenharmony_ci return result; 741bf215546Sopenharmony_ci 742bf215546Sopenharmony_ci result = 743bf215546Sopenharmony_ci pvr_rt_rgn_headers_data_init(device, rt_dataset, mtile_info, layers); 744bf215546Sopenharmony_ci if (result != VK_SUCCESS) 745bf215546Sopenharmony_ci goto err_pvr_rt_mta_mlist_data_fini; 746bf215546Sopenharmony_ci 747bf215546Sopenharmony_ci return VK_SUCCESS; 748bf215546Sopenharmony_ci 749bf215546Sopenharmony_cierr_pvr_rt_mta_mlist_data_fini: 750bf215546Sopenharmony_ci pvr_rt_mta_mlist_data_fini(rt_dataset); 751bf215546Sopenharmony_ci 752bf215546Sopenharmony_ci return VK_SUCCESS; 753bf215546Sopenharmony_ci} 754bf215546Sopenharmony_ci 755bf215546Sopenharmony_cistatic void pvr_rt_datas_fini(struct pvr_rt_dataset *rt_dataset) 756bf215546Sopenharmony_ci{ 757bf215546Sopenharmony_ci pvr_rt_rgn_headers_data_fini(rt_dataset); 758bf215546Sopenharmony_ci pvr_rt_mta_mlist_data_fini(rt_dataset); 759bf215546Sopenharmony_ci} 760bf215546Sopenharmony_ci 761bf215546Sopenharmony_cistatic uint32_t 762bf215546Sopenharmony_cipvr_rogue_get_cr_isp_mtile_size_val(const struct pvr_device_info *dev_info, 763bf215546Sopenharmony_ci uint32_t samples, 764bf215546Sopenharmony_ci const struct pvr_rt_mtile_info *mtile_info) 765bf215546Sopenharmony_ci{ 766bf215546Sopenharmony_ci uint32_t samples_per_pixel = 767bf215546Sopenharmony_ci PVR_GET_FEATURE_VALUE(dev_info, isp_samples_per_pixel, 0); 768bf215546Sopenharmony_ci uint32_t isp_mtile_size; 769bf215546Sopenharmony_ci 770bf215546Sopenharmony_ci pvr_csb_pack (&isp_mtile_size, CR_ISP_MTILE_SIZE, value) { 771bf215546Sopenharmony_ci value.x = mtile_info->mtile_x1; 772bf215546Sopenharmony_ci value.y = mtile_info->mtile_y1; 773bf215546Sopenharmony_ci 774bf215546Sopenharmony_ci if (samples_per_pixel == 1) { 775bf215546Sopenharmony_ci if (samples >= 4) 776bf215546Sopenharmony_ci value.x <<= 1; 777bf215546Sopenharmony_ci 778bf215546Sopenharmony_ci if (samples >= 2) 779bf215546Sopenharmony_ci value.y <<= 1; 780bf215546Sopenharmony_ci } else if (samples_per_pixel == 2) { 781bf215546Sopenharmony_ci if (samples >= 8) 782bf215546Sopenharmony_ci value.x <<= 1; 783bf215546Sopenharmony_ci 784bf215546Sopenharmony_ci if (samples >= 4) 785bf215546Sopenharmony_ci value.y <<= 1; 786bf215546Sopenharmony_ci } else if (samples_per_pixel == 4) { 787bf215546Sopenharmony_ci if (samples >= 8) 788bf215546Sopenharmony_ci value.y <<= 1; 789bf215546Sopenharmony_ci } else { 790bf215546Sopenharmony_ci assert(!"Unsupported ISP samples per pixel value"); 791bf215546Sopenharmony_ci } 792bf215546Sopenharmony_ci } 793bf215546Sopenharmony_ci 794bf215546Sopenharmony_ci return isp_mtile_size; 795bf215546Sopenharmony_ci} 796bf215546Sopenharmony_ci 797bf215546Sopenharmony_cistatic uint64_t pvr_rogue_get_cr_multisamplectl_val(uint32_t samples, 798bf215546Sopenharmony_ci bool y_flip) 799bf215546Sopenharmony_ci{ 800bf215546Sopenharmony_ci static const struct { 801bf215546Sopenharmony_ci uint8_t x[8]; 802bf215546Sopenharmony_ci uint8_t y[8]; 803bf215546Sopenharmony_ci } sample_positions[4] = { 804bf215546Sopenharmony_ci /* 1 sample */ 805bf215546Sopenharmony_ci { 806bf215546Sopenharmony_ci .x = { 8 }, 807bf215546Sopenharmony_ci .y = { 8 }, 808bf215546Sopenharmony_ci }, 809bf215546Sopenharmony_ci /* 2 samples */ 810bf215546Sopenharmony_ci { 811bf215546Sopenharmony_ci .x = { 12, 4 }, 812bf215546Sopenharmony_ci .y = { 12, 4 }, 813bf215546Sopenharmony_ci }, 814bf215546Sopenharmony_ci /* 4 samples */ 815bf215546Sopenharmony_ci { 816bf215546Sopenharmony_ci .x = { 6, 14, 2, 10 }, 817bf215546Sopenharmony_ci .y = { 2, 6, 10, 14 }, 818bf215546Sopenharmony_ci }, 819bf215546Sopenharmony_ci /* 8 samples */ 820bf215546Sopenharmony_ci { 821bf215546Sopenharmony_ci .x = { 9, 7, 13, 5, 3, 1, 11, 15 }, 822bf215546Sopenharmony_ci .y = { 5, 11, 9, 3, 13, 7, 15, 1 }, 823bf215546Sopenharmony_ci }, 824bf215546Sopenharmony_ci }; 825bf215546Sopenharmony_ci uint64_t multisamplectl; 826bf215546Sopenharmony_ci uint8_t idx; 827bf215546Sopenharmony_ci 828bf215546Sopenharmony_ci idx = util_fast_log2(samples); 829bf215546Sopenharmony_ci assert(idx < ARRAY_SIZE(sample_positions)); 830bf215546Sopenharmony_ci 831bf215546Sopenharmony_ci pvr_csb_pack (&multisamplectl, CR_PPP_MULTISAMPLECTL, value) { 832bf215546Sopenharmony_ci switch (samples) { 833bf215546Sopenharmony_ci case 8: 834bf215546Sopenharmony_ci value.msaa_x7 = sample_positions[idx].x[7]; 835bf215546Sopenharmony_ci value.msaa_x6 = sample_positions[idx].x[6]; 836bf215546Sopenharmony_ci value.msaa_x5 = sample_positions[idx].x[5]; 837bf215546Sopenharmony_ci value.msaa_x4 = sample_positions[idx].x[4]; 838bf215546Sopenharmony_ci 839bf215546Sopenharmony_ci if (y_flip) { 840bf215546Sopenharmony_ci value.msaa_y7 = 16U - sample_positions[idx].y[7]; 841bf215546Sopenharmony_ci value.msaa_y6 = 16U - sample_positions[idx].y[6]; 842bf215546Sopenharmony_ci value.msaa_y5 = 16U - sample_positions[idx].y[5]; 843bf215546Sopenharmony_ci value.msaa_y4 = 16U - sample_positions[idx].y[4]; 844bf215546Sopenharmony_ci } else { 845bf215546Sopenharmony_ci value.msaa_y7 = sample_positions[idx].y[7]; 846bf215546Sopenharmony_ci value.msaa_y6 = sample_positions[idx].y[6]; 847bf215546Sopenharmony_ci value.msaa_y5 = sample_positions[idx].y[5]; 848bf215546Sopenharmony_ci value.msaa_y4 = sample_positions[idx].y[4]; 849bf215546Sopenharmony_ci } 850bf215546Sopenharmony_ci 851bf215546Sopenharmony_ci FALLTHROUGH; 852bf215546Sopenharmony_ci case 4: 853bf215546Sopenharmony_ci value.msaa_x3 = sample_positions[idx].x[3]; 854bf215546Sopenharmony_ci value.msaa_x2 = sample_positions[idx].x[2]; 855bf215546Sopenharmony_ci 856bf215546Sopenharmony_ci if (y_flip) { 857bf215546Sopenharmony_ci value.msaa_y3 = 16U - sample_positions[idx].y[3]; 858bf215546Sopenharmony_ci value.msaa_y2 = 16U - sample_positions[idx].y[2]; 859bf215546Sopenharmony_ci } else { 860bf215546Sopenharmony_ci value.msaa_y3 = sample_positions[idx].y[3]; 861bf215546Sopenharmony_ci value.msaa_y2 = sample_positions[idx].y[2]; 862bf215546Sopenharmony_ci } 863bf215546Sopenharmony_ci 864bf215546Sopenharmony_ci FALLTHROUGH; 865bf215546Sopenharmony_ci case 2: 866bf215546Sopenharmony_ci value.msaa_x1 = sample_positions[idx].x[1]; 867bf215546Sopenharmony_ci 868bf215546Sopenharmony_ci if (y_flip) { 869bf215546Sopenharmony_ci value.msaa_y1 = 16U - sample_positions[idx].y[1]; 870bf215546Sopenharmony_ci } else { 871bf215546Sopenharmony_ci value.msaa_y1 = sample_positions[idx].y[1]; 872bf215546Sopenharmony_ci } 873bf215546Sopenharmony_ci 874bf215546Sopenharmony_ci FALLTHROUGH; 875bf215546Sopenharmony_ci case 1: 876bf215546Sopenharmony_ci value.msaa_x0 = sample_positions[idx].x[0]; 877bf215546Sopenharmony_ci 878bf215546Sopenharmony_ci if (y_flip) { 879bf215546Sopenharmony_ci value.msaa_y0 = 16U - sample_positions[idx].y[0]; 880bf215546Sopenharmony_ci } else { 881bf215546Sopenharmony_ci value.msaa_y0 = sample_positions[idx].y[0]; 882bf215546Sopenharmony_ci } 883bf215546Sopenharmony_ci 884bf215546Sopenharmony_ci break; 885bf215546Sopenharmony_ci default: 886bf215546Sopenharmony_ci unreachable("Unsupported number of samples"); 887bf215546Sopenharmony_ci } 888bf215546Sopenharmony_ci } 889bf215546Sopenharmony_ci 890bf215546Sopenharmony_ci return multisamplectl; 891bf215546Sopenharmony_ci} 892bf215546Sopenharmony_ci 893bf215546Sopenharmony_cistatic uint32_t 894bf215546Sopenharmony_cipvr_rogue_get_cr_te_aa_val(const struct pvr_device_info *dev_info, 895bf215546Sopenharmony_ci uint32_t samples) 896bf215546Sopenharmony_ci{ 897bf215546Sopenharmony_ci uint32_t samples_per_pixel = 898bf215546Sopenharmony_ci PVR_GET_FEATURE_VALUE(dev_info, isp_samples_per_pixel, 0); 899bf215546Sopenharmony_ci uint32_t te_aa; 900bf215546Sopenharmony_ci 901bf215546Sopenharmony_ci pvr_csb_pack (&te_aa, CR_TE_AA, value) { 902bf215546Sopenharmony_ci if (samples_per_pixel == 1) { 903bf215546Sopenharmony_ci if (samples >= 2) 904bf215546Sopenharmony_ci value.y = true; 905bf215546Sopenharmony_ci if (samples >= 4) 906bf215546Sopenharmony_ci value.x = true; 907bf215546Sopenharmony_ci } else if (samples_per_pixel == 2) { 908bf215546Sopenharmony_ci if (samples >= 2) 909bf215546Sopenharmony_ci value.x2 = true; 910bf215546Sopenharmony_ci if (samples >= 4) 911bf215546Sopenharmony_ci value.y = true; 912bf215546Sopenharmony_ci if (samples >= 8) 913bf215546Sopenharmony_ci value.x = true; 914bf215546Sopenharmony_ci } else if (samples_per_pixel == 4) { 915bf215546Sopenharmony_ci if (samples >= 2) 916bf215546Sopenharmony_ci value.x2 = true; 917bf215546Sopenharmony_ci if (samples >= 4) 918bf215546Sopenharmony_ci value.y2 = true; 919bf215546Sopenharmony_ci if (samples >= 8) 920bf215546Sopenharmony_ci value.y = true; 921bf215546Sopenharmony_ci } else { 922bf215546Sopenharmony_ci assert(!"Unsupported ISP samples per pixel value"); 923bf215546Sopenharmony_ci } 924bf215546Sopenharmony_ci } 925bf215546Sopenharmony_ci 926bf215546Sopenharmony_ci return te_aa; 927bf215546Sopenharmony_ci} 928bf215546Sopenharmony_ci 929bf215546Sopenharmony_cistatic void pvr_rt_dataset_ws_create_info_init( 930bf215546Sopenharmony_ci struct pvr_rt_dataset *rt_dataset, 931bf215546Sopenharmony_ci const struct pvr_rt_mtile_info *mtile_info, 932bf215546Sopenharmony_ci struct pvr_winsys_rt_dataset_create_info *create_info) 933bf215546Sopenharmony_ci{ 934bf215546Sopenharmony_ci struct pvr_device *device = rt_dataset->device; 935bf215546Sopenharmony_ci const struct pvr_device_info *dev_info = &device->pdevice->dev_info; 936bf215546Sopenharmony_ci 937bf215546Sopenharmony_ci memset(create_info, 0, sizeof(*create_info)); 938bf215546Sopenharmony_ci 939bf215546Sopenharmony_ci /* Local freelist. */ 940bf215546Sopenharmony_ci create_info->local_free_list = rt_dataset->local_free_list->ws_free_list; 941bf215546Sopenharmony_ci 942bf215546Sopenharmony_ci /* ISP register values. */ 943bf215546Sopenharmony_ci if (PVR_HAS_ERN(dev_info, 42307) && 944bf215546Sopenharmony_ci !(PVR_HAS_FEATURE(dev_info, roguexe) && mtile_info->tile_size_x == 16)) { 945bf215546Sopenharmony_ci float value; 946bf215546Sopenharmony_ci 947bf215546Sopenharmony_ci if (rt_dataset->width != 0) { 948bf215546Sopenharmony_ci value = 949bf215546Sopenharmony_ci ROGUE_ISP_MERGE_LOWER_LIMIT_NUMERATOR / (float)rt_dataset->width; 950bf215546Sopenharmony_ci create_info->isp_merge_lower_x = fui(value); 951bf215546Sopenharmony_ci 952bf215546Sopenharmony_ci value = 953bf215546Sopenharmony_ci ROGUE_ISP_MERGE_UPPER_LIMIT_NUMERATOR / (float)rt_dataset->width; 954bf215546Sopenharmony_ci create_info->isp_merge_upper_x = fui(value); 955bf215546Sopenharmony_ci } 956bf215546Sopenharmony_ci 957bf215546Sopenharmony_ci if (rt_dataset->height != 0) { 958bf215546Sopenharmony_ci value = 959bf215546Sopenharmony_ci ROGUE_ISP_MERGE_LOWER_LIMIT_NUMERATOR / (float)rt_dataset->height; 960bf215546Sopenharmony_ci create_info->isp_merge_lower_y = fui(value); 961bf215546Sopenharmony_ci 962bf215546Sopenharmony_ci value = 963bf215546Sopenharmony_ci ROGUE_ISP_MERGE_UPPER_LIMIT_NUMERATOR / (float)rt_dataset->height; 964bf215546Sopenharmony_ci create_info->isp_merge_upper_y = fui(value); 965bf215546Sopenharmony_ci } 966bf215546Sopenharmony_ci 967bf215546Sopenharmony_ci value = ((float)rt_dataset->width * ROGUE_ISP_MERGE_SCALE_FACTOR) / 968bf215546Sopenharmony_ci (ROGUE_ISP_MERGE_UPPER_LIMIT_NUMERATOR - 969bf215546Sopenharmony_ci ROGUE_ISP_MERGE_LOWER_LIMIT_NUMERATOR); 970bf215546Sopenharmony_ci create_info->isp_merge_scale_x = fui(value); 971bf215546Sopenharmony_ci 972bf215546Sopenharmony_ci value = ((float)rt_dataset->height * ROGUE_ISP_MERGE_SCALE_FACTOR) / 973bf215546Sopenharmony_ci (ROGUE_ISP_MERGE_UPPER_LIMIT_NUMERATOR - 974bf215546Sopenharmony_ci ROGUE_ISP_MERGE_LOWER_LIMIT_NUMERATOR); 975bf215546Sopenharmony_ci create_info->isp_merge_scale_y = fui(value); 976bf215546Sopenharmony_ci } 977bf215546Sopenharmony_ci 978bf215546Sopenharmony_ci create_info->isp_mtile_size = 979bf215546Sopenharmony_ci pvr_rogue_get_cr_isp_mtile_size_val(dev_info, 980bf215546Sopenharmony_ci rt_dataset->samples, 981bf215546Sopenharmony_ci mtile_info); 982bf215546Sopenharmony_ci 983bf215546Sopenharmony_ci /* PPP register values. */ 984bf215546Sopenharmony_ci create_info->ppp_multi_sample_ctl = 985bf215546Sopenharmony_ci pvr_rogue_get_cr_multisamplectl_val(rt_dataset->samples, false); 986bf215546Sopenharmony_ci create_info->ppp_multi_sample_ctl_y_flipped = 987bf215546Sopenharmony_ci pvr_rogue_get_cr_multisamplectl_val(rt_dataset->samples, true); 988bf215546Sopenharmony_ci 989bf215546Sopenharmony_ci pvr_csb_pack (&create_info->ppp_screen, CR_PPP_SCREEN, value) { 990bf215546Sopenharmony_ci value.pixxmax = rt_dataset->width - 1; 991bf215546Sopenharmony_ci value.pixymax = rt_dataset->height - 1; 992bf215546Sopenharmony_ci } 993bf215546Sopenharmony_ci 994bf215546Sopenharmony_ci /* TE register values. */ 995bf215546Sopenharmony_ci create_info->te_aa = 996bf215546Sopenharmony_ci pvr_rogue_get_cr_te_aa_val(dev_info, rt_dataset->samples); 997bf215546Sopenharmony_ci 998bf215546Sopenharmony_ci pvr_csb_pack (&create_info->te_mtile1, CR_TE_MTILE1, value) { 999bf215546Sopenharmony_ci value.x1 = mtile_info->mtile_x1; 1000bf215546Sopenharmony_ci if (!PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format)) { 1001bf215546Sopenharmony_ci value.x2 = mtile_info->mtile_x2; 1002bf215546Sopenharmony_ci value.x3 = mtile_info->mtile_x3; 1003bf215546Sopenharmony_ci } 1004bf215546Sopenharmony_ci } 1005bf215546Sopenharmony_ci 1006bf215546Sopenharmony_ci pvr_csb_pack (&create_info->te_mtile2, CR_TE_MTILE2, value) { 1007bf215546Sopenharmony_ci value.y1 = mtile_info->mtile_y1; 1008bf215546Sopenharmony_ci if (!PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format)) { 1009bf215546Sopenharmony_ci value.y2 = mtile_info->mtile_y2; 1010bf215546Sopenharmony_ci value.y3 = mtile_info->mtile_y3; 1011bf215546Sopenharmony_ci } 1012bf215546Sopenharmony_ci } 1013bf215546Sopenharmony_ci 1014bf215546Sopenharmony_ci pvr_csb_pack (&create_info->te_screen, CR_TE_SCREEN, value) { 1015bf215546Sopenharmony_ci value.xmax = mtile_info->x_tile_max; 1016bf215546Sopenharmony_ci value.ymax = mtile_info->y_tile_max; 1017bf215546Sopenharmony_ci } 1018bf215546Sopenharmony_ci 1019bf215546Sopenharmony_ci /* Allocations and associated information. */ 1020bf215546Sopenharmony_ci create_info->vheap_table_dev_addr = rt_dataset->vheap_dev_addr; 1021bf215546Sopenharmony_ci create_info->rtc_dev_addr = rt_dataset->rtc_dev_addr; 1022bf215546Sopenharmony_ci 1023bf215546Sopenharmony_ci create_info->tpc_dev_addr = rt_dataset->tpc_bo->vma->dev_addr; 1024bf215546Sopenharmony_ci create_info->tpc_stride = rt_dataset->tpc_stride; 1025bf215546Sopenharmony_ci create_info->tpc_size = rt_dataset->tpc_size; 1026bf215546Sopenharmony_ci 1027bf215546Sopenharmony_ci STATIC_ASSERT(ARRAY_SIZE(create_info->rt_datas) == 1028bf215546Sopenharmony_ci ARRAY_SIZE(rt_dataset->rt_datas)); 1029bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(create_info->rt_datas); i++) { 1030bf215546Sopenharmony_ci create_info->rt_datas[i].pm_mlist_dev_addr = 1031bf215546Sopenharmony_ci rt_dataset->rt_datas[i].mlist_dev_addr; 1032bf215546Sopenharmony_ci create_info->rt_datas[i].macrotile_array_dev_addr = 1033bf215546Sopenharmony_ci rt_dataset->rt_datas[i].mta_dev_addr; 1034bf215546Sopenharmony_ci create_info->rt_datas[i].rgn_header_dev_addr = 1035bf215546Sopenharmony_ci rt_dataset->rt_datas[i].rgn_headers_dev_addr; 1036bf215546Sopenharmony_ci } 1037bf215546Sopenharmony_ci 1038bf215546Sopenharmony_ci create_info->rgn_header_size = 1039bf215546Sopenharmony_ci pvr_rt_get_isp_region_size(device, mtile_info); 1040bf215546Sopenharmony_ci 1041bf215546Sopenharmony_ci /* Miscellaneous. */ 1042bf215546Sopenharmony_ci create_info->mtile_stride = mtile_info->mtile_stride; 1043bf215546Sopenharmony_ci create_info->max_rts = rt_dataset->layers; 1044bf215546Sopenharmony_ci} 1045bf215546Sopenharmony_ci 1046bf215546Sopenharmony_ciVkResult 1047bf215546Sopenharmony_cipvr_render_target_dataset_create(struct pvr_device *device, 1048bf215546Sopenharmony_ci uint32_t width, 1049bf215546Sopenharmony_ci uint32_t height, 1050bf215546Sopenharmony_ci uint32_t samples, 1051bf215546Sopenharmony_ci uint32_t layers, 1052bf215546Sopenharmony_ci struct pvr_rt_dataset **const rt_dataset_out) 1053bf215546Sopenharmony_ci{ 1054bf215546Sopenharmony_ci const struct pvr_device_info *dev_info = &device->pdevice->dev_info; 1055bf215546Sopenharmony_ci struct pvr_winsys_rt_dataset_create_info rt_dataset_create_info; 1056bf215546Sopenharmony_ci struct pvr_rt_mtile_info mtile_info; 1057bf215546Sopenharmony_ci struct pvr_rt_dataset *rt_dataset; 1058bf215546Sopenharmony_ci VkResult result; 1059bf215546Sopenharmony_ci 1060bf215546Sopenharmony_ci assert(device->global_free_list); 1061bf215546Sopenharmony_ci assert(width <= rogue_get_render_size_max_x(dev_info)); 1062bf215546Sopenharmony_ci assert(height <= rogue_get_render_size_max_y(dev_info)); 1063bf215546Sopenharmony_ci assert(layers > 0 && layers <= PVR_MAX_FRAMEBUFFER_LAYERS); 1064bf215546Sopenharmony_ci 1065bf215546Sopenharmony_ci pvr_rt_mtile_info_init(device, &mtile_info, width, height, samples); 1066bf215546Sopenharmony_ci 1067bf215546Sopenharmony_ci rt_dataset = vk_zalloc(&device->vk.alloc, 1068bf215546Sopenharmony_ci sizeof(*rt_dataset), 1069bf215546Sopenharmony_ci 8, 1070bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 1071bf215546Sopenharmony_ci if (!rt_dataset) 1072bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 1073bf215546Sopenharmony_ci 1074bf215546Sopenharmony_ci rt_dataset->device = device; 1075bf215546Sopenharmony_ci rt_dataset->width = width; 1076bf215546Sopenharmony_ci rt_dataset->height = height; 1077bf215546Sopenharmony_ci rt_dataset->samples = samples; 1078bf215546Sopenharmony_ci rt_dataset->layers = layers; 1079bf215546Sopenharmony_ci rt_dataset->global_free_list = device->global_free_list; 1080bf215546Sopenharmony_ci 1081bf215546Sopenharmony_ci /* The maximum supported free list size is based on the assumption that this 1082bf215546Sopenharmony_ci * freelist (the "local" freelist) is always the minimum size required by 1083bf215546Sopenharmony_ci * the hardware. See the documentation of ROGUE_FREE_LIST_MAX_SIZE for more 1084bf215546Sopenharmony_ci * details. 1085bf215546Sopenharmony_ci */ 1086bf215546Sopenharmony_ci result = pvr_free_list_create(device, 1087bf215546Sopenharmony_ci rogue_get_min_free_list_size(dev_info), 1088bf215546Sopenharmony_ci rogue_get_min_free_list_size(dev_info), 1089bf215546Sopenharmony_ci 0 /* grow_size */, 1090bf215546Sopenharmony_ci 0 /* grow_threshold */, 1091bf215546Sopenharmony_ci rt_dataset->global_free_list, 1092bf215546Sopenharmony_ci &rt_dataset->local_free_list); 1093bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1094bf215546Sopenharmony_ci goto err_vk_free_rt_dataset; 1095bf215546Sopenharmony_ci 1096bf215546Sopenharmony_ci result = pvr_rt_vheap_rtc_data_init(device, rt_dataset, layers); 1097bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1098bf215546Sopenharmony_ci goto err_pvr_free_list_destroy; 1099bf215546Sopenharmony_ci 1100bf215546Sopenharmony_ci result = pvr_rt_tpc_data_init(device, rt_dataset, &mtile_info, layers); 1101bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1102bf215546Sopenharmony_ci goto err_pvr_rt_vheap_rtc_data_fini; 1103bf215546Sopenharmony_ci 1104bf215546Sopenharmony_ci result = pvr_rt_datas_init(device, 1105bf215546Sopenharmony_ci rt_dataset, 1106bf215546Sopenharmony_ci rt_dataset->global_free_list, 1107bf215546Sopenharmony_ci rt_dataset->local_free_list, 1108bf215546Sopenharmony_ci &mtile_info, 1109bf215546Sopenharmony_ci layers); 1110bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1111bf215546Sopenharmony_ci goto err_pvr_rt_tpc_data_fini; 1112bf215546Sopenharmony_ci 1113bf215546Sopenharmony_ci /* rt_dataset must be fully initialized by this point since 1114bf215546Sopenharmony_ci * pvr_rt_dataset_ws_create_info_init() depends on this. 1115bf215546Sopenharmony_ci */ 1116bf215546Sopenharmony_ci pvr_rt_dataset_ws_create_info_init(rt_dataset, 1117bf215546Sopenharmony_ci &mtile_info, 1118bf215546Sopenharmony_ci &rt_dataset_create_info); 1119bf215546Sopenharmony_ci 1120bf215546Sopenharmony_ci result = 1121bf215546Sopenharmony_ci device->ws->ops->render_target_dataset_create(device->ws, 1122bf215546Sopenharmony_ci &rt_dataset_create_info, 1123bf215546Sopenharmony_ci &rt_dataset->ws_rt_dataset); 1124bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1125bf215546Sopenharmony_ci goto err_pvr_rt_datas_fini; 1126bf215546Sopenharmony_ci 1127bf215546Sopenharmony_ci *rt_dataset_out = rt_dataset; 1128bf215546Sopenharmony_ci 1129bf215546Sopenharmony_ci return VK_SUCCESS; 1130bf215546Sopenharmony_ci 1131bf215546Sopenharmony_cierr_pvr_rt_datas_fini: 1132bf215546Sopenharmony_ci pvr_rt_datas_fini(rt_dataset); 1133bf215546Sopenharmony_ci 1134bf215546Sopenharmony_cierr_pvr_rt_tpc_data_fini: 1135bf215546Sopenharmony_ci pvr_rt_tpc_data_fini(rt_dataset); 1136bf215546Sopenharmony_ci 1137bf215546Sopenharmony_cierr_pvr_rt_vheap_rtc_data_fini: 1138bf215546Sopenharmony_ci pvr_rt_vheap_rtc_data_fini(rt_dataset); 1139bf215546Sopenharmony_ci 1140bf215546Sopenharmony_cierr_pvr_free_list_destroy: 1141bf215546Sopenharmony_ci pvr_free_list_destroy(rt_dataset->local_free_list); 1142bf215546Sopenharmony_ci 1143bf215546Sopenharmony_cierr_vk_free_rt_dataset: 1144bf215546Sopenharmony_ci vk_free(&device->vk.alloc, rt_dataset); 1145bf215546Sopenharmony_ci 1146bf215546Sopenharmony_ci return result; 1147bf215546Sopenharmony_ci} 1148bf215546Sopenharmony_ci 1149bf215546Sopenharmony_civoid pvr_render_target_dataset_destroy(struct pvr_rt_dataset *rt_dataset) 1150bf215546Sopenharmony_ci{ 1151bf215546Sopenharmony_ci struct pvr_device *device = rt_dataset->device; 1152bf215546Sopenharmony_ci 1153bf215546Sopenharmony_ci device->ws->ops->render_target_dataset_destroy(rt_dataset->ws_rt_dataset); 1154bf215546Sopenharmony_ci 1155bf215546Sopenharmony_ci pvr_rt_datas_fini(rt_dataset); 1156bf215546Sopenharmony_ci pvr_rt_tpc_data_fini(rt_dataset); 1157bf215546Sopenharmony_ci pvr_rt_vheap_rtc_data_fini(rt_dataset); 1158bf215546Sopenharmony_ci 1159bf215546Sopenharmony_ci pvr_free_list_destroy(rt_dataset->local_free_list); 1160bf215546Sopenharmony_ci 1161bf215546Sopenharmony_ci vk_free(&device->vk.alloc, rt_dataset); 1162bf215546Sopenharmony_ci} 1163bf215546Sopenharmony_ci 1164bf215546Sopenharmony_cistatic void 1165bf215546Sopenharmony_cipvr_render_job_ws_geometry_state_init(struct pvr_render_ctx *ctx, 1166bf215546Sopenharmony_ci struct pvr_render_job *job, 1167bf215546Sopenharmony_ci struct pvr_winsys_geometry_state *state) 1168bf215546Sopenharmony_ci{ 1169bf215546Sopenharmony_ci const struct pvr_device_info *dev_info = &ctx->device->pdevice->dev_info; 1170bf215546Sopenharmony_ci 1171bf215546Sopenharmony_ci /* FIXME: Should this just be done unconditionally? The firmware will just 1172bf215546Sopenharmony_ci * ignore the value anyway. 1173bf215546Sopenharmony_ci */ 1174bf215546Sopenharmony_ci if (PVR_HAS_QUIRK(dev_info, 56279)) { 1175bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.pds_ctrl, CR_PDS_CTRL, value) { 1176bf215546Sopenharmony_ci value.max_num_vdm_tasks = rogue_get_max_num_vdm_pds_tasks(dev_info); 1177bf215546Sopenharmony_ci } 1178bf215546Sopenharmony_ci } else { 1179bf215546Sopenharmony_ci state->regs.pds_ctrl = 0; 1180bf215546Sopenharmony_ci } 1181bf215546Sopenharmony_ci 1182bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.ppp_ctrl, CR_PPP_CTRL, value) { 1183bf215546Sopenharmony_ci value.wclampen = true; 1184bf215546Sopenharmony_ci value.fixed_point_format = 1; 1185bf215546Sopenharmony_ci } 1186bf215546Sopenharmony_ci 1187bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.te_psg, CR_TE_PSG, value) { 1188bf215546Sopenharmony_ci value.completeonterminate = job->geometry_terminate; 1189bf215546Sopenharmony_ci 1190bf215546Sopenharmony_ci value.region_stride = job->rt_dataset->rgn_headers_stride / 1191bf215546Sopenharmony_ci PVRX(CR_TE_PSG_REGION_STRIDE_UNIT_SIZE); 1192bf215546Sopenharmony_ci 1193bf215546Sopenharmony_ci value.forcenewstate = PVR_HAS_QUIRK(dev_info, 52942); 1194bf215546Sopenharmony_ci } 1195bf215546Sopenharmony_ci 1196bf215546Sopenharmony_ci /* The set up of CR_TPU must be identical to 1197bf215546Sopenharmony_ci * pvr_render_job_ws_fragment_state_init(). 1198bf215546Sopenharmony_ci */ 1199bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.tpu, CR_TPU, value) { 1200bf215546Sopenharmony_ci value.tag_cem_4k_face_packing = true; 1201bf215546Sopenharmony_ci } 1202bf215546Sopenharmony_ci 1203bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.tpu_border_colour_table, 1204bf215546Sopenharmony_ci CR_TPU_BORDER_COLOUR_TABLE_VDM, 1205bf215546Sopenharmony_ci value) { 1206bf215546Sopenharmony_ci value.border_colour_table_address = job->border_colour_table_addr; 1207bf215546Sopenharmony_ci } 1208bf215546Sopenharmony_ci 1209bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.vdm_ctrl_stream_base, 1210bf215546Sopenharmony_ci CR_VDM_CTRL_STREAM_BASE, 1211bf215546Sopenharmony_ci value) { 1212bf215546Sopenharmony_ci value.addr = job->ctrl_stream_addr; 1213bf215546Sopenharmony_ci } 1214bf215546Sopenharmony_ci 1215bf215546Sopenharmony_ci /* Set up the USC common size for the context switch resume/load program 1216bf215546Sopenharmony_ci * (ctx->ctx_switch.programs[i].sr->pds_load_program), which was created 1217bf215546Sopenharmony_ci * as part of the render context. 1218bf215546Sopenharmony_ci */ 1219bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.vdm_ctx_resume_task0_size, 1220bf215546Sopenharmony_ci VDMCTRL_PDS_STATE0, 1221bf215546Sopenharmony_ci value) { 1222bf215546Sopenharmony_ci /* Calculate the size in bytes. */ 1223bf215546Sopenharmony_ci const uint16_t shared_registers_size = job->max_shared_registers * 4; 1224bf215546Sopenharmony_ci 1225bf215546Sopenharmony_ci value.usc_common_size = 1226bf215546Sopenharmony_ci DIV_ROUND_UP(shared_registers_size, 1227bf215546Sopenharmony_ci PVRX(VDMCTRL_PDS_STATE0_USC_COMMON_SIZE_UNIT_SIZE)); 1228bf215546Sopenharmony_ci }; 1229bf215546Sopenharmony_ci 1230bf215546Sopenharmony_ci state->flags = 0; 1231bf215546Sopenharmony_ci 1232bf215546Sopenharmony_ci if (!job->rt_dataset->need_frag) 1233bf215546Sopenharmony_ci state->flags |= PVR_WINSYS_GEOM_FLAG_FIRST_GEOMETRY; 1234bf215546Sopenharmony_ci 1235bf215546Sopenharmony_ci if (job->geometry_terminate) 1236bf215546Sopenharmony_ci state->flags |= PVR_WINSYS_GEOM_FLAG_LAST_GEOMETRY; 1237bf215546Sopenharmony_ci 1238bf215546Sopenharmony_ci if (job->frag_uses_atomic_ops) 1239bf215546Sopenharmony_ci state->flags |= PVR_WINSYS_GEOM_FLAG_SINGLE_CORE; 1240bf215546Sopenharmony_ci} 1241bf215546Sopenharmony_ci 1242bf215546Sopenharmony_cistatic inline void 1243bf215546Sopenharmony_cipvr_get_isp_num_tiles_xy(const struct pvr_device_info *dev_info, 1244bf215546Sopenharmony_ci uint32_t samples, 1245bf215546Sopenharmony_ci uint32_t width, 1246bf215546Sopenharmony_ci uint32_t height, 1247bf215546Sopenharmony_ci uint32_t *const x_out, 1248bf215546Sopenharmony_ci uint32_t *const y_out) 1249bf215546Sopenharmony_ci{ 1250bf215546Sopenharmony_ci uint32_t tile_samples_x; 1251bf215546Sopenharmony_ci uint32_t tile_samples_y; 1252bf215546Sopenharmony_ci uint32_t scale_x; 1253bf215546Sopenharmony_ci uint32_t scale_y; 1254bf215546Sopenharmony_ci 1255bf215546Sopenharmony_ci rogue_get_isp_samples_per_tile_xy(dev_info, 1256bf215546Sopenharmony_ci samples, 1257bf215546Sopenharmony_ci &tile_samples_x, 1258bf215546Sopenharmony_ci &tile_samples_y); 1259bf215546Sopenharmony_ci 1260bf215546Sopenharmony_ci switch (samples) { 1261bf215546Sopenharmony_ci case 1: 1262bf215546Sopenharmony_ci scale_x = 1; 1263bf215546Sopenharmony_ci scale_y = 1; 1264bf215546Sopenharmony_ci break; 1265bf215546Sopenharmony_ci case 2: 1266bf215546Sopenharmony_ci scale_x = 1; 1267bf215546Sopenharmony_ci scale_y = 2; 1268bf215546Sopenharmony_ci break; 1269bf215546Sopenharmony_ci case 4: 1270bf215546Sopenharmony_ci scale_x = 2; 1271bf215546Sopenharmony_ci scale_y = 2; 1272bf215546Sopenharmony_ci break; 1273bf215546Sopenharmony_ci case 8: 1274bf215546Sopenharmony_ci scale_x = 2; 1275bf215546Sopenharmony_ci scale_y = 4; 1276bf215546Sopenharmony_ci break; 1277bf215546Sopenharmony_ci default: 1278bf215546Sopenharmony_ci unreachable("Unsupported number of samples"); 1279bf215546Sopenharmony_ci } 1280bf215546Sopenharmony_ci 1281bf215546Sopenharmony_ci *x_out = DIV_ROUND_UP(width * scale_x, tile_samples_x); 1282bf215546Sopenharmony_ci *y_out = DIV_ROUND_UP(height * scale_y, tile_samples_y); 1283bf215546Sopenharmony_ci 1284bf215546Sopenharmony_ci if (PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format)) { 1285bf215546Sopenharmony_ci assert(PVR_GET_FEATURE_VALUE(dev_info, 1286bf215546Sopenharmony_ci simple_parameter_format_version, 1287bf215546Sopenharmony_ci 0U) == 2U); 1288bf215546Sopenharmony_ci /* Align to a 2x2 tile block. */ 1289bf215546Sopenharmony_ci *x_out = ALIGN_POT(*x_out, 2); 1290bf215546Sopenharmony_ci *y_out = ALIGN_POT(*y_out, 2); 1291bf215546Sopenharmony_ci } 1292bf215546Sopenharmony_ci} 1293bf215546Sopenharmony_ci 1294bf215546Sopenharmony_cistatic void 1295bf215546Sopenharmony_cipvr_render_job_ws_fragment_state_init(struct pvr_render_ctx *ctx, 1296bf215546Sopenharmony_ci struct pvr_render_job *job, 1297bf215546Sopenharmony_ci struct pvr_winsys_fragment_state *state) 1298bf215546Sopenharmony_ci{ 1299bf215546Sopenharmony_ci const enum PVRX(CR_ISP_AA_MODE_TYPE) 1300bf215546Sopenharmony_ci isp_aa_mode = pvr_cr_isp_aa_mode_type(job->samples); 1301bf215546Sopenharmony_ci const struct pvr_device_runtime_info *dev_runtime_info = 1302bf215546Sopenharmony_ci &ctx->device->pdevice->dev_runtime_info; 1303bf215546Sopenharmony_ci const struct pvr_device_info *dev_info = &ctx->device->pdevice->dev_info; 1304bf215546Sopenharmony_ci uint32_t isp_ctl; 1305bf215546Sopenharmony_ci 1306bf215546Sopenharmony_ci /* FIXME: what to do when job->run_frag is false? */ 1307bf215546Sopenharmony_ci 1308bf215546Sopenharmony_ci /* FIXME: pass in the number of samples rather than isp_aa_mode? */ 1309bf215546Sopenharmony_ci pvr_setup_tiles_in_flight(dev_info, 1310bf215546Sopenharmony_ci dev_runtime_info, 1311bf215546Sopenharmony_ci isp_aa_mode, 1312bf215546Sopenharmony_ci job->pixel_output_width, 1313bf215546Sopenharmony_ci false, 1314bf215546Sopenharmony_ci job->max_tiles_in_flight, 1315bf215546Sopenharmony_ci &isp_ctl, 1316bf215546Sopenharmony_ci &state->regs.usc_pixel_output_ctrl); 1317bf215546Sopenharmony_ci 1318bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.isp_ctl, CR_ISP_CTL, value) { 1319bf215546Sopenharmony_ci value.sample_pos = true; 1320bf215546Sopenharmony_ci 1321bf215546Sopenharmony_ci /* FIXME: There are a number of things that cause this to be set, this 1322bf215546Sopenharmony_ci * is just one of them. 1323bf215546Sopenharmony_ci */ 1324bf215546Sopenharmony_ci value.process_empty_tiles = job->process_empty_tiles; 1325bf215546Sopenharmony_ci } 1326bf215546Sopenharmony_ci 1327bf215546Sopenharmony_ci /* FIXME: When pvr_setup_tiles_in_flight() is refactored it might be 1328bf215546Sopenharmony_ci * possible to fully pack CR_ISP_CTL above rather than having to OR in part 1329bf215546Sopenharmony_ci * of the value. 1330bf215546Sopenharmony_ci */ 1331bf215546Sopenharmony_ci state->regs.isp_ctl |= isp_ctl; 1332bf215546Sopenharmony_ci 1333bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.isp_aa, CR_ISP_AA, value) { 1334bf215546Sopenharmony_ci value.mode = isp_aa_mode; 1335bf215546Sopenharmony_ci } 1336bf215546Sopenharmony_ci 1337bf215546Sopenharmony_ci /* The set up of CR_TPU must be identical to 1338bf215546Sopenharmony_ci * pvr_render_job_ws_geometry_state_init(). 1339bf215546Sopenharmony_ci */ 1340bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.tpu, CR_TPU, value) { 1341bf215546Sopenharmony_ci value.tag_cem_4k_face_packing = true; 1342bf215546Sopenharmony_ci } 1343bf215546Sopenharmony_ci 1344bf215546Sopenharmony_ci if (PVR_HAS_FEATURE(dev_info, cluster_grouping) && 1345bf215546Sopenharmony_ci PVR_HAS_FEATURE(dev_info, slc_mcu_cache_controls) && 1346bf215546Sopenharmony_ci dev_runtime_info->num_phantoms > 1 && job->frag_uses_atomic_ops) { 1347bf215546Sopenharmony_ci /* Each phantom has its own MCU, so atomicity can only be guaranteed 1348bf215546Sopenharmony_ci * when all work items are processed on the same phantom. This means we 1349bf215546Sopenharmony_ci * need to disable all USCs other than those of the first phantom, which 1350bf215546Sopenharmony_ci * has 4 clusters. Note that we only need to do this for atomic 1351bf215546Sopenharmony_ci * operations in fragment shaders, since hardware prevents the TA to run 1352bf215546Sopenharmony_ci * on more than one phantom anyway. 1353bf215546Sopenharmony_ci */ 1354bf215546Sopenharmony_ci state->regs.pixel_phantom = 0xF; 1355bf215546Sopenharmony_ci } else { 1356bf215546Sopenharmony_ci state->regs.pixel_phantom = 0; 1357bf215546Sopenharmony_ci } 1358bf215546Sopenharmony_ci 1359bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.isp_bgobjvals, CR_ISP_BGOBJVALS, value) { 1360bf215546Sopenharmony_ci value.enablebgtag = job->enable_bg_tag; 1361bf215546Sopenharmony_ci 1362bf215546Sopenharmony_ci value.mask = true; 1363bf215546Sopenharmony_ci 1364bf215546Sopenharmony_ci /* FIXME: Hard code this for now as we don't currently support any 1365bf215546Sopenharmony_ci * stencil image formats. 1366bf215546Sopenharmony_ci */ 1367bf215546Sopenharmony_ci value.stencil = 0xFF; 1368bf215546Sopenharmony_ci } 1369bf215546Sopenharmony_ci 1370bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.isp_bgobjdepth, CR_ISP_BGOBJDEPTH, value) { 1371bf215546Sopenharmony_ci /* FIXME: This is suitable for the single depth format the driver 1372bf215546Sopenharmony_ci * currently supports, but may need updating to handle other depth 1373bf215546Sopenharmony_ci * formats. 1374bf215546Sopenharmony_ci */ 1375bf215546Sopenharmony_ci value.value = fui(job->depth_clear_value); 1376bf215546Sopenharmony_ci } 1377bf215546Sopenharmony_ci 1378bf215546Sopenharmony_ci /* FIXME: Some additional set up needed to support depth and stencil 1379bf215546Sopenharmony_ci * load/store operations. 1380bf215546Sopenharmony_ci */ 1381bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.isp_zlsctl, CR_ISP_ZLSCTL, value) { 1382bf215546Sopenharmony_ci uint32_t aligned_width = 1383bf215546Sopenharmony_ci ALIGN_POT(job->depth_physical_width, ROGUE_IPF_TILE_SIZE_PIXELS); 1384bf215546Sopenharmony_ci uint32_t aligned_height = 1385bf215546Sopenharmony_ci ALIGN_POT(job->depth_physical_height, ROGUE_IPF_TILE_SIZE_PIXELS); 1386bf215546Sopenharmony_ci 1387bf215546Sopenharmony_ci pvr_get_isp_num_tiles_xy(dev_info, 1388bf215546Sopenharmony_ci job->samples, 1389bf215546Sopenharmony_ci aligned_width, 1390bf215546Sopenharmony_ci aligned_height, 1391bf215546Sopenharmony_ci &value.zlsextent_x_z, 1392bf215546Sopenharmony_ci &value.zlsextent_y_z); 1393bf215546Sopenharmony_ci value.zlsextent_x_z -= 1; 1394bf215546Sopenharmony_ci value.zlsextent_y_z -= 1; 1395bf215546Sopenharmony_ci 1396bf215546Sopenharmony_ci if (job->depth_memlayout == PVR_MEMLAYOUT_TWIDDLED) { 1397bf215546Sopenharmony_ci value.loadtwiddled = true; 1398bf215546Sopenharmony_ci value.storetwiddled = true; 1399bf215546Sopenharmony_ci } 1400bf215546Sopenharmony_ci 1401bf215546Sopenharmony_ci /* FIXME: This is suitable for the single depth format the driver 1402bf215546Sopenharmony_ci * currently supports, but may need updating to handle other depth 1403bf215546Sopenharmony_ci * formats. 1404bf215546Sopenharmony_ci */ 1405bf215546Sopenharmony_ci assert(job->depth_vk_format == VK_FORMAT_D32_SFLOAT); 1406bf215546Sopenharmony_ci value.zloadformat = PVRX(CR_ZLOADFORMAT_TYPE_F32Z); 1407bf215546Sopenharmony_ci value.zstoreformat = PVRX(CR_ZSTOREFORMAT_TYPE_F32Z); 1408bf215546Sopenharmony_ci } 1409bf215546Sopenharmony_ci 1410bf215546Sopenharmony_ci if (PVR_HAS_FEATURE(dev_info, zls_subtile)) { 1411bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.isp_zls_pixels, CR_ISP_ZLS_PIXELS, value) { 1412bf215546Sopenharmony_ci value.x = job->depth_stride - 1; 1413bf215546Sopenharmony_ci value.y = job->depth_height - 1; 1414bf215546Sopenharmony_ci } 1415bf215546Sopenharmony_ci } else { 1416bf215546Sopenharmony_ci state->regs.isp_zls_pixels = 0; 1417bf215546Sopenharmony_ci } 1418bf215546Sopenharmony_ci 1419bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.isp_zload_store_base, CR_ISP_ZLOAD_BASE, value) { 1420bf215546Sopenharmony_ci value.addr = job->depth_addr; 1421bf215546Sopenharmony_ci } 1422bf215546Sopenharmony_ci 1423bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.isp_stencil_load_store_base, 1424bf215546Sopenharmony_ci CR_ISP_STENCIL_LOAD_BASE, 1425bf215546Sopenharmony_ci value) { 1426bf215546Sopenharmony_ci value.addr = job->stencil_addr; 1427bf215546Sopenharmony_ci 1428bf215546Sopenharmony_ci /* FIXME: May need to set value.enable to true. */ 1429bf215546Sopenharmony_ci } 1430bf215546Sopenharmony_ci 1431bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.tpu_border_colour_table, 1432bf215546Sopenharmony_ci CR_TPU_BORDER_COLOUR_TABLE_PDM, 1433bf215546Sopenharmony_ci value) { 1434bf215546Sopenharmony_ci value.border_colour_table_address = job->border_colour_table_addr; 1435bf215546Sopenharmony_ci } 1436bf215546Sopenharmony_ci 1437bf215546Sopenharmony_ci state->regs.isp_oclqry_base = 0; 1438bf215546Sopenharmony_ci 1439bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.isp_dbias_base, CR_ISP_DBIAS_BASE, value) { 1440bf215546Sopenharmony_ci value.addr = job->depth_bias_table_addr; 1441bf215546Sopenharmony_ci } 1442bf215546Sopenharmony_ci 1443bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.isp_scissor_base, CR_ISP_SCISSOR_BASE, value) { 1444bf215546Sopenharmony_ci value.addr = job->scissor_table_addr; 1445bf215546Sopenharmony_ci } 1446bf215546Sopenharmony_ci 1447bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.event_pixel_pds_info, 1448bf215546Sopenharmony_ci CR_EVENT_PIXEL_PDS_INFO, 1449bf215546Sopenharmony_ci value) { 1450bf215546Sopenharmony_ci value.const_size = 1451bf215546Sopenharmony_ci DIV_ROUND_UP(ctx->device->pixel_event_data_size_in_dwords, 1452bf215546Sopenharmony_ci PVRX(CR_EVENT_PIXEL_PDS_INFO_CONST_SIZE_UNIT_SIZE)); 1453bf215546Sopenharmony_ci value.temp_stride = 0; 1454bf215546Sopenharmony_ci value.usc_sr_size = 1455bf215546Sopenharmony_ci DIV_ROUND_UP(PVR_STATE_PBE_DWORDS, 1456bf215546Sopenharmony_ci PVRX(CR_EVENT_PIXEL_PDS_INFO_USC_SR_SIZE_UNIT_SIZE)); 1457bf215546Sopenharmony_ci } 1458bf215546Sopenharmony_ci 1459bf215546Sopenharmony_ci pvr_csb_pack (&state->regs.event_pixel_pds_data, 1460bf215546Sopenharmony_ci CR_EVENT_PIXEL_PDS_DATA, 1461bf215546Sopenharmony_ci value) { 1462bf215546Sopenharmony_ci value.addr = PVR_DEV_ADDR(job->pds_pixel_event_data_offset); 1463bf215546Sopenharmony_ci } 1464bf215546Sopenharmony_ci 1465bf215546Sopenharmony_ci STATIC_ASSERT(ARRAY_SIZE(state->regs.pbe_word) == 1466bf215546Sopenharmony_ci ARRAY_SIZE(job->pbe_reg_words)); 1467bf215546Sopenharmony_ci STATIC_ASSERT(ARRAY_SIZE(state->regs.pbe_word[0]) == 1468bf215546Sopenharmony_ci ARRAY_SIZE(job->pbe_reg_words[0])); 1469bf215546Sopenharmony_ci 1470bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(job->pbe_reg_words); i++) { 1471bf215546Sopenharmony_ci state->regs.pbe_word[i][0] = job->pbe_reg_words[i][0]; 1472bf215546Sopenharmony_ci state->regs.pbe_word[i][1] = job->pbe_reg_words[i][1]; 1473bf215546Sopenharmony_ci state->regs.pbe_word[i][2] = job->pbe_reg_words[i][2]; 1474bf215546Sopenharmony_ci } 1475bf215546Sopenharmony_ci 1476bf215546Sopenharmony_ci STATIC_ASSERT(__same_type(state->regs.pds_bgnd, job->pds_bgnd_reg_values)); 1477bf215546Sopenharmony_ci typed_memcpy(state->regs.pds_bgnd, 1478bf215546Sopenharmony_ci job->pds_bgnd_reg_values, 1479bf215546Sopenharmony_ci ARRAY_SIZE(state->regs.pds_bgnd)); 1480bf215546Sopenharmony_ci 1481bf215546Sopenharmony_ci memset(state->regs.pds_pr_bgnd, 0, sizeof(state->regs.pds_pr_bgnd)); 1482bf215546Sopenharmony_ci 1483bf215546Sopenharmony_ci /* FIXME: Merge geometry and fragment flags into a single flags member? */ 1484bf215546Sopenharmony_ci /* FIXME: move to its own function? */ 1485bf215546Sopenharmony_ci state->flags = 0; 1486bf215546Sopenharmony_ci 1487bf215546Sopenharmony_ci if (job->depth_addr.addr) 1488bf215546Sopenharmony_ci state->flags |= PVR_WINSYS_FRAG_FLAG_DEPTH_BUFFER_PRESENT; 1489bf215546Sopenharmony_ci 1490bf215546Sopenharmony_ci if (job->stencil_addr.addr) 1491bf215546Sopenharmony_ci state->flags |= PVR_WINSYS_FRAG_FLAG_STENCIL_BUFFER_PRESENT; 1492bf215546Sopenharmony_ci 1493bf215546Sopenharmony_ci if (job->disable_compute_overlap) 1494bf215546Sopenharmony_ci state->flags |= PVR_WINSYS_FRAG_FLAG_PREVENT_CDM_OVERLAP; 1495bf215546Sopenharmony_ci 1496bf215546Sopenharmony_ci if (job->frag_uses_atomic_ops) 1497bf215546Sopenharmony_ci state->flags |= PVR_WINSYS_FRAG_FLAG_SINGLE_CORE; 1498bf215546Sopenharmony_ci 1499bf215546Sopenharmony_ci state->zls_stride = job->depth_layer_size; 1500bf215546Sopenharmony_ci state->sls_stride = job->depth_layer_size; 1501bf215546Sopenharmony_ci} 1502bf215546Sopenharmony_ci 1503bf215546Sopenharmony_cistatic void pvr_render_job_ws_submit_info_init( 1504bf215546Sopenharmony_ci struct pvr_render_ctx *ctx, 1505bf215546Sopenharmony_ci struct pvr_render_job *job, 1506bf215546Sopenharmony_ci const struct pvr_winsys_job_bo *bos, 1507bf215546Sopenharmony_ci uint32_t bo_count, 1508bf215546Sopenharmony_ci struct vk_sync **waits, 1509bf215546Sopenharmony_ci uint32_t wait_count, 1510bf215546Sopenharmony_ci uint32_t *stage_flags, 1511bf215546Sopenharmony_ci struct pvr_winsys_render_submit_info *submit_info) 1512bf215546Sopenharmony_ci{ 1513bf215546Sopenharmony_ci memset(submit_info, 0, sizeof(*submit_info)); 1514bf215546Sopenharmony_ci 1515bf215546Sopenharmony_ci submit_info->rt_dataset = job->rt_dataset->ws_rt_dataset; 1516bf215546Sopenharmony_ci submit_info->rt_data_idx = job->rt_dataset->rt_data_idx; 1517bf215546Sopenharmony_ci 1518bf215546Sopenharmony_ci submit_info->frame_num = ctx->device->global_queue_present_count; 1519bf215546Sopenharmony_ci submit_info->job_num = ctx->device->global_queue_job_count; 1520bf215546Sopenharmony_ci 1521bf215546Sopenharmony_ci submit_info->run_frag = job->run_frag; 1522bf215546Sopenharmony_ci 1523bf215546Sopenharmony_ci submit_info->bos = bos; 1524bf215546Sopenharmony_ci submit_info->bo_count = bo_count; 1525bf215546Sopenharmony_ci 1526bf215546Sopenharmony_ci submit_info->waits = waits; 1527bf215546Sopenharmony_ci submit_info->wait_count = wait_count; 1528bf215546Sopenharmony_ci submit_info->stage_flags = stage_flags; 1529bf215546Sopenharmony_ci 1530bf215546Sopenharmony_ci /* FIXME: add WSI image bos. */ 1531bf215546Sopenharmony_ci 1532bf215546Sopenharmony_ci pvr_render_job_ws_geometry_state_init(ctx, job, &submit_info->geometry); 1533bf215546Sopenharmony_ci pvr_render_job_ws_fragment_state_init(ctx, job, &submit_info->fragment); 1534bf215546Sopenharmony_ci 1535bf215546Sopenharmony_ci /* These values are expected to match. */ 1536bf215546Sopenharmony_ci assert(submit_info->geometry.regs.tpu == submit_info->fragment.regs.tpu); 1537bf215546Sopenharmony_ci} 1538bf215546Sopenharmony_ci 1539bf215546Sopenharmony_ciVkResult pvr_render_job_submit(struct pvr_render_ctx *ctx, 1540bf215546Sopenharmony_ci struct pvr_render_job *job, 1541bf215546Sopenharmony_ci const struct pvr_winsys_job_bo *bos, 1542bf215546Sopenharmony_ci uint32_t bo_count, 1543bf215546Sopenharmony_ci struct vk_sync **waits, 1544bf215546Sopenharmony_ci uint32_t wait_count, 1545bf215546Sopenharmony_ci uint32_t *stage_flags, 1546bf215546Sopenharmony_ci struct vk_sync *signal_sync_geom, 1547bf215546Sopenharmony_ci struct vk_sync *signal_sync_frag) 1548bf215546Sopenharmony_ci{ 1549bf215546Sopenharmony_ci struct pvr_rt_dataset *rt_dataset = job->rt_dataset; 1550bf215546Sopenharmony_ci struct pvr_winsys_render_submit_info submit_info; 1551bf215546Sopenharmony_ci struct pvr_device *device = ctx->device; 1552bf215546Sopenharmony_ci VkResult result; 1553bf215546Sopenharmony_ci 1554bf215546Sopenharmony_ci pvr_render_job_ws_submit_info_init(ctx, 1555bf215546Sopenharmony_ci job, 1556bf215546Sopenharmony_ci bos, 1557bf215546Sopenharmony_ci bo_count, 1558bf215546Sopenharmony_ci waits, 1559bf215546Sopenharmony_ci wait_count, 1560bf215546Sopenharmony_ci stage_flags, 1561bf215546Sopenharmony_ci &submit_info); 1562bf215546Sopenharmony_ci 1563bf215546Sopenharmony_ci result = device->ws->ops->render_submit(ctx->ws_ctx, 1564bf215546Sopenharmony_ci &submit_info, 1565bf215546Sopenharmony_ci signal_sync_geom, 1566bf215546Sopenharmony_ci signal_sync_frag); 1567bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1568bf215546Sopenharmony_ci return result; 1569bf215546Sopenharmony_ci 1570bf215546Sopenharmony_ci if (job->run_frag) { 1571bf215546Sopenharmony_ci /* Move to the next render target data now that a fragment job has been 1572bf215546Sopenharmony_ci * successfully submitted. This will allow the next geometry job to be 1573bf215546Sopenharmony_ci * submitted to been run in parallel with it. 1574bf215546Sopenharmony_ci */ 1575bf215546Sopenharmony_ci rt_dataset->rt_data_idx = 1576bf215546Sopenharmony_ci (rt_dataset->rt_data_idx + 1) % ARRAY_SIZE(rt_dataset->rt_datas); 1577bf215546Sopenharmony_ci 1578bf215546Sopenharmony_ci rt_dataset->need_frag = false; 1579bf215546Sopenharmony_ci } else { 1580bf215546Sopenharmony_ci rt_dataset->need_frag = true; 1581bf215546Sopenharmony_ci } 1582bf215546Sopenharmony_ci 1583bf215546Sopenharmony_ci return VK_SUCCESS; 1584bf215546Sopenharmony_ci} 1585