diff options
Diffstat (limited to 'video/out/vulkan')
-rw-r--r-- | video/out/vulkan/common.h | 58 | ||||
-rw-r--r-- | video/out/vulkan/context.c | 482 | ||||
-rw-r--r-- | video/out/vulkan/context.h | 4 | ||||
-rw-r--r-- | video/out/vulkan/context_wayland.c | 18 | ||||
-rw-r--r-- | video/out/vulkan/context_win.c | 105 | ||||
-rw-r--r-- | video/out/vulkan/context_xlib.c | 11 | ||||
-rw-r--r-- | video/out/vulkan/formats.c | 55 | ||||
-rw-r--r-- | video/out/vulkan/formats.h | 16 | ||||
-rw-r--r-- | video/out/vulkan/malloc.c | 471 | ||||
-rw-r--r-- | video/out/vulkan/malloc.h | 37 | ||||
-rw-r--r-- | video/out/vulkan/ra_vk.c | 1982 | ||||
-rw-r--r-- | video/out/vulkan/ra_vk.h | 51 | ||||
-rw-r--r-- | video/out/vulkan/utils.c | 990 | ||||
-rw-r--r-- | video/out/vulkan/utils.h | 190 |
14 files changed, 117 insertions, 4353 deletions
diff --git a/video/out/vulkan/common.h b/video/out/vulkan/common.h index a4284f9055..b085fb462c 100644 --- a/video/out/vulkan/common.h +++ b/video/out/vulkan/common.h @@ -23,58 +23,14 @@ #define VK_USE_PLATFORM_WIN32_KHR #endif -#include <vulkan/vulkan.h> - -// Vulkan allows the optional use of a custom allocator. We don't need one but -// mark this parameter with a better name in case we ever decide to change this -// in the future. (And to make the code more readable) -#define MPVK_ALLOCATOR NULL - -// A lot of things depend on streaming resources across frames. Depending on -// how many frames we render ahead of time, we need to pick enough to avoid -// any conflicts, so make all of these tunable relative to this constant in -// order to centralize them. -#define MPVK_MAX_STREAMING_DEPTH 8 +#include <libplacebo/vulkan.h> // Shared struct used to hold vulkan context information struct mpvk_ctx { - struct mp_log *log; - VkInstance inst; - VkPhysicalDevice physd; - VkDebugReportCallbackEXT dbg; - VkDevice dev; - - // Surface, must be initialized fter the context itself - VkSurfaceKHR surf; - VkSurfaceFormatKHR surf_format; // picked at surface initialization time - - struct vk_malloc *alloc; // memory allocator for this device - struct spirv_compiler *spirv; // GLSL -> SPIR-V compiler - struct vk_cmdpool **pools; // command pools (one per queue family) - int num_pools; - struct vk_cmd *last_cmd; // most recently submitted command - - // Queued/pending commands. These are shared for the entire mpvk_ctx to - // ensure submission and callbacks are FIFO - struct vk_cmd **cmds_queued; // recorded but not yet submitted - struct vk_cmd **cmds_pending; // submitted but not completed - int num_cmds_queued; - int num_cmds_pending; - - // Pointers into *pools - struct vk_cmdpool *pool_graphics; // required - struct vk_cmdpool *pool_compute; // optional - struct vk_cmdpool *pool_transfer; // optional - - // Common pool of signals, to avoid having to re-create these objects often - struct vk_signal **signals; - int num_signals; - - // Cached capabilities - VkPhysicalDeviceLimits limits; - VkPhysicalDeviceFeatures features; - - // Extension availability - bool has_ext_external_memory; - bool has_ext_external_memory_export; + struct mp_log *pl_log; + struct pl_context *ctx; + const struct pl_vk_inst *vkinst; + const struct pl_vulkan *vulkan; + const struct pl_gpu *gpu; // points to vulkan->gpu for convenience + VkSurfaceKHR surface; }; diff --git a/video/out/vulkan/context.c b/video/out/vulkan/context.c index 29a2c9b727..c05a5ac209 100644 --- a/video/out/vulkan/context.c +++ b/video/out/vulkan/context.c @@ -16,25 +16,17 @@ */ #include "options/m_config.h" -#include "video/out/gpu/spirv.h" +#include "video/out/placebo/ra_pl.h" #include "context.h" -#include "ra_vk.h" #include "utils.h" -enum { - SWAP_AUTO = 0, - SWAP_FIFO, - SWAP_FIFO_RELAXED, - SWAP_MAILBOX, - SWAP_IMMEDIATE, - SWAP_COUNT, -}; - struct vulkan_opts { - struct mpvk_device_opts dev_opts; // logical device options char *device; // force a specific GPU int swap_mode; + int queue_count; + int async_transfer; + int async_compute; }; static int vk_validate_dev(struct mp_log *log, const struct m_option *opt, @@ -52,7 +44,7 @@ static int vk_validate_dev(struct mp_log *log, const struct m_option *opt, VkPhysicalDevice *devices = NULL; uint32_t num = 0; - res = vkCreateInstance(&info, MPVK_ALLOCATOR, &inst); + res = vkCreateInstance(&info, NULL, &inst); if (res != VK_SUCCESS) goto done; @@ -97,45 +89,30 @@ const struct m_sub_options vulkan_conf = { .opts = (const struct m_option[]) { OPT_STRING_VALIDATE("vulkan-device", device, 0, vk_validate_dev), OPT_CHOICE("vulkan-swap-mode", swap_mode, 0, - ({"auto", SWAP_AUTO}, - {"fifo", SWAP_FIFO}, - {"fifo-relaxed", SWAP_FIFO_RELAXED}, - {"mailbox", SWAP_MAILBOX}, - {"immediate", SWAP_IMMEDIATE})), - OPT_INTRANGE("vulkan-queue-count", dev_opts.queue_count, 0, 1, 8, - OPTDEF_INT(1)), - OPT_FLAG("vulkan-async-transfer", dev_opts.async_transfer, 0), - OPT_FLAG("vulkan-async-compute", dev_opts.async_compute, 0), + ({"auto", -1}, + {"fifo", VK_PRESENT_MODE_FIFO_KHR}, + {"fifo-relaxed", VK_PRESENT_MODE_FIFO_RELAXED_KHR}, + {"mailbox", VK_PRESENT_MODE_MAILBOX_KHR}, + {"immediate", VK_PRESENT_MODE_IMMEDIATE_KHR})), + OPT_INTRANGE("vulkan-queue-count", queue_count, 0, 1, 8), + OPT_FLAG("vulkan-async-transfer", async_transfer, 0), + OPT_FLAG("vulkan-async-compute", async_compute, 0), {0} }, .size = sizeof(struct vulkan_opts), .defaults = &(struct vulkan_opts) { - .dev_opts = { - .async_transfer = 1, - }, + .swap_mode = -1, + .queue_count = 1, + .async_transfer = true, + .async_compute = true, }, }; struct priv { struct mpvk_ctx *vk; struct vulkan_opts *opts; - // Swapchain metadata: - int w, h; // current size - VkSwapchainCreateInfoKHR protoInfo; // partially filled-in prototype - VkSwapchainKHR swapchain; - VkSwapchainKHR old_swapchain; - int frames_in_flight; - // state of the images: - struct ra_tex **images; // ra_tex wrappers for the vkimages - int num_images; // size of images - 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) - - // This is used to pre-fetch the next frame at the end of swap_buffers - struct ra_fbo queued_fbo; + const struct pl_swapchain *swapchain; + struct ra_tex proxy_tex; }; static const struct ra_swapchain_fns vulkan_swapchain; @@ -149,133 +126,26 @@ struct mpvk_ctx *ra_vk_ctx_get(struct ra_ctx *ctx) return p->vk; } -static bool update_swapchain_info(struct priv *p, - VkSwapchainCreateInfoKHR *info) -{ - struct mpvk_ctx *vk = p->vk; - - // Query the supported capabilities and update this struct as needed - VkSurfaceCapabilitiesKHR caps; - VK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk->physd, vk->surf, &caps)); - - // Sorted by preference - static const VkCompositeAlphaFlagsKHR alphaModes[] = { - VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, - VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, - }; - - for (int i = 0; i < MP_ARRAY_SIZE(alphaModes); i++) { - if (caps.supportedCompositeAlpha & alphaModes[i]) { - info->compositeAlpha = alphaModes[i]; - break; - } - } - - if (!info->compositeAlpha) { - MP_ERR(vk, "Failed picking alpha compositing mode (caps: 0x%x)\n", - caps.supportedCompositeAlpha); - goto error; - } - - static const VkSurfaceTransformFlagsKHR rotModes[] = { - VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, - VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR, - }; - - for (int i = 0; i < MP_ARRAY_SIZE(rotModes); i++) { - if (caps.supportedTransforms & rotModes[i]) { - info->preTransform = rotModes[i]; - break; - } - } - - if (!info->preTransform) { - MP_ERR(vk, "Failed picking surface transform mode (caps: 0x%x)\n", - caps.supportedTransforms); - goto error; - } - - // Image count as required - MP_VERBOSE(vk, "Requested image count: %d (min %d max %d)\n", - (int)info->minImageCount, (int)caps.minImageCount, - (int)caps.maxImageCount); - - info->minImageCount = MPMAX(info->minImageCount, caps.minImageCount); - if (caps.maxImageCount) - info->minImageCount = MPMIN(info->minImageCount, caps.maxImageCount); - - // Check the extent against the allowed parameters - if (caps.currentExtent.width != info->imageExtent.width && - caps.currentExtent.width != 0xFFFFFFFF) - { - MP_WARN(vk, "Requested width %d does not match current width %d\n", - (int)info->imageExtent.width, (int)caps.currentExtent.width); - info->imageExtent.width = caps.currentExtent.width; - } - - if (caps.currentExtent.height != info->imageExtent.height && - caps.currentExtent.height != 0xFFFFFFFF) - { - MP_WARN(vk, "Requested height %d does not match current height %d\n", - (int)info->imageExtent.height, (int)caps.currentExtent.height); - info->imageExtent.height = caps.currentExtent.height; - } - - if (caps.minImageExtent.width > info->imageExtent.width || - caps.minImageExtent.height > info->imageExtent.height) - { - MP_ERR(vk, "Requested size %dx%d smaller than device minimum %d%d\n", - (int)info->imageExtent.width, (int)info->imageExtent.height, - (int)caps.minImageExtent.width, (int)caps.minImageExtent.height); - goto error; - } - - if (caps.maxImageExtent.width < info->imageExtent.width || - caps.maxImageExtent.height < info->imageExtent.height) - { - MP_ERR(vk, "Requested size %dx%d larger than device maximum %d%d\n", - (int)info->imageExtent.width, (int)info->imageExtent.height, - (int)caps.maxImageExtent.width, (int)caps.maxImageExtent.height); - goto error; - } - - // We just request whatever usage we can, and let the ra_vk decide what - // ra_tex_params that translates to. This makes the images as flexible - // as possible. - info->imageUsage = caps.supportedUsageFlags; - return true; - -error: - return false; -} - void ra_vk_ctx_uninit(struct ra_ctx *ctx) { - if (ctx->ra) { - struct priv *p = ctx->swapchain->priv; - struct mpvk_ctx *vk = p->vk; - - mpvk_flush_commands(vk); - mpvk_poll_commands(vk, UINT64_MAX); + if (!ctx->swapchain) + return; - for (int i = 0; i < p->num_images; i++) - ra_tex_free(ctx->ra, &p->images[i]); - 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); - } + struct priv *p = ctx->swapchain->priv; + struct mpvk_ctx *vk = p->vk; - vkDestroySwapchainKHR(vk->dev, p->swapchain, MPVK_ALLOCATOR); + if (ctx->ra) { + pl_gpu_finish(vk->gpu); + pl_swapchain_destroy(&p->swapchain); ctx->ra->fns->destroy(ctx->ra); ctx->ra = NULL; } - talloc_free(ctx->swapchain); - ctx->swapchain = NULL; + vk->gpu = NULL; + pl_vulkan_destroy(&vk->vulkan); + TA_FREEP(&ctx->swapchain); } -static const struct ra_swapchain_fns vulkan_swapchain; - bool ra_vk_ctx_init(struct ra_ctx *ctx, struct mpvk_ctx *vk, VkPresentModeKHR preferred_mode) { @@ -287,56 +157,36 @@ bool ra_vk_ctx_init(struct ra_ctx *ctx, struct mpvk_ctx *vk, p->vk = vk; p->opts = mp_get_config_group(p, ctx->global, &vulkan_conf); - if (!mpvk_find_phys_device(vk, p->opts->device, ctx->opts.allow_sw)) - goto error; - if (!spirv_compiler_init(ctx)) - goto error; - vk->spirv = ctx->spirv; - if (!mpvk_pick_surface_format(vk)) - goto error; - if (!mpvk_device_init(vk, p->opts->dev_opts)) + assert(vk->ctx); + assert(vk->vkinst); + vk->vulkan = pl_vulkan_create(vk->ctx, &(struct pl_vulkan_params) { + .instance = vk->vkinst->instance, + .surface = vk->surface, + .async_transfer = p->opts->async_transfer, + .async_compute = p->opts->async_compute, + .queue_count = p->opts->queue_count, + }); + if (!vk->vulkan) goto error; - ctx->ra = ra_create_vk(vk, ctx->log); + vk->gpu = vk->vulkan->gpu; + ctx->ra = ra_create_pl(vk->gpu, ctx->log); if (!ctx->ra) goto error; - static const VkPresentModeKHR present_modes[SWAP_COUNT] = { - [SWAP_FIFO] = VK_PRESENT_MODE_FIFO_KHR, - [SWAP_FIFO_RELAXED] = VK_PRESENT_MODE_FIFO_RELAXED_KHR, - [SWAP_MAILBOX] = VK_PRESENT_MODE_MAILBOX_KHR, - [SWAP_IMMEDIATE] = VK_PRESENT_MODE_IMMEDIATE_KHR, + // Create the swapchain + struct pl_vulkan_swapchain_params params = { + .surface = vk->surface, + .present_mode = preferred_mode, + .swapchain_depth = ctx->opts.swapchain_depth, }; - p->protoInfo = (VkSwapchainCreateInfoKHR) { - .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, - .surface = vk->surf, - .imageFormat = vk->surf_format.format, - .imageColorSpace = vk->surf_format.colorSpace, - .imageArrayLayers = 1, // non-stereoscopic - .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, - .minImageCount = ctx->opts.swapchain_depth + 1, // +1 for FB - .presentMode = p->opts->swap_mode ? present_modes[p->opts->swap_mode] - : preferred_mode, - .clipped = true, - }; + if (p->opts->swap_mode >= 0) // user override + params.present_mode = p->opts->swap_mode; - // Make sure the swapchain present mode is supported - int num_modes; - VK(vkGetPhysicalDeviceSurfacePresentModesKHR(vk->physd, vk->surf, - &num_modes, NULL)); - VkPresentModeKHR *modes = talloc_array(NULL, VkPresentModeKHR, num_modes); - VK(vkGetPhysicalDeviceSurfacePresentModesKHR(vk->physd, vk->surf, - &num_modes, modes)); - bool supported = false; - for (int i = 0; i < num_modes; i++) - supported |= (modes[i] == p->protoInfo.presentMode); - talloc_free(modes); - - if (!supported) { - MP_ERR(ctx, "Requested swap mode unsupported by this device!\n"); + p->swapchain = pl_vulkan_create_swapchain(vk->vulkan, ¶ms); + if (!p->swapchain) goto error; - } return true; @@ -345,245 +195,49 @@ error: return false; } -static void destroy_swapchain(struct mpvk_ctx *vk, struct priv *p) +bool ra_vk_ctx_resize(struct ra_ctx *ctx, int width, int height) { - assert(p->old_swapchain); - vkDestroySwapchainKHR(vk->dev, p->old_swapchain, MPVK_ALLOCATOR); - p->old_swapchain = NULL; -} - -bool ra_vk_ctx_resize(struct ra_swapchain *sw, int w, int h) -{ - struct priv *p = sw->priv; - if (w == p->w && h == p->h) - return true; - - struct ra *ra = sw->ctx->ra; - struct mpvk_ctx *vk = p->vk; - VkImage *vkimages = NULL; - - // It's invalid to trigger another swapchain recreation while there's - // more than one swapchain already active, so we need to flush any pending - // asynchronous swapchain release operations that may be ongoing. - while (p->old_swapchain) - mpvk_poll_commands(vk, 100000); // 100μs - - VkSwapchainCreateInfoKHR sinfo = p->protoInfo; - sinfo.imageExtent = (VkExtent2D){ w, h }; - sinfo.oldSwapchain = p->swapchain; - - if (!update_swapchain_info(p, &sinfo)) - goto error; - - VK(vkCreateSwapchainKHR(vk->dev, &sinfo, MPVK_ALLOCATOR, &p->swapchain)); - p->w = w; - p->h = h; - - // Freeing the old swapchain while it's still in use is an error, so do - // it asynchronously once the device is idle. - if (sinfo.oldSwapchain) { - p->old_swapchain = sinfo.oldSwapchain; - vk_dev_callback(vk, (vk_cb) destroy_swapchain, vk, p); - } - - // Get the new swapchain images - int num; - VK(vkGetSwapchainImagesKHR(vk->dev, p->swapchain, &num, NULL)); - vkimages = talloc_array(NULL, VkImage, num); - VK(vkGetSwapchainImagesKHR(vk->dev, p->swapchain, &num, vkimages)); - - // If needed, allocate some more semaphores - 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_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; - } - - // Invalidate the queued texture - p->queued_fbo = (struct ra_fbo) {0}; - - // Recreate the ra_tex wrappers - for (int i = 0; i < p->num_images; i++) - ra_tex_free(ra, &p->images[i]); - - p->num_images = num; - 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]) - goto error; - } + struct priv *p = ctx->swapchain->priv; - talloc_free(vkimages); - return true; + bool ok = pl_swapchain_resize(p->swapchain, &width, &height); + ctx->vo->dwidth = width; + ctx->vo->dheight = height; -error: - talloc_free(vkimages); - vkDestroySwapchainKHR(vk->dev, p->swapchain, MPVK_ALLOCATOR); - p->swapchain = NULL; - return false; + return ok; } static int color_depth(struct ra_swapchain *sw) { - struct priv *p = sw->priv; - int bits = 0; - - if (!p->num_images) - return bits; - - // The channel with the most bits is probably the most authoritative about - // the actual color information (consider e.g. a2bgr10). Slight downside - // in that it results in rounding r/b for e.g. rgb565, but we don't pick - // surfaces with fewer than 8 bits anyway. - const struct ra_format *fmt = p->images[0]->params.format; - for (int i = 0; i < fmt->num_components; i++) { - int depth = fmt->component_depth[i]; - bits = MPMAX(bits, depth ? depth : fmt->component_size[i]); - } - - return bits; + return 0; // TODO: implement this somehow? } static bool start_frame(struct ra_swapchain *sw, struct ra_fbo *out_fbo) { struct priv *p = sw->priv; - struct mpvk_ctx *vk = p->vk; - if (!p->swapchain) + struct pl_swapchain_frame frame; + if (!pl_swapchain_start_frame(p->swapchain, &frame)) + return false; + if (!mppl_wrap_tex(sw->ctx->ra, frame.fbo, &p->proxy_tex)) return false; - if (p->queued_fbo.tex) { - assert(out_fbo != &p->queued_fbo); - *out_fbo = p->queued_fbo; - p->queued_fbo = (struct ra_fbo) {0}; - return true; - } - - VkSemaphore sem_in = p->sems_in[p->idx_sems]; - MP_TRACE(vk, "vkAcquireNextImageKHR signals %p\n", (void *)sem_in); - - for (int attempts = 0; attempts < 2; attempts++) { - uint32_t imgidx = 0; - VkResult res = vkAcquireNextImageKHR(vk->dev, p->swapchain, UINT64_MAX, - sem_in, NULL, &imgidx); - - switch (res) { - case VK_SUCCESS: - p->last_imgidx = imgidx; - *out_fbo = (struct ra_fbo) { - .tex = p->images[imgidx], - .flip = false, - }; - ra_tex_vk_external_dep(sw->ctx->ra, out_fbo->tex, sem_in); - return true; - - case VK_ERROR_OUT_OF_DATE_KHR: { - // In these cases try recreating the swapchain - int w = p->w, h = p->h; - p->w = p->h = 0; // invalidate the current state - if (!ra_vk_ctx_resize(sw, w, h)) - return false; - continue; - } - - default: - MP_ERR(vk, "Failed acquiring swapchain image: %s\n", vk_err(res)); - return false; - } - } - - // If we've exhausted the number of attempts to recreate the swapchain, - // just give up silently. - return false; -} + *out_fbo = (struct ra_fbo) { + .tex = &p->proxy_tex, + .flip = frame.flipped, + }; -static void present_cb(struct priv *p, void *arg) -{ - p->frames_in_flight--; + return true; } static bool submit_frame(struct ra_swapchain *sw, const struct vo_frame *frame) { struct priv *p = sw->priv; - struct ra *ra = sw->ctx->ra; - struct mpvk_ctx *vk = p->vk; - if (!p->swapchain) - return false; - - struct vk_cmd *cmd = ra_vk_submit(ra, p->images[p->last_imgidx]); - if (!cmd) - return false; - - VkSemaphore sem_out = p->sems_out[p->idx_sems++]; - p->idx_sems %= p->num_sems; - vk_cmd_sig(cmd, sem_out); - - p->frames_in_flight++; - vk_cmd_callback(cmd, (vk_cb) present_cb, p, NULL); - - vk_cmd_queue(vk, cmd); - if (!mpvk_flush_commands(vk)) - return false; - - // Submit to the same queue that we were currently rendering to - struct vk_cmdpool *pool_gfx = vk->pool_graphics; - VkQueue queue = pool_gfx->queues[pool_gfx->idx_queues]; - - // Rotate the queues to ensure good parallelism across frames - for (int i = 0; i < vk->num_pools; i++) { - struct vk_cmdpool *pool = vk->pools[i]; - pool->idx_queues = (pool->idx_queues + 1) % pool->num_queues; - } - - VkPresentInfoKHR pinfo = { - .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, - .waitSemaphoreCount = 1, - .pWaitSemaphores = &sem_out, - .swapchainCount = 1, - .pSwapchains = &p->swapchain, - .pImageIndices = &p->last_imgidx, - }; - - MP_TRACE(vk, "vkQueuePresentKHR waits on %p\n", (void *)sem_out); - VkResult res = vkQueuePresentKHR(queue, &pinfo); - switch (res) { - case VK_SUCCESS: - case VK_SUBOPTIMAL_KHR: - return true; - - case VK_ERROR_OUT_OF_DATE_KHR: - // We can silently ignore this error, since the next start_frame will - // recreate the swapchain automatically. - return true; - - default: - MP_ERR(vk, "Failed presenting to queue %p: %s\n", (void *)queue, - vk_err(res)); - return false; - } + return pl_swapchain_submit_frame(p->swapchain); } static void swap_buffers(struct ra_swapchain *sw) { struct priv *p = sw->priv; - - while (p->frames_in_flight >= sw->ctx->opts.swapchain_depth) - mpvk_poll_commands(p->vk, 100000); // 100μs - - // Also try and block until the next hardware buffer swap early. this - // prevents start_frame from blocking later, thus slightly improving the - // frame timing stats. (since mpv assumes most blocking will happen in - // swap_buffers) - start_frame(sw, &p->queued_fbo); + pl_swapchain_swap_buffers(p->swapchain); } static const struct ra_swapchain_fns vulkan_swapchain = { diff --git a/video/out/vulkan/context.h b/video/out/vulkan/context.h index a64d39f125..30c97cfb4f 100644 --- a/video/out/vulkan/context.h +++ b/video/out/vulkan/context.h @@ -7,7 +7,9 @@ void ra_vk_ctx_uninit(struct ra_ctx *ctx); bool ra_vk_ctx_init(struct ra_ctx *ctx, struct mpvk_ctx *vk, VkPresentModeKHR preferred_mode); -bool ra_vk_ctx_resize(struct ra_swapchain *sw, int w, int h); + +// Handles a resize request, and updates ctx->vo->dwidth/dheight +bool ra_vk_ctx_resize(struct ra_ctx *ctx, int width, int height); // May be called on a ra_ctx of any type. struct mpvk_ctx *ra_vk_ctx_get(struct ra_ctx *ctx); diff --git a/video/out/vulkan/context_wayland.c b/video/out/vulkan/context_wayland.c index 7276775242..f1091a534f 100644 --- a/video/out/vulkan/context_wayland.c +++ b/video/out/vulkan/context_wayland.c @@ -41,8 +41,7 @@ static bool wayland_vk_init(struct ra_ctx *ctx) struct mpvk_ctx *vk = &p->vk; int msgl = ctx->opts.probing ? MSGL_V : MSGL_ERR; - if (!mpvk_instance_init(vk, ctx->log, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, - ctx->opts.debug)) + if (!mpvk_init(vk, ctx, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME)) goto error; if (!vo_wayland_init(ctx->vo)) @@ -54,10 +53,10 @@ static bool wayland_vk_init(struct ra_ctx *ctx) .surface = ctx->vo->wl->surface, }; - VkResult res = vkCreateWaylandSurfaceKHR(vk->inst, &wlinfo, MPVK_ALLOCATOR, - &vk->surf); + VkInstance inst = vk->vkinst->instance; + VkResult res = vkCreateWaylandSurfaceKHR(inst, &wlinfo, NULL, &vk->surface); if (res != VK_SUCCESS) { - MP_MSG(ctx, msgl, "Failed creating Wayland surface: %s\n", vk_err(res)); + MP_MSG(ctx, msgl, "Failed creating Wayland surface\n"); goto error; } @@ -77,7 +76,7 @@ error: return false; } -static void resize(struct ra_ctx *ctx) +static bool resize(struct ra_ctx *ctx) { struct vo_wayland_state *wl = ctx->vo->wl; @@ -87,9 +86,7 @@ static void resize(struct ra_ctx *ctx) const int32_t height = wl->scaling*mp_rect_h(wl->geometry); wl_surface_set_buffer_scale(wl->surface, wl->scaling); - - wl->vo->dwidth = width; - wl->vo->dheight = height; + return ra_vk_ctx_resize(ctx, width, height); } static bool wayland_vk_reconfig(struct ra_ctx *ctx) @@ -104,8 +101,7 @@ static int wayland_vk_control(struct ra_ctx *ctx, int *events, int request, void { int ret = vo_wayland_control(ctx->vo, events, request, arg); if (*events & VO_EVENT_RESIZE) { - resize(ctx); - if (ra_vk_ctx_resize(ctx->swapchain, ctx->vo->dwidth, ctx->vo->dheight)) + if (!resize(ctx)) return VO_ERROR; } return ret; diff --git a/video/out/vulkan/context_win.c b/video/out/vulkan/context_win.c deleted file mode 100644 index cf31586d00..0000000000 --- a/video/out/vulkan/context_win.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "video/out/gpu/context.h" -#include "video/out/w32_common.h" - -#include "common.h" -#include "context.h" -#include "utils.h" - -EXTERN_C IMAGE_DOS_HEADER __ImageBase; -#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase) - -struct priv { - struct mpvk_ctx vk; -}; - -static void win_uninit(struct ra_ctx *ctx) -{ - struct priv *p = ctx->priv; - - ra_vk_ctx_uninit(ctx); - mpvk_uninit(&p->vk); - vo_w32_uninit(ctx->vo); -} - -static bool win_init(struct ra_ctx *ctx) -{ - struct priv *p = ctx->priv = talloc_zero(ctx, struct priv); - struct mpvk_ctx *vk = &p->vk; - int msgl = ctx->opts.probing ? MSGL_V : MSGL_ERR; - - if (!mpvk_instance_init(vk, ctx->log, VK_KHR_WIN32_SURFACE_EXTENSION_NAME, - ctx->opts.debug)) - goto error; - - if (!vo_w32_init(ctx->vo)) - goto error; - - VkWin32SurfaceCreateInfoKHR wininfo = { - .sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, - .hinstance = HINST_THISCOMPONENT, - .hwnd = vo_w32_hwnd(ctx->vo), - }; - - VkResult res = vkCreateWin32SurfaceKHR(vk->inst, &wininfo, MPVK_ALLOCATOR, - &vk->surf); - if (res != VK_SUCCESS) { - MP_MSG(ctx, msgl, "Failed creating Windows surface: %s\n", vk_err(res)); - goto error; - } - - if (!ra_vk_ctx_init(ctx, vk, VK_PRESENT_MODE_FIFO_KHR)) - goto error; - - return true; - -error: - win_uninit(ctx); - return false; -} - -static bool resize(struct ra_ctx *ctx) -{ - return ra_vk_ctx_resize(ctx->swapchain, ctx->vo->dwidth, ctx->vo->dheight); -} - -static bool win_reconfig(struct ra_ctx *ctx) -{ - vo_w32_config(ctx->vo); - return resize(ctx); -} - -static int win_control(struct ra_ctx *ctx, int *events, int request, void *arg) -{ - int ret = vo_w32_control(ctx->vo, events, request, arg); - if (*events & VO_EVENT_RESIZE) { - if (!resize(ctx)) - return VO_ERROR; - } - return ret; -} - -const struct ra_ctx_fns ra_ctx_vulkan_win = { - .type = "vulkan", - .name = "winvk", - .reconfig = win_reconfig, - .control = win_control, - .init = win_init, - .uninit = win_uninit, -}; diff --git a/video/out/vulkan/context_xlib.c b/video/out/vulkan/context_xlib.c index c3bd49f4fb..9baa7c4dc4 100644 --- a/video/out/vulkan/context_xlib.c +++ b/video/out/vulkan/context_xlib.c @@ -41,8 +41,7 @@ static bool xlib_init(struct ra_ctx *ctx) struct mpvk_ctx *vk = &p->vk; int msgl = ctx->opts.probing ? MSGL_V : MSGL_ERR; - if (!mpvk_instance_init(vk, ctx->log, VK_KHR_XLIB_SURFACE_EXTENSION_NAME, - ctx->opts.debug)) + if (!mpvk_init(vk, ctx, VK_KHR_XLIB_SURFACE_EXTENSION_NAME)) goto error; if (!vo_x11_init(ctx->vo)) @@ -57,10 +56,10 @@ static bool xlib_init(struct ra_ctx *ctx) .window = ctx->vo->x11->window, }; - VkResult res = vkCreateXlibSurfaceKHR(vk->inst, &xinfo, MPVK_ALLOCATOR, - &vk->surf); + VkInstance inst = vk->vkinst->instance; + VkResult res = vkCreateXlibSurfaceKHR(inst, &xinfo, NULL, &vk->surface); if (res != VK_SUCCESS) { - MP_MSG(ctx, msgl, "Failed creating Xlib surface: %s\n", vk_err(res)); + MP_MSG(ctx, msgl, "Failed creating Xlib surface\n"); goto error; } @@ -76,7 +75,7 @@ error: static bool resize(struct ra_ctx *ctx) { - return ra_vk_ctx_resize(ctx->swapchain, ctx->vo->dwidth, ctx->vo->dheight); + return ra_vk_ctx_resize(ctx, ctx->vo->dwidth, ctx->vo->dheight); } static bool xlib_reconfig(struct ra_ctx *ctx) diff --git a/video/out/vulkan/formats.c b/video/out/vulkan/formats.c deleted file mode 100644 index 327a7ac809..0000000000 --- a/video/out/vulkan/formats.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "formats.h" - -const struct vk_format vk_formats[] = { - // Regular, byte-aligned integer formats - {"r8", VK_FORMAT_R8_UNORM, 1, 1, {8 }, RA_CTYPE_UNORM }, - {"rg8", VK_FORMAT_R8G8_UNORM, 2, 2, {8, 8 }, RA_CTYPE_UNORM }, - {"rgb8", VK_FORMAT_R8G8B8_UNORM, 3, 3, {8, 8, 8 }, RA_CTYPE_UNORM }, - {"rgba8", VK_FORMAT_R8G8B8A8_UNORM, 4, 4, {8, 8, 8, 8 }, RA_CTYPE_UNORM }, - {"r16", VK_FORMAT_R16_UNORM, 1, 2, {16 }, RA_CTYPE_UNORM }, - {"rg16", VK_FORMAT_R16G16_UNORM, 2, 4, {16, 16 }, RA_CTYPE_UNORM }, - {"rgb16", VK_FORMAT_R16G16B16_UNORM, 3, 6, {16, 16, 16 }, RA_CTYPE_UNORM }, - {"rgba16", VK_FORMAT_R16G16B16A16_UNORM, 4, 8, {16, 16, 16, 16}, RA_CTYPE_UNORM }, - - // Special, integer- |