mirror of
https://github.com/mpv-player/mpv
synced 2025-04-01 00:07:33 +00:00
vf_gpu: vulkan and egl implementations
Abstract out EGL, and allow choosing between EGL and vulkan at runtime. vf_gpu_egl.c contains GL specific context and creation/destroy code, vf_gpu_vulkan.c contains Vulkan specific. This allows vf_gpu being built in systems where EGL is not available and where Vulkan is available.
This commit is contained in:
parent
773c5e2ae0
commit
d9c5aef98d
@ -94,7 +94,7 @@ const struct mp_user_filter_entry *vf_list[] = {
|
|||||||
#if HAVE_D3D_HWACCEL
|
#if HAVE_D3D_HWACCEL
|
||||||
&vf_d3d11vpp,
|
&vf_d3d11vpp,
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_GL && HAVE_EGL
|
#if (HAVE_GL && HAVE_EGL) || HAVE_VULKAN
|
||||||
&vf_gpu,
|
&vf_gpu,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
@ -1249,7 +1249,7 @@ if features['egl'] or features['egl-android'] or features['egl-angle-win32']
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
if features['gl'] and features['egl']
|
if features['gl'] and features['egl']
|
||||||
sources += files('video/filter/vf_gpu.c')
|
sources += files('video/filter/vf_gpu_egl.c')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if features['gl']
|
if features['gl']
|
||||||
@ -1274,7 +1274,8 @@ features += {'vulkan': vulkan.found()}
|
|||||||
if features['vulkan']
|
if features['vulkan']
|
||||||
dependencies += vulkan
|
dependencies += vulkan
|
||||||
sources += files('video/out/vulkan/context.c',
|
sources += files('video/out/vulkan/context.c',
|
||||||
'video/out/vulkan/utils.c')
|
'video/out/vulkan/utils.c',
|
||||||
|
'video/filter/vf_gpu_vulkan.c')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if features['vulkan'] and features['android']
|
if features['vulkan'] and features['android']
|
||||||
@ -1299,6 +1300,10 @@ if features['vk-khr-display']
|
|||||||
sources += files('video/out/vulkan/context_display.c')
|
sources += files('video/out/vulkan/context_display.c')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if features['vulkan'] or (features['gl'] and features['egl'])
|
||||||
|
sources += files('video/filter/vf_gpu.c')
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
# hwaccel
|
# hwaccel
|
||||||
ffnvcodec = dependency('ffnvcodec', version: '>= 11.1.5.1', required: false)
|
ffnvcodec = dependency('ffnvcodec', version: '>= 11.1.5.1', required: false)
|
||||||
|
@ -24,95 +24,49 @@
|
|||||||
#include "options/options.h"
|
#include "options/options.h"
|
||||||
#include "video/out/aspect.h"
|
#include "video/out/aspect.h"
|
||||||
#include "video/out/gpu/video.h"
|
#include "video/out/gpu/video.h"
|
||||||
#include "video/out/opengl/egl_helpers.h"
|
#include "video/filter/vf_gpu.h"
|
||||||
#include "video/out/opengl/ra_gl.h"
|
|
||||||
|
|
||||||
struct offscreen_ctx {
|
extern const struct offscreen_context offscreen_vk;
|
||||||
struct mp_log *log;
|
extern const struct offscreen_context offscreen_egl;
|
||||||
struct ra *ra;
|
|
||||||
void *priv;
|
|
||||||
|
|
||||||
void (*set_context)(struct offscreen_ctx *ctx, bool enable);
|
static const struct offscreen_context *contexts[] = {
|
||||||
|
#if HAVE_EGL
|
||||||
|
&offscreen_egl,
|
||||||
|
#endif
|
||||||
|
#if HAVE_VULKAN
|
||||||
|
&offscreen_vk,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gl_offscreen_ctx {
|
static inline OPT_STRING_VALIDATE_FUNC(offscreen_ctx_validate_api)
|
||||||
GL gl;
|
|
||||||
EGLDisplay egl_display;
|
|
||||||
EGLContext egl_context;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void gl_ctx_destroy(void *p)
|
|
||||||
{
|
{
|
||||||
struct offscreen_ctx *ctx = p;
|
struct bstr param = bstr0(*value);
|
||||||
struct gl_offscreen_ctx *gl = ctx->priv;
|
for (int i = 0; i < MP_ARRAY_SIZE(contexts); i++) {
|
||||||
|
if (bstr_equals0(param, contexts[i]->api))
|
||||||
ra_free(&ctx->ra);
|
return 1;
|
||||||
|
}
|
||||||
if (gl->egl_context)
|
return M_OPT_INVALID;
|
||||||
eglDestroyContext(gl->egl_display, gl->egl_context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gl_ctx_set_context(struct offscreen_ctx *ctx, bool enable)
|
static int offscreen_ctx_api_help(struct mp_log *log, const struct m_option *opt,
|
||||||
|
struct bstr name)
|
||||||
{
|
{
|
||||||
struct gl_offscreen_ctx *gl = ctx->priv;
|
mp_info(log, "GPU APIs (offscreen contexts):\n");
|
||||||
EGLContext c = enable ? gl->egl_context : EGL_NO_CONTEXT;
|
for (int i = 0; i < MP_ARRAY_SIZE(contexts); i++)
|
||||||
|
mp_info(log, " %s\n", contexts[i]->api);
|
||||||
if (!eglMakeCurrent(gl->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, c))
|
return M_OPT_EXIT;
|
||||||
MP_ERR(ctx, "Could not make EGL context current.\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct offscreen_ctx *gl_offscreen_ctx_create(struct mpv_global *global,
|
static struct offscreen_ctx *offscreen_ctx_create(struct mpv_global *global,
|
||||||
struct mp_log *log)
|
struct mp_log *log,
|
||||||
|
const char *api)
|
||||||
{
|
{
|
||||||
struct offscreen_ctx *ctx = talloc_zero(NULL, struct offscreen_ctx);
|
for (int i = 0; i < MP_ARRAY_SIZE(contexts); i++) {
|
||||||
struct gl_offscreen_ctx *gl = talloc_zero(ctx, struct gl_offscreen_ctx);
|
if (api && strcmp(contexts[i]->api, api) != 0)
|
||||||
talloc_set_destructor(ctx, gl_ctx_destroy);
|
continue;
|
||||||
*ctx = (struct offscreen_ctx){
|
mp_info(log, "Creating offscreen GPU context '%s'\n", contexts[i]->api);
|
||||||
.log = log,
|
return contexts[i]->offscreen_ctx_create(global, log);
|
||||||
.priv = gl,
|
|
||||||
.set_context = gl_ctx_set_context,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This appears to work with Mesa. EGL 1.5 doesn't specify what a "default
|
|
||||||
// display" is at all.
|
|
||||||
gl->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
|
||||||
if (!eglInitialize(gl->egl_display, NULL, NULL)) {
|
|
||||||
MP_ERR(ctx, "Could not initialize EGL.\n");
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unfortunately, mpegl_create_context() is entangled with ra_ctx.
|
|
||||||
// Fortunately, it does not need much, and we can provide a stub.
|
|
||||||
struct ra_ctx ractx = {
|
|
||||||
.log = ctx->log,
|
|
||||||
.global = global,
|
|
||||||
};
|
|
||||||
EGLConfig config;
|
|
||||||
if (!mpegl_create_context(&ractx, gl->egl_display, &gl->egl_context, &config))
|
|
||||||
{
|
|
||||||
MP_ERR(ctx, "Could not create EGL context.\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!eglMakeCurrent(gl->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
|
||||||
gl->egl_context))
|
|
||||||
{
|
|
||||||
MP_ERR(ctx, "Could not make EGL context current.\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
mpegl_load_functions(&gl->gl, ctx->log);
|
|
||||||
ctx->ra = ra_create_gl(&gl->gl, ctx->log);
|
|
||||||
|
|
||||||
if (!ctx->ra)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
gl_ctx_set_context(ctx, false);
|
|
||||||
|
|
||||||
return ctx;
|
|
||||||
|
|
||||||
error:
|
|
||||||
talloc_free(ctx);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,6 +78,7 @@ static void offscreen_ctx_set_current(struct offscreen_ctx *ctx, bool enable)
|
|||||||
|
|
||||||
struct gpu_opts {
|
struct gpu_opts {
|
||||||
int w, h;
|
int w, h;
|
||||||
|
char *api;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct priv {
|
struct priv {
|
||||||
@ -327,7 +282,7 @@ static struct mp_filter *gpu_create(struct mp_filter *parent, void *options)
|
|||||||
priv->vo_opts_cache = m_config_cache_alloc(f, f->global, &vo_sub_opts);
|
priv->vo_opts_cache = m_config_cache_alloc(f, f->global, &vo_sub_opts);
|
||||||
priv->vo_opts = priv->vo_opts_cache->opts;
|
priv->vo_opts = priv->vo_opts_cache->opts;
|
||||||
|
|
||||||
priv->ctx = gl_offscreen_ctx_create(f->global, f->log);
|
priv->ctx = offscreen_ctx_create(f->global, f->log, priv->opts->api);
|
||||||
if (!priv->ctx) {
|
if (!priv->ctx) {
|
||||||
MP_FATAL(f, "Could not create offscreen ra context.\n");
|
MP_FATAL(f, "Could not create offscreen ra context.\n");
|
||||||
goto error;
|
goto error;
|
||||||
@ -368,6 +323,8 @@ const struct mp_user_filter_entry vf_gpu = {
|
|||||||
.options = (const struct m_option[]){
|
.options = (const struct m_option[]){
|
||||||
{"w", OPT_INT(w)},
|
{"w", OPT_INT(w)},
|
||||||
{"h", OPT_INT(h)},
|
{"h", OPT_INT(h)},
|
||||||
|
{"api", OPT_STRING_VALIDATE(api, offscreen_ctx_validate_api),
|
||||||
|
.help = offscreen_ctx_api_help},
|
||||||
{0}
|
{0}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
35
video/filter/vf_gpu.h
Normal file
35
video/filter/vf_gpu.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/common.h"
|
||||||
|
#include "common/global.h"
|
||||||
|
|
||||||
|
struct offscreen_ctx {
|
||||||
|
struct mp_log *log;
|
||||||
|
struct ra *ra;
|
||||||
|
void *priv;
|
||||||
|
|
||||||
|
void (*set_context)(struct offscreen_ctx *ctx, bool enable);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct offscreen_context {
|
||||||
|
const char *api;
|
||||||
|
struct offscreen_ctx *(*offscreen_ctx_create)(struct mpv_global *,
|
||||||
|
struct mp_log *);
|
||||||
|
};
|
107
video/filter/vf_gpu_egl.c
Normal file
107
video/filter/vf_gpu_egl.c
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* 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 "common/common.h"
|
||||||
|
#include "video/filter/vf_gpu.h"
|
||||||
|
#include "video/out/opengl/egl_helpers.h"
|
||||||
|
#include "video/out/opengl/ra_gl.h"
|
||||||
|
|
||||||
|
struct gl_offscreen_ctx {
|
||||||
|
GL gl;
|
||||||
|
EGLDisplay egl_display;
|
||||||
|
EGLContext egl_context;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gl_ctx_destroy(void *p)
|
||||||
|
{
|
||||||
|
struct offscreen_ctx *ctx = p;
|
||||||
|
struct gl_offscreen_ctx *gl = ctx->priv;
|
||||||
|
|
||||||
|
ra_free(&ctx->ra);
|
||||||
|
|
||||||
|
if (gl->egl_context)
|
||||||
|
eglDestroyContext(gl->egl_display, gl->egl_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gl_ctx_set_context(struct offscreen_ctx *ctx, bool enable)
|
||||||
|
{
|
||||||
|
struct gl_offscreen_ctx *gl = ctx->priv;
|
||||||
|
EGLContext c = enable ? gl->egl_context : EGL_NO_CONTEXT;
|
||||||
|
|
||||||
|
if (!eglMakeCurrent(gl->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, c))
|
||||||
|
MP_ERR(ctx, "Could not make EGL context current.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct offscreen_ctx *gl_offscreen_ctx_create(struct mpv_global *global,
|
||||||
|
struct mp_log *log)
|
||||||
|
{
|
||||||
|
struct offscreen_ctx *ctx = talloc(NULL, struct offscreen_ctx);
|
||||||
|
struct gl_offscreen_ctx *gl = talloc_zero(ctx, struct gl_offscreen_ctx);
|
||||||
|
talloc_set_destructor(ctx, gl_ctx_destroy);
|
||||||
|
*ctx = (struct offscreen_ctx){
|
||||||
|
.log = log,
|
||||||
|
.priv = gl,
|
||||||
|
.set_context = gl_ctx_set_context,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This appears to work with Mesa. EGL 1.5 doesn't specify what a "default
|
||||||
|
// display" is at all.
|
||||||
|
gl->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||||
|
if (!eglInitialize(gl->egl_display, NULL, NULL)) {
|
||||||
|
MP_ERR(ctx, "Could not initialize EGL.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unfortunately, mpegl_create_context() is entangled with ra_ctx.
|
||||||
|
// Fortunately, it does not need much, and we can provide a stub.
|
||||||
|
struct ra_ctx ractx = {
|
||||||
|
.log = ctx->log,
|
||||||
|
.global = global,
|
||||||
|
};
|
||||||
|
EGLConfig config;
|
||||||
|
if (!mpegl_create_context(&ractx, gl->egl_display, &gl->egl_context, &config))
|
||||||
|
{
|
||||||
|
MP_ERR(ctx, "Could not create EGL context.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eglMakeCurrent(gl->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||||
|
gl->egl_context))
|
||||||
|
{
|
||||||
|
MP_ERR(ctx, "Could not make EGL context current.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpegl_load_functions(&gl->gl, ctx->log);
|
||||||
|
ctx->ra = ra_create_gl(&gl->gl, ctx->log);
|
||||||
|
|
||||||
|
if (!ctx->ra)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
gl_ctx_set_context(ctx, false);
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
|
||||||
|
error:
|
||||||
|
talloc_free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct offscreen_context offscreen_egl = {
|
||||||
|
.api = "egl",
|
||||||
|
.offscreen_ctx_create = gl_offscreen_ctx_create
|
||||||
|
};
|
115
video/filter/vf_gpu_vulkan.c
Normal file
115
video/filter/vf_gpu_vulkan.c
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* 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 "options/m_config.h"
|
||||||
|
#include "video/filter/vf_gpu.h"
|
||||||
|
#include "video/out/placebo/ra_pl.h"
|
||||||
|
#include "video/out/placebo/utils.h"
|
||||||
|
#include "video/out/vulkan/context.h"
|
||||||
|
#include "video/out/vulkan/utils.h"
|
||||||
|
|
||||||
|
struct vk_offscreen_ctx {
|
||||||
|
struct ra_ctx *ractx;
|
||||||
|
struct mpvk_ctx *vk;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct m_sub_options vulkan_conf;
|
||||||
|
|
||||||
|
static void vk_ctx_destroy(void *p)
|
||||||
|
{
|
||||||
|
struct offscreen_ctx *ctx = p;
|
||||||
|
struct vk_offscreen_ctx *vkctx = ctx->priv;
|
||||||
|
struct ra_ctx *ractx = vkctx->ractx;
|
||||||
|
struct mpvk_ctx *vk = vkctx->vk;
|
||||||
|
|
||||||
|
if (ractx->ra) {
|
||||||
|
pl_gpu_finish(vk->gpu);
|
||||||
|
ractx->ra->fns->destroy(ctx->ra);
|
||||||
|
ractx->ra = NULL;
|
||||||
|
ctx->ra = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vk->gpu = NULL;
|
||||||
|
pl_vulkan_destroy(&vk->vulkan);
|
||||||
|
mpvk_uninit(vk);
|
||||||
|
talloc_free(vk);
|
||||||
|
talloc_free(ractx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct offscreen_ctx *vk_offscreen_ctx_create(struct mpv_global *global,
|
||||||
|
struct mp_log *log)
|
||||||
|
{
|
||||||
|
struct offscreen_ctx *ctx = talloc(NULL, struct offscreen_ctx);
|
||||||
|
talloc_set_destructor(ctx, vk_ctx_destroy);
|
||||||
|
*ctx = (struct offscreen_ctx){
|
||||||
|
.log = log,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ra_ctx *ractx = talloc_zero(ctx, struct ra_ctx);
|
||||||
|
struct mpvk_ctx *vk = talloc_zero(ctx, struct mpvk_ctx);
|
||||||
|
ractx->log = ctx->log;
|
||||||
|
ractx->global = global;
|
||||||
|
|
||||||
|
vk->pllog = mppl_log_create(ctx, log);
|
||||||
|
if (!vk->pllog)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
struct pl_vk_inst_params pl_vk_params = {0};
|
||||||
|
struct ra_ctx_opts *ctx_opts = mp_get_config_group(NULL, global, &ra_ctx_conf);
|
||||||
|
pl_vk_params.debug = ctx_opts->debug;
|
||||||
|
talloc_free(ctx_opts);
|
||||||
|
mppl_log_set_probing(vk->pllog, true);
|
||||||
|
vk->vkinst = pl_vk_inst_create(vk->pllog, &pl_vk_params);
|
||||||
|
mppl_log_set_probing(vk->pllog, false);
|
||||||
|
if (!vk->vkinst)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
struct vulkan_opts *vk_opts = mp_get_config_group(NULL, global, &vulkan_conf);
|
||||||
|
vk->vulkan = mppl_create_vulkan(vk_opts, vk->vkinst, vk->pllog, NULL);
|
||||||
|
talloc_free(vk_opts);
|
||||||
|
if (!vk->vulkan)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
vk->gpu = vk->vulkan->gpu;
|
||||||
|
ractx->ra = ra_create_pl(vk->gpu, ractx->log);
|
||||||
|
if (!ractx->ra)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
struct vk_offscreen_ctx *vkctx = talloc(ctx, struct vk_offscreen_ctx);
|
||||||
|
*vkctx = (struct vk_offscreen_ctx){
|
||||||
|
.ractx = ractx,
|
||||||
|
.vk = vk
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx->ra = ractx->ra;
|
||||||
|
ctx->priv = vkctx;
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
|
||||||
|
error:
|
||||||
|
pl_vulkan_destroy(&vk->vulkan);
|
||||||
|
mpvk_uninit(vk);
|
||||||
|
talloc_free(vk);
|
||||||
|
talloc_free(ractx);
|
||||||
|
talloc_free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct offscreen_context offscreen_vk = {
|
||||||
|
.api = "vulkan",
|
||||||
|
.offscreen_ctx_create = vk_offscreen_ctx_create
|
||||||
|
};
|
@ -28,7 +28,6 @@
|
|||||||
#include "video/out/placebo/utils.h"
|
#include "video/out/placebo/utils.h"
|
||||||
|
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
struct vulkan_opts {
|
struct vulkan_opts {
|
||||||
char *device; // force a specific GPU
|
char *device; // force a specific GPU
|
||||||
@ -174,19 +173,11 @@ void ra_vk_ctx_uninit(struct ra_ctx *ctx)
|
|||||||
TA_FREEP(&ctx->swapchain);
|
TA_FREEP(&ctx->swapchain);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ra_vk_ctx_init(struct ra_ctx *ctx, struct mpvk_ctx *vk,
|
pl_vulkan mppl_create_vulkan(struct vulkan_opts *opts,
|
||||||
struct ra_vk_ctx_params params,
|
pl_vk_inst vkinst,
|
||||||
VkPresentModeKHR preferred_mode)
|
pl_log pllog,
|
||||||
|
VkSurfaceKHR surface)
|
||||||
{
|
{
|
||||||
struct ra_swapchain *sw = ctx->swapchain = talloc_zero(NULL, struct ra_swapchain);
|
|
||||||
sw->ctx = ctx;
|
|
||||||
sw->fns = &vulkan_swapchain;
|
|
||||||
|
|
||||||
struct priv *p = sw->priv = talloc_zero(sw, struct priv);
|
|
||||||
p->vk = vk;
|
|
||||||
p->params = params;
|
|
||||||
p->opts = mp_get_config_group(p, ctx->global, &vulkan_conf);
|
|
||||||
|
|
||||||
VkPhysicalDeviceFeatures2 features = {
|
VkPhysicalDeviceFeatures2 features = {
|
||||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
|
||||||
};
|
};
|
||||||
@ -224,30 +215,47 @@ bool ra_vk_ctx_init(struct ra_ctx *ctx, struct mpvk_ctx *vk,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
AVUUID param_uuid = { 0 };
|
AVUUID param_uuid = { 0 };
|
||||||
bool is_uuid = p->opts->device &&
|
bool is_uuid = opts->device &&
|
||||||
av_uuid_parse(p->opts->device, param_uuid) == 0;
|
av_uuid_parse(opts->device, param_uuid) == 0;
|
||||||
|
|
||||||
assert(vk->pllog);
|
assert(pllog);
|
||||||
assert(vk->vkinst);
|
assert(vkinst);
|
||||||
struct pl_vulkan_params device_params = {
|
struct pl_vulkan_params device_params = {
|
||||||
.instance = vk->vkinst->instance,
|
.instance = vkinst->instance,
|
||||||
.get_proc_addr = vk->vkinst->get_proc_addr,
|
.get_proc_addr = vkinst->get_proc_addr,
|
||||||
.surface = vk->surface,
|
.surface = surface,
|
||||||
.async_transfer = p->opts->async_transfer,
|
.async_transfer = opts->async_transfer,
|
||||||
.async_compute = p->opts->async_compute,
|
.async_compute = opts->async_compute,
|
||||||
.queue_count = p->opts->queue_count,
|
.queue_count = opts->queue_count,
|
||||||
#if HAVE_VULKAN_INTEROP
|
#if HAVE_VULKAN_INTEROP
|
||||||
.extra_queues = VK_QUEUE_VIDEO_DECODE_BIT_KHR,
|
.extra_queues = VK_QUEUE_VIDEO_DECODE_BIT_KHR,
|
||||||
.opt_extensions = opt_extensions,
|
.opt_extensions = opt_extensions,
|
||||||
.num_opt_extensions = MP_ARRAY_SIZE(opt_extensions),
|
.num_opt_extensions = MP_ARRAY_SIZE(opt_extensions),
|
||||||
#endif
|
#endif
|
||||||
.features = &features,
|
.features = &features,
|
||||||
.device_name = is_uuid ? NULL : p->opts->device,
|
.device_name = is_uuid ? NULL : opts->device,
|
||||||
};
|
};
|
||||||
if (is_uuid)
|
if (is_uuid)
|
||||||
av_uuid_copy(device_params.device_uuid, param_uuid);
|
av_uuid_copy(device_params.device_uuid, param_uuid);
|
||||||
|
|
||||||
vk->vulkan = pl_vulkan_create(vk->pllog, &device_params);
|
return pl_vulkan_create(pllog, &device_params);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ra_vk_ctx_init(struct ra_ctx *ctx, struct mpvk_ctx *vk,
|
||||||
|
struct ra_vk_ctx_params params,
|
||||||
|
VkPresentModeKHR preferred_mode)
|
||||||
|
{
|
||||||
|
struct ra_swapchain *sw = ctx->swapchain = talloc_zero(NULL, struct ra_swapchain);
|
||||||
|
sw->ctx = ctx;
|
||||||
|
sw->fns = &vulkan_swapchain;
|
||||||
|
|
||||||
|
struct priv *p = sw->priv = talloc_zero(sw, struct priv);
|
||||||
|
p->vk = vk;
|
||||||
|
p->params = params;
|
||||||
|
p->opts = mp_get_config_group(p, ctx->global, &vulkan_conf);
|
||||||
|
|
||||||
|
vk->vulkan = mppl_create_vulkan(p->opts, vk->vkinst, vk->pllog, vk->surface);
|
||||||
if (!vk->vulkan)
|
if (!vk->vulkan)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
@ -21,6 +21,12 @@ bool ra_vk_ctx_init(struct ra_ctx *ctx, struct mpvk_ctx *vk,
|
|||||||
struct ra_vk_ctx_params params,
|
struct ra_vk_ctx_params params,
|
||||||
VkPresentModeKHR preferred_mode);
|
VkPresentModeKHR preferred_mode);
|
||||||
|
|
||||||
|
// Helper for initializing mpvk_ctx->vulkan
|
||||||
|
pl_vulkan mppl_create_vulkan(struct vulkan_opts *opts,
|
||||||
|
pl_vk_inst vkinst,
|
||||||
|
pl_log pllog,
|
||||||
|
VkSurfaceKHR surface);
|
||||||
|
|
||||||
// Handles a resize request, and updates ctx->vo->dwidth/dheight
|
// Handles a resize request, and updates ctx->vo->dwidth/dheight
|
||||||
bool ra_vk_ctx_resize(struct ra_ctx *ctx, int width, int height);
|
bool ra_vk_ctx_resize(struct ra_ctx *ctx, int width, int height);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user