Skip to content

Commit

Permalink
vulkan/gpu: add vk_gpu_idle_callback
Browse files Browse the repository at this point in the history
To safely attach a callback to the "GPU idle" state, replacing code
duplication of previous constructions of this nature.
  • Loading branch information
haasn committed Feb 15, 2023
1 parent 09e6ae3 commit 18f6d18
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 18 deletions.
24 changes: 15 additions & 9 deletions src/vulkan/gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,7 @@ static pl_timer vk_timer_create(pl_gpu gpu)

static void vk_timer_destroy(pl_gpu gpu, pl_timer timer)
{
struct pl_vk *p = PL_PRIV(gpu);
struct vk_ctx *vk = p->vk;
pl_mutex_lock(&p->recording);
if (p->cmd) {
vk_cmd_callback(p->cmd, (vk_cb) timer_destroy_cb, gpu, timer);
} else {
vk_dev_callback(vk, (vk_cb) timer_destroy_cb, gpu, timer);
}
pl_mutex_unlock(&p->recording);
vk_gpu_idle_callback(gpu, (vk_cb) timer_destroy_cb, gpu, timer);
}

static uint64_t vk_timer_query(pl_gpu gpu, pl_timer timer)
Expand Down Expand Up @@ -245,6 +237,20 @@ bool _end_cmd(pl_gpu gpu, struct vk_cmd **pcmd, bool submit)
return ret;
}

void vk_gpu_idle_callback(pl_gpu gpu, vk_cb cb, const void *priv, const void *arg)
{
struct pl_vk *p = PL_PRIV(gpu);
struct vk_ctx *vk = p->vk;

pl_mutex_lock(&p->recording);
if (p->cmd) {
vk_cmd_callback(p->cmd, cb, priv, arg);
} else {
vk_dev_callback(vk, cb, priv, arg);
}
pl_mutex_unlock(&p->recording);
}

static void vk_gpu_destroy(pl_gpu gpu)
{
struct pl_vk *p = PL_PRIV(gpu);
Expand Down
7 changes: 7 additions & 0 deletions src/vulkan/gpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ bool _end_cmd(pl_gpu, struct vk_cmd **, bool submit);
#define CMD_FINISH(cmd) _end_cmd(gpu, cmd, false)
#define CMD_SUBMIT(cmd) _end_cmd(gpu, cmd, true)

// Helper to fire a callback the next time the `pl_gpu` is in an idle state
//
// Use this instead of `vk_dev_callback` when you need to clean up after
// resources that might possibly still be in use by the `pl_gpu` at the time of
// creating the callback.
void vk_gpu_idle_callback(pl_gpu, vk_cb, const void *priv, const void *arg);

struct pl_tex_vk {
pl_rc_t rc;
bool external_img;
Expand Down
12 changes: 3 additions & 9 deletions src/vulkan/gpu_pass.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,7 @@ static void pass_destroy_cb(pl_gpu gpu, pl_pass pass)

void vk_pass_destroy(pl_gpu gpu, pl_pass pass)
{
struct pl_vk *p = PL_PRIV(gpu);
struct vk_ctx *vk = p->vk;
pl_mutex_lock(&p->recording);
if (p->cmd) {
vk_cmd_callback(p->cmd, (vk_cb) pass_destroy_cb, gpu, pass);
} else {
vk_dev_callback(vk, (vk_cb) pass_destroy_cb, gpu, pass);
}
pl_mutex_unlock(&p->recording);
vk_gpu_idle_callback(gpu, (vk_cb) pass_destroy_cb, gpu, pass);
}

static const VkDescriptorType dsType[] = {
Expand Down Expand Up @@ -191,6 +183,8 @@ static VkResult vk_recreate_pipelines(struct vk_ctx *vk, pl_pass pass,
// The old pipeline might still be in use, so we have to destroy it
// asynchronously with a device idle callback
if (*out_pipe) {
// We don't need to use `vk_gpu_idle_callback` because the only command
// that can access a VkPipeline, `vk_pass_run`, always flushes `p->cmd`.
vk_dev_callback(vk, (vk_cb) destroy_pipeline, vk, vk_wrap_handle(*out_pipe));
*out_pipe = VK_NULL_HANDLE;
}
Expand Down

0 comments on commit 18f6d18

Please sign in to comment.