summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.xyz>2017-09-28 22:33:31 +0200
committerMartin Herkt <652892+lachs0r@users.noreply.github.com>2017-12-25 00:47:53 +0100
commit885497a4456256a147d9e7e30daa3170e461d7d6 (patch)
treeca0d9d08b032654aa52c326016baadebfdfe5af1 /video
parent4e34615872011f906bf653f61e7ac75d2066a06b (diff)
downloadmpv-885497a4456256a147d9e7e30daa3170e461d7d6.tar.bz2
mpv-885497a4456256a147d9e7e30daa3170e461d7d6.tar.xz
vo_gpu: vulkan: reorganize vk_cmd slightly
Instead of associating a single VkSemaphore with every command buffer and allowing the user to ad-hoc wait on it during submission, make the raw semaphores-to-signal array work like the raw semaphores-to-wait-on array. Doesn't really provide a clear benefit yet, but it's required for upcoming modifications.
Diffstat (limited to 'video')
-rw-r--r--video/out/vulkan/context.c45
-rw-r--r--video/out/vulkan/ra_vk.c15
-rw-r--r--video/out/vulkan/ra_vk.h7
-rw-r--r--video/out/vulkan/utils.c28
-rw-r--r--video/out/vulkan/utils.h20
5 files changed, 58 insertions, 57 deletions
diff --git a/video/out/vulkan/context.c b/video/out/vulkan/context.c
index 5d9b40cbb5..b51bb78578 100644
--- a/video/out/vulkan/context.c
+++ b/video/out/vulkan/context.c
@@ -121,9 +121,10 @@ struct priv {
// state of the images:
struct ra_tex **images; // ra_tex wrappers for the vkimages
int num_images; // size of images
- VkSemaphore *acquired; // pool of semaphores used to synchronize images
- int num_acquired; // size of this pool
- int idx_acquired; // index of next free semaphore within this pool
+ VkSemaphore *sems_in; // pool of semaphores used to synchronize images
+ VkSemaphore *sems_out; // outgoing semaphores (rendering complete)
+ int num_sems;
+ int idx_sems; // index of next free semaphore pair
int last_imgidx; // the image index last acquired (for submit)
};
@@ -248,13 +249,12 @@ void ra_vk_ctx_uninit(struct ra_ctx *ctx)
for (int i = 0; i < p->num_images; i++)
ra_tex_free(ctx->ra, &p->images[i]);
- for (int i = 0; i < p->num_acquired; i++)
- vkDestroySemaphore(vk->dev, p->acquired[i], MPVK_ALLOCATOR);
+ for (int i = 0; i < p->num_sems; i++) {
+ vkDestroySemaphore(vk->dev, p->sems_in[i], MPVK_ALLOCATOR);
+ vkDestroySemaphore(vk->dev, p->sems_out[i], MPVK_ALLOCATOR);
+ }
vkDestroySwapchainKHR(vk->dev, p->swapchain, MPVK_ALLOCATOR);
-
- talloc_free(p->images);
- talloc_free(p->acquired);
ctx->ra->fns->destroy(ctx->ra);
ctx->ra = NULL;
}
@@ -382,13 +382,19 @@ bool ra_vk_ctx_resize(struct ra_swapchain *sw, int w, int h)
VK(vkGetSwapchainImagesKHR(vk->dev, p->swapchain, &num, vkimages));
// If needed, allocate some more semaphores
- while (num > p->num_acquired) {
- VkSemaphore sem;
+ while (num > p->num_sems) {
+ VkSemaphore sem_in, sem_out;
static const VkSemaphoreCreateInfo seminfo = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
};
- VK(vkCreateSemaphore(vk->dev, &seminfo, MPVK_ALLOCATOR, &sem));
- MP_TARRAY_APPEND(NULL, p->acquired, p->num_acquired, sem);
+ VK(vkCreateSemaphore(vk->dev, &seminfo, MPVK_ALLOCATOR, &sem_in));
+ VK(vkCreateSemaphore(vk->dev, &seminfo, MPVK_ALLOCATOR, &sem_out));
+
+ int idx = p->num_sems++;
+ MP_TARRAY_GROW(p, p->sems_in, idx);
+ MP_TARRAY_GROW(p, p->sems_out, idx);
+ p->sems_in[idx] = sem_in;
+ p->sems_out[idx] = sem_out;
}
// Recreate the ra_tex wrappers
@@ -396,7 +402,7 @@ bool ra_vk_ctx_resize(struct ra_swapchain *sw, int w, int h)
ra_tex_free(ra, &p->images[i]);
p->num_images = num;
- MP_TARRAY_GROW(NULL, p->images, p->num_images);
+ MP_TARRAY_GROW(p, p->images, p->num_images);
for (int i = 0; i < num; i++) {
p->images[i] = ra_vk_wrap_swapchain_img(ra, vkimages[i], sinfo);
if (!p->images[i])
@@ -444,7 +450,7 @@ static bool start_frame(struct ra_swapchain *sw, struct ra_fbo *out_fbo)
uint32_t imgidx = 0;
MP_TRACE(vk, "vkAcquireNextImageKHR\n");
VkResult res = vkAcquireNextImageKHR(vk->dev, p->swapchain, UINT64_MAX,
- p->acquired[p->idx_acquired], NULL,
+ p->sems_in[p->idx_sems], NULL,
&imgidx);
if (res == VK_ERROR_OUT_OF_DATE_KHR)
goto error; // just return in this case
@@ -469,12 +475,11 @@ static bool submit_frame(struct ra_swapchain *sw, const struct vo_frame *frame)
if (!p->swapchain)
goto error;
- VkSemaphore acquired = p->acquired[p->idx_acquired++];
- p->idx_acquired %= p->num_acquired;
+ int semidx = p->idx_sems++;
+ p->idx_sems %= p->num_sems;
- VkSemaphore done;
- if (!ra_vk_submit(ra, p->images[p->last_imgidx], acquired, &done,
- &p->frames_in_flight))
+ if (!ra_vk_submit(ra, p->images[p->last_imgidx], p->sems_in[semidx],
+ p->sems_out[semidx], &p->frames_in_flight))
goto error;
// Older nvidia drivers can spontaneously combust when submitting to the
@@ -488,7 +493,7 @@ static bool submit_frame(struct ra_swapchain *sw, const struct vo_frame *frame)
VkPresentInfoKHR pinfo = {
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
.waitSemaphoreCount = 1,
- .pWaitSemaphores = &done,
+ .pWaitSemaphores = &p->sems_out[semidx],
.swapchainCount = 1,
.pSwapchains = &p->swapchain,
.pImageIndices = &p->last_imgidx,
diff --git a/video/out/vulkan/ra_vk.c b/video/out/vulkan/ra_vk.c
index 9101233495..e0e13391af 100644
--- a/video/out/vulkan/ra_vk.c
+++ b/video/out/vulkan/ra_vk.c
@@ -34,16 +34,13 @@ static struct vk_cmd *vk_require_cmd(struct ra *ra)
return p->cmd;
}
-// Note: This technically follows the flush() API, but we don't need
-// to expose that (and in fact, it's a bad idea) since we control flushing
-// behavior with ra_vk_present_frame already.
-static bool vk_flush(struct ra *ra, VkSemaphore *done)
+static bool vk_flush(struct ra *ra)
{
struct ra_vk *p = ra->priv;
struct mpvk_ctx *vk = ra_vk_get(ra);
if (p->cmd) {
- if (!vk_cmd_submit(vk, p->cmd, done))
+ if (!vk_cmd_submit(vk, p->cmd))
return false;
p->cmd = NULL;
}
@@ -74,7 +71,7 @@ static void vk_destroy_ra(struct ra *ra)
struct ra_vk *p = ra->priv;
struct mpvk_ctx *vk = ra_vk_get(ra);
- vk_flush(ra, NULL);
+ vk_flush(ra);
mpvk_dev_wait_cmds(vk, UINT64_MAX);
ra_tex_free(ra, &p->clear_tex);
@@ -1715,7 +1712,7 @@ static void present_cb(void *priv, int *inflight)
}
bool ra_vk_submit(struct ra *ra, struct ra_tex *tex, VkSemaphore acquired,
- VkSemaphore *done, int *inflight)
+ VkSemaphore done, int *inflight)
{
struct vk_cmd *cmd = vk_require_cmd(ra);
if (!cmd)
@@ -1740,7 +1737,9 @@ bool ra_vk_submit(struct ra *ra, struct ra_tex *tex, VkSemaphore acquired,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_TRANSFER_BIT);
- return vk_flush(ra, done);
+ vk_cmd_sig(cmd, done);
+
+ return vk_flush(ra);
error:
return false;
diff --git a/video/out/vulkan/ra_vk.h b/video/out/vulkan/ra_vk.h
index 893421bc59..d15b6380f0 100644
--- a/video/out/vulkan/ra_vk.h
+++ b/video/out/vulkan/ra_vk.h
@@ -18,13 +18,12 @@ struct ra_tex *ra_vk_wrap_swapchain_img(struct ra *ra, VkImage vkimg,
// This function flushes the command buffers, transitions `tex` (which must be
// a wrapped swapchain image) into a format suitable for presentation, and
-// submits the current rendering commands. The indicated semaphore must fire
-// before the submitted command can run. If `done` is non-NULL, it will be
-// set to a semaphore that fires once the command completes. If `inflight`
+// submits the current rendering commands. `acquired` must fire before the
+// command can run, and `done` will fire after it completes. If `inflight`
// is non-NULL, it will be incremented when the command starts and decremented
// when it completes.
bool ra_vk_submit(struct ra *ra, struct ra_tex *tex, VkSemaphore acquired,
- VkSemaphore *done, int *inflight);
+ VkSemaphore done, int *inflight);
// May be called on a struct ra of any type. Returns NULL if the ra is not
// a vulkan ra.
diff --git a/video/out/vulkan/utils.c b/video/out/vulkan/utils.c
index ba7ff66f2b..7c8511a9d2 100644
--- a/video/out/vulkan/utils.c
+++ b/video/out/vulkan/utils.c
@@ -484,6 +484,7 @@ static void vk_cmd_reset(struct mpvk_ctx *vk, struct vk_cmd *cmd)
cmd->num_callbacks = 0;
cmd->num_deps = 0;
+ cmd->num_sigs = 0;
// also make sure to reset vk->last_cmd in case this was the last command
if (vk->last_cmd == cmd)
@@ -497,7 +498,6 @@ static void vk_cmd_destroy(struct mpvk_ctx *vk, struct vk_cmd *cmd)
vk_cmd_poll(vk, cmd, UINT64_MAX);
vk_cmd_reset(vk, cmd);
- vkDestroySemaphore(vk->dev, cmd->done, MPVK_ALLOCATOR);
vkDestroyFence(vk->dev, cmd->fence, MPVK_ALLOCATOR);
vkFreeCommandBuffers(vk->dev, cmd->pool->pool, 1, &cmd->buf);
@@ -525,12 +525,6 @@ static struct vk_cmd *vk_cmd_create(struct mpvk_ctx *vk, struct vk_cmdpool *pool
VK(vkCreateFence(vk->dev, &finfo, MPVK_ALLOCATOR, &cmd->fence));
- VkSemaphoreCreateInfo sinfo = {
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
- };
-
- VK(vkCreateSemaphore(vk->dev, &sinfo, MPVK_ALLOCATOR, &cmd->done));
-
return cmd;
error:
@@ -547,14 +541,18 @@ void vk_cmd_callback(struct vk_cmd *cmd, vk_cb callback, void *p, void *arg)
});
}
-void vk_cmd_dep(struct vk_cmd *cmd, VkSemaphore dep,
- VkPipelineStageFlags depstage)
+void vk_cmd_dep(struct vk_cmd *cmd, VkSemaphore dep, VkPipelineStageFlags stage)
{
int idx = cmd->num_deps++;
MP_TARRAY_GROW(cmd, cmd->deps, idx);
MP_TARRAY_GROW(cmd, cmd->depstages, idx);
cmd->deps[idx] = dep;
- cmd->depstages[idx] = depstage;
+ cmd->depstages[idx] = stage;
+}
+
+void vk_cmd_sig(struct vk_cmd *cmd, VkSemaphore sig)
+{
+ MP_TARRAY_APPEND(cmd, cmd->sigs, cmd->num_sigs, sig);
}
static void vk_cmdpool_destroy(struct mpvk_ctx *vk, struct vk_cmdpool *pool)
@@ -667,7 +665,7 @@ error:
return NULL;
}
-bool vk_cmd_submit(struct mpvk_ctx *vk, struct vk_cmd *cmd, VkSemaphore *done)
+bool vk_cmd_submit(struct mpvk_ctx *vk, struct vk_cmd *cmd)
{
struct vk_cmdpool *pool = cmd->pool;
@@ -680,14 +678,10 @@ bool vk_cmd_submit(struct mpvk_ctx *vk, struct vk_cmd *cmd, VkSemaphore *done)
.waitSemaphoreCount = cmd->num_deps,
.pWaitSemaphores = cmd->deps,
.pWaitDstStageMask = cmd->depstages,
+ .signalSemaphoreCount = cmd->num_sigs,
+ .pSignalSemaphores = cmd->sigs,
};
- if (done) {
- sinfo.signalSemaphoreCount = 1;
- sinfo.pSignalSemaphores = &cmd->done;
- *done = cmd->done;
- }
-
VK(vkResetFences(vk->dev, 1, &cmd->fence));
VK(vkQueueSubmit(cmd->queue, 1, &sinfo, cmd->fence));
MP_TRACE(vk, "Submitted command on queue %p (QF %d)\n", (void *)cmd->queue,
diff --git a/video/out/vulkan/utils.h b/video/out/vulkan/utils.h
index 36a0e3c5d0..3ade92d6a0 100644
--- a/video/out/vulkan/utils.h
+++ b/video/out/vulkan/utils.h
@@ -93,12 +93,15 @@ struct vk_cmd {
VkQueue queue; // the submission queue (for recording/pending)
VkCommandBuffer buf; // the command buffer itself
VkFence fence; // the fence guards cmd buffer reuse
- VkSemaphore done; // the semaphore signals when execution is done
// The semaphores represent dependencies that need to complete before
// this command can be executed. These are *not* owned by the vk_cmd
VkSemaphore *deps;
VkPipelineStageFlags *depstages;
int num_deps;
+ // The signals represent semaphores that fire once the command finishes
+ // executing. These are also not owned by the vk_cmd
+ VkSemaphore *sigs;
+ int num_sigs;
// Since VkFences are useless, we have to manually track "callbacks"
// to fire once the VkFence completes. These are used for multiple purposes,
// ranging from garbage collection (resource deallocation) to fencing.
@@ -110,10 +113,13 @@ struct vk_cmd {
// bool will be set to `true` once the command completes, or shortly thereafter.
void vk_cmd_callback(struct vk_cmd *cmd, vk_cb callback, void *p, void *arg);
-// Associate a dependency for the current command. This semaphore must signal
-// by the corresponding stage before the command may execute.
-void vk_cmd_dep(struct vk_cmd *cmd, VkSemaphore dep,
- VkPipelineStageFlags depstage);
+// Associate a raw dependency for the current command. This semaphore must
+// signal by the corresponding stage before the command may execute.
+void vk_cmd_dep(struct vk_cmd *cmd, VkSemaphore dep, VkPipelineStageFlags stage);
+
+// Associate a raw signal with the current command. This semaphore will signal
+// after the command completes.
+void vk_cmd_sig(struct vk_cmd *cmd, VkSemaphore sig);
// Command pool / queue family hybrid abstraction
struct vk_cmdpool {
@@ -136,10 +142,8 @@ struct vk_cmd *vk_cmd_begin(struct mpvk_ctx *vk, struct vk_cmdpool *pool);
// Finish recording a command buffer and submit it for execution. This function
// takes over ownership of *cmd, i.e. the caller should not touch it again.
-// If `done` is not NULL, it will be set to a semaphore that will signal once
-// the command completes.
// Returns whether successful.
-bool vk_cmd_submit(struct mpvk_ctx *vk, struct vk_cmd *cmd, VkSemaphore *done);
+bool vk_cmd_submit(struct mpvk_ctx *vk, struct vk_cmd *cmd);
// Rotate the queues for each vk_cmdpool. Call this once per frame to ensure
// good parallelism between frames when using multiple queues