pvr/srv: define per-arch winsys-ops

This moves the dispatching for each winsys function out to arch-specific
variants of the pvr_winsys_ops structure instead. This gets rid of some
needless complexity, and should make the code easier to maintain in the
long run.

Reviewed-by: Ashish Chauhan <ashish.chauhan@imgtec.com
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39348>
This commit is contained in:
Erik Faye-Lund 2026-01-08 13:27:50 +01:00 committed by Marge Bot
parent 65f06dd25b
commit 2736dd1220
10 changed files with 516 additions and 563 deletions

View file

@ -23,10 +23,16 @@
#include "pvr_srv_job_compute.h"
#include "util/os_file.h"
#include "vk_log.h"
#include "fw-api/pvr_rogue_fwif.h"
#include "pvr_csb.h"
#include "pvr_device_info.h"
#include "pvr_srv.h"
#include "pvr_srv_bridge.h"
static uint32_t
pvr_srv_compute_cmd_stream_load(struct rogue_fwif_cmd_compute *const cmd,
@ -104,10 +110,10 @@ static void pvr_srv_compute_cmd_ext_stream_load(
assert((const uint8_t *)ext_stream_ptr - stream == stream_len);
}
void PVR_PER_ARCH(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)
static void
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;
@ -135,3 +141,74 @@ void PVR_PER_ARCH(srv_compute_cmd_init)(
if (submit_info->flags.use_single_core)
cmd->flags |= ROGUE_FWIF_COMPUTE_FLAG_SINGLE_CORE;
}
VkResult PVR_PER_ARCH(srv_winsys_compute_submit)(
const struct pvr_winsys_compute_ctx *ctx,
const struct pvr_winsys_compute_submit_info *submit_info,
const struct pvr_device_info *const dev_info,
struct vk_sync *signal_sync)
{
const struct pvr_srv_winsys_compute_ctx *srv_ctx =
to_pvr_srv_winsys_compute_ctx(ctx);
const struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws);
struct rogue_fwif_cmd_compute compute_cmd;
struct pvr_srv_sync *srv_signal_sync;
VkResult result;
int in_fd = -1;
int fence;
srv_compute_cmd_init(submit_info, &compute_cmd, dev_info);
if (submit_info->wait) {
struct pvr_srv_sync *srv_wait_sync = to_srv_sync(submit_info->wait);
if (srv_wait_sync->fd >= 0) {
in_fd = os_dupfd_cloexec(srv_wait_sync->fd);
if (in_fd == -1) {
return vk_errorf(NULL,
VK_ERROR_OUT_OF_HOST_MEMORY,
"dup called on wait sync failed, Errno: %s",
strerror(errno));
}
}
}
do {
result = pvr_srv_rgx_kick_compute2(srv_ws->base.render_fd,
srv_ctx->handle,
0U,
NULL,
NULL,
NULL,
in_fd,
srv_ctx->timeline,
sizeof(compute_cmd),
(uint8_t *)&compute_cmd,
submit_info->job_num,
0,
NULL,
NULL,
0U,
0U,
0U,
0U,
"COMPUTE",
&fence);
} while (result == VK_NOT_READY);
if (result != VK_SUCCESS)
goto end_close_in_fd;
if (signal_sync) {
srv_signal_sync = to_srv_sync(signal_sync);
pvr_srv_set_sync_payload(srv_signal_sync, fence);
} else if (fence != -1) {
close(fence);
}
end_close_in_fd:
if (in_fd >= 0)
close(in_fd);
return result;
}

View file

@ -523,11 +523,11 @@ static void pvr_srv_geometry_cmd_ext_stream_load(
assert((const uint8_t *)ext_stream_ptr - stream == stream_len);
}
void PVR_PER_ARCH(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)
static void
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;
@ -706,11 +706,10 @@ static void pvr_srv_fragment_cmd_ext_stream_load(
assert((const uint8_t *)ext_stream_ptr - stream == stream_len);
}
void PVR_PER_ARCH(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)
static void 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;
@ -752,3 +751,192 @@ void PVR_PER_ARCH(srv_fragment_cmd_init)(
if (state->flags.disable_pixel_merging)
cmd->flags |= ROGUE_FWIF_RENDERFLAGS_DISABLE_PIXELMERGE;
}
VkResult PVR_PER_ARCH(srv_winsys_render_submit)(
const struct pvr_winsys_render_ctx *ctx,
const struct pvr_winsys_render_submit_info *submit_info,
const struct pvr_device_info *dev_info,
struct vk_sync *signal_sync_geom,
struct vk_sync *signal_sync_frag)
{
const struct pvr_srv_winsys_rt_dataset *srv_rt_dataset =
to_pvr_srv_winsys_rt_dataset(submit_info->rt_dataset);
struct pvr_srv_sync_prim *sync_prim =
srv_rt_dataset->rt_datas[submit_info->rt_data_idx].sync_prim;
void *rt_data_handle =
srv_rt_dataset->rt_datas[submit_info->rt_data_idx].handle;
const struct pvr_srv_winsys_render_ctx *srv_ctx =
to_pvr_srv_winsys_render_ctx(ctx);
const struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws);
struct pvr_srv_sync *srv_signal_sync_geom;
struct pvr_srv_sync *srv_signal_sync_frag;
struct rogue_fwif_cmd_ta geom_cmd;
struct rogue_fwif_cmd_3d frag_cmd = { 0 };
struct rogue_fwif_cmd_3d pr_cmd = { 0 };
uint8_t *frag_cmd_ptr = NULL;
uint32_t frag_cmd_size = 0;
uint32_t current_sync_value = sync_prim->value;
uint32_t geom_sync_update_value;
uint32_t frag_to_geom_fence_count = 0;
uint32_t frag_to_geom_fence_value;
uint32_t frag_sync_update_count = 0;
uint32_t frag_sync_update_value;
int in_frag_fd = -1;
int in_geom_fd = -1;
int fence_frag;
int fence_geom;
VkResult result;
srv_geometry_cmd_init(submit_info, sync_prim, &geom_cmd, dev_info);
srv_fragment_cmd_init(&pr_cmd,
&submit_info->fragment_pr,
dev_info,
submit_info->frame_num);
if (submit_info->has_fragment_job) {
srv_fragment_cmd_init(&frag_cmd,
&submit_info->fragment,
dev_info,
submit_info->frame_num);
frag_cmd_ptr = (uint8_t *)&frag_cmd;
frag_cmd_size = sizeof(frag_cmd);
}
if (submit_info->geometry.wait) {
struct pvr_srv_sync *srv_wait_sync =
to_srv_sync(submit_info->geometry.wait);
if (srv_wait_sync->fd >= 0) {
in_geom_fd = os_dupfd_cloexec(srv_wait_sync->fd);
if (in_geom_fd == -1) {
return vk_errorf(NULL,
VK_ERROR_OUT_OF_HOST_MEMORY,
"dup called on wait sync failed, Errno: %s",
strerror(errno));
}
}
}
if (submit_info->fragment.wait) {
struct pvr_srv_sync *srv_wait_sync =
to_srv_sync(submit_info->fragment.wait);
if (srv_wait_sync->fd >= 0) {
in_frag_fd = os_dupfd_cloexec(srv_wait_sync->fd);
if (in_frag_fd == -1) {
return vk_errorf(NULL,
VK_ERROR_OUT_OF_HOST_MEMORY,
"dup called on wait sync failed, Errno: %s",
strerror(errno));
}
}
}
if (submit_info->geometry.flags.is_first_geometry) {
frag_to_geom_fence_count = 1;
frag_to_geom_fence_value = current_sync_value;
}
/* Geometery is always kicked */
geom_sync_update_value = ++current_sync_value;
if (submit_info->has_fragment_job) {
frag_sync_update_count = 1;
frag_sync_update_value = ++current_sync_value;
}
do {
/* The fw allows the ZS and MSAA scratch buffers to be lazily allocated in
* which case we need to provide a status update (i.e. if they are
* physically backed or not) to the fw. In our case they will always be
* physically backed so no need to inform the fw about their status and
* pass in anything. We'll just pass in NULL.
*/
result = pvr_srv_rgx_kick_render2(srv_ws->base.render_fd,
srv_ctx->handle,
frag_to_geom_fence_count,
&sync_prim->ctx->block_handle,
&sync_prim->offset,
&frag_to_geom_fence_value,
1,
&sync_prim->ctx->block_handle,
&sync_prim->offset,
&geom_sync_update_value,
frag_sync_update_count,
&sync_prim->ctx->block_handle,
&sync_prim->offset,
&frag_sync_update_value,
sync_prim->ctx->block_handle,
sync_prim->offset,
geom_sync_update_value,
in_geom_fd,
srv_ctx->timeline_geom,
&fence_geom,
"GEOM",
in_frag_fd,
srv_ctx->timeline_frag,
&fence_frag,
"FRAG",
sizeof(geom_cmd),
(uint8_t *)&geom_cmd,
sizeof(pr_cmd),
(uint8_t *)&pr_cmd,
frag_cmd_size,
frag_cmd_ptr,
submit_info->job_num,
/* Always kick the TA. */
true,
/* Always kick a PR. */
true,
submit_info->has_fragment_job,
false,
0,
rt_data_handle,
NULL,
NULL,
0,
NULL,
NULL,
0,
0,
0,
0,
0);
} while (result == VK_NOT_READY);
if (result != VK_SUCCESS)
goto end_close_in_fds;
/* The job submission was succesful, update the sync prim value. */
sync_prim->value = current_sync_value;
if (signal_sync_geom) {
srv_signal_sync_geom = to_srv_sync(signal_sync_geom);
pvr_srv_set_sync_payload(srv_signal_sync_geom, fence_geom);
} else if (fence_geom != -1) {
close(fence_geom);
}
if (signal_sync_frag) {
srv_signal_sync_frag = to_srv_sync(signal_sync_frag);
pvr_srv_set_sync_payload(srv_signal_sync_frag, fence_frag);
} else if (fence_frag != -1) {
close(fence_frag);
}
end_close_in_fds:
if (in_geom_fd >= 0)
close(in_geom_fd);
if (in_frag_fd >= 0)
close(in_frag_fd);
return result;
}

View file

@ -23,15 +23,23 @@
#include "pvr_srv_job_transfer.h"
#include "util/os_file.h"
#include "vk_log.h"
#include "vk_util.h"
#include "fw-api/pvr_rogue_fwif.h"
#include "pvr_csb.h"
#include "pvr_device_info.h"
#include "pvr_srv.h"
#include "pvr_srv_bridge.h"
void PVR_PER_ARCH(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)
static void
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;
@ -112,3 +120,126 @@ void PVR_PER_ARCH(srv_transfer_cmd_stream_load)(
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,
uint32_t cmd_count,
const struct pvr_device_info *const dev_info)
{
memset(cmds, 0, sizeof(*cmds) * submit_info->cmd_count);
for (uint32_t i = 0; i < cmd_count; i++) {
const struct pvr_winsys_transfer_cmd *submit_cmd = &submit_info->cmds[i];
struct rogue_fwif_cmd_transfer *cmd = &cmds[i];
cmd->cmn.frame_num = submit_info->frame_num;
srv_transfer_cmd_stream_load(cmd,
submit_cmd->fw_stream,
submit_cmd->fw_stream_len,
dev_info);
if (submit_info->cmds[i].flags.use_single_core)
cmd->flags |= ROGUE_FWIF_CMDTRANSFER_SINGLE_CORE;
}
}
VkResult PVR_PER_ARCH(srv_winsys_transfer_submit)(
const struct pvr_winsys_transfer_ctx *ctx,
const struct pvr_winsys_transfer_submit_info *submit_info,
const struct pvr_device_info *const dev_info,
struct vk_sync *signal_sync)
{
const struct pvr_srv_winsys_transfer_ctx *srv_ctx =
to_pvr_srv_winsys_transfer_ctx(ctx);
const struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws);
struct rogue_fwif_cmd_transfer
*cmds_ptr_arr[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT];
uint32_t *update_sync_offsets[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
uint32_t client_update_count[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
void **update_ufo_syc_prims[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
uint32_t *update_values[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
uint32_t cmd_flags[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
uint32_t cmd_sizes[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT];
struct pvr_srv_sync *srv_signal_sync;
uint32_t job_num;
VkResult result;
int in_fd = -1;
int fence;
STACK_ARRAY(struct rogue_fwif_cmd_transfer,
transfer_cmds,
submit_info->cmd_count);
if (!transfer_cmds)
return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
pvr_srv_transfer_cmds_init(submit_info,
transfer_cmds,
submit_info->cmd_count,
dev_info);
for (uint32_t i = 0U; i < submit_info->cmd_count; i++) {
cmd_sizes[i] = sizeof(**cmds_ptr_arr);
cmds_ptr_arr[i] = &transfer_cmds[i];
}
if (submit_info->wait) {
struct pvr_srv_sync *srv_wait_sync = to_srv_sync(submit_info->wait);
if (srv_wait_sync->fd >= 0) {
in_fd = os_dupfd_cloexec(srv_wait_sync->fd);
if (in_fd == -1) {
return vk_errorf(NULL,
VK_ERROR_OUT_OF_HOST_MEMORY,
"dup called on wait sync failed, Errno: %s",
strerror(errno));
}
}
}
job_num = submit_info->job_num;
do {
result = pvr_srv_rgx_submit_transfer2(srv_ws->base.render_fd,
srv_ctx->handle,
submit_info->cmd_count,
client_update_count,
update_ufo_syc_prims,
update_sync_offsets,
update_values,
in_fd,
-1,
srv_ctx->timeline_3d,
"TRANSFER",
cmd_sizes,
(uint8_t **)cmds_ptr_arr,
cmd_flags,
job_num,
0U,
NULL,
NULL,
NULL,
&fence);
} while (result == VK_NOT_READY);
if (result != VK_SUCCESS)
goto end_close_in_fd;
if (signal_sync) {
srv_signal_sync = to_srv_sync(signal_sync);
pvr_srv_set_sync_payload(srv_signal_sync, fence);
} else if (fence != -1) {
close(fence);
}
end_close_in_fd:
if (in_fd >= 0)
close(in_fd);
STACK_ARRAY_FINISH(transfer_cmds);
return result;
}

View file

@ -618,35 +618,67 @@ static void pvr_srv_winsys_get_heaps_info(struct pvr_winsys *ws,
heaps->rgn_hdr_heap = &srv_ws->general_heap.base;
}
static const struct pvr_winsys_ops srv_winsys_ops = {
.destroy = pvr_srv_winsys_destroy,
.device_info_init = pvr_srv_winsys_device_info_init,
.get_heaps_info = pvr_srv_winsys_get_heaps_info,
.buffer_create = pvr_srv_winsys_buffer_create,
.buffer_create_from_fd = pvr_srv_winsys_buffer_create_from_fd,
.buffer_destroy = pvr_srv_winsys_buffer_destroy,
.buffer_get_fd = pvr_srv_winsys_buffer_get_fd,
.buffer_map = pvr_srv_winsys_buffer_map,
.buffer_unmap = pvr_srv_winsys_buffer_unmap,
.heap_alloc = pvr_srv_winsys_heap_alloc,
.heap_free = pvr_srv_winsys_heap_free,
.vma_map = pvr_srv_winsys_vma_map,
.vma_unmap = pvr_srv_winsys_vma_unmap,
.free_list_create = pvr_srv_winsys_free_list_create,
.free_list_destroy = pvr_srv_winsys_free_list_destroy,
.render_target_dataset_create = pvr_srv_render_target_dataset_create,
.render_target_dataset_destroy = pvr_srv_render_target_dataset_destroy,
.render_ctx_create = pvr_srv_winsys_render_ctx_create,
.render_ctx_destroy = pvr_srv_winsys_render_ctx_destroy,
.render_submit = pvr_srv_winsys_render_submit,
.compute_ctx_create = pvr_srv_winsys_compute_ctx_create,
.compute_ctx_destroy = pvr_srv_winsys_compute_ctx_destroy,
.compute_submit = pvr_srv_winsys_compute_submit,
.transfer_ctx_create = pvr_srv_winsys_transfer_ctx_create,
.transfer_ctx_destroy = pvr_srv_winsys_transfer_ctx_destroy,
.transfer_submit = pvr_srv_winsys_transfer_submit,
.null_job_submit = pvr_srv_winsys_null_job_submit,
};
#define PER_ARCH_FUNCS(arch) \
VkResult pvr_##arch##_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); \
\
VkResult pvr_##arch##_srv_winsys_render_submit( \
const struct pvr_winsys_render_ctx *ctx, \
const struct pvr_winsys_render_submit_info *submit_info, \
const struct pvr_device_info *dev_info, \
struct vk_sync *signal_sync_geom, \
struct vk_sync *signal_sync_frag); \
\
VkResult pvr_##arch##_srv_winsys_transfer_submit( \
const struct pvr_winsys_transfer_ctx *ctx, \
const struct pvr_winsys_transfer_submit_info *submit_info, \
const struct pvr_device_info *const dev_info, \
struct vk_sync *signal_sync); \
\
VkResult pvr_##arch##_srv_winsys_compute_submit( \
const struct pvr_winsys_compute_ctx *ctx, \
const struct pvr_winsys_compute_submit_info *submit_info, \
const struct pvr_device_info *dev_info, \
struct vk_sync *signal_sync)
PER_ARCH_FUNCS(rogue);
#define SRV_WINSYS(arch) \
static const struct pvr_winsys_ops pvr_##arch##_srv_winsys_ops = { \
.destroy = pvr_srv_winsys_destroy, \
.device_info_init = pvr_srv_winsys_device_info_init, \
.get_heaps_info = pvr_srv_winsys_get_heaps_info, \
.buffer_create = pvr_srv_winsys_buffer_create, \
.buffer_create_from_fd = pvr_srv_winsys_buffer_create_from_fd, \
.buffer_destroy = pvr_srv_winsys_buffer_destroy, \
.buffer_get_fd = pvr_srv_winsys_buffer_get_fd, \
.buffer_map = pvr_srv_winsys_buffer_map, \
.buffer_unmap = pvr_srv_winsys_buffer_unmap, \
.heap_alloc = pvr_srv_winsys_heap_alloc, \
.heap_free = pvr_srv_winsys_heap_free, \
.vma_map = pvr_srv_winsys_vma_map, \
.vma_unmap = pvr_srv_winsys_vma_unmap, \
.free_list_create = pvr_srv_winsys_free_list_create, \
.free_list_destroy = pvr_srv_winsys_free_list_destroy, \
.render_target_dataset_create = \
pvr_##arch##_srv_render_target_dataset_create, \
.render_target_dataset_destroy = pvr_srv_render_target_dataset_destroy, \
.render_ctx_create = pvr_srv_winsys_render_ctx_create, \
.render_ctx_destroy = pvr_srv_winsys_render_ctx_destroy, \
.render_submit = pvr_##arch##_srv_winsys_render_submit, \
.compute_ctx_create = pvr_srv_winsys_compute_ctx_create, \
.compute_ctx_destroy = pvr_srv_winsys_compute_ctx_destroy, \
.compute_submit = pvr_##arch##_srv_winsys_compute_submit, \
.transfer_ctx_create = pvr_srv_winsys_transfer_ctx_create, \
.transfer_ctx_destroy = pvr_srv_winsys_transfer_ctx_destroy, \
.transfer_submit = pvr_##arch##_srv_winsys_transfer_submit, \
.null_job_submit = pvr_srv_winsys_null_job_submit, \
}
SRV_WINSYS(rogue);
static bool pvr_is_driver_compatible(int render_fd)
{
@ -714,7 +746,12 @@ VkResult pvr_srv_winsys_create(const int render_fd,
PVR_BVNC_UNPACK_C(bvnc));
}
srv_ws->base.ops = &srv_winsys_ops;
switch (srv_ws->dev_info.ident.arch) {
case PVR_DEVICE_ARCH_ROGUE:
srv_ws->base.ops = &pvr_rogue_srv_winsys_ops;
break;
}
srv_ws->base.render_fd = render_fd;
srv_ws->base.display_fd = display_fd;
srv_ws->base.alloc = alloc;

View file

@ -44,17 +44,6 @@
#include "vk_alloc.h"
#include "vk_log.h"
struct pvr_srv_winsys_compute_ctx {
struct pvr_winsys_compute_ctx base;
void *handle;
int timeline;
};
#define to_pvr_srv_winsys_compute_ctx(ctx) \
container_of(ctx, struct pvr_srv_winsys_compute_ctx, base)
VkResult pvr_srv_winsys_compute_ctx_create(
struct pvr_winsys *ws,
const struct pvr_winsys_compute_ctx_create_info *create_info,
@ -138,87 +127,3 @@ void pvr_srv_winsys_compute_ctx_destroy(struct pvr_winsys_compute_ctx *ctx)
close(srv_ctx->timeline);
vk_free(srv_ws->base.alloc, srv_ctx);
}
#define PER_ARCH_FUNCS(arch) \
void pvr_##arch##_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)
PER_ARCH_FUNCS(rogue);
VkResult pvr_srv_winsys_compute_submit(
const struct pvr_winsys_compute_ctx *ctx,
const struct pvr_winsys_compute_submit_info *submit_info,
const struct pvr_device_info *const dev_info,
struct vk_sync *signal_sync)
{
const struct pvr_srv_winsys_compute_ctx *srv_ctx =
to_pvr_srv_winsys_compute_ctx(ctx);
const struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws);
struct rogue_fwif_cmd_compute compute_cmd;
struct pvr_srv_sync *srv_signal_sync;
VkResult result;
int in_fd = -1;
int fence;
enum pvr_device_arch arch = dev_info->ident.arch;
PVR_ARCH_DISPATCH(srv_compute_cmd_init,
arch,
submit_info,
&compute_cmd,
dev_info);
if (submit_info->wait) {
struct pvr_srv_sync *srv_wait_sync = to_srv_sync(submit_info->wait);
if (srv_wait_sync->fd >= 0) {
in_fd = os_dupfd_cloexec(srv_wait_sync->fd);
if (in_fd == -1) {
return vk_errorf(NULL,
VK_ERROR_OUT_OF_HOST_MEMORY,
"dup called on wait sync failed, Errno: %s",
strerror(errno));
}
}
}
do {
result = pvr_srv_rgx_kick_compute2(srv_ws->base.render_fd,
srv_ctx->handle,
0U,
NULL,
NULL,
NULL,
in_fd,
srv_ctx->timeline,
sizeof(compute_cmd),
(uint8_t *)&compute_cmd,
submit_info->job_num,
0,
NULL,
NULL,
0U,
0U,
0U,
0U,
"COMPUTE",
&fence);
} while (result == VK_NOT_READY);
if (result != VK_SUCCESS)
goto end_close_in_fd;
if (signal_sync) {
srv_signal_sync = to_srv_sync(signal_sync);
pvr_srv_set_sync_payload(srv_signal_sync, fence);
} else if (fence != -1) {
close(fence);
}
end_close_in_fd:
if (in_fd >= 0)
close(in_fd);
return result;
}

View file

@ -27,15 +27,23 @@
#include <vulkan/vulkan.h>
#include "pvr_macros.h"
#include "pvr_winsys.h"
struct rogue_fwif_cmd_compute;
struct pvr_device_info;
struct pvr_winsys;
struct pvr_winsys_compute_ctx;
struct pvr_winsys_compute_ctx_create_info;
struct pvr_winsys_compute_submit_info;
struct vk_sync;
struct pvr_srv_winsys_compute_ctx {
struct pvr_winsys_compute_ctx base;
void *handle;
int timeline;
};
#define to_pvr_srv_winsys_compute_ctx(ctx) \
container_of(ctx, struct pvr_srv_winsys_compute_ctx, base)
/*******************************************
Function prototypes
*******************************************/
@ -47,17 +55,12 @@ VkResult pvr_srv_winsys_compute_ctx_create(
struct pvr_winsys_compute_ctx **const ctx_out);
void pvr_srv_winsys_compute_ctx_destroy(struct pvr_winsys_compute_ctx *ctx);
VkResult pvr_srv_winsys_compute_submit(
#ifdef PVR_PER_ARCH
VkResult PVR_PER_ARCH(srv_winsys_compute_submit)(
const struct pvr_winsys_compute_ctx *ctx,
const struct pvr_winsys_compute_submit_info *submit_info,
const struct pvr_device_info *dev_info,
struct vk_sync *signal_sync);
#ifdef PVR_PER_ARCH
void PVR_PER_ARCH(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
#endif /* PVR_SRV_JOB_COMPUTE_H */

View file

@ -166,45 +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);
}
#define PER_ARCH_FUNCS(arch) \
VkResult pvr_##arch##_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_##arch##_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_##arch##_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)
PER_ARCH_FUNCS(rogue);
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)
{
VkResult result = VK_SUCCESS;
enum pvr_device_arch arch = dev_info->ident.arch;
PVR_ARCH_DISPATCH_RET(srv_render_target_dataset_create,
arch,
result,
ws,
create_info,
dev_info,
rt_dataset_out);
return result;
}
void pvr_srv_render_target_dataset_destroy(
struct pvr_winsys_rt_dataset *rt_dataset)
{
@ -339,202 +300,3 @@ void pvr_srv_winsys_render_ctx_destroy(struct pvr_winsys_render_ctx *ctx)
close(srv_ctx->timeline_geom);
vk_free(srv_ws->base.alloc, srv_ctx);
}
VkResult pvr_srv_winsys_render_submit(
const struct pvr_winsys_render_ctx *ctx,
const struct pvr_winsys_render_submit_info *submit_info,
const struct pvr_device_info *dev_info,
struct vk_sync *signal_sync_geom,
struct vk_sync *signal_sync_frag)
{
const struct pvr_srv_winsys_rt_dataset *srv_rt_dataset =
to_pvr_srv_winsys_rt_dataset(submit_info->rt_dataset);
struct pvr_srv_sync_prim *sync_prim =
srv_rt_dataset->rt_datas[submit_info->rt_data_idx].sync_prim;
void *rt_data_handle =
srv_rt_dataset->rt_datas[submit_info->rt_data_idx].handle;
const struct pvr_srv_winsys_render_ctx *srv_ctx =
to_pvr_srv_winsys_render_ctx(ctx);
const struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws);
struct pvr_srv_sync *srv_signal_sync_geom;
struct pvr_srv_sync *srv_signal_sync_frag;
struct rogue_fwif_cmd_ta geom_cmd;
struct rogue_fwif_cmd_3d frag_cmd = { 0 };
struct rogue_fwif_cmd_3d pr_cmd = { 0 };
uint8_t *frag_cmd_ptr = NULL;
uint32_t frag_cmd_size = 0;
uint32_t current_sync_value = sync_prim->value;
uint32_t geom_sync_update_value;
uint32_t frag_to_geom_fence_count = 0;
uint32_t frag_to_geom_fence_value;
uint32_t frag_sync_update_count = 0;
uint32_t frag_sync_update_value;
int in_frag_fd = -1;
int in_geom_fd = -1;
int fence_frag;
int fence_geom;
VkResult result;
enum pvr_device_arch arch = dev_info->ident.arch;
PVR_ARCH_DISPATCH(srv_geometry_cmd_init,
arch,
submit_info,
sync_prim,
&geom_cmd,
dev_info);
PVR_ARCH_DISPATCH(srv_fragment_cmd_init,
arch,
&pr_cmd,
&submit_info->fragment_pr,
dev_info,
submit_info->frame_num);
if (submit_info->has_fragment_job) {
PVR_ARCH_DISPATCH(srv_fragment_cmd_init,
arch,
&frag_cmd,
&submit_info->fragment,
dev_info,
submit_info->frame_num);
frag_cmd_ptr = (uint8_t *)&frag_cmd;
frag_cmd_size = sizeof(frag_cmd);
}
if (submit_info->geometry.wait) {
struct pvr_srv_sync *srv_wait_sync =
to_srv_sync(submit_info->geometry.wait);
if (srv_wait_sync->fd >= 0) {
in_geom_fd = os_dupfd_cloexec(srv_wait_sync->fd);
if (in_geom_fd == -1) {
return vk_errorf(NULL,
VK_ERROR_OUT_OF_HOST_MEMORY,
"dup called on wait sync failed, Errno: %s",
strerror(errno));
}
}
}
if (submit_info->fragment.wait) {
struct pvr_srv_sync *srv_wait_sync =
to_srv_sync(submit_info->fragment.wait);
if (srv_wait_sync->fd >= 0) {
in_frag_fd = os_dupfd_cloexec(srv_wait_sync->fd);
if (in_frag_fd == -1) {
return vk_errorf(NULL,
VK_ERROR_OUT_OF_HOST_MEMORY,
"dup called on wait sync failed, Errno: %s",
strerror(errno));
}
}
}
if (submit_info->geometry.flags.is_first_geometry) {
frag_to_geom_fence_count = 1;
frag_to_geom_fence_value = current_sync_value;
}
/* Geometery is always kicked */
geom_sync_update_value = ++current_sync_value;
if (submit_info->has_fragment_job) {
frag_sync_update_count = 1;
frag_sync_update_value = ++current_sync_value;
}
do {
/* The fw allows the ZS and MSAA scratch buffers to be lazily allocated in
* which case we need to provide a status update (i.e. if they are
* physically backed or not) to the fw. In our case they will always be
* physically backed so no need to inform the fw about their status and
* pass in anything. We'll just pass in NULL.
*/
result = pvr_srv_rgx_kick_render2(srv_ws->base.render_fd,
srv_ctx->handle,
frag_to_geom_fence_count,
&sync_prim->ctx->block_handle,
&sync_prim->offset,
&frag_to_geom_fence_value,
1,
&sync_prim->ctx->block_handle,
&sync_prim->offset,
&geom_sync_update_value,
frag_sync_update_count,
&sync_prim->ctx->block_handle,
&sync_prim->offset,
&frag_sync_update_value,
sync_prim->ctx->block_handle,
sync_prim->offset,
geom_sync_update_value,
in_geom_fd,
srv_ctx->timeline_geom,
&fence_geom,
"GEOM",
in_frag_fd,
srv_ctx->timeline_frag,
&fence_frag,
"FRAG",
sizeof(geom_cmd),
(uint8_t *)&geom_cmd,
sizeof(pr_cmd),
(uint8_t *)&pr_cmd,
frag_cmd_size,
frag_cmd_ptr,
submit_info->job_num,
/* Always kick the TA. */
true,
/* Always kick a PR. */
true,
submit_info->has_fragment_job,
false,
0,
rt_data_handle,
NULL,
NULL,
0,
NULL,
NULL,
0,
0,
0,
0,
0);
} while (result == VK_NOT_READY);
if (result != VK_SUCCESS)
goto end_close_in_fds;
/* The job submission was succesful, update the sync prim value. */
sync_prim->value = current_sync_value;
if (signal_sync_geom) {
srv_signal_sync_geom = to_srv_sync(signal_sync_geom);
pvr_srv_set_sync_payload(srv_signal_sync_geom, fence_geom);
} else if (fence_geom != -1) {
close(fence_geom);
}
if (signal_sync_frag) {
srv_signal_sync_frag = to_srv_sync(signal_sync_frag);
pvr_srv_set_sync_payload(srv_signal_sync_frag, fence_frag);
} else if (fence_frag != -1) {
close(fence_frag);
}
end_close_in_fds:
if (in_geom_fd >= 0)
close(in_geom_fd);
if (in_frag_fd >= 0)
close(in_frag_fd);
return result;
}

View file

@ -59,12 +59,6 @@ VkResult pvr_srv_winsys_free_list_create(
struct pvr_winsys_free_list **const free_list_out);
void pvr_srv_winsys_free_list_destroy(struct pvr_winsys_free_list *free_list);
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_render_target_dataset_destroy(
struct pvr_winsys_rt_dataset *rt_dataset);
@ -75,14 +69,14 @@ VkResult pvr_srv_winsys_render_ctx_create(
struct pvr_winsys_render_ctx **const ctx_out);
void pvr_srv_winsys_render_ctx_destroy(struct pvr_winsys_render_ctx *ctx);
VkResult pvr_srv_winsys_render_submit(
#ifdef PVR_PER_ARCH
VkResult PVR_PER_ARCH(srv_winsys_render_submit)(
const struct pvr_winsys_render_ctx *ctx,
const struct pvr_winsys_render_submit_info *submit_info,
const struct pvr_device_info *dev_info,
struct vk_sync *signal_sync_geom,
struct vk_sync *signal_sync_frag);
#ifdef PVR_PER_ARCH
VkResult PVR_PER_ARCH(srv_render_target_dataset_create)(
struct pvr_winsys *ws,
const struct pvr_winsys_rt_dataset_create_info *create_info,

View file

@ -31,33 +31,22 @@
#include "fw-api/pvr_rogue_fwif.h"
#include "fw-api/pvr_rogue_fwif_rf.h"
#include "pvr_device_info.h"
#include "pvr_srv.h"
#include "pvr_srv_bridge.h"
#include "pvr_srv_job_common.h"
#include "pvr_srv_job_transfer.h"
#include "pvr_srv_sync.h"
#include "pvr_winsys.h"
#include "util/macros.h"
#include "util/os_file.h"
#include "vk_alloc.h"
#include "vk_log.h"
#include "vk_util.h"
#define PVR_SRV_TRANSFER_CONTEXT_INITIAL_CCB_SIZE_LOG2 16U
#define PVR_SRV_TRANSFER_CONTEXT_MAX_CCB_SIZE_LOG2 0U
struct pvr_srv_winsys_transfer_ctx {
struct pvr_winsys_transfer_ctx base;
void *handle;
int timeline_3d;
};
#define to_pvr_srv_winsys_transfer_ctx(ctx) \
container_of(ctx, struct pvr_srv_winsys_transfer_ctx, base)
VkResult pvr_srv_winsys_transfer_ctx_create(
struct pvr_winsys *ws,
const struct pvr_winsys_transfer_ctx_create_info *create_info,
@ -131,138 +120,3 @@ void pvr_srv_winsys_transfer_ctx_destroy(struct pvr_winsys_transfer_ctx *ctx)
close(srv_ctx->timeline_3d);
vk_free(srv_ws->base.alloc, srv_ctx);
}
#define PER_ARCH_FUNCS(arch) \
void pvr_##arch##_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)
PER_ARCH_FUNCS(rogue);
static void pvr_srv_transfer_cmds_init(
const struct pvr_winsys_transfer_submit_info *submit_info,
struct rogue_fwif_cmd_transfer *cmds,
uint32_t cmd_count,
const struct pvr_device_info *const dev_info)
{
memset(cmds, 0, sizeof(*cmds) * submit_info->cmd_count);
enum pvr_device_arch arch = dev_info->ident.arch;
for (uint32_t i = 0; i < cmd_count; i++) {
const struct pvr_winsys_transfer_cmd *submit_cmd = &submit_info->cmds[i];
struct rogue_fwif_cmd_transfer *cmd = &cmds[i];
cmd->cmn.frame_num = submit_info->frame_num;
PVR_ARCH_DISPATCH(srv_transfer_cmd_stream_load,
arch,
cmd,
submit_cmd->fw_stream,
submit_cmd->fw_stream_len,
dev_info);
if (submit_info->cmds[i].flags.use_single_core)
cmd->flags |= ROGUE_FWIF_CMDTRANSFER_SINGLE_CORE;
}
}
VkResult pvr_srv_winsys_transfer_submit(
const struct pvr_winsys_transfer_ctx *ctx,
const struct pvr_winsys_transfer_submit_info *submit_info,
const struct pvr_device_info *const dev_info,
struct vk_sync *signal_sync)
{
const struct pvr_srv_winsys_transfer_ctx *srv_ctx =
to_pvr_srv_winsys_transfer_ctx(ctx);
const struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws);
struct rogue_fwif_cmd_transfer
*cmds_ptr_arr[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT];
uint32_t *update_sync_offsets[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
uint32_t client_update_count[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
void **update_ufo_syc_prims[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
uint32_t *update_values[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
uint32_t cmd_flags[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
uint32_t cmd_sizes[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT];
struct pvr_srv_sync *srv_signal_sync;
uint32_t job_num;
VkResult result;
int in_fd = -1;
int fence;
STACK_ARRAY(struct rogue_fwif_cmd_transfer,
transfer_cmds,
submit_info->cmd_count);
if (!transfer_cmds)
return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
pvr_srv_transfer_cmds_init(submit_info,
transfer_cmds,
submit_info->cmd_count,
dev_info);
for (uint32_t i = 0U; i < submit_info->cmd_count; i++) {
cmd_sizes[i] = sizeof(**cmds_ptr_arr);
cmds_ptr_arr[i] = &transfer_cmds[i];
}
if (submit_info->wait) {
struct pvr_srv_sync *srv_wait_sync = to_srv_sync(submit_info->wait);
if (srv_wait_sync->fd >= 0) {
in_fd = os_dupfd_cloexec(srv_wait_sync->fd);
if (in_fd == -1) {
return vk_errorf(NULL,
VK_ERROR_OUT_OF_HOST_MEMORY,
"dup called on wait sync failed, Errno: %s",
strerror(errno));
}
}
}
job_num = submit_info->job_num;
do {
result = pvr_srv_rgx_submit_transfer2(srv_ws->base.render_fd,
srv_ctx->handle,
submit_info->cmd_count,
client_update_count,
update_ufo_syc_prims,
update_sync_offsets,
update_values,
in_fd,
-1,
srv_ctx->timeline_3d,
"TRANSFER",
cmd_sizes,
(uint8_t **)cmds_ptr_arr,
cmd_flags,
job_num,
0U,
NULL,
NULL,
NULL,
&fence);
} while (result == VK_NOT_READY);
if (result != VK_SUCCESS)
goto end_close_in_fd;
if (signal_sync) {
srv_signal_sync = to_srv_sync(signal_sync);
pvr_srv_set_sync_payload(srv_signal_sync, fence);
} else if (fence != -1) {
close(fence);
}
end_close_in_fd:
if (in_fd >= 0)
close(in_fd);
STACK_ARRAY_FINISH(transfer_cmds);
return result;
}

View file

@ -27,15 +27,23 @@
#include <vulkan/vulkan.h>
#include "pvr_macros.h"
#include "pvr_winsys.h"
struct rogue_fwif_cmd_transfer;
struct pvr_device_info;
struct pvr_winsys;
struct pvr_winsys_transfer_ctx;
struct pvr_winsys_transfer_ctx_create_info;
struct pvr_winsys_transfer_submit_info;
struct vk_sync;
struct pvr_srv_winsys_transfer_ctx {
struct pvr_winsys_transfer_ctx base;
void *handle;
int timeline_3d;
};
#define to_pvr_srv_winsys_transfer_ctx(ctx) \
container_of(ctx, struct pvr_srv_winsys_transfer_ctx, base)
/*******************************************
Function prototypes
*******************************************/
@ -46,18 +54,12 @@ VkResult pvr_srv_winsys_transfer_ctx_create(
struct pvr_winsys_transfer_ctx **const ctx_out);
void pvr_srv_winsys_transfer_ctx_destroy(struct pvr_winsys_transfer_ctx *ctx);
VkResult pvr_srv_winsys_transfer_submit(
#ifdef PVR_PER_ARCH
VkResult PVR_PER_ARCH(srv_winsys_transfer_submit)(
const struct pvr_winsys_transfer_ctx *ctx,
const struct pvr_winsys_transfer_submit_info *submit_info,
const struct pvr_device_info *dev_info,
const struct pvr_device_info *const dev_info,
struct vk_sync *signal_sync);
#ifdef PVR_PER_ARCH
void PVR_PER_ARCH(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
#endif /* PVR_SRV_JOB_TRANSFER_H */