Add Vulkan backend placeholder with dynamic fallback
This commit is contained in:
+17
-1
@@ -117,6 +117,22 @@ if (OAK_ENABLE_DYNAMIC_RENDER_BACKEND)
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
add_library(oakvulkan SHARED
|
||||
render/vulkan/vulkanbackend_c.cpp
|
||||
)
|
||||
target_include_directories(oakvulkan PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/app
|
||||
)
|
||||
target_link_libraries(oakvulkan PRIVATE Qt${QT_VERSION_MAJOR}::Core)
|
||||
target_compile_definitions(oakvulkan PRIVATE ${OLIVE_DEFINITIONS})
|
||||
target_compile_options(oakvulkan PRIVATE ${OLIVE_COMPILE_OPTIONS})
|
||||
set_target_properties(oakvulkan PROPERTIES
|
||||
OUTPUT_NAME oakvulkan
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(oakgl-cabi-check OBJECT
|
||||
@@ -142,7 +158,7 @@ target_include_directories(olive-editor PUBLIC pluginSupport)
|
||||
target_link_libraries(olive-editor PUBLIC OfxHost)
|
||||
add_dependencies(olive-editor oakgl-cabi-check)
|
||||
if (OAK_ENABLE_DYNAMIC_RENDER_BACKEND)
|
||||
add_dependencies(olive-editor oakgl)
|
||||
add_dependencies(olive-editor oakgl oakvulkan)
|
||||
endif()
|
||||
|
||||
# Add render worker process (olive-render-worker).
|
||||
|
||||
@@ -86,11 +86,27 @@ bool DynamicRenderer::Load()
|
||||
}
|
||||
|
||||
handle_ = create_(this->parent());
|
||||
if (!handle_) {
|
||||
library_.unload();
|
||||
return false;
|
||||
}
|
||||
if (is_available_ && !is_available_(handle_)) {
|
||||
qWarning() << "Render backend is not available" << backend_
|
||||
<< library_.fileName();
|
||||
if (backend_ == QStringLiteral("vulkan")) {
|
||||
return FallbackToOpenGL();
|
||||
}
|
||||
destroy_(handle_);
|
||||
handle_ = nullptr;
|
||||
library_.unload();
|
||||
return false;
|
||||
}
|
||||
return handle_ != nullptr;
|
||||
}
|
||||
|
||||
bool DynamicRenderer::ResolveFunctions()
|
||||
{
|
||||
ResetFunctions();
|
||||
#define RESOLVE(member, type, symbol) \
|
||||
member = reinterpret_cast<type>(library_.resolve(symbol)); \
|
||||
if (!member) return false
|
||||
@@ -126,9 +142,48 @@ bool DynamicRenderer::ResolveFunctions()
|
||||
RESOLVE(opengl_context_, OakBackendOpenGLContextFn,
|
||||
"oak_renderer_opengl_context");
|
||||
#undef RESOLVE
|
||||
is_available_ = reinterpret_cast<OakBackendIsAvailableFn>(
|
||||
library_.resolve("oak_renderer_is_available"));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DynamicRenderer::FallbackToOpenGL()
|
||||
{
|
||||
if (handle_ && destroy_) {
|
||||
destroy_(handle_);
|
||||
handle_ = nullptr;
|
||||
}
|
||||
if (library_.isLoaded()) {
|
||||
library_.unload();
|
||||
}
|
||||
ResetFunctions();
|
||||
backend_ = QStringLiteral("opengl");
|
||||
return Load();
|
||||
}
|
||||
|
||||
void DynamicRenderer::ResetFunctions()
|
||||
{
|
||||
create_ = nullptr;
|
||||
destroy_ = nullptr;
|
||||
is_available_ = nullptr;
|
||||
init_ = nullptr;
|
||||
init_with_context_ = nullptr;
|
||||
post_init_ = nullptr;
|
||||
post_destroy_ = nullptr;
|
||||
destroy_internal_ = nullptr;
|
||||
clear_destination_ = nullptr;
|
||||
create_native_texture_ = nullptr;
|
||||
destroy_native_texture_ = nullptr;
|
||||
create_native_shader_ = nullptr;
|
||||
destroy_native_shader_ = nullptr;
|
||||
upload_to_texture_ = nullptr;
|
||||
download_from_texture_ = nullptr;
|
||||
flush_ = nullptr;
|
||||
get_pixel_from_texture_ = nullptr;
|
||||
blit_ = nullptr;
|
||||
opengl_context_ = nullptr;
|
||||
}
|
||||
|
||||
bool DynamicRenderer::Init()
|
||||
{
|
||||
return Load() && init_(handle_);
|
||||
|
||||
@@ -52,6 +52,8 @@ protected:
|
||||
|
||||
private:
|
||||
bool ResolveFunctions();
|
||||
bool FallbackToOpenGL();
|
||||
void ResetFunctions();
|
||||
QString LibraryFilename() const;
|
||||
|
||||
QString backend_;
|
||||
@@ -60,6 +62,7 @@ private:
|
||||
|
||||
OakBackendCreateFn create_ = nullptr;
|
||||
OakBackendDestroyFn destroy_ = nullptr;
|
||||
OakBackendIsAvailableFn is_available_ = nullptr;
|
||||
OakBackendInitFn init_ = nullptr;
|
||||
OakBackendInitWithContextFn init_with_context_ = nullptr;
|
||||
OakBackendPostInitFn post_init_ = nullptr;
|
||||
|
||||
@@ -17,6 +17,7 @@ typedef void *OakRenderBackendHandle;
|
||||
|
||||
typedef OakRenderBackendHandle (*OakBackendCreateFn)(void *parent);
|
||||
typedef void (*OakBackendDestroyFn)(OakRenderBackendHandle handle);
|
||||
typedef bool (*OakBackendIsAvailableFn)(OakRenderBackendHandle handle);
|
||||
typedef bool (*OakBackendInitFn)(OakRenderBackendHandle handle);
|
||||
typedef void (*OakBackendInitWithContextFn)(OakRenderBackendHandle handle,
|
||||
void *context);
|
||||
|
||||
@@ -43,6 +43,12 @@ OAK_RENDER_BACKEND_EXPORT void oak_renderer_destroy(OakRenderBackendHandle handl
|
||||
delete Renderer(handle);
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT bool oak_renderer_is_available(
|
||||
OakRenderBackendHandle handle)
|
||||
{
|
||||
return handle != nullptr;
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT bool oak_renderer_init(OakRenderBackendHandle handle)
|
||||
{
|
||||
return Renderer(handle)->Init();
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
#include "render/backend/renderbackend_c.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QVariant>
|
||||
|
||||
namespace {
|
||||
|
||||
struct VulkanBackend {
|
||||
bool warned = false;
|
||||
};
|
||||
|
||||
VulkanBackend *Backend(OakRenderBackendHandle handle)
|
||||
{
|
||||
return static_cast<VulkanBackend *>(handle);
|
||||
}
|
||||
|
||||
void WarnUnavailable(OakRenderBackendHandle handle, const char *function)
|
||||
{
|
||||
auto *backend = Backend(handle);
|
||||
if (!backend || backend->warned) {
|
||||
return;
|
||||
}
|
||||
backend->warned = true;
|
||||
qWarning() << "Vulkan render backend is a C ABI placeholder; function"
|
||||
<< function << "is not implemented yet";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT OakRenderBackendHandle oak_renderer_create(void *parent)
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return new VulkanBackend();
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_destroy(OakRenderBackendHandle handle)
|
||||
{
|
||||
delete Backend(handle);
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT bool oak_renderer_is_available(
|
||||
OakRenderBackendHandle handle)
|
||||
{
|
||||
Q_UNUSED(handle)
|
||||
return false;
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT bool oak_renderer_init(OakRenderBackendHandle handle)
|
||||
{
|
||||
WarnUnavailable(handle, "init");
|
||||
return false;
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_init_with_context(
|
||||
OakRenderBackendHandle handle, void *context)
|
||||
{
|
||||
Q_UNUSED(context)
|
||||
WarnUnavailable(handle, "init_with_context");
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_post_init(
|
||||
OakRenderBackendHandle handle)
|
||||
{
|
||||
Q_UNUSED(handle)
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_post_destroy(
|
||||
OakRenderBackendHandle handle)
|
||||
{
|
||||
Q_UNUSED(handle)
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_destroy_internal(
|
||||
OakRenderBackendHandle handle)
|
||||
{
|
||||
Q_UNUSED(handle)
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_clear_destination(
|
||||
OakRenderBackendHandle handle, void *texture, double r, double g, double b,
|
||||
double a)
|
||||
{
|
||||
Q_UNUSED(texture)
|
||||
Q_UNUSED(r)
|
||||
Q_UNUSED(g)
|
||||
Q_UNUSED(b)
|
||||
Q_UNUSED(a)
|
||||
WarnUnavailable(handle, "clear_destination");
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_create_native_texture(
|
||||
OakRenderBackendHandle handle, int width, int height, int depth, int format,
|
||||
int channel_count, const void *data, int linesize, void *out_variant)
|
||||
{
|
||||
Q_UNUSED(width)
|
||||
Q_UNUSED(height)
|
||||
Q_UNUSED(depth)
|
||||
Q_UNUSED(format)
|
||||
Q_UNUSED(channel_count)
|
||||
Q_UNUSED(data)
|
||||
Q_UNUSED(linesize)
|
||||
static_cast<QVariant *>(out_variant)->clear();
|
||||
WarnUnavailable(handle, "create_native_texture");
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_destroy_native_texture(
|
||||
OakRenderBackendHandle handle, const void *variant)
|
||||
{
|
||||
Q_UNUSED(variant)
|
||||
WarnUnavailable(handle, "destroy_native_texture");
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_create_native_shader(
|
||||
OakRenderBackendHandle handle, const void *shader_code, void *out_variant)
|
||||
{
|
||||
Q_UNUSED(shader_code)
|
||||
static_cast<QVariant *>(out_variant)->clear();
|
||||
WarnUnavailable(handle, "create_native_shader");
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_destroy_native_shader(
|
||||
OakRenderBackendHandle handle, const void *variant)
|
||||
{
|
||||
Q_UNUSED(variant)
|
||||
WarnUnavailable(handle, "destroy_native_shader");
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_upload_to_texture(
|
||||
OakRenderBackendHandle handle, const void *variant, const void *video_params,
|
||||
const void *data, int linesize)
|
||||
{
|
||||
Q_UNUSED(variant)
|
||||
Q_UNUSED(video_params)
|
||||
Q_UNUSED(data)
|
||||
Q_UNUSED(linesize)
|
||||
WarnUnavailable(handle, "upload_to_texture");
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_download_from_texture(
|
||||
OakRenderBackendHandle handle, const void *variant, const void *video_params,
|
||||
void *data, int linesize)
|
||||
{
|
||||
Q_UNUSED(variant)
|
||||
Q_UNUSED(video_params)
|
||||
Q_UNUSED(data)
|
||||
Q_UNUSED(linesize)
|
||||
WarnUnavailable(handle, "download_from_texture");
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_flush(OakRenderBackendHandle handle)
|
||||
{
|
||||
Q_UNUSED(handle)
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_get_pixel_from_texture(
|
||||
OakRenderBackendHandle handle, void *texture, const void *point,
|
||||
void *out_color)
|
||||
{
|
||||
Q_UNUSED(texture)
|
||||
Q_UNUSED(point)
|
||||
Q_UNUSED(out_color)
|
||||
WarnUnavailable(handle, "get_pixel_from_texture");
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_blit(
|
||||
OakRenderBackendHandle handle, const void *shader, void *job,
|
||||
void *destination, const void *destination_params, bool clear_destination)
|
||||
{
|
||||
Q_UNUSED(shader)
|
||||
Q_UNUSED(job)
|
||||
Q_UNUSED(destination)
|
||||
Q_UNUSED(destination_params)
|
||||
Q_UNUSED(clear_destination)
|
||||
WarnUnavailable(handle, "blit");
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void *oak_renderer_opengl_context(
|
||||
OakRenderBackendHandle handle)
|
||||
{
|
||||
Q_UNUSED(handle)
|
||||
return nullptr;
|
||||
}
|
||||
Reference in New Issue
Block a user