Skip to content

Commit

Permalink
vo_gpu: vulkan: initial implementation
Browse files Browse the repository at this point in the history
This time based on ra/vo_gpu. 2017 is the year of the vulkan desktop!

Current problems / limitations / improvement opportunities:

1. The swapchain/flipping code violates the vulkan spec, by assuming
   that the presentation queue will be bounded (in cases where rendering
   is significantly faster than vsync). But apparently, there's simply
   no better way to do this right now, to the point where even the
   stupid cube.c examples from LunarG etc. do it wrong.
   (cf. KhronosGroup/Vulkan-Docs#370)

2. The memory allocator could be improved. (This is a universal
   constant)

3. Could explore using push descriptors instead of descriptor sets,
   especially since we expect to switch descriptors semi-often for some
   passes (like interpolation). Probably won't make a difference, but
   the synchronization overhead might be a factor. Who knows.

vo_gpu: vulkan: implement ra_vk_ctx.depth

Also moved the depth querying for vo_gpu from preinit to resize, since
it was a tiny bit more convenient. (And in theory, it could change during
runtime anyway)

This only affects a calculation in the dither code path anyway.
  • Loading branch information
haasn committed Sep 20, 2017
1 parent a97080c commit 445ded0
Show file tree
Hide file tree
Showing 20 changed files with 3,736 additions and 15 deletions.
5 changes: 5 additions & 0 deletions options/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ extern const struct m_obj_list vo_obj_list;
extern const struct m_obj_list ao_obj_list;

extern const struct m_sub_options opengl_conf;
extern const struct m_sub_options vulkan_conf;
extern const struct m_sub_options angle_conf;
extern const struct m_sub_options cocoa_conf;

Expand Down Expand Up @@ -691,6 +692,10 @@ const m_option_t mp_opts[] = {
OPT_SUBSTRUCT("", opengl_opts, opengl_conf, 0),
#endif

#if HAVE_VULKAN
OPT_SUBSTRUCT("", vulkan_opts, vulkan_conf, 0),
#endif

#if HAVE_EGL_ANGLE_WIN32
OPT_SUBSTRUCT("", angle_opts, angle_conf, 0),
#endif
Expand Down
1 change: 1 addition & 0 deletions options/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ typedef struct MPOpts {
struct gl_video_opts *gl_video_opts;
struct angle_opts *angle_opts;
struct opengl_opts *opengl_opts;
struct vulkan_opts *vulkan_opts;
struct cocoa_opts *cocoa_opts;
struct dvd_opts *dvd_opts;

Expand Down
8 changes: 8 additions & 0 deletions video/out/gpu/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ extern const struct ra_ctx_fns ra_ctx_dxgl;
extern const struct ra_ctx_fns ra_ctx_rpi;
extern const struct ra_ctx_fns ra_ctx_mali;
extern const struct ra_ctx_fns ra_ctx_vdpauglx;
extern const struct ra_ctx_fns ra_ctx_vulkan_xlib;

static const struct ra_ctx_fns *contexts[] = {
// OpenGL contexts:
Expand Down Expand Up @@ -83,6 +84,13 @@ static const struct ra_ctx_fns *contexts[] = {
#if HAVE_VDPAU_GL_X11
&ra_ctx_vdpauglx,
#endif

// Vulkan contexts:
#if HAVE_VULKAN
#if HAVE_X11
&ra_ctx_vulkan_xlib,
#endif
#endif
};

static bool get_help(struct mp_log *log, struct bstr param)
Expand Down
4 changes: 3 additions & 1 deletion video/out/gpu/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ struct ra_swchain_fns {
void (*update_length)(struct ra_swchain *sw, int depth);

// Called when rendering starts. Returns NULL on failure. This must be
// followed by submit_frame, to submit the rendered frame.
// followed by submit_frame, to submit the rendered frame. This function
// can also fail sporadically, and such errors should be ignored unless
// they persist.
struct ra_tex *(*start_frame)(struct ra_swchain *sw);

// Present the frame. Issued in lockstep with start_frame, with rendering
Expand Down
9 changes: 5 additions & 4 deletions video/out/gpu/ra.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ enum ra_buf_type {
RA_BUF_TYPE_TEX_UPLOAD, // texture upload buffer (pixel buffer object)
RA_BUF_TYPE_SHADER_STORAGE, // shader buffer (SSBO), for RA_VARTYPE_BUF_RW
RA_BUF_TYPE_UNIFORM, // uniform buffer (UBO), for RA_VARTYPE_BUF_RO
RA_BUF_TYPE_VERTEX, // not publicly usable (RA-internal usage)
};

struct ra_buf_params {
Expand Down Expand Up @@ -369,10 +370,10 @@ struct ra_fns {

void (*buf_destroy)(struct ra *ra, struct ra_buf *buf);

// Update the contents of a buffer, starting at a given offset and up to a
// given size, with the contents of *data. This is an extremely common
// operation. Calling this while the buffer is considered "in use" is an
// error. (See: buf_poll)
// Update the contents of a buffer, starting at a given offset (*must* be a
// multiple of 4) and up to a given size, with the contents of *data. This
// is an extremely common operation. Calling this while the buffer is
// considered "in use" is an error. (See: buf_poll)
void (*buf_update)(struct ra *ra, struct ra_buf *buf, ptrdiff_t offset,
const void *data, size_t size);

Expand Down
16 changes: 7 additions & 9 deletions video/out/vo_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ struct gpu_priv {
static void resize(struct gpu_priv *p)
{
struct vo *vo = p->vo;
struct ra_swchain *sw = p->ctx->swchain;

MP_VERBOSE(vo, "Resize: %dx%d\n", vo->dwidth, vo->dheight);

Expand All @@ -68,6 +69,11 @@ static void resize(struct gpu_priv *p)

gl_video_resize(p->renderer, &src, &dst, &osd);

int fb_depth = sw->fns->color_depth ? sw->fns->color_depth(sw) : 0;
if (fb_depth)
MP_VERBOSE(p, "Reported display depth: %d\n", fb_depth);
gl_video_set_fb_depth(p->renderer, fb_depth);

vo->want_redraw = true;
}

Expand All @@ -77,10 +83,8 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
struct ra_swchain *sw = p->ctx->swchain;

struct ra_tex *tex = sw->fns->start_frame(sw);
if (!tex) {
MP_ERR(vo, "Failed starting frame!\n");
if (!tex)
return;
}

struct fbodst dst = {
.tex = tex,
Expand Down Expand Up @@ -298,7 +302,6 @@ static int preinit(struct vo *vo)
goto err_out;
assert(p->ctx->ra);
assert(p->ctx->swchain);
struct ra_swchain *sw = p->ctx->swchain;

p->renderer = gl_video_init(p->ctx->ra, vo->log, vo->global);
gl_video_set_osd_source(p->renderer, vo->osd);
Expand All @@ -314,11 +317,6 @@ static int preinit(struct vo *vo)
vo->hwdec_devs, vo->opts->gl_hwdec_interop);
gl_video_set_hwdec(p->renderer, p->hwdec);

int fb_depth = sw->fns->color_depth ? sw->fns->color_depth(sw) : 0;
if (fb_depth)
MP_VERBOSE(p, "Reported display depth: %d\n", fb_depth);
gl_video_set_fb_depth(p->renderer, fb_depth);

return 0;

err_out:
Expand Down
52 changes: 52 additions & 0 deletions video/out/vulkan/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#pragma once

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>

#include "config.h"

#include "common/common.h"
#include "common/msg.h"

// We need to define all platforms we want to support. Since we have
// our own mechanism for checking this, we re-define the right symbols
#if HAVE_X11
#define VK_USE_PLATFORM_XLIB_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

// 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 vk_cmdpool *pool; // primary command pool for this device
struct vk_cmdpool *pool_transfer; // pool for async transfers (optional)
struct vk_cmd *last_cmd; // most recently submitted command

// Cached capabilities
VkPhysicalDeviceLimits limits;
};
Loading

0 comments on commit 445ded0

Please sign in to comment.