Skip to content
Draft

Vulkan #1677

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ build
dist
CMakeFiles
casparcg_server
*.spv

src/cmake-build-*
src/.idea
Expand Down
4 changes: 4 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ else ()
message(STATUS "Build Version: ${CONFIG_VERSION_MAJOR}.${CONFIG_VERSION_MINOR}.${CONFIG_VERSION_BUG} ${CONFIG_VERSION_TAG} (Revision: ${CONFIG_VERSION_GIT_HASH})")
endif ()

IF(ENABLE_VULKAN)
add_definitions(-DENABLE_VULKAN)
ENDIF()

include_directories("${CMAKE_BINARY_DIR}/generated")

add_subdirectory(tools)
Expand Down
26 changes: 26 additions & 0 deletions src/CMakeModules/Bootstrap_Linux.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ set(USE_STATIC_BOOST OFF CACHE BOOL "Use shared library version of Boost")
set(USE_SYSTEM_CEF ON CACHE BOOL "Use the version of cef from your OS (only tested with Ubuntu)")
set(CASPARCG_BINARY_NAME "casparcg" CACHE STRING "Custom name of the binary to build (this disables some install files)")
set(ENABLE_AVX2 ON CACHE BOOL "Enable the AVX2 instruction set (requires a CPU that supports it)")
set(ENABLE_VULKAN OFF CACHE BOOL "Enable Vulkan support")

# Determine build (target) platform
SET (PLATFORM_FOLDER_NAME "linux")
Expand All @@ -39,6 +40,24 @@ find_package(OpenAL REQUIRED)
find_package(SFML 2 COMPONENTS graphics window REQUIRED)
find_package(X11 REQUIRED)

IF (ENABLE_VULKAN)
find_package(Vulkan REQUIRED)

FetchContent_Declare(
fetch_vk_bootstrap
GIT_REPOSITORY https://github.com/charles-lunarg/vk-bootstrap
GIT_TAG v1.4.328 #suggest using a tag so the library doesn't update whenever new commits are pushed to a branch
)
FetchContent_MakeAvailable(fetch_vk_bootstrap)

FetchContent_Declare(
fetch_vma
GIT_REPOSITORY https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
GIT_TAG v3.3.0 #suggest using a tag so the library doesn't update whenever new commits are pushed to a branch
)
FetchContent_MakeAvailable(fetch_vma)
endif()

# support for Ubuntu 22.04
if (NOT TARGET OpenAL::OpenAL)
add_library(OpenAL::OpenAL INTERFACE IMPORTED)
Expand Down Expand Up @@ -143,6 +162,11 @@ ADD_COMPILE_OPTIONS (-fopenmp-simd) # Enable OpenMP SIMD support
ADD_COMPILE_OPTIONS (-fnon-call-exceptions) # Allow signal handler to throw exception

ADD_COMPILE_OPTIONS (-Wno-deprecated-declarations -Wno-write-strings -Wno-multichar -Wno-cpp -Werror)

IF (ENABLE_VULKAN)
ADD_COMPILE_OPTIONS (-Wno-nonnull -Wno-nullability-completeness)
ENDIF()

IF (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
ADD_COMPILE_OPTIONS (-Wno-terminate)
ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
Expand All @@ -152,3 +176,5 @@ ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
message(STATUS "ADDING: -DTBB_USE_GLIBCXX_VERSION=${TBB_USE_GLIBCXX_VERSION}")
add_definitions(-DTBB_USE_GLIBCXX_VERSION=${TBB_USE_GLIBCXX_VERSION})
ENDIF ()

set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
17 changes: 17 additions & 0 deletions src/CMakeModules/Bootstrap_Windows.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ if(POLICY CMP0167)
endif()

set(BOOST_USE_PRECOMPILED ON CACHE BOOL "Use precompiled boost")
set(ENABLE_VULKAN OFF CACHE BOOL "Enable Vulkan support")

set(CASPARCG_RUNTIME_DEPENDENCIES_RELEASE "" CACHE INTERNAL "")
set(CASPARCG_RUNTIME_DEPENDENCIES_DEBUG "" CACHE INTERNAL "")
Expand Down Expand Up @@ -151,6 +152,22 @@ target_link_directories(GLEW::glew INTERFACE ${glew_SOURCE_DIR}/lib/Release/x64)
target_link_libraries(GLEW::glew INTERFACE glew32)
casparcg_add_runtime_dependency("${glew_SOURCE_DIR}/bin/Release/x64/glew32.dll")

IF(ENABLE_VULKAN)
find_package(Vulkan REQUIRED)

FetchContent_Declare(fetch_vk_bootstrap
GIT_REPOSITORY https://github.com/charles-lunarg/vk-bootstrap
GIT_TAG v1.4.328 #suggest using a tag so the library doesn't update whenever new commits are pushed to a branch
)
FetchContent_MakeAvailable(fetch_vk_bootstrap)

FetchContent_Declare(fetch_vma
GIT_REPOSITORY https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
GIT_TAG v3.3.0 #suggest using a tag so the library doesn't update whenever new commits are pushed to a branch
)
FetchContent_MakeAvailable(fetch_vma)
ENDIF()

# SFML
FetchContent_Declare(sfml
URL ${CASPARCG_DOWNLOAD_MIRROR}/sfml/SFML-2.6.2-windows-vc17-64-bit.zip
Expand Down
73 changes: 73 additions & 0 deletions src/accelerator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ set(SOURCES

accelerator.cpp
)

set(HEADERS
ogl/image/image_kernel.h
ogl/image/image_mixer.h
Expand All @@ -35,6 +36,38 @@ set(HEADERS
StdAfx.h
)

IF(ENABLE_VULKAN)
list(APPEND SOURCES
vulkan/image/image_kernel.cpp
vulkan/image/image_mixer.cpp

vulkan/util/buffer.cpp
vulkan/util/device.cpp
vulkan/util/pipeline.cpp
vulkan/util/renderpass.cpp
vulkan/util/texture.cpp
vulkan/util/matrix.cpp
vulkan/util/transforms.cpp
)

list(APPEND HEADERS
vulkan/image/image_kernel.h
vulkan/image/image_mixer.h

vulkan/util/buffer.h
vulkan/util/device.h
vulkan/util/draw_params.h
vulkan/util/pipeline.h
vulkan/util/texture.h
vulkan/util/matrix.h
vulkan/util/transforms.h
vulkan/util/uniform_block.h

vulkan_image_vertex.h
vulkan_image_fragment.h
)
ENDIF()

if (MSVC)
list(APPEND SOURCES
ogl/util/context_sfml.cpp
Expand All @@ -45,6 +78,36 @@ else()
)
endif()

IF (ENABLE_VULKAN)
find_program(glslc_executable NAMES glslc HINTS Vulkan::glslc)
set(SHADER_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vulkan/image)
set(SHADER_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vulkan/image)

file(GLOB SHADERS
${SHADER_SOURCE_DIR}/vertex_shader.vert
${SHADER_SOURCE_DIR}/fragment_shader.frag)

foreach(source IN LISTS SHADERS)
get_filename_component(FILENAME ${source} NAME_WLE)
add_custom_command(
COMMAND
${glslc_executable}
# -MD -MF ${SHADER_BINARY_DIR}/${FILENAME}.d
-o ${SHADER_BINARY_DIR}/${FILENAME}.spv
${source}
OUTPUT ${SHADER_BINARY_DIR}/${FILENAME}.spv
DEPENDS ${source} ${SHADER_BINARY_DIR}
COMMENT "Compiling ${FILENAME}"
)
list(APPEND SPV_SHADERS ${SHADER_BINARY_DIR}/${FILENAME}.spv)
endforeach()

add_custom_target(shaders ALL DEPENDS ${SPV_SHADERS})

bin2c("vulkan/image/vertex_shader.spv" "vulkan_image_vertex.h" "caspar::accelerator::vulkan" "vertex_shader")
bin2c("vulkan/image/fragment_shader.spv" "vulkan_image_fragment.h" "caspar::accelerator::vulkan" "fragment_shader")
ENDIF()

bin2c("ogl/image/shader.vert" "ogl_image_vertex.h" "caspar::accelerator::ogl" "vertex_shader")
bin2c("ogl/image/shader.frag" "ogl_image_fragment.h" "caspar::accelerator::ogl" "fragment_shader")

Expand All @@ -53,6 +116,11 @@ target_include_directories(accelerator PRIVATE .. ${CMAKE_CURRENT_BINARY_DIR})
target_precompile_headers(accelerator PRIVATE StdAfx.h)
target_link_libraries(accelerator PRIVATE common core GLEW::glew)

IF(ENABLE_VULKAN)
target_link_libraries(accelerator PRIVATE vk-bootstrap::vk-bootstrap GPUOpen::VulkanMemoryAllocator Vulkan::Vulkan)
ENDIF()


if (MSVC)
target_link_libraries(accelerator PRIVATE sfml-window)
endif()
Expand All @@ -62,3 +130,8 @@ source_group(sources\\cpu\\image cpu/image/.*)
source_group(sources\\cpu\\util cpu/util/.*)
source_group(sources\\ogl\\image ogl/image/.*)
source_group(sources\\ogl\\util ogl/util/.*)

IF(ENABLE_VULKAN)
source_group(sources\\vulkan\\image vulkan/image/.*)
source_group(sources\\vulkan\\util vulkan/util/.*)
ENDIF()
60 changes: 50 additions & 10 deletions src/accelerator/accelerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@
#include "ogl/image/image_mixer.h"
#include "ogl/util/device.h"

#ifdef ENABLE_VULKAN
#include "vulkan/image/image_mixer.h"
#include "vulkan/util/device.h"
#endif

#include <boost/property_tree/ptree.hpp>

#include <common/bit_depth.h>
#include <common/except.h>

#include <core/mixer/image/image_mixer.h>

Expand All @@ -17,27 +23,62 @@ namespace caspar { namespace accelerator {

struct accelerator::impl
{
std::shared_ptr<ogl::device> ogl_device_;
std::shared_ptr<accelerator_device> device_;
const core::video_format_repository format_repository_;
accelerator_backend backend_;

impl(const core::video_format_repository format_repository)
: format_repository_(format_repository)
, backend_(accelerator_backend::invalid)
{
}

void set_backend(accelerator_backend backend)
{
if (backend_ != accelerator_backend::invalid) {
CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"Accelerator backend already set"));
}

backend_ = backend;
}

std::unique_ptr<core::image_mixer> create_image_mixer(int channel_id, common::bit_depth depth)
{
#ifdef ENABLE_VULKAN
if (backend_ == accelerator_backend::vulkan) {
return std::make_unique<vulkan::image_mixer>(
spl::make_shared_ptr(std::dynamic_pointer_cast<vulkan::device>(get_device())),
channel_id,
format_repository_.get_max_video_format_size(),
depth);
}
#endif
return std::make_unique<ogl::image_mixer>(
spl::make_shared_ptr(get_device()), channel_id, format_repository_.get_max_video_format_size(), depth);
spl::make_shared_ptr(std::dynamic_pointer_cast<ogl::device>(get_device())),
channel_id,
format_repository_.get_max_video_format_size(),
depth);
}

std::shared_ptr<ogl::device> get_device()
std::shared_ptr<accelerator_device> get_device()
{
if (!ogl_device_) {
ogl_device_ = std::make_shared<ogl::device>();
if (backend_ == accelerator_backend::invalid) {
CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"Accelerator backend not set"));
}
#ifdef ENABLE_VULKAN
if (backend_ == accelerator_backend::vulkan) {
if (!device_) {
device_ = std::dynamic_pointer_cast<accelerator_device>(std::make_shared<vulkan::device>());
}

return ogl_device_;
return device_;
}
#endif

if (!device_) {
device_ = std::dynamic_pointer_cast<accelerator_device>(std::make_shared<ogl::device>());
}
return device_;
}
};

Expand All @@ -48,14 +89,13 @@ accelerator::accelerator(const core::video_format_repository format_repository)

accelerator::~accelerator() {}

void accelerator::set_backend(accelerator_backend backend) { impl_->set_backend(backend); }

std::unique_ptr<core::image_mixer> accelerator::create_image_mixer(const int channel_id, common::bit_depth depth)
{
return impl_->create_image_mixer(channel_id, depth);
}

std::shared_ptr<accelerator_device> accelerator::get_device() const
{
return std::dynamic_pointer_cast<accelerator_device>(impl_->get_device());
}
std::shared_ptr<accelerator_device> accelerator::get_device() const { return impl_->get_device(); }

}} // namespace caspar::accelerator
11 changes: 11 additions & 0 deletions src/accelerator/accelerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ class accelerator_device
virtual std::future<void> gc() = 0;
};

enum class accelerator_backend
{
invalid = 0,
opengl,
#ifdef ENABLE_VULKAN
vulkan,
#endif
};

class accelerator
{
public:
Expand All @@ -30,6 +39,8 @@ class accelerator

accelerator& operator=(accelerator&) = delete;

void set_backend(accelerator_backend backend);

std::unique_ptr<caspar::core::image_mixer> create_image_mixer(int channel_id, common::bit_depth depth);

std::shared_ptr<accelerator_device> get_device() const;
Expand Down
3 changes: 2 additions & 1 deletion src/accelerator/ogl/image/image_mixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ class image_renderer
const core::video_format_desc& format_desc)
{
if (layers.empty()) { // Bypass GPU with empty frame.
static const std::vector<uint8_t, boost::alignment::aligned_allocator<uint8_t, 32>> buffer(max_frame_size_, 0);
static const std::vector<uint8_t, boost::alignment::aligned_allocator<uint8_t, 32>> buffer(max_frame_size_,
0);
return make_ready_future(array<const std::uint8_t>(buffer.data(), format_desc.size, true));
}

Expand Down
5 changes: 3 additions & 2 deletions src/accelerator/ogl/image/image_shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ std::shared_ptr<shader> get_image_shader(const spl::shared_ptr<device>& ogl)
}
};

existing_shader.reset(new shader(std::string(vertex_shader), std::string(fragment_shader)), deleter);

existing_shader.reset(new shader(std::string(reinterpret_cast<const char*>(vertex_shader)),
std::string(reinterpret_cast<const char*>(fragment_shader))),
deleter);
g_shader = existing_shader;

return existing_shader;
Expand Down
Loading