pvr: Add vk_sync support and remove service winsys syncobjs interface.
Removing internal pvr_winsys_syncobj abstraction and porting service winsys syncobj over to vk_sync_type. Signed-off-by: Rajnesh Kanwal <rajnesh.kanwal@imgtec.com> Reviewed-by: Karmjit Mahil <Karmjit.Mahil@imgtec.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15709>
This commit is contained in:
parent
98cc4c3a20
commit
d50418a4fc
|
@ -85,9 +85,10 @@ if with_imagination_srv
|
|||
'winsys/pvrsrvkm/pvr_srv_bridge.c',
|
||||
'winsys/pvrsrvkm/pvr_srv_job_common.c',
|
||||
'winsys/pvrsrvkm/pvr_srv_job_compute.c',
|
||||
'winsys/pvrsrvkm/pvr_srv_job_null.c',
|
||||
'winsys/pvrsrvkm/pvr_srv_job_render.c',
|
||||
'winsys/pvrsrvkm/pvr_srv_job_transfer.c',
|
||||
'winsys/pvrsrvkm/pvr_srv_syncobj.c',
|
||||
'winsys/pvrsrvkm/pvr_srv_sync.c',
|
||||
)
|
||||
pvr_flags += '-DPVR_SUPPORT_SERVICES_DRIVER'
|
||||
endif
|
||||
|
|
|
@ -356,6 +356,8 @@ static VkResult pvr_physical_device_init(struct pvr_physical_device *pdevice,
|
|||
goto err_vk_free_master_path;
|
||||
}
|
||||
|
||||
pdevice->vk.supported_sync_types = pdevice->ws->sync_types;
|
||||
|
||||
ret = pdevice->ws->ops->device_info_init(pdevice->ws,
|
||||
&pdevice->dev_info,
|
||||
&pdevice->dev_runtime_info);
|
||||
|
@ -1128,6 +1130,8 @@ VkResult pvr_CreateDevice(VkPhysicalDevice physicalDevice,
|
|||
else
|
||||
device->master_fd = -1;
|
||||
|
||||
vk_device_set_drm_fd(&device->vk, device->render_fd);
|
||||
|
||||
device->instance = instance;
|
||||
device->pdevice = pdevice;
|
||||
|
||||
|
|
|
@ -37,8 +37,8 @@
|
|||
static void pvr_compute_job_ws_submit_info_init(
|
||||
struct pvr_compute_ctx *ctx,
|
||||
struct pvr_sub_cmd *sub_cmd,
|
||||
const VkSemaphore *semaphores,
|
||||
uint32_t semaphore_count,
|
||||
struct vk_sync **waits,
|
||||
uint32_t wait_count,
|
||||
uint32_t *stage_flags,
|
||||
struct pvr_winsys_compute_submit_info *submit_info)
|
||||
{
|
||||
|
@ -48,8 +48,8 @@ static void pvr_compute_job_ws_submit_info_init(
|
|||
submit_info->frame_num = ctx->device->global_queue_present_count;
|
||||
submit_info->job_num = ctx->device->global_queue_job_count;
|
||||
|
||||
submit_info->semaphores = semaphores;
|
||||
submit_info->semaphore_count = semaphore_count;
|
||||
submit_info->waits = waits;
|
||||
submit_info->wait_count = wait_count;
|
||||
submit_info->stage_flags = stage_flags;
|
||||
|
||||
pvr_csb_pack (&submit_info->regs.cdm_ctx_state_base_addr,
|
||||
|
@ -87,21 +87,21 @@ static void pvr_compute_job_ws_submit_info_init(
|
|||
|
||||
VkResult pvr_compute_job_submit(struct pvr_compute_ctx *ctx,
|
||||
struct pvr_sub_cmd *sub_cmd,
|
||||
const VkSemaphore *semaphores,
|
||||
uint32_t semaphore_count,
|
||||
struct vk_sync **waits,
|
||||
uint32_t wait_count,
|
||||
uint32_t *stage_flags,
|
||||
struct pvr_winsys_syncobj **const syncobj_out)
|
||||
struct vk_sync *signal_sync)
|
||||
{
|
||||
struct pvr_device *device = ctx->device;
|
||||
|
||||
pvr_compute_job_ws_submit_info_init(ctx,
|
||||
sub_cmd,
|
||||
semaphores,
|
||||
semaphore_count,
|
||||
waits,
|
||||
wait_count,
|
||||
stage_flags,
|
||||
&sub_cmd->compute.submit_info);
|
||||
|
||||
return device->ws->ops->compute_submit(ctx->ws_ctx,
|
||||
&sub_cmd->compute.submit_info,
|
||||
syncobj_out);
|
||||
signal_sync);
|
||||
}
|
||||
|
|
|
@ -29,13 +29,13 @@
|
|||
|
||||
struct pvr_compute_ctx;
|
||||
struct pvr_sub_cmd;
|
||||
struct pvr_winsys_syncobj;
|
||||
struct vk_sync;
|
||||
|
||||
VkResult pvr_compute_job_submit(struct pvr_compute_ctx *ctx,
|
||||
struct pvr_sub_cmd *sub_cmd,
|
||||
const VkSemaphore *semaphores,
|
||||
uint32_t semaphore_count,
|
||||
struct vk_sync **waits,
|
||||
uint32_t wait_count,
|
||||
uint32_t *stage_flags,
|
||||
struct pvr_winsys_syncobj **const syncobj_out);
|
||||
struct vk_sync *signal_sync);
|
||||
|
||||
#endif /* PVR_JOB_COMPUTE_H */
|
||||
|
|
|
@ -1515,8 +1515,8 @@ static void pvr_render_job_ws_submit_info_init(
|
|||
struct pvr_render_job *job,
|
||||
const struct pvr_winsys_job_bo *bos,
|
||||
uint32_t bo_count,
|
||||
const VkSemaphore *semaphores,
|
||||
uint32_t semaphore_count,
|
||||
struct vk_sync **waits,
|
||||
uint32_t wait_count,
|
||||
uint32_t *stage_flags,
|
||||
struct pvr_winsys_render_submit_info *submit_info)
|
||||
{
|
||||
|
@ -1533,8 +1533,8 @@ static void pvr_render_job_ws_submit_info_init(
|
|||
submit_info->bos = bos;
|
||||
submit_info->bo_count = bo_count;
|
||||
|
||||
submit_info->semaphores = semaphores;
|
||||
submit_info->semaphore_count = semaphore_count;
|
||||
submit_info->waits = waits;
|
||||
submit_info->wait_count = wait_count;
|
||||
submit_info->stage_flags = stage_flags;
|
||||
|
||||
/* FIXME: add WSI image bos. */
|
||||
|
@ -1546,16 +1546,15 @@ static void pvr_render_job_ws_submit_info_init(
|
|||
assert(submit_info->geometry.regs.tpu == submit_info->fragment.regs.tpu);
|
||||
}
|
||||
|
||||
VkResult
|
||||
pvr_render_job_submit(struct pvr_render_ctx *ctx,
|
||||
struct pvr_render_job *job,
|
||||
const struct pvr_winsys_job_bo *bos,
|
||||
uint32_t bo_count,
|
||||
const VkSemaphore *semaphores,
|
||||
uint32_t semaphore_count,
|
||||
uint32_t *stage_flags,
|
||||
struct pvr_winsys_syncobj **const syncobj_geom_out,
|
||||
struct pvr_winsys_syncobj **const syncobj_frag_out)
|
||||
VkResult pvr_render_job_submit(struct pvr_render_ctx *ctx,
|
||||
struct pvr_render_job *job,
|
||||
const struct pvr_winsys_job_bo *bos,
|
||||
uint32_t bo_count,
|
||||
struct vk_sync **waits,
|
||||
uint32_t wait_count,
|
||||
uint32_t *stage_flags,
|
||||
struct vk_sync *signal_sync_geom,
|
||||
struct vk_sync *signal_sync_frag)
|
||||
{
|
||||
struct pvr_rt_dataset *rt_dataset = job->rt_dataset;
|
||||
struct pvr_winsys_render_submit_info submit_info;
|
||||
|
@ -1566,15 +1565,15 @@ pvr_render_job_submit(struct pvr_render_ctx *ctx,
|
|||
job,
|
||||
bos,
|
||||
bo_count,
|
||||
semaphores,
|
||||
semaphore_count,
|
||||
waits,
|
||||
wait_count,
|
||||
stage_flags,
|
||||
&submit_info);
|
||||
|
||||
result = device->ws->ops->render_submit(ctx->ws_ctx,
|
||||
&submit_info,
|
||||
syncobj_geom_out,
|
||||
syncobj_frag_out);
|
||||
signal_sync_geom,
|
||||
signal_sync_frag);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ struct pvr_device;
|
|||
struct pvr_free_list;
|
||||
struct pvr_render_ctx;
|
||||
struct pvr_rt_dataset;
|
||||
struct vk_sync;
|
||||
|
||||
/* FIXME: Turn 'struct pvr_sub_cmd' into 'struct pvr_job' and change 'struct
|
||||
* pvr_render_job' to subclass it? This is approximately what v3dv does
|
||||
|
@ -114,15 +115,14 @@ pvr_render_target_dataset_create(struct pvr_device *device,
|
|||
struct pvr_rt_dataset **const rt_dataset_out);
|
||||
void pvr_render_target_dataset_destroy(struct pvr_rt_dataset *dataset);
|
||||
|
||||
VkResult
|
||||
pvr_render_job_submit(struct pvr_render_ctx *ctx,
|
||||
struct pvr_render_job *job,
|
||||
const struct pvr_winsys_job_bo *bos,
|
||||
uint32_t bo_count,
|
||||
const VkSemaphore *semaphores,
|
||||
uint32_t semaphore_count,
|
||||
uint32_t *stage_flags,
|
||||
struct pvr_winsys_syncobj **const syncobj_geom_out,
|
||||
struct pvr_winsys_syncobj **const syncobj_frag_out);
|
||||
VkResult pvr_render_job_submit(struct pvr_render_ctx *ctx,
|
||||
struct pvr_render_job *job,
|
||||
const struct pvr_winsys_job_bo *bos,
|
||||
uint32_t bo_count,
|
||||
struct vk_sync **waits,
|
||||
uint32_t wait_count,
|
||||
uint32_t *stage_flags,
|
||||
struct vk_sync *signal_sync_geom,
|
||||
struct vk_sync *signal_sync_frag);
|
||||
|
||||
#endif /* PVR_JOB_RENDER_H */
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "vk_log.h"
|
||||
#include "vk_physical_device.h"
|
||||
#include "vk_queue.h"
|
||||
#include "vk_sync.h"
|
||||
#include "wsi_common.h"
|
||||
|
||||
#ifdef HAVE_VALGRIND
|
||||
|
@ -232,19 +233,7 @@ struct pvr_queue {
|
|||
struct pvr_compute_ctx *compute_ctx;
|
||||
struct pvr_transfer_ctx *transfer_ctx;
|
||||
|
||||
struct pvr_winsys_syncobj *completion[PVR_JOB_TYPE_MAX];
|
||||
};
|
||||
|
||||
struct pvr_semaphore {
|
||||
struct vk_object_base base;
|
||||
|
||||
struct pvr_winsys_syncobj *syncobj;
|
||||
};
|
||||
|
||||
struct pvr_fence {
|
||||
struct vk_object_base base;
|
||||
|
||||
struct pvr_winsys_syncobj *syncobj;
|
||||
struct vk_sync *completion[PVR_JOB_TYPE_MAX];
|
||||
};
|
||||
|
||||
struct pvr_vertex_binding {
|
||||
|
@ -1391,11 +1380,6 @@ VK_DEFINE_NONDISP_HANDLE_CASTS(pvr_sampler,
|
|||
base,
|
||||
VkSampler,
|
||||
VK_OBJECT_TYPE_SAMPLER)
|
||||
VK_DEFINE_NONDISP_HANDLE_CASTS(pvr_semaphore,
|
||||
base,
|
||||
VkSemaphore,
|
||||
VK_OBJECT_TYPE_SEMAPHORE)
|
||||
VK_DEFINE_NONDISP_HANDLE_CASTS(pvr_fence, base, VkFence, VK_OBJECT_TYPE_FENCE)
|
||||
VK_DEFINE_NONDISP_HANDLE_CASTS(pvr_pipeline_layout,
|
||||
base,
|
||||
VkPipelineLayout,
|
||||
|
|
|
@ -44,9 +44,13 @@
|
|||
#include "util/macros.h"
|
||||
#include "util/u_atomic.h"
|
||||
#include "vk_alloc.h"
|
||||
#include "vk_fence.h"
|
||||
#include "vk_log.h"
|
||||
#include "vk_object.h"
|
||||
#include "vk_queue.h"
|
||||
#include "vk_semaphore.h"
|
||||
#include "vk_sync.h"
|
||||
#include "vk_sync_dummy.h"
|
||||
#include "vk_util.h"
|
||||
|
||||
static VkResult pvr_queue_init(struct pvr_device *device,
|
||||
|
@ -144,7 +148,7 @@ static void pvr_queue_finish(struct pvr_queue *queue)
|
|||
{
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(queue->completion); i++) {
|
||||
if (queue->completion[i])
|
||||
queue->device->ws->ops->syncobj_destroy(queue->completion[i]);
|
||||
vk_sync_destroy(&queue->device->vk, queue->completion[i]);
|
||||
}
|
||||
|
||||
pvr_render_ctx_destroy(queue->gfx_ctx);
|
||||
|
@ -166,152 +170,26 @@ VkResult pvr_QueueWaitIdle(VkQueue _queue)
|
|||
{
|
||||
PVR_FROM_HANDLE(pvr_queue, queue, _queue);
|
||||
|
||||
return queue->device->ws->ops->syncobjs_wait(queue->device->ws,
|
||||
queue->completion,
|
||||
ARRAY_SIZE(queue->completion),
|
||||
true,
|
||||
UINT64_MAX);
|
||||
}
|
||||
for (int i = 0U; i < ARRAY_SIZE(queue->completion); i++) {
|
||||
VkResult result;
|
||||
|
||||
VkResult pvr_CreateFence(VkDevice _device,
|
||||
const VkFenceCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkFence *pFence)
|
||||
{
|
||||
PVR_FROM_HANDLE(pvr_device, device, _device);
|
||||
struct pvr_fence *fence;
|
||||
VkResult result;
|
||||
if (!queue->completion[i])
|
||||
continue;
|
||||
|
||||
fence = vk_object_alloc(&device->vk,
|
||||
pAllocator,
|
||||
sizeof(*fence),
|
||||
VK_OBJECT_TYPE_FENCE);
|
||||
if (!fence)
|
||||
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
/* We don't really need to create a syncobj here unless it's a signaled
|
||||
* fence.
|
||||
*/
|
||||
if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) {
|
||||
result =
|
||||
device->ws->ops->syncobj_create(device->ws, true, &fence->syncobj);
|
||||
if (result != VK_SUCCESS) {
|
||||
vk_object_free(&device->vk, pAllocator, fence);
|
||||
result = vk_sync_wait(&queue->device->vk,
|
||||
queue->completion[i],
|
||||
0U,
|
||||
VK_SYNC_WAIT_COMPLETE,
|
||||
UINT64_MAX);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
fence->syncobj = NULL;
|
||||
}
|
||||
|
||||
*pFence = pvr_fence_to_handle(fence);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void pvr_DestroyFence(VkDevice _device,
|
||||
VkFence _fence,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
PVR_FROM_HANDLE(pvr_device, device, _device);
|
||||
PVR_FROM_HANDLE(pvr_fence, fence, _fence);
|
||||
|
||||
if (!fence)
|
||||
return;
|
||||
|
||||
if (fence->syncobj)
|
||||
device->ws->ops->syncobj_destroy(fence->syncobj);
|
||||
|
||||
vk_object_free(&device->vk, pAllocator, fence);
|
||||
}
|
||||
|
||||
VkResult
|
||||
pvr_ResetFences(VkDevice _device, uint32_t fenceCount, const VkFence *pFences)
|
||||
{
|
||||
struct pvr_winsys_syncobj *syncobjs[fenceCount];
|
||||
PVR_FROM_HANDLE(pvr_device, device, _device);
|
||||
|
||||
for (uint32_t i = 0; i < fenceCount; i++) {
|
||||
PVR_FROM_HANDLE(pvr_fence, fence, pFences[i]);
|
||||
|
||||
syncobjs[i] = fence->syncobj;
|
||||
}
|
||||
|
||||
return device->ws->ops->syncobjs_reset(device->ws, syncobjs, fenceCount);
|
||||
}
|
||||
|
||||
VkResult pvr_GetFenceStatus(VkDevice _device, VkFence _fence)
|
||||
{
|
||||
PVR_FROM_HANDLE(pvr_device, device, _device);
|
||||
PVR_FROM_HANDLE(pvr_fence, fence, _fence);
|
||||
VkResult result;
|
||||
|
||||
result =
|
||||
device->ws->ops->syncobjs_wait(device->ws, &fence->syncobj, 1U, true, 0U);
|
||||
if (result == VK_TIMEOUT)
|
||||
return VK_NOT_READY;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VkResult pvr_WaitForFences(VkDevice _device,
|
||||
uint32_t fenceCount,
|
||||
const VkFence *pFences,
|
||||
VkBool32 waitAll,
|
||||
uint64_t timeout)
|
||||
{
|
||||
struct pvr_winsys_syncobj *syncobjs[fenceCount];
|
||||
PVR_FROM_HANDLE(pvr_device, device, _device);
|
||||
|
||||
for (uint32_t i = 0; i < fenceCount; i++) {
|
||||
PVR_FROM_HANDLE(pvr_fence, fence, pFences[i]);
|
||||
|
||||
syncobjs[i] = fence->syncobj;
|
||||
}
|
||||
|
||||
return device->ws->ops->syncobjs_wait(device->ws,
|
||||
syncobjs,
|
||||
fenceCount,
|
||||
!!waitAll,
|
||||
timeout);
|
||||
}
|
||||
|
||||
VkResult pvr_CreateSemaphore(VkDevice _device,
|
||||
const VkSemaphoreCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkSemaphore *pSemaphore)
|
||||
{
|
||||
PVR_FROM_HANDLE(pvr_device, device, _device);
|
||||
struct pvr_semaphore *semaphore;
|
||||
|
||||
semaphore = vk_object_alloc(&device->vk,
|
||||
pAllocator,
|
||||
sizeof(*semaphore),
|
||||
VK_OBJECT_TYPE_SEMAPHORE);
|
||||
if (!semaphore)
|
||||
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
semaphore->syncobj = NULL;
|
||||
|
||||
*pSemaphore = pvr_semaphore_to_handle(semaphore);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void pvr_DestroySemaphore(VkDevice _device,
|
||||
VkSemaphore _semaphore,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
PVR_FROM_HANDLE(pvr_device, device, _device);
|
||||
PVR_FROM_HANDLE(pvr_semaphore, semaphore, _semaphore);
|
||||
|
||||
if (semaphore->syncobj)
|
||||
device->ws->ops->syncobj_destroy(semaphore->syncobj);
|
||||
|
||||
vk_object_free(&device->vk, pAllocator, semaphore);
|
||||
}
|
||||
|
||||
static enum pvr_pipeline_stage_bits
|
||||
pvr_convert_stage_mask(VkPipelineStageFlags stage_mask)
|
||||
pvr_convert_stage_mask(VkPipelineStageFlags2KHR stage_mask)
|
||||
{
|
||||
enum pvr_pipeline_stage_bits stages = 0;
|
||||
|
||||
|
@ -350,19 +228,19 @@ pvr_convert_stage_mask(VkPipelineStageFlags stage_mask)
|
|||
return stages;
|
||||
}
|
||||
|
||||
static VkResult pvr_process_graphics_cmd(
|
||||
struct pvr_device *device,
|
||||
struct pvr_queue *queue,
|
||||
struct pvr_cmd_buffer *cmd_buffer,
|
||||
struct pvr_sub_cmd *sub_cmd,
|
||||
const VkSemaphore *semaphores,
|
||||
uint32_t semaphore_count,
|
||||
uint32_t *stage_flags,
|
||||
struct pvr_winsys_syncobj *completions[static PVR_JOB_TYPE_MAX])
|
||||
static VkResult
|
||||
pvr_process_graphics_cmd(struct pvr_device *device,
|
||||
struct pvr_queue *queue,
|
||||
struct pvr_cmd_buffer *cmd_buffer,
|
||||
struct pvr_sub_cmd *sub_cmd,
|
||||
struct vk_sync **waits,
|
||||
uint32_t wait_count,
|
||||
uint32_t *stage_flags,
|
||||
struct vk_sync *completions[static PVR_JOB_TYPE_MAX])
|
||||
{
|
||||
const struct pvr_framebuffer *framebuffer = sub_cmd->gfx.framebuffer;
|
||||
struct pvr_winsys_syncobj *syncobj_geom = NULL;
|
||||
struct pvr_winsys_syncobj *syncobj_frag = NULL;
|
||||
struct vk_sync *sync_geom;
|
||||
struct vk_sync *sync_frag;
|
||||
uint32_t bo_count = 0;
|
||||
VkResult result;
|
||||
|
||||
|
@ -370,6 +248,24 @@ static VkResult pvr_process_graphics_cmd(
|
|||
if (!bos)
|
||||
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
result = vk_sync_create(&device->vk,
|
||||
&device->pdevice->ws->syncobj_type,
|
||||
0U,
|
||||
0UL,
|
||||
&sync_geom);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
result = vk_sync_create(&device->vk,
|
||||
&device->pdevice->ws->syncobj_type,
|
||||
0U,
|
||||
0UL,
|
||||
&sync_frag);
|
||||
if (result != VK_SUCCESS) {
|
||||
vk_sync_destroy(&device->vk, sync_geom);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* FIXME: DoShadowLoadOrStore() */
|
||||
|
||||
/* FIXME: If the framebuffer being rendered to has multiple layers then we
|
||||
|
@ -393,95 +289,96 @@ static VkResult pvr_process_graphics_cmd(
|
|||
&sub_cmd->gfx.job,
|
||||
bos,
|
||||
bo_count,
|
||||
semaphores,
|
||||
semaphore_count,
|
||||
waits,
|
||||
wait_count,
|
||||
stage_flags,
|
||||
&syncobj_geom,
|
||||
&syncobj_frag);
|
||||
sync_geom,
|
||||
sync_frag);
|
||||
STACK_ARRAY_FINISH(bos);
|
||||
if (result != VK_SUCCESS)
|
||||
if (result != VK_SUCCESS) {
|
||||
vk_sync_destroy(&device->vk, sync_geom);
|
||||
vk_sync_destroy(&device->vk, sync_frag);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Replace the completion fences. */
|
||||
if (syncobj_geom) {
|
||||
if (completions[PVR_JOB_TYPE_GEOM])
|
||||
device->ws->ops->syncobj_destroy(completions[PVR_JOB_TYPE_GEOM]);
|
||||
if (completions[PVR_JOB_TYPE_GEOM])
|
||||
vk_sync_destroy(&device->vk, completions[PVR_JOB_TYPE_GEOM]);
|
||||
|
||||
completions[PVR_JOB_TYPE_GEOM] = syncobj_geom;
|
||||
}
|
||||
completions[PVR_JOB_TYPE_GEOM] = sync_geom;
|
||||
|
||||
if (syncobj_frag) {
|
||||
if (completions[PVR_JOB_TYPE_FRAG])
|
||||
device->ws->ops->syncobj_destroy(completions[PVR_JOB_TYPE_FRAG]);
|
||||
if (completions[PVR_JOB_TYPE_FRAG])
|
||||
vk_sync_destroy(&device->vk, completions[PVR_JOB_TYPE_FRAG]);
|
||||
|
||||
completions[PVR_JOB_TYPE_FRAG] = syncobj_frag;
|
||||
}
|
||||
completions[PVR_JOB_TYPE_FRAG] = sync_frag;
|
||||
|
||||
/* FIXME: DoShadowLoadOrStore() */
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static VkResult pvr_process_compute_cmd(
|
||||
struct pvr_device *device,
|
||||
struct pvr_queue *queue,
|
||||
struct pvr_sub_cmd *sub_cmd,
|
||||
const VkSemaphore *semaphores,
|
||||
uint32_t semaphore_count,
|
||||
uint32_t *stage_flags,
|
||||
struct pvr_winsys_syncobj *completions[static PVR_JOB_TYPE_MAX])
|
||||
static VkResult
|
||||
pvr_process_compute_cmd(struct pvr_device *device,
|
||||
struct pvr_queue *queue,
|
||||
struct pvr_sub_cmd *sub_cmd,
|
||||
struct vk_sync **waits,
|
||||
uint32_t wait_count,
|
||||
uint32_t *stage_flags,
|
||||
struct vk_sync *completions[static PVR_JOB_TYPE_MAX])
|
||||
{
|
||||
struct pvr_winsys_syncobj *syncobj = NULL;
|
||||
struct vk_sync *sync;
|
||||
VkResult result;
|
||||
|
||||
result = vk_sync_create(&device->vk,
|
||||
&device->pdevice->ws->syncobj_type,
|
||||
0U,
|
||||
0UL,
|
||||
&sync);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
/* This passes ownership of the wait fences to pvr_compute_job_submit(). */
|
||||
result = pvr_compute_job_submit(queue->compute_ctx,
|
||||
sub_cmd,
|
||||
semaphores,
|
||||
semaphore_count,
|
||||
waits,
|
||||
wait_count,
|
||||
stage_flags,
|
||||
&syncobj);
|
||||
if (result != VK_SUCCESS)
|
||||
sync);
|
||||
if (result != VK_SUCCESS) {
|
||||
vk_sync_destroy(&device->vk, sync);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Replace the completion fences. */
|
||||
if (syncobj) {
|
||||
if (completions[PVR_JOB_TYPE_COMPUTE])
|
||||
device->ws->ops->syncobj_destroy(completions[PVR_JOB_TYPE_COMPUTE]);
|
||||
if (completions[PVR_JOB_TYPE_COMPUTE])
|
||||
vk_sync_destroy(&device->vk, completions[PVR_JOB_TYPE_COMPUTE]);
|
||||
|
||||
completions[PVR_JOB_TYPE_COMPUTE] = syncobj;
|
||||
}
|
||||
completions[PVR_JOB_TYPE_COMPUTE] = sync;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* FIXME: Implement gpu based transfer support. */
|
||||
static VkResult pvr_process_transfer_cmds(
|
||||
struct pvr_device *device,
|
||||
struct pvr_sub_cmd *sub_cmd,
|
||||
const VkSemaphore *semaphores,
|
||||
uint32_t semaphore_count,
|
||||
uint32_t *stage_flags,
|
||||
struct pvr_winsys_syncobj *completions[static PVR_JOB_TYPE_MAX])
|
||||
static VkResult
|
||||
pvr_process_transfer_cmds(struct pvr_device *device,
|
||||
struct pvr_sub_cmd *sub_cmd,
|
||||
struct vk_sync **waits,
|
||||
uint32_t wait_count,
|
||||
uint32_t *stage_flags,
|
||||
struct vk_sync *completions[static PVR_JOB_TYPE_MAX])
|
||||
{
|
||||
/* Wait for transfer semaphores here before doing any transfers. */
|
||||
for (uint32_t i = 0; i < semaphore_count; i++) {
|
||||
PVR_FROM_HANDLE(pvr_semaphore, sem, semaphores[i]);
|
||||
|
||||
if (sem->syncobj && stage_flags[i] & PVR_PIPELINE_STAGE_TRANSFER_BIT) {
|
||||
VkResult result = device->ws->ops->syncobjs_wait(device->ws,
|
||||
&sem->syncobj,
|
||||
1,
|
||||
true,
|
||||
UINT64_MAX);
|
||||
for (uint32_t i = 0U; i < wait_count; i++) {
|
||||
if (stage_flags[i] & PVR_PIPELINE_STAGE_TRANSFER_BIT) {
|
||||
VkResult result = vk_sync_wait(&device->vk,
|
||||
waits[i],
|
||||
0U,
|
||||
VK_SYNC_WAIT_COMPLETE,
|
||||
UINT64_MAX);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
stage_flags[i] &= ~PVR_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
if (stage_flags[i] == 0) {
|
||||
device->ws->ops->syncobj_destroy(sem->syncobj);
|
||||
sem->syncobj = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -530,91 +427,116 @@ static VkResult pvr_process_transfer_cmds(
|
|||
device->ws->ops->buffer_unmap(transfer_cmd->dst->vma->bo);
|
||||
}
|
||||
|
||||
/* Given we are doing CPU based copy, completion fence should always be -1.
|
||||
* This should be fixed when GPU based copy is implemented.
|
||||
/* Given we are doing CPU based copy, completion fence should always be
|
||||
* signaled. This should be fixed when GPU based copy is implemented.
|
||||
*/
|
||||
assert(!completions[PVR_JOB_TYPE_TRANSFER]);
|
||||
|
||||
return VK_SUCCESS;
|
||||
return vk_sync_create(&device->vk,
|
||||
&device->pdevice->ws->syncobj_type,
|
||||
0U,
|
||||
1UL,
|
||||
&completions[PVR_JOB_TYPE_TRANSFER]);
|
||||
}
|
||||
|
||||
static VkResult pvr_set_semaphore_payloads(
|
||||
struct pvr_device *device,
|
||||
struct pvr_winsys_syncobj *completions[static PVR_JOB_TYPE_MAX],
|
||||
const VkSemaphore *semaphores,
|
||||
uint32_t semaphore_count)
|
||||
static VkResult
|
||||
pvr_set_semaphore_payloads(struct pvr_device *device,
|
||||
struct vk_sync *completions[static PVR_JOB_TYPE_MAX],
|
||||
const VkSemaphore *signals,
|
||||
uint32_t signal_count)
|
||||
{
|
||||
struct pvr_winsys_syncobj *syncobj = NULL;
|
||||
struct vk_sync *sync;
|
||||
VkResult result;
|
||||
int fd = -1;
|
||||
|
||||
if (!semaphore_count)
|
||||
return VK_SUCCESS;
|
||||
result = vk_sync_create(&device->vk,
|
||||
&device->pdevice->ws->syncobj_type,
|
||||
0U,
|
||||
0UL,
|
||||
&sync);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
for (uint32_t i = 0; i < PVR_JOB_TYPE_MAX; i++) {
|
||||
if (completions[i]) {
|
||||
result =
|
||||
device->ws->ops->syncobjs_merge(completions[i], syncobj, &syncobj);
|
||||
if (result != VK_SUCCESS)
|
||||
goto err_destroy_syncobj;
|
||||
}
|
||||
result = device->ws->ops->null_job_submit(device->ws,
|
||||
completions,
|
||||
PVR_JOB_TYPE_MAX,
|
||||
sync);
|
||||
if (result != VK_SUCCESS)
|
||||
goto end_set_semaphore_payloads;
|
||||
|
||||
/* If we have a single signal semaphore, we can simply move merged sync's
|
||||
* payload to the signal semahpore's payload.
|
||||
*/
|
||||
if (signal_count == 1U) {
|
||||
VK_FROM_HANDLE(vk_semaphore, sem, signals[0]);
|
||||
struct vk_sync *sem_sync = vk_semaphore_get_active_sync(sem);
|
||||
|
||||
result = vk_sync_move(&device->vk, sem_sync, sync);
|
||||
goto end_set_semaphore_payloads;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < semaphore_count; i++) {
|
||||
PVR_FROM_HANDLE(pvr_semaphore, semaphore, semaphores[i]);
|
||||
struct pvr_winsys_syncobj *dup_signal_fence;
|
||||
result = vk_sync_export_sync_file(&device->vk, sync, &fd);
|
||||
if (result != VK_SUCCESS)
|
||||
goto end_set_semaphore_payloads;
|
||||
|
||||
/* Duplicate signal_fence and store it in each signal semaphore. */
|
||||
result =
|
||||
device->ws->ops->syncobjs_merge(syncobj, NULL, &dup_signal_fence);
|
||||
for (uint32_t i = 0U; i < signal_count; i++) {
|
||||
VK_FROM_HANDLE(vk_semaphore, sem, signals[i]);
|
||||
struct vk_sync *sem_sync = vk_semaphore_get_active_sync(sem);
|
||||
|
||||
result = vk_sync_import_sync_file(&device->vk, sem_sync, fd);
|
||||
if (result != VK_SUCCESS)
|
||||
goto err_destroy_syncobj;
|
||||
|
||||
if (semaphore->syncobj)
|
||||
device->ws->ops->syncobj_destroy(semaphore->syncobj);
|
||||
semaphore->syncobj = dup_signal_fence;
|
||||
goto end_set_semaphore_payloads;
|
||||
}
|
||||
|
||||
err_destroy_syncobj:
|
||||
if (syncobj)
|
||||
device->ws->ops->syncobj_destroy(syncobj);
|
||||
end_set_semaphore_payloads:
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
|
||||
vk_sync_destroy(&device->vk, sync);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static VkResult pvr_set_fence_payload(
|
||||
struct pvr_device *device,
|
||||
struct pvr_winsys_syncobj *completions[static PVR_JOB_TYPE_MAX],
|
||||
VkFence _fence)
|
||||
static VkResult
|
||||
pvr_set_fence_payload(struct pvr_device *device,
|
||||
struct vk_sync *completions[static PVR_JOB_TYPE_MAX],
|
||||
VkFence _fence)
|
||||
{
|
||||
PVR_FROM_HANDLE(pvr_fence, fence, _fence);
|
||||
struct pvr_winsys_syncobj *syncobj = NULL;
|
||||
VK_FROM_HANDLE(vk_fence, fence, _fence);
|
||||
struct vk_sync *fence_sync;
|
||||
struct vk_sync *sync;
|
||||
VkResult result;
|
||||
|
||||
for (uint32_t i = 0; i < PVR_JOB_TYPE_MAX; i++) {
|
||||
if (completions[i]) {
|
||||
VkResult result =
|
||||
device->ws->ops->syncobjs_merge(completions[i], syncobj, &syncobj);
|
||||
if (result != VK_SUCCESS) {
|
||||
device->ws->ops->syncobj_destroy(syncobj);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
result = vk_sync_create(&device->vk,
|
||||
&device->pdevice->ws->syncobj_type,
|
||||
0U,
|
||||
0UL,
|
||||
&sync);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
result = device->ws->ops->null_job_submit(device->ws,
|
||||
completions,
|
||||
PVR_JOB_TYPE_MAX,
|
||||
sync);
|
||||
if (result != VK_SUCCESS) {
|
||||
vk_sync_destroy(&device->vk, sync);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (fence->syncobj)
|
||||
device->ws->ops->syncobj_destroy(fence->syncobj);
|
||||
fence->syncobj = syncobj;
|
||||
fence_sync = vk_fence_get_active_sync(fence);
|
||||
result = vk_sync_move(&device->vk, fence_sync, sync);
|
||||
vk_sync_destroy(&device->vk, sync);
|
||||
|
||||
return VK_SUCCESS;
|
||||
return result;
|
||||
}
|
||||
|
||||
static VkResult pvr_process_cmd_buffer(
|
||||
struct pvr_device *device,
|
||||
struct pvr_queue *queue,
|
||||
VkCommandBuffer commandBuffer,
|
||||
const VkSemaphore *semaphores,
|
||||
uint32_t semaphore_count,
|
||||
uint32_t *stage_flags,
|
||||
struct pvr_winsys_syncobj *completions[static PVR_JOB_TYPE_MAX])
|
||||
static VkResult
|
||||
pvr_process_cmd_buffer(struct pvr_device *device,
|
||||
struct pvr_queue *queue,
|
||||
VkCommandBuffer commandBuffer,
|
||||
struct vk_sync **waits,
|
||||
uint32_t wait_count,
|
||||
uint32_t *stage_flags,
|
||||
struct vk_sync *completions[static PVR_JOB_TYPE_MAX])
|
||||
{
|
||||
PVR_FROM_HANDLE(pvr_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
VkResult result;
|
||||
|
@ -631,8 +553,8 @@ static VkResult pvr_process_cmd_buffer(
|
|||
queue,
|
||||
cmd_buffer,
|
||||
sub_cmd,
|
||||
semaphores,
|
||||
semaphore_count,
|
||||
waits,
|
||||
wait_count,
|
||||
stage_flags,
|
||||
completions);
|
||||
break;
|
||||
|
@ -641,8 +563,8 @@ static VkResult pvr_process_cmd_buffer(
|
|||
result = pvr_process_compute_cmd(device,
|
||||
queue,
|
||||
sub_cmd,
|
||||
semaphores,
|
||||
semaphore_count,
|
||||
waits,
|
||||
wait_count,
|
||||
stage_flags,
|
||||
completions);
|
||||
break;
|
||||
|
@ -650,8 +572,8 @@ static VkResult pvr_process_cmd_buffer(
|
|||
case PVR_SUB_CMD_TYPE_TRANSFER:
|
||||
result = pvr_process_transfer_cmds(device,
|
||||
sub_cmd,
|
||||
semaphores,
|
||||
semaphore_count,
|
||||
waits,
|
||||
wait_count,
|
||||
stage_flags,
|
||||
completions);
|
||||
break;
|
||||
|
@ -672,48 +594,68 @@ static VkResult pvr_process_cmd_buffer(
|
|||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static VkResult pvr_process_empty_job(
|
||||
struct pvr_device *device,
|
||||
const VkSemaphore *semaphores,
|
||||
uint32_t semaphore_count,
|
||||
uint32_t *stage_flags,
|
||||
struct pvr_winsys_syncobj *completions[static PVR_JOB_TYPE_MAX])
|
||||
static VkResult
|
||||
pvr_submit_null_job(struct pvr_device *device,
|
||||
struct vk_sync **waits,
|
||||
uint32_t wait_count,
|
||||
uint32_t *stage_flags,
|
||||
struct vk_sync *completions[static PVR_JOB_TYPE_MAX])
|
||||
{
|
||||
VkResult result;
|
||||
|
||||
STATIC_ASSERT(PVR_JOB_TYPE_MAX >= PVR_NUM_SYNC_PIPELINE_STAGES);
|
||||
for (uint32_t i = 0U; i < PVR_JOB_TYPE_MAX; i++) {
|
||||
struct vk_sync *per_job_waits[wait_count];
|
||||
uint32_t per_job_waits_count = 0;
|
||||
|
||||
for (uint32_t i = 0; i < semaphore_count; i++) {
|
||||
PVR_FROM_HANDLE(pvr_semaphore, semaphore, semaphores[i]);
|
||||
|
||||
if (!semaphore->syncobj)
|
||||
continue;
|
||||
|
||||
for (uint32_t j = 0; j < PVR_NUM_SYNC_PIPELINE_STAGES; j++) {
|
||||
if (stage_flags[i] & (1U << j)) {
|
||||
VkResult result =
|
||||
device->ws->ops->syncobjs_merge(semaphore->syncobj,
|
||||
completions[j],
|
||||
&completions[j]);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
/* Get the waits specific to the job type. */
|
||||
for (uint32_t j = 0U; j < wait_count; j++) {
|
||||
if (stage_flags[j] & (1U << i)) {
|
||||
per_job_waits[per_job_waits_count] = waits[j];
|
||||
per_job_waits_count++;
|
||||
}
|
||||
}
|
||||
|
||||
device->ws->ops->syncobj_destroy(semaphore->syncobj);
|
||||
semaphore->syncobj = NULL;
|
||||
if (per_job_waits_count == 0U)
|
||||
continue;
|
||||
|
||||
result = vk_sync_create(&device->vk,
|
||||
&device->pdevice->ws->syncobj_type,
|
||||
0U,
|
||||
0UL,
|
||||
&completions[i]);
|
||||
if (result != VK_SUCCESS)
|
||||
goto err_destroy_completion_syncs;
|
||||
|
||||
result = device->ws->ops->null_job_submit(device->ws,
|
||||
per_job_waits,
|
||||
per_job_waits_count,
|
||||
completions[i]);
|
||||
if (result != VK_SUCCESS)
|
||||
goto err_destroy_completion_syncs;
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
err_destroy_completion_syncs:
|
||||
for (uint32_t i = 0U; i < PVR_JOB_TYPE_MAX; i++) {
|
||||
if (completions[i]) {
|
||||
vk_sync_destroy(&device->vk, completions[i]);
|
||||
completions[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
pvr_update_syncobjs(struct pvr_device *device,
|
||||
struct pvr_winsys_syncobj *src[static PVR_JOB_TYPE_MAX],
|
||||
struct pvr_winsys_syncobj *dst[static PVR_JOB_TYPE_MAX])
|
||||
static void pvr_update_syncobjs(struct pvr_device *device,
|
||||
struct vk_sync *src[static PVR_JOB_TYPE_MAX],
|
||||
struct vk_sync *dst[static PVR_JOB_TYPE_MAX])
|
||||
{
|
||||
for (uint32_t i = 0; i < PVR_JOB_TYPE_MAX; i++) {
|
||||
if (src[i]) {
|
||||
if (dst[i])
|
||||
device->ws->ops->syncobj_destroy(dst[i]);
|
||||
vk_sync_destroy(&device->vk, dst[i]);
|
||||
|
||||
dst[i] = src[i];
|
||||
}
|
||||
|
@ -726,37 +668,51 @@ VkResult pvr_QueueSubmit(VkQueue _queue,
|
|||
VkFence fence)
|
||||
{
|
||||
PVR_FROM_HANDLE(pvr_queue, queue, _queue);
|
||||
struct pvr_winsys_syncobj *completion_syncobjs[PVR_JOB_TYPE_MAX] = {};
|
||||
struct vk_sync *completion_syncobjs[PVR_JOB_TYPE_MAX] = {};
|
||||
struct pvr_device *device = queue->device;
|
||||
VkResult result;
|
||||
|
||||
for (uint32_t i = 0; i < submitCount; i++) {
|
||||
struct pvr_winsys_syncobj
|
||||
*per_submit_completion_syncobjs[PVR_JOB_TYPE_MAX] = {};
|
||||
for (uint32_t i = 0U; i < submitCount; i++) {
|
||||
struct vk_sync *per_submit_completion_syncobjs[PVR_JOB_TYPE_MAX] = {};
|
||||
const VkSubmitInfo *desc = &pSubmits[i];
|
||||
struct vk_sync *waits[desc->waitSemaphoreCount];
|
||||
uint32_t stage_flags[desc->waitSemaphoreCount];
|
||||
uint32_t wait_count = 0;
|
||||
|
||||
for (uint32_t j = 0; j < desc->waitSemaphoreCount; j++)
|
||||
stage_flags[j] = pvr_convert_stage_mask(desc->pWaitDstStageMask[j]);
|
||||
for (uint32_t j = 0U; j < desc->waitSemaphoreCount; j++) {
|
||||
VK_FROM_HANDLE(vk_semaphore, semaphore, desc->pWaitSemaphores[j]);
|
||||
struct vk_sync *sync = vk_semaphore_get_active_sync(semaphore);
|
||||
|
||||
if (sync->type == &vk_sync_dummy_type)
|
||||
continue;
|
||||
|
||||
/* We don't currently support timeline semaphores. */
|
||||
assert(!(sync->flags & VK_SYNC_IS_TIMELINE));
|
||||
|
||||
stage_flags[wait_count] =
|
||||
pvr_convert_stage_mask(desc->pWaitDstStageMask[j]);
|
||||
waits[wait_count] = vk_semaphore_get_active_sync(semaphore);
|
||||
wait_count++;
|
||||
}
|
||||
|
||||
if (desc->commandBufferCount > 0U) {
|
||||
for (uint32_t j = 0U; j < desc->commandBufferCount; j++) {
|
||||
result = pvr_process_cmd_buffer(device,
|
||||
queue,
|
||||
desc->pCommandBuffers[j],
|
||||
desc->pWaitSemaphores,
|
||||
desc->waitSemaphoreCount,
|
||||
waits,
|
||||
wait_count,
|
||||
stage_flags,
|
||||
per_submit_completion_syncobjs);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
result = pvr_process_empty_job(device,
|
||||
desc->pWaitSemaphores,
|
||||
desc->waitSemaphoreCount,
|
||||
stage_flags,
|
||||
per_submit_completion_syncobjs);
|
||||
result = pvr_submit_null_job(device,
|
||||
waits,
|
||||
wait_count,
|
||||
stage_flags,
|
||||
per_submit_completion_syncobjs);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -25,11 +25,16 @@
|
|||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "pvr_private.h"
|
||||
#include "pvr_winsys.h"
|
||||
#include "util/u_atomic.h"
|
||||
#include "vk_fence.h"
|
||||
#include "vk_object.h"
|
||||
#include "vk_semaphore.h"
|
||||
#include "vk_sync_dummy.h"
|
||||
#include "wsi_common.h"
|
||||
|
||||
static PFN_vkVoidFunction pvr_wsi_proc_addr(VkPhysicalDevice physicalDevice,
|
||||
|
@ -89,9 +94,9 @@ VkResult pvr_AcquireNextImage2KHR(VkDevice _device,
|
|||
const VkAcquireNextImageInfoKHR *pAcquireInfo,
|
||||
uint32_t *pImageIndex)
|
||||
{
|
||||
VK_FROM_HANDLE(vk_semaphore, sem, pAcquireInfo->semaphore);
|
||||
VK_FROM_HANDLE(vk_fence, fence, pAcquireInfo->fence);
|
||||
PVR_FROM_HANDLE(pvr_device, device, _device);
|
||||
struct pvr_winsys_syncobj *handles[2];
|
||||
uint32_t count = 0U;
|
||||
VkResult result;
|
||||
VkResult ret;
|
||||
|
||||
|
@ -102,23 +107,27 @@ VkResult pvr_AcquireNextImage2KHR(VkDevice _device,
|
|||
if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
|
||||
return result;
|
||||
|
||||
if (pAcquireInfo->fence) {
|
||||
PVR_FROM_HANDLE(pvr_fence, fence, pAcquireInfo->fence);
|
||||
handles[count++] = fence->syncobj;
|
||||
if (fence) {
|
||||
vk_fence_reset_temporary(&device->vk, fence);
|
||||
ret = vk_sync_create(&device->vk,
|
||||
&vk_sync_dummy_type,
|
||||
0U,
|
||||
0UL,
|
||||
&fence->temporary);
|
||||
if (ret != VK_SUCCESS)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pAcquireInfo->semaphore) {
|
||||
PVR_FROM_HANDLE(pvr_semaphore, semaphore, pAcquireInfo->semaphore);
|
||||
handles[count++] = semaphore->syncobj;
|
||||
if (sem) {
|
||||
vk_semaphore_reset_temporary(&device->vk, sem);
|
||||
ret = vk_sync_create(&device->vk,
|
||||
&vk_sync_dummy_type,
|
||||
0U,
|
||||
0UL,
|
||||
&sem->temporary);
|
||||
if (ret != VK_SUCCESS)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (count == 0U)
|
||||
return result;
|
||||
|
||||
/* We need to preserve VK_SUBOPTIMAL_KHR status. */
|
||||
ret = device->ws->ops->syncobjs_signal(device->ws, handles, count);
|
||||
if (ret != VK_SUCCESS)
|
||||
return ret;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "pvr_limits.h"
|
||||
#include "util/macros.h"
|
||||
#include "util/vma.h"
|
||||
#include "vk_sync.h"
|
||||
|
||||
struct pvr_device_info;
|
||||
struct pvr_device_runtime_info;
|
||||
|
@ -141,10 +142,6 @@ struct pvr_winsys_vma {
|
|||
uint64_t mapped_size;
|
||||
};
|
||||
|
||||
struct pvr_winsys_syncobj {
|
||||
struct pvr_winsys *ws;
|
||||
};
|
||||
|
||||
struct pvr_winsys_free_list {
|
||||
struct pvr_winsys *ws;
|
||||
};
|
||||
|
@ -262,10 +259,10 @@ struct pvr_winsys_compute_submit_info {
|
|||
uint32_t frame_num;
|
||||
uint32_t job_num;
|
||||
|
||||
/* semaphores and stage_flags are arrays of length semaphore_count. */
|
||||
const VkSemaphore *semaphores;
|
||||
/* waits and stage_flags are arrays of length wait_count. */
|
||||
struct vk_sync **waits;
|
||||
uint32_t wait_count;
|
||||
uint32_t *stage_flags;
|
||||
uint32_t semaphore_count;
|
||||
|
||||
struct {
|
||||
uint64_t tpu_border_colour_table;
|
||||
|
@ -311,10 +308,10 @@ struct pvr_winsys_render_submit_info {
|
|||
/* FIXME: should this be flags instead? */
|
||||
bool run_frag;
|
||||
|
||||
/* semaphores and stage_flags are arrays of length semaphore_count. */
|
||||
const VkSemaphore *semaphores;
|
||||
/* waits and stage_flags are arrays of length wait_count. */
|
||||
struct vk_sync **waits;
|
||||
uint32_t wait_count;
|
||||
uint32_t *stage_flags;
|
||||
uint32_t semaphore_count;
|
||||
|
||||
struct pvr_winsys_geometry_state {
|
||||
struct {
|
||||
|
@ -398,25 +395,6 @@ struct pvr_winsys_ops {
|
|||
uint64_t size);
|
||||
void (*vma_unmap)(struct pvr_winsys_vma *vma);
|
||||
|
||||
VkResult (*syncobj_create)(struct pvr_winsys *ws,
|
||||
bool signaled,
|
||||
struct pvr_winsys_syncobj **const syncobj_out);
|
||||
void (*syncobj_destroy)(struct pvr_winsys_syncobj *syncobj);
|
||||
VkResult (*syncobjs_reset)(struct pvr_winsys *ws,
|
||||
struct pvr_winsys_syncobj **const syncobjs,
|
||||
uint32_t count);
|
||||
VkResult (*syncobjs_signal)(struct pvr_winsys *ws,
|
||||
struct pvr_winsys_syncobj **const syncobjs,
|
||||
uint32_t count);
|
||||
VkResult (*syncobjs_wait)(struct pvr_winsys *ws,
|
||||
struct pvr_winsys_syncobj **const syncobjs,
|
||||
uint32_t count,
|
||||
bool wait_all,
|
||||
uint64_t timeout);
|
||||
VkResult (*syncobjs_merge)(struct pvr_winsys_syncobj *src,
|
||||
struct pvr_winsys_syncobj *target,
|
||||
struct pvr_winsys_syncobj **out);
|
||||
|
||||
VkResult (*free_list_create)(
|
||||
struct pvr_winsys *ws,
|
||||
struct pvr_winsys_vma *free_list_vma,
|
||||
|
@ -443,8 +421,8 @@ struct pvr_winsys_ops {
|
|||
VkResult (*render_submit)(
|
||||
const struct pvr_winsys_render_ctx *ctx,
|
||||
const struct pvr_winsys_render_submit_info *submit_info,
|
||||
struct pvr_winsys_syncobj **const syncobj_geom_out,
|
||||
struct pvr_winsys_syncobj **const syncobj_frag_out);
|
||||
struct vk_sync *signal_sync_geom,
|
||||
struct vk_sync *signal_sync_frag);
|
||||
|
||||
VkResult (*compute_ctx_create)(
|
||||
struct pvr_winsys *ws,
|
||||
|
@ -454,19 +432,27 @@ struct pvr_winsys_ops {
|
|||
VkResult (*compute_submit)(
|
||||
const struct pvr_winsys_compute_ctx *ctx,
|
||||
const struct pvr_winsys_compute_submit_info *submit_info,
|
||||
struct pvr_winsys_syncobj **const syncobj_out);
|
||||
struct vk_sync *signal_sync);
|
||||
|
||||
VkResult (*transfer_ctx_create)(
|
||||
struct pvr_winsys *ws,
|
||||
const struct pvr_winsys_transfer_ctx_create_info *create_info,
|
||||
struct pvr_winsys_transfer_ctx **const ctx_out);
|
||||
void (*transfer_ctx_destroy)(struct pvr_winsys_transfer_ctx *ctx);
|
||||
|
||||
VkResult (*null_job_submit)(struct pvr_winsys *ws,
|
||||
struct vk_sync **waits,
|
||||
uint32_t wait_count,
|
||||
struct vk_sync *signal_sync);
|
||||
};
|
||||
|
||||
struct pvr_winsys {
|
||||
uint64_t page_size;
|
||||
uint32_t log2_page_size;
|
||||
|
||||
const struct vk_sync_type *sync_types[2];
|
||||
struct vk_sync_type syncobj_type;
|
||||
|
||||
const struct pvr_winsys_ops *ops;
|
||||
};
|
||||
|
||||
|
|
|
@ -36,7 +36,8 @@
|
|||
#include "pvr_srv_job_render.h"
|
||||
#include "pvr_srv_job_transfer.h"
|
||||
#include "pvr_srv_public.h"
|
||||
#include "pvr_srv_syncobj.h"
|
||||
#include "pvr_srv_sync.h"
|
||||
#include "pvr_srv_job_null.h"
|
||||
#include "pvr_winsys.h"
|
||||
#include "pvr_winsys_helper.h"
|
||||
#include "util/log.h"
|
||||
|
@ -414,12 +415,6 @@ static const struct pvr_winsys_ops srv_winsys_ops = {
|
|||
.heap_free = pvr_srv_winsys_heap_free,
|
||||
.vma_map = pvr_srv_winsys_vma_map,
|
||||
.vma_unmap = pvr_srv_winsys_vma_unmap,
|
||||
.syncobj_create = pvr_srv_winsys_syncobj_create,
|
||||
.syncobj_destroy = pvr_srv_winsys_syncobj_destroy,
|
||||
.syncobjs_reset = pvr_srv_winsys_syncobjs_reset,
|
||||
.syncobjs_signal = pvr_srv_winsys_syncobjs_signal,
|
||||
.syncobjs_wait = pvr_srv_winsys_syncobjs_wait,
|
||||
.syncobjs_merge = pvr_srv_winsys_syncobjs_merge,
|
||||
.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,
|
||||
|
@ -432,6 +427,7 @@ static const struct pvr_winsys_ops srv_winsys_ops = {
|
|||
.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,
|
||||
.null_job_submit = pvr_srv_winsys_null_job_submit,
|
||||
};
|
||||
|
||||
static bool pvr_is_driver_compatible(int render_fd)
|
||||
|
@ -494,6 +490,10 @@ struct pvr_winsys *pvr_srv_winsys_create(int master_fd,
|
|||
srv_ws->render_fd = render_fd;
|
||||
srv_ws->alloc = alloc;
|
||||
|
||||
srv_ws->base.syncobj_type = pvr_srv_sync_type;
|
||||
srv_ws->base.sync_types[0] = &srv_ws->base.syncobj_type;
|
||||
srv_ws->base.sync_types[1] = NULL;
|
||||
|
||||
result = pvr_srv_memctx_init(srv_ws);
|
||||
if (result != VK_SUCCESS)
|
||||
goto err_vk_free_srv_ws;
|
||||
|
|
|
@ -33,10 +33,11 @@
|
|||
#include "pvr_private.h"
|
||||
#include "pvr_srv.h"
|
||||
#include "pvr_srv_bridge.h"
|
||||
#include "pvr_srv_job_compute.h"
|
||||
#include "pvr_srv_job_common.h"
|
||||
#include "pvr_srv_syncobj.h"
|
||||
#include "pvr_srv_job_compute.h"
|
||||
#include "pvr_srv_sync.h"
|
||||
#include "pvr_winsys.h"
|
||||
#include "util/libsync.h"
|
||||
#include "util/macros.h"
|
||||
#include "vk_alloc.h"
|
||||
#include "vk_log.h"
|
||||
|
@ -164,46 +165,37 @@ static void pvr_srv_compute_cmd_init(
|
|||
VkResult pvr_srv_winsys_compute_submit(
|
||||
const struct pvr_winsys_compute_ctx *ctx,
|
||||
const struct pvr_winsys_compute_submit_info *submit_info,
|
||||
struct pvr_winsys_syncobj **const syncobj_out)
|
||||
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 pvr_winsys_syncobj *signal_syncobj = NULL;
|
||||
struct pvr_winsys_syncobj *wait_syncobj = NULL;
|
||||
struct pvr_srv_winsys_syncobj *srv_syncobj;
|
||||
|
||||
struct rogue_fwif_cmd_compute compute_cmd;
|
||||
struct pvr_srv_sync *srv_signal_sync;
|
||||
VkResult result;
|
||||
int in_fd = -1;
|
||||
int fence;
|
||||
|
||||
pvr_srv_compute_cmd_init(submit_info, &compute_cmd);
|
||||
|
||||
for (uint32_t i = 0U; i < submit_info->semaphore_count; i++) {
|
||||
PVR_FROM_HANDLE(pvr_semaphore, sem, submit_info->semaphores[i]);
|
||||
for (uint32_t i = 0U; i < submit_info->wait_count; i++) {
|
||||
struct pvr_srv_sync *srv_wait_sync = to_srv_sync(submit_info->waits[i]);
|
||||
int ret;
|
||||
|
||||
if (!sem->syncobj)
|
||||
if (!submit_info->waits[i] || srv_wait_sync->fd < 0)
|
||||
continue;
|
||||
|
||||
if (submit_info->stage_flags[i] & PVR_PIPELINE_STAGE_COMPUTE_BIT) {
|
||||
result = pvr_srv_winsys_syncobjs_merge(sem->syncobj,
|
||||
wait_syncobj,
|
||||
&wait_syncobj);
|
||||
if (result != VK_SUCCESS)
|
||||
goto err_destroy_wait_syncobj;
|
||||
ret = sync_accumulate("", &in_fd, srv_wait_sync->fd);
|
||||
if (ret) {
|
||||
result = vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
goto err_close_in_fd;
|
||||
}
|
||||
|
||||
submit_info->stage_flags[i] &= ~PVR_PIPELINE_STAGE_COMPUTE_BIT;
|
||||
}
|
||||
|
||||
if (submit_info->stage_flags[i] == 0U) {
|
||||
pvr_srv_winsys_syncobj_destroy(sem->syncobj);
|
||||
sem->syncobj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
srv_syncobj = to_pvr_srv_winsys_syncobj(wait_syncobj);
|
||||
|
||||
do {
|
||||
result = pvr_srv_rgx_kick_compute2(srv_ws->render_fd,
|
||||
srv_ctx->handle,
|
||||
|
@ -211,7 +203,7 @@ VkResult pvr_srv_winsys_compute_submit(
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
wait_syncobj ? srv_syncobj->fd : -1,
|
||||
in_fd,
|
||||
srv_ctx->timeline,
|
||||
sizeof(compute_cmd),
|
||||
(uint8_t *)&compute_cmd,
|
||||
|
@ -228,27 +220,16 @@ VkResult pvr_srv_winsys_compute_submit(
|
|||
} while (result == VK_NOT_READY);
|
||||
|
||||
if (result != VK_SUCCESS)
|
||||
goto err_destroy_wait_syncobj;
|
||||
goto err_close_in_fd;
|
||||
|
||||
/* Given job submission succeeded, we don't need to close wait fence and it
|
||||
* should be consumed by the compute job itself.
|
||||
*/
|
||||
if (wait_syncobj)
|
||||
srv_syncobj->fd = -1;
|
||||
srv_signal_sync = to_srv_sync(signal_sync);
|
||||
pvr_srv_set_sync_payload(srv_signal_sync, fence);
|
||||
|
||||
if (fence != -1) {
|
||||
result = pvr_srv_winsys_syncobj_create(ctx->ws, false, &signal_syncobj);
|
||||
if (result != VK_SUCCESS)
|
||||
goto err_destroy_wait_syncobj;
|
||||
return VK_SUCCESS;
|
||||
|
||||
pvr_srv_set_syncobj_payload(signal_syncobj, fence);
|
||||
}
|
||||
|
||||
*syncobj_out = signal_syncobj;
|
||||
|
||||
err_destroy_wait_syncobj:
|
||||
if (wait_syncobj)
|
||||
pvr_srv_winsys_syncobj_destroy(wait_syncobj);
|
||||
err_close_in_fd:
|
||||
if (in_fd >= 0)
|
||||
close(in_fd);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ struct pvr_winsys;
|
|||
struct pvr_winsys_compute_ctx;
|
||||
struct pvr_winsys_compute_ctx_create_info;
|
||||
struct pvr_winsys_compute_submit_info;
|
||||
struct pvr_winsys_syncobj;
|
||||
struct vk_sync;
|
||||
|
||||
/*******************************************
|
||||
Function prototypes
|
||||
|
@ -45,6 +45,6 @@ void pvr_srv_winsys_compute_ctx_destroy(struct pvr_winsys_compute_ctx *ctx);
|
|||
VkResult pvr_srv_winsys_compute_submit(
|
||||
const struct pvr_winsys_compute_ctx *ctx,
|
||||
const struct pvr_winsys_compute_submit_info *submit_info,
|
||||
struct pvr_winsys_syncobj **const syncobj_out);
|
||||
struct vk_sync *signal_sync);
|
||||
|
||||
#endif /* PVR_SRV_JOB_COMPUTE_H */
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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 <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "pvr_srv_job_null.h"
|
||||
#include "pvr_srv_sync.h"
|
||||
#include "pvr_winsys.h"
|
||||
#include "util/libsync.h"
|
||||
#include "vk_log.h"
|
||||
#include "vk_sync.h"
|
||||
|
||||
VkResult pvr_srv_winsys_null_job_submit(struct pvr_winsys *ws,
|
||||
struct vk_sync **waits,
|
||||
uint32_t wait_count,
|
||||
struct vk_sync *signal_sync)
|
||||
{
|
||||
struct pvr_srv_sync *srv_signal_sync = to_srv_sync(signal_sync);
|
||||
int fd = -1;
|
||||
|
||||
assert(signal_sync);
|
||||
|
||||
for (uint32_t i = 0; i < wait_count; i++) {
|
||||
struct pvr_srv_sync *srv_wait_sync = to_srv_sync(waits[i]);
|
||||
int ret;
|
||||
|
||||
if (!waits[i] || srv_wait_sync->fd < 0)
|
||||
continue;
|
||||
|
||||
ret = sync_accumulate("", &fd, srv_wait_sync->fd);
|
||||
if (ret) {
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
|
||||
return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
pvr_srv_set_sync_payload(srv_signal_sync, fd);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef PVR_SRV_JOB_NULL_H
|
||||
#define PVR_SRV_JOB_NULL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
struct pvr_winsys;
|
||||
struct vk_sync;
|
||||
|
||||
VkResult pvr_srv_winsys_null_job_submit(struct pvr_winsys *ws,
|
||||
struct vk_sync **waits,
|
||||
uint32_t wait_count,
|
||||
struct vk_sync *signal_sync);
|
||||
|
||||
#endif /* PVR_SRV_JOB_NULL_H */
|
|
@ -39,8 +39,9 @@
|
|||
#include "pvr_srv_bridge.h"
|
||||
#include "pvr_srv_job_common.h"
|
||||
#include "pvr_srv_job_render.h"
|
||||
#include "pvr_srv_syncobj.h"
|
||||
#include "pvr_srv_sync.h"
|
||||
#include "pvr_winsys.h"
|
||||
#include "util/libsync.h"
|
||||
#include "util/log.h"
|
||||
#include "util/macros.h"
|
||||
#include "vk_alloc.h"
|
||||
|
@ -526,8 +527,8 @@ static void pvr_srv_fragment_cmd_init(
|
|||
VkResult pvr_srv_winsys_render_submit(
|
||||
const struct pvr_winsys_render_ctx *ctx,
|
||||
const struct pvr_winsys_render_submit_info *submit_info,
|
||||
struct pvr_winsys_syncobj **const syncobj_geom_out,
|
||||
struct pvr_winsys_syncobj **const syncobj_frag_out)
|
||||
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);
|
||||
|
@ -543,16 +544,14 @@ VkResult pvr_srv_winsys_render_submit(
|
|||
void *sync_pmrs[PVR_SRV_SYNC_MAX] = { NULL };
|
||||
uint32_t sync_pmr_count;
|
||||
|
||||
struct pvr_winsys_syncobj *geom_signal_syncobj = NULL;
|
||||
struct pvr_winsys_syncobj *frag_signal_syncobj = NULL;
|
||||
struct pvr_winsys_syncobj *geom_wait_syncobj = NULL;
|
||||
struct pvr_winsys_syncobj *frag_wait_syncobj = NULL;
|
||||
struct pvr_srv_winsys_syncobj *srv_geom_syncobj;
|
||||
struct pvr_srv_winsys_syncobj *srv_frag_syncobj;
|
||||
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;
|
||||
|
||||
int in_frag_fd = -1;
|
||||
int in_geom_fd = -1;
|
||||
int fence_frag;
|
||||
int fence_geom;
|
||||
|
||||
|
@ -561,41 +560,34 @@ VkResult pvr_srv_winsys_render_submit(
|
|||
pvr_srv_geometry_cmd_init(submit_info, sync_prim, &geom_cmd);
|
||||
pvr_srv_fragment_cmd_init(submit_info, &frag_cmd);
|
||||
|
||||
for (uint32_t i = 0U; i < submit_info->semaphore_count; i++) {
|
||||
PVR_FROM_HANDLE(pvr_semaphore, sem, submit_info->semaphores[i]);
|
||||
for (uint32_t i = 0U; i < submit_info->wait_count; i++) {
|
||||
struct pvr_srv_sync *srv_wait_sync = to_srv_sync(submit_info->waits[i]);
|
||||
int ret;
|
||||
|
||||
if (!sem->syncobj)
|
||||
if (!submit_info->waits[i] || srv_wait_sync->fd < 0)
|
||||
continue;
|
||||
|
||||
if (submit_info->stage_flags[i] & PVR_PIPELINE_STAGE_GEOM_BIT) {
|
||||
result = pvr_srv_winsys_syncobjs_merge(sem->syncobj,
|
||||
geom_wait_syncobj,
|
||||
&geom_wait_syncobj);
|
||||
if (result != VK_SUCCESS)
|
||||
goto err_destroy_wait_syncobjs;
|
||||
ret = sync_accumulate("", &in_geom_fd, srv_wait_sync->fd);
|
||||
if (ret) {
|
||||
result = vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
goto err_close_in_fds;
|
||||
}
|
||||
|
||||
submit_info->stage_flags[i] &= ~PVR_PIPELINE_STAGE_GEOM_BIT;
|
||||
}
|
||||
|
||||
if (submit_info->stage_flags[i] & PVR_PIPELINE_STAGE_FRAG_BIT) {
|
||||
result = pvr_srv_winsys_syncobjs_merge(sem->syncobj,
|
||||
frag_wait_syncobj,
|
||||
&frag_wait_syncobj);
|
||||
if (result != VK_SUCCESS)
|
||||
goto err_destroy_wait_syncobjs;
|
||||
ret = sync_accumulate("", &in_frag_fd, srv_wait_sync->fd);
|
||||
if (ret) {
|
||||
result = vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
goto err_close_in_fds;
|
||||
}
|
||||
|
||||
submit_info->stage_flags[i] &= ~PVR_PIPELINE_STAGE_FRAG_BIT;
|
||||
}
|
||||
|
||||
if (submit_info->stage_flags[i] == 0U) {
|
||||
pvr_srv_winsys_syncobj_destroy(sem->syncobj);
|
||||
sem->syncobj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
srv_geom_syncobj = to_pvr_srv_winsys_syncobj(geom_wait_syncobj);
|
||||
srv_frag_syncobj = to_pvr_srv_winsys_syncobj(frag_wait_syncobj);
|
||||
|
||||
if (submit_info->bo_count <= ARRAY_SIZE(sync_pmrs)) {
|
||||
sync_pmr_count = submit_info->bo_count;
|
||||
} else {
|
||||
|
@ -629,105 +621,76 @@ VkResult pvr_srv_winsys_render_submit(
|
|||
sync_prim->value++;
|
||||
|
||||
do {
|
||||
result =
|
||||
pvr_srv_rgx_kick_render2(srv_ws->render_fd,
|
||||
srv_ctx->handle,
|
||||
/* Currently no support for cache operations.
|
||||
*/
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
1,
|
||||
&sync_prim->srv_ws->sync_block_handle,
|
||||
&sync_prim->offset,
|
||||
&sync_prim->value,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
sync_prim->srv_ws->sync_block_handle,
|
||||
sync_prim->offset,
|
||||
sync_prim->value,
|
||||
geom_wait_syncobj ? srv_geom_syncobj->fd : -1,
|
||||
srv_ctx->timeline_geom,
|
||||
&fence_geom,
|
||||
"GEOM",
|
||||
frag_wait_syncobj ? srv_frag_syncobj->fd : -1,
|
||||
srv_ctx->timeline_frag,
|
||||
&fence_frag,
|
||||
"FRAG",
|
||||
sizeof(geom_cmd),
|
||||
(uint8_t *)&geom_cmd,
|
||||
/* Currently no support for PRs. */
|
||||
0,
|
||||
/* Currently no support for PRs. */
|
||||
NULL,
|
||||
sizeof(frag_cmd),
|
||||
(uint8_t *)&frag_cmd,
|
||||
submit_info->job_num,
|
||||
true, /* Always kick the TA. */
|
||||
true, /* Always kick a PR. */
|
||||
submit_info->run_frag,
|
||||
false,
|
||||
0,
|
||||
rt_data_handle,
|
||||
/* Currently no support for PRs. */
|
||||
NULL,
|
||||
/* Currently no support for PRs. */
|
||||
NULL,
|
||||
sync_pmr_count,
|
||||
sync_pmr_count ? sync_pmr_flags : NULL,
|
||||
sync_pmr_count ? sync_pmrs : NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
result = pvr_srv_rgx_kick_render2(srv_ws->render_fd,
|
||||
srv_ctx->handle,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
1,
|
||||
&sync_prim->srv_ws->sync_block_handle,
|
||||
&sync_prim->offset,
|
||||
&sync_prim->value,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
sync_prim->srv_ws->sync_block_handle,
|
||||
sync_prim->offset,
|
||||
sync_prim->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,
|
||||
/* Currently no support for PRs. */
|
||||
0,
|
||||
/* Currently no support for PRs. */
|
||||
NULL,
|
||||
sizeof(frag_cmd),
|
||||
(uint8_t *)&frag_cmd,
|
||||
submit_info->job_num,
|
||||
true, /* Always kick the TA. */
|
||||
true, /* Always kick a PR. */
|
||||
submit_info->run_frag,
|
||||
false,
|
||||
0,
|
||||
rt_data_handle,
|
||||
/* Currently no support for PRs. */
|
||||
NULL,
|
||||
/* Currently no support for PRs. */
|
||||
NULL,
|
||||
sync_pmr_count,
|
||||
sync_pmr_count ? sync_pmr_flags : NULL,
|
||||
sync_pmr_count ? sync_pmrs : NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
} while (result == VK_NOT_READY);
|
||||
|
||||
if (result != VK_SUCCESS)
|
||||
goto err_destroy_wait_syncobjs;
|
||||
goto err_close_in_fds;
|
||||
|
||||
/* Given job submission succeeded, we don't need to close wait fences, these
|
||||
* should be consumed by the render job itself.
|
||||
*/
|
||||
if (geom_wait_syncobj)
|
||||
srv_geom_syncobj->fd = -1;
|
||||
srv_signal_sync_geom = to_srv_sync(signal_sync_geom);
|
||||
srv_signal_sync_frag = to_srv_sync(signal_sync_frag);
|
||||
pvr_srv_set_sync_payload(srv_signal_sync_geom, fence_geom);
|
||||
pvr_srv_set_sync_payload(srv_signal_sync_frag, fence_frag);
|
||||
|
||||
if (frag_wait_syncobj)
|
||||
srv_frag_syncobj->fd = -1;
|
||||
return VK_SUCCESS;
|
||||
|
||||
if (fence_geom != -1) {
|
||||
result =
|
||||
pvr_srv_winsys_syncobj_create(ctx->ws, false, &geom_signal_syncobj);
|
||||
if (result != VK_SUCCESS)
|
||||
goto err_destroy_wait_syncobjs;
|
||||
err_close_in_fds:
|
||||
if (in_geom_fd >= 0)
|
||||
close(in_geom_fd);
|
||||
|
||||
pvr_srv_set_syncobj_payload(geom_signal_syncobj, fence_geom);
|
||||
}
|
||||
|
||||
if (fence_frag != -1) {
|
||||
result =
|
||||
pvr_srv_winsys_syncobj_create(ctx->ws, false, &frag_signal_syncobj);
|
||||
if (result != VK_SUCCESS) {
|
||||
if (geom_signal_syncobj)
|
||||
pvr_srv_winsys_syncobj_destroy(geom_signal_syncobj);
|
||||
goto err_destroy_wait_syncobjs;
|
||||
}
|
||||
|
||||
pvr_srv_set_syncobj_payload(frag_signal_syncobj, fence_frag);
|
||||
}
|
||||
|
||||
*syncobj_geom_out = geom_signal_syncobj;
|
||||
*syncobj_frag_out = frag_signal_syncobj;
|
||||
|
||||
err_destroy_wait_syncobjs:
|
||||
if (geom_wait_syncobj)
|
||||
pvr_srv_winsys_syncobj_destroy(geom_wait_syncobj);
|
||||
|
||||
if (frag_wait_syncobj)
|
||||
pvr_srv_winsys_syncobj_destroy(frag_wait_syncobj);
|
||||
if (in_frag_fd >= 0)
|
||||
close(in_frag_fd);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -34,8 +34,8 @@ struct pvr_winsys_render_ctx_create_info;
|
|||
struct pvr_winsys_render_submit_info;
|
||||
struct pvr_winsys_rt_dataset;
|
||||
struct pvr_winsys_rt_dataset_create_info;
|
||||
struct pvr_winsys_syncobj;
|
||||
struct pvr_winsys_vma;
|
||||
struct vk_sync;
|
||||
|
||||
/*******************************************
|
||||
Function prototypes
|
||||
|
@ -68,7 +68,7 @@ void pvr_srv_winsys_render_ctx_destroy(struct pvr_winsys_render_ctx *ctx);
|
|||
VkResult pvr_srv_winsys_render_submit(
|
||||
const struct pvr_winsys_render_ctx *ctx,
|
||||
const struct pvr_winsys_render_submit_info *submit_info,
|
||||
struct pvr_winsys_syncobj **const syncobj_geom_out,
|
||||
struct pvr_winsys_syncobj **const syncobj_frag_out);
|
||||
struct vk_sync *signal_sync_geom,
|
||||
struct vk_sync *signal_sync_frag);
|
||||
|
||||
#endif /* PVR_SRV_JOB_RENDER_H */
|
||||
|
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* 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 <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "pvr_private.h"
|
||||
#include "pvr_srv.h"
|
||||
#include "pvr_srv_sync.h"
|
||||
#include "util/libsync.h"
|
||||
#include "util/macros.h"
|
||||
#include "util/timespec.h"
|
||||
#include "vk_alloc.h"
|
||||
#include "vk_log.h"
|
||||
#include "vk_sync.h"
|
||||
#include "vk_util.h"
|
||||
|
||||
static VkResult pvr_srv_sync_init(struct vk_device *device,
|
||||
struct vk_sync *sync,
|
||||
uint64_t initial_value)
|
||||
{
|
||||
struct pvr_srv_sync *srv_sync = to_srv_sync(sync);
|
||||
|
||||
srv_sync->signaled = initial_value ? true : false;
|
||||
srv_sync->fd = -1;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void pvr_srv_sync_finish(struct vk_device *device, struct vk_sync *sync)
|
||||
{
|
||||
struct pvr_srv_sync *srv_sync = to_srv_sync(sync);
|
||||
|
||||
if (srv_sync->fd != -1)
|
||||
close(srv_sync->fd);
|
||||
}
|
||||
|
||||
/* Note: function closes the fd. */
|
||||
static void pvr_set_sync_state(struct pvr_srv_sync *srv_sync, bool signaled)
|
||||
{
|
||||
if (srv_sync->fd != -1) {
|
||||
close(srv_sync->fd);
|
||||
srv_sync->fd = -1;
|
||||
}
|
||||
|
||||
srv_sync->signaled = signaled;
|
||||
}
|
||||
|
||||
void pvr_srv_set_sync_payload(struct pvr_srv_sync *srv_sync, int payload)
|
||||
{
|
||||
if (srv_sync->fd != -1)
|
||||
close(srv_sync->fd);
|
||||
|
||||
srv_sync->fd = payload;
|
||||
srv_sync->signaled = (payload == -1);
|
||||
}
|
||||
|
||||
static VkResult pvr_srv_sync_signal(struct vk_device *device,
|
||||
struct vk_sync *sync,
|
||||
UNUSED uint64_t value)
|
||||
{
|
||||
struct pvr_srv_sync *srv_sync = to_srv_sync(sync);
|
||||
|
||||
pvr_set_sync_state(srv_sync, true);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static VkResult pvr_srv_sync_reset(struct vk_device *device,
|
||||
struct vk_sync *sync)
|
||||
{
|
||||
struct pvr_srv_sync *srv_sync = to_srv_sync(sync);
|
||||
|
||||
pvr_set_sync_state(srv_sync, false);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
/* Careful, timeout might overflow. */
|
||||
static inline void pvr_start_timeout(struct timespec *timeout,
|
||||
uint64_t timeout_ns)
|
||||
{
|
||||
clock_gettime(CLOCK_MONOTONIC, timeout);
|
||||
timespec_add_nsec(timeout, timeout, timeout_ns);
|
||||
}
|
||||
|
||||
/* Careful, a negative value might be returned. */
|
||||
static inline struct timespec
|
||||
pvr_get_remaining_time(const struct timespec *timeout)
|
||||
{
|
||||
struct timespec time;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &time);
|
||||
timespec_sub(&time, timeout, &time);
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
/* abs_timeout_ns == 0 -> Get status without waiting.
|
||||
* abs_timeout_ns == ~0 -> Wait infinitely.
|
||||
* else wait for the given abs_timeout_ns in nanoseconds. */
|
||||
static VkResult pvr_srv_sync_wait_many(struct vk_device *device,
|
||||
uint32_t wait_count,
|
||||
const struct vk_sync_wait *waits,
|
||||
enum vk_sync_wait_flags wait_flags,
|
||||
uint64_t abs_timeout_ns)
|
||||
{
|
||||
uint32_t unsignaled_count = 0U;
|
||||
struct timespec end_time;
|
||||
VkResult result;
|
||||
int ppoll_ret;
|
||||
|
||||
STACK_ARRAY(struct pollfd, poll_fds, wait_count);
|
||||
if (!poll_fds)
|
||||
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
if (abs_timeout_ns != 0U && abs_timeout_ns != ~0U) {
|
||||
/* Syncobj timeouts are signed. */
|
||||
abs_timeout_ns = MIN2(abs_timeout_ns, (uint64_t)INT64_MAX);
|
||||
pvr_start_timeout(&end_time, abs_timeout_ns);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0U; i < wait_count; i++) {
|
||||
struct pvr_srv_sync *srv_sync = to_srv_sync(waits[i].sync);
|
||||
|
||||
/* -1 in case if fence is signaled or uninitialized, ppoll will skip the
|
||||
* fence.
|
||||
*/
|
||||
/* FIXME: We don't currently support wait-for-fd path, so the caller
|
||||
* should make sure all the sync have been assigned before calling this
|
||||
* function.
|
||||
*/
|
||||
if (srv_sync->signaled || srv_sync->fd == -1) {
|
||||
poll_fds[i].fd = -1;
|
||||
} else {
|
||||
poll_fds[i].fd = srv_sync->fd;
|
||||
unsignaled_count++;
|
||||
}
|
||||
|
||||
poll_fds[i].events = POLLIN;
|
||||
poll_fds[i].revents = 0U;
|
||||
}
|
||||
|
||||
if (unsignaled_count == 0U) {
|
||||
result = VK_SUCCESS;
|
||||
goto end_wait_for_fences;
|
||||
}
|
||||
|
||||
/* FIXME: Fix device loss handling. */
|
||||
do {
|
||||
if (abs_timeout_ns == ~0U) {
|
||||
ppoll_ret = ppoll(poll_fds, wait_count, NULL, NULL);
|
||||
} else {
|
||||
struct timespec remaining_time;
|
||||
|
||||
if (abs_timeout_ns == 0U) {
|
||||
remaining_time = (struct timespec){ 0UL, 0UL };
|
||||
} else {
|
||||
/* ppoll() returns EINVAL on negative timeout. Nothing to worry.
|
||||
*/
|
||||
remaining_time = pvr_get_remaining_time(&end_time);
|
||||
}
|
||||
|
||||
ppoll_ret = ppoll(poll_fds, wait_count, &remaining_time, NULL);
|
||||
}
|
||||
|
||||
if (ppoll_ret > 0U) {
|
||||
/* ppoll_ret contains the amount of structs updated by poll(). */
|
||||
unsignaled_count -= ppoll_ret;
|
||||
|
||||
/* ppoll_ret > 0 is for early loop termination. */
|
||||
for (uint32_t i = 0; ppoll_ret > 0 && i < wait_count; i++) {
|
||||
if (poll_fds[i].revents == 0)
|
||||
continue;
|
||||
|
||||
if (poll_fds[i].revents & (POLLNVAL | POLLERR)) {
|
||||
result = vk_error(NULL, VK_ERROR_DEVICE_LOST);
|
||||
goto end_wait_for_fences;
|
||||
}
|
||||
|
||||
pvr_srv_sync_signal(device, waits[i].sync, 0U);
|
||||
|
||||
if (wait_flags & VK_SYNC_WAIT_ANY) {
|
||||
result = VK_SUCCESS;
|
||||
goto end_wait_for_fences;
|
||||
}
|
||||
|
||||
/* -1 makes ppoll ignore it and set revents to 0. */
|
||||
poll_fds[i].fd = -1;
|
||||
ppoll_ret--;
|
||||
}
|
||||
|
||||
/* For zero timeout, just return even if we still have unsignaled
|
||||
* syncs.
|
||||
*/
|
||||
if (abs_timeout_ns == 0U && unsignaled_count != 0U) {
|
||||
result = VK_TIMEOUT;
|
||||
goto end_wait_for_fences;
|
||||
}
|
||||
} else if (ppoll_ret == 0) {
|
||||
result = VK_TIMEOUT;
|
||||
goto end_wait_for_fences;
|
||||
}
|
||||
|
||||
/* Careful as we might have decremented ppoll_ret to 0. */
|
||||
} while ((ppoll_ret != -1 && unsignaled_count != 0) ||
|
||||
(ppoll_ret == -1 && (errno == EINTR || errno == EAGAIN)));
|
||||
|
||||
/* We assume device loss in case of an unknown error or invalid fd. */
|
||||
if (ppoll_ret != -1)
|
||||
result = VK_SUCCESS;
|
||||
else if (errno == EINVAL)
|
||||
result = VK_TIMEOUT;
|
||||
else if (errno == ENOMEM)
|
||||
result = vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
else
|
||||
result = vk_error(NULL, VK_ERROR_DEVICE_LOST);
|
||||
|
||||
end_wait_for_fences:
|
||||
STACK_ARRAY_FINISH(poll_fds);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static VkResult pvr_srv_sync_move(struct vk_device *device,
|
||||
struct vk_sync *dst,
|
||||
struct vk_sync *src)
|
||||
{
|
||||
struct pvr_srv_sync *srv_dst_sync = to_srv_sync(dst);
|
||||
struct pvr_srv_sync *srv_src_sync = to_srv_sync(src);
|
||||
|
||||
if (!(dst->flags & VK_SYNC_IS_SHARED) && !(src->flags & VK_SYNC_IS_SHARED)) {
|
||||
pvr_srv_set_sync_payload(srv_dst_sync, srv_src_sync->fd);
|
||||
srv_src_sync->fd = -1;
|
||||
pvr_srv_sync_reset(device, src);
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
unreachable("srv_sync doesn't support move for shared sync objects.");
|
||||
return VK_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
static VkResult pvr_srv_sync_import_sync_file(struct vk_device *device,
|
||||
struct vk_sync *sync,
|
||||
int sync_file)
|
||||
{
|
||||
struct pvr_srv_sync *srv_sync = to_srv_sync(sync);
|
||||
int fd = -1;
|
||||
|
||||
if (sync_file >= 0) {
|
||||
fd = dup(sync_file);
|
||||
if (fd < 0)
|
||||
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
}
|
||||
|
||||
pvr_srv_set_sync_payload(srv_sync, fd);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static VkResult pvr_srv_sync_export_sync_file(struct vk_device *device,
|
||||
struct vk_sync *sync,
|
||||
int *sync_file)
|
||||
{
|
||||
struct pvr_srv_sync *srv_sync = to_srv_sync(sync);
|
||||
int fd;
|
||||
|
||||
if (srv_sync->fd < 0) {
|
||||
*sync_file = -1;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
fd = dup(srv_sync->fd);
|
||||
if (fd < 0)
|
||||
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
*sync_file = fd;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
const struct vk_sync_type pvr_srv_sync_type = {
|
||||
.size = sizeof(struct pvr_srv_sync),
|
||||
/* clang-format off */
|
||||
.features = VK_SYNC_FEATURE_BINARY |
|
||||
VK_SYNC_FEATURE_GPU_WAIT |
|
||||
VK_SYNC_FEATURE_GPU_MULTI_WAIT |
|
||||
VK_SYNC_FEATURE_CPU_WAIT |
|
||||
VK_SYNC_FEATURE_CPU_RESET |
|
||||
VK_SYNC_FEATURE_CPU_SIGNAL |
|
||||
VK_SYNC_FEATURE_WAIT_ANY,
|
||||
/* clang-format on */
|
||||
.init = pvr_srv_sync_init,
|
||||
.finish = pvr_srv_sync_finish,
|
||||
.signal = pvr_srv_sync_signal,
|
||||
.reset = pvr_srv_sync_reset,
|
||||
.wait_many = pvr_srv_sync_wait_many,
|
||||
.move = pvr_srv_sync_move,
|
||||
.import_sync_file = pvr_srv_sync_import_sync_file,
|
||||
.export_sync_file = pvr_srv_sync_export_sync_file,
|
||||
};
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef PVR_SRV_SYNC_H
|
||||
#define PVR_SRV_SYNC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "pvr_winsys.h"
|
||||
#include "util/macros.h"
|
||||
#include "vk_sync.h"
|
||||
|
||||
struct vk_device;
|
||||
|
||||
struct pvr_srv_sync {
|
||||
struct vk_sync base;
|
||||
|
||||
/* Cached version of completion. */
|
||||
bool signaled;
|
||||
|
||||
int fd;
|
||||
};
|
||||
|
||||
extern const struct vk_sync_type pvr_srv_sync_type;
|
||||
|
||||
void pvr_srv_sync_finish(struct vk_device *device, struct vk_sync *sync);
|
||||
void pvr_srv_set_sync_payload(struct pvr_srv_sync *srv_sync, int payload);
|
||||
|
||||
static inline bool pvr_sync_type_is_srv_sync(const struct vk_sync_type *type)
|
||||
{
|
||||
return type->finish == pvr_srv_sync_finish;
|
||||
}
|
||||
|
||||
static inline struct pvr_srv_sync *to_srv_sync(struct vk_sync *sync)
|
||||
{
|
||||
assert(!sync || pvr_sync_type_is_srv_sync(sync->type));
|
||||
return container_of(sync, struct pvr_srv_sync, base);
|
||||
}
|
||||
|
||||
#endif /* PVR_SRV_SYNC_H */
|
|
@ -1,349 +0,0 @@
|
|||
/*
|
||||
* 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 <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "pvr_private.h"
|
||||
#include "pvr_srv.h"
|
||||
#include "pvr_srv_syncobj.h"
|
||||
#include "pvr_winsys.h"
|
||||
#include "util/libsync.h"
|
||||
#include "util/macros.h"
|
||||
#include "util/timespec.h"
|
||||
#include "vk_alloc.h"
|
||||
#include "vk_log.h"
|
||||
|
||||
VkResult
|
||||
pvr_srv_winsys_syncobj_create(struct pvr_winsys *ws,
|
||||
bool signaled,
|
||||
struct pvr_winsys_syncobj **const syncobj_out)
|
||||
{
|
||||
struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ws);
|
||||
struct pvr_srv_winsys_syncobj *srv_syncobj;
|
||||
|
||||
srv_syncobj = vk_alloc(srv_ws->alloc,
|
||||
sizeof(*srv_syncobj),
|
||||
8,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
|
||||
if (!srv_syncobj)
|
||||
return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
srv_syncobj->base.ws = ws;
|
||||
srv_syncobj->signaled = signaled;
|
||||
srv_syncobj->fd = -1;
|
||||
|
||||
*syncobj_out = &srv_syncobj->base;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void pvr_srv_winsys_syncobj_destroy(struct pvr_winsys_syncobj *syncobj)
|
||||
{
|
||||
struct pvr_srv_winsys_syncobj *srv_syncobj;
|
||||
struct pvr_srv_winsys *srv_ws;
|
||||
|
||||
assert(syncobj);
|
||||
|
||||
srv_ws = to_pvr_srv_winsys(syncobj->ws);
|
||||
srv_syncobj = to_pvr_srv_winsys_syncobj(syncobj);
|
||||
|
||||
if (srv_syncobj->fd != -1)
|
||||
close(srv_syncobj->fd);
|
||||
|
||||
vk_free(srv_ws->alloc, srv_syncobj);
|
||||
}
|
||||
|
||||
/* Note: function closes the fd. */
|
||||
static void pvr_set_syncobj_state(struct pvr_srv_winsys_syncobj *srv_syncobj,
|
||||
bool signaled)
|
||||
{
|
||||
if (srv_syncobj->fd != -1) {
|
||||
close(srv_syncobj->fd);
|
||||
srv_syncobj->fd = -1;
|
||||
}
|
||||
|
||||
srv_syncobj->signaled = signaled;
|
||||
}
|
||||
|
||||
void pvr_srv_set_syncobj_payload(struct pvr_winsys_syncobj *syncobj,
|
||||
int payload)
|
||||
{
|
||||
struct pvr_srv_winsys_syncobj *srv_syncobj =
|
||||
to_pvr_srv_winsys_syncobj(syncobj);
|
||||
|
||||
if (srv_syncobj->fd != -1)
|
||||
close(srv_syncobj->fd);
|
||||
|
||||
srv_syncobj->fd = payload;
|
||||
/* FIXME: Is this valid? */
|
||||
srv_syncobj->signaled = (payload == -1);
|
||||
}
|
||||
|
||||
VkResult
|
||||
pvr_srv_winsys_syncobjs_reset(struct pvr_winsys *ws,
|
||||
struct pvr_winsys_syncobj **const syncobjs,
|
||||
uint32_t count)
|
||||
{
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
struct pvr_srv_winsys_syncobj *srv_syncobj;
|
||||
|
||||
if (!syncobjs[i])
|
||||
continue;
|
||||
|
||||
srv_syncobj = to_pvr_srv_winsys_syncobj(syncobjs[i]);
|
||||
pvr_set_syncobj_state(srv_syncobj, false);
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult
|
||||
pvr_srv_winsys_syncobjs_signal(struct pvr_winsys *ws,
|
||||
struct pvr_winsys_syncobj **const syncobjs,
|
||||
uint32_t count)
|
||||
{
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
struct pvr_srv_winsys_syncobj *srv_syncobj;
|
||||
|
||||
if (!syncobjs[i])
|
||||
continue;
|
||||
|
||||
srv_syncobj = to_pvr_srv_winsys_syncobj(syncobjs[i]);
|
||||
pvr_set_syncobj_state(srv_syncobj, true);
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
/* Careful, timeout might overflow. */
|
||||
static inline void pvr_start_timeout(struct timespec *timeout,
|
||||
uint64_t timeout_ns)
|
||||
{
|
||||
clock_gettime(CLOCK_MONOTONIC, timeout);
|
||||
timespec_add_nsec(timeout, timeout, timeout_ns);
|
||||
}
|
||||
|
||||
/* Careful, a negative value might be returned. */
|
||||
static inline struct timespec
|
||||
pvr_get_remaining_time(const struct timespec *timeout)
|
||||
{
|
||||
struct timespec time;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &time);
|
||||
timespec_sub(&time, timeout, &time);
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
/* timeout == 0 -> Get status without waiting.
|
||||
* timeout == ~0 -> Wait infinitely
|
||||
* else wait for the given timeout in nanoseconds. */
|
||||
VkResult
|
||||
pvr_srv_winsys_syncobjs_wait(struct pvr_winsys *ws,
|
||||
struct pvr_winsys_syncobj **const syncobjs,
|
||||
uint32_t count,
|
||||
bool wait_all,
|
||||
uint64_t timeout)
|
||||
{
|
||||
const struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ws);
|
||||
uint32_t unsignaled_count = 0U;
|
||||
struct timespec end_time;
|
||||
struct pollfd *poll_fds;
|
||||
VkResult result;
|
||||
int ppoll_ret;
|
||||
|
||||
if (timeout != 0U && timeout != ~0U) {
|
||||
/* We don't worry about overflow since ppoll() returns EINVAL on
|
||||
* negative timeout.
|
||||
*/
|
||||
pvr_start_timeout(&end_time, timeout);
|
||||
}
|
||||
|
||||
poll_fds = vk_alloc(srv_ws->alloc,
|
||||
sizeof(*poll_fds) * count,
|
||||
8,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
|
||||
if (!poll_fds)
|
||||
return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
struct pvr_srv_winsys_syncobj *srv_syncobj =
|
||||
to_pvr_srv_winsys_syncobj(syncobjs[i]);
|
||||
|
||||
/* -1 in case if fence is signaled or uninitialized, ppoll will skip the
|
||||
* fence.
|
||||
*/
|
||||
if (!srv_syncobj || srv_syncobj->signaled || srv_syncobj->fd == -1) {
|
||||
poll_fds[i].fd = -1;
|
||||
} else {
|
||||
poll_fds[i].fd = srv_syncobj->fd;
|
||||
unsignaled_count++;
|
||||
}
|
||||
|
||||
poll_fds[i].events = POLLIN;
|
||||
poll_fds[i].revents = 0U;
|
||||
}
|
||||
|
||||
if (unsignaled_count == 0U) {
|
||||
result = VK_SUCCESS;
|
||||
goto end_wait_for_fences;
|
||||
}
|
||||
|
||||
/* TODO: Implement device loss handling like anvil: reporting the loss
|
||||
* save the reported status, maybe abort() on env flag, etc.
|
||||
*/
|
||||
|
||||
do {
|
||||
if (timeout == ~0U) {
|
||||
ppoll_ret = ppoll(poll_fds, count, NULL, NULL);
|
||||
} else {
|
||||
struct timespec remaining_time;
|
||||
|
||||
if (timeout == 0U) {
|
||||
remaining_time = (struct timespec){ 0UL, 0UL };
|
||||
} else {
|
||||
/* ppoll() returns EINVAL on negative timeout. Nothing to worry.
|
||||
*/
|
||||
remaining_time = pvr_get_remaining_time(&end_time);
|
||||
}
|
||||
|
||||
ppoll_ret = ppoll(poll_fds, count, &remaining_time, NULL);
|
||||
}
|
||||
|
||||
if (ppoll_ret > 0U) {
|
||||
/* ppoll_ret contains the amount of structs updated by poll(). */
|
||||
unsignaled_count -= ppoll_ret;
|
||||
|
||||
/* ppoll_ret > 0 is for early loop termination. */
|
||||
for (uint32_t i = 0; ppoll_ret > 0 && i < count; i++) {
|
||||
struct pvr_srv_winsys_syncobj *srv_syncobj;
|
||||
|
||||
if (poll_fds[i].revents == 0)
|
||||
continue;
|
||||
|
||||
if (poll_fds[i].revents & (POLLNVAL | POLLERR)) {
|
||||
result = vk_error(NULL, VK_ERROR_DEVICE_LOST);
|
||||
goto end_wait_for_fences;
|
||||
}
|
||||
|
||||
srv_syncobj = to_pvr_srv_winsys_syncobj(syncobjs[i]);
|
||||
pvr_set_syncobj_state(srv_syncobj, true);
|
||||
|
||||
if (!wait_all) {
|
||||
result = VK_SUCCESS;
|
||||
goto end_wait_for_fences;
|
||||
}
|
||||
|
||||
/* -1 makes ppoll ignore it and set revents to 0. */
|
||||
poll_fds[i].fd = -1;
|
||||
ppoll_ret--;
|
||||
}
|
||||
|
||||
/* For zero timeout, just return even if we still have unsignaled
|
||||
* fences.
|
||||
*/
|
||||
if (timeout == 0U && unsignaled_count != 0U) {
|
||||
result = VK_TIMEOUT;
|
||||
goto end_wait_for_fences;
|
||||
}
|
||||
} else if (ppoll_ret == 0) {
|
||||
result = VK_TIMEOUT;
|
||||
goto end_wait_for_fences;
|
||||
}
|
||||
|
||||
/* Careful as we might have decremented ppoll_ret to 0. */
|
||||
} while ((ppoll_ret != -1 && unsignaled_count != 0) ||
|
||||
(ppoll_ret == -1 && (errno == EINTR || errno == EAGAIN)));
|
||||
|
||||
/* We assume device loss in case of an unknown error or invalid fd. */
|
||||
if (ppoll_ret != -1)
|
||||
result = VK_SUCCESS;
|
||||
else if (errno == EINVAL)
|
||||
result = VK_TIMEOUT;
|
||||
else if (errno == ENOMEM)
|
||||
result = vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
else
|
||||
result = vk_error(NULL, VK_ERROR_DEVICE_LOST);
|
||||
|
||||
end_wait_for_fences:
|
||||
vk_free(srv_ws->alloc, poll_fds);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VkResult pvr_srv_winsys_syncobjs_merge(struct pvr_winsys_syncobj *src,
|
||||
struct pvr_winsys_syncobj *target,
|
||||
struct pvr_winsys_syncobj **syncobj_out)
|
||||
{
|
||||
struct pvr_srv_winsys_syncobj *srv_target =
|
||||
to_pvr_srv_winsys_syncobj(target);
|
||||
struct pvr_srv_winsys_syncobj *srv_src = to_pvr_srv_winsys_syncobj(src);
|
||||
struct pvr_srv_winsys_syncobj *srv_output;
|
||||
struct pvr_winsys_syncobj *output = NULL;
|
||||
VkResult result;
|
||||
|
||||
if (!srv_src || srv_src->fd == -1) {
|
||||
*syncobj_out = target;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
result = pvr_srv_winsys_syncobj_create(src->ws, false, &output);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
srv_output = to_pvr_srv_winsys_syncobj(output);
|
||||
|
||||
if (!srv_target || srv_target->fd == -1) {
|
||||
int fd = dup(srv_src->fd);
|
||||
if (fd < 0) {
|
||||
result = vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
goto err_syncobj_destroy;
|
||||
}
|
||||
|
||||
pvr_srv_set_syncobj_payload(output, fd);
|
||||
if (target)
|
||||
pvr_srv_winsys_syncobj_destroy(target);
|
||||
*syncobj_out = output;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
srv_output->fd = sync_merge("", srv_src->fd, srv_target->fd);
|
||||
if (srv_output->fd < 0) {
|
||||
result = vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
goto err_syncobj_destroy;
|
||||
}
|
||||
|
||||
pvr_srv_winsys_syncobj_destroy(target);
|
||||
|
||||
*syncobj_out = output;
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
err_syncobj_destroy:
|
||||
pvr_srv_winsys_syncobj_destroy(output);
|
||||
|
||||
return result;
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef PVR_SRV_SYNCOBJ_H
|
||||
#define PVR_SRV_SYNCOBJ_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "pvr_winsys.h"
|
||||
#include "util/macros.h"
|
||||
|
||||
struct pvr_srv_winsys_syncobj {
|
||||
struct pvr_winsys_syncobj base;
|
||||
|
||||
/* Cached version of completion. */
|
||||
bool signaled;
|
||||
|
||||
int fd;
|
||||
};
|
||||
|
||||
#define to_pvr_srv_winsys_syncobj(syncobj) \
|
||||
container_of(syncobj, struct pvr_srv_winsys_syncobj, base)
|
||||
|
||||
/*******************************************
|
||||
function prototypes
|
||||
*******************************************/
|
||||
|
||||
VkResult
|
||||
pvr_srv_winsys_syncobj_create(struct pvr_winsys *ws,
|
||||
bool signaled,
|
||||
struct pvr_winsys_syncobj **const syncobj_out);
|
||||
void pvr_srv_winsys_syncobj_destroy(struct pvr_winsys_syncobj *syncobj);
|
||||
VkResult
|
||||
pvr_srv_winsys_syncobjs_reset(struct pvr_winsys *ws,
|
||||
struct pvr_winsys_syncobj **const syncobjs,
|
||||
uint32_t count);
|
||||
VkResult
|
||||
pvr_srv_winsys_syncobjs_signal(struct pvr_winsys *ws,
|
||||
struct pvr_winsys_syncobj **const syncobjs,
|
||||
uint32_t count);
|
||||
VkResult
|
||||
pvr_srv_winsys_syncobjs_wait(struct pvr_winsys *ws,
|
||||
struct pvr_winsys_syncobj **const syncobjs,
|
||||
uint32_t count,
|
||||
bool wait_all,
|
||||
uint64_t timeout);
|
||||
VkResult pvr_srv_winsys_syncobjs_merge(struct pvr_winsys_syncobj *src,
|
||||
struct pvr_winsys_syncobj *target,
|
||||
struct pvr_winsys_syncobj **out);
|
||||
|
||||
void pvr_srv_set_syncobj_payload(struct pvr_winsys_syncobj *syncobj,
|
||||
int payload);
|
||||
|
||||
#endif /* PVR_SRV_SYNCOBJ_H */
|
Loading…
Reference in New Issue