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 (109)
Showing
with 442 additions and 149 deletions
...@@ -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", \
vkcv::getLogName(level), \
output_message, \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__ \
); \
}
#else
#define vkcv_log(level, ...) {}
#endif
}
...@@ -32,23 +32,15 @@ namespace vkcv ...@@ -32,23 +32,15 @@ namespace vkcv
struct AttachmentDescription struct AttachmentDescription
{ {
AttachmentDescription() = delete;
AttachmentDescription( AttachmentDescription(
AttachmentLayout initial, AttachmentOperation store_op,
AttachmentLayout in_pass, AttachmentOperation load_op,
AttachmentLayout final, vk::Format format) noexcept;
AttachmentOperation store_op,
AttachmentOperation load_op,
vk::Format format) noexcept;
AttachmentLayout layout_initial;
AttachmentLayout layout_in_pass;
AttachmentLayout layout_final;
AttachmentOperation store_operation; AttachmentOperation store_operation;
AttachmentOperation load_operation; AttachmentOperation load_operation;
vk::Format format; vk::Format format;
}; };
struct PassConfig struct PassConfig
......
...@@ -7,9 +7,9 @@ ...@@ -7,9 +7,9 @@
#include <vector> #include <vector>
#include <cstdint> #include <cstdint>
#include "vkcv/Handles.hpp" #include "Handles.hpp"
#include "ShaderProgram.hpp" #include "ShaderProgram.hpp"
#include <vkcv/VertexLayout.hpp> #include "VertexLayout.hpp"
namespace vkcv { namespace vkcv {
...@@ -21,22 +21,26 @@ namespace vkcv { ...@@ -21,22 +21,26 @@ namespace vkcv {
* @param shaderProgram shaders of the pipeline * @param shaderProgram shaders of the pipeline
* @param height height of the application window * @param height height of the application window
* @param width width of the application window * @param width width of the application window
* @param passHandle handle for Render Pass * @param passHandle handle for render pass
* @param vertexLayout layout of vertex buffer, comprised of its bindings and the bindings' attachments
*/ */
PipelineConfig( PipelineConfig(
const ShaderProgram& shaderProgram, const ShaderProgram& shaderProgram,
uint32_t width, uint32_t width,
uint32_t height, uint32_t height,
PassHandle &passHandle, const PassHandle &passHandle,
const std::vector<VertexAttribute> &vertexAttributes, const VertexLayout &vertexLayouts,
const std::vector<vk::DescriptorSetLayout> &descriptorLayouts); const std::vector<vk::DescriptorSetLayout> &descriptorLayouts,
bool useDynamicViewport);
ShaderProgram m_ShaderProgram;
uint32_t m_Height;
uint32_t m_Width;
PassHandle m_PassHandle;
VertexLayout m_VertexLayout;
std::vector<vk::DescriptorSetLayout> m_DescriptorLayouts;
bool m_UseDynamicViewport;
ShaderProgram m_ShaderProgram;
uint32_t m_Height;
uint32_t m_Width;
PassHandle m_PassHandle;
std::vector<VertexAttribute> m_vertexAttributes;
std::vector<vk::DescriptorSetLayout> m_descriptorLayouts;
}; };
} }
\ No newline at end of file
...@@ -8,23 +8,16 @@ ...@@ -8,23 +8,16 @@
#include <unordered_map> #include <unordered_map>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <algorithm>
#include <filesystem> #include <filesystem>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include <spirv_cross.hpp> #include <spirv_cross.hpp>
#include "vkcv/VertexLayout.hpp" #include "VertexLayout.hpp"
#include "ShaderStage.hpp"
#include "DescriptorConfig.hpp"
namespace vkcv { namespace vkcv {
enum class ShaderStage
{
VERTEX,
TESS_CONTROL,
TESS_EVAL,
GEOMETRY,
FRAGMENT,
COMPUTE
};
struct Shader struct Shader
{ {
std::vector<char> shaderCode; std::vector<char> shaderCode;
...@@ -55,13 +48,24 @@ namespace vkcv { ...@@ -55,13 +48,24 @@ namespace vkcv {
bool existsShader(ShaderStage shaderStage) const; bool existsShader(ShaderStage shaderStage) const;
void reflectShader(ShaderStage shaderStage); const std::vector<VertexAttachment> &getVertexAttachments() const;
size_t getPushConstantSize() const;
const VertexLayout &getVertexLayout() const; const std::vector<std::vector<DescriptorBinding>> &getReflectedDescriptors() const;
private: private:
/**
* Called after successfully adding a shader to the program.
* Fills vertex input attachments and descriptor sets (if present).
* @param shaderStage the stage to reflect data from
*/
void reflectShader(ShaderStage shaderStage);
std::unordered_map<ShaderStage, Shader> m_Shaders; std::unordered_map<ShaderStage, Shader> m_Shaders;
VertexLayout m_VertexLayout; // contains all vertex input attachments used in the vertex buffer
std::vector<VertexAttachment> m_VertexAttachments;
std::vector<std::vector<DescriptorBinding>> m_DescriptorSets;
size_t m_pushConstantSize = 0;
}; };
} }
#pragma once
namespace vkcv {
enum class ShaderStage
{
VERTEX,
TESS_CONTROL,
TESS_EVAL,
GEOMETRY,
FRAGMENT,
COMPUTE
};
}
...@@ -107,7 +107,7 @@ namespace vkcv ...@@ -107,7 +107,7 @@ namespace vkcv
/** /**
* *
*/ */
void recreateSwapchain(); void signalSwapchainRecreation();
/** /**
* TODO * TODO
......
#pragma once #pragma once
#include <unordered_map>
#include <vector> #include <vector>
#include <iostream> #include <iostream>
#include <string>
namespace vkcv{ namespace vkcv{
enum class VertexAttachmentFormat{
/* With these enums, 0 is reserved to signal uninitialized or invalid data. */
enum class PrimitiveType : uint32_t {
UNDEFINED = 0,
POSITION = 1,
NORMAL = 2,
TEXCOORD_0 = 3
};
/* This struct describes one vertex attribute of a vertex buffer. */
typedef struct {
PrimitiveType type; // POSITION, NORMAL, ...
uint32_t offset; // offset in bytes
uint32_t length; // length of ... in bytes
uint32_t stride; // stride in bytes
uint16_t componentType; // eg. 5126 for float
uint8_t componentCount; // eg. 3 for vec3
} VertexAttribute;
enum class VertexFormat{
FLOAT, FLOAT,
FLOAT2, FLOAT2,
FLOAT3, FLOAT3,
...@@ -34,22 +16,51 @@ namespace vkcv{ ...@@ -34,22 +16,51 @@ namespace vkcv{
INT4 INT4
}; };
uint32_t getFormatSize(VertexFormat format); uint32_t getFormatSize(VertexAttachmentFormat format);
struct VertexInputAttachment{ struct VertexAttachment{
VertexInputAttachment() = delete; friend struct VertexBinding;
VertexInputAttachment(uint32_t location, uint32_t binding, VertexFormat format, uint32_t offset) noexcept; /**
* Describes an individual vertex input attribute/attachment.
* @param inputLocation its location in the vertex shader.
* @param name the name referred to in the shader.
* @param format the format (and therefore, the size) this attachment is in.
* The offset is calculated when a collection of attachments forms a binding, hence the friend declaration.
*/
VertexAttachment(uint32_t inputLocation, const std::string &name, VertexAttachmentFormat format) noexcept;
VertexAttachment() = delete;
uint32_t location; uint32_t inputLocation;
uint32_t binding; std::string name;
VertexFormat format; VertexAttachmentFormat format;
uint32_t offset; uint32_t offset;
};
struct VertexBinding{
/**
* Describes all vertex input attachments _one_ buffer contains to create a vertex buffer binding.
* NOTE: multiple vertex layouts may contain various (mutually exclusive) vertex input attachments
* to form one complete vertex buffer binding!
* @param bindingLocation its entry in the buffers that make up the whole vertex buffer.
* @param attachments the vertex input attachments this specific buffer layout contains.
*/
VertexBinding(uint32_t bindingLocation, const std::vector<VertexAttachment> &attachments) noexcept;
VertexBinding() = delete;
uint32_t bindingLocation;
uint32_t stride;
std::vector<VertexAttachment> vertexAttachments;
}; };
struct VertexLayout{ struct VertexLayout{
/**
* Describes the complete layout of one vertex, e.g. all of the vertex input attachments used,
* and all of the buffer bindings that refer to the attachments (for when multiple buffers are used).
* @param bindings bindings the complete vertex buffer is comprised of.
*/
VertexLayout() noexcept; VertexLayout() noexcept;
VertexLayout(const std::vector<VertexInputAttachment> &inputs) noexcept; VertexLayout(const std::vector<VertexBinding> &bindings) noexcept;
std::unordered_map<uint32_t, VertexInputAttachment> attachmentMap;
uint32_t stride; std::vector<VertexBinding> vertexBindings;
}; };
} }
\ No newline at end of file
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <cstdint> #include <cstdint>
#include <vkcv/VertexLayout.hpp>
/* These macros define limits of the following structs. Implementations can /* These macros define limits of the following structs. Implementations can
* test against these limits when performing sanity checks. The main constraint * test against these limits when performing sanity checks. The main constraint
...@@ -53,6 +52,23 @@ enum PrimitiveMode { ...@@ -53,6 +52,23 @@ enum PrimitiveMode {
/* The indices in the index buffer can be of different bit width. */ /* The indices in the index buffer can be of different bit width. */
enum IndexType { UINT32=0, UINT16=1, UINT8=2 }; enum IndexType { UINT32=0, UINT16=1, UINT8=2 };
/* With these enums, 0 is reserved to signal uninitialized or invalid data. */
enum class PrimitiveType : uint32_t {
UNDEFINED = 0,
POSITION = 1,
NORMAL = 2,
TEXCOORD_0 = 3
};
/* This struct describes one vertex attribute of a vertex buffer. */
typedef struct {
PrimitiveType type; // POSITION, NORMAL, ...
uint32_t offset; // offset in bytes
uint32_t length; // length of ... in bytes
uint32_t stride; // stride in bytes
uint16_t componentType; // eg. 5126 for float
uint8_t componentCount; // eg. 3 for vec3
} VertexAttribute;
typedef struct { typedef struct {
// TODO not yet needed for the first (unlit) triangle // TODO not yet needed for the first (unlit) triangle
} Material; } Material;
...@@ -71,7 +87,7 @@ typedef struct { ...@@ -71,7 +87,7 @@ typedef struct {
} indexBuffer; } indexBuffer;
struct { struct {
std::vector<uint8_t> data; // binary data of the vertex buffer std::vector<uint8_t> data; // binary data of the vertex buffer
std::vector<VertexAttribute> attributes; std::vector<VertexAttribute> attributes; // description of one
} vertexBuffer; } vertexBuffer;
struct { float x, y, z; } min; // bounding box lower left struct { float x, y, z; } min; // bounding box lower left
struct { float x, y, z; } max; // bounding box upper right struct { float x, y, z; } max; // bounding box upper right
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#define STBI_ONLY_JPEG #define STBI_ONLY_JPEG
#include <stb_image.h> #include <stb_image.h>
#include <vkcv/Logger.hpp>
namespace vkcv::asset { namespace vkcv::asset {
/** /**
...@@ -39,11 +41,12 @@ uint8_t convertTypeToInt(const fx::gltf::Accessor::Type type) { ...@@ -39,11 +41,12 @@ uint8_t convertTypeToInt(const fx::gltf::Accessor::Type type) {
* @param path path to file that is responsible for error * @param path path to file that is responsible for error
*/ */
void print_what (const std::exception& e, const std::string &path) { void print_what (const std::exception& e, const std::string &path) {
fprintf(stderr, "ERROR loading file %s: %s\n", path.c_str(), e.what()); vkcv_log(LogLevel::ERROR, "Loading file %s: %s",
path.c_str(), e.what());
try { try {
std::rethrow_if_nested(e); std::rethrow_if_nested(e);
} catch (const std::exception& nested) { } catch (const std::exception& nested) {
std::cerr << "nested: ";
print_what(nested, path); print_what(nested, path);
} }
} }
...@@ -121,7 +124,7 @@ int loadMesh(const std::string &path, Mesh &mesh) { ...@@ -121,7 +124,7 @@ int loadMesh(const std::string &path, Mesh &mesh) {
const size_t off = indexBufferView.byteOffset; const size_t off = indexBufferView.byteOffset;
const void *const ptr = ((char*)indexBuffer.data.data()) + off; const void *const ptr = ((char*)indexBuffer.data.data()) + off;
if (!memcpy(indexBufferData.data(), ptr, indexBufferView.byteLength)) { if (!memcpy(indexBufferData.data(), ptr, indexBufferView.byteLength)) {
std::cerr << "ERROR copying index buffer data.\n"; vkcv_log(LogLevel::ERROR, "Copying index buffer data");
return 0; return 0;
} }
} }
...@@ -136,7 +139,7 @@ int loadMesh(const std::string &path, Mesh &mesh) { ...@@ -136,7 +139,7 @@ int loadMesh(const std::string &path, Mesh &mesh) {
const size_t off = 0; const size_t off = 0;
const void *const ptr = ((char*)vertexBuffer.data.data()) + off; const void *const ptr = ((char*)vertexBuffer.data.data()) + off;
if (!memcpy(vertexBufferData.data(), ptr, vertexBuffer.byteLength)) { if (!memcpy(vertexBufferData.data(), ptr, vertexBuffer.byteLength)) {
std::cerr << "ERROR copying vertex buffer data.\n"; vkcv_log(LogLevel::ERROR, "Copying vertex buffer data");
return 0; return 0;
} }
} }
...@@ -150,9 +153,8 @@ int loadMesh(const std::string &path, Mesh &mesh) { ...@@ -150,9 +153,8 @@ int loadMesh(const std::string &path, Mesh &mesh) {
case fx::gltf::Accessor::ComponentType::UnsignedInt: case fx::gltf::Accessor::ComponentType::UnsignedInt:
indexType = UINT32; break; indexType = UINT32; break;
default: default:
std::cerr << "ERROR: Index type not supported: " << vkcv_log(LogLevel::ERROR, "Index type (%u) not supported",
static_cast<uint16_t>(indexAccessor.componentType) << static_cast<uint16_t>(indexAccessor.componentType));
std::endl;
return 0; return 0;
} }
......
...@@ -11,10 +11,13 @@ set(vkcv_camera_include ${PROJECT_SOURCE_DIR}/include) ...@@ -11,10 +11,13 @@ set(vkcv_camera_include ${PROJECT_SOURCE_DIR}/include)
set(vkcv_camera_sources set(vkcv_camera_sources
${vkcv_camera_include}/vkcv/camera/Camera.hpp ${vkcv_camera_include}/vkcv/camera/Camera.hpp
${vkcv_camera_source}/vkcv/camera/Camera.cpp ${vkcv_camera_source}/vkcv/camera/Camera.cpp
${vkcv_camera_include}/vkcv/camera/TrackballCamera.hpp
${vkcv_camera_source}/vkcv/camera/TrackballCamera.cpp
${vkcv_camera_include}/vkcv/camera/CameraManager.hpp ${vkcv_camera_include}/vkcv/camera/CameraManager.hpp
${vkcv_camera_source}/vkcv/camera/CameraManager.cpp ${vkcv_camera_source}/vkcv/camera/CameraManager.cpp
${vkcv_camera_include}/vkcv/camera/CameraController.hpp
${vkcv_camera_include}/vkcv/camera/PilotCameraController.hpp
${vkcv_camera_source}/vkcv/camera/PilotCameraController.cpp
${vkcv_camera_include}/vkcv/camera/TrackballCameraController.hpp
${vkcv_camera_source}/vkcv/camera/TrackballCameraController.cpp
) )
# adding source files to the project # adding source files to the project
......