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. Use async compute on supported devices.

4. Could/should use sub-command buffers instead of semaphores/switching
   for stuff involving multiple queue families.

5. 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.
  • Loading branch information
haasn committed Sep 16, 2017
1 parent 1088d0e commit 890f479
Show file tree
Hide file tree
Showing 20 changed files with 3,702 additions and 10 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 @@ -695,6 +696,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 @@ -331,6 +331,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
7 changes: 7 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 @@ -87,10 +88,16 @@ static const struct ra_ctx_fns *contexts[] = {
#if HAVE_VDPAU_GL_X11
&ra_ctx_vdpauglx,
#endif

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

static const char *type_names[] = {
[RA_API_OPENGL] = "opengl",
[RA_API_VULKAN] = "vulkan",
};

int ra_ctx_validate_context(struct mp_log *log, const struct m_option *opt,
Expand Down
9 changes: 8 additions & 1 deletion video/out/gpu/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
enum ra_api_type {
RA_API_ANY = 0,
RA_API_OPENGL,
RA_API_VULKAN,
};

// Essentially a bit mask of what GL types to allow
Expand Down Expand Up @@ -50,6 +51,10 @@ struct ra_ctx {
#if HAVE_GL
struct ra_gl_ctx *gl_priv;
#endif

#if HAVE_VULKAN
struct ra_vk_ctx *vk_priv;
#endif
};

// The functions that make up a ra_ctx.
Expand All @@ -70,7 +75,9 @@ struct ra_ctx_fns {
struct mp_image *(*screenshot)(struct ra_ctx *ctx);

// Called when rendering starts. Returns NULL on failure. This must be
// followed by present_frame, to submit the rendered frame.
// followed by present_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_ctx *ctx);

// 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
7 changes: 3 additions & 4 deletions video/out/vo_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,8 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
struct gpu_priv *p = vo->priv;

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

struct fbodst dst = {
.tex = tex,
Expand Down Expand Up @@ -322,7 +320,8 @@ static const m_option_t options[] = {
ra_ctx_validate_context),
OPT_CHOICE("gpu-api", context_type, 0,
({"auto", RA_API_ANY},
{"opengl", RA_API_OPENGL})),
{"opengl", RA_API_OPENGL},
{"vulkan", RA_API_VULKAN})),
OPT_CHOICE("opengl-es", opts.gl_flags, 0,
({"auto", RA_GL_ANY},
{"yes", RA_GL_ANY_ES},
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_VULKAN_XLIB
#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 890f479

Please sign in to comment.