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 <stddef.h> 27bf215546Sopenharmony_ci#include <stdint.h> 28bf215546Sopenharmony_ci#include <vulkan/vulkan.h> 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "hwdef/rogue_hw_utils.h" 31bf215546Sopenharmony_ci#include "pvr_bo.h" 32bf215546Sopenharmony_ci#include "pvr_cdm_load_sr.h" 33bf215546Sopenharmony_ci#include "pvr_csb.h" 34bf215546Sopenharmony_ci#include "pvr_job_context.h" 35bf215546Sopenharmony_ci#include "pvr_pds.h" 36bf215546Sopenharmony_ci#include "pvr_private.h" 37bf215546Sopenharmony_ci#include "pvr_transfer_eot.h" 38bf215546Sopenharmony_ci#include "pvr_types.h" 39bf215546Sopenharmony_ci#include "pvr_vdm_load_sr.h" 40bf215546Sopenharmony_ci#include "pvr_vdm_store_sr.h" 41bf215546Sopenharmony_ci#include "pvr_winsys.h" 42bf215546Sopenharmony_ci#include "util/macros.h" 43bf215546Sopenharmony_ci#include "vk_alloc.h" 44bf215546Sopenharmony_ci#include "vk_log.h" 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci/* TODO: Is there some way to ensure the Vulkan driver doesn't exceed this 47bf215546Sopenharmony_ci * value when constructing the control stream? 48bf215546Sopenharmony_ci */ 49bf215546Sopenharmony_ci/* The VDM callstack is used by the hardware to implement control stream links 50bf215546Sopenharmony_ci * with a return, i.e. sub-control streams/subroutines. This value specifies the 51bf215546Sopenharmony_ci * maximum callstack depth. 52bf215546Sopenharmony_ci */ 53bf215546Sopenharmony_ci#define PVR_VDM_CALLSTACK_MAX_DEPTH 1U 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci#define ROGUE_PDS_TASK_PROGRAM_SIZE 256U 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_cistatic VkResult pvr_ctx_reset_cmd_init(struct pvr_device *device, 58bf215546Sopenharmony_ci struct pvr_reset_cmd *const reset_cmd) 59bf215546Sopenharmony_ci{ 60bf215546Sopenharmony_ci const struct pvr_device_info *dev_info = &device->pdevice->dev_info; 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci /* The reset framework depends on compute support in the hw. */ 63bf215546Sopenharmony_ci assert(PVR_HAS_FEATURE(dev_info, compute)); 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci if (PVR_HAS_QUIRK(dev_info, 51764)) 66bf215546Sopenharmony_ci pvr_finishme("Missing reset support for brn51764"); 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci if (PVR_HAS_QUIRK(dev_info, 58839)) 69bf215546Sopenharmony_ci pvr_finishme("Missing reset support for brn58839"); 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci return VK_SUCCESS; 72bf215546Sopenharmony_ci} 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_cistatic void pvr_ctx_reset_cmd_fini(struct pvr_device *device, 75bf215546Sopenharmony_ci struct pvr_reset_cmd *reset_cmd) 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci{ 78bf215546Sopenharmony_ci /* TODO: reset command cleanup. */ 79bf215546Sopenharmony_ci} 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_cistatic VkResult pvr_pds_pt_store_program_create_and_upload( 82bf215546Sopenharmony_ci struct pvr_device *device, 83bf215546Sopenharmony_ci struct pvr_bo *pt_bo, 84bf215546Sopenharmony_ci uint32_t pt_bo_size, 85bf215546Sopenharmony_ci struct pvr_pds_upload *const pds_upload_out) 86bf215546Sopenharmony_ci{ 87bf215546Sopenharmony_ci struct pvr_pds_stream_out_terminate_program program = { 0 }; 88bf215546Sopenharmony_ci const struct pvr_device_info *dev_info = &device->pdevice->dev_info; 89bf215546Sopenharmony_ci const uint32_t cache_line_size = rogue_get_slc_cache_line_size(dev_info); 90bf215546Sopenharmony_ci size_t staging_buffer_size; 91bf215546Sopenharmony_ci uint32_t *staging_buffer; 92bf215546Sopenharmony_ci uint32_t *data_buffer; 93bf215546Sopenharmony_ci uint32_t *code_buffer; 94bf215546Sopenharmony_ci VkResult result; 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci /* Check the bo size can be converted to dwords without any rounding. */ 97bf215546Sopenharmony_ci assert(pt_bo_size % 4 == 0); 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci program.pds_persistent_temp_size_to_store = pt_bo_size / 4; 100bf215546Sopenharmony_ci program.dev_address_for_storing_persistent_temp = pt_bo->vma->dev_addr.addr; 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci pvr_pds_generate_stream_out_terminate_program(&program, 103bf215546Sopenharmony_ci NULL, 104bf215546Sopenharmony_ci PDS_GENERATE_SIZES, 105bf215546Sopenharmony_ci dev_info); 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci staging_buffer_size = (program.stream_out_terminate_pds_data_size + 108bf215546Sopenharmony_ci program.stream_out_terminate_pds_code_size) * 109bf215546Sopenharmony_ci sizeof(*staging_buffer); 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci staging_buffer = vk_zalloc(&device->vk.alloc, 112bf215546Sopenharmony_ci staging_buffer_size, 113bf215546Sopenharmony_ci 8, 114bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 115bf215546Sopenharmony_ci if (!staging_buffer) 116bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci data_buffer = staging_buffer; 119bf215546Sopenharmony_ci code_buffer = 120bf215546Sopenharmony_ci pvr_pds_generate_stream_out_terminate_program(&program, 121bf215546Sopenharmony_ci data_buffer, 122bf215546Sopenharmony_ci PDS_GENERATE_DATA_SEGMENT, 123bf215546Sopenharmony_ci dev_info); 124bf215546Sopenharmony_ci pvr_pds_generate_stream_out_terminate_program(&program, 125bf215546Sopenharmony_ci code_buffer, 126bf215546Sopenharmony_ci PDS_GENERATE_CODE_SEGMENT, 127bf215546Sopenharmony_ci dev_info); 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci /* This PDS program is passed to the HW via the PPP state words. These only 130bf215546Sopenharmony_ci * allow the data segment address to be specified and expect the code 131bf215546Sopenharmony_ci * segment to immediately follow. Assume the code alignment is the same as 132bf215546Sopenharmony_ci * the data. 133bf215546Sopenharmony_ci */ 134bf215546Sopenharmony_ci result = 135bf215546Sopenharmony_ci pvr_gpu_upload_pds(device, 136bf215546Sopenharmony_ci data_buffer, 137bf215546Sopenharmony_ci program.stream_out_terminate_pds_data_size, 138bf215546Sopenharmony_ci PVRX(TA_STATE_STREAM_OUT1_PDS_DATA_SIZE_UNIT_SIZE), 139bf215546Sopenharmony_ci code_buffer, 140bf215546Sopenharmony_ci program.stream_out_terminate_pds_code_size, 141bf215546Sopenharmony_ci PVRX(TA_STATE_STREAM_OUT1_PDS_DATA_SIZE_UNIT_SIZE), 142bf215546Sopenharmony_ci cache_line_size, 143bf215546Sopenharmony_ci pds_upload_out); 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci vk_free(&device->vk.alloc, staging_buffer); 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci return result; 148bf215546Sopenharmony_ci} 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_cistatic VkResult pvr_pds_pt_resume_program_create_and_upload( 151bf215546Sopenharmony_ci struct pvr_device *device, 152bf215546Sopenharmony_ci struct pvr_bo *pt_bo, 153bf215546Sopenharmony_ci uint32_t pt_bo_size, 154bf215546Sopenharmony_ci struct pvr_pds_upload *const pds_upload_out) 155bf215546Sopenharmony_ci{ 156bf215546Sopenharmony_ci struct pvr_pds_stream_out_init_program program = { 0 }; 157bf215546Sopenharmony_ci const struct pvr_device_info *dev_info = &device->pdevice->dev_info; 158bf215546Sopenharmony_ci const uint32_t cache_line_size = rogue_get_slc_cache_line_size(dev_info); 159bf215546Sopenharmony_ci size_t staging_buffer_size; 160bf215546Sopenharmony_ci uint32_t *staging_buffer; 161bf215546Sopenharmony_ci uint32_t *data_buffer; 162bf215546Sopenharmony_ci uint32_t *code_buffer; 163bf215546Sopenharmony_ci VkResult result; 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci /* Check the bo size can be converted to dwords without any rounding. */ 166bf215546Sopenharmony_ci assert(pt_bo_size % 4 == 0); 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci program.num_buffers = 1; 169bf215546Sopenharmony_ci program.pds_buffer_data_size[0] = pt_bo_size / 4; 170bf215546Sopenharmony_ci program.dev_address_for_buffer_data[0] = pt_bo->vma->dev_addr.addr; 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci pvr_pds_generate_stream_out_init_program(&program, 173bf215546Sopenharmony_ci NULL, 174bf215546Sopenharmony_ci false, 175bf215546Sopenharmony_ci PDS_GENERATE_SIZES, 176bf215546Sopenharmony_ci dev_info); 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci staging_buffer_size = (program.stream_out_init_pds_data_size + 179bf215546Sopenharmony_ci program.stream_out_init_pds_code_size) * 180bf215546Sopenharmony_ci sizeof(*staging_buffer); 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci staging_buffer = vk_zalloc(&device->vk.alloc, 183bf215546Sopenharmony_ci staging_buffer_size, 184bf215546Sopenharmony_ci 8, 185bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 186bf215546Sopenharmony_ci if (!staging_buffer) 187bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci data_buffer = staging_buffer; 190bf215546Sopenharmony_ci code_buffer = 191bf215546Sopenharmony_ci pvr_pds_generate_stream_out_init_program(&program, 192bf215546Sopenharmony_ci data_buffer, 193bf215546Sopenharmony_ci false, 194bf215546Sopenharmony_ci PDS_GENERATE_DATA_SEGMENT, 195bf215546Sopenharmony_ci dev_info); 196bf215546Sopenharmony_ci pvr_pds_generate_stream_out_init_program(&program, 197bf215546Sopenharmony_ci code_buffer, 198bf215546Sopenharmony_ci false, 199bf215546Sopenharmony_ci PDS_GENERATE_CODE_SEGMENT, 200bf215546Sopenharmony_ci dev_info); 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci /* This PDS program is passed to the HW via the PPP state words. These only 203bf215546Sopenharmony_ci * allow the data segment address to be specified and expect the code 204bf215546Sopenharmony_ci * segment to immediately follow. Assume the code alignment is the same as 205bf215546Sopenharmony_ci * the data. 206bf215546Sopenharmony_ci */ 207bf215546Sopenharmony_ci result = 208bf215546Sopenharmony_ci pvr_gpu_upload_pds(device, 209bf215546Sopenharmony_ci data_buffer, 210bf215546Sopenharmony_ci program.stream_out_init_pds_data_size, 211bf215546Sopenharmony_ci PVRX(TA_STATE_STREAM_OUT1_PDS_DATA_SIZE_UNIT_SIZE), 212bf215546Sopenharmony_ci code_buffer, 213bf215546Sopenharmony_ci program.stream_out_init_pds_code_size, 214bf215546Sopenharmony_ci PVRX(TA_STATE_STREAM_OUT1_PDS_DATA_SIZE_UNIT_SIZE), 215bf215546Sopenharmony_ci cache_line_size, 216bf215546Sopenharmony_ci pds_upload_out); 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci vk_free(&device->vk.alloc, staging_buffer); 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci return result; 221bf215546Sopenharmony_ci} 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_cistatic VkResult 224bf215546Sopenharmony_cipvr_render_job_pt_programs_setup(struct pvr_device *device, 225bf215546Sopenharmony_ci struct rogue_pt_programs *pt_programs) 226bf215546Sopenharmony_ci{ 227bf215546Sopenharmony_ci VkResult result; 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci result = pvr_bo_alloc(device, 230bf215546Sopenharmony_ci device->heaps.pds_heap, 231bf215546Sopenharmony_ci ROGUE_LLS_PDS_PERSISTENT_TEMPS_BUFFER_SIZE, 232bf215546Sopenharmony_ci ROGUE_LLS_PDS_PERSISTENT_TEMPS_BUFFER_ALIGNMENT, 233bf215546Sopenharmony_ci PVR_BO_ALLOC_FLAG_CPU_ACCESS, 234bf215546Sopenharmony_ci &pt_programs->store_resume_state_bo); 235bf215546Sopenharmony_ci if (result != VK_SUCCESS) 236bf215546Sopenharmony_ci return result; 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci result = pvr_pds_pt_store_program_create_and_upload( 239bf215546Sopenharmony_ci device, 240bf215546Sopenharmony_ci pt_programs->store_resume_state_bo, 241bf215546Sopenharmony_ci ROGUE_LLS_PDS_PERSISTENT_TEMPS_BUFFER_SIZE, 242bf215546Sopenharmony_ci &pt_programs->pds_store_program); 243bf215546Sopenharmony_ci if (result != VK_SUCCESS) 244bf215546Sopenharmony_ci goto err_free_store_resume_state_bo; 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci result = pvr_pds_pt_resume_program_create_and_upload( 247bf215546Sopenharmony_ci device, 248bf215546Sopenharmony_ci pt_programs->store_resume_state_bo, 249bf215546Sopenharmony_ci ROGUE_LLS_PDS_PERSISTENT_TEMPS_BUFFER_SIZE, 250bf215546Sopenharmony_ci &pt_programs->pds_resume_program); 251bf215546Sopenharmony_ci if (result != VK_SUCCESS) 252bf215546Sopenharmony_ci goto err_free_pds_store_program; 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci return VK_SUCCESS; 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_cierr_free_pds_store_program: 257bf215546Sopenharmony_ci pvr_bo_free(device, pt_programs->pds_store_program.pvr_bo); 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_cierr_free_store_resume_state_bo: 260bf215546Sopenharmony_ci pvr_bo_free(device, pt_programs->store_resume_state_bo); 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci return result; 263bf215546Sopenharmony_ci} 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_cistatic void 266bf215546Sopenharmony_cipvr_render_job_pt_programs_cleanup(struct pvr_device *device, 267bf215546Sopenharmony_ci struct rogue_pt_programs *pt_programs) 268bf215546Sopenharmony_ci{ 269bf215546Sopenharmony_ci pvr_bo_free(device, pt_programs->pds_resume_program.pvr_bo); 270bf215546Sopenharmony_ci pvr_bo_free(device, pt_programs->pds_store_program.pvr_bo); 271bf215546Sopenharmony_ci pvr_bo_free(device, pt_programs->store_resume_state_bo); 272bf215546Sopenharmony_ci} 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_cistatic void pvr_pds_ctx_sr_program_setup( 275bf215546Sopenharmony_ci bool cc_enable, 276bf215546Sopenharmony_ci uint64_t usc_program_upload_offset, 277bf215546Sopenharmony_ci uint8_t usc_temps, 278bf215546Sopenharmony_ci pvr_dev_addr_t sr_addr, 279bf215546Sopenharmony_ci struct pvr_pds_shared_storing_program *const program_out) 280bf215546Sopenharmony_ci{ 281bf215546Sopenharmony_ci /* The PDS task is the same for stores and loads. */ 282bf215546Sopenharmony_ci *program_out = (struct pvr_pds_shared_storing_program){ 283bf215546Sopenharmony_ci .cc_enable = cc_enable, 284bf215546Sopenharmony_ci .doutw_control = { 285bf215546Sopenharmony_ci .dest_store = PDS_UNIFIED_STORE, 286bf215546Sopenharmony_ci .num_const64 = 2, 287bf215546Sopenharmony_ci .doutw_data = { 288bf215546Sopenharmony_ci [0] = sr_addr.addr, 289bf215546Sopenharmony_ci [1] = sr_addr.addr + ROGUE_LLS_SHARED_REGS_RESERVE_SIZE, 290bf215546Sopenharmony_ci }, 291bf215546Sopenharmony_ci .last_instruction = false, 292bf215546Sopenharmony_ci }, 293bf215546Sopenharmony_ci }; 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci pvr_pds_setup_doutu(&program_out->usc_task.usc_task_control, 296bf215546Sopenharmony_ci usc_program_upload_offset, 297bf215546Sopenharmony_ci usc_temps, 298bf215546Sopenharmony_ci PVRX(PDSINST_DOUTU_SAMPLE_RATE_INSTANCE), 299bf215546Sopenharmony_ci false); 300bf215546Sopenharmony_ci} 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci/* Note: pvr_pds_compute_ctx_sr_program_create_and_upload() is very similar to 303bf215546Sopenharmony_ci * this. If there is a problem here it's likely that the same problem exists 304bf215546Sopenharmony_ci * there so don't forget to update the compute function. 305bf215546Sopenharmony_ci */ 306bf215546Sopenharmony_cistatic VkResult pvr_pds_render_ctx_sr_program_create_and_upload( 307bf215546Sopenharmony_ci struct pvr_device *device, 308bf215546Sopenharmony_ci uint64_t usc_program_upload_offset, 309bf215546Sopenharmony_ci uint8_t usc_temps, 310bf215546Sopenharmony_ci pvr_dev_addr_t sr_addr, 311bf215546Sopenharmony_ci struct pvr_pds_upload *const pds_upload_out) 312bf215546Sopenharmony_ci{ 313bf215546Sopenharmony_ci const struct pvr_device_info *dev_info = &device->pdevice->dev_info; 314bf215546Sopenharmony_ci const uint32_t cache_line_size = rogue_get_slc_cache_line_size(dev_info); 315bf215546Sopenharmony_ci const uint32_t pds_data_alignment = 316bf215546Sopenharmony_ci PVRX(VDMCTRL_PDS_STATE0_PDS_DATA_SIZE_UNIT_SIZE) / 4U; 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ci /* FIXME: pvr_pds_generate_shared_storing_program() doesn't return the data 319bf215546Sopenharmony_ci * and code size when using the PDS_GENERATE_SIZES mode. 320bf215546Sopenharmony_ci */ 321bf215546Sopenharmony_ci STATIC_ASSERT(ROGUE_PDS_TASK_PROGRAM_SIZE % 4 == 0); 322bf215546Sopenharmony_ci uint32_t staging_buffer[ROGUE_PDS_TASK_PROGRAM_SIZE / 4U] = { 0 }; 323bf215546Sopenharmony_ci struct pvr_pds_shared_storing_program program; 324bf215546Sopenharmony_ci ASSERTED uint32_t *buffer_end; 325bf215546Sopenharmony_ci uint32_t code_offset; 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci pvr_pds_ctx_sr_program_setup(false, 328bf215546Sopenharmony_ci usc_program_upload_offset, 329bf215546Sopenharmony_ci usc_temps, 330bf215546Sopenharmony_ci sr_addr, 331bf215546Sopenharmony_ci &program); 332bf215546Sopenharmony_ci 333bf215546Sopenharmony_ci pvr_pds_generate_shared_storing_program(&program, 334bf215546Sopenharmony_ci &staging_buffer[0], 335bf215546Sopenharmony_ci PDS_GENERATE_DATA_SEGMENT, 336bf215546Sopenharmony_ci dev_info); 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci code_offset = ALIGN_POT(program.data_size, pds_data_alignment); 339bf215546Sopenharmony_ci 340bf215546Sopenharmony_ci buffer_end = 341bf215546Sopenharmony_ci pvr_pds_generate_shared_storing_program(&program, 342bf215546Sopenharmony_ci &staging_buffer[code_offset], 343bf215546Sopenharmony_ci PDS_GENERATE_CODE_SEGMENT, 344bf215546Sopenharmony_ci dev_info); 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci assert((uint32_t)(buffer_end - staging_buffer) * 4 < 347bf215546Sopenharmony_ci ROGUE_PDS_TASK_PROGRAM_SIZE); 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_ci return pvr_gpu_upload_pds(device, 350bf215546Sopenharmony_ci &staging_buffer[0], 351bf215546Sopenharmony_ci program.data_size, 352bf215546Sopenharmony_ci PVRX(VDMCTRL_PDS_STATE1_PDS_DATA_ADDR_ALIGNMENT), 353bf215546Sopenharmony_ci &staging_buffer[code_offset], 354bf215546Sopenharmony_ci program.code_size, 355bf215546Sopenharmony_ci PVRX(VDMCTRL_PDS_STATE2_PDS_CODE_ADDR_ALIGNMENT), 356bf215546Sopenharmony_ci cache_line_size, 357bf215546Sopenharmony_ci pds_upload_out); 358bf215546Sopenharmony_ci} 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_ci/* Note: pvr_pds_render_ctx_sr_program_create_and_upload() is very similar to 361bf215546Sopenharmony_ci * this. If there is a problem here it's likely that the same problem exists 362bf215546Sopenharmony_ci * there so don't forget to update the render_ctx function. 363bf215546Sopenharmony_ci */ 364bf215546Sopenharmony_cistatic VkResult pvr_pds_compute_ctx_sr_program_create_and_upload( 365bf215546Sopenharmony_ci struct pvr_device *device, 366bf215546Sopenharmony_ci bool is_loading_program, 367bf215546Sopenharmony_ci uint64_t usc_program_upload_offset, 368bf215546Sopenharmony_ci uint8_t usc_temps, 369bf215546Sopenharmony_ci pvr_dev_addr_t sr_addr, 370bf215546Sopenharmony_ci struct pvr_pds_upload *const pds_upload_out) 371bf215546Sopenharmony_ci{ 372bf215546Sopenharmony_ci const struct pvr_device_info *dev_info = &device->pdevice->dev_info; 373bf215546Sopenharmony_ci const uint32_t cache_line_size = rogue_get_slc_cache_line_size(dev_info); 374bf215546Sopenharmony_ci const uint32_t pds_data_alignment = 375bf215546Sopenharmony_ci PVRX(VDMCTRL_PDS_STATE0_PDS_DATA_SIZE_UNIT_SIZE) / 4U; 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_ci /* FIXME: pvr_pds_generate_shared_storing_program() doesn't return the data 378bf215546Sopenharmony_ci * and code size when using the PDS_GENERATE_SIZES mode. 379bf215546Sopenharmony_ci */ 380bf215546Sopenharmony_ci STATIC_ASSERT(ROGUE_PDS_TASK_PROGRAM_SIZE % 4 == 0); 381bf215546Sopenharmony_ci uint32_t staging_buffer[ROGUE_PDS_TASK_PROGRAM_SIZE / 4U] = { 0 }; 382bf215546Sopenharmony_ci struct pvr_pds_shared_storing_program program; 383bf215546Sopenharmony_ci uint32_t *buffer_ptr; 384bf215546Sopenharmony_ci uint32_t code_offset; 385bf215546Sopenharmony_ci 386bf215546Sopenharmony_ci pvr_pds_ctx_sr_program_setup(PVR_HAS_ERN(dev_info, 35421), 387bf215546Sopenharmony_ci usc_program_upload_offset, 388bf215546Sopenharmony_ci usc_temps, 389bf215546Sopenharmony_ci sr_addr, 390bf215546Sopenharmony_ci &program); 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci if (is_loading_program && PVR_NEED_SW_COMPUTE_PDS_BARRIER(dev_info)) { 393bf215546Sopenharmony_ci pvr_pds_generate_compute_shared_loading_program(&program, 394bf215546Sopenharmony_ci &staging_buffer[0], 395bf215546Sopenharmony_ci PDS_GENERATE_DATA_SEGMENT, 396bf215546Sopenharmony_ci dev_info); 397bf215546Sopenharmony_ci } else { 398bf215546Sopenharmony_ci pvr_pds_generate_shared_storing_program(&program, 399bf215546Sopenharmony_ci &staging_buffer[0], 400bf215546Sopenharmony_ci PDS_GENERATE_DATA_SEGMENT, 401bf215546Sopenharmony_ci dev_info); 402bf215546Sopenharmony_ci } 403bf215546Sopenharmony_ci 404bf215546Sopenharmony_ci code_offset = ALIGN_POT(program.data_size, pds_data_alignment); 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_ci buffer_ptr = 407bf215546Sopenharmony_ci pvr_pds_generate_compute_barrier_conditional(&staging_buffer[code_offset], 408bf215546Sopenharmony_ci PDS_GENERATE_CODE_SEGMENT); 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ci if (is_loading_program && PVR_NEED_SW_COMPUTE_PDS_BARRIER(dev_info)) { 411bf215546Sopenharmony_ci buffer_ptr = pvr_pds_generate_compute_shared_loading_program( 412bf215546Sopenharmony_ci &program, 413bf215546Sopenharmony_ci buffer_ptr, 414bf215546Sopenharmony_ci PDS_GENERATE_CODE_SEGMENT, 415bf215546Sopenharmony_ci dev_info); 416bf215546Sopenharmony_ci } else { 417bf215546Sopenharmony_ci buffer_ptr = 418bf215546Sopenharmony_ci pvr_pds_generate_shared_storing_program(&program, 419bf215546Sopenharmony_ci buffer_ptr, 420bf215546Sopenharmony_ci PDS_GENERATE_CODE_SEGMENT, 421bf215546Sopenharmony_ci dev_info); 422bf215546Sopenharmony_ci } 423bf215546Sopenharmony_ci 424bf215546Sopenharmony_ci assert((uint32_t)(buffer_ptr - staging_buffer) * 4 < 425bf215546Sopenharmony_ci ROGUE_PDS_TASK_PROGRAM_SIZE); 426bf215546Sopenharmony_ci 427bf215546Sopenharmony_ci STATIC_ASSERT(PVRX(CR_CDM_CONTEXT_PDS0_DATA_ADDR_ALIGNMENT) == 428bf215546Sopenharmony_ci PVRX(CR_CDM_CONTEXT_LOAD_PDS0_DATA_ADDR_ALIGNMENT)); 429bf215546Sopenharmony_ci 430bf215546Sopenharmony_ci STATIC_ASSERT(PVRX(CR_CDM_CONTEXT_PDS0_CODE_ADDR_ALIGNMENT) == 431bf215546Sopenharmony_ci PVRX(CR_CDM_CONTEXT_LOAD_PDS0_CODE_ADDR_ALIGNMENT)); 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_ci return pvr_gpu_upload_pds( 434bf215546Sopenharmony_ci device, 435bf215546Sopenharmony_ci &staging_buffer[0], 436bf215546Sopenharmony_ci program.data_size, 437bf215546Sopenharmony_ci PVRX(CR_CDM_CONTEXT_PDS0_DATA_ADDR_ALIGNMENT), 438bf215546Sopenharmony_ci &staging_buffer[code_offset], 439bf215546Sopenharmony_ci (uint32_t)(buffer_ptr - &staging_buffer[code_offset]), 440bf215546Sopenharmony_ci PVRX(CR_CDM_CONTEXT_PDS0_CODE_ADDR_ALIGNMENT), 441bf215546Sopenharmony_ci cache_line_size, 442bf215546Sopenharmony_ci pds_upload_out); 443bf215546Sopenharmony_ci} 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_cienum pvr_ctx_sr_program_target { 446bf215546Sopenharmony_ci PVR_CTX_SR_RENDER_TARGET, 447bf215546Sopenharmony_ci PVR_CTX_SR_COMPUTE_TARGET, 448bf215546Sopenharmony_ci}; 449bf215546Sopenharmony_ci 450bf215546Sopenharmony_cistatic VkResult pvr_ctx_sr_programs_setup(struct pvr_device *device, 451bf215546Sopenharmony_ci enum pvr_ctx_sr_program_target target, 452bf215546Sopenharmony_ci struct rogue_sr_programs *sr_programs) 453bf215546Sopenharmony_ci{ 454bf215546Sopenharmony_ci const uint64_t store_load_state_bo_size = 455bf215546Sopenharmony_ci PVRX(LLS_USC_SHARED_REGS_BUFFER_SIZE) + 456bf215546Sopenharmony_ci ROGUE_LLS_SHARED_REGS_RESERVE_SIZE; 457bf215546Sopenharmony_ci const struct pvr_device_info *dev_info = &device->pdevice->dev_info; 458bf215546Sopenharmony_ci const uint32_t cache_line_size = rogue_get_slc_cache_line_size(dev_info); 459bf215546Sopenharmony_ci uint64_t usc_store_program_upload_offset; 460bf215546Sopenharmony_ci uint64_t usc_load_program_upload_offset; 461bf215546Sopenharmony_ci const uint8_t *usc_load_sr_code; 462bf215546Sopenharmony_ci uint32_t usc_load_sr_code_size; 463bf215546Sopenharmony_ci VkResult result; 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci /* Note that this is being used for both compute and render ctx. There is no 466bf215546Sopenharmony_ci * compute equivalent define for the VDMCTRL unit size. 467bf215546Sopenharmony_ci */ 468bf215546Sopenharmony_ci /* 4 blocks (16 dwords / 64 bytes) in USC to prevent fragmentation. */ 469bf215546Sopenharmony_ci sr_programs->usc.unified_size = 470bf215546Sopenharmony_ci DIV_ROUND_UP(64, PVRX(VDMCTRL_PDS_STATE0_USC_UNIFIED_SIZE_UNIT_SIZE)); 471bf215546Sopenharmony_ci 472bf215546Sopenharmony_ci result = pvr_bo_alloc(device, 473bf215546Sopenharmony_ci device->heaps.pds_heap, 474bf215546Sopenharmony_ci store_load_state_bo_size, 475bf215546Sopenharmony_ci cache_line_size, 476bf215546Sopenharmony_ci PVR_WINSYS_BO_FLAG_CPU_ACCESS, 477bf215546Sopenharmony_ci &sr_programs->store_load_state_bo); 478bf215546Sopenharmony_ci if (result != VK_SUCCESS) 479bf215546Sopenharmony_ci return result; 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci /* USC state update: SR state store. */ 482bf215546Sopenharmony_ci 483bf215546Sopenharmony_ci assert(sizeof(pvr_vdm_store_sr_code) < ROGUE_USC_TASK_PROGRAM_SIZE); 484bf215546Sopenharmony_ci 485bf215546Sopenharmony_ci result = pvr_gpu_upload_usc(device, 486bf215546Sopenharmony_ci pvr_vdm_store_sr_code, 487bf215546Sopenharmony_ci sizeof(pvr_vdm_store_sr_code), 488bf215546Sopenharmony_ci cache_line_size, 489bf215546Sopenharmony_ci &sr_programs->usc.store_program_bo); 490bf215546Sopenharmony_ci if (result != VK_SUCCESS) 491bf215546Sopenharmony_ci goto err_free_store_load_state_bo; 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci usc_store_program_upload_offset = 494bf215546Sopenharmony_ci sr_programs->usc.store_program_bo->vma->dev_addr.addr - 495bf215546Sopenharmony_ci device->heaps.usc_heap->base_addr.addr; 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci /* USC state update: SR state load. */ 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_ci if (target == PVR_CTX_SR_COMPUTE_TARGET && PVR_HAS_QUIRK(dev_info, 62269)) { 500bf215546Sopenharmony_ci STATIC_ASSERT(sizeof(pvr_cdm_load_sr_code) < ROGUE_USC_TASK_PROGRAM_SIZE); 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_ci usc_load_sr_code = pvr_cdm_load_sr_code; 503bf215546Sopenharmony_ci usc_load_sr_code_size = sizeof(pvr_cdm_load_sr_code); 504bf215546Sopenharmony_ci } else { 505bf215546Sopenharmony_ci STATIC_ASSERT(sizeof(pvr_vdm_load_sr_code) < ROGUE_USC_TASK_PROGRAM_SIZE); 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_ci usc_load_sr_code = pvr_vdm_load_sr_code; 508bf215546Sopenharmony_ci usc_load_sr_code_size = sizeof(pvr_vdm_load_sr_code); 509bf215546Sopenharmony_ci } 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_ci result = pvr_gpu_upload_usc(device, 512bf215546Sopenharmony_ci usc_load_sr_code, 513bf215546Sopenharmony_ci usc_load_sr_code_size, 514bf215546Sopenharmony_ci cache_line_size, 515bf215546Sopenharmony_ci &sr_programs->usc.load_program_bo); 516bf215546Sopenharmony_ci if (result != VK_SUCCESS) 517bf215546Sopenharmony_ci goto err_free_usc_store_program_bo; 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci usc_load_program_upload_offset = 520bf215546Sopenharmony_ci sr_programs->usc.load_program_bo->vma->dev_addr.addr - 521bf215546Sopenharmony_ci device->heaps.usc_heap->base_addr.addr; 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_ci /* FIXME: The number of USC temps should be output alongside 524bf215546Sopenharmony_ci * pvr_vdm_store_sr_code rather than hard coded. 525bf215546Sopenharmony_ci */ 526bf215546Sopenharmony_ci /* Create and upload the PDS load and store programs. Point them to the 527bf215546Sopenharmony_ci * appropriate USC load and store programs. 528bf215546Sopenharmony_ci */ 529bf215546Sopenharmony_ci switch (target) { 530bf215546Sopenharmony_ci case PVR_CTX_SR_RENDER_TARGET: 531bf215546Sopenharmony_ci /* PDS state update: SR state store. */ 532bf215546Sopenharmony_ci result = pvr_pds_render_ctx_sr_program_create_and_upload( 533bf215546Sopenharmony_ci device, 534bf215546Sopenharmony_ci usc_store_program_upload_offset, 535bf215546Sopenharmony_ci 8, 536bf215546Sopenharmony_ci sr_programs->store_load_state_bo->vma->dev_addr, 537bf215546Sopenharmony_ci &sr_programs->pds.store_program); 538bf215546Sopenharmony_ci if (result != VK_SUCCESS) 539bf215546Sopenharmony_ci goto err_free_usc_load_program_bo; 540bf215546Sopenharmony_ci 541bf215546Sopenharmony_ci /* PDS state update: SR state load. */ 542bf215546Sopenharmony_ci result = pvr_pds_render_ctx_sr_program_create_and_upload( 543bf215546Sopenharmony_ci device, 544bf215546Sopenharmony_ci usc_load_program_upload_offset, 545bf215546Sopenharmony_ci 20, 546bf215546Sopenharmony_ci sr_programs->store_load_state_bo->vma->dev_addr, 547bf215546Sopenharmony_ci &sr_programs->pds.load_program); 548bf215546Sopenharmony_ci if (result != VK_SUCCESS) 549bf215546Sopenharmony_ci goto err_free_pds_store_program_bo; 550bf215546Sopenharmony_ci 551bf215546Sopenharmony_ci break; 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci case PVR_CTX_SR_COMPUTE_TARGET: 554bf215546Sopenharmony_ci /* PDS state update: SR state store. */ 555bf215546Sopenharmony_ci result = pvr_pds_compute_ctx_sr_program_create_and_upload( 556bf215546Sopenharmony_ci device, 557bf215546Sopenharmony_ci false, 558bf215546Sopenharmony_ci usc_store_program_upload_offset, 559bf215546Sopenharmony_ci 8, 560bf215546Sopenharmony_ci sr_programs->store_load_state_bo->vma->dev_addr, 561bf215546Sopenharmony_ci &sr_programs->pds.store_program); 562bf215546Sopenharmony_ci if (result != VK_SUCCESS) 563bf215546Sopenharmony_ci goto err_free_usc_load_program_bo; 564bf215546Sopenharmony_ci 565bf215546Sopenharmony_ci /* PDS state update: SR state load. */ 566bf215546Sopenharmony_ci result = pvr_pds_compute_ctx_sr_program_create_and_upload( 567bf215546Sopenharmony_ci device, 568bf215546Sopenharmony_ci true, 569bf215546Sopenharmony_ci usc_load_program_upload_offset, 570bf215546Sopenharmony_ci 20, 571bf215546Sopenharmony_ci sr_programs->store_load_state_bo->vma->dev_addr, 572bf215546Sopenharmony_ci &sr_programs->pds.load_program); 573bf215546Sopenharmony_ci if (result != VK_SUCCESS) 574bf215546Sopenharmony_ci goto err_free_pds_store_program_bo; 575bf215546Sopenharmony_ci 576bf215546Sopenharmony_ci break; 577bf215546Sopenharmony_ci 578bf215546Sopenharmony_ci default: 579bf215546Sopenharmony_ci unreachable("Invalid target."); 580bf215546Sopenharmony_ci break; 581bf215546Sopenharmony_ci } 582bf215546Sopenharmony_ci 583bf215546Sopenharmony_ci return VK_SUCCESS; 584bf215546Sopenharmony_ci 585bf215546Sopenharmony_cierr_free_pds_store_program_bo: 586bf215546Sopenharmony_ci pvr_bo_free(device, sr_programs->pds.store_program.pvr_bo); 587bf215546Sopenharmony_ci 588bf215546Sopenharmony_cierr_free_usc_load_program_bo: 589bf215546Sopenharmony_ci pvr_bo_free(device, sr_programs->usc.load_program_bo); 590bf215546Sopenharmony_ci 591bf215546Sopenharmony_cierr_free_usc_store_program_bo: 592bf215546Sopenharmony_ci pvr_bo_free(device, sr_programs->usc.store_program_bo); 593bf215546Sopenharmony_ci 594bf215546Sopenharmony_cierr_free_store_load_state_bo: 595bf215546Sopenharmony_ci pvr_bo_free(device, sr_programs->store_load_state_bo); 596bf215546Sopenharmony_ci 597bf215546Sopenharmony_ci return VK_SUCCESS; 598bf215546Sopenharmony_ci} 599bf215546Sopenharmony_ci 600bf215546Sopenharmony_cistatic void pvr_ctx_sr_programs_cleanup(struct pvr_device *device, 601bf215546Sopenharmony_ci struct rogue_sr_programs *sr_programs) 602bf215546Sopenharmony_ci{ 603bf215546Sopenharmony_ci pvr_bo_free(device, sr_programs->pds.load_program.pvr_bo); 604bf215546Sopenharmony_ci pvr_bo_free(device, sr_programs->pds.store_program.pvr_bo); 605bf215546Sopenharmony_ci pvr_bo_free(device, sr_programs->usc.load_program_bo); 606bf215546Sopenharmony_ci pvr_bo_free(device, sr_programs->usc.store_program_bo); 607bf215546Sopenharmony_ci pvr_bo_free(device, sr_programs->store_load_state_bo); 608bf215546Sopenharmony_ci} 609bf215546Sopenharmony_ci 610bf215546Sopenharmony_cistatic VkResult 611bf215546Sopenharmony_cipvr_render_ctx_switch_programs_setup(struct pvr_device *device, 612bf215546Sopenharmony_ci struct pvr_render_ctx_programs *programs) 613bf215546Sopenharmony_ci{ 614bf215546Sopenharmony_ci VkResult result; 615bf215546Sopenharmony_ci 616bf215546Sopenharmony_ci result = pvr_render_job_pt_programs_setup(device, &programs->pt); 617bf215546Sopenharmony_ci if (result != VK_SUCCESS) 618bf215546Sopenharmony_ci return result; 619bf215546Sopenharmony_ci 620bf215546Sopenharmony_ci result = pvr_ctx_sr_programs_setup(device, 621bf215546Sopenharmony_ci PVR_CTX_SR_RENDER_TARGET, 622bf215546Sopenharmony_ci &programs->sr); 623bf215546Sopenharmony_ci if (result != VK_SUCCESS) 624bf215546Sopenharmony_ci goto err_pt_programs_cleanup; 625bf215546Sopenharmony_ci 626bf215546Sopenharmony_ci return VK_SUCCESS; 627bf215546Sopenharmony_ci 628bf215546Sopenharmony_cierr_pt_programs_cleanup: 629bf215546Sopenharmony_ci pvr_render_job_pt_programs_cleanup(device, &programs->pt); 630bf215546Sopenharmony_ci 631bf215546Sopenharmony_ci return result; 632bf215546Sopenharmony_ci} 633bf215546Sopenharmony_ci 634bf215546Sopenharmony_cistatic void 635bf215546Sopenharmony_cipvr_render_ctx_switch_programs_cleanup(struct pvr_device *device, 636bf215546Sopenharmony_ci struct pvr_render_ctx_programs *programs) 637bf215546Sopenharmony_ci{ 638bf215546Sopenharmony_ci pvr_ctx_sr_programs_cleanup(device, &programs->sr); 639bf215546Sopenharmony_ci pvr_render_job_pt_programs_cleanup(device, &programs->pt); 640bf215546Sopenharmony_ci} 641bf215546Sopenharmony_ci 642bf215546Sopenharmony_cistatic VkResult pvr_render_ctx_switch_init(struct pvr_device *device, 643bf215546Sopenharmony_ci struct pvr_render_ctx *ctx) 644bf215546Sopenharmony_ci{ 645bf215546Sopenharmony_ci struct pvr_render_ctx_switch *ctx_switch = &ctx->ctx_switch; 646bf215546Sopenharmony_ci const uint64_t vdm_state_bo_flags = PVR_BO_ALLOC_FLAG_GPU_UNCACHED | 647bf215546Sopenharmony_ci PVR_BO_ALLOC_FLAG_CPU_ACCESS; 648bf215546Sopenharmony_ci const uint64_t geom_state_bo_flags = PVR_BO_ALLOC_FLAG_GPU_UNCACHED | 649bf215546Sopenharmony_ci PVR_BO_ALLOC_FLAG_CPU_ACCESS; 650bf215546Sopenharmony_ci VkResult result; 651bf215546Sopenharmony_ci 652bf215546Sopenharmony_ci result = pvr_bo_alloc(device, 653bf215546Sopenharmony_ci device->heaps.general_heap, 654bf215546Sopenharmony_ci ROGUE_LLS_VDM_CONTEXT_RESUME_BUFFER_SIZE, 655bf215546Sopenharmony_ci ROGUE_LLS_VDM_CONTEXT_RESUME_BUFFER_ALIGNMENT, 656bf215546Sopenharmony_ci vdm_state_bo_flags, 657bf215546Sopenharmony_ci &ctx_switch->vdm_state_bo); 658bf215546Sopenharmony_ci if (result != VK_SUCCESS) 659bf215546Sopenharmony_ci return result; 660bf215546Sopenharmony_ci 661bf215546Sopenharmony_ci result = pvr_bo_alloc(device, 662bf215546Sopenharmony_ci device->heaps.general_heap, 663bf215546Sopenharmony_ci ROGUE_LLS_TA_STATE_BUFFER_SIZE, 664bf215546Sopenharmony_ci ROGUE_LLS_TA_STATE_BUFFER_ALIGNMENT, 665bf215546Sopenharmony_ci geom_state_bo_flags, 666bf215546Sopenharmony_ci &ctx_switch->geom_state_bo); 667bf215546Sopenharmony_ci if (result != VK_SUCCESS) 668bf215546Sopenharmony_ci goto err_pvr_bo_free_vdm_state_bo; 669bf215546Sopenharmony_ci 670bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(ctx_switch->programs); i++) { 671bf215546Sopenharmony_ci result = 672bf215546Sopenharmony_ci pvr_render_ctx_switch_programs_setup(device, &ctx_switch->programs[i]); 673bf215546Sopenharmony_ci if (result) 674bf215546Sopenharmony_ci goto err_programs_cleanup; 675bf215546Sopenharmony_ci } 676bf215546Sopenharmony_ci 677bf215546Sopenharmony_ci return result; 678bf215546Sopenharmony_ci 679bf215546Sopenharmony_cierr_programs_cleanup: 680bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(ctx_switch->programs); i++) { 681bf215546Sopenharmony_ci pvr_render_ctx_switch_programs_cleanup(device, &ctx_switch->programs[i]); 682bf215546Sopenharmony_ci } 683bf215546Sopenharmony_ci 684bf215546Sopenharmony_ci pvr_bo_free(device, ctx_switch->geom_state_bo); 685bf215546Sopenharmony_ci 686bf215546Sopenharmony_cierr_pvr_bo_free_vdm_state_bo: 687bf215546Sopenharmony_ci pvr_bo_free(device, ctx_switch->vdm_state_bo); 688bf215546Sopenharmony_ci 689bf215546Sopenharmony_ci return result; 690bf215546Sopenharmony_ci} 691bf215546Sopenharmony_ci 692bf215546Sopenharmony_cistatic void pvr_render_ctx_switch_fini(struct pvr_device *device, 693bf215546Sopenharmony_ci struct pvr_render_ctx *ctx) 694bf215546Sopenharmony_ci{ 695bf215546Sopenharmony_ci struct pvr_render_ctx_switch *ctx_switch = &ctx->ctx_switch; 696bf215546Sopenharmony_ci 697bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(ctx_switch->programs); i++) { 698bf215546Sopenharmony_ci pvr_render_ctx_switch_programs_cleanup(device, &ctx_switch->programs[i]); 699bf215546Sopenharmony_ci } 700bf215546Sopenharmony_ci 701bf215546Sopenharmony_ci pvr_bo_free(device, ctx_switch->geom_state_bo); 702bf215546Sopenharmony_ci pvr_bo_free(device, ctx_switch->vdm_state_bo); 703bf215546Sopenharmony_ci} 704bf215546Sopenharmony_ci 705bf215546Sopenharmony_cistatic void 706bf215546Sopenharmony_cipvr_rogue_get_vdmctrl_pds_state_words(struct pvr_pds_upload *pds_program, 707bf215546Sopenharmony_ci enum PVRX(VDMCTRL_USC_TARGET) usc_target, 708bf215546Sopenharmony_ci uint8_t usc_unified_size, 709bf215546Sopenharmony_ci uint32_t *const state0_out, 710bf215546Sopenharmony_ci uint32_t *const state1_out) 711bf215546Sopenharmony_ci{ 712bf215546Sopenharmony_ci pvr_csb_pack (state0_out, VDMCTRL_PDS_STATE0, state) { 713bf215546Sopenharmony_ci /* Convert the data size from dwords to bytes. */ 714bf215546Sopenharmony_ci const uint32_t pds_data_size = pds_program->data_size * 4; 715bf215546Sopenharmony_ci 716bf215546Sopenharmony_ci state.dm_target = PVRX(VDMCTRL_DM_TARGET_VDM); 717bf215546Sopenharmony_ci state.usc_target = usc_target; 718bf215546Sopenharmony_ci state.usc_common_size = 0; 719bf215546Sopenharmony_ci state.usc_unified_size = usc_unified_size; 720bf215546Sopenharmony_ci state.pds_temp_size = 0; 721bf215546Sopenharmony_ci 722bf215546Sopenharmony_ci assert(pds_data_size % PVRX(VDMCTRL_PDS_STATE0_PDS_DATA_SIZE_UNIT_SIZE) == 723bf215546Sopenharmony_ci 0); 724bf215546Sopenharmony_ci state.pds_data_size = 725bf215546Sopenharmony_ci pds_data_size / PVRX(VDMCTRL_PDS_STATE0_PDS_DATA_SIZE_UNIT_SIZE); 726bf215546Sopenharmony_ci }; 727bf215546Sopenharmony_ci 728bf215546Sopenharmony_ci pvr_csb_pack (state1_out, VDMCTRL_PDS_STATE1, state) { 729bf215546Sopenharmony_ci state.pds_data_addr = PVR_DEV_ADDR(pds_program->data_offset); 730bf215546Sopenharmony_ci state.sd_type = PVRX(VDMCTRL_SD_TYPE_PDS); 731bf215546Sopenharmony_ci state.sd_next_type = PVRX(VDMCTRL_SD_TYPE_PDS); 732bf215546Sopenharmony_ci } 733bf215546Sopenharmony_ci} 734bf215546Sopenharmony_ci 735bf215546Sopenharmony_cistatic void 736bf215546Sopenharmony_cipvr_rogue_get_geom_state_stream_out_words(struct pvr_pds_upload *pds_program, 737bf215546Sopenharmony_ci uint32_t *const stream_out1_out, 738bf215546Sopenharmony_ci uint32_t *const stream_out2_out) 739bf215546Sopenharmony_ci{ 740bf215546Sopenharmony_ci pvr_csb_pack (stream_out1_out, TA_STATE_STREAM_OUT1, state) { 741bf215546Sopenharmony_ci /* Convert the data size from dwords to bytes. */ 742bf215546Sopenharmony_ci const uint32_t pds_data_size = pds_program->data_size * 4; 743bf215546Sopenharmony_ci 744bf215546Sopenharmony_ci state.sync = true; 745bf215546Sopenharmony_ci 746bf215546Sopenharmony_ci assert(pds_data_size % 747bf215546Sopenharmony_ci PVRX(TA_STATE_STREAM_OUT1_PDS_DATA_SIZE_UNIT_SIZE) == 748bf215546Sopenharmony_ci 0); 749bf215546Sopenharmony_ci state.pds_data_size = 750bf215546Sopenharmony_ci pds_data_size / PVRX(TA_STATE_STREAM_OUT1_PDS_DATA_SIZE_UNIT_SIZE); 751bf215546Sopenharmony_ci 752bf215546Sopenharmony_ci state.pds_temp_size = 0; 753bf215546Sopenharmony_ci } 754bf215546Sopenharmony_ci 755bf215546Sopenharmony_ci pvr_csb_pack (stream_out2_out, TA_STATE_STREAM_OUT2, state) { 756bf215546Sopenharmony_ci state.pds_data_addr = PVR_DEV_ADDR(pds_program->data_offset); 757bf215546Sopenharmony_ci } 758bf215546Sopenharmony_ci} 759bf215546Sopenharmony_ci 760bf215546Sopenharmony_cistatic void pvr_render_ctx_ws_static_state_init( 761bf215546Sopenharmony_ci struct pvr_render_ctx *ctx, 762bf215546Sopenharmony_ci struct pvr_winsys_render_ctx_static_state *static_state) 763bf215546Sopenharmony_ci{ 764bf215546Sopenharmony_ci uint64_t *q_dst; 765bf215546Sopenharmony_ci uint32_t *d_dst; 766bf215546Sopenharmony_ci 767bf215546Sopenharmony_ci q_dst = &static_state->vdm_ctx_state_base_addr; 768bf215546Sopenharmony_ci pvr_csb_pack (q_dst, CR_VDM_CONTEXT_STATE_BASE, base) { 769bf215546Sopenharmony_ci base.addr = ctx->ctx_switch.vdm_state_bo->vma->dev_addr; 770bf215546Sopenharmony_ci } 771bf215546Sopenharmony_ci 772bf215546Sopenharmony_ci q_dst = &static_state->geom_ctx_state_base_addr; 773bf215546Sopenharmony_ci pvr_csb_pack (q_dst, CR_TA_CONTEXT_STATE_BASE, base) { 774bf215546Sopenharmony_ci base.addr = ctx->ctx_switch.geom_state_bo->vma->dev_addr; 775bf215546Sopenharmony_ci } 776bf215546Sopenharmony_ci 777bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(ctx->ctx_switch.programs); i++) { 778bf215546Sopenharmony_ci struct rogue_pt_programs *pt_prog = &ctx->ctx_switch.programs[i].pt; 779bf215546Sopenharmony_ci struct rogue_sr_programs *sr_prog = &ctx->ctx_switch.programs[i].sr; 780bf215546Sopenharmony_ci 781bf215546Sopenharmony_ci /* Context store state. */ 782bf215546Sopenharmony_ci q_dst = &static_state->geom_state[i].vdm_ctx_store_task0; 783bf215546Sopenharmony_ci pvr_csb_pack (q_dst, CR_VDM_CONTEXT_STORE_TASK0, task0) { 784bf215546Sopenharmony_ci pvr_rogue_get_vdmctrl_pds_state_words(&sr_prog->pds.store_program, 785bf215546Sopenharmony_ci PVRX(VDMCTRL_USC_TARGET_ANY), 786bf215546Sopenharmony_ci sr_prog->usc.unified_size, 787bf215546Sopenharmony_ci &task0.pds_state0, 788bf215546Sopenharmony_ci &task0.pds_state1); 789bf215546Sopenharmony_ci } 790bf215546Sopenharmony_ci 791bf215546Sopenharmony_ci d_dst = &static_state->geom_state[i].vdm_ctx_store_task1; 792bf215546Sopenharmony_ci pvr_csb_pack (d_dst, CR_VDM_CONTEXT_STORE_TASK1, task1) { 793bf215546Sopenharmony_ci pvr_csb_pack (&task1.pds_state2, VDMCTRL_PDS_STATE2, state) { 794bf215546Sopenharmony_ci state.pds_code_addr = 795bf215546Sopenharmony_ci PVR_DEV_ADDR(sr_prog->pds.store_program.code_offset); 796bf215546Sopenharmony_ci } 797bf215546Sopenharmony_ci } 798bf215546Sopenharmony_ci 799bf215546Sopenharmony_ci q_dst = &static_state->geom_state[i].vdm_ctx_store_task2; 800bf215546Sopenharmony_ci pvr_csb_pack (q_dst, CR_VDM_CONTEXT_STORE_TASK2, task2) { 801bf215546Sopenharmony_ci pvr_rogue_get_geom_state_stream_out_words(&pt_prog->pds_store_program, 802bf215546Sopenharmony_ci &task2.stream_out1, 803bf215546Sopenharmony_ci &task2.stream_out2); 804bf215546Sopenharmony_ci } 805bf215546Sopenharmony_ci 806bf215546Sopenharmony_ci /* Context resume state. */ 807bf215546Sopenharmony_ci q_dst = &static_state->geom_state[i].vdm_ctx_resume_task0; 808bf215546Sopenharmony_ci pvr_csb_pack (q_dst, CR_VDM_CONTEXT_RESUME_TASK0, task0) { 809bf215546Sopenharmony_ci pvr_rogue_get_vdmctrl_pds_state_words(&sr_prog->pds.load_program, 810bf215546Sopenharmony_ci PVRX(VDMCTRL_USC_TARGET_ALL), 811bf215546Sopenharmony_ci sr_prog->usc.unified_size, 812bf215546Sopenharmony_ci &task0.pds_state0, 813bf215546Sopenharmony_ci &task0.pds_state1); 814bf215546Sopenharmony_ci } 815bf215546Sopenharmony_ci 816bf215546Sopenharmony_ci d_dst = &static_state->geom_state[i].vdm_ctx_resume_task1; 817bf215546Sopenharmony_ci pvr_csb_pack (d_dst, CR_VDM_CONTEXT_RESUME_TASK1, task1) { 818bf215546Sopenharmony_ci pvr_csb_pack (&task1.pds_state2, VDMCTRL_PDS_STATE2, state) { 819bf215546Sopenharmony_ci state.pds_code_addr = 820bf215546Sopenharmony_ci PVR_DEV_ADDR(sr_prog->pds.load_program.code_offset); 821bf215546Sopenharmony_ci } 822bf215546Sopenharmony_ci } 823bf215546Sopenharmony_ci 824bf215546Sopenharmony_ci q_dst = &static_state->geom_state[i].vdm_ctx_resume_task2; 825bf215546Sopenharmony_ci pvr_csb_pack (q_dst, CR_VDM_CONTEXT_RESUME_TASK2, task2) { 826bf215546Sopenharmony_ci pvr_rogue_get_geom_state_stream_out_words(&pt_prog->pds_resume_program, 827bf215546Sopenharmony_ci &task2.stream_out1, 828bf215546Sopenharmony_ci &task2.stream_out2); 829bf215546Sopenharmony_ci } 830bf215546Sopenharmony_ci } 831bf215546Sopenharmony_ci} 832bf215546Sopenharmony_ci 833bf215546Sopenharmony_cistatic void pvr_render_ctx_ws_create_info_init( 834bf215546Sopenharmony_ci struct pvr_render_ctx *ctx, 835bf215546Sopenharmony_ci enum pvr_winsys_ctx_priority priority, 836bf215546Sopenharmony_ci struct pvr_winsys_render_ctx_create_info *create_info) 837bf215546Sopenharmony_ci{ 838bf215546Sopenharmony_ci create_info->priority = priority; 839bf215546Sopenharmony_ci create_info->vdm_callstack_addr = ctx->vdm_callstack_bo->vma->dev_addr; 840bf215546Sopenharmony_ci 841bf215546Sopenharmony_ci pvr_render_ctx_ws_static_state_init(ctx, &create_info->static_state); 842bf215546Sopenharmony_ci} 843bf215546Sopenharmony_ci 844bf215546Sopenharmony_ciVkResult pvr_render_ctx_create(struct pvr_device *device, 845bf215546Sopenharmony_ci enum pvr_winsys_ctx_priority priority, 846bf215546Sopenharmony_ci struct pvr_render_ctx **const ctx_out) 847bf215546Sopenharmony_ci{ 848bf215546Sopenharmony_ci const uint64_t vdm_callstack_size = 849bf215546Sopenharmony_ci sizeof(uint64_t) * PVR_VDM_CALLSTACK_MAX_DEPTH; 850bf215546Sopenharmony_ci struct pvr_winsys_render_ctx_create_info create_info; 851bf215546Sopenharmony_ci struct pvr_render_ctx *ctx; 852bf215546Sopenharmony_ci VkResult result; 853bf215546Sopenharmony_ci 854bf215546Sopenharmony_ci ctx = vk_alloc(&device->vk.alloc, 855bf215546Sopenharmony_ci sizeof(*ctx), 856bf215546Sopenharmony_ci 8, 857bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 858bf215546Sopenharmony_ci if (!ctx) 859bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 860bf215546Sopenharmony_ci 861bf215546Sopenharmony_ci ctx->device = device; 862bf215546Sopenharmony_ci 863bf215546Sopenharmony_ci result = pvr_bo_alloc(device, 864bf215546Sopenharmony_ci device->heaps.general_heap, 865bf215546Sopenharmony_ci vdm_callstack_size, 866bf215546Sopenharmony_ci PVRX(CR_VDM_CALL_STACK_POINTER_ADDR_ALIGNMENT), 867bf215546Sopenharmony_ci 0, 868bf215546Sopenharmony_ci &ctx->vdm_callstack_bo); 869bf215546Sopenharmony_ci if (result != VK_SUCCESS) 870bf215546Sopenharmony_ci goto err_vk_free_ctx; 871bf215546Sopenharmony_ci 872bf215546Sopenharmony_ci result = pvr_render_ctx_switch_init(device, ctx); 873bf215546Sopenharmony_ci if (result != VK_SUCCESS) 874bf215546Sopenharmony_ci goto err_free_vdm_callstack_bo; 875bf215546Sopenharmony_ci 876bf215546Sopenharmony_ci result = pvr_ctx_reset_cmd_init(device, &ctx->reset_cmd); 877bf215546Sopenharmony_ci if (result != VK_SUCCESS) 878bf215546Sopenharmony_ci goto err_render_ctx_switch_fini; 879bf215546Sopenharmony_ci 880bf215546Sopenharmony_ci /* ctx must be fully initialized by this point since 881bf215546Sopenharmony_ci * pvr_render_ctx_ws_create_info_init() depends on this. 882bf215546Sopenharmony_ci */ 883bf215546Sopenharmony_ci pvr_render_ctx_ws_create_info_init(ctx, priority, &create_info); 884bf215546Sopenharmony_ci 885bf215546Sopenharmony_ci result = device->ws->ops->render_ctx_create(device->ws, 886bf215546Sopenharmony_ci &create_info, 887bf215546Sopenharmony_ci &ctx->ws_ctx); 888bf215546Sopenharmony_ci if (result != VK_SUCCESS) 889bf215546Sopenharmony_ci goto err_render_ctx_reset_cmd_fini; 890bf215546Sopenharmony_ci 891bf215546Sopenharmony_ci *ctx_out = ctx; 892bf215546Sopenharmony_ci 893bf215546Sopenharmony_ci return VK_SUCCESS; 894bf215546Sopenharmony_ci 895bf215546Sopenharmony_cierr_render_ctx_reset_cmd_fini: 896bf215546Sopenharmony_ci pvr_ctx_reset_cmd_fini(device, &ctx->reset_cmd); 897bf215546Sopenharmony_ci 898bf215546Sopenharmony_cierr_render_ctx_switch_fini: 899bf215546Sopenharmony_ci pvr_render_ctx_switch_fini(device, ctx); 900bf215546Sopenharmony_ci 901bf215546Sopenharmony_cierr_free_vdm_callstack_bo: 902bf215546Sopenharmony_ci pvr_bo_free(device, ctx->vdm_callstack_bo); 903bf215546Sopenharmony_ci 904bf215546Sopenharmony_cierr_vk_free_ctx: 905bf215546Sopenharmony_ci vk_free(&device->vk.alloc, ctx); 906bf215546Sopenharmony_ci 907bf215546Sopenharmony_ci return result; 908bf215546Sopenharmony_ci} 909bf215546Sopenharmony_ci 910bf215546Sopenharmony_civoid pvr_render_ctx_destroy(struct pvr_render_ctx *ctx) 911bf215546Sopenharmony_ci{ 912bf215546Sopenharmony_ci struct pvr_device *device = ctx->device; 913bf215546Sopenharmony_ci 914bf215546Sopenharmony_ci device->ws->ops->render_ctx_destroy(ctx->ws_ctx); 915bf215546Sopenharmony_ci 916bf215546Sopenharmony_ci pvr_ctx_reset_cmd_fini(device, &ctx->reset_cmd); 917bf215546Sopenharmony_ci pvr_render_ctx_switch_fini(device, ctx); 918bf215546Sopenharmony_ci pvr_bo_free(device, ctx->vdm_callstack_bo); 919bf215546Sopenharmony_ci vk_free(&device->vk.alloc, ctx); 920bf215546Sopenharmony_ci} 921bf215546Sopenharmony_ci 922bf215546Sopenharmony_cistatic VkResult pvr_pds_sr_fence_terminate_program_create_and_upload( 923bf215546Sopenharmony_ci struct pvr_device *device, 924bf215546Sopenharmony_ci struct pvr_pds_upload *const pds_upload_out) 925bf215546Sopenharmony_ci{ 926bf215546Sopenharmony_ci const uint32_t pds_data_alignment = 927bf215546Sopenharmony_ci PVRX(VDMCTRL_PDS_STATE0_PDS_DATA_SIZE_UNIT_SIZE) / 4U; 928bf215546Sopenharmony_ci const struct pvr_device_runtime_info *dev_runtime_info = 929bf215546Sopenharmony_ci &device->pdevice->dev_runtime_info; 930bf215546Sopenharmony_ci ASSERTED const struct pvr_device_info *dev_info = &device->pdevice->dev_info; 931bf215546Sopenharmony_ci uint32_t staging_buffer[PVRX(PDS_TASK_PROGRAM_SIZE) >> 2U]; 932bf215546Sopenharmony_ci struct pvr_pds_fence_program program = { 0 }; 933bf215546Sopenharmony_ci ASSERTED uint32_t *buffer_end; 934bf215546Sopenharmony_ci uint32_t code_offset; 935bf215546Sopenharmony_ci uint32_t data_size; 936bf215546Sopenharmony_ci 937bf215546Sopenharmony_ci /* SW_COMPUTE_PDS_BARRIER is not supported with 2 or more phantoms. */ 938bf215546Sopenharmony_ci assert(!(PVR_NEED_SW_COMPUTE_PDS_BARRIER(dev_info) && 939bf215546Sopenharmony_ci dev_runtime_info->num_phantoms >= 2)); 940bf215546Sopenharmony_ci 941bf215546Sopenharmony_ci pvr_pds_generate_fence_terminate_program(&program, 942bf215546Sopenharmony_ci staging_buffer, 943bf215546Sopenharmony_ci PDS_GENERATE_DATA_SEGMENT, 944bf215546Sopenharmony_ci &device->pdevice->dev_info); 945bf215546Sopenharmony_ci 946bf215546Sopenharmony_ci /* FIXME: pvr_pds_generate_fence_terminate_program() zeros out the data_size 947bf215546Sopenharmony_ci * when we generate the code segment. Implement 948bf215546Sopenharmony_ci * PDS_GENERATE_CODEDATA_SEGMENTS? Or wait for the pds gen api to change? 949bf215546Sopenharmony_ci * This behavior doesn't seem consistent with the rest of the api. For now 950bf215546Sopenharmony_ci * we store the size in a variable. 951bf215546Sopenharmony_ci */ 952bf215546Sopenharmony_ci data_size = program.data_size; 953bf215546Sopenharmony_ci code_offset = ALIGN_POT(program.data_size, pds_data_alignment); 954bf215546Sopenharmony_ci 955bf215546Sopenharmony_ci buffer_end = 956bf215546Sopenharmony_ci pvr_pds_generate_fence_terminate_program(&program, 957bf215546Sopenharmony_ci &staging_buffer[code_offset], 958bf215546Sopenharmony_ci PDS_GENERATE_CODE_SEGMENT, 959bf215546Sopenharmony_ci &device->pdevice->dev_info); 960bf215546Sopenharmony_ci 961bf215546Sopenharmony_ci assert((uint64_t)(buffer_end - staging_buffer) * 4U < 962bf215546Sopenharmony_ci ROGUE_PDS_TASK_PROGRAM_SIZE); 963bf215546Sopenharmony_ci 964bf215546Sopenharmony_ci return pvr_gpu_upload_pds(device, 965bf215546Sopenharmony_ci staging_buffer, 966bf215546Sopenharmony_ci data_size, 967bf215546Sopenharmony_ci PVRX(CR_CDM_TERMINATE_PDS_DATA_ADDR_ALIGNMENT), 968bf215546Sopenharmony_ci &staging_buffer[code_offset], 969bf215546Sopenharmony_ci program.code_size, 970bf215546Sopenharmony_ci PVRX(CR_CDM_TERMINATE_PDS_CODE_ADDR_ALIGNMENT), 971bf215546Sopenharmony_ci 0, 972bf215546Sopenharmony_ci pds_upload_out); 973bf215546Sopenharmony_ci} 974bf215546Sopenharmony_ci 975bf215546Sopenharmony_cistatic void pvr_compute_ctx_ws_static_state_init( 976bf215546Sopenharmony_ci const struct pvr_device_info *const dev_info, 977bf215546Sopenharmony_ci const struct pvr_compute_ctx *const ctx, 978bf215546Sopenharmony_ci struct pvr_winsys_compute_ctx_static_state *const static_state) 979bf215546Sopenharmony_ci{ 980bf215546Sopenharmony_ci const struct pvr_compute_ctx_switch *const ctx_switch = &ctx->ctx_switch; 981bf215546Sopenharmony_ci 982bf215546Sopenharmony_ci /* CR_CDM_CONTEXT_... use state store program info. */ 983bf215546Sopenharmony_ci 984bf215546Sopenharmony_ci pvr_csb_pack (&static_state->cdm_ctx_store_pds0, 985bf215546Sopenharmony_ci CR_CDM_CONTEXT_PDS0, 986bf215546Sopenharmony_ci state) { 987bf215546Sopenharmony_ci state.data_addr = 988bf215546Sopenharmony_ci PVR_DEV_ADDR(ctx_switch->sr[0].pds.store_program.data_offset); 989bf215546Sopenharmony_ci state.code_addr = 990bf215546Sopenharmony_ci PVR_DEV_ADDR(ctx_switch->sr[0].pds.store_program.code_offset); 991bf215546Sopenharmony_ci } 992bf215546Sopenharmony_ci 993bf215546Sopenharmony_ci pvr_csb_pack (&static_state->cdm_ctx_store_pds0_b, 994bf215546Sopenharmony_ci CR_CDM_CONTEXT_PDS0, 995bf215546Sopenharmony_ci state) { 996bf215546Sopenharmony_ci state.data_addr = 997bf215546Sopenharmony_ci PVR_DEV_ADDR(ctx_switch->sr[1].pds.store_program.data_offset); 998bf215546Sopenharmony_ci state.code_addr = 999bf215546Sopenharmony_ci PVR_DEV_ADDR(ctx_switch->sr[1].pds.store_program.code_offset); 1000bf215546Sopenharmony_ci } 1001bf215546Sopenharmony_ci 1002bf215546Sopenharmony_ci pvr_csb_pack (&static_state->cdm_ctx_store_pds1, 1003bf215546Sopenharmony_ci CR_CDM_CONTEXT_PDS1, 1004bf215546Sopenharmony_ci state) { 1005bf215546Sopenharmony_ci /* Convert the data size from dwords to bytes. */ 1006bf215546Sopenharmony_ci const uint32_t store_program_data_size = 1007bf215546Sopenharmony_ci ctx_switch->sr[0].pds.store_program.data_size * 4U; 1008bf215546Sopenharmony_ci 1009bf215546Sopenharmony_ci state.pds_seq_dep = true; 1010bf215546Sopenharmony_ci state.usc_seq_dep = false; 1011bf215546Sopenharmony_ci state.target = true; 1012bf215546Sopenharmony_ci state.unified_size = ctx_switch->sr[0].usc.unified_size; 1013bf215546Sopenharmony_ci state.common_shared = false; 1014bf215546Sopenharmony_ci state.common_size = 0; 1015bf215546Sopenharmony_ci state.temp_size = 0; 1016bf215546Sopenharmony_ci 1017bf215546Sopenharmony_ci assert(store_program_data_size % 1018bf215546Sopenharmony_ci PVRX(VDMCTRL_PDS_STATE0_PDS_DATA_SIZE_UNIT_SIZE) == 1019bf215546Sopenharmony_ci 0); 1020bf215546Sopenharmony_ci state.data_size = store_program_data_size / 1021bf215546Sopenharmony_ci PVRX(VDMCTRL_PDS_STATE0_PDS_DATA_SIZE_UNIT_SIZE); 1022bf215546Sopenharmony_ci 1023bf215546Sopenharmony_ci state.fence = true; 1024bf215546Sopenharmony_ci } 1025bf215546Sopenharmony_ci 1026bf215546Sopenharmony_ci /* CR_CDM_TERMINATE_... use fence terminate info. */ 1027bf215546Sopenharmony_ci 1028bf215546Sopenharmony_ci pvr_csb_pack (&static_state->cdm_ctx_terminate_pds, 1029bf215546Sopenharmony_ci CR_CDM_TERMINATE_PDS, 1030bf215546Sopenharmony_ci state) { 1031bf215546Sopenharmony_ci state.data_addr = 1032bf215546Sopenharmony_ci PVR_DEV_ADDR(ctx_switch->sr_fence_terminate_program.data_offset); 1033bf215546Sopenharmony_ci state.code_addr = 1034bf215546Sopenharmony_ci PVR_DEV_ADDR(ctx_switch->sr_fence_terminate_program.code_offset); 1035bf215546Sopenharmony_ci } 1036bf215546Sopenharmony_ci 1037bf215546Sopenharmony_ci pvr_csb_pack (&static_state->cdm_ctx_terminate_pds1, 1038bf215546Sopenharmony_ci CR_CDM_TERMINATE_PDS1, 1039bf215546Sopenharmony_ci state) { 1040bf215546Sopenharmony_ci /* Convert the data size from dwords to bytes. */ 1041bf215546Sopenharmony_ci const uint32_t fence_terminate_program_data_size = 1042bf215546Sopenharmony_ci ctx_switch->sr_fence_terminate_program.data_size * 4U; 1043bf215546Sopenharmony_ci 1044bf215546Sopenharmony_ci state.pds_seq_dep = true; 1045bf215546Sopenharmony_ci state.usc_seq_dep = false; 1046bf215546Sopenharmony_ci state.target = !PVR_HAS_FEATURE(dev_info, compute_morton_capable); 1047bf215546Sopenharmony_ci state.unified_size = 0; 1048bf215546Sopenharmony_ci /* Common store is for shareds -- this will free the partitions. */ 1049bf215546Sopenharmony_ci state.common_shared = true; 1050bf215546Sopenharmony_ci state.common_size = 0; 1051bf215546Sopenharmony_ci state.temp_size = 0; 1052bf215546Sopenharmony_ci 1053bf215546Sopenharmony_ci assert(fence_terminate_program_data_size % 1054bf215546Sopenharmony_ci PVRX(VDMCTRL_PDS_STATE0_PDS_DATA_SIZE_UNIT_SIZE) == 1055bf215546Sopenharmony_ci 0); 1056bf215546Sopenharmony_ci state.data_size = fence_terminate_program_data_size / 1057bf215546Sopenharmony_ci PVRX(VDMCTRL_PDS_STATE0_PDS_DATA_SIZE_UNIT_SIZE); 1058bf215546Sopenharmony_ci state.fence = true; 1059bf215546Sopenharmony_ci } 1060bf215546Sopenharmony_ci 1061bf215546Sopenharmony_ci /* CR_CDM_RESUME_... use state load program info. */ 1062bf215546Sopenharmony_ci 1063bf215546Sopenharmony_ci pvr_csb_pack (&static_state->cdm_ctx_resume_pds0, 1064bf215546Sopenharmony_ci CR_CDM_CONTEXT_LOAD_PDS0, 1065bf215546Sopenharmony_ci state) { 1066bf215546Sopenharmony_ci state.data_addr = 1067bf215546Sopenharmony_ci PVR_DEV_ADDR(ctx_switch->sr[0].pds.load_program.data_offset); 1068bf215546Sopenharmony_ci state.code_addr = 1069bf215546Sopenharmony_ci PVR_DEV_ADDR(ctx_switch->sr[0].pds.load_program.code_offset); 1070bf215546Sopenharmony_ci } 1071bf215546Sopenharmony_ci 1072bf215546Sopenharmony_ci pvr_csb_pack (&static_state->cdm_ctx_resume_pds0_b, 1073bf215546Sopenharmony_ci CR_CDM_CONTEXT_LOAD_PDS0, 1074bf215546Sopenharmony_ci state) { 1075bf215546Sopenharmony_ci state.data_addr = 1076bf215546Sopenharmony_ci PVR_DEV_ADDR(ctx_switch->sr[1].pds.load_program.data_offset); 1077bf215546Sopenharmony_ci state.code_addr = 1078bf215546Sopenharmony_ci PVR_DEV_ADDR(ctx_switch->sr[1].pds.load_program.code_offset); 1079bf215546Sopenharmony_ci } 1080bf215546Sopenharmony_ci} 1081bf215546Sopenharmony_ci 1082bf215546Sopenharmony_cistatic void pvr_compute_ctx_ws_create_info_init( 1083bf215546Sopenharmony_ci const struct pvr_compute_ctx *const ctx, 1084bf215546Sopenharmony_ci enum pvr_winsys_ctx_priority priority, 1085bf215546Sopenharmony_ci struct pvr_winsys_compute_ctx_create_info *const create_info) 1086bf215546Sopenharmony_ci{ 1087bf215546Sopenharmony_ci create_info->priority = priority; 1088bf215546Sopenharmony_ci 1089bf215546Sopenharmony_ci pvr_compute_ctx_ws_static_state_init(&ctx->device->pdevice->dev_info, 1090bf215546Sopenharmony_ci ctx, 1091bf215546Sopenharmony_ci &create_info->static_state); 1092bf215546Sopenharmony_ci} 1093bf215546Sopenharmony_ci 1094bf215546Sopenharmony_ciVkResult pvr_compute_ctx_create(struct pvr_device *const device, 1095bf215546Sopenharmony_ci enum pvr_winsys_ctx_priority priority, 1096bf215546Sopenharmony_ci struct pvr_compute_ctx **const ctx_out) 1097bf215546Sopenharmony_ci{ 1098bf215546Sopenharmony_ci struct pvr_winsys_compute_ctx_create_info create_info; 1099bf215546Sopenharmony_ci struct pvr_compute_ctx *ctx; 1100bf215546Sopenharmony_ci VkResult result; 1101bf215546Sopenharmony_ci 1102bf215546Sopenharmony_ci ctx = vk_alloc(&device->vk.alloc, 1103bf215546Sopenharmony_ci sizeof(*ctx), 1104bf215546Sopenharmony_ci 8, 1105bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 1106bf215546Sopenharmony_ci if (!ctx) 1107bf215546Sopenharmony_ci return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 1108bf215546Sopenharmony_ci 1109bf215546Sopenharmony_ci ctx->device = device; 1110bf215546Sopenharmony_ci 1111bf215546Sopenharmony_ci result = pvr_bo_alloc( 1112bf215546Sopenharmony_ci device, 1113bf215546Sopenharmony_ci device->heaps.general_heap, 1114bf215546Sopenharmony_ci rogue_get_cdm_context_resume_buffer_size(&device->pdevice->dev_info), 1115bf215546Sopenharmony_ci rogue_get_cdm_context_resume_buffer_alignment(&device->pdevice->dev_info), 1116bf215546Sopenharmony_ci PVR_WINSYS_BO_FLAG_CPU_ACCESS | PVR_WINSYS_BO_FLAG_GPU_UNCACHED, 1117bf215546Sopenharmony_ci &ctx->ctx_switch.compute_state_bo); 1118bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1119bf215546Sopenharmony_ci goto err_free_ctx; 1120bf215546Sopenharmony_ci 1121bf215546Sopenharmony_ci /* TODO: Change this so that enabling storage to B doesn't change the array 1122bf215546Sopenharmony_ci * size. Instead of looping we could unroll this and have the second 1123bf215546Sopenharmony_ci * programs setup depending on the B enable. Doing it that way would make 1124bf215546Sopenharmony_ci * things more obvious. 1125bf215546Sopenharmony_ci */ 1126bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(ctx->ctx_switch.sr); i++) { 1127bf215546Sopenharmony_ci result = pvr_ctx_sr_programs_setup(device, 1128bf215546Sopenharmony_ci PVR_CTX_SR_COMPUTE_TARGET, 1129bf215546Sopenharmony_ci &ctx->ctx_switch.sr[i]); 1130bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 1131bf215546Sopenharmony_ci for (uint32_t j = 0; j < i; j++) 1132bf215546Sopenharmony_ci pvr_ctx_sr_programs_cleanup(device, &ctx->ctx_switch.sr[j]); 1133bf215546Sopenharmony_ci 1134bf215546Sopenharmony_ci goto err_free_state_buffer; 1135bf215546Sopenharmony_ci } 1136bf215546Sopenharmony_ci } 1137bf215546Sopenharmony_ci 1138bf215546Sopenharmony_ci result = pvr_pds_sr_fence_terminate_program_create_and_upload( 1139bf215546Sopenharmony_ci device, 1140bf215546Sopenharmony_ci &ctx->ctx_switch.sr_fence_terminate_program); 1141bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1142bf215546Sopenharmony_ci goto err_free_sr_programs; 1143bf215546Sopenharmony_ci 1144bf215546Sopenharmony_ci pvr_compute_ctx_ws_create_info_init(ctx, priority, &create_info); 1145bf215546Sopenharmony_ci 1146bf215546Sopenharmony_ci result = pvr_ctx_reset_cmd_init(device, &ctx->reset_cmd); 1147bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1148bf215546Sopenharmony_ci goto err_free_pds_fence_terminate_program; 1149bf215546Sopenharmony_ci 1150bf215546Sopenharmony_ci result = device->ws->ops->compute_ctx_create(device->ws, 1151bf215546Sopenharmony_ci &create_info, 1152bf215546Sopenharmony_ci &ctx->ws_ctx); 1153bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1154bf215546Sopenharmony_ci goto err_fini_reset_cmd; 1155bf215546Sopenharmony_ci 1156bf215546Sopenharmony_ci *ctx_out = ctx; 1157bf215546Sopenharmony_ci 1158bf215546Sopenharmony_ci return VK_SUCCESS; 1159bf215546Sopenharmony_ci 1160bf215546Sopenharmony_cierr_fini_reset_cmd: 1161bf215546Sopenharmony_ci pvr_ctx_reset_cmd_fini(device, &ctx->reset_cmd); 1162bf215546Sopenharmony_ci 1163bf215546Sopenharmony_cierr_free_pds_fence_terminate_program: 1164bf215546Sopenharmony_ci pvr_bo_free(device, ctx->ctx_switch.sr_fence_terminate_program.pvr_bo); 1165bf215546Sopenharmony_ci 1166bf215546Sopenharmony_cierr_free_sr_programs: 1167bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(ctx->ctx_switch.sr); ++i) 1168bf215546Sopenharmony_ci pvr_ctx_sr_programs_cleanup(device, &ctx->ctx_switch.sr[i]); 1169bf215546Sopenharmony_ci 1170bf215546Sopenharmony_cierr_free_state_buffer: 1171bf215546Sopenharmony_ci pvr_bo_free(device, ctx->ctx_switch.compute_state_bo); 1172bf215546Sopenharmony_ci 1173bf215546Sopenharmony_cierr_free_ctx: 1174bf215546Sopenharmony_ci vk_free(&device->vk.alloc, ctx); 1175bf215546Sopenharmony_ci 1176bf215546Sopenharmony_ci return result; 1177bf215546Sopenharmony_ci} 1178bf215546Sopenharmony_ci 1179bf215546Sopenharmony_civoid pvr_compute_ctx_destroy(struct pvr_compute_ctx *const ctx) 1180bf215546Sopenharmony_ci{ 1181bf215546Sopenharmony_ci struct pvr_device *device = ctx->device; 1182bf215546Sopenharmony_ci 1183bf215546Sopenharmony_ci device->ws->ops->compute_ctx_destroy(ctx->ws_ctx); 1184bf215546Sopenharmony_ci 1185bf215546Sopenharmony_ci pvr_ctx_reset_cmd_fini(device, &ctx->reset_cmd); 1186bf215546Sopenharmony_ci 1187bf215546Sopenharmony_ci pvr_bo_free(device, ctx->ctx_switch.sr_fence_terminate_program.pvr_bo); 1188bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(ctx->ctx_switch.sr); ++i) 1189bf215546Sopenharmony_ci pvr_ctx_sr_programs_cleanup(device, &ctx->ctx_switch.sr[i]); 1190bf215546Sopenharmony_ci 1191bf215546Sopenharmony_ci pvr_bo_free(device, ctx->ctx_switch.compute_state_bo); 1192bf215546Sopenharmony_ci 1193bf215546Sopenharmony_ci vk_free(&device->vk.alloc, ctx); 1194bf215546Sopenharmony_ci} 1195bf215546Sopenharmony_ci 1196bf215546Sopenharmony_cistatic void pvr_transfer_ctx_ws_create_info_init( 1197bf215546Sopenharmony_ci enum pvr_winsys_ctx_priority priority, 1198bf215546Sopenharmony_ci struct pvr_winsys_transfer_ctx_create_info *const create_info) 1199bf215546Sopenharmony_ci{ 1200bf215546Sopenharmony_ci create_info->priority = priority; 1201bf215546Sopenharmony_ci} 1202bf215546Sopenharmony_ci 1203bf215546Sopenharmony_cistatic VkResult pvr_transfer_ctx_setup_shaders(struct pvr_device *device, 1204bf215546Sopenharmony_ci struct pvr_transfer_ctx *ctx) 1205bf215546Sopenharmony_ci{ 1206bf215546Sopenharmony_ci const uint32_t cache_line_size = 1207bf215546Sopenharmony_ci rogue_get_slc_cache_line_size(&device->pdevice->dev_info); 1208bf215546Sopenharmony_ci VkResult result; 1209bf215546Sopenharmony_ci 1210bf215546Sopenharmony_ci /* TODO: Setup USC fragments. */ 1211bf215546Sopenharmony_ci 1212bf215546Sopenharmony_ci /* Setup EOT program. */ 1213bf215546Sopenharmony_ci result = pvr_gpu_upload_usc(device, 1214bf215546Sopenharmony_ci pvr_transfer_eot_usc_code, 1215bf215546Sopenharmony_ci sizeof(pvr_transfer_eot_usc_code), 1216bf215546Sopenharmony_ci cache_line_size, 1217bf215546Sopenharmony_ci &ctx->usc_eot_bo); 1218bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1219bf215546Sopenharmony_ci return result; 1220bf215546Sopenharmony_ci 1221bf215546Sopenharmony_ci STATIC_ASSERT(ARRAY_SIZE(pvr_transfer_eot_usc_offsets) == 1222bf215546Sopenharmony_ci ARRAY_SIZE(ctx->transfer_mrts)); 1223bf215546Sopenharmony_ci for (uint32_t i = 0U; i < ARRAY_SIZE(pvr_transfer_eot_usc_offsets); i++) { 1224bf215546Sopenharmony_ci ctx->transfer_mrts[i] = 1225bf215546Sopenharmony_ci PVR_DEV_ADDR_OFFSET(ctx->usc_eot_bo->vma->dev_addr, 1226bf215546Sopenharmony_ci pvr_transfer_eot_usc_offsets[i]); 1227bf215546Sopenharmony_ci } 1228bf215546Sopenharmony_ci 1229bf215546Sopenharmony_ci return VK_SUCCESS; 1230bf215546Sopenharmony_ci} 1231bf215546Sopenharmony_ci 1232bf215546Sopenharmony_cistatic void pvr_transfer_ctx_fini_shaders(struct pvr_device *device, 1233bf215546Sopenharmony_ci struct pvr_transfer_ctx *ctx) 1234bf215546Sopenharmony_ci{ 1235bf215546Sopenharmony_ci pvr_bo_free(device, ctx->usc_eot_bo); 1236bf215546Sopenharmony_ci} 1237bf215546Sopenharmony_ci 1238bf215546Sopenharmony_ciVkResult pvr_transfer_ctx_create(struct pvr_device *const device, 1239bf215546Sopenharmony_ci enum pvr_winsys_ctx_priority priority, 1240bf215546Sopenharmony_ci struct pvr_transfer_ctx **const ctx_out) 1241bf215546Sopenharmony_ci{ 1242bf215546Sopenharmony_ci struct pvr_winsys_transfer_ctx_create_info create_info; 1243bf215546Sopenharmony_ci struct pvr_transfer_ctx *ctx; 1244bf215546Sopenharmony_ci VkResult result; 1245bf215546Sopenharmony_ci 1246bf215546Sopenharmony_ci ctx = vk_zalloc(&device->vk.alloc, 1247bf215546Sopenharmony_ci sizeof(*ctx), 1248bf215546Sopenharmony_ci 8U, 1249bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 1250bf215546Sopenharmony_ci if (!ctx) 1251bf215546Sopenharmony_ci return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 1252bf215546Sopenharmony_ci 1253bf215546Sopenharmony_ci ctx->device = device; 1254bf215546Sopenharmony_ci 1255bf215546Sopenharmony_ci result = pvr_ctx_reset_cmd_init(device, &ctx->reset_cmd); 1256bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1257bf215546Sopenharmony_ci goto err_free_ctx; 1258bf215546Sopenharmony_ci 1259bf215546Sopenharmony_ci pvr_transfer_ctx_ws_create_info_init(priority, &create_info); 1260bf215546Sopenharmony_ci 1261bf215546Sopenharmony_ci result = device->ws->ops->transfer_ctx_create(device->ws, 1262bf215546Sopenharmony_ci &create_info, 1263bf215546Sopenharmony_ci &ctx->ws_ctx); 1264bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1265bf215546Sopenharmony_ci goto err_fini_reset_cmd; 1266bf215546Sopenharmony_ci 1267bf215546Sopenharmony_ci result = pvr_transfer_ctx_setup_shaders(device, ctx); 1268bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1269bf215546Sopenharmony_ci goto err_destroy_transfer_ctx; 1270bf215546Sopenharmony_ci 1271bf215546Sopenharmony_ci /* Create the PDS Uniform/Tex state code segment array. */ 1272bf215546Sopenharmony_ci for (uint32_t i = 0U; i < ARRAY_SIZE(ctx->pds_unitex_code); i++) { 1273bf215546Sopenharmony_ci for (uint32_t j = 0U; j < ARRAY_SIZE(ctx->pds_unitex_code[0U]); j++) { 1274bf215546Sopenharmony_ci if (i == 0U && j == 0U) 1275bf215546Sopenharmony_ci continue; 1276bf215546Sopenharmony_ci 1277bf215546Sopenharmony_ci result = pvr_pds_unitex_state_program_create_and_upload( 1278bf215546Sopenharmony_ci device, 1279bf215546Sopenharmony_ci NULL, 1280bf215546Sopenharmony_ci i, 1281bf215546Sopenharmony_ci j, 1282bf215546Sopenharmony_ci &ctx->pds_unitex_code[i][j]); 1283bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 1284bf215546Sopenharmony_ci goto err_free_pds_unitex_bos; 1285bf215546Sopenharmony_ci } 1286bf215546Sopenharmony_ci } 1287bf215546Sopenharmony_ci } 1288bf215546Sopenharmony_ci 1289bf215546Sopenharmony_ci *ctx_out = ctx; 1290bf215546Sopenharmony_ci 1291bf215546Sopenharmony_ci return VK_SUCCESS; 1292bf215546Sopenharmony_ci 1293bf215546Sopenharmony_cierr_free_pds_unitex_bos: 1294bf215546Sopenharmony_ci for (uint32_t i = 0U; i < ARRAY_SIZE(ctx->pds_unitex_code); i++) { 1295bf215546Sopenharmony_ci for (uint32_t j = 0U; j < ARRAY_SIZE(ctx->pds_unitex_code[0U]); j++) { 1296bf215546Sopenharmony_ci if (!ctx->pds_unitex_code[i][j].pvr_bo) 1297bf215546Sopenharmony_ci continue; 1298bf215546Sopenharmony_ci 1299bf215546Sopenharmony_ci pvr_bo_free(device, ctx->pds_unitex_code[i][j].pvr_bo); 1300bf215546Sopenharmony_ci } 1301bf215546Sopenharmony_ci } 1302bf215546Sopenharmony_ci 1303bf215546Sopenharmony_ci pvr_transfer_ctx_fini_shaders(device, ctx); 1304bf215546Sopenharmony_ci 1305bf215546Sopenharmony_cierr_destroy_transfer_ctx: 1306bf215546Sopenharmony_ci device->ws->ops->transfer_ctx_destroy(ctx->ws_ctx); 1307bf215546Sopenharmony_ci 1308bf215546Sopenharmony_cierr_fini_reset_cmd: 1309bf215546Sopenharmony_ci pvr_ctx_reset_cmd_fini(device, &ctx->reset_cmd); 1310bf215546Sopenharmony_ci 1311bf215546Sopenharmony_cierr_free_ctx: 1312bf215546Sopenharmony_ci vk_free(&device->vk.alloc, ctx); 1313bf215546Sopenharmony_ci 1314bf215546Sopenharmony_ci return result; 1315bf215546Sopenharmony_ci} 1316bf215546Sopenharmony_ci 1317bf215546Sopenharmony_civoid pvr_transfer_ctx_destroy(struct pvr_transfer_ctx *const ctx) 1318bf215546Sopenharmony_ci{ 1319bf215546Sopenharmony_ci struct pvr_device *device = ctx->device; 1320bf215546Sopenharmony_ci 1321bf215546Sopenharmony_ci for (uint32_t i = 0U; i < ARRAY_SIZE(ctx->pds_unitex_code); i++) { 1322bf215546Sopenharmony_ci for (uint32_t j = 0U; j < ARRAY_SIZE(ctx->pds_unitex_code[0U]); j++) { 1323bf215546Sopenharmony_ci if (!ctx->pds_unitex_code[i][j].pvr_bo) 1324bf215546Sopenharmony_ci continue; 1325bf215546Sopenharmony_ci 1326bf215546Sopenharmony_ci pvr_bo_free(device, ctx->pds_unitex_code[i][j].pvr_bo); 1327bf215546Sopenharmony_ci } 1328bf215546Sopenharmony_ci } 1329bf215546Sopenharmony_ci 1330bf215546Sopenharmony_ci pvr_transfer_ctx_fini_shaders(device, ctx); 1331bf215546Sopenharmony_ci device->ws->ops->transfer_ctx_destroy(ctx->ws_ctx); 1332bf215546Sopenharmony_ci pvr_ctx_reset_cmd_fini(device, &ctx->reset_cmd); 1333bf215546Sopenharmony_ci vk_free(&device->vk.alloc, ctx); 1334bf215546Sopenharmony_ci} 1335