Verified Commit 8ea8f76b authored by Tobias Frisch's avatar Tobias Frisch
Browse files

Merge branch 'develop' into 43-multi-threading


Signed-off-by: Tobias Frisch's avatarTobias Frisch <tfrisch@uni-koblenz.de>
parents a68ddf84 7297fd95
Pipeline #25732 passed with stages
in 3 minutes and 4 seconds
...@@ -29,10 +29,14 @@ set(vkcv_sources ...@@ -29,10 +29,14 @@ set(vkcv_sources
${vkcv_source}/vkcv/ImageManager.hpp ${vkcv_source}/vkcv/ImageManager.hpp
${vkcv_source}/vkcv/ImageManager.cpp ${vkcv_source}/vkcv/ImageManager.cpp
${vkcv_include}/vkcv/Logger.hpp
${vkcv_include}/vkcv/SwapChain.hpp ${vkcv_include}/vkcv/SwapChain.hpp
${vkcv_source}/vkcv/SwapChain.cpp ${vkcv_source}/vkcv/SwapChain.cpp
${vkcv_include}/vkcv/ShaderStage.hpp
${vkcv_include}/vkcv/ShaderProgram.hpp ${vkcv_include}/vkcv/ShaderProgram.hpp
${vkcv_source}/vkcv/ShaderProgram.cpp ${vkcv_source}/vkcv/ShaderProgram.cpp
...@@ -69,4 +73,12 @@ set(vkcv_sources ...@@ -69,4 +73,12 @@ set(vkcv_sources
${vkcv_source}/vkcv/SamplerManager.cpp ${vkcv_source}/vkcv/SamplerManager.cpp
${vkcv_include}/vkcv/DescriptorWrites.hpp ${vkcv_include}/vkcv/DescriptorWrites.hpp
${vkcv_include}/vkcv/DrawcallRecording.hpp
${vkcv_source}/vkcv/DrawcallRecording.cpp
${vkcv_include}/vkcv/CommandStreamManager.hpp
${vkcv_source}/vkcv/CommandStreamManager.cpp
${vkcv_include}/vkcv/CommandRecordingFunctionTypes.hpp
) )
...@@ -6,9 +6,20 @@ if (spirv-cross_FOUND) ...@@ -6,9 +6,20 @@ if (spirv-cross_FOUND)
message(${vkcv_config_msg} " SPIRV Cross - " ${SPIRV_CROSS_VERSION}) message(${vkcv_config_msg} " SPIRV Cross - " ${SPIRV_CROSS_VERSION})
else() else()
if (EXISTS "${vkcv_lib_path}/SPIRV-Cross") if (EXISTS "${vkcv_lib_path}/SPIRV-Cross")
set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS OFF CACHE INTERNAL "")
set(SPIRV_CROSS_SHARED OFF CACHE INTERNAL "")
set(SPIRV_CROSS_STATIC ON CACHE INTERNAL "")
set(SPIRV_CROSS_CLI OFF CACHE INTERNAL "") set(SPIRV_CROSS_CLI OFF CACHE INTERNAL "")
set(SPIRV_CROSS_ENABLE_TESTS OFF CACHE INTERNAL "") set(SPIRV_CROSS_ENABLE_TESTS OFF CACHE INTERNAL "")
set(SPIRV_CROSS_ENABLE_GLSL ON CACHE INTERNAL "")
set(SPIRV_CROSS_ENABLE_HLSL OFF CACHE INTERNAL "")
set(SPIRV_CROSS_ENABLE_MSL OFF CACHE INTERNAL "")
set(SPIRV_CROSS_ENABLE_CPP ON CACHE INTERNAL "")
set(SPIRV_CROSS_ENABLE_REFLECT OFF CACHE INTERNAL "")
set(SPIRV_CROSS_ENABLE_C_API OFF CACHE INTERNAL "") set(SPIRV_CROSS_ENABLE_C_API OFF CACHE INTERNAL "")
set(SPIRV_CROSS_ENABLE_UTIL OFF CACHE INTERNAL "")
set(SPIRV_CROSS_SKIP_INSTALL ON CACHE INTERNAL "") set(SPIRV_CROSS_SKIP_INSTALL ON CACHE INTERNAL "")
add_subdirectory(${vkcv_lib}/SPIRV-Cross) add_subdirectory(${vkcv_lib}/SPIRV-Cross)
......
...@@ -37,6 +37,11 @@ namespace vkcv { ...@@ -37,6 +37,11 @@ namespace vkcv {
size_t getSize() const { size_t getSize() const {
return m_count * sizeof(T); return m_count * sizeof(T);
} }
[[nodiscard]]
const vk::Buffer getVulkanHandle() const {
return m_manager->getBuffer(m_handle);
}
void fill(const T* data, size_t count = 0, size_t offset = 0) { void fill(const T* data, size_t count = 0, size_t offset = 0) {
m_manager->fillBuffer(m_handle, data, count * sizeof(T), offset * sizeof(T)); m_manager->fillBuffer(m_handle, data, count * sizeof(T), offset * sizeof(T));
......
#pragma once
#include "vkcv/Event.hpp"
#include <vulkan/vulkan.hpp>
namespace vkcv {
typedef typename event_function<const vk::CommandBuffer&>::type RecordCommandFunction;
typedef typename event_function<>::type FinishCommandFunction;
}
\ No newline at end of file
#pragma once
#include <vulkan/vulkan.hpp>
#include <vector>
#include "vkcv/Event.hpp"
#include "vkcv/Handles.hpp"
#include "vkcv/CommandRecordingFunctionTypes.hpp"
namespace vkcv {
class Core;
class CommandStreamManager
{
friend class Core;
private:
struct CommandStream {
inline CommandStream(vk::CommandBuffer cmdBuffer, vk::Queue queue, vk::CommandPool cmdPool)
: cmdBuffer(cmdBuffer), cmdPool(cmdPool), queue(queue) {};
vk::CommandBuffer cmdBuffer;
vk::CommandPool cmdPool;
vk::Queue queue;
std::vector<FinishCommandFunction> callbacks;
};
Core* m_core;
std::vector<CommandStream> m_commandStreams;
CommandStreamManager() noexcept;
void init(Core* core);
public:
~CommandStreamManager() noexcept;
CommandStreamManager(CommandStreamManager&& other) = delete;
CommandStreamManager(const CommandStreamManager& other) = delete;
CommandStreamManager& operator=(CommandStreamManager&& other) = delete;
CommandStreamManager& operator=(const CommandStreamManager& other) = delete;
CommandStreamHandle createCommandStream(
const vk::Queue queue,
vk::CommandPool cmdPool);
void recordCommandsToStream(const CommandStreamHandle handle, const RecordCommandFunction record);
void addFinishCallbackToStream(const CommandStreamHandle handle, const FinishCommandFunction finish);
void submitCommandStreamSynchronous(
const CommandStreamHandle handle,
std::vector<vk::Semaphore> &waitSemaphores,
std::vector<vk::Semaphore> &signalSemaphores);
vk::CommandBuffer getStreamCommandBuffer(const CommandStreamHandle handle);
};
}
\ No newline at end of file
...@@ -22,13 +22,11 @@ ...@@ -22,13 +22,11 @@
#include "Sampler.hpp" #include "Sampler.hpp"
#include "DescriptorWrites.hpp" #include "DescriptorWrites.hpp"
#include "Event.hpp" #include "Event.hpp"
#include "DrawcallRecording.hpp"
#include "CommandRecordingFunctionTypes.hpp"
namespace vkcv namespace vkcv
{ {
struct VertexBufferBinding {
vk::DeviceSize offset;
BufferHandle buffer;
};
// forward declarations // forward declarations
class PassManager; class PassManager;
...@@ -37,15 +35,13 @@ namespace vkcv ...@@ -37,15 +35,13 @@ namespace vkcv
class BufferManager; class BufferManager;
class SamplerManager; class SamplerManager;
class ImageManager; class ImageManager;
class CommandStreamManager;
struct SubmitInfo { struct SubmitInfo {
QueueType queueType; QueueType queueType;
std::vector<vk::Semaphore> waitSemaphores; std::vector<vk::Semaphore> waitSemaphores;
std::vector<vk::Semaphore> signalSemaphores; std::vector<vk::Semaphore> signalSemaphores;
}; };
typedef typename event_function<const vk::CommandBuffer&>::type RecordCommandFunction;
typedef typename event_function<>::type FinishCommandFunction;
class Core final class Core final
{ {
...@@ -65,27 +61,30 @@ namespace vkcv ...@@ -65,27 +61,30 @@ namespace vkcv
Context m_Context; Context m_Context;
SwapChain m_swapchain; SwapChain m_swapchain;
std::vector<vk::ImageView> m_swapchainImageViews; std::vector<vk::ImageView> m_swapchainImageViews;
const Window& m_window; std::vector<vk::Image> m_swapchainImages;
std::vector<vk::ImageLayout> m_swapchainImageLayouts;
std::unique_ptr<PassManager> m_PassManager; const Window& m_window;
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;
CommandResources m_CommandResources; std::unique_ptr<PassManager> m_PassManager;
SyncResources m_SyncResources; std::unique_ptr<PipelineManager> m_PipelineManager;
uint32_t m_currentSwapchainImageIndex; 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;
ImageHandle m_DepthImage; CommandResources m_CommandResources;
SyncResources m_SyncResources;
uint32_t m_currentSwapchainImageIndex;
std::function<void(int, int)> e_resizeHandle; std::function<void(int, int)> e_resizeHandle;
static std::vector<vk::ImageView> createImageViews( Context &context, SwapChain& swapChain); static std::vector<vk::ImageView> createImageViews( Context &context, SwapChain& swapChain);
void recordSwapchainImageLayoutTransition(vk::CommandBuffer cmdBuffer, vk::ImageLayout newLayout);
public: public:
/** /**
* Destructor of #Core destroys the Vulkan objects contained in the core's context. * Destructor of #Core destroys the Vulkan objects contained in the core's context.
...@@ -158,6 +157,19 @@ namespace vkcv ...@@ -158,6 +157,19 @@ namespace vkcv
[[nodiscard]] [[nodiscard]]
PipelineHandle createGraphicsPipeline(const PipelineConfig &config); PipelineHandle createGraphicsPipeline(const PipelineConfig &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
* @return True if pipeline creation was successful, False if not
*/
[[nodiscard]]
PipelineHandle createComputePipeline(
const ShaderProgram &config,
const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts);
/** /**
* Creates a basic vulkan render pass using @p config from the render pass config class and returns it using the @p handle. * Creates a basic vulkan render pass using @p config from the render pass config class and returns it using the @p handle.
* Fixed Functions for pipeline are set with standard values. * Fixed Functions for pipeline are set with standard values.
...@@ -211,29 +223,30 @@ namespace vkcv ...@@ -211,29 +223,30 @@ namespace vkcv
* @return * @return
*/ */
[[nodiscard]] [[nodiscard]]
ResourcesHandle createResourceDescription(const std::vector<DescriptorSetConfig> &descriptorSets); DescriptorSetHandle createDescriptorSet(const std::vector<DescriptorBinding> &bindings);
void writeResourceDescription(ResourcesHandle handle, size_t setIndex, const DescriptorWrites& writes); void writeDescriptorSet(DescriptorSetHandle handle, const DescriptorWrites& writes);
vk::DescriptorSetLayout getDescriptorSetLayout(ResourcesHandle handle, size_t setIndex); DescriptorSet getDescriptorSet(const DescriptorSetHandle handle) const;
/** /**
* @brief start recording command buffers and increment frame index * @brief start recording command buffers and increment frame index
*/ */
void beginFrame(); bool beginFrame(uint32_t& width, uint32_t& height);
/** void recordDrawcallsToCmdStream(
* @brief render a beautiful triangle const CommandStreamHandle cmdStreamHandle,
*/ const PassHandle renderpassHandle,
void renderMesh( const PipelineHandle pipelineHandle,
const PassHandle &renderpassHandle, const PushConstantData &pushConstantData,
const PipelineHandle &pipelineHandle, const std::vector<DrawcallInfo> &drawcalls,
const size_t pushConstantSize, const std::vector<ImageHandle> &renderTargets);
const void* pushConstantData,
const std::vector<VertexBufferBinding> &vertexBufferBindings, void recordComputeDispatchToCmdStream(
const BufferHandle &indexBuffer, CommandStreamHandle cmdStream,
const size_t indexCount, PipelineHandle computePipeline,
const vkcv::ResourcesHandle resourceHandle, const uint32_t dispatchCount[3],
const size_t resourceDescriptorSetIndex); const std::vector<DescriptorSetUsage> &descriptorSetUsages,
const PushConstantData& pushConstantData);
/** /**
* @brief end recording and present image * @brief end recording and present image
...@@ -251,6 +264,20 @@ namespace vkcv ...@@ -251,6 +264,20 @@ namespace vkcv
* @param record Record-command-function * @param record Record-command-function
* @param finish Finish-command-function or nullptr * @param finish Finish-command-function or nullptr
*/ */
void submitCommands(const SubmitInfo &submitInfo, const RecordCommandFunction& record, const FinishCommandFunction& finish); void recordAndSubmitCommands(
const SubmitInfo &submitInfo,
const RecordCommandFunction &record,
const FinishCommandFunction &finish);
CommandStreamHandle createCommandStream(QueueType queueType);
void recordCommandsToStream(
const CommandStreamHandle cmdStreamHandle,
const RecordCommandFunction &record,
const FinishCommandFunction &finish);
void submitCommandStream(const CommandStreamHandle handle);
void prepareSwapchainImageForPresent(const CommandStreamHandle handle);
void prepareImageForSampling(const CommandStreamHandle cmdStream, const ImageHandle image);
}; };
} }
#pragma once #pragma once
#include <vkcv/ShaderProgram.hpp>
#include <vulkan/vulkan.hpp>
#include "vkcv/Handles.hpp"
#include "vkcv/ShaderStage.hpp"
namespace vkcv namespace vkcv
{ {
struct DescriptorSet
{
vk::DescriptorSet vulkanHandle;
vk::DescriptorSetLayout layout;
};
/* /*
* All the types of descriptors (resources) that can be retrieved by the shaders * All the types of descriptors (resources) that can be retrieved by the shaders
*/ */
...@@ -24,27 +34,16 @@ namespace vkcv ...@@ -24,27 +34,16 @@ namespace vkcv
*/ */
struct DescriptorBinding struct DescriptorBinding
{ {
DescriptorBinding() = delete;
DescriptorBinding( DescriptorBinding(
uint32_t bindingID,
DescriptorType descriptorType, DescriptorType descriptorType,
uint32_t descriptorCount, uint32_t descriptorCount,
ShaderStage shaderStage ShaderStage shaderStage
) noexcept; ) noexcept;
uint32_t bindingID;
DescriptorType descriptorType; DescriptorType descriptorType;
uint32_t descriptorCount; uint32_t descriptorCount;
ShaderStage shaderStage; ShaderStage shaderStage;
}; };
/*
* One descriptor set struct that contains all the necessary information for the actual creation.
* @param[in] a number of bindings that were created beforehand
* @param[in] the number of (identical) sets that should be created from the attached bindings
*/
struct DescriptorSetConfig
{
explicit DescriptorSetConfig(std::vector<DescriptorBinding> bindings) noexcept;
std::vector<DescriptorBinding> bindings;
};
} }
#pragma once
#include <vulkan/vulkan.hpp>
#include <vkcv/Handles.hpp>
#include <vkcv/DescriptorConfig.hpp>
namespace vkcv {
struct VertexBufferBinding {
inline VertexBufferBinding(vk::DeviceSize offset, vk::Buffer buffer) noexcept
: offset(offset), buffer(buffer) {}
vk::DeviceSize offset;
vk::Buffer buffer;
};
struct DescriptorSetUsage {
inline DescriptorSetUsage(uint32_t setLocation, vk::DescriptorSet vulkanHandle) noexcept
: setLocation(setLocation), vulkanHandle(vulkanHandle) {}
const uint32_t setLocation;
const vk::DescriptorSet vulkanHandle;
};
struct Mesh {
inline Mesh(std::vector<VertexBufferBinding> vertexBufferBindings, vk::Buffer indexBuffer, size_t indexCount) noexcept
: vertexBufferBindings(vertexBufferBindings), indexBuffer(indexBuffer), indexCount(indexCount){}
std::vector<VertexBufferBinding> vertexBufferBindings;
vk::Buffer indexBuffer;
size_t indexCount;
};
struct PushConstantData {
inline PushConstantData(void* data, size_t sizePerDrawcall) : data(data), sizePerDrawcall(sizePerDrawcall) {}
void* data;
size_t sizePerDrawcall;
};
struct DrawcallInfo {
inline DrawcallInfo(const Mesh& mesh, const std::vector<DescriptorSetUsage>& descriptorSets)
: mesh(mesh), descriptorSets(descriptorSets) {}
Mesh mesh;
std::vector<DescriptorSetUsage> descriptorSets;
};
void recordDrawcall(
const DrawcallInfo &drawcall,
vk::CommandBuffer cmdBuffer,
vk::PipelineLayout pipelineLayout,
const PushConstantData &pushConstantData,
const size_t drawcallIndex);
}
\ No newline at end of file
...@@ -79,7 +79,7 @@ namespace vkcv ...@@ -79,7 +79,7 @@ namespace vkcv
using Handle::Handle; using Handle::Handle;
}; };
class ResourcesHandle : public Handle { class DescriptorSetHandle : public Handle {
friend class DescriptorManager; friend class DescriptorManager;
private: private:
using Handle::Handle; using Handle::Handle;
...@@ -93,14 +93,19 @@ namespace vkcv ...@@ -93,14 +93,19 @@ namespace vkcv
class ImageHandle : public Handle { class ImageHandle : public Handle {
friend class ImageManager; friend class ImageManager;
private:
using Handle::Handle; using Handle::Handle;
public:
[[nodiscard]] [[nodiscard]]
bool isSwapchainImage() const; bool isSwapchainImage() const;
static ImageHandle createSwapchainImageHandle(const HandleDestroyFunction& destroy = nullptr); static ImageHandle createSwapchainImageHandle(const HandleDestroyFunction& destroy = nullptr);
}; };
class CommandStreamHandle : public Handle {
friend class CommandStreamManager;
private:
using Handle::Handle;
};
} }
...@@ -9,8 +9,12 @@ ...@@ -9,8 +9,12 @@
#include "Handles.hpp" #include "Handles.hpp"
namespace vkcv { namespace vkcv {
class ImageManager; // forward declares
class ImageManager;
bool isDepthFormat(const vk::Format format);
class Image { class Image {
friend class Core; friend class Core;
public: public:
...@@ -37,11 +41,9 @@ namespace vkcv { ...@@ -37,11 +41,9 @@ namespace vkcv {
void fill(void* data, size_t size = SIZE_MAX); void fill(void* data, size_t size = SIZE_MAX);
private: private:
ImageManager* const m_manager; ImageManager* const m_manager;
const ImageHandle m_handle; const ImageHandle m_handle;
const vk::Format m_format;
vk::ImageLayout m_layout;
Image(ImageManager* manager, const ImageHandle& handle, vk::Format format); Image(ImageManager* manager, const ImageHandle& handle);
static Image create(ImageManager* manager, vk::Format format, uint32_t width, uint32_t height, uint32_t depth); static Image create(ImageManager* manager, vk::Format format, uint32_t width, uint32_t height, uint32_t depth);
......
#pragma once
#include <iostream>
namespace vkcv {
enum class LogLevel {
INFO,
WARNING,
ERROR
};
constexpr auto getLogOutput(LogLevel level) {
switch (level) {
case LogLevel::INFO:
return stdout;
default:
return stderr;
}
}
constexpr const char* getLogName(LogLevel level) {
switch (level) {
case LogLevel::INFO:
return "INFO";
case LogLevel::WARNING:
return "WARNING";
case LogLevel::ERROR:
return "ERROR";
default:
return "UNKNOWN";
}
}
#ifndef NDEBUG
#ifndef VKCV_DEBUG_MESSAGE_LEN
#define VKCV_DEBUG_MESSAGE_LEN 1024
#endif
#ifdef _MSC_VER
#define __PRETTY_FUNCTION__ __FUNCSIG__
#endif
#define vkcv_log(level, ...) { \
char output_message [ \
VKCV_DEBUG_MESSAGE_LEN \
]; \
std::snprintf( \
output_message, \
VKCV_DEBUG_MESSAGE_LEN, \
__VA_ARGS__ \
); \
std::fprintf( \
getLogOutput(level), \
"[%s]: %s [%s, line %d: %s]\n", \