mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-13 21:28:01 +02:00
lavu/vulkan: add option to switch between shader compilers and cleanup glslang
This commit is contained in:
parent
d1133e8c44
commit
b2aec70bd6
@ -578,8 +578,6 @@ SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h
|
||||
SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h
|
||||
SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h
|
||||
|
||||
OBJS-$(CONFIG_LIBGLSLANG) += glslang.o
|
||||
|
||||
TOOLS = graph2dot
|
||||
TESTPROGS = drawutils filtfmts formats integral
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg 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.
|
||||
*
|
||||
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "libavutil/vulkan_glslang.c"
|
@ -188,8 +188,5 @@ int ff_vk_filter_init(AVFilterContext *avctx)
|
||||
|
||||
s->output_format = AV_PIX_FMT_NONE;
|
||||
|
||||
if (ff_vk_glslang_init())
|
||||
return AVERROR_EXTERNAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -16,12 +16,15 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "vulkan.h"
|
||||
#include "vulkan_glslang.h"
|
||||
|
||||
#include "avassert.h"
|
||||
|
||||
#include "vulkan.h"
|
||||
#include "vulkan_loader.h"
|
||||
|
||||
#if FF_VK_ENABLE_SHADER_COMPILATION && CONFIG_LIBGLSLANG
|
||||
#include "vulkan_glslang.c"
|
||||
#endif
|
||||
|
||||
/* Generic macro for creating contexts which need to keep their addresses
|
||||
* if another context is created. */
|
||||
#define FN_CREATING(ctx, type, shortname, array, num) \
|
||||
@ -843,7 +846,6 @@ void ff_vk_print_shader(void *ctx, FFVkSPIRVShader *shd, int prio)
|
||||
int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd,
|
||||
const char *entrypoint)
|
||||
{
|
||||
#if CONFIG_LIBGLSLANG
|
||||
int err;
|
||||
VkResult ret;
|
||||
FFVulkanFunctions *vk = &s->vkfn;
|
||||
@ -854,12 +856,21 @@ int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd,
|
||||
|
||||
shd->shader.pName = entrypoint;
|
||||
|
||||
err = ff_vk_glslang_shader_compile(s, shd, &spirv, &spirv_size, &priv);
|
||||
if (!s->spirv_compiler) {
|
||||
#if FF_VK_ENABLE_SHADER_COMPILATION && CONFIG_LIBGLSLANG
|
||||
s->spirv_compiler = ff_vk_glslang_init();
|
||||
#else
|
||||
return AVERROR(ENOSYS);
|
||||
#endif
|
||||
if (!s->spirv_compiler)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
err = s->spirv_compiler->compile_shader(s->spirv_compiler, s, shd, &spirv,
|
||||
&spirv_size, entrypoint, &priv);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
ff_vk_print_shader(s, shd, AV_LOG_VERBOSE);
|
||||
|
||||
av_log(s, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n",
|
||||
shd->name, spirv_size);
|
||||
|
||||
@ -872,7 +883,7 @@ int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd,
|
||||
ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL,
|
||||
&shd->shader.module);
|
||||
|
||||
ff_vk_glslang_shader_free(priv);
|
||||
s->spirv_compiler->free_shader(s->spirv_compiler, &priv);
|
||||
|
||||
if (ret != VK_SUCCESS) {
|
||||
av_log(s, AV_LOG_ERROR, "Unable to create shader module: %s\n",
|
||||
@ -881,9 +892,6 @@ int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd,
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return AVERROR(ENOSYS);
|
||||
#endif
|
||||
}
|
||||
|
||||
static const struct descriptor_props {
|
||||
@ -1367,7 +1375,8 @@ void ff_vk_uninit(FFVulkanContext *s)
|
||||
{
|
||||
FFVulkanFunctions *vk = &s->vkfn;
|
||||
|
||||
ff_vk_glslang_uninit();
|
||||
if (s->spirv_compiler)
|
||||
s->spirv_compiler->uninit(&s->spirv_compiler);
|
||||
|
||||
for (int i = 0; i < s->exec_ctx_num; i++)
|
||||
free_exec_ctx(s, s->exec_ctx[i]);
|
||||
|
@ -22,6 +22,10 @@
|
||||
#define VK_NO_PROTOTYPES
|
||||
#define VK_ENABLE_BETA_EXTENSIONS
|
||||
|
||||
#ifndef FF_VK_ENABLE_SHADER_COMPILATION
|
||||
#define FF_VK_ENABLE_SHADER_COMPILATION 1
|
||||
#endif
|
||||
|
||||
#include "pixdesc.h"
|
||||
#include "bprint.h"
|
||||
#include "hwcontext.h"
|
||||
@ -64,6 +68,15 @@ typedef struct FFVkSPIRVShader {
|
||||
VkPipelineShaderStageCreateInfo shader;
|
||||
} FFVkSPIRVShader;
|
||||
|
||||
typedef struct FFVkSPIRVCompiler {
|
||||
void *priv;
|
||||
int (*compile_shader)(struct FFVkSPIRVCompiler *ctx, void *avctx,
|
||||
struct FFVkSPIRVShader *shd, uint8_t **data,
|
||||
size_t *size, const char *entrypoint, void **opaque);
|
||||
void (*free_shader)(struct FFVkSPIRVCompiler *ctx, void **opaque);
|
||||
void (*uninit)(struct FFVkSPIRVCompiler **ctx);
|
||||
} FFVkSPIRVCompiler;
|
||||
|
||||
typedef struct FFVkSampler {
|
||||
VkSampler sampler[4];
|
||||
} FFVkSampler;
|
||||
@ -194,6 +207,8 @@ typedef struct FFVulkanContext {
|
||||
AVHWFramesContext *frames;
|
||||
AVVulkanFramesContext *hwfc;
|
||||
|
||||
FFVkSPIRVCompiler *spirv_compiler;
|
||||
|
||||
/* Properties */
|
||||
int output_width;
|
||||
int output_height;
|
||||
|
@ -24,10 +24,8 @@
|
||||
#include "mem.h"
|
||||
#include "avassert.h"
|
||||
|
||||
#include "vulkan_glslang.h"
|
||||
|
||||
static pthread_mutex_t glslang_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int glslang_refcount = 0;
|
||||
static pthread_mutex_t glslc_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int glslc_refcount = 0;
|
||||
|
||||
static const glslang_resource_t glslc_resource_limits = {
|
||||
.max_lights = 32,
|
||||
@ -137,8 +135,10 @@ static const glslang_resource_t glslc_resource_limits = {
|
||||
}
|
||||
};
|
||||
|
||||
int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd,
|
||||
uint8_t **data, size_t *size, void **opaque)
|
||||
static int glslc_shader_compile(FFVkSPIRVCompiler *ctx, void *avctx,
|
||||
FFVkSPIRVShader *shd, uint8_t **data,
|
||||
size_t *size, const char *entrypoint,
|
||||
void **opaque)
|
||||
{
|
||||
const char *messages;
|
||||
glslang_shader_t *glslc_shader;
|
||||
@ -174,7 +174,7 @@ int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd,
|
||||
.resource = &glslc_resource_limits,
|
||||
};
|
||||
|
||||
av_assert0(glslang_refcount);
|
||||
av_assert0(glslc_refcount);
|
||||
|
||||
if (!(glslc_shader = glslang_shader_create(&glslc_input)))
|
||||
return AVERROR(ENOMEM);
|
||||
@ -218,8 +218,12 @@ int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd,
|
||||
glslang_program_SPIRV_generate(glslc_program, glslc_input.stage);
|
||||
|
||||
messages = glslang_program_SPIRV_get_messages(glslc_program);
|
||||
if (messages)
|
||||
if (messages) {
|
||||
ff_vk_print_shader(s, shd, AV_LOG_WARNING);
|
||||
av_log(avctx, AV_LOG_WARNING, "%s\n", messages);
|
||||
} else {
|
||||
ff_vk_print_shader(s, shd, AV_LOG_VERBOSE);
|
||||
}
|
||||
|
||||
glslang_shader_delete(glslc_shader);
|
||||
|
||||
@ -230,27 +234,47 @@ int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ff_vk_glslang_shader_free(void *opaque)
|
||||
static void glslc_shader_free(FFVkSPIRVCompiler *ctx, void **opaque)
|
||||
{
|
||||
glslang_program_delete(opaque);
|
||||
if (!opaque || !*opaque)
|
||||
return;
|
||||
|
||||
av_assert0(glslc_refcount);
|
||||
glslang_program_delete(*opaque);
|
||||
*opaque = NULL;
|
||||
}
|
||||
|
||||
int ff_vk_glslang_init(void)
|
||||
static void glslc_uninit(FFVkSPIRVCompiler **ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
if (!ctx || !*ctx)
|
||||
return;
|
||||
|
||||
pthread_mutex_lock(&glslang_mutex);
|
||||
if (glslang_refcount++ == 0)
|
||||
ret = !glslang_initialize_process();
|
||||
pthread_mutex_unlock(&glslang_mutex);
|
||||
pthread_mutex_lock(&glslc_mutex);
|
||||
if (glslc_refcount && (--glslc_refcount == 0))
|
||||
glslang_finalize_process();
|
||||
pthread_mutex_unlock(&glslc_mutex);
|
||||
|
||||
av_freep(ctx);
|
||||
}
|
||||
|
||||
static FFVkSPIRVCompiler *ff_vk_glslang_init(void)
|
||||
{
|
||||
FFVkSPIRVCompiler *ret = av_mallocz(sizeof(*ret));
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
ret->compile_shader = glslc_shader_compile;
|
||||
ret->free_shader = glslc_shader_free;
|
||||
ret->uninit = glslc_uninit;
|
||||
|
||||
pthread_mutex_lock(&glslc_mutex);
|
||||
if (!glslc_refcount++) {
|
||||
if (!glslang_initialize_process()) {
|
||||
av_freep(&ret);
|
||||
glslc_refcount--;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&glslc_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ff_vk_glslang_uninit(void)
|
||||
{
|
||||
pthread_mutex_lock(&glslang_mutex);
|
||||
if (glslang_refcount && (--glslang_refcount == 0))
|
||||
glslang_finalize_process();
|
||||
pthread_mutex_unlock(&glslang_mutex);
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg 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.
|
||||
*
|
||||
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVUTIL_GLSLANG_H
|
||||
#define AVUTIL_GLSLANG_H
|
||||
|
||||
#include "vulkan.h"
|
||||
|
||||
/**
|
||||
* Un/initialize glslang's global state. Thread-safe and reference counted.
|
||||
*/
|
||||
int ff_vk_glslang_init(void);
|
||||
void ff_vk_glslang_uninit(void);
|
||||
|
||||
/**
|
||||
* Compile GLSL into SPIR-V using glslang.
|
||||
*/
|
||||
int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd,
|
||||
uint8_t **data, size_t *size, void **opaque);
|
||||
|
||||
/**
|
||||
* Frees the shader-specific context.
|
||||
*/
|
||||
void ff_vk_glslang_shader_free(void *opaque);
|
||||
|
||||
#endif /* AVUTIL_GLSLANG_H */
|
Loading…
Reference in New Issue
Block a user