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

Target

Select target project
  • vulkan2021/vkcv-framework
1 result
Show changes
Commits on Source (154)
Showing
with 1324 additions and 545 deletions
......@@ -23,7 +23,7 @@ build_ubuntu_gcc:
- mkdir debug
- cd debug
- cmake -DCMAKE_BUILD_TYPE=Debug ..
- cmake --build .
- cmake --build . -j 4
artifacts:
name: "Documentation - $CI_PIPELINE_ID"
paths:
......@@ -49,7 +49,7 @@ build_win10_msvc:
- mkdir debug
- cd debug
- cmake -DCMAKE_BUILD_TYPE=Debug ..
- cmake --build .
- cmake --build . -j 4
build_win10_mingw:
only:
......@@ -66,7 +66,7 @@ build_win10_mingw:
- mkdir debug
- cd debug
- cmake --no-warn-unused-cli -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=C:\msys64\mingw64\bin\x86_64-w64-mingw32-gcc.exe -DCMAKE_CXX_COMPILER:FILEPATH=C:\msys64\mingw64\bin\x86_64-w64-mingw32-g++.exe .. -G "Unix Makefiles"
- cmake --build . -j 8
- cmake --build . -j 4
build_mac_clang:
only:
......@@ -85,7 +85,7 @@ build_mac_clang:
- export LDFLAGS="-L/usr/local/opt/llvm/lib"
- export CPPFLAGS="-I/usr/local/opt/llvm/include"
- cmake -DCMAKE_C_COMPILER="/usr/local/opt/llvm/bin/clang" -DCMAKE_CXX_COMPILER="/usr/local/opt/llvm/bin/clang++" -DCMAKE_BUILD_TYPE=Debug ..
- cmake --build .
- cmake --build . -j 4
deploy_doc_develop:
only:
......
......@@ -22,9 +22,6 @@
[submodule "modules/gui/lib/imgui"]
path = modules/gui/lib/imgui
url = https://github.com/ocornut/imgui.git
[submodule "lib/VulkanMemoryAllocator"]
path = lib/VulkanMemoryAllocator
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
[submodule "lib/VulkanMemoryAllocator-Hpp"]
path = lib/VulkanMemoryAllocator-Hpp
url = https://github.com/malte-v/VulkanMemoryAllocator-Hpp.git
......
......@@ -65,7 +65,7 @@ add_library(vkcv STATIC ${vkcv_sources})
if(MSVC)
#enable multicore compilation on visual studio
target_compile_options(vkcv PRIVATE "/MP" "/openmp")
target_compile_options(vkcv PRIVATE "/MP" "/openmp" "/Zc:offsetof-")
#set source groups to create proper filters in visual studio
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${vkcv_sources})
......
# adding all source files and header files of the framework:
set(vkcv_sources
${vkcv_include}/vkcv/Features.hpp
${vkcv_source}/vkcv/Features.cpp
${vkcv_include}/vkcv/FeatureManager.hpp
${vkcv_source}/vkcv/FeatureManager.cpp
${vkcv_include}/vkcv/Context.hpp
${vkcv_source}/vkcv/Context.cpp
......
......@@ -76,8 +76,8 @@ namespace vkcv {
{}
[[nodiscard]]
static Buffer<T> create(BufferManager* manager, BufferType type, size_t count, BufferMemoryType memoryType) {
return Buffer<T>(manager, manager->createBuffer(type, count * sizeof(T), memoryType), type, count, memoryType);
static Buffer<T> create(BufferManager* manager, BufferType type, size_t count, BufferMemoryType memoryType, bool supportIndirect) {
return Buffer<T>(manager, manager->createBuffer(type, count * sizeof(T), memoryType, supportIndirect), type, count, memoryType);
}
};
......
......@@ -70,7 +70,7 @@ namespace vkcv
* @param memoryType Type of buffers memory
* @return New buffer handle
*/
BufferHandle createBuffer(BufferType type, size_t size, BufferMemoryType memoryType);
BufferHandle createBuffer(BufferType type, size_t size, BufferMemoryType memoryType, bool supportIndirect);
/**
* Returns the Vulkan buffer handle of a buffer
......
......@@ -5,6 +5,7 @@
#include "QueueManager.hpp"
#include "DrawcallRecording.hpp"
#include "Features.hpp"
namespace vkcv
{
......@@ -32,6 +33,9 @@ namespace vkcv
[[nodiscard]]
const vk::Device &getDevice() const;
[[nodiscard]]
const FeatureManager& getFeatureManager() const;
[[nodiscard]]
const QueueManager& getQueueManager() const;
......@@ -41,8 +45,8 @@ namespace vkcv
static Context create(const char *applicationName,
uint32_t applicationVersion,
const std::vector<vk::QueueFlagBits>& queueFlags,
const std::vector<const char *>& instanceExtensions,
const std::vector<const char *>& deviceExtensions);
const Features& features,
const std::vector<const char*>& instanceExtensions = {});
private:
/**
......@@ -53,11 +57,12 @@ namespace vkcv
* @param device Vulkan-Device
*/
Context(vk::Instance instance, vk::PhysicalDevice physicalDevice, vk::Device device,
QueueManager&& queueManager, vma::Allocator&& allocator) noexcept;
FeatureManager&& featureManager, QueueManager&& queueManager, vma::Allocator&& allocator) noexcept;
vk::Instance m_Instance;
vk::PhysicalDevice m_PhysicalDevice;
vk::Device m_Device;
FeatureManager m_FeatureManager;
QueueManager m_QueueManager;
vma::Allocator m_Allocator;
......
......@@ -7,14 +7,14 @@
#include <memory>
#include <vulkan/vulkan.hpp>
#include "vkcv/Context.hpp"
#include "vkcv/Swapchain.hpp"
#include "vkcv/Window.hpp"
#include "vkcv/PassConfig.hpp"
#include "vkcv/Handles.hpp"
#include "vkcv/Buffer.hpp"
#include "vkcv/Image.hpp"
#include "vkcv/PipelineConfig.hpp"
#include "Context.hpp"
#include "Swapchain.hpp"
#include "Window.hpp"
#include "PassConfig.hpp"
#include "Handles.hpp"
#include "Buffer.hpp"
#include "Image.hpp"
#include "PipelineConfig.hpp"
#include "CommandResources.hpp"
#include "SyncResources.hpp"
#include "Result.hpp"
......@@ -139,8 +139,8 @@ namespace vkcv
const char *applicationName,
uint32_t applicationVersion,
const std::vector<vk::QueueFlagBits>& queueFlags = {},
const std::vector<const char*>& instanceExtensions = {},
const std::vector<const char*>& deviceExtensions = {});
const Features& features = {},
const std::vector<const char *>& instanceExtensions = {});
/**
* Creates a basic vulkan graphics pipeline using @p config from the pipeline config class and returns it using the @p handle.
......@@ -185,8 +185,8 @@ namespace vkcv
* return Buffer-Object
*/
template<typename T>
Buffer<T> createBuffer(vkcv::BufferType type, size_t count, BufferMemoryType memoryType = BufferMemoryType::DEVICE_LOCAL) {
return Buffer<T>::create(m_BufferManager.get(), type, count, memoryType);
Buffer<T> createBuffer(vkcv::BufferType type, size_t count, BufferMemoryType memoryType = BufferMemoryType::DEVICE_LOCAL, bool supportIndirect = false) {
return Buffer<T>::create(m_BufferManager.get(), type, count, memoryType, supportIndirect);
}
/**
......@@ -249,16 +249,16 @@ namespace vkcv
bool beginFrame(uint32_t& width, uint32_t& height);
void recordDrawcallsToCmdStream(
const CommandStreamHandle cmdStreamHandle,
const PassHandle renderpassHandle,
const CommandStreamHandle& cmdStreamHandle,
const PassHandle& renderpassHandle,
const PipelineHandle pipelineHandle,
const PushConstants &pushConstants,
const std::vector<DrawcallInfo> &drawcalls,
const std::vector<ImageHandle> &renderTargets);
void recordMeshShaderDrawcalls(
const CommandStreamHandle cmdStreamHandle,
const PassHandle renderpassHandle,
const CommandStreamHandle& cmdStreamHandle,
const PassHandle& renderpassHandle,
const PipelineHandle pipelineHandle,
const PushConstants& pushConstantData,
const std::vector<MeshShaderDrawcall>& drawcalls,
......@@ -270,6 +270,20 @@ namespace vkcv
const uint32_t dispatchCount[3],
const std::vector<DescriptorSetUsage> &descriptorSetUsages,
const PushConstants& pushConstants);
void recordBeginDebugLabel(const CommandStreamHandle &cmdStream,
const std::string& label,
const std::array<float, 4>& color);
void recordEndDebugLabel(const CommandStreamHandle &cmdStream);
void recordComputeIndirectDispatchToCmdStream(
const CommandStreamHandle cmdStream,
const PipelineHandle computePipeline,
const vkcv::BufferHandle buffer,
const size_t bufferArgOffset,
const std::vector<DescriptorSetUsage>& descriptorSetUsages,
const PushConstants& pushConstants);
/**
* @brief end recording and present image
......@@ -312,6 +326,14 @@ namespace vkcv
void recordBlitImage(const CommandStreamHandle& cmdStream, const ImageHandle& src, const ImageHandle& dst,
SamplerFilterType filterType);
void setDebugLabel(const BufferHandle &handle, const std::string &label);
void setDebugLabel(const PassHandle &handle, const std::string &label);
void setDebugLabel(const 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
#include <vulkan/vulkan.hpp>
#include "vkcv/Handles.hpp"
#include "vkcv/ShaderStage.hpp"
......@@ -41,12 +39,12 @@ namespace vkcv
uint32_t bindingID,
DescriptorType descriptorType,
uint32_t descriptorCount,
ShaderStage shaderStage
ShaderStages shaderStages
) noexcept;
uint32_t bindingID;
DescriptorType descriptorType;
uint32_t descriptorCount;
ShaderStage shaderStage;
ShaderStages shaderStages;
};
}
......@@ -29,8 +29,19 @@ namespace vkcv {
};
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;
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 {
VKCV_DEBUG_MESSAGE_LEN, \
__VA_ARGS__ \
); \
auto output = getLogOutput(level); \
if (level != vkcv::LogLevel::RAW_INFO) { \
fprintf( \
getLogOutput(level), \
output, \
"[%s]: %s [%s, line %d: %s]\n", \
vkcv::getLogName(level), \
output_message, \
......@@ -65,12 +66,13 @@ namespace vkcv {
); \
} else { \
fprintf( \
getLogOutput(level), \
output, \
"[%s]: %s\n", \
vkcv::getLogName(level), \
output_message \
); \
} \
fflush(output); \
}
#else
......
......@@ -13,8 +13,8 @@
#include <vulkan/vulkan.hpp>
#include <spirv_cross.hpp>
#include "VertexLayout.hpp"
#include "ShaderStage.hpp"
#include "DescriptorConfig.hpp"
#include "ShaderStage.hpp"
namespace vkcv {
......
#pragma once
namespace vkcv {
enum class ShaderStage
{
VERTEX,
TESS_CONTROL,
TESS_EVAL,
GEOMETRY,
FRAGMENT,
COMPUTE,
TASK,
MESH
};
#include <vulkan/vulkan.hpp>
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)
include(config/STB.cmake)
# 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
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
target_include_directories(vkcv_asset_loader BEFORE PUBLIC ${vkcv_asset_loader_include})
......
......@@ -11,17 +11,7 @@
#include <cstdint>
#include <filesystem>
/** These macros define limits of the following structs. Implementations can
* 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
/* LOADING MESHES
* The description of meshes is a hierarchy of structures with the Mesh at the
* top.
*
......@@ -46,53 +36,89 @@
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 {
POINTS=0, LINES, LINELOOP, LINESTRIP, TRIANGLES, TRIANGLESTRIP,
TRIANGLEFAN
POINTS = 0,
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 };
typedef struct {
// TODO define struct for samplers (low priority)
// NOTE: glTF defines samplers based on OpenGL, which can not be
// directly translated to Vulkan. Specifically, OpenGL (and glTF)
// define a different set of Min/Mag-filters than Vulkan.
} 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 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 asset loader module only supports the PBR-MetallicRoughness model for
* materials.*/
typedef struct {
uint16_t textureMask; // bit mask with active texture targets
// Indices into the Array.textures array
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;
} Material;
/**
* This struct defines a sampler for a texture object. All values here can
* directly be passed to VkSamplerCreateInfo.
* NOTE that glTF defines samplers based on OpenGL, which can not be directly
* translated to Vulkan. The vkcv::asset::Sampler struct defined here adheres
* to the Vulkan spec, having alerady translated the flags from glTF to Vulkan.
* Since glTF does not specify border sampling for more than two dimensions,
* the addressModeW is hardcoded to a default: VK_SAMPLER_ADDRESS_MODE_REPEAT.
*/
struct Sampler {
int minFilter, magFilter;
int mipmapMode;
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
* the material struct and the enum. */
* the material struct and the enum.
*/
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
* working with the bitmask of texture targets ("textureMask") in the Material
* struct:
......@@ -103,100 +129,196 @@ enum class PBRTextureTarget {
* contact with bit-level operations. */
#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:
* Material mat = ...;
* if (materialHasTexture(&mat, baseColor)) {...} */
bool materialHasTexture(const Material *const m, const PBRTextureTarget t);
/**
* The asset loader module only supports the PBR-MetallicRoughness model for
* materials.
*/
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 {
UNDEFINED = 0,
POSITION = 1,
NORMAL = 2,
TEXCOORD_0 = 3,
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
* 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
* 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 {
NONE = 0, INT8 = 5120, UINT8 = 5121, INT16 = 5122, UINT16 = 5123,
UINT32 = 5125, FLOAT32 = 5126
NONE = 0,
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, ...
uint32_t offset; // offset in bytes
uint32_t length; // length of ... in bytes
uint32_t stride; // stride in bytes
ComponentType componentType; // eg. 5126 for float
uint8_t componentCount; // eg. 3 for vec3
} VertexAttribute;
ComponentType componentType; // eg. 5126 for float
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
* 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
* vertex attributes. */
typedef struct {
* vertex attributes.
*/
struct VertexGroup {
enum PrimitiveMode mode; // draw as points, lines or triangle?
size_t numIndices, numVertices;
size_t numIndices;
size_t numVertices;
struct {
enum IndexType type; // data type of the indices
std::vector<uint8_t> data; // binary data of the index buffer
} indexBuffer;
struct {
std::vector<uint8_t> data; // binary data of the vertex buffer
std::vector<VertexAttribute> attributes; // description of one
} vertexBuffer;
struct { float x, y, z; } min; // bounding box lower left
struct { float x, y, z; } max; // bounding box upper right
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
* such as Materials. */
typedef struct {
* such as Materials.
*/
struct Mesh {
std::string name;
std::array<float, 16> modelMatrix;
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.
* For now the only type of object are the meshes and they are represented in a
* flat array.
* Note that parent-child relations are not yet possible. */
typedef struct {
* Note that parent-child relations are not yet possible.
*/
struct Scene {
std::vector<Mesh> meshes;
std::vector<VertexGroup> vertexGroups;
std::vector<Material> materials;
std::vector<Texture> textures;
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
* content of the glTF file being loaded.
* */
int loadScene(const std::string &path, Scene &scene);
struct TextureData {
int width;
int height;
int componentCount;
std::vector<char*> data;
};
TextureData loadTexture(const std::filesystem::path& path);
* @return ASSET_ERROR on failure, otherwise ASSET_SUCCESS
*/
int loadScene(const std::filesystem::path &path, Scene &scene);
/**
* Simply loads a single image at the given path and returns a Texture
* struct describing it. This is for special use cases only (eg.
* 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
* 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
......@@ -29,42 +29,6 @@ namespace vkcv::camera {
float m_fov_min;
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:
/**
......
......@@ -52,8 +52,8 @@ namespace vkcv::camera {
}
void CameraManager::mouseMoveCallback(double x, double y){
auto xoffset = static_cast<float>(x - m_lastX);
auto yoffset = static_cast<float>(y - m_lastY);
auto xoffset = static_cast<float>(x - m_lastX) / m_window.getWidth();
auto yoffset = static_cast<float>(y - m_lastY) / m_window.getHeight();
m_lastX = x;
m_lastY = y;
getActiveController().mouseMoveCallback(xoffset, yoffset, getActiveCamera());
......