From edca79bc41b3a10ed2d22c252b3cd28e5dc299d7 Mon Sep 17 00:00:00 2001 From: Erik Faye-Lund Date: Tue, 25 Nov 2025 16:29:38 +0100 Subject: [PATCH] pvr: prepare winsys files for multi-arch Acked-by: Frank Binns Part-of: --- src/imagination/vulkan/meson.build | 5 + .../winsys/powervr/pvr_arch_drm_job_compute.c | 36 + .../winsys/powervr/pvr_arch_drm_job_render.c | 49 ++ .../winsys/powervr/pvr_drm_job_compute.c | 50 +- .../winsys/powervr/pvr_drm_job_compute.h | 5 + .../winsys/powervr/pvr_drm_job_render.c | 40 - .../winsys/powervr/pvr_drm_job_render.h | 7 + .../vulkan/winsys/pvr_winsys_helper.c | 14 +- .../pvrsrvkm/pvr_arch_srv_job_compute.c | 137 ++++ .../winsys/pvrsrvkm/pvr_arch_srv_job_render.c | 753 ++++++++++++++++++ .../pvrsrvkm/pvr_arch_srv_job_transfer.c | 114 +++ .../winsys/pvrsrvkm/pvr_srv_job_compute.c | 109 --- .../winsys/pvrsrvkm/pvr_srv_job_compute.h | 6 + .../winsys/pvrsrvkm/pvr_srv_job_render.c | 641 +-------------- .../winsys/pvrsrvkm/pvr_srv_job_render.h | 21 + .../winsys/pvrsrvkm/pvr_srv_job_transfer.c | 87 -- .../winsys/pvrsrvkm/pvr_srv_job_transfer.h | 7 + 17 files changed, 1167 insertions(+), 914 deletions(-) create mode 100644 src/imagination/vulkan/winsys/powervr/pvr_arch_drm_job_compute.c create mode 100644 src/imagination/vulkan/winsys/powervr/pvr_arch_drm_job_render.c create mode 100644 src/imagination/vulkan/winsys/pvrsrvkm/pvr_arch_srv_job_compute.c create mode 100644 src/imagination/vulkan/winsys/pvrsrvkm/pvr_arch_srv_job_render.c create mode 100644 src/imagination/vulkan/winsys/pvrsrvkm/pvr_arch_srv_job_transfer.c diff --git a/src/imagination/vulkan/meson.build b/src/imagination/vulkan/meson.build index a3e1ca39204..94e88ae4c0f 100644 --- a/src/imagination/vulkan/meson.build +++ b/src/imagination/vulkan/meson.build @@ -16,6 +16,8 @@ pvr_entrypoints = custom_target( ) pvr_files = files( + 'winsys/powervr/pvr_arch_drm_job_compute.c', + 'winsys/powervr/pvr_arch_drm_job_render.c', 'winsys/powervr/pvr_drm.c', 'winsys/powervr/pvr_drm_bo.c', 'winsys/powervr/pvr_drm_job_compute.c', @@ -92,6 +94,9 @@ pvr_flags = [ if with_imagination_srv pvr_files += files( + 'winsys/pvrsrvkm/pvr_arch_srv_job_compute.c', + 'winsys/pvrsrvkm/pvr_arch_srv_job_render.c', + 'winsys/pvrsrvkm/pvr_arch_srv_job_transfer.c', 'winsys/pvrsrvkm/pvr_srv.c', 'winsys/pvrsrvkm/pvr_srv_bo.c', 'winsys/pvrsrvkm/pvr_srv_bridge.c', diff --git a/src/imagination/vulkan/winsys/powervr/pvr_arch_drm_job_compute.c b/src/imagination/vulkan/winsys/powervr/pvr_arch_drm_job_compute.c new file mode 100644 index 00000000000..7781dcc3c6e --- /dev/null +++ b/src/imagination/vulkan/winsys/powervr/pvr_arch_drm_job_compute.c @@ -0,0 +1,36 @@ +/* + * Copyright © 2022 Imagination Technologies Ltd. + * + * SPDX-License-Identifier: MIT + */ + +#include "pvr_drm_job_compute.h" + +#include "pvr_csb.h" + +void pvr_drm_compute_ctx_static_state_init( + const struct pvr_winsys_compute_ctx_create_info *create_info, + uint8_t *stream_ptr_start, + uint32_t *stream_len_ptr) +{ + const struct pvr_winsys_compute_ctx_static_state *ws_static_state = + &create_info->static_state; + uint64_t *stream_ptr = (uint64_t *)stream_ptr_start; + + /* Leave space for stream header. */ + stream_ptr += pvr_cmd_length(KMD_STREAM_HDR) / 2; + + *stream_ptr++ = ws_static_state->cdm_ctx_store_pds0; + *stream_ptr++ = ws_static_state->cdm_ctx_store_pds1; + *stream_ptr++ = ws_static_state->cdm_ctx_terminate_pds; + *stream_ptr++ = ws_static_state->cdm_ctx_terminate_pds1; + *stream_ptr++ = ws_static_state->cdm_ctx_resume_pds0; + *stream_ptr++ = ws_static_state->cdm_ctx_store_pds0_b; + *stream_ptr++ = ws_static_state->cdm_ctx_resume_pds0_b; + + *stream_len_ptr = ((uint8_t *)stream_ptr - stream_ptr_start); + + pvr_csb_pack ((uint64_t *)stream_ptr_start, KMD_STREAM_HDR, value) { + value.length = *stream_len_ptr; + } +} diff --git a/src/imagination/vulkan/winsys/powervr/pvr_arch_drm_job_render.c b/src/imagination/vulkan/winsys/powervr/pvr_arch_drm_job_render.c new file mode 100644 index 00000000000..3864878bebf --- /dev/null +++ b/src/imagination/vulkan/winsys/powervr/pvr_arch_drm_job_render.c @@ -0,0 +1,49 @@ +/* + * Copyright © 2022 Imagination Technologies Ltd. + * + * SPDX-License-Identifier: MIT + */ + +#include "pvr_drm_job_render.h" + +#include "pvr_csb.h" + +void pvr_drm_render_ctx_static_state_init( + struct pvr_winsys_render_ctx_create_info *create_info, + uint8_t *stream_ptr_start, + uint32_t *stream_len_ptr) +{ + struct pvr_winsys_render_ctx_static_state *ws_static_state = + &create_info->static_state; + uint64_t *stream_ptr = (uint64_t *)stream_ptr_start; + + /* Leave space for stream header. */ + stream_ptr += pvr_cmd_length(KMD_STREAM_HDR) / 2; + + *stream_ptr++ = ws_static_state->vdm_ctx_state_base_addr; + /* geom_reg_vdm_context_state_resume_addr is unused and zeroed. */ + *stream_ptr++ = 0; + *stream_ptr++ = ws_static_state->geom_ctx_state_base_addr; + + for (uint32_t i = 0; i < ARRAY_SIZE(ws_static_state->geom_state); i++) { + *stream_ptr++ = ws_static_state->geom_state[i].vdm_ctx_store_task0; + *stream_ptr++ = ws_static_state->geom_state[i].vdm_ctx_store_task1; + *stream_ptr++ = ws_static_state->geom_state[i].vdm_ctx_store_task2; + /* {store, resume}_task{3, 4} are unused and zeroed. */ + *stream_ptr++ = 0; + *stream_ptr++ = 0; + + *stream_ptr++ = ws_static_state->geom_state[i].vdm_ctx_resume_task0; + *stream_ptr++ = ws_static_state->geom_state[i].vdm_ctx_resume_task1; + *stream_ptr++ = ws_static_state->geom_state[i].vdm_ctx_resume_task2; + /* {store, resume}_task{3, 4} are unused and zeroed. */ + *stream_ptr++ = 0; + *stream_ptr++ = 0; + } + + *stream_len_ptr = ((uint8_t *)stream_ptr - stream_ptr_start); + + pvr_csb_pack ((uint64_t *)stream_ptr_start, KMD_STREAM_HDR, value) { + value.length = *stream_len_ptr; + } +} diff --git a/src/imagination/vulkan/winsys/powervr/pvr_drm_job_compute.c b/src/imagination/vulkan/winsys/powervr/pvr_drm_job_compute.c index 6a56a331cb7..0a13cf03f3e 100644 --- a/src/imagination/vulkan/winsys/powervr/pvr_drm_job_compute.c +++ b/src/imagination/vulkan/winsys/powervr/pvr_drm_job_compute.c @@ -21,26 +21,19 @@ * SOFTWARE. */ -#include -#include -#include -#include -#include -#include -#include - -#include "drm-uapi/pvr_drm.h" -#include "pvr_csb.h" -#include "pvr_drm.h" -#include "pvr_drm_job_common.h" #include "pvr_drm_job_compute.h" -#include "pvr_winsys.h" -#include "pvr_winsys_helper.h" -#include "util/macros.h" + #include "vk_alloc.h" #include "vk_drm_syncobj.h" #include "vk_log.h" +#include "drm-uapi/pvr_drm.h" + +#include "pvr_drm_job_common.h" +#include "pvr_drm.h" +#include "pvr_macros.h" +#include "pvr_winsys_helper.h" + struct pvr_drm_winsys_compute_ctx { struct pvr_winsys_compute_ctx base; @@ -51,33 +44,6 @@ struct pvr_drm_winsys_compute_ctx { #define to_pvr_drm_winsys_compute_ctx(ctx) \ container_of(ctx, struct pvr_drm_winsys_compute_ctx, base) -static void pvr_drm_compute_ctx_static_state_init( - const struct pvr_winsys_compute_ctx_create_info *create_info, - uint8_t *stream_ptr_start, - uint32_t *stream_len_ptr) -{ - const struct pvr_winsys_compute_ctx_static_state *ws_static_state = - &create_info->static_state; - uint64_t *stream_ptr = (uint64_t *)stream_ptr_start; - - /* Leave space for stream header. */ - stream_ptr += pvr_cmd_length(KMD_STREAM_HDR) / 2; - - *stream_ptr++ = ws_static_state->cdm_ctx_store_pds0; - *stream_ptr++ = ws_static_state->cdm_ctx_store_pds1; - *stream_ptr++ = ws_static_state->cdm_ctx_terminate_pds; - *stream_ptr++ = ws_static_state->cdm_ctx_terminate_pds1; - *stream_ptr++ = ws_static_state->cdm_ctx_resume_pds0; - *stream_ptr++ = ws_static_state->cdm_ctx_store_pds0_b; - *stream_ptr++ = ws_static_state->cdm_ctx_resume_pds0_b; - - *stream_len_ptr = ((uint8_t *)stream_ptr - stream_ptr_start); - - pvr_csb_pack ((uint64_t *)stream_ptr_start, KMD_STREAM_HDR, value) { - value.length = *stream_len_ptr; - } -} - VkResult pvr_drm_winsys_compute_ctx_create( struct pvr_winsys *ws, const struct pvr_winsys_compute_ctx_create_info *create_info, diff --git a/src/imagination/vulkan/winsys/powervr/pvr_drm_job_compute.h b/src/imagination/vulkan/winsys/powervr/pvr_drm_job_compute.h index d3037ab1a5a..37f209fc083 100644 --- a/src/imagination/vulkan/winsys/powervr/pvr_drm_job_compute.h +++ b/src/imagination/vulkan/winsys/powervr/pvr_drm_job_compute.h @@ -49,4 +49,9 @@ VkResult pvr_drm_winsys_compute_submit( const struct pvr_device_info *dev_info, struct vk_sync *signal_sync); +void pvr_drm_compute_ctx_static_state_init( + const struct pvr_winsys_compute_ctx_create_info *create_info, + uint8_t *stream_ptr_start, + uint32_t *stream_len_ptr); + #endif /* PVR_DRM_JOB_COMPUTE_H */ diff --git a/src/imagination/vulkan/winsys/powervr/pvr_drm_job_render.c b/src/imagination/vulkan/winsys/powervr/pvr_drm_job_render.c index a44f8b0f3b1..6e85b7eb680 100644 --- a/src/imagination/vulkan/winsys/powervr/pvr_drm_job_render.c +++ b/src/imagination/vulkan/winsys/powervr/pvr_drm_job_render.c @@ -143,46 +143,6 @@ void pvr_drm_winsys_free_list_destroy(struct pvr_winsys_free_list *free_list) vk_free(drm_ws->base.alloc, free_list); } -static void pvr_drm_render_ctx_static_state_init( - struct pvr_winsys_render_ctx_create_info *create_info, - uint8_t *stream_ptr_start, - uint32_t *stream_len_ptr) -{ - struct pvr_winsys_render_ctx_static_state *ws_static_state = - &create_info->static_state; - uint64_t *stream_ptr = (uint64_t *)stream_ptr_start; - - /* Leave space for stream header. */ - stream_ptr += pvr_cmd_length(KMD_STREAM_HDR) / 2; - - *stream_ptr++ = ws_static_state->vdm_ctx_state_base_addr; - /* geom_reg_vdm_context_state_resume_addr is unused and zeroed. */ - *stream_ptr++ = 0; - *stream_ptr++ = ws_static_state->geom_ctx_state_base_addr; - - for (uint32_t i = 0; i < ARRAY_SIZE(ws_static_state->geom_state); i++) { - *stream_ptr++ = ws_static_state->geom_state[i].vdm_ctx_store_task0; - *stream_ptr++ = ws_static_state->geom_state[i].vdm_ctx_store_task1; - *stream_ptr++ = ws_static_state->geom_state[i].vdm_ctx_store_task2; - /* {store, resume}_task{3, 4} are unused and zeroed. */ - *stream_ptr++ = 0; - *stream_ptr++ = 0; - - *stream_ptr++ = ws_static_state->geom_state[i].vdm_ctx_resume_task0; - *stream_ptr++ = ws_static_state->geom_state[i].vdm_ctx_resume_task1; - *stream_ptr++ = ws_static_state->geom_state[i].vdm_ctx_resume_task2; - /* {store, resume}_task{3, 4} are unused and zeroed. */ - *stream_ptr++ = 0; - *stream_ptr++ = 0; - } - - *stream_len_ptr = ((uint8_t *)stream_ptr - stream_ptr_start); - - pvr_csb_pack ((uint64_t *)stream_ptr_start, KMD_STREAM_HDR, value) { - value.length = *stream_len_ptr; - } -} - struct pvr_drm_winsys_render_ctx { struct pvr_winsys_render_ctx base; diff --git a/src/imagination/vulkan/winsys/powervr/pvr_drm_job_render.h b/src/imagination/vulkan/winsys/powervr/pvr_drm_job_render.h index 204451afff9..82c2165f580 100644 --- a/src/imagination/vulkan/winsys/powervr/pvr_drm_job_render.h +++ b/src/imagination/vulkan/winsys/powervr/pvr_drm_job_render.h @@ -27,6 +27,8 @@ #include #include +#include "pvr_macros.h" + struct pvr_device_info; struct pvr_winsys; struct pvr_winsys_free_list; @@ -74,4 +76,9 @@ VkResult pvr_drm_winsys_render_submit( struct vk_sync *signal_sync_geom, struct vk_sync *signal_sync_frag); +void pvr_drm_render_ctx_static_state_init( + struct pvr_winsys_render_ctx_create_info *create_info, + uint8_t *stream_ptr_start, + uint32_t *stream_len_ptr); + #endif /* PVR_DRM_JOB_RENDER_H */ diff --git a/src/imagination/vulkan/winsys/pvr_winsys_helper.c b/src/imagination/vulkan/winsys/pvr_winsys_helper.c index 9e9888edeae..2dcddfc17ad 100644 --- a/src/imagination/vulkan/winsys/pvr_winsys_helper.c +++ b/src/imagination/vulkan/winsys/pvr_winsys_helper.c @@ -29,7 +29,6 @@ #include "pco/pco_data.h" #include "pco_uscgen_programs.h" -#include "pvr_csb.h" #include "pvr_pass.h" #include "pvr_pds.h" #include "pvr_types.h" @@ -276,6 +275,8 @@ void pvr_winsys_helper_free_static_memory( pvr_buffer_destroy_and_unmap(general_vma); } +static uint32_t get_doutu_sample_rate(void); + static void pvr_setup_static_vdm_sync(uint8_t *const pds_ptr, uint64_t pds_sync_offset_in_bytes, uint8_t *const usc_ptr, @@ -292,7 +293,7 @@ static void pvr_setup_static_vdm_sync(uint8_t *const pds_ptr, pvr_pds_setup_doutu(&ppp_state_update_program.usc_task_control, usc_sync_offset_in_bytes, precomp_data->temps, - ROGUE_PDSINST_DOUTU_SAMPLE_RATE_INSTANCE, + get_doutu_sample_rate(), false); pvr_pds_kick_usc(&ppp_state_update_program, @@ -357,3 +358,12 @@ err_pvr_srv_winsys_buffer_unmap_general: err_out: return result; } + +/* Leave this at the very end, to avoid leakage of HW-defs here */ +#define PVR_BUILD_ARCH_ROGUE +#include "pvr_csb.h" + +static uint32_t get_doutu_sample_rate(void) +{ + return ROGUE_PDSINST_DOUTU_SAMPLE_RATE_INSTANCE; +} diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_arch_srv_job_compute.c b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_arch_srv_job_compute.c new file mode 100644 index 00000000000..911265afac1 --- /dev/null +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_arch_srv_job_compute.c @@ -0,0 +1,137 @@ +/* + * Copyright © 2022 Imagination Technologies Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "pvr_srv_job_compute.h" + +#include "fw-api/pvr_rogue_fwif.h" + +#include "pvr_csb.h" +#include "pvr_device_info.h" + +static uint32_t +pvr_srv_compute_cmd_stream_load(struct rogue_fwif_cmd_compute *const cmd, + const uint8_t *const stream, + const uint32_t stream_len, + const struct pvr_device_info *const dev_info) +{ + const uint32_t *stream_ptr = (const uint32_t *)stream; + struct rogue_fwif_cdm_regs *const regs = &cmd->regs; + uint32_t main_stream_len = + pvr_csb_unpack((uint64_t *)stream_ptr, KMD_STREAM_HDR).length; + + stream_ptr += pvr_cmd_length(KMD_STREAM_HDR); + + regs->tpu_border_colour_table = *(const uint64_t *)stream_ptr; + stream_ptr += pvr_cmd_length(CR_TPU_BORDER_COLOUR_TABLE_CDM); + + regs->cdm_ctrl_stream_base = *(const uint64_t *)stream_ptr; + stream_ptr += pvr_cmd_length(CR_CDM_CTRL_STREAM_BASE); + + regs->cdm_context_state_base_addr = *(const uint64_t *)stream_ptr; + stream_ptr += pvr_cmd_length(CR_CDM_CONTEXT_STATE_BASE); + + regs->cdm_resume_pds1 = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_CDM_CONTEXT_PDS1); + + if (PVR_HAS_FEATURE(dev_info, compute_morton_capable)) { + regs->cdm_item = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_CDM_ITEM); + } + + if (PVR_HAS_FEATURE(dev_info, cluster_grouping)) { + regs->compute_cluster = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_COMPUTE_CLUSTER); + } + + if (PVR_HAS_FEATURE(dev_info, tpu_dm_global_registers)) { + regs->tpu_tag_cdm_ctrl = *stream_ptr; + stream_ptr++; + } + + if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) { + cmd->execute_count = *stream_ptr; + stream_ptr++; + } + + assert((const uint8_t *)stream_ptr - stream <= stream_len); + assert((const uint8_t *)stream_ptr - stream == main_stream_len); + + return main_stream_len; +} + +static void pvr_srv_compute_cmd_ext_stream_load( + struct rogue_fwif_cmd_compute *const cmd, + const uint8_t *const stream, + const uint32_t stream_len, + const uint32_t ext_stream_offset, + const struct pvr_device_info *const dev_info) +{ + const uint32_t *ext_stream_ptr = + (const uint32_t *)((uint8_t *)stream + ext_stream_offset); + struct rogue_fwif_cdm_regs *const regs = &cmd->regs; + + struct ROGUE_KMD_STREAM_EXTHDR_COMPUTE0 header0; + + header0 = pvr_csb_unpack(ext_stream_ptr, KMD_STREAM_EXTHDR_COMPUTE0); + ext_stream_ptr += pvr_cmd_length(KMD_STREAM_EXTHDR_COMPUTE0); + + assert(PVR_HAS_QUIRK(dev_info, 49927) == header0.has_brn49927); + if (header0.has_brn49927) { + regs->tpu = *ext_stream_ptr; + ext_stream_ptr += pvr_cmd_length(CR_TPU); + } + + assert((const uint8_t *)ext_stream_ptr - stream == stream_len); +} + +void pvr_srv_compute_cmd_init( + const struct pvr_winsys_compute_submit_info *submit_info, + struct rogue_fwif_cmd_compute *cmd, + const struct pvr_device_info *const dev_info) +{ + uint32_t ext_stream_offset; + + memset(cmd, 0, sizeof(*cmd)); + + cmd->cmn.frame_num = submit_info->frame_num; + + ext_stream_offset = + pvr_srv_compute_cmd_stream_load(cmd, + submit_info->fw_stream, + submit_info->fw_stream_len, + dev_info); + + if (ext_stream_offset < submit_info->fw_stream_len) { + pvr_srv_compute_cmd_ext_stream_load(cmd, + submit_info->fw_stream, + submit_info->fw_stream_len, + ext_stream_offset, + dev_info); + } + + if (submit_info->flags.prevent_all_overlap) + cmd->flags |= ROGUE_FWIF_COMPUTE_FLAG_PREVENT_ALL_OVERLAP; + + if (submit_info->flags.use_single_core) + cmd->flags |= ROGUE_FWIF_COMPUTE_FLAG_SINGLE_CORE; +} diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_arch_srv_job_render.c b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_arch_srv_job_render.c new file mode 100644 index 00000000000..51e3189d22a --- /dev/null +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_arch_srv_job_render.c @@ -0,0 +1,753 @@ +/* + * Copyright © 2022 Imagination Technologies Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fw-api/pvr_rogue_fwif.h" +#include "fw-api/pvr_rogue_fwif_rf.h" +#include "pvr_csb.h" +#include "pvr_job_render.h" +#include "pvr_srv.h" +#include "pvr_srv_bo.h" +#include "pvr_srv_bridge.h" +#include "pvr_srv_job_common.h" +#include "pvr_srv_job_render.h" +#include "pvr_srv_sync.h" +#include "pvr_srv_sync_prim.h" +#include "pvr_types.h" +#include "pvr_winsys.h" +#include "util/compiler.h" +#include "util/log.h" +#include "util/macros.h" +#include "util/os_file.h" +#include "util/u_math.h" +#include "vk_alloc.h" +#include "vk_log.h" +#include "vk_util.h" + +struct pvr_srv_winsys_free_list { + struct pvr_winsys_free_list base; + + void *handle; + + struct pvr_srv_winsys_free_list *parent; +}; + +#define to_pvr_srv_winsys_free_list(free_list) \ + container_of(free_list, struct pvr_srv_winsys_free_list, base) + +struct pvr_srv_winsys_rt_dataset { + struct pvr_winsys_rt_dataset base; + + struct { + void *handle; + struct pvr_srv_sync_prim *sync_prim; + } rt_datas[ROGUE_FWIF_NUM_RTDATAS]; +}; + +#define to_pvr_srv_winsys_rt_dataset(rt_dataset) \ + container_of(rt_dataset, struct pvr_srv_winsys_rt_dataset, base) + +struct pvr_srv_winsys_render_ctx { + struct pvr_winsys_render_ctx base; + + /* Handle to kernel context. */ + void *handle; + + int timeline_geom; + int timeline_frag; +}; + +#define to_pvr_srv_winsys_render_ctx(ctx) \ + container_of(ctx, struct pvr_srv_winsys_render_ctx, base) + +static uint64_t pvr_rogue_get_cr_multisamplectl_val(uint32_t samples, + bool y_flip) +{ + static const struct { + uint8_t x[8]; + uint8_t y[8]; + } sample_positions[4] = { + /* 1 sample */ + { + .x = { 8 }, + .y = { 8 }, + }, + /* 2 samples */ + { + .x = { 12, 4 }, + .y = { 12, 4 }, + }, + /* 4 samples */ + { + .x = { 6, 14, 2, 10 }, + .y = { 2, 6, 10, 14 }, + }, + /* 8 samples */ + { + .x = { 9, 7, 13, 5, 3, 1, 11, 15 }, + .y = { 5, 11, 9, 3, 13, 7, 15, 1 }, + }, + }; + uint64_t multisamplectl; + uint8_t idx; + + idx = util_fast_log2(samples); + assert(idx < ARRAY_SIZE(sample_positions)); + + pvr_csb_pack (&multisamplectl, CR_PPP_MULTISAMPLECTL, value) { + switch (samples) { + case 8: + value.msaa_x7 = sample_positions[idx].x[7]; + value.msaa_x6 = sample_positions[idx].x[6]; + value.msaa_x5 = sample_positions[idx].x[5]; + value.msaa_x4 = sample_positions[idx].x[4]; + + if (y_flip) { + value.msaa_y7 = 16U - sample_positions[idx].y[7]; + value.msaa_y6 = 16U - sample_positions[idx].y[6]; + value.msaa_y5 = 16U - sample_positions[idx].y[5]; + value.msaa_y4 = 16U - sample_positions[idx].y[4]; + } else { + value.msaa_y7 = sample_positions[idx].y[7]; + value.msaa_y6 = sample_positions[idx].y[6]; + value.msaa_y5 = sample_positions[idx].y[5]; + value.msaa_y4 = sample_positions[idx].y[4]; + } + + FALLTHROUGH; + case 4: + value.msaa_x3 = sample_positions[idx].x[3]; + value.msaa_x2 = sample_positions[idx].x[2]; + + if (y_flip) { + value.msaa_y3 = 16U - sample_positions[idx].y[3]; + value.msaa_y2 = 16U - sample_positions[idx].y[2]; + } else { + value.msaa_y3 = sample_positions[idx].y[3]; + value.msaa_y2 = sample_positions[idx].y[2]; + } + + FALLTHROUGH; + case 2: + value.msaa_x1 = sample_positions[idx].x[1]; + + if (y_flip) { + value.msaa_y1 = 16U - sample_positions[idx].y[1]; + } else { + value.msaa_y1 = sample_positions[idx].y[1]; + } + + FALLTHROUGH; + case 1: + value.msaa_x0 = sample_positions[idx].x[0]; + + if (y_flip) { + value.msaa_y0 = 16U - sample_positions[idx].y[0]; + } else { + value.msaa_y0 = sample_positions[idx].y[0]; + } + + break; + default: + UNREACHABLE("Unsupported number of samples"); + } + } + + return multisamplectl; +} + +static uint32_t +pvr_rogue_get_cr_isp_mtile_size_val(const struct pvr_device_info *dev_info, + const struct pvr_rt_mtile_info *mtile_info, + uint32_t samples) +{ + uint32_t samples_per_pixel = + PVR_GET_FEATURE_VALUE(dev_info, isp_samples_per_pixel, 0); + uint32_t isp_mtile_size; + + pvr_csb_pack (&isp_mtile_size, CR_ISP_MTILE_SIZE, value) { + value.x = mtile_info->mtile_x1; + value.y = mtile_info->mtile_y1; + + if (samples_per_pixel == 1) { + if (samples >= 4) + value.x <<= 1; + + if (samples >= 2) + value.y <<= 1; + } else if (samples_per_pixel == 2) { + if (samples >= 8) + value.x <<= 1; + + if (samples >= 4) + value.y <<= 1; + } else if (samples_per_pixel == 4) { + if (samples >= 8) + value.y <<= 1; + } else { + assert(!"Unsupported ISP samples per pixel value"); + } + } + + return isp_mtile_size; +} + +static uint32_t pvr_rogue_get_ppp_screen_val(uint32_t width, uint32_t height) +{ + uint32_t val; + + pvr_csb_pack (&val, CR_PPP_SCREEN, state) { + state.pixxmax = width - 1; + state.pixymax = height - 1; + } + + return val; +} + +struct pvr_rogue_cr_te { + uint32_t aa; + uint32_t mtile1; + uint32_t mtile2; + uint32_t screen; + uint32_t mtile_stride; +}; + +static void pvr_rogue_ct_te_init(const struct pvr_device_info *dev_info, + const struct pvr_rt_mtile_info *mtile_info, + uint32_t samples, + struct pvr_rogue_cr_te *const te_regs) +{ + uint32_t samples_per_pixel = + PVR_GET_FEATURE_VALUE(dev_info, isp_samples_per_pixel, 0); + + pvr_csb_pack (&te_regs->aa, CR_TE_AA, value) { + if (samples_per_pixel == 1) { + if (samples >= 2) + value.y = true; + if (samples >= 4) + value.x = true; + } else if (samples_per_pixel == 2) { + if (samples >= 2) + value.x2 = true; + if (samples >= 4) + value.y = true; + if (samples >= 8) + value.x = true; + } else if (samples_per_pixel == 4) { + if (samples >= 2) + value.x2 = true; + if (samples >= 4) + value.y2 = true; + if (samples >= 8) + value.y = true; + } else { + assert(!"Unsupported ISP samples per pixel value"); + } + } + + pvr_csb_pack (&te_regs->mtile1, CR_TE_MTILE1, value) { + value.x1 = mtile_info->mtile_x1; + if (!PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format)) { + value.x2 = mtile_info->mtile_x2; + value.x3 = mtile_info->mtile_x3; + } + } + + pvr_csb_pack (&te_regs->mtile2, CR_TE_MTILE2, value) { + value.y1 = mtile_info->mtile_y1; + if (!PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format)) { + value.y2 = mtile_info->mtile_y2; + value.y3 = mtile_info->mtile_y3; + } + } + + pvr_csb_pack (&te_regs->screen, CR_TE_SCREEN, value) { + value.xmax = mtile_info->x_tile_max; + value.ymax = mtile_info->y_tile_max; + } + + te_regs->mtile_stride = mtile_info->mtile_x1 * mtile_info->mtile_y1; +} + +VkResult pvr_srv_render_target_dataset_create( + struct pvr_winsys *ws, + const struct pvr_winsys_rt_dataset_create_info *create_info, + const struct pvr_device_info *dev_info, + struct pvr_winsys_rt_dataset **const rt_dataset_out) +{ + const pvr_dev_addr_t macrotile_addrs[ROGUE_FWIF_NUM_RTDATAS] = { + [0] = create_info->rt_datas[0].macrotile_array_dev_addr, + [1] = create_info->rt_datas[1].macrotile_array_dev_addr, + }; + const pvr_dev_addr_t pm_mlist_addrs[ROGUE_FWIF_NUM_RTDATAS] = { + [0] = create_info->rt_datas[0].pm_mlist_dev_addr, + [1] = create_info->rt_datas[1].pm_mlist_dev_addr, + }; + const pvr_dev_addr_t rgn_header_addrs[ROGUE_FWIF_NUM_RTDATAS] = { + [0] = create_info->rt_datas[0].rgn_header_dev_addr, + [1] = create_info->rt_datas[1].rgn_header_dev_addr, + }; + + struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ws); + struct pvr_srv_winsys_free_list *srv_local_free_list = + to_pvr_srv_winsys_free_list(create_info->local_free_list); + void *free_lists[ROGUE_FW_MAX_FREELISTS] = { NULL }; + struct pvr_srv_winsys_rt_dataset *srv_rt_dataset; + void *handles[ROGUE_FWIF_NUM_RTDATAS]; + struct pvr_rogue_cr_te rogue_te_regs; + struct pvr_rt_mtile_info mtile_info; + uint32_t isp_mtile_size; + VkResult result; + + free_lists[ROGUE_FW_LOCAL_FREELIST] = srv_local_free_list->handle; + + if (srv_local_free_list->parent) { + free_lists[ROGUE_FW_GLOBAL_FREELIST] = + srv_local_free_list->parent->handle; + } + + srv_rt_dataset = vk_zalloc(ws->alloc, + sizeof(*srv_rt_dataset), + 8, + VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); + if (!srv_rt_dataset) + return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); + + /* If greater than 1 we'll have to pass in an array. For now just passing in + * the reference. + */ + STATIC_ASSERT(ROGUE_FWIF_NUM_GEOMDATAS == 1); + /* If not 2 the arrays used in the bridge call will require updating. */ + STATIC_ASSERT(ROGUE_FWIF_NUM_RTDATAS == 2); + + pvr_rt_mtile_info_init(dev_info, + &mtile_info, + create_info->width, + create_info->height, + create_info->samples); + + isp_mtile_size = pvr_rogue_get_cr_isp_mtile_size_val(dev_info, + &mtile_info, + create_info->samples); + + pvr_rogue_ct_te_init(dev_info, + &mtile_info, + create_info->samples, + &rogue_te_regs); + + result = pvr_srv_rgx_create_hwrt_dataset( + ws->render_fd, + pvr_rogue_get_cr_multisamplectl_val(create_info->samples, true), + pvr_rogue_get_cr_multisamplectl_val(create_info->samples, false), + macrotile_addrs, + pm_mlist_addrs, + &create_info->rtc_dev_addr, + rgn_header_addrs, + &create_info->tpc_dev_addr, + &create_info->vheap_table_dev_addr, + free_lists, + create_info->isp_merge_lower_x, + create_info->isp_merge_lower_y, + create_info->isp_merge_scale_x, + create_info->isp_merge_scale_y, + create_info->isp_merge_upper_x, + create_info->isp_merge_upper_y, + isp_mtile_size, + rogue_te_regs.mtile_stride, + pvr_rogue_get_ppp_screen_val(create_info->width, create_info->height), + create_info->rgn_header_size, + rogue_te_regs.aa, + rogue_te_regs.mtile1, + rogue_te_regs.mtile2, + rogue_te_regs.screen, + create_info->tpc_size, + create_info->tpc_stride, + create_info->layers, + handles); + if (result != VK_SUCCESS) + goto err_vk_free_srv_rt_dataset; + + srv_rt_dataset->rt_datas[0].handle = handles[0]; + srv_rt_dataset->rt_datas[1].handle = handles[1]; + + for (uint32_t i = 0; i < ARRAY_SIZE(srv_rt_dataset->rt_datas); i++) { + srv_rt_dataset->rt_datas[i].sync_prim = pvr_srv_sync_prim_alloc(srv_ws); + if (!srv_rt_dataset->rt_datas[i].sync_prim) + goto err_srv_sync_prim_free; + } + + srv_rt_dataset->base.ws = ws; + + *rt_dataset_out = &srv_rt_dataset->base; + + return VK_SUCCESS; + +err_srv_sync_prim_free: + for (uint32_t i = 0; i < ARRAY_SIZE(srv_rt_dataset->rt_datas); i++) { + pvr_srv_sync_prim_free(srv_ws, srv_rt_dataset->rt_datas[i].sync_prim); + + if (srv_rt_dataset->rt_datas[i].handle) { + pvr_srv_rgx_destroy_hwrt_dataset(ws->render_fd, + srv_rt_dataset->rt_datas[i].handle); + } + } + +err_vk_free_srv_rt_dataset: + vk_free(ws->alloc, srv_rt_dataset); + + return result; +} + +static void pvr_srv_render_ctx_fw_static_state_init( + struct pvr_winsys_render_ctx_create_info *create_info, + struct rogue_fwif_static_rendercontext_state *static_state) +{ + struct pvr_winsys_render_ctx_static_state *ws_static_state = + &create_info->static_state; + struct rogue_fwif_ta_regs_cswitch *regs = + &static_state->ctx_switch_geom_regs[0]; + + memset(static_state, 0, sizeof(*static_state)); + + regs->vdm_context_state_base_addr = ws_static_state->vdm_ctx_state_base_addr; + regs->ta_context_state_base_addr = ws_static_state->geom_ctx_state_base_addr; + + STATIC_ASSERT(ARRAY_SIZE(regs->ta_state) == + ARRAY_SIZE(ws_static_state->geom_state)); + for (uint32_t i = 0; i < ARRAY_SIZE(ws_static_state->geom_state); i++) { + regs->ta_state[i].vdm_context_store_task0 = + ws_static_state->geom_state[i].vdm_ctx_store_task0; + regs->ta_state[i].vdm_context_store_task1 = + ws_static_state->geom_state[i].vdm_ctx_store_task1; + regs->ta_state[i].vdm_context_store_task2 = + ws_static_state->geom_state[i].vdm_ctx_store_task2; + + regs->ta_state[i].vdm_context_resume_task0 = + ws_static_state->geom_state[i].vdm_ctx_resume_task0; + regs->ta_state[i].vdm_context_resume_task1 = + ws_static_state->geom_state[i].vdm_ctx_resume_task1; + regs->ta_state[i].vdm_context_resume_task2 = + ws_static_state->geom_state[i].vdm_ctx_resume_task2; + } +} + +static uint32_t +pvr_srv_geometry_cmd_stream_load(struct rogue_fwif_cmd_ta *const cmd, + const uint8_t *const stream, + const uint32_t stream_len, + const struct pvr_device_info *const dev_info) +{ + const uint32_t *stream_ptr = (const uint32_t *)stream; + struct rogue_fwif_ta_regs *const regs = &cmd->regs; + uint32_t main_stream_len = + pvr_csb_unpack((const uint64_t *)stream_ptr, KMD_STREAM_HDR).length; + + stream_ptr += pvr_cmd_length(KMD_STREAM_HDR); + + regs->vdm_ctrl_stream_base = *(const uint64_t *)stream_ptr; + stream_ptr += pvr_cmd_length(CR_VDM_CTRL_STREAM_BASE); + + regs->tpu_border_colour_table = *(const uint64_t *)stream_ptr; + stream_ptr += pvr_cmd_length(CR_TPU_BORDER_COLOUR_TABLE_VDM); + + regs->ppp_ctrl = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_PPP_CTRL); + + regs->te_psg = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_TE_PSG); + + regs->vdm_context_resume_task0_size = *stream_ptr; + stream_ptr += pvr_cmd_length(VDMCTRL_PDS_STATE0); + + regs->view_idx = *stream_ptr; + stream_ptr++; + + assert((const uint8_t *)stream_ptr - stream <= stream_len); + assert((const uint8_t *)stream_ptr - stream == main_stream_len); + + return main_stream_len; +} + +static void pvr_srv_geometry_cmd_ext_stream_load( + struct rogue_fwif_cmd_ta *const cmd, + const uint8_t *const stream, + const uint32_t stream_len, + const uint32_t ext_stream_offset, + const struct pvr_device_info *const dev_info) +{ + const uint32_t *ext_stream_ptr = + (const uint32_t *)((uint8_t *)stream + ext_stream_offset); + struct rogue_fwif_ta_regs *const regs = &cmd->regs; + + struct ROGUE_KMD_STREAM_EXTHDR_GEOM0 header0; + + header0 = pvr_csb_unpack(ext_stream_ptr, KMD_STREAM_EXTHDR_GEOM0); + ext_stream_ptr += pvr_cmd_length(KMD_STREAM_EXTHDR_GEOM0); + + assert(PVR_HAS_QUIRK(dev_info, 49927) == header0.has_brn49927); + if (header0.has_brn49927) { + regs->tpu = *ext_stream_ptr; + ext_stream_ptr += pvr_cmd_length(CR_TPU); + } + + assert((const uint8_t *)ext_stream_ptr - stream == stream_len); +} + +void pvr_srv_geometry_cmd_init( + const struct pvr_winsys_render_submit_info *submit_info, + const struct pvr_srv_sync_prim *sync_prim, + struct rogue_fwif_cmd_ta *cmd, + const struct pvr_device_info *const dev_info) +{ + const struct pvr_winsys_geometry_state *state = &submit_info->geometry; + uint32_t ext_stream_offset; + + memset(cmd, 0, sizeof(*cmd)); + + cmd->cmd_shared.cmn.frame_num = submit_info->frame_num; + + ext_stream_offset = pvr_srv_geometry_cmd_stream_load(cmd, + state->fw_stream, + state->fw_stream_len, + dev_info); + + if (ext_stream_offset < state->fw_stream_len) { + pvr_srv_geometry_cmd_ext_stream_load(cmd, + state->fw_stream, + state->fw_stream_len, + ext_stream_offset, + dev_info); + } + + if (state->flags.is_first_geometry) + cmd->flags |= ROGUE_FWIF_TAFLAGS_FIRSTKICK; + + if (state->flags.is_last_geometry) + cmd->flags |= ROGUE_FWIF_TAFLAGS_LASTKICK; + + if (state->flags.use_single_core) + cmd->flags |= ROGUE_FWIF_TAFLAGS_SINGLE_CORE; + + cmd->partial_render_ta_3d_fence.ufo_addr.addr = + pvr_srv_sync_prim_get_fw_addr(sync_prim); + cmd->partial_render_ta_3d_fence.value = sync_prim->value; +} + +static uint32_t +pvr_srv_fragment_cmd_stream_load(struct rogue_fwif_cmd_3d *const cmd, + const uint8_t *const stream, + const uint32_t stream_len, + const struct pvr_device_info *const dev_info) +{ + const uint32_t *stream_ptr = (const uint32_t *)stream; + struct rogue_fwif_3d_regs *const regs = &cmd->regs; + uint32_t main_stream_len = + pvr_csb_unpack((const uint64_t *)stream_ptr, KMD_STREAM_HDR).length; + + stream_ptr += pvr_cmd_length(KMD_STREAM_HDR); + + regs->isp_scissor_base = *(const uint64_t *)stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_SCISSOR_BASE); + + regs->isp_dbias_base = *(const uint64_t *)stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_DBIAS_BASE); + + regs->isp_oclqry_base = *(const uint64_t *)stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_OCLQRY_BASE); + + regs->isp_zlsctl = *(const uint64_t *)stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_ZLSCTL); + + regs->isp_zload_store_base = *(const uint64_t *)stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_ZLOAD_BASE); + + regs->isp_stencil_load_store_base = *(const uint64_t *)stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_STENCIL_LOAD_BASE); + + if (PVR_HAS_FEATURE(dev_info, requires_fb_cdc_zls_setup)) { + regs->fb_cdc_zls = *(const uint64_t *)stream_ptr; + stream_ptr += 2U; + } + + STATIC_ASSERT(ARRAY_SIZE(regs->pbe_word) == 8U); + STATIC_ASSERT(ARRAY_SIZE(regs->pbe_word[0]) == 3U); + STATIC_ASSERT(sizeof(regs->pbe_word[0][0]) == sizeof(uint64_t)); + memcpy(regs->pbe_word, stream_ptr, sizeof(regs->pbe_word)); + stream_ptr += 8U * 3U * 2U; + + regs->tpu_border_colour_table = *(const uint64_t *)stream_ptr; + stream_ptr += pvr_cmd_length(CR_TPU_BORDER_COLOUR_TABLE_PDM); + + STATIC_ASSERT(ARRAY_SIZE(regs->pds_bgnd) == 3U); + STATIC_ASSERT(sizeof(regs->pds_bgnd[0]) == sizeof(uint64_t)); + memcpy(regs->pds_bgnd, stream_ptr, sizeof(regs->pds_bgnd)); + stream_ptr += 3U * 2U; + + STATIC_ASSERT(ARRAY_SIZE(regs->pds_pr_bgnd) == 3U); + STATIC_ASSERT(sizeof(regs->pds_pr_bgnd[0]) == sizeof(uint64_t)); + memcpy(regs->pds_pr_bgnd, stream_ptr, sizeof(regs->pds_pr_bgnd)); + stream_ptr += 3U * 2U; + + STATIC_ASSERT(ARRAY_SIZE(regs->usc_clear_register) == 8U); + STATIC_ASSERT(sizeof(regs->usc_clear_register[0]) == sizeof(uint32_t)); + memcpy(regs->usc_clear_register, + stream_ptr, + sizeof(regs->usc_clear_register)); + stream_ptr += 8U; + + regs->usc_pixel_output_ctrl = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_USC_PIXEL_OUTPUT_CTRL); + + regs->isp_bgobjdepth = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_BGOBJDEPTH); + + regs->isp_bgobjvals = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_BGOBJVALS); + + regs->isp_aa = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_AA); + + regs->isp_ctl = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_CTL); + + regs->event_pixel_pds_info = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_EVENT_PIXEL_PDS_INFO); + + if (PVR_HAS_FEATURE(dev_info, cluster_grouping)) { + regs->pixel_phantom = *stream_ptr; + stream_ptr++; + } + + regs->view_idx = *stream_ptr; + stream_ptr++; + + regs->event_pixel_pds_data = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_EVENT_PIXEL_PDS_DATA); + + if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) { + regs->isp_oclqry_stride = *stream_ptr; + stream_ptr++; + } + + if (PVR_HAS_FEATURE(dev_info, zls_subtile)) { + regs->isp_zls_pixels = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_ZLS_PIXELS); + } + + cmd->zls_stride = *stream_ptr; + stream_ptr++; + + cmd->sls_stride = *stream_ptr; + stream_ptr++; + + if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) { + cmd->execute_count = *stream_ptr; + stream_ptr++; + } + + assert((const uint8_t *)stream_ptr - stream <= stream_len); + assert((const uint8_t *)stream_ptr - stream == main_stream_len); + + return main_stream_len; +} + +static void pvr_srv_fragment_cmd_ext_stream_load( + struct rogue_fwif_cmd_3d *const cmd, + const uint8_t *const stream, + const uint32_t stream_len, + const uint32_t ext_stream_offset, + const struct pvr_device_info *const dev_info) +{ + const uint32_t *ext_stream_ptr = + (const uint32_t *)((uint8_t *)stream + ext_stream_offset); + struct rogue_fwif_3d_regs *const regs = &cmd->regs; + + struct ROGUE_KMD_STREAM_EXTHDR_FRAG0 header0; + + header0 = pvr_csb_unpack(ext_stream_ptr, KMD_STREAM_EXTHDR_FRAG0); + ext_stream_ptr += pvr_cmd_length(KMD_STREAM_EXTHDR_FRAG0); + + assert(PVR_HAS_QUIRK(dev_info, 49927) == header0.has_brn49927); + if (header0.has_brn49927) { + regs->tpu = *ext_stream_ptr; + ext_stream_ptr += pvr_cmd_length(CR_TPU); + } + + assert((const uint8_t *)ext_stream_ptr - stream == stream_len); +} + +void pvr_srv_fragment_cmd_init(struct rogue_fwif_cmd_3d *cmd, + const struct pvr_winsys_fragment_state *state, + const struct pvr_device_info *dev_info, + uint32_t frame_num) +{ + uint32_t ext_stream_offset; + + memset(cmd, 0, sizeof(*cmd)); + + cmd->cmd_shared.cmn.frame_num = frame_num; + + ext_stream_offset = pvr_srv_fragment_cmd_stream_load(cmd, + state->fw_stream, + state->fw_stream_len, + dev_info); + + if (ext_stream_offset < state->fw_stream_len) { + pvr_srv_fragment_cmd_ext_stream_load(cmd, + state->fw_stream, + state->fw_stream_len, + ext_stream_offset, + dev_info); + } + + if (state->flags.has_depth_buffer) + cmd->flags |= ROGUE_FWIF_RENDERFLAGS_DEPTHBUFFER; + + if (state->flags.has_stencil_buffer) + cmd->flags |= ROGUE_FWIF_RENDERFLAGS_STENCILBUFFER; + + if (state->flags.prevent_cdm_overlap) + cmd->flags |= ROGUE_FWIF_RENDERFLAGS_PREVENT_CDM_OVERLAP; + + if (state->flags.use_single_core) + cmd->flags |= ROGUE_FWIF_RENDERFLAGS_SINGLE_CORE; + + if (state->flags.get_vis_results) + cmd->flags |= ROGUE_FWIF_RENDERFLAGS_GETVISRESULTS; + + if (state->flags.has_spm_scratch_buffer) + cmd->flags |= ROGUE_FWIF_RENDERFLAGS_SPMSCRATCHBUFFER; + + if (state->flags.disable_pixel_merging) + cmd->flags |= ROGUE_FWIF_RENDERFLAGS_DISABLE_PIXELMERGE; +} diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_arch_srv_job_transfer.c b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_arch_srv_job_transfer.c new file mode 100644 index 00000000000..ea4bcbf129e --- /dev/null +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_arch_srv_job_transfer.c @@ -0,0 +1,114 @@ +/* + * Copyright © 2022 Imagination Technologies Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "pvr_srv_job_transfer.h" + +#include "fw-api/pvr_rogue_fwif.h" +#include "pvr_csb.h" +#include "pvr_device_info.h" + +void pvr_srv_transfer_cmd_stream_load( + struct rogue_fwif_cmd_transfer *const cmd, + const uint8_t *const stream, + const uint32_t stream_len, + const struct pvr_device_info *const dev_info) +{ + const uint32_t *stream_ptr = (const uint32_t *)stream; + struct rogue_fwif_transfer_regs *const regs = &cmd->regs; + uint32_t main_stream_len = + pvr_csb_unpack((uint64_t *)stream_ptr, KMD_STREAM_HDR).length; + + stream_ptr += pvr_cmd_length(KMD_STREAM_HDR); + + memcpy(®s->pds_bgnd0_base, stream_ptr, sizeof(regs->pds_bgnd0_base)); + stream_ptr += pvr_cmd_length(CR_PDS_BGRND0_BASE); + + memcpy(®s->pds_bgnd1_base, stream_ptr, sizeof(regs->pds_bgnd1_base)); + stream_ptr += pvr_cmd_length(CR_PDS_BGRND1_BASE); + + memcpy(®s->pds_bgnd3_sizeinfo, + stream_ptr, + sizeof(regs->pds_bgnd3_sizeinfo)); + stream_ptr += pvr_cmd_length(CR_PDS_BGRND3_SIZEINFO); + + memcpy(®s->isp_mtile_base, stream_ptr, sizeof(regs->isp_mtile_base)); + stream_ptr += pvr_cmd_length(CR_ISP_MTILE_BASE); + + STATIC_ASSERT(ARRAY_SIZE(regs->pbe_wordx_mrty) == 9U); + STATIC_ASSERT(sizeof(regs->pbe_wordx_mrty[0]) == sizeof(uint64_t)); + memcpy(regs->pbe_wordx_mrty, stream_ptr, sizeof(regs->pbe_wordx_mrty)); + stream_ptr += 9U * 2U; + + regs->isp_bgobjvals = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_BGOBJVALS); + + regs->usc_pixel_output_ctrl = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_USC_PIXEL_OUTPUT_CTRL); + + regs->usc_clear_register0 = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_USC_CLEAR_REGISTER); + + regs->usc_clear_register1 = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_USC_CLEAR_REGISTER); + + regs->usc_clear_register2 = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_USC_CLEAR_REGISTER); + + regs->usc_clear_register3 = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_USC_CLEAR_REGISTER); + + regs->isp_mtile_size = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_MTILE_SIZE); + + regs->isp_render_origin = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_RENDER_ORIGIN); + + regs->isp_ctl = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_CTL); + + regs->isp_aa = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_AA); + + regs->event_pixel_pds_info = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_EVENT_PIXEL_PDS_INFO); + + regs->event_pixel_pds_code = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_EVENT_PIXEL_PDS_CODE); + + regs->event_pixel_pds_data = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_EVENT_PIXEL_PDS_DATA); + + regs->isp_render = *stream_ptr; + stream_ptr += pvr_cmd_length(CR_ISP_RENDER); + + regs->isp_rgn = *stream_ptr; + stream_ptr++; + + if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) { + regs->frag_screen = *stream_ptr; + stream_ptr++; + } + + assert((const uint8_t *)stream_ptr - stream == stream_len); + assert((const uint8_t *)stream_ptr - stream == main_stream_len); +} diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_compute.c b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_compute.c index cd78ba32dde..6057e6a48ae 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_compute.c +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_compute.c @@ -32,7 +32,6 @@ #include "fw-api/pvr_rogue_fwif.h" #include "fw-api/pvr_rogue_fwif_rf.h" -#include "pvr_csb.h" #include "pvr_device_info.h" #include "pvr_srv.h" #include "pvr_srv_bridge.h" @@ -139,114 +138,6 @@ void pvr_srv_winsys_compute_ctx_destroy(struct pvr_winsys_compute_ctx *ctx) vk_free(srv_ws->base.alloc, srv_ctx); } -static uint32_t -pvr_srv_compute_cmd_stream_load(struct rogue_fwif_cmd_compute *const cmd, - const uint8_t *const stream, - const uint32_t stream_len, - const struct pvr_device_info *const dev_info) -{ - const uint32_t *stream_ptr = (const uint32_t *)stream; - struct rogue_fwif_cdm_regs *const regs = &cmd->regs; - uint32_t main_stream_len = - pvr_csb_unpack((uint64_t *)stream_ptr, KMD_STREAM_HDR).length; - - stream_ptr += pvr_cmd_length(KMD_STREAM_HDR); - - regs->tpu_border_colour_table = *(const uint64_t *)stream_ptr; - stream_ptr += pvr_cmd_length(CR_TPU_BORDER_COLOUR_TABLE_CDM); - - regs->cdm_ctrl_stream_base = *(const uint64_t *)stream_ptr; - stream_ptr += pvr_cmd_length(CR_CDM_CTRL_STREAM_BASE); - - regs->cdm_context_state_base_addr = *(const uint64_t *)stream_ptr; - stream_ptr += pvr_cmd_length(CR_CDM_CONTEXT_STATE_BASE); - - regs->cdm_resume_pds1 = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_CDM_CONTEXT_PDS1); - - if (PVR_HAS_FEATURE(dev_info, compute_morton_capable)) { - regs->cdm_item = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_CDM_ITEM); - } - - if (PVR_HAS_FEATURE(dev_info, cluster_grouping)) { - regs->compute_cluster = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_COMPUTE_CLUSTER); - } - - if (PVR_HAS_FEATURE(dev_info, tpu_dm_global_registers)) { - regs->tpu_tag_cdm_ctrl = *stream_ptr; - stream_ptr++; - } - - if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) { - cmd->execute_count = *stream_ptr; - stream_ptr++; - } - - assert((const uint8_t *)stream_ptr - stream <= stream_len); - assert((const uint8_t *)stream_ptr - stream == main_stream_len); - - return main_stream_len; -} - -static void pvr_srv_compute_cmd_ext_stream_load( - struct rogue_fwif_cmd_compute *const cmd, - const uint8_t *const stream, - const uint32_t stream_len, - const uint32_t ext_stream_offset, - const struct pvr_device_info *const dev_info) -{ - const uint32_t *ext_stream_ptr = - (const uint32_t *)((uint8_t *)stream + ext_stream_offset); - struct rogue_fwif_cdm_regs *const regs = &cmd->regs; - - struct ROGUE_KMD_STREAM_EXTHDR_COMPUTE0 header0; - - header0 = pvr_csb_unpack(ext_stream_ptr, KMD_STREAM_EXTHDR_COMPUTE0); - ext_stream_ptr += pvr_cmd_length(KMD_STREAM_EXTHDR_COMPUTE0); - - assert(PVR_HAS_QUIRK(dev_info, 49927) == header0.has_brn49927); - if (header0.has_brn49927) { - regs->tpu = *ext_stream_ptr; - ext_stream_ptr += pvr_cmd_length(CR_TPU); - } - - assert((const uint8_t *)ext_stream_ptr - stream == stream_len); -} - -static void pvr_srv_compute_cmd_init( - const struct pvr_winsys_compute_submit_info *submit_info, - struct rogue_fwif_cmd_compute *cmd, - const struct pvr_device_info *const dev_info) -{ - uint32_t ext_stream_offset; - - memset(cmd, 0, sizeof(*cmd)); - - cmd->cmn.frame_num = submit_info->frame_num; - - ext_stream_offset = - pvr_srv_compute_cmd_stream_load(cmd, - submit_info->fw_stream, - submit_info->fw_stream_len, - dev_info); - - if (ext_stream_offset < submit_info->fw_stream_len) { - pvr_srv_compute_cmd_ext_stream_load(cmd, - submit_info->fw_stream, - submit_info->fw_stream_len, - ext_stream_offset, - dev_info); - } - - if (submit_info->flags.prevent_all_overlap) - cmd->flags |= ROGUE_FWIF_COMPUTE_FLAG_PREVENT_ALL_OVERLAP; - - if (submit_info->flags.use_single_core) - cmd->flags |= ROGUE_FWIF_COMPUTE_FLAG_SINGLE_CORE; -} - VkResult pvr_srv_winsys_compute_submit( const struct pvr_winsys_compute_ctx *ctx, const struct pvr_winsys_compute_submit_info *submit_info, diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_compute.h b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_compute.h index a5a50754d61..1c7a7d2ef31 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_compute.h +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_compute.h @@ -26,6 +26,7 @@ #include +struct rogue_fwif_cmd_compute; struct pvr_device_info; struct pvr_winsys; struct pvr_winsys_compute_ctx; @@ -49,4 +50,9 @@ VkResult pvr_srv_winsys_compute_submit( const struct pvr_device_info *dev_info, struct vk_sync *signal_sync); +void pvr_srv_compute_cmd_init( + const struct pvr_winsys_compute_submit_info *submit_info, + struct rogue_fwif_cmd_compute *cmd, + const struct pvr_device_info *const dev_info); + #endif /* PVR_SRV_JOB_COMPUTE_H */ diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_render.c b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_render.c index 34e34c4ef80..27e1ed1a75e 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_render.c +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_render.c @@ -21,6 +21,8 @@ * SOFTWARE. */ +#include "pvr_srv_job_render.h" + #include #include #include @@ -34,17 +36,18 @@ #include "fw-api/pvr_rogue_fwif.h" #include "fw-api/pvr_rogue_fwif_rf.h" -#include "pvr_csb.h" -#include "pvr_job_render.h" -#include "pvr_srv.h" + +#include "pvr_macros.h" #include "pvr_srv_bo.h" #include "pvr_srv_bridge.h" #include "pvr_srv_job_common.h" #include "pvr_srv_job_render.h" -#include "pvr_srv_sync.h" #include "pvr_srv_sync_prim.h" +#include "pvr_srv_sync.h" +#include "pvr_srv.h" #include "pvr_types.h" #include "pvr_winsys.h" + #include "util/compiler.h" #include "util/log.h" #include "util/macros.h" @@ -163,344 +166,6 @@ void pvr_srv_winsys_free_list_destroy(struct pvr_winsys_free_list *free_list) vk_free(srv_ws->base.alloc, srv_free_list); } -static uint64_t pvr_rogue_get_cr_multisamplectl_val(uint32_t samples, - bool y_flip) -{ - static const struct { - uint8_t x[8]; - uint8_t y[8]; - } sample_positions[4] = { - /* 1 sample */ - { - .x = { 8 }, - .y = { 8 }, - }, - /* 2 samples */ - { - .x = { 12, 4 }, - .y = { 12, 4 }, - }, - /* 4 samples */ - { - .x = { 6, 14, 2, 10 }, - .y = { 2, 6, 10, 14 }, - }, - /* 8 samples */ - { - .x = { 9, 7, 13, 5, 3, 1, 11, 15 }, - .y = { 5, 11, 9, 3, 13, 7, 15, 1 }, - }, - }; - uint64_t multisamplectl; - uint8_t idx; - - idx = util_fast_log2(samples); - assert(idx < ARRAY_SIZE(sample_positions)); - - pvr_csb_pack (&multisamplectl, CR_PPP_MULTISAMPLECTL, value) { - switch (samples) { - case 8: - value.msaa_x7 = sample_positions[idx].x[7]; - value.msaa_x6 = sample_positions[idx].x[6]; - value.msaa_x5 = sample_positions[idx].x[5]; - value.msaa_x4 = sample_positions[idx].x[4]; - - if (y_flip) { - value.msaa_y7 = 16U - sample_positions[idx].y[7]; - value.msaa_y6 = 16U - sample_positions[idx].y[6]; - value.msaa_y5 = 16U - sample_positions[idx].y[5]; - value.msaa_y4 = 16U - sample_positions[idx].y[4]; - } else { - value.msaa_y7 = sample_positions[idx].y[7]; - value.msaa_y6 = sample_positions[idx].y[6]; - value.msaa_y5 = sample_positions[idx].y[5]; - value.msaa_y4 = sample_positions[idx].y[4]; - } - - FALLTHROUGH; - case 4: - value.msaa_x3 = sample_positions[idx].x[3]; - value.msaa_x2 = sample_positions[idx].x[2]; - - if (y_flip) { - value.msaa_y3 = 16U - sample_positions[idx].y[3]; - value.msaa_y2 = 16U - sample_positions[idx].y[2]; - } else { - value.msaa_y3 = sample_positions[idx].y[3]; - value.msaa_y2 = sample_positions[idx].y[2]; - } - - FALLTHROUGH; - case 2: - value.msaa_x1 = sample_positions[idx].x[1]; - - if (y_flip) { - value.msaa_y1 = 16U - sample_positions[idx].y[1]; - } else { - value.msaa_y1 = sample_positions[idx].y[1]; - } - - FALLTHROUGH; - case 1: - value.msaa_x0 = sample_positions[idx].x[0]; - - if (y_flip) { - value.msaa_y0 = 16U - sample_positions[idx].y[0]; - } else { - value.msaa_y0 = sample_positions[idx].y[0]; - } - - break; - default: - UNREACHABLE("Unsupported number of samples"); - } - } - - return multisamplectl; -} - -static uint32_t -pvr_rogue_get_cr_isp_mtile_size_val(const struct pvr_device_info *dev_info, - const struct pvr_rt_mtile_info *mtile_info, - uint32_t samples) -{ - uint32_t samples_per_pixel = - PVR_GET_FEATURE_VALUE(dev_info, isp_samples_per_pixel, 0); - uint32_t isp_mtile_size; - - pvr_csb_pack (&isp_mtile_size, CR_ISP_MTILE_SIZE, value) { - value.x = mtile_info->mtile_x1; - value.y = mtile_info->mtile_y1; - - if (samples_per_pixel == 1) { - if (samples >= 4) - value.x <<= 1; - - if (samples >= 2) - value.y <<= 1; - } else if (samples_per_pixel == 2) { - if (samples >= 8) - value.x <<= 1; - - if (samples >= 4) - value.y <<= 1; - } else if (samples_per_pixel == 4) { - if (samples >= 8) - value.y <<= 1; - } else { - assert(!"Unsupported ISP samples per pixel value"); - } - } - - return isp_mtile_size; -} - -static uint32_t pvr_rogue_get_ppp_screen_val(uint32_t width, uint32_t height) -{ - uint32_t val; - - pvr_csb_pack (&val, CR_PPP_SCREEN, state) { - state.pixxmax = width - 1; - state.pixymax = height - 1; - } - - return val; -} - -struct pvr_rogue_cr_te { - uint32_t aa; - uint32_t mtile1; - uint32_t mtile2; - uint32_t screen; - uint32_t mtile_stride; -}; - -static void pvr_rogue_ct_te_init(const struct pvr_device_info *dev_info, - const struct pvr_rt_mtile_info *mtile_info, - uint32_t samples, - struct pvr_rogue_cr_te *const te_regs) -{ - uint32_t samples_per_pixel = - PVR_GET_FEATURE_VALUE(dev_info, isp_samples_per_pixel, 0); - - pvr_csb_pack (&te_regs->aa, CR_TE_AA, value) { - if (samples_per_pixel == 1) { - if (samples >= 2) - value.y = true; - if (samples >= 4) - value.x = true; - } else if (samples_per_pixel == 2) { - if (samples >= 2) - value.x2 = true; - if (samples >= 4) - value.y = true; - if (samples >= 8) - value.x = true; - } else if (samples_per_pixel == 4) { - if (samples >= 2) - value.x2 = true; - if (samples >= 4) - value.y2 = true; - if (samples >= 8) - value.y = true; - } else { - assert(!"Unsupported ISP samples per pixel value"); - } - } - - pvr_csb_pack (&te_regs->mtile1, CR_TE_MTILE1, value) { - value.x1 = mtile_info->mtile_x1; - if (!PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format)) { - value.x2 = mtile_info->mtile_x2; - value.x3 = mtile_info->mtile_x3; - } - } - - pvr_csb_pack (&te_regs->mtile2, CR_TE_MTILE2, value) { - value.y1 = mtile_info->mtile_y1; - if (!PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format)) { - value.y2 = mtile_info->mtile_y2; - value.y3 = mtile_info->mtile_y3; - } - } - - pvr_csb_pack (&te_regs->screen, CR_TE_SCREEN, value) { - value.xmax = mtile_info->x_tile_max; - value.ymax = mtile_info->y_tile_max; - } - - te_regs->mtile_stride = mtile_info->mtile_x1 * mtile_info->mtile_y1; -} - -VkResult pvr_srv_render_target_dataset_create( - struct pvr_winsys *ws, - const struct pvr_winsys_rt_dataset_create_info *create_info, - const struct pvr_device_info *dev_info, - struct pvr_winsys_rt_dataset **const rt_dataset_out) -{ - const pvr_dev_addr_t macrotile_addrs[ROGUE_FWIF_NUM_RTDATAS] = { - [0] = create_info->rt_datas[0].macrotile_array_dev_addr, - [1] = create_info->rt_datas[1].macrotile_array_dev_addr, - }; - const pvr_dev_addr_t pm_mlist_addrs[ROGUE_FWIF_NUM_RTDATAS] = { - [0] = create_info->rt_datas[0].pm_mlist_dev_addr, - [1] = create_info->rt_datas[1].pm_mlist_dev_addr, - }; - const pvr_dev_addr_t rgn_header_addrs[ROGUE_FWIF_NUM_RTDATAS] = { - [0] = create_info->rt_datas[0].rgn_header_dev_addr, - [1] = create_info->rt_datas[1].rgn_header_dev_addr, - }; - - struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ws); - struct pvr_srv_winsys_free_list *srv_local_free_list = - to_pvr_srv_winsys_free_list(create_info->local_free_list); - void *free_lists[ROGUE_FW_MAX_FREELISTS] = { NULL }; - struct pvr_srv_winsys_rt_dataset *srv_rt_dataset; - void *handles[ROGUE_FWIF_NUM_RTDATAS]; - struct pvr_rogue_cr_te rogue_te_regs; - struct pvr_rt_mtile_info mtile_info; - uint32_t isp_mtile_size; - VkResult result; - - free_lists[ROGUE_FW_LOCAL_FREELIST] = srv_local_free_list->handle; - - if (srv_local_free_list->parent) { - free_lists[ROGUE_FW_GLOBAL_FREELIST] = - srv_local_free_list->parent->handle; - } - - srv_rt_dataset = vk_zalloc(ws->alloc, - sizeof(*srv_rt_dataset), - 8, - VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); - if (!srv_rt_dataset) - return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); - - /* If greater than 1 we'll have to pass in an array. For now just passing in - * the reference. - */ - STATIC_ASSERT(ROGUE_FWIF_NUM_GEOMDATAS == 1); - /* If not 2 the arrays used in the bridge call will require updating. */ - STATIC_ASSERT(ROGUE_FWIF_NUM_RTDATAS == 2); - - pvr_rt_mtile_info_init(dev_info, - &mtile_info, - create_info->width, - create_info->height, - create_info->samples); - - isp_mtile_size = pvr_rogue_get_cr_isp_mtile_size_val(dev_info, - &mtile_info, - create_info->samples); - - pvr_rogue_ct_te_init(dev_info, - &mtile_info, - create_info->samples, - &rogue_te_regs); - - result = pvr_srv_rgx_create_hwrt_dataset( - ws->render_fd, - pvr_rogue_get_cr_multisamplectl_val(create_info->samples, true), - pvr_rogue_get_cr_multisamplectl_val(create_info->samples, false), - macrotile_addrs, - pm_mlist_addrs, - &create_info->rtc_dev_addr, - rgn_header_addrs, - &create_info->tpc_dev_addr, - &create_info->vheap_table_dev_addr, - free_lists, - create_info->isp_merge_lower_x, - create_info->isp_merge_lower_y, - create_info->isp_merge_scale_x, - create_info->isp_merge_scale_y, - create_info->isp_merge_upper_x, - create_info->isp_merge_upper_y, - isp_mtile_size, - rogue_te_regs.mtile_stride, - pvr_rogue_get_ppp_screen_val(create_info->width, create_info->height), - create_info->rgn_header_size, - rogue_te_regs.aa, - rogue_te_regs.mtile1, - rogue_te_regs.mtile2, - rogue_te_regs.screen, - create_info->tpc_size, - create_info->tpc_stride, - create_info->layers, - handles); - if (result != VK_SUCCESS) - goto err_vk_free_srv_rt_dataset; - - srv_rt_dataset->rt_datas[0].handle = handles[0]; - srv_rt_dataset->rt_datas[1].handle = handles[1]; - - for (uint32_t i = 0; i < ARRAY_SIZE(srv_rt_dataset->rt_datas); i++) { - srv_rt_dataset->rt_datas[i].sync_prim = pvr_srv_sync_prim_alloc(srv_ws); - if (!srv_rt_dataset->rt_datas[i].sync_prim) - goto err_srv_sync_prim_free; - } - - srv_rt_dataset->base.ws = ws; - - *rt_dataset_out = &srv_rt_dataset->base; - - return VK_SUCCESS; - -err_srv_sync_prim_free: - for (uint32_t i = 0; i < ARRAY_SIZE(srv_rt_dataset->rt_datas); i++) { - pvr_srv_sync_prim_free(srv_ws, srv_rt_dataset->rt_datas[i].sync_prim); - - if (srv_rt_dataset->rt_datas[i].handle) { - pvr_srv_rgx_destroy_hwrt_dataset(ws->render_fd, - srv_rt_dataset->rt_datas[i].handle); - } - } - -err_vk_free_srv_rt_dataset: - vk_free(ws->alloc, srv_rt_dataset); - - return result; -} - void pvr_srv_render_target_dataset_destroy( struct pvr_winsys_rt_dataset *rt_dataset) { @@ -635,298 +300,6 @@ void pvr_srv_winsys_render_ctx_destroy(struct pvr_winsys_render_ctx *ctx) vk_free(srv_ws->base.alloc, srv_ctx); } -static uint32_t -pvr_srv_geometry_cmd_stream_load(struct rogue_fwif_cmd_ta *const cmd, - const uint8_t *const stream, - const uint32_t stream_len, - const struct pvr_device_info *const dev_info) -{ - const uint32_t *stream_ptr = (const uint32_t *)stream; - struct rogue_fwif_ta_regs *const regs = &cmd->regs; - uint32_t main_stream_len = - pvr_csb_unpack((const uint64_t *)stream_ptr, KMD_STREAM_HDR).length; - - stream_ptr += pvr_cmd_length(KMD_STREAM_HDR); - - regs->vdm_ctrl_stream_base = *(const uint64_t *)stream_ptr; - stream_ptr += pvr_cmd_length(CR_VDM_CTRL_STREAM_BASE); - - regs->tpu_border_colour_table = *(const uint64_t *)stream_ptr; - stream_ptr += pvr_cmd_length(CR_TPU_BORDER_COLOUR_TABLE_VDM); - - regs->ppp_ctrl = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_PPP_CTRL); - - regs->te_psg = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_TE_PSG); - - regs->vdm_context_resume_task0_size = *stream_ptr; - stream_ptr += pvr_cmd_length(VDMCTRL_PDS_STATE0); - - regs->view_idx = *stream_ptr; - stream_ptr++; - - assert((const uint8_t *)stream_ptr - stream <= stream_len); - assert((const uint8_t *)stream_ptr - stream == main_stream_len); - - return main_stream_len; -} - -static void pvr_srv_geometry_cmd_ext_stream_load( - struct rogue_fwif_cmd_ta *const cmd, - const uint8_t *const stream, - const uint32_t stream_len, - const uint32_t ext_stream_offset, - const struct pvr_device_info *const dev_info) -{ - const uint32_t *ext_stream_ptr = - (const uint32_t *)((uint8_t *)stream + ext_stream_offset); - struct rogue_fwif_ta_regs *const regs = &cmd->regs; - - struct ROGUE_KMD_STREAM_EXTHDR_GEOM0 header0; - - header0 = pvr_csb_unpack(ext_stream_ptr, KMD_STREAM_EXTHDR_GEOM0); - ext_stream_ptr += pvr_cmd_length(KMD_STREAM_EXTHDR_GEOM0); - - assert(PVR_HAS_QUIRK(dev_info, 49927) == header0.has_brn49927); - if (header0.has_brn49927) { - regs->tpu = *ext_stream_ptr; - ext_stream_ptr += pvr_cmd_length(CR_TPU); - } - - assert((const uint8_t *)ext_stream_ptr - stream == stream_len); -} - -static void pvr_srv_geometry_cmd_init( - const struct pvr_winsys_render_submit_info *submit_info, - const struct pvr_srv_sync_prim *sync_prim, - struct rogue_fwif_cmd_ta *cmd, - const struct pvr_device_info *const dev_info) -{ - const struct pvr_winsys_geometry_state *state = &submit_info->geometry; - uint32_t ext_stream_offset; - - memset(cmd, 0, sizeof(*cmd)); - - cmd->cmd_shared.cmn.frame_num = submit_info->frame_num; - - ext_stream_offset = pvr_srv_geometry_cmd_stream_load(cmd, - state->fw_stream, - state->fw_stream_len, - dev_info); - - if (ext_stream_offset < state->fw_stream_len) { - pvr_srv_geometry_cmd_ext_stream_load(cmd, - state->fw_stream, - state->fw_stream_len, - ext_stream_offset, - dev_info); - } - - if (state->flags.is_first_geometry) - cmd->flags |= ROGUE_FWIF_TAFLAGS_FIRSTKICK; - - if (state->flags.is_last_geometry) - cmd->flags |= ROGUE_FWIF_TAFLAGS_LASTKICK; - - if (state->flags.use_single_core) - cmd->flags |= ROGUE_FWIF_TAFLAGS_SINGLE_CORE; - - cmd->partial_render_ta_3d_fence.ufo_addr.addr = - pvr_srv_sync_prim_get_fw_addr(sync_prim); - cmd->partial_render_ta_3d_fence.value = sync_prim->value; -} - -static uint32_t -pvr_srv_fragment_cmd_stream_load(struct rogue_fwif_cmd_3d *const cmd, - const uint8_t *const stream, - const uint32_t stream_len, - const struct pvr_device_info *const dev_info) -{ - const uint32_t *stream_ptr = (const uint32_t *)stream; - struct rogue_fwif_3d_regs *const regs = &cmd->regs; - uint32_t main_stream_len = - pvr_csb_unpack((const uint64_t *)stream_ptr, KMD_STREAM_HDR).length; - - stream_ptr += pvr_cmd_length(KMD_STREAM_HDR); - - regs->isp_scissor_base = *(const uint64_t *)stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_SCISSOR_BASE); - - regs->isp_dbias_base = *(const uint64_t *)stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_DBIAS_BASE); - - regs->isp_oclqry_base = *(const uint64_t *)stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_OCLQRY_BASE); - - regs->isp_zlsctl = *(const uint64_t *)stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_ZLSCTL); - - regs->isp_zload_store_base = *(const uint64_t *)stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_ZLOAD_BASE); - - regs->isp_stencil_load_store_base = *(const uint64_t *)stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_STENCIL_LOAD_BASE); - - if (PVR_HAS_FEATURE(dev_info, requires_fb_cdc_zls_setup)) { - regs->fb_cdc_zls = *(const uint64_t *)stream_ptr; - stream_ptr += 2U; - } - - STATIC_ASSERT(ARRAY_SIZE(regs->pbe_word) == 8U); - STATIC_ASSERT(ARRAY_SIZE(regs->pbe_word[0]) == 3U); - STATIC_ASSERT(sizeof(regs->pbe_word[0][0]) == sizeof(uint64_t)); - memcpy(regs->pbe_word, stream_ptr, sizeof(regs->pbe_word)); - stream_ptr += 8U * 3U * 2U; - - regs->tpu_border_colour_table = *(const uint64_t *)stream_ptr; - stream_ptr += pvr_cmd_length(CR_TPU_BORDER_COLOUR_TABLE_PDM); - - STATIC_ASSERT(ARRAY_SIZE(regs->pds_bgnd) == 3U); - STATIC_ASSERT(sizeof(regs->pds_bgnd[0]) == sizeof(uint64_t)); - memcpy(regs->pds_bgnd, stream_ptr, sizeof(regs->pds_bgnd)); - stream_ptr += 3U * 2U; - - STATIC_ASSERT(ARRAY_SIZE(regs->pds_pr_bgnd) == 3U); - STATIC_ASSERT(sizeof(regs->pds_pr_bgnd[0]) == sizeof(uint64_t)); - memcpy(regs->pds_pr_bgnd, stream_ptr, sizeof(regs->pds_pr_bgnd)); - stream_ptr += 3U * 2U; - - STATIC_ASSERT(ARRAY_SIZE(regs->usc_clear_register) == 8U); - STATIC_ASSERT(sizeof(regs->usc_clear_register[0]) == sizeof(uint32_t)); - memcpy(regs->usc_clear_register, - stream_ptr, - sizeof(regs->usc_clear_register)); - stream_ptr += 8U; - - regs->usc_pixel_output_ctrl = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_USC_PIXEL_OUTPUT_CTRL); - - regs->isp_bgobjdepth = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_BGOBJDEPTH); - - regs->isp_bgobjvals = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_BGOBJVALS); - - regs->isp_aa = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_AA); - - regs->isp_ctl = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_CTL); - - regs->event_pixel_pds_info = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_EVENT_PIXEL_PDS_INFO); - - if (PVR_HAS_FEATURE(dev_info, cluster_grouping)) { - regs->pixel_phantom = *stream_ptr; - stream_ptr++; - } - - regs->view_idx = *stream_ptr; - stream_ptr++; - - regs->event_pixel_pds_data = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_EVENT_PIXEL_PDS_DATA); - - if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) { - regs->isp_oclqry_stride = *stream_ptr; - stream_ptr++; - } - - if (PVR_HAS_FEATURE(dev_info, zls_subtile)) { - regs->isp_zls_pixels = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_ZLS_PIXELS); - } - - cmd->zls_stride = *stream_ptr; - stream_ptr++; - - cmd->sls_stride = *stream_ptr; - stream_ptr++; - - if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) { - cmd->execute_count = *stream_ptr; - stream_ptr++; - } - - assert((const uint8_t *)stream_ptr - stream <= stream_len); - assert((const uint8_t *)stream_ptr - stream == main_stream_len); - - return main_stream_len; -} - -static void pvr_srv_fragment_cmd_ext_stream_load( - struct rogue_fwif_cmd_3d *const cmd, - const uint8_t *const stream, - const uint32_t stream_len, - const uint32_t ext_stream_offset, - const struct pvr_device_info *const dev_info) -{ - const uint32_t *ext_stream_ptr = - (const uint32_t *)((uint8_t *)stream + ext_stream_offset); - struct rogue_fwif_3d_regs *const regs = &cmd->regs; - - struct ROGUE_KMD_STREAM_EXTHDR_FRAG0 header0; - - header0 = pvr_csb_unpack(ext_stream_ptr, KMD_STREAM_EXTHDR_FRAG0); - ext_stream_ptr += pvr_cmd_length(KMD_STREAM_EXTHDR_FRAG0); - - assert(PVR_HAS_QUIRK(dev_info, 49927) == header0.has_brn49927); - if (header0.has_brn49927) { - regs->tpu = *ext_stream_ptr; - ext_stream_ptr += pvr_cmd_length(CR_TPU); - } - - assert((const uint8_t *)ext_stream_ptr - stream == stream_len); -} - -static void -pvr_srv_fragment_cmd_init(struct rogue_fwif_cmd_3d *cmd, - const struct pvr_winsys_fragment_state *state, - const struct pvr_device_info *dev_info, - uint32_t frame_num) -{ - uint32_t ext_stream_offset; - - memset(cmd, 0, sizeof(*cmd)); - - cmd->cmd_shared.cmn.frame_num = frame_num; - - ext_stream_offset = pvr_srv_fragment_cmd_stream_load(cmd, - state->fw_stream, - state->fw_stream_len, - dev_info); - - if (ext_stream_offset < state->fw_stream_len) { - pvr_srv_fragment_cmd_ext_stream_load(cmd, - state->fw_stream, - state->fw_stream_len, - ext_stream_offset, - dev_info); - } - - if (state->flags.has_depth_buffer) - cmd->flags |= ROGUE_FWIF_RENDERFLAGS_DEPTHBUFFER; - - if (state->flags.has_stencil_buffer) - cmd->flags |= ROGUE_FWIF_RENDERFLAGS_STENCILBUFFER; - - if (state->flags.prevent_cdm_overlap) - cmd->flags |= ROGUE_FWIF_RENDERFLAGS_PREVENT_CDM_OVERLAP; - - if (state->flags.use_single_core) - cmd->flags |= ROGUE_FWIF_RENDERFLAGS_SINGLE_CORE; - - if (state->flags.get_vis_results) - cmd->flags |= ROGUE_FWIF_RENDERFLAGS_GETVISRESULTS; - - if (state->flags.has_spm_scratch_buffer) - cmd->flags |= ROGUE_FWIF_RENDERFLAGS_SPMSCRATCHBUFFER; - - if (state->flags.disable_pixel_merging) - cmd->flags |= ROGUE_FWIF_RENDERFLAGS_DISABLE_PIXELMERGE; -} - VkResult pvr_srv_winsys_render_submit( const struct pvr_winsys_render_ctx *ctx, const struct pvr_winsys_render_submit_info *submit_info, diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_render.h b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_render.h index d9bb9f2c303..d3ca0cadf7b 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_render.h +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_render.h @@ -27,8 +27,12 @@ #include #include +struct rogue_fwif_cmd_3d; +struct rogue_fwif_cmd_ta; struct pvr_device_info; +struct pvr_srv_sync_prim; struct pvr_winsys; +struct pvr_winsys_fragment_state; struct pvr_winsys_free_list; struct pvr_winsys_render_ctx; struct pvr_winsys_render_ctx_create_info; @@ -74,4 +78,21 @@ VkResult pvr_srv_winsys_render_submit( struct vk_sync *signal_sync_geom, struct vk_sync *signal_sync_frag); +VkResult pvr_srv_render_target_dataset_create( + struct pvr_winsys *ws, + const struct pvr_winsys_rt_dataset_create_info *create_info, + const struct pvr_device_info *dev_info, + struct pvr_winsys_rt_dataset **const rt_dataset_out); + +void pvr_srv_fragment_cmd_init(struct rogue_fwif_cmd_3d *cmd, + const struct pvr_winsys_fragment_state *state, + const struct pvr_device_info *dev_info, + uint32_t frame_num); + +void pvr_srv_geometry_cmd_init( + const struct pvr_winsys_render_submit_info *submit_info, + const struct pvr_srv_sync_prim *sync_prim, + struct rogue_fwif_cmd_ta *cmd, + const struct pvr_device_info *const dev_info); + #endif /* PVR_SRV_JOB_RENDER_H */ diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.c b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.c index 3e6d450f79b..ce6eb7c1683 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.c +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.c @@ -31,7 +31,6 @@ #include "fw-api/pvr_rogue_fwif.h" #include "fw-api/pvr_rogue_fwif_rf.h" -#include "pvr_csb.h" #include "pvr_device_info.h" #include "pvr_srv.h" #include "pvr_srv_bridge.h" @@ -133,92 +132,6 @@ void pvr_srv_winsys_transfer_ctx_destroy(struct pvr_winsys_transfer_ctx *ctx) vk_free(srv_ws->base.alloc, srv_ctx); } -static void -pvr_srv_transfer_cmd_stream_load(struct rogue_fwif_cmd_transfer *const cmd, - const uint8_t *const stream, - const uint32_t stream_len, - const struct pvr_device_info *const dev_info) -{ - const uint32_t *stream_ptr = (const uint32_t *)stream; - struct rogue_fwif_transfer_regs *const regs = &cmd->regs; - uint32_t main_stream_len = - pvr_csb_unpack((uint64_t *)stream_ptr, KMD_STREAM_HDR).length; - - stream_ptr += pvr_cmd_length(KMD_STREAM_HDR); - - memcpy(®s->pds_bgnd0_base, stream_ptr, sizeof(regs->pds_bgnd0_base)); - stream_ptr += pvr_cmd_length(CR_PDS_BGRND0_BASE); - - memcpy(®s->pds_bgnd1_base, stream_ptr, sizeof(regs->pds_bgnd1_base)); - stream_ptr += pvr_cmd_length(CR_PDS_BGRND1_BASE); - - memcpy(®s->pds_bgnd3_sizeinfo, - stream_ptr, - sizeof(regs->pds_bgnd3_sizeinfo)); - stream_ptr += pvr_cmd_length(CR_PDS_BGRND3_SIZEINFO); - - memcpy(®s->isp_mtile_base, stream_ptr, sizeof(regs->isp_mtile_base)); - stream_ptr += pvr_cmd_length(CR_ISP_MTILE_BASE); - - STATIC_ASSERT(ARRAY_SIZE(regs->pbe_wordx_mrty) == 9U); - STATIC_ASSERT(sizeof(regs->pbe_wordx_mrty[0]) == sizeof(uint64_t)); - memcpy(regs->pbe_wordx_mrty, stream_ptr, sizeof(regs->pbe_wordx_mrty)); - stream_ptr += 9U * 2U; - - regs->isp_bgobjvals = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_BGOBJVALS); - - regs->usc_pixel_output_ctrl = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_USC_PIXEL_OUTPUT_CTRL); - - regs->usc_clear_register0 = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_USC_CLEAR_REGISTER); - - regs->usc_clear_register1 = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_USC_CLEAR_REGISTER); - - regs->usc_clear_register2 = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_USC_CLEAR_REGISTER); - - regs->usc_clear_register3 = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_USC_CLEAR_REGISTER); - - regs->isp_mtile_size = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_MTILE_SIZE); - - regs->isp_render_origin = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_RENDER_ORIGIN); - - regs->isp_ctl = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_CTL); - - regs->isp_aa = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_AA); - - regs->event_pixel_pds_info = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_EVENT_PIXEL_PDS_INFO); - - regs->event_pixel_pds_code = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_EVENT_PIXEL_PDS_CODE); - - regs->event_pixel_pds_data = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_EVENT_PIXEL_PDS_DATA); - - regs->isp_render = *stream_ptr; - stream_ptr += pvr_cmd_length(CR_ISP_RENDER); - - regs->isp_rgn = *stream_ptr; - stream_ptr++; - - if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) { - regs->frag_screen = *stream_ptr; - stream_ptr++; - } - - assert((const uint8_t *)stream_ptr - stream == stream_len); - assert((const uint8_t *)stream_ptr - stream == main_stream_len); -} - static void pvr_srv_transfer_cmds_init( const struct pvr_winsys_transfer_submit_info *submit_info, struct rogue_fwif_cmd_transfer *cmds, diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.h b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.h index 86f548f99a7..b9d8e8cad38 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.h +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.h @@ -26,6 +26,7 @@ #include +struct rogue_fwif_cmd_transfer; struct pvr_device_info; struct pvr_winsys; struct pvr_winsys_transfer_ctx; @@ -49,4 +50,10 @@ VkResult pvr_srv_winsys_transfer_submit( const struct pvr_device_info *dev_info, struct vk_sync *signal_sync); +void pvr_srv_transfer_cmd_stream_load( + struct rogue_fwif_cmd_transfer *const cmd, + const uint8_t *const stream, + const uint32_t stream_len, + const struct pvr_device_info *const dev_info); + #endif /* PVR_SRV_JOB_TRANSFER_H */