Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 119-graphicspipeline-refactoring
  • 129-projekte-und-assets-auslagern
  • 132-denoising-module
  • 143-ar-vr-support-via-openxr
  • 43-multi-threading
  • 91-compute-first-network
  • 95-arm64-raspberry-pi-4-support
  • develop
  • master
  • optimizations
  • 0.1.0
  • 0.2.0
12 results

Target

Select target project
  • vulkan2021/vkcv-framework
1 result
Select Git revision
  • 119-graphicspipeline-refactoring
  • 129-projekte-und-assets-auslagern
  • 132-denoising-module
  • 143-ar-vr-support-via-openxr
  • 43-multi-threading
  • 91-compute-first-network
  • 95-arm64-raspberry-pi-4-support
  • develop
  • master
  • optimizations
  • 0.1.0
  • 0.2.0
12 results
Show changes
Commits on Source (351)
Showing
with 743 additions and 118 deletions
......@@ -18,3 +18,8 @@ cmake-build-release/
# GUI configuration files
imgui.ini
# Generated source and header files for shaders
*.hxx
*.cxx
variables:
RUN:
value: "all"
description: "The tests that should run. Possible values: ubuntu, win, all."
GIT_DEPTH: 1
description: "The tests that should run. Possible values: ubuntu, win-msvc, win-mingw, mac, all."
GIT_DEPTH: 15
stages:
- build
......@@ -17,13 +17,13 @@ build_ubuntu_gcc:
- ubuntu-gcc-cached
variables:
GIT_SUBMODULE_STRATEGY: recursive
timeout: 10m
timeout: 15m
retry: 1
script:
- mkdir debug
- cd debug
- cmake -DCMAKE_BUILD_TYPE=Debug ..
- cmake --build .
- cmake --build . -j 4
artifacts:
name: "Documentation - $CI_PIPELINE_ID"
paths:
......@@ -34,13 +34,13 @@ build_ubuntu_gcc:
build_win10_msvc:
only:
variables:
- $RUN =~ /\bwin.*/i || $RUN =~ /\ball.*/i
- $RUN =~ /\bwin-msvc.*/i || $RUN =~ /\ball.*/i
stage: build
tags:
- win10-msvc-cached
variables:
GIT_SUBMODULE_STRATEGY: recursive
timeout: 10m
timeout: 15m
retry: 0
script:
- cd 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\'
......@@ -49,7 +49,43 @@ build_win10_msvc:
- mkdir debug
- cd debug
- cmake -DCMAKE_BUILD_TYPE=Debug ..
- cmake --build .
- cmake --build . -j 4
build_win10_mingw:
only:
variables:
- $RUN =~ /\bwin-mingw.*/i || $RUN =~ /\ball.*/i
stage: build
tags:
- win10-mingw-cached
variables:
GIT_SUBMODULE_STRATEGY: recursive
timeout: 15m
retry: 0
script:
- mkdir debug
- cd debug
- cmake --no-warn-unused-cli -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=C:\msys64\mingw64\bin\x86_64-w64-mingw32-gcc.exe -DCMAKE_CXX_COMPILER:FILEPATH=C:\msys64\mingw64\bin\x86_64-w64-mingw32-g++.exe .. -G "Unix Makefiles"
- cmake --build . -j 4
build_mac_clang:
only:
variables:
- $RUN =~ /\bmac.*/i || $RUN =~ /\ball.*/i
stage: build
tags:
- catalina-clang-cached
variables:
GIT_SUBMODULE_STRATEGY: recursive
timeout: 15m
retry: 1
script:
- mkdir debug
- cd debug
- export LDFLAGS="-L/usr/local/opt/llvm/lib"
- export CPPFLAGS="-I/usr/local/opt/llvm/include"
- cmake -DCMAKE_C_COMPILER="/usr/local/opt/llvm/bin/clang" -DCMAKE_CXX_COMPILER="/usr/local/opt/llvm/bin/clang++" -DCMAKE_BUILD_TYPE=Debug ..
- cmake --build . -j 4
deploy_doc_develop:
only:
......
......@@ -22,9 +22,9 @@
[submodule "modules/gui/lib/imgui"]
path = modules/gui/lib/imgui
url = https://github.com/ocornut/imgui.git
[submodule "lib/VulkanMemoryAllocator"]
path = lib/VulkanMemoryAllocator
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
[submodule "lib/VulkanMemoryAllocator-Hpp"]
path = lib/VulkanMemoryAllocator-Hpp
url = https://github.com/malte-v/VulkanMemoryAllocator-Hpp.git
[submodule "modules/upscaling/lib/FidelityFX-FSR"]
path = modules/upscaling/lib/FidelityFX-FSR
url = https://github.com/GPUOpen-Effects/FidelityFX-FSR.git
......@@ -33,9 +33,10 @@ set(vkcv_flags ${CMAKE_CXX_FLAGS})
# enabling warnings in the debug build
if (vkcv_build_debug)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(vkcv_flags ${vkcv_flags} " -Weverything")
#set(vkcv_flags ${vkcv_flags} " -Weverything")
set(vkcv_flags ${vkcv_flags} " -Wextra -Wall -Wno-unused-parameter")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(vkcv_flags ${vkcv_flags} " -Wextra -Wall -pedantic")
set(vkcv_flags ${vkcv_flags} " -Wextra -Wall -pedantic -Wno-unused-parameter")
else()
set(vkcv_flags ${vkcv_flags} " -W4")
endif()
......@@ -64,7 +65,7 @@ add_library(vkcv STATIC ${vkcv_sources})
if(MSVC)
#enable multicore compilation on visual studio
target_compile_options(vkcv PRIVATE "/MP" "/openmp")
target_compile_options(vkcv PRIVATE "/MP" "/openmp" "/Zc:offsetof-")
#set source groups to create proper filters in visual studio
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${vkcv_sources})
......
......@@ -3,7 +3,13 @@ set(vkcv_config_lib ${vkcv_config}/lib)
set(vkcv_lib_path ${PROJECT_SOURCE_DIR}/${vkcv_lib})
if(NOT WIN32)
set(vkcv_libraries stdc++fs)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(vkcv_libraries stdc++fs)
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
list(APPEND vkcv_flags -Xpreprocessor)
endif()
# optimization for loading times
list(APPEND vkcv_flags -pthread)
......@@ -34,6 +40,9 @@ endif ()
# fix dependencies for different Linux distros (looking at you Ubuntu)
include(${vkcv_config_ext}/CheckLibraries.cmake)
# add custom function to include a file like a shader as string
include(${vkcv_config_ext}/IncludeShader.cmake)
# cleanup of compiler definitions aka preprocessor variables
if (vkcv_definitions)
list(REMOVE_DUPLICATES vkcv_definitions)
......
# adding all source files and header files of the framework:
set(vkcv_sources
${vkcv_include}/vkcv/Features.hpp
${vkcv_source}/vkcv/Features.cpp
${vkcv_include}/vkcv/FeatureManager.hpp
${vkcv_source}/vkcv/FeatureManager.cpp
${vkcv_include}/vkcv/Context.hpp
${vkcv_source}/vkcv/Context.cpp
${vkcv_include}/vkcv/Core.hpp
${vkcv_source}/vkcv/Core.cpp
${vkcv_include}/vkcv/File.hpp
${vkcv_source}/vkcv/File.cpp
${vkcv_include}/vkcv/PassConfig.hpp
${vkcv_source}/vkcv/PassConfig.cpp
......@@ -42,11 +51,15 @@ set(vkcv_sources
${vkcv_include}/vkcv/ShaderProgram.hpp
${vkcv_source}/vkcv/ShaderProgram.cpp
${vkcv_include}/vkcv/PipelineConfig.hpp
${vkcv_include}/vkcv/GraphicsPipelineConfig.hpp
${vkcv_include}/vkcv/ComputePipelineConfig.hpp
${vkcv_source}/vkcv/ComputePipelineManager.hpp
${vkcv_source}/vkcv/ComputePipelineManager.cpp
${vkcv_source}/vkcv/GraphicsPipelineManager.hpp
${vkcv_source}/vkcv/GraphicsPipelineManager.cpp
${vkcv_source}/vkcv/PipelineManager.hpp
${vkcv_source}/vkcv/PipelineManager.cpp
${vkcv_include}/vkcv/CommandResources.hpp
${vkcv_source}/vkcv/CommandResources.cpp
......@@ -72,6 +85,12 @@ set(vkcv_sources
${vkcv_source}/vkcv/SamplerManager.hpp
${vkcv_source}/vkcv/SamplerManager.cpp
${vkcv_source}/vkcv/WindowManager.hpp
${vkcv_source}/vkcv/WindowManager.cpp
${vkcv_source}/vkcv/SwapchainManager.hpp
${vkcv_source}/vkcv/SwapchainManager.cpp
${vkcv_include}/vkcv/DescriptorWrites.hpp
......
function(include_shader shader include_dir source_dir)
if (NOT EXISTS ${shader})
message(WARNING "Shader file does not exist: ${shader}")
else()
get_filename_component(filename ${shader} NAME)
file(SIZE ${shader} filesize)
set(include_target_file ${include_dir}/${filename}.hxx)
set(source_target_file ${source_dir}/${filename}.cxx)
if ((EXISTS ${source_target_file}) AND (EXISTS ${include_target_file}))
file(TIMESTAMP ${shader} shader_timestamp "%Y-%m-%dT%H:%M:%S")
file(TIMESTAMP ${source_target_file} source_timestamp "%Y-%m-%dT%H:%M:%S")
string(COMPARE GREATER ${shader_timestamp} ${source_timestamp} shader_update)
else()
set(shader_update true)
endif()
if (shader_update)
string(TOUPPER ${filename} varname)
string(REPLACE "." "_" varname ${varname})
set(shader_header "#pragma once\n")
string(APPEND shader_header "// This file is auto-generated via cmake, so don't touch it!\n")
string(APPEND shader_header "extern unsigned char ${varname} [${filesize}]\;\n")
string(APPEND shader_header "extern unsigned int ${varname}_LEN\;\n")
string(APPEND shader_header "const std::string ${varname}_SHADER (reinterpret_cast<const char*>(${varname}), ${varname}_LEN)\;")
file(WRITE ${include_target_file} ${shader_header})
find_program(xxd_program "xxd")
if (EXISTS ${xxd_program})
get_filename_component(shader_directory ${shader} DIRECTORY)
add_custom_command(
OUTPUT ${source_target_file}
WORKING_DIRECTORY "${shader_directory}"
COMMAND xxd -i -C "${filename}" "${source_target_file}"
COMMENT "Processing shader into source files: ${shader}"
)
else()
set(shader_source "// This file is auto-generated via cmake, so don't touch it!\n")
string(APPEND shader_source "unsigned char ${varname}[] = {")
math(EXPR max_fileoffset "${filesize} - 1" OUTPUT_FORMAT DECIMAL)
message(STATUS "Processing shader into source files: ${shader}")
foreach(fileoffset RANGE ${max_fileoffset})
file(READ ${shader} shader_source_byte OFFSET ${fileoffset} LIMIT 1 HEX)
math(EXPR offset_modulo "${fileoffset} % 12" OUTPUT_FORMAT DECIMAL)
if (${offset_modulo} EQUAL 0)
string(APPEND shader_source "\n ")
endif()
if (${fileoffset} LESS ${max_fileoffset})
string(APPEND shader_source "0x${shader_source_byte}, ")
else()
string(APPEND shader_source "0x${shader_source_byte}\n")
endif()
endforeach()
string(APPEND shader_source "}\;\n")
string(APPEND shader_source "unsigned int ${varname}_LEN = ${filesize}\;")
file(WRITE ${source_target_file} ${shader_source})
endif()
endif()
endif()
endfunction()
......@@ -76,8 +76,8 @@ namespace vkcv {
{}
[[nodiscard]]
static Buffer<T> create(BufferManager* manager, BufferType type, size_t count, BufferMemoryType memoryType) {
return Buffer<T>(manager, manager->createBuffer(type, count * sizeof(T), memoryType), type, count, memoryType);
static Buffer<T> create(BufferManager* manager, BufferType type, size_t count, BufferMemoryType memoryType, bool supportIndirect) {
return Buffer<T>(manager, manager->createBuffer(type, count * sizeof(T), memoryType, supportIndirect), type, count, memoryType);
}
};
......
......@@ -70,7 +70,7 @@ namespace vkcv
* @param memoryType Type of buffers memory
* @return New buffer handle
*/
BufferHandle createBuffer(BufferType type, size_t size, BufferMemoryType memoryType);
BufferHandle createBuffer(BufferType type, size_t size, BufferMemoryType memoryType, bool supportIndirect);
/**
* Returns the Vulkan buffer handle of a buffer
......
#pragma once
/**
* @authors Mark Mints
* @file src/vkcv/ComputePipelineConfig.hpp
* @brief Compute Pipeline Config Struct to hand over required information to Pipeline Creation.
*/
#include <vector>
#include "ShaderProgram.hpp"
namespace vkcv
{
struct ComputePipelineConfig {
ShaderProgram& m_ShaderProgram;
std::vector<vk::DescriptorSetLayout> m_DescriptorSetLayouts;
};
}
\ No newline at end of file
......@@ -4,6 +4,8 @@
#include <vk_mem_alloc.hpp>
#include "QueueManager.hpp"
#include "DrawcallRecording.hpp"
#include "Features.hpp"
namespace vkcv
{
......@@ -31,6 +33,9 @@ namespace vkcv
[[nodiscard]]
const vk::Device &getDevice() const;
[[nodiscard]]
const FeatureManager& getFeatureManager() const;
[[nodiscard]]
const QueueManager& getQueueManager() const;
......@@ -39,9 +44,9 @@ namespace vkcv
static Context create(const char *applicationName,
uint32_t applicationVersion,
std::vector<vk::QueueFlagBits> queueFlags,
std::vector<const char *> instanceExtensions,
std::vector<const char *> deviceExtensions);
const std::vector<vk::QueueFlagBits>& queueFlags,
const Features& features,
const std::vector<const char*>& instanceExtensions = {});
private:
/**
......@@ -52,11 +57,12 @@ namespace vkcv
* @param device Vulkan-Device
*/
Context(vk::Instance instance, vk::PhysicalDevice physicalDevice, vk::Device device,
QueueManager&& queueManager, vma::Allocator&& allocator) noexcept;
FeatureManager&& featureManager, QueueManager&& queueManager, vma::Allocator&& allocator) noexcept;
vk::Instance m_Instance;
vk::PhysicalDevice m_PhysicalDevice;
vk::Device m_Device;
FeatureManager m_FeatureManager;
QueueManager m_QueueManager;
vma::Allocator m_Allocator;
......
......@@ -7,14 +7,15 @@
#include <memory>
#include <vulkan/vulkan.hpp>
#include "vkcv/Context.hpp"
#include "vkcv/Swapchain.hpp"
#include "vkcv/Window.hpp"
#include "vkcv/PassConfig.hpp"
#include "vkcv/Handles.hpp"
#include "vkcv/Buffer.hpp"
#include "vkcv/Image.hpp"
#include "vkcv/PipelineConfig.hpp"
#include "Context.hpp"
#include "Swapchain.hpp"
#include "Window.hpp"
#include "PassConfig.hpp"
#include "Handles.hpp"
#include "Buffer.hpp"
#include "Image.hpp"
#include "GraphicsPipelineConfig.hpp"
#include "ComputePipelineConfig.hpp"
#include "CommandResources.hpp"
#include "SyncResources.hpp"
#include "Result.hpp"
......@@ -24,18 +25,24 @@
#include "Event.hpp"
#include "DrawcallRecording.hpp"
#include "CommandRecordingFunctionTypes.hpp"
#include "../../src/vkcv/WindowManager.hpp"
#include "../../src/vkcv/SwapchainManager.hpp"
namespace vkcv
{
// forward declarations
class PassManager;
class PipelineManager;
class GraphicsPipelineManager;
class ComputePipelineManager;
class DescriptorManager;
class BufferManager;
class SamplerManager;
class ImageManager;
class CommandStreamManager;
class WindowManager;
class SwapchainManager;
struct SubmitInfo {
QueueType queueType;
......@@ -52,31 +59,34 @@ namespace vkcv
*
* @param context encapsulates various Vulkan objects
*/
Core(Context &&context, Window &window, const Swapchain& swapChain, std::vector<vk::ImageView> imageViews,
const CommandResources& commandResources, const SyncResources& syncResources) noexcept;
Core(Context &&context, const CommandResources& commandResources, const SyncResources& syncResources) noexcept;
// explicit destruction of default constructor
Core() = delete;
Result acquireSwapchainImage();
Result acquireSwapchainImage(const SwapchainHandle &swapchainHandle);
Context m_Context;
Swapchain m_swapchain;
Window& m_window;
std::unique_ptr<PassManager> m_PassManager;
std::unique_ptr<PipelineManager> m_PipelineManager;
std::unique_ptr<DescriptorManager> m_DescriptorManager;
std::unique_ptr<BufferManager> m_BufferManager;
std::unique_ptr<SamplerManager> m_SamplerManager;
std::unique_ptr<ImageManager> m_ImageManager;
std::unique_ptr<CommandStreamManager> m_CommandStreamManager;
std::unique_ptr<PassManager> m_PassManager;
std::unique_ptr<GraphicsPipelineManager> m_PipelineManager;
std::unique_ptr<ComputePipelineManager> m_ComputePipelineManager;
std::unique_ptr<DescriptorManager> m_DescriptorManager;
std::unique_ptr<BufferManager> m_BufferManager;
std::unique_ptr<SamplerManager> m_SamplerManager;
std::unique_ptr<ImageManager> m_ImageManager;
std::unique_ptr<CommandStreamManager> m_CommandStreamManager;
std::unique_ptr<WindowManager> m_WindowManager;
std::unique_ptr<SwapchainManager> m_SwapchainManager;
CommandResources m_CommandResources;
SyncResources m_SyncResources;
uint32_t m_currentSwapchainImageIndex;
event_handle<int,int> e_resizeHandle;
/**
* sets up swapchain images
* @param swapchainHandles of swapchain
*/
void setSwapchainImages(SwapchainHandle handle);
public:
/**
......@@ -116,9 +126,6 @@ namespace vkcv
[[nodiscard]]
const Context &getContext() const;
[[nodiscard]]
const Swapchain& getSwapchain() const;
/**
* Creates a #Core with given @p applicationName and @p applicationVersion for your application.
......@@ -135,12 +142,11 @@ namespace vkcv
* @param[in] deviceExtensions (optional) Requested device extensions
* @return New instance of #Context
*/
static Core create(Window &window,
const char *applicationName,
static Core create(const char *applicationName,
uint32_t applicationVersion,
std::vector<vk::QueueFlagBits> queueFlags = {},
std::vector<const char*> instanceExtensions = {},
std::vector<const char*> deviceExtensions = {});
const std::vector<vk::QueueFlagBits>& queueFlags = {},
const Features& features = {},
const std::vector<const char *>& instanceExtensions = {});
/**
* Creates a basic vulkan graphics pipeline using @p config from the pipeline config class and returns it using the @p handle.
......@@ -151,20 +157,17 @@ namespace vkcv
* @return True if pipeline creation was successful, False if not
*/
[[nodiscard]]
PipelineHandle createGraphicsPipeline(const PipelineConfig &config);
GraphicsPipelineHandle createGraphicsPipeline(const GraphicsPipelineConfig &config);
/**
* Creates a basic vulkan compute pipeline using @p shader program and returns it using the @p handle.
* Fixed Functions for pipeline are set with standard values.
*
* @param shader program that hold the compiles compute shader
* @param handle a handle to return the created vulkan handle
* @param config Contains the compiles compute shader and the corresponding descriptor set layout
* @return True if pipeline creation was successful, False if not
*/
[[nodiscard]]
PipelineHandle createComputePipeline(
const ShaderProgram &config,
const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts);
ComputePipelineHandle createComputePipeline(const ComputePipelineConfig &config);
/**
* Creates a basic vulkan render pass using @p config from the render pass config class and returns it using the @p handle.
......@@ -185,8 +188,8 @@ namespace vkcv
* return Buffer-Object
*/
template<typename T>
Buffer<T> createBuffer(vkcv::BufferType type, size_t count, BufferMemoryType memoryType = BufferMemoryType::DEVICE_LOCAL) {
return Buffer<T>::create(m_BufferManager.get(), type, count, memoryType);
Buffer<T> createBuffer(vkcv::BufferType type, size_t count, BufferMemoryType memoryType = BufferMemoryType::DEVICE_LOCAL, bool supportIndirect = false) {
return Buffer<T>::create(m_BufferManager.get(), type, count, memoryType, supportIndirect);
}
/**
......@@ -196,11 +199,13 @@ namespace vkcv
* @param minFilter Minimizing filter
* @param mipmapMode Mipmapping filter
* @param addressMode Address mode
* @param mipLodBias Mip level of detail bias
* @return Sampler handle
*/
[[nodiscard]]
SamplerHandle createSampler(SamplerFilterType magFilter, SamplerFilterType minFilter,
SamplerMipmapMode mipmapMode, SamplerAddressMode addressMode);
SamplerMipmapMode mipmapMode, SamplerAddressMode addressMode,
float mipLodBias = 0.0f);
/**
* Creates an #Image with a given format, width, height and depth.
......@@ -222,45 +227,144 @@ namespace vkcv
bool supportColorAttachment = false,
Multisampling multisampling = Multisampling::None);
/**
* creates a new window and returns it's handle
* @param applicationName window name
* @param windowWidth
* @param windowHeight
* @param resizeable resizeability bool
* @return windowHandle
*/
[[nodiscard]]
WindowHandle createWindow(
const char *applicationName,
uint32_t windowWidth,
uint32_t windowHeight,
bool resizeable);
/**
* getter for window reference
* @param handle of the window
* @return the window
*/
[[nodiscard]]
Window& getWindow(const WindowHandle& handle );
/**
* gets the swapchain of the current focused window
* @return swapchain
*/
[[nodiscard]]
Swapchain& getSwapchainOfCurrentWindow();
/**
* returns the swapchain reference
* @param handle of the swapchain
* @return swapchain
*/
[[nodiscard]]
Swapchain& getSwapchain(const SwapchainHandle& handle);
/**
* gets the swapchain handle from the window
* @param handle of the window
* @return the swapchain from getSwapchain( SwapchainHandle )
*/
[[nodiscard]]
Swapchain& getSwapchain(const WindowHandle& handle);
/**
* returns the image width
* @param image handle
* @return imageWidth
*/
[[nodiscard]]
uint32_t getImageWidth(ImageHandle imageHandle);
uint32_t getImageWidth(const ImageHandle& image);
/**
* returns the image height
* @param image handle
* @return imageHeight
*/
[[nodiscard]]
uint32_t getImageHeight(ImageHandle imageHandle);
uint32_t getImageHeight(const ImageHandle& image);
/**
* returns the image format of the image
* @param image handle
* @return imageFormat
*/
[[nodiscard]]
vk::Format getImageFormat(const ImageHandle& image);
/** TODO:
* @param bindings
* @return
*/
[[nodiscard]]
DescriptorSetLayoutHandle createDescriptorSetLayout(const std::unordered_map<uint32_t, DescriptorBinding> &bindingsMap);
DescriptorSetLayout getDescriptorSetLayout(const DescriptorSetLayoutHandle handle) const;
// TODO: existsDescriptorSetLayout function that checks and returns fitting layout upon existence.
/** TODO:
* @param setDescriptions
* @return
*/
[[nodiscard]]
DescriptorSetHandle createDescriptorSet(const std::vector<DescriptorBinding> &bindings);
DescriptorSetHandle createDescriptorSet(const DescriptorSetLayoutHandle &layoutHandle);
void writeDescriptorSet(DescriptorSetHandle handle, const DescriptorWrites& writes);
DescriptorSet getDescriptorSet(const DescriptorSetHandle handle) const;
/**
* @brief start recording command buffers and increment frame index
*/
bool beginFrame(uint32_t& width, uint32_t& height);
bool beginFrame(uint32_t& width, uint32_t& height, const WindowHandle &windowHandle);
void recordDrawcallsToCmdStream(
const CommandStreamHandle cmdStreamHandle,
const PassHandle renderpassHandle,
const PipelineHandle pipelineHandle,
const CommandStreamHandle& cmdStreamHandle,
const PassHandle& renderpassHandle,
const GraphicsPipelineHandle &pipelineHandle,
const PushConstants &pushConstants,
const std::vector<DrawcallInfo> &drawcalls,
const std::vector<ImageHandle> &renderTargets);
const std::vector<ImageHandle> &renderTargets,
const WindowHandle &windowHandle);
void recordMeshShaderDrawcalls(
const CommandStreamHandle& cmdStreamHandle,
const PassHandle& renderpassHandle,
const GraphicsPipelineHandle &pipelineHandle,
const PushConstants& pushConstantData,
const std::vector<MeshShaderDrawcall>& drawcalls,
const std::vector<ImageHandle>& renderTargets,
const WindowHandle& windowHandle);
void recordComputeDispatchToCmdStream(
CommandStreamHandle cmdStream,
PipelineHandle computePipeline,
ComputePipelineHandle computePipeline,
const uint32_t dispatchCount[3],
const std::vector<DescriptorSetUsage> &descriptorSetUsages,
const PushConstants& pushConstants);
void recordBeginDebugLabel(const CommandStreamHandle &cmdStream,
const std::string& label,
const std::array<float, 4>& color);
void recordEndDebugLabel(const CommandStreamHandle &cmdStream);
void recordComputeIndirectDispatchToCmdStream(
const CommandStreamHandle cmdStream,
const ComputePipelineHandle computePipeline,
const vkcv::BufferHandle buffer,
const size_t bufferArgOffset,
const std::vector<DescriptorSetUsage>& descriptorSetUsages,
const PushConstants& pushConstants);
/**
* @brief end recording and present image
*/
void endFrame();
void endFrame( const WindowHandle& windowHandle );
/**
* Submit a command buffer to any queue of selected type. The recording can be customized by a
......@@ -283,15 +387,40 @@ namespace vkcv
const RecordCommandFunction &record,
const FinishCommandFunction &finish);
void submitCommandStream(const CommandStreamHandle handle);
void prepareSwapchainImageForPresent(const CommandStreamHandle handle);
void prepareImageForSampling(const CommandStreamHandle cmdStream, const ImageHandle image);
void prepareImageForStorage(const CommandStreamHandle cmdStream, const ImageHandle image);
void recordImageMemoryBarrier(const CommandStreamHandle cmdStream, const ImageHandle image);
void recordBufferMemoryBarrier(const CommandStreamHandle cmdStream, const BufferHandle buffer);
void resolveMSAAImage(CommandStreamHandle cmdStream, ImageHandle src, ImageHandle dst);
void submitCommandStream(const CommandStreamHandle& handle);
void prepareSwapchainImageForPresent(const CommandStreamHandle& handle);
void prepareImageForSampling(const CommandStreamHandle& cmdStream, const ImageHandle& image);
void prepareImageForStorage(const CommandStreamHandle& cmdStream, const ImageHandle& image);
// normally layout transitions for attachments are handled by the core
// however for manual vulkan use, e.g. ImGui integration, this function is exposed
// this is also why the command buffer is passed directly, instead of the command stream handle
void prepareImageForAttachmentManually(const vk::CommandBuffer& cmdBuffer, const ImageHandle& image);
// if manual vulkan work, e.g. ImGui integration, changes an image layout this function must be used
// to update the internal image state
void updateImageLayoutManual(const vkcv::ImageHandle& image, const vk::ImageLayout layout);
void recordImageMemoryBarrier(const CommandStreamHandle& cmdStream, const ImageHandle& image);
void recordBufferMemoryBarrier(const CommandStreamHandle& cmdStream, const BufferHandle& buffer);
void resolveMSAAImage(const CommandStreamHandle& cmdStream, const ImageHandle& src, const ImageHandle& dst);
[[nodiscard]]
vk::ImageView getSwapchainImageView() const;
void recordMemoryBarrier(const CommandStreamHandle& cmdStream);
void recordBlitImage(const CommandStreamHandle& cmdStream, const ImageHandle& src, const ImageHandle& dst,
SamplerFilterType filterType);
void setDebugLabel(const BufferHandle &handle, const std::string &label);
void setDebugLabel(const PassHandle &handle, const std::string &label);
void setDebugLabel(const GraphicsPipelineHandle &handle, const std::string &label);
void setDebugLabel(const ComputePipelineHandle &handle, const std::string &label);
void setDebugLabel(const DescriptorSetHandle &handle, const std::string &label);
void setDebugLabel(const SamplerHandle &handle, const std::string &label);
void setDebugLabel(const ImageHandle &handle, const std::string &label);
void setDebugLabel(const CommandStreamHandle &handle, const std::string &label);
};
}
#pragma once
#include <vulkan/vulkan.hpp>
#include <unordered_map>
#include "vkcv/Handles.hpp"
#include "vkcv/ShaderStage.hpp"
#include "vkcv/Logger.hpp"
namespace vkcv
{
struct DescriptorSet
{
vk::DescriptorSet vulkanHandle;
vk::DescriptorSetLayout layout;
size_t poolIndex;
};
/*
* All the types of descriptors (resources) that can be retrieved by the shaders
*/
......@@ -23,9 +17,38 @@ namespace vkcv
STORAGE_BUFFER,
SAMPLER,
IMAGE_SAMPLED,
IMAGE_STORAGE
IMAGE_STORAGE,
UNIFORM_BUFFER_DYNAMIC,
STORAGE_BUFFER_DYNAMIC
};
/**
* Converts the descriptor types from VulkanCV (vkcv) to native Vulkan (vk).
* @param[in] vkcv DescriptorType
* @return vk DescriptorType
*/
constexpr vk::DescriptorType getVkDescriptorType(DescriptorType type) noexcept {
switch (type)
{
case DescriptorType::UNIFORM_BUFFER:
return vk::DescriptorType::eUniformBuffer;
case DescriptorType::UNIFORM_BUFFER_DYNAMIC:
return vk::DescriptorType::eUniformBufferDynamic;
case DescriptorType::STORAGE_BUFFER:
return vk::DescriptorType::eStorageBuffer;
case DescriptorType::STORAGE_BUFFER_DYNAMIC:
return vk::DescriptorType::eStorageBufferDynamic;
case DescriptorType::SAMPLER:
return vk::DescriptorType::eSampler;
case DescriptorType::IMAGE_SAMPLED:
return vk::DescriptorType::eSampledImage;
case DescriptorType::IMAGE_STORAGE:
return vk::DescriptorType::eStorageImage;
default:
return vk::DescriptorType::eMutableVALVE;
}
}
/*
* One binding for a descriptor set
* @param[in] a unique binding ID
......@@ -39,12 +62,29 @@ namespace vkcv
uint32_t bindingID,
DescriptorType descriptorType,
uint32_t descriptorCount,
ShaderStage shaderStage
ShaderStages shaderStages
) noexcept;
uint32_t bindingID;
DescriptorType descriptorType;
uint32_t descriptorCount;
ShaderStage shaderStage;
uint32_t bindingID;
DescriptorType descriptorType;
uint32_t descriptorCount;
ShaderStages shaderStages;
bool operator ==(const DescriptorBinding &other) const;
};
typedef std::unordered_map<uint32_t, DescriptorBinding> DescriptorBindings;
struct DescriptorSetLayout
{
vk::DescriptorSetLayout vulkanHandle;
DescriptorBindings descriptorBindings;
};
struct DescriptorSet
{
vk::DescriptorSet vulkanHandle;
DescriptorSetLayoutHandle setLayoutHandle;
size_t poolIndex;
};
}
......@@ -20,16 +20,15 @@ namespace vkcv {
uint32_t mipLevel;
};
struct UniformBufferDescriptorWrite {
inline UniformBufferDescriptorWrite(uint32_t binding, BufferHandle buffer) : binding(binding), buffer(buffer) {};
uint32_t binding;
BufferHandle buffer;
};
struct StorageBufferDescriptorWrite {
inline StorageBufferDescriptorWrite(uint32_t binding, BufferHandle buffer) : binding(binding), buffer(buffer) {};
struct BufferDescriptorWrite {
inline BufferDescriptorWrite(uint32_t binding, BufferHandle buffer, bool dynamic = false,
uint32_t offset = 0, uint32_t size = 0) :
binding(binding), buffer(buffer), dynamic(dynamic), offset(offset), size(size) {};
uint32_t binding;
BufferHandle buffer;
bool dynamic;
uint32_t offset;
uint32_t size;
};
struct SamplerDescriptorWrite {
......@@ -41,8 +40,8 @@ namespace vkcv {
struct DescriptorWrites {
std::vector<SampledImageDescriptorWrite> sampledImageWrites;
std::vector<StorageImageDescriptorWrite> storageImageWrites;
std::vector<UniformBufferDescriptorWrite> uniformBufferWrites;
std::vector<StorageBufferDescriptorWrite> storageBufferWrites;
std::vector<BufferDescriptorWrite> uniformBufferWrites;
std::vector<BufferDescriptorWrite> storageBufferWrites;
std::vector<SamplerDescriptorWrite> samplerWrites;
};
}
\ No newline at end of file
......@@ -13,21 +13,41 @@ namespace vkcv {
vk::Buffer buffer;
};
enum class IndexBitCount{
Bit16,
Bit32
};
struct DescriptorSetUsage {
inline DescriptorSetUsage(uint32_t setLocation, vk::DescriptorSet vulkanHandle) noexcept
: setLocation(setLocation), vulkanHandle(vulkanHandle) {}
inline DescriptorSetUsage(uint32_t setLocation, vk::DescriptorSet vulkanHandle,
const std::vector<uint32_t>& dynamicOffsets = {}) noexcept
: setLocation(setLocation), vulkanHandle(vulkanHandle), dynamicOffsets(dynamicOffsets) {}
const uint32_t setLocation;
const vk::DescriptorSet vulkanHandle;
const uint32_t setLocation;
const vk::DescriptorSet vulkanHandle;
const std::vector<uint32_t> dynamicOffsets;
};
struct Mesh {
inline Mesh(std::vector<VertexBufferBinding> vertexBufferBindings, vk::Buffer indexBuffer, size_t indexCount) noexcept
: vertexBufferBindings(vertexBufferBindings), indexBuffer(indexBuffer), indexCount(indexCount){}
inline Mesh(){}
inline Mesh(
std::vector<VertexBufferBinding> vertexBufferBindings,
vk::Buffer indexBuffer,
size_t indexCount,
IndexBitCount indexBitCount = IndexBitCount::Bit16) noexcept
:
vertexBufferBindings(vertexBufferBindings),
indexBuffer(indexBuffer),
indexCount(indexCount),
indexBitCount(indexBitCount) {}
std::vector<VertexBufferBinding> vertexBufferBindings;
vk::Buffer indexBuffer;
size_t indexCount;
IndexBitCount indexBitCount;
};
struct DrawcallInfo {
......@@ -46,4 +66,21 @@ namespace vkcv {
const PushConstants &pushConstants,
const size_t drawcallIndex);
}
\ No newline at end of file
void InitMeshShaderDrawFunctions(vk::Device device);
struct MeshShaderDrawcall {
inline MeshShaderDrawcall(const std::vector<DescriptorSetUsage> descriptorSets, uint32_t taskCount)
: descriptorSets(descriptorSets), taskCount(taskCount) {}
std::vector<DescriptorSetUsage> descriptorSets;
uint32_t taskCount;
};
void recordMeshShaderDrawcall(
vk::CommandBuffer cmdBuffer,
vk::PipelineLayout pipelineLayout,
const PushConstants& pushConstantData,
const uint32_t pushConstantOffset,
const MeshShaderDrawcall& drawcall,
const uint32_t firstTask);
}
......@@ -6,6 +6,8 @@
#include <mutex>
#endif
#include <vector>
namespace vkcv {
template<typename... T>
......
#pragma once
#include "Logger.hpp"
#include <functional>
#include <unordered_set>
#include <vector>
#include <vulkan/vulkan.hpp>
namespace vkcv {
class FeatureManager {
private:
vk::PhysicalDevice& m_physicalDevice;
std::vector<const char*> m_supportedExtensions;
std::vector<const char*> m_activeExtensions;
vk::PhysicalDeviceFeatures2 m_featuresBase;
std::vector<vk::BaseOutStructure*> m_featuresExtensions;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceFeatures& features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDevice16BitStorageFeatures& features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDevice8BitStorageFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceBufferDeviceAddressFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceDescriptorIndexingFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceHostQueryResetFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceImagelessFramebufferFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceMultiviewFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceProtectedMemoryFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceSamplerYcbcrConversionFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceScalarBlockLayoutFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceSeparateDepthStencilLayoutsFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceShaderAtomicInt64Features &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceShaderFloat16Int8Features& features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceShaderSubgroupExtendedTypesFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceTimelineSemaphoreFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceUniformBufferStandardLayoutFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceVariablePointersFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceVulkanMemoryModelFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceMeshShaderFeaturesNV& features, bool required) const;
vk::BaseOutStructure* findFeatureStructure(vk::StructureType type) const;
public:
explicit FeatureManager(vk::PhysicalDevice& physicalDevice);
FeatureManager(const FeatureManager& other) = delete;
FeatureManager(FeatureManager&& other) noexcept;
~FeatureManager();
FeatureManager& operator=(const FeatureManager& other) = delete;
FeatureManager& operator=(FeatureManager&& other) noexcept;
[[nodiscard]]
bool isExtensionSupported(const std::string& extension) const;
bool useExtension(const std::string& extension, bool required = true);
[[nodiscard]]
bool isExtensionActive(const std::string& extension) const;
[[nodiscard]]
const std::vector<const char*>& getActiveExtensions() const;
bool useFeatures(const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction, bool required = true);
template<typename T>
bool useFeatures(const std::function<void(T&)>& featureFunction, bool required = true) {
T features;
T* features_ptr = reinterpret_cast<T*>(findFeatureStructure(features.sType));
if (features_ptr) {
features = *features_ptr;
}
featureFunction(features);
if (!checkSupport(features, required)) {
if (required) {
throw std::runtime_error("Required feature is not supported!");
}
return false;
}
if (features_ptr) {
*features_ptr = features;
return true;
}
features_ptr = new T(features);
if (m_featuresExtensions.empty()) {
m_featuresBase.setPNext(features_ptr);
} else {
m_featuresExtensions.back()->setPNext(
reinterpret_cast<vk::BaseOutStructure*>(features_ptr)
);
}
m_featuresExtensions.push_back(
reinterpret_cast<vk::BaseOutStructure*>(features_ptr)
);
return true;
}
[[nodiscard]]
const vk::PhysicalDeviceFeatures2& getFeatures() const;
};
}
#pragma once
#include <functional>
#include <vector>
#include <initializer_list>
#include "FeatureManager.hpp"
namespace vkcv {
typedef std::function<bool(FeatureManager&)> Feature;
class Features {
private:
std::vector<Feature> m_features;
public:
Features() = default;
Features(const std::initializer_list<std::string>& list);
Features(const Features& other) = default;
Features(Features&& other) = default;
~Features() = default;
Features& operator=(const Features& other) = default;
Features& operator=(Features&& other) = default;
void requireExtension(const std::string& extension);
void requireExtensionFeature(const std::string& extension,
const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction);
template<typename T>
void requireExtensionFeature(const std::string& extension, const std::function<void(T&)>& featureFunction) {
m_features.emplace_back([extension, featureFunction](FeatureManager& featureManager) {
if (featureManager.useExtension(extension, true)) {
return featureManager.template useFeatures<T>(featureFunction, true);
} else {
return false;
}
});
}
void requireFeature(const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction);
template<typename T>
void requireFeature(const std::function<void(T&)>& featureFunction) {
m_features.emplace_back([featureFunction](FeatureManager& featureManager) {
return featureManager.template useFeatures<T>(featureFunction, true);
});
}
void tryExtension(const std::string& extension);
void tryExtensionFeature(const std::string& extension,
const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction);
template<typename T>
void tryExtensionFeature(const std::string& extension, const std::function<void(T&)>& featureFunction) {
m_features.emplace_back([extension, featureFunction](FeatureManager& featureManager) {
if (featureManager.useExtension(extension, false)) {
return featureManager.template useFeatures<T>(featureFunction, false);
} else {
return false;
}
});
}
void tryFeature(const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction);
template<typename T>
void tryFeature(const std::function<void(T&)>& featureFunction) {
m_features.emplace_back([featureFunction](FeatureManager& featureManager) {
return featureManager.template useFeatures<T>(featureFunction, false);
});
}
[[nodiscard]]
const std::vector<Feature>& getList() const;
};
}
#pragma once
#include <filesystem>
namespace vkcv {
std::filesystem::path generateTemporaryFilePath();
std::filesystem::path generateTemporaryDirectoryPath();
}
#pragma once
/**
* @authors Mara Vogt, Mark Mints
* @file src/vkcv/Pipeline.hpp
* @brief Pipeline class to handle shader stages
* @file src/vkcv/PipelineConfig.hpp
* @brief Graphics Pipeline Config Struct to hand over required information to Pipeline Creation
*/
#include <vector>
......@@ -22,7 +22,7 @@ namespace vkcv {
// alternatively we could expose the blend factors directly
enum class BlendMode{ None, Additive };
struct PipelineConfig {
struct GraphicsPipelineConfig {
ShaderProgram m_ShaderProgram;
uint32_t m_Width;
uint32_t m_Height;
......