Skip to content
Snippets Groups Projects
Verified Commit 61b71826 authored by Tobias Frisch's avatar Tobias Frisch
Browse files

Merge branch 'develop' into 91-compute-first-network

parents 62af3841 21de8ef7
No related branches found
No related tags found
1 merge request!79Draft: Resolve "Compute: First Network"
Pipeline #26955 passed
Showing
with 1324 additions and 545 deletions
...@@ -23,7 +23,7 @@ build_ubuntu_gcc: ...@@ -23,7 +23,7 @@ build_ubuntu_gcc:
- mkdir debug - mkdir debug
- cd debug - cd debug
- cmake -DCMAKE_BUILD_TYPE=Debug .. - cmake -DCMAKE_BUILD_TYPE=Debug ..
- cmake --build . - cmake --build . -j 4
artifacts: artifacts:
name: "Documentation - $CI_PIPELINE_ID" name: "Documentation - $CI_PIPELINE_ID"
paths: paths:
...@@ -49,7 +49,7 @@ build_win10_msvc: ...@@ -49,7 +49,7 @@ build_win10_msvc:
- mkdir debug - mkdir debug
- cd debug - cd debug
- cmake -DCMAKE_BUILD_TYPE=Debug .. - cmake -DCMAKE_BUILD_TYPE=Debug ..
- cmake --build . - cmake --build . -j 4
build_win10_mingw: build_win10_mingw:
only: only:
...@@ -66,7 +66,7 @@ build_win10_mingw: ...@@ -66,7 +66,7 @@ build_win10_mingw:
- mkdir debug - mkdir debug
- cd 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 --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 8 - cmake --build . -j 4
build_mac_clang: build_mac_clang:
only: only:
...@@ -85,7 +85,7 @@ build_mac_clang: ...@@ -85,7 +85,7 @@ build_mac_clang:
- export LDFLAGS="-L/usr/local/opt/llvm/lib" - export LDFLAGS="-L/usr/local/opt/llvm/lib"
- export CPPFLAGS="-I/usr/local/opt/llvm/include" - 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 -DCMAKE_C_COMPILER="/usr/local/opt/llvm/bin/clang" -DCMAKE_CXX_COMPILER="/usr/local/opt/llvm/bin/clang++" -DCMAKE_BUILD_TYPE=Debug ..
- cmake --build . - cmake --build . -j 4
deploy_doc_develop: deploy_doc_develop:
only: only:
......
...@@ -22,9 +22,6 @@ ...@@ -22,9 +22,6 @@
[submodule "modules/gui/lib/imgui"] [submodule "modules/gui/lib/imgui"]
path = modules/gui/lib/imgui path = modules/gui/lib/imgui
url = https://github.com/ocornut/imgui.git 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"] [submodule "lib/VulkanMemoryAllocator-Hpp"]
path = lib/VulkanMemoryAllocator-Hpp path = lib/VulkanMemoryAllocator-Hpp
url = https://github.com/malte-v/VulkanMemoryAllocator-Hpp.git url = https://github.com/malte-v/VulkanMemoryAllocator-Hpp.git
......
...@@ -65,7 +65,7 @@ add_library(vkcv STATIC ${vkcv_sources}) ...@@ -65,7 +65,7 @@ add_library(vkcv STATIC ${vkcv_sources})
if(MSVC) if(MSVC)
#enable multicore compilation on visual studio #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 #set source groups to create proper filters in visual studio
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${vkcv_sources}) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${vkcv_sources})
......
# adding all source files and header files of the framework: # adding all source files and header files of the framework:
set(vkcv_sources 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_include}/vkcv/Context.hpp
${vkcv_source}/vkcv/Context.cpp ${vkcv_source}/vkcv/Context.cpp
......
...@@ -76,8 +76,8 @@ namespace vkcv { ...@@ -76,8 +76,8 @@ namespace vkcv {
{} {}
[[nodiscard]] [[nodiscard]]
static Buffer<T> create(BufferManager* manager, BufferType type, size_t count, BufferMemoryType 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), type, count, memoryType); return Buffer<T>(manager, manager->createBuffer(type, count * sizeof(T), memoryType, supportIndirect), type, count, memoryType);
} }
}; };
......
...@@ -70,7 +70,7 @@ namespace vkcv ...@@ -70,7 +70,7 @@ namespace vkcv
* @param memoryType Type of buffers memory * @param memoryType Type of buffers memory
* @return New buffer handle * @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 * Returns the Vulkan buffer handle of a buffer
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "QueueManager.hpp" #include "QueueManager.hpp"
#include "DrawcallRecording.hpp" #include "DrawcallRecording.hpp"
#include "Features.hpp"
namespace vkcv namespace vkcv
{ {
...@@ -32,6 +33,9 @@ namespace vkcv ...@@ -32,6 +33,9 @@ namespace vkcv
[[nodiscard]] [[nodiscard]]
const vk::Device &getDevice() const; const vk::Device &getDevice() const;
[[nodiscard]]
const FeatureManager& getFeatureManager() const;
[[nodiscard]] [[nodiscard]]
const QueueManager& getQueueManager() const; const QueueManager& getQueueManager() const;
...@@ -41,8 +45,8 @@ namespace vkcv ...@@ -41,8 +45,8 @@ namespace vkcv
static Context create(const char *applicationName, static Context create(const char *applicationName,
uint32_t applicationVersion, uint32_t applicationVersion,
const std::vector<vk::QueueFlagBits>& queueFlags, const std::vector<vk::QueueFlagBits>& queueFlags,
const std::vector<const char *>& instanceExtensions, const Features& features,
const std::vector<const char *>& deviceExtensions); const std::vector<const char*>& instanceExtensions = {});
private: private:
/** /**
...@@ -53,11 +57,12 @@ namespace vkcv ...@@ -53,11 +57,12 @@ namespace vkcv
* @param device Vulkan-Device * @param device Vulkan-Device
*/ */
Context(vk::Instance instance, vk::PhysicalDevice physicalDevice, vk::Device 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::Instance m_Instance;
vk::PhysicalDevice m_PhysicalDevice; vk::PhysicalDevice m_PhysicalDevice;
vk::Device m_Device; vk::Device m_Device;
FeatureManager m_FeatureManager;
QueueManager m_QueueManager; QueueManager m_QueueManager;
vma::Allocator m_Allocator; vma::Allocator m_Allocator;
......
...@@ -7,14 +7,14 @@ ...@@ -7,14 +7,14 @@
#include <memory> #include <memory>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include "vkcv/Context.hpp" #include "Context.hpp"
#include "vkcv/Swapchain.hpp" #include "Swapchain.hpp"
#include "vkcv/Window.hpp" #include "Window.hpp"
#include "vkcv/PassConfig.hpp" #include "PassConfig.hpp"
#include "vkcv/Handles.hpp" #include "Handles.hpp"
#include "vkcv/Buffer.hpp" #include "Buffer.hpp"
#include "vkcv/Image.hpp" #include "Image.hpp"
#include "vkcv/PipelineConfig.hpp" #include "PipelineConfig.hpp"
#include "CommandResources.hpp" #include "CommandResources.hpp"
#include "SyncResources.hpp" #include "SyncResources.hpp"
#include "Result.hpp" #include "Result.hpp"
...@@ -139,8 +139,8 @@ namespace vkcv ...@@ -139,8 +139,8 @@ namespace vkcv
const char *applicationName, const char *applicationName,
uint32_t applicationVersion, uint32_t applicationVersion,
const std::vector<vk::QueueFlagBits>& queueFlags = {}, const std::vector<vk::QueueFlagBits>& queueFlags = {},
const std::vector<const char*>& instanceExtensions = {}, const Features& features = {},
const std::vector<const char*>& deviceExtensions = {}); 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. * Creates a basic vulkan graphics pipeline using @p config from the pipeline config class and returns it using the @p handle.
...@@ -185,8 +185,8 @@ namespace vkcv ...@@ -185,8 +185,8 @@ namespace vkcv
* return Buffer-Object * return Buffer-Object
*/ */
template<typename T> template<typename T>
Buffer<T> createBuffer(vkcv::BufferType type, size_t count, BufferMemoryType memoryType = BufferMemoryType::DEVICE_LOCAL) { 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); return Buffer<T>::create(m_BufferManager.get(), type, count, memoryType, supportIndirect);
} }
/** /**
...@@ -249,16 +249,16 @@ namespace vkcv ...@@ -249,16 +249,16 @@ namespace vkcv
bool beginFrame(uint32_t& width, uint32_t& height); bool beginFrame(uint32_t& width, uint32_t& height);
void recordDrawcallsToCmdStream( void recordDrawcallsToCmdStream(
const CommandStreamHandle cmdStreamHandle, const CommandStreamHandle& cmdStreamHandle,
const PassHandle renderpassHandle, const PassHandle& renderpassHandle,
const PipelineHandle pipelineHandle, const PipelineHandle pipelineHandle,
const PushConstants &pushConstants, const PushConstants &pushConstants,
const std::vector<DrawcallInfo> &drawcalls, const std::vector<DrawcallInfo> &drawcalls,
const std::vector<ImageHandle> &renderTargets); const std::vector<ImageHandle> &renderTargets);
void recordMeshShaderDrawcalls( void recordMeshShaderDrawcalls(
const CommandStreamHandle cmdStreamHandle, const CommandStreamHandle& cmdStreamHandle,
const PassHandle renderpassHandle, const PassHandle& renderpassHandle,
const PipelineHandle pipelineHandle, const PipelineHandle pipelineHandle,
const PushConstants& pushConstantData, const PushConstants& pushConstantData,
const std::vector<MeshShaderDrawcall>& drawcalls, const std::vector<MeshShaderDrawcall>& drawcalls,
...@@ -270,6 +270,20 @@ namespace vkcv ...@@ -270,6 +270,20 @@ namespace vkcv
const uint32_t dispatchCount[3], const uint32_t dispatchCount[3],
const std::vector<DescriptorSetUsage> &descriptorSetUsages, const std::vector<DescriptorSetUsage> &descriptorSetUsages,
const PushConstants& pushConstants); 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 PipelineHandle computePipeline,
const vkcv::BufferHandle buffer,
const size_t bufferArgOffset,
const std::vector<DescriptorSetUsage>& descriptorSetUsages,
const PushConstants& pushConstants);
/** /**
* @brief end recording and present image * @brief end recording and present image
...@@ -313,6 +327,14 @@ namespace vkcv ...@@ -313,6 +327,14 @@ namespace vkcv
void recordBlitImage(const CommandStreamHandle& cmdStream, const ImageHandle& src, const ImageHandle& dst, void recordBlitImage(const CommandStreamHandle& cmdStream, const ImageHandle& src, const ImageHandle& dst,
SamplerFilterType filterType); SamplerFilterType filterType);
void setDebugLabel(const BufferHandle &handle, const std::string &label);
void setDebugLabel(const PassHandle &handle, const std::string &label);
void setDebugLabel(const PipelineHandle &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 #pragma once
#include <vulkan/vulkan.hpp>
#include "vkcv/Handles.hpp" #include "vkcv/Handles.hpp"
#include "vkcv/ShaderStage.hpp" #include "vkcv/ShaderStage.hpp"
...@@ -41,12 +39,12 @@ namespace vkcv ...@@ -41,12 +39,12 @@ namespace vkcv
uint32_t bindingID, uint32_t bindingID,
DescriptorType descriptorType, DescriptorType descriptorType,
uint32_t descriptorCount, uint32_t descriptorCount,
ShaderStage shaderStage ShaderStages shaderStages
) noexcept; ) noexcept;
uint32_t bindingID; uint32_t bindingID;
DescriptorType descriptorType; DescriptorType descriptorType;
uint32_t descriptorCount; uint32_t descriptorCount;
ShaderStage shaderStage; ShaderStages shaderStages;
}; };
} }
...@@ -29,8 +29,19 @@ namespace vkcv { ...@@ -29,8 +29,19 @@ namespace vkcv {
}; };
struct Mesh { struct 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){} 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; std::vector<VertexBufferBinding> vertexBufferBindings;
vk::Buffer indexBuffer; vk::Buffer indexBuffer;
......
#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)) {
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;
};
}
...@@ -53,9 +53,10 @@ namespace vkcv { ...@@ -53,9 +53,10 @@ namespace vkcv {
VKCV_DEBUG_MESSAGE_LEN, \ VKCV_DEBUG_MESSAGE_LEN, \
__VA_ARGS__ \ __VA_ARGS__ \
); \ ); \
auto output = getLogOutput(level); \
if (level != vkcv::LogLevel::RAW_INFO) { \ if (level != vkcv::LogLevel::RAW_INFO) { \
fprintf( \ fprintf( \
getLogOutput(level), \ output, \
"[%s]: %s [%s, line %d: %s]\n", \ "[%s]: %s [%s, line %d: %s]\n", \
vkcv::getLogName(level), \ vkcv::getLogName(level), \
output_message, \ output_message, \
...@@ -65,12 +66,13 @@ namespace vkcv { ...@@ -65,12 +66,13 @@ namespace vkcv {
); \ ); \
} else { \ } else { \
fprintf( \ fprintf( \
getLogOutput(level), \ output, \
"[%s]: %s\n", \ "[%s]: %s\n", \
vkcv::getLogName(level), \ vkcv::getLogName(level), \
output_message \ output_message \
); \ ); \
} \ } \
fflush(output); \
} }
#else #else
......
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include <spirv_cross.hpp> #include <spirv_cross.hpp>
#include "VertexLayout.hpp" #include "VertexLayout.hpp"
#include "ShaderStage.hpp"
#include "DescriptorConfig.hpp" #include "DescriptorConfig.hpp"
#include "ShaderStage.hpp"
namespace vkcv { namespace vkcv {
......
#pragma once #pragma once
namespace vkcv { #include <vulkan/vulkan.hpp>
enum class ShaderStage
{
VERTEX,
TESS_CONTROL,
TESS_EVAL,
GEOMETRY,
FRAGMENT,
COMPUTE,
TASK,
MESH
};
namespace vkcv {
enum class ShaderStage : VkShaderStageFlags {
VERTEX = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eVertex),
TESS_CONTROL = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eTessellationControl),
TESS_EVAL = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eTessellationEvaluation),
GEOMETRY = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eGeometry),
FRAGMENT = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eFragment),
COMPUTE = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eCompute),
TASK = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eTaskNV),
MESH = static_cast<VkShaderStageFlags>(vk::ShaderStageFlagBits::eMeshNV)
};
using ShaderStages = vk::Flags<ShaderStage>;
constexpr vk::ShaderStageFlags getShaderStageFlags(ShaderStages shaderStages) noexcept {
return vk::ShaderStageFlags(static_cast<VkShaderStageFlags>(shaderStages));
}
constexpr ShaderStages operator|(ShaderStage stage0, ShaderStage stage1) noexcept {
return ShaderStages(stage0) | stage1;
}
constexpr ShaderStages operator&(ShaderStage stage0, ShaderStage stage1) noexcept {
return ShaderStages(stage0) & stage1;
}
constexpr ShaderStages operator^(ShaderStage stage0, ShaderStage stage1) noexcept {
return ShaderStages(stage0) ^ stage1;
}
constexpr ShaderStages operator~(ShaderStage stage) noexcept {
return ~(ShaderStages(stage));
}
} }
...@@ -31,10 +31,10 @@ include(config/FX_GLTF.cmake) ...@@ -31,10 +31,10 @@ include(config/FX_GLTF.cmake)
include(config/STB.cmake) include(config/STB.cmake)
# link the required libraries to the module # link the required libraries to the module
target_link_libraries(vkcv_asset_loader ${vkcv_asset_loader_libraries} vkcv) target_link_libraries(vkcv_asset_loader ${vkcv_asset_loader_libraries} vkcv ${vkcv_libraries})
# including headers of dependencies and the VkCV framework # including headers of dependencies and the VkCV framework
target_include_directories(vkcv_asset_loader SYSTEM BEFORE PRIVATE ${vkcv_asset_loader_includes}) target_include_directories(vkcv_asset_loader SYSTEM BEFORE PRIVATE ${vkcv_asset_loader_includes} ${vkcv_includes})
# add the own include directory for public headers # add the own include directory for public headers
target_include_directories(vkcv_asset_loader BEFORE PUBLIC ${vkcv_asset_loader_include}) target_include_directories(vkcv_asset_loader BEFORE PUBLIC ${vkcv_asset_loader_include})
......
...@@ -11,17 +11,7 @@ ...@@ -11,17 +11,7 @@
#include <cstdint> #include <cstdint>
#include <filesystem> #include <filesystem>
/** These macros define limits of the following structs. Implementations can /* LOADING MESHES
* test against these limits when performing sanity checks. The main constraint
* expressed is that of the data type: Material indices are identified by a
* uint8_t in the VertexGroup struct, so there can't be more than UINT8_MAX
* materials in the mesh. Should these limits be too narrow, the data type has
* to be changed, but the current ones should be generous enough for most use
* cases. */
#define MAX_MATERIALS_PER_MESH UINT8_MAX
#define MAX_VERTICES_PER_VERTEX_GROUP UINT32_MAX
/** LOADING MESHES
* The description of meshes is a hierarchy of structures with the Mesh at the * The description of meshes is a hierarchy of structures with the Mesh at the
* top. * top.
* *
...@@ -46,53 +36,89 @@ ...@@ -46,53 +36,89 @@
namespace vkcv::asset { namespace vkcv::asset {
/** This enum matches modes in fx-gltf, the library returns a standard mode /**
* (TRIANGLES) if no mode is given in the file. */ * These return codes are limited to the asset loader module. If unified return
* codes are defined for the vkcv framework, these will be used instead.
*/
#define ASSET_ERROR 0
#define ASSET_SUCCESS 1
/**
* This enum matches modes in fx-gltf, the library returns a standard mode
* (TRIANGLES) if no mode is given in the file.
*/
enum class PrimitiveMode : uint8_t { enum class PrimitiveMode : uint8_t {
POINTS=0, LINES, LINELOOP, LINESTRIP, TRIANGLES, TRIANGLESTRIP, POINTS = 0,
TRIANGLEFAN LINES = 1,
LINELOOP = 2,
LINESTRIP = 3,
TRIANGLES = 4,
TRIANGLESTRIP = 5,
TRIANGLEFAN = 6
}; };
/** The indices in the index buffer can be of different bit width. */ /**
enum class IndexType : uint8_t { UNDEFINED=0, UINT8=1, UINT16=2, UINT32=3 }; * The indices in the index buffer can be of different bit width.
*/
typedef struct { enum class IndexType : uint8_t {
// TODO define struct for samplers (low priority) UNDEFINED=0,
// NOTE: glTF defines samplers based on OpenGL, which can not be UINT8=1,
// directly translated to Vulkan. Specifically, OpenGL (and glTF) UINT16=2,
// define a different set of Min/Mag-filters than Vulkan. UINT32=3
} Sampler; };
/** struct for defining the loaded texture */
typedef struct {
int sampler; // index into the sampler array of the Scene
uint8_t channels; // number of channels
uint16_t w, h; // width and height of the texture
std::vector<uint8_t> data; // binary data of the decoded texture
} Texture;
/** The asset loader module only supports the PBR-MetallicRoughness model for /**
* materials.*/ * This struct defines a sampler for a texture object. All values here can
typedef struct { * directly be passed to VkSamplerCreateInfo.
uint16_t textureMask; // bit mask with active texture targets * NOTE that glTF defines samplers based on OpenGL, which can not be directly
// Indices into the Array.textures array * translated to Vulkan. The vkcv::asset::Sampler struct defined here adheres
int baseColor, metalRough, normal, occlusion, emissive; * to the Vulkan spec, having alerady translated the flags from glTF to Vulkan.
// Scaling factors for each texture target * Since glTF does not specify border sampling for more than two dimensions,
struct { float r, g, b, a; } baseColorFactor; * the addressModeW is hardcoded to a default: VK_SAMPLER_ADDRESS_MODE_REPEAT.
float metallicFactor, roughnessFactor; */
float normalScale; struct Sampler {
float occlusionStrength; int minFilter, magFilter;
struct { float r, g, b; } emissiveFactor; int mipmapMode;
} Material; float minLOD, maxLOD;
int addressModeU, addressModeV, addressModeW;
};
/** Flags for the bit-mask in the Material struct. To check if a material has a /**
* This struct describes a (partially) loaded texture.
* The data member is not populated after calling probeScene() but only when
* calling loadMesh(), loadScene() or loadTexture(). Note that textures are
* currently always loaded with 4 channels as RGBA, even if the image has just
* RGB or is grayscale. In the case where the glTF-file does not provide a URI
* but references a buffer view for the raw data, the path member will be empty
* even though the rest is initialized properly.
* NOTE: Loading textures without URI is untested.
*/
struct Texture {
std::filesystem::path path; // URI to the encoded texture data
int sampler; // index into the sampler array of the Scene
union { int width; int w; };
union { int height; int h; };
int channels;
std::vector<uint8_t> data; // binary data of the decoded texture
};
/**
* Flags for the bit-mask in the Material struct. To check if a material has a
* certain texture target, you can use the hasTexture() function below, passing * certain texture target, you can use the hasTexture() function below, passing
* the material struct and the enum. */ * the material struct and the enum.
*/
enum class PBRTextureTarget { enum class PBRTextureTarget {
baseColor=1, metalRough=2, normal=4, occlusion=8, emissive=16 baseColor=1,
metalRough=2,
normal=4,
occlusion=8,
emissive=16
}; };
/** This macro translates the index of an enum in the defined order to an /**
* This macro translates the index of an enum in the defined order to an
* integer with a single bit set in the corresponding place. It is used for * integer with a single bit set in the corresponding place. It is used for
* working with the bitmask of texture targets ("textureMask") in the Material * working with the bitmask of texture targets ("textureMask") in the Material
* struct: * struct:
...@@ -103,100 +129,196 @@ enum class PBRTextureTarget { ...@@ -103,100 +129,196 @@ enum class PBRTextureTarget {
* contact with bit-level operations. */ * contact with bit-level operations. */
#define bitflag(ENUM) (0x1u << ((unsigned)(ENUM))) #define bitflag(ENUM) (0x1u << ((unsigned)(ENUM)))
/** To signal that a certain texture target is active in a Material struct, its /**
* bit is set in the textureMask. You can use this function to check that: * The asset loader module only supports the PBR-MetallicRoughness model for
* Material mat = ...; * materials.
* if (materialHasTexture(&mat, baseColor)) {...} */ */
bool materialHasTexture(const Material *const m, const PBRTextureTarget t); struct Material {
uint16_t textureMask; // bit mask with active texture targets
// Indices into the Scene.textures vector
int baseColor, metalRough, normal, occlusion, emissive;
// Scaling factors for each texture target
struct { float r, g, b, a; } baseColorFactor;
float metallicFactor, roughnessFactor;
float normalScale;
float occlusionStrength;
struct { float r, g, b; } emissiveFactor;
/**
* To signal that a certain texture target is active in this Material
* struct, its bit is set in the textureMask. You can use this function
* to check that:
* if (myMaterial.hasTexture(baseColor)) {...}
*
* @param t The target to query for
* @return Boolean to signal whether the texture target is active in
* the material.
*/
bool hasTexture(PBRTextureTarget target) const;
};
/** With these enums, 0 is reserved to signal uninitialized or invalid data. */ /* With these enums, 0 is reserved to signal uninitialized or invalid data. */
enum class PrimitiveType : uint32_t { enum class PrimitiveType : uint32_t {
UNDEFINED = 0, UNDEFINED = 0,
POSITION = 1, POSITION = 1,
NORMAL = 2, NORMAL = 2,
TEXCOORD_0 = 3, TEXCOORD_0 = 3,
TEXCOORD_1 = 4, TEXCOORD_1 = 4,
TANGENT = 5 TANGENT = 5,
COLOR_0 = 6,
COLOR_1 = 7,
JOINTS_0 = 8,
WEIGHTS_0 = 9
}; };
/** These integer values are used the same way in OpenGL, Vulkan and glTF. This /**
* These integer values are used the same way in OpenGL, Vulkan and glTF. This
* enum is not needed for translation, it's only for the programmers * enum is not needed for translation, it's only for the programmers
* convenience (easier to read in if/switch statements etc). While this enum * convenience (easier to read in if/switch statements etc). While this enum
* exists in (almost) the same definition in the fx-gltf library, we want to * exists in (almost) the same definition in the fx-gltf library, we want to
* avoid exposing that dependency, thus it is re-defined here. */ * avoid exposing that dependency, thus it is re-defined here.
*/
enum class ComponentType : uint16_t { enum class ComponentType : uint16_t {
NONE = 0, INT8 = 5120, UINT8 = 5121, INT16 = 5122, UINT16 = 5123, NONE = 0,
UINT32 = 5125, FLOAT32 = 5126 INT8 = 5120,
UINT8 = 5121,
INT16 = 5122,
UINT16 = 5123,
UINT32 = 5125,
FLOAT32 = 5126
}; };
/** This struct describes one vertex attribute of a vertex buffer. */ /**
typedef struct { * This struct describes one vertex attribute of a vertex buffer.
*/
struct VertexAttribute {
PrimitiveType type; // POSITION, NORMAL, ... PrimitiveType type; // POSITION, NORMAL, ...
uint32_t offset; // offset in bytes uint32_t offset; // offset in bytes
uint32_t length; // length of ... in bytes uint32_t length; // length of ... in bytes
uint32_t stride; // stride in bytes uint32_t stride; // stride in bytes
ComponentType componentType; // eg. 5126 for float
uint8_t componentCount; // eg. 3 for vec3 ComponentType componentType; // eg. 5126 for float
} VertexAttribute; uint8_t componentCount; // eg. 3 for vec3
};
/** This struct represents one (possibly the only) part of a mesh. There is /**
* This struct represents one (possibly the only) part of a mesh. There is
* always one vertexBuffer and zero or one indexBuffer (indexed rendering is * always one vertexBuffer and zero or one indexBuffer (indexed rendering is
* common but not always used). If there is no index buffer, this is indicated * common but not always used). If there is no index buffer, this is indicated
* by indexBuffer.data being empty. Each vertex buffer can have one or more * by indexBuffer.data being empty. Each vertex buffer can have one or more
* vertex attributes. */ * vertex attributes.
typedef struct { */
struct VertexGroup {
enum PrimitiveMode mode; // draw as points, lines or triangle? enum PrimitiveMode mode; // draw as points, lines or triangle?
size_t numIndices, numVertices; size_t numIndices;
size_t numVertices;
struct { struct {
enum IndexType type; // data type of the indices enum IndexType type; // data type of the indices
std::vector<uint8_t> data; // binary data of the index buffer std::vector<uint8_t> data; // binary data of the index buffer
} 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; // description of one 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
int materialIndex; // index to one of the materials int materialIndex; // index to one of the materials
} VertexGroup; };
/** This struct represents a single mesh as it was loaded from a glTF file. It /**
* This struct represents a single mesh as it was loaded from a glTF file. It
* consists of at least one VertexGroup, which then references other resources * consists of at least one VertexGroup, which then references other resources
* such as Materials. */ * such as Materials.
typedef struct { */
struct Mesh {
std::string name; std::string name;
std::array<float, 16> modelMatrix; std::array<float, 16> modelMatrix;
std::vector<int> vertexGroups; std::vector<int> vertexGroups;
} Mesh; };
/** The scene struct is simply a collection of objects in the scene as well as /**
* The scene struct is simply a collection of objects in the scene as well as
* the resources used by those objects. * the resources used by those objects.
* For now the only type of object are the meshes and they are represented in a * Note that parent-child relations are not yet possible.
* flat array. */
* Note that parent-child relations are not yet possible. */ struct Scene {
typedef struct {
std::vector<Mesh> meshes; std::vector<Mesh> meshes;
std::vector<VertexGroup> vertexGroups; std::vector<VertexGroup> vertexGroups;
std::vector<Material> materials; std::vector<Material> materials;
std::vector<Texture> textures; std::vector<Texture> textures;
std::vector<Sampler> samplers; std::vector<Sampler> samplers;
} Scene; std::vector<std::string> uris;
};
/** /**
* Load every mesh from the glTF file, as well as materials and textures. * Parse the given glTF file and create a shallow description of the content.
* Only the meta-data of the objects in the scene is loaded, not the binary
* content. The rationale is to provide a means of probing the content of a
* glTF file without the costly process of loading and decoding large amounts
* of data. The returned Scene struct can be used to search for specific meshes
* in the scene, that can then be loaded on their own using the loadMesh()
* function. Note that the Scene struct received as output argument will be
* overwritten by this function.
* After this function completes, the returned Scene struct is completely
* initialized and all information is final, except for the missing binary
* data. This means that indices to vectors will remain valid even when the
* shallow scene struct is filled with data by loadMesh().
* Note that for URIs only (local) filesystem paths are supported, no
* URLs using network protocols etc.
* *
* @param path must be the path to a glTF or glb file. * @param path must be the path to a glTF- or glb-file.
* @param scene is a reference to a Scene struct that will be filled with the
* meta-data of all objects described in the glTF file.
* @return ASSET_ERROR on failure, otherwise ASSET_SUCCESS
*/
int probeScene(const std::filesystem::path &path, Scene &scene);
/**
* This function loads a single mesh from the given file and adds it to the
* given scene. The scene must already be initialized (via probeScene()).
* The mesh_index refers to the Scenes meshes array and identifies the mesh to
* load. To find the mesh you want, iterate over the probed scene and check the
* meshes details (eg. name).
* Besides the mesh, this function will also add any associated data to the
* Scene struct such as Materials and Textures required by the Mesh.
*
* @param path must be the path to a glTF- or glb-file.
* @param scene is the scene struct to which the results will be written.
* @return ASSET_ERROR on failure, otherwise ASSET_SUCCESS
*/
int loadMesh(Scene &scene, int mesh_index);
/**
* Load every mesh from the glTF file, as well as materials, textures and other
* associated objects.
*
* @param path must be the path to a glTF- or glb-file.
* @param scene is a reference to a Scene struct that will be filled with the * @param scene is a reference to a Scene struct that will be filled with the
* content of the glTF file being loaded. * content of the glTF file being loaded.
* */ * @return ASSET_ERROR on failure, otherwise ASSET_SUCCESS
int loadScene(const std::string &path, Scene &scene); */
int loadScene(const std::filesystem::path &path, Scene &scene);
struct TextureData {
int width; /**
int height; * Simply loads a single image at the given path and returns a Texture
int componentCount; * struct describing it. This is for special use cases only (eg.
std::vector<char*> data; * loading a font atlas) and not meant to be used for regular assets.
}; * The sampler is set to -1, signalling that this Texture was loaded
TextureData loadTexture(const std::filesystem::path& path); * outside the context of a glTF-file.
* If there was an error loading or decoding the image, the returned struct
* will be cleared to all 0 with path and data being empty; make sure to always
* check that !data.empty() before using the struct.
*
* @param path must be the path to an image file.
* @return Texture struct describing the loaded image.
*/
Texture loadTexture(const std::filesystem::path& path);
} } // end namespace vkcv::asset
This diff is collapsed.
...@@ -29,42 +29,6 @@ namespace vkcv::camera { ...@@ -29,42 +29,6 @@ namespace vkcv::camera {
float m_fov_min; float m_fov_min;
float m_fov_max; float m_fov_max;
/**
* @brief Indicates forward movement of the camera depending on the performed @p action.
* @param[in] action The performed action.
*/
void moveForward(int action);
/**
* @brief Indicates backward movement of the camera depending on the performed @p action.
* @param[in] action The performed action.
*/
void moveBackward(int action);
/**
* @brief Indicates left movement of the camera depending on the performed @p action.
* @param[in] action The performed action.
*/
void moveLeft(int action);
/**
* @brief Indicates right movement of the camera depending on the performed @p action.
* @param[in] action The performed action.
*/
void moveRight(int action);
/**
* @brief Indicates upward movement of the camera depending on the performed @p action.
* @param[in] action The performed action.
*/
void moveUpward(int action);
/**
* @brief Indicates downward movement of the camera depending on the performed @p action.
* @param[in] action The performed action.
*/
void moveDownward(int action);
public: public:
/** /**
......
...@@ -52,8 +52,8 @@ namespace vkcv::camera { ...@@ -52,8 +52,8 @@ namespace vkcv::camera {
} }
void CameraManager::mouseMoveCallback(double x, double y){ void CameraManager::mouseMoveCallback(double x, double y){
auto xoffset = static_cast<float>(x - m_lastX); auto xoffset = static_cast<float>(x - m_lastX) / m_window.getWidth();
auto yoffset = static_cast<float>(y - m_lastY); auto yoffset = static_cast<float>(y - m_lastY) / m_window.getHeight();
m_lastX = x; m_lastX = x;
m_lastY = y; m_lastY = y;
getActiveController().mouseMoveCallback(xoffset, yoffset, getActiveCamera()); getActiveController().mouseMoveCallback(xoffset, yoffset, getActiveCamera());
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment