improved docs

This commit is contained in:
Jorijn van der Graaf 2025-06-14 14:58:02 +02:00
commit dfe9b1abe9
16 changed files with 315 additions and 40 deletions

View file

@ -607,7 +607,7 @@ HIDE_UNDOC_MEMBERS = NO
# if EXTRACT_ALL is enabled. # if EXTRACT_ALL is enabled.
# The default value is: NO. # The default value is: NO.
HIDE_UNDOC_CLASSES = NO HIDE_UNDOC_CLASSES = YES
# If the HIDE_UNDOC_NAMESPACES tag is set to YES, Doxygen will hide all # If the HIDE_UNDOC_NAMESPACES tag is set to YES, Doxygen will hide all
# undocumented namespaces that are normally visible in the namespace hierarchy. # undocumented namespaces that are normally visible in the namespace hierarchy.

View file

@ -28,6 +28,9 @@ import Crafter.Math;
import Crafter.Event; import Crafter.Event;
namespace Crafter { namespace Crafter {
/**
* @brief Camera with projection and view matrices.
*/
export class Camera { export class Camera {
public: public:
MatrixRowMajor<float, 4, 4, 1> projection; MatrixRowMajor<float, 4, 4, 1> projection;
@ -45,7 +48,7 @@ namespace Crafter {
Camera(float fov, float aspectRatio, float near, float far); Camera(float fov, float aspectRatio, float near, float far);
/** /**
* @brief calculates the projectionView matrix by multiplying the projection and view matricies. * @brief Calculates the projectionView matrix by multiplying the projection and view matricies.
*/ */
void Update(); void Update();

View file

@ -35,22 +35,31 @@ import :WindowWaylandVulkan;
import :VulkanPipeline; import :VulkanPipeline;
namespace Crafter { namespace Crafter {
export struct DescriptorEntry { struct DescriptorEntry {
VkDescriptorType type; VkDescriptorType type;
bool occured = true; bool occured = true;
}; };
/** /**
* @brief A holder for descriptor sets. * @brief Holder for VkDescriptorSet.
*
* This class stores 2 VkDescriptorSet one for the first stage and one for the second stage,
* This class has static members to effeciently use a VkDescriptorPool.
* @tparam MeshShader the VulkanShader to use for the first stage.
* @tparam FragmentShader the VulkanShader to use for the second stage.
*/ */
export template <typename MeshShader, typename FragmentShader> export template <typename MeshShader, typename FragmentShader>
class DescriptorSet { class DescriptorSet {
public: public:
/**
* @brief [0] refers to the first stage, [1] refers to the second stage.
*/
VkDescriptorSet set[2]; VkDescriptorSet set[2];
/** /**
* @brief This event is triggered when a descriptor is aded to this static set which invalidates all previous descriptors, subscribe to this event to renew them. * @brief This event is triggered when a descriptor is aded to this static set which invalidates all previous descriptors, subscribe to this event to renew them.
*/ */
inline static Event<void> onDescriptorRefresh; inline static Event<void> onDescriptorRefresh;
private:
inline static std::vector<DescriptorSet*> sets; inline static std::vector<DescriptorSet*> sets;
inline static VkDescriptorPool descriptorPool = VK_NULL_HANDLE; inline static VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
@ -132,6 +141,10 @@ namespace Crafter {
return types; return types;
} }
public:
/**
* @brief Allocates 2 VkDescriptorSet from the pool, all descriptors previously allocated become invalid.
*/
DescriptorSet() { DescriptorSet() {
sets.push_back(this); sets.push_back(this);
@ -153,20 +166,11 @@ namespace Crafter {
onDescriptorRefresh.Invoke(); onDescriptorRefresh.Invoke();
} }
/**
* @brief Deallocates 2 VkDescriptorSet from the pool.
*/
~DescriptorSet() { ~DescriptorSet() {
sets.erase(find(sets.begin(), sets.end(), this)); sets.erase(find(sets.begin(), sets.end(), this));
} }
// void Write(VkWriteDescriptorSet* descriptors, std::uint32_t count) {
// vkUpdateDescriptorSets(VulkanDevice::device, count, descriptors, 0, nullptr);
// }
// void Write(std::uint32_t stage, VkDescriptorType type, std::uint32_t binding, VkDescriptorBufferInfo* buffer) {
// VkWriteDescriptorSet write = vks::initializers::writeDescriptorSet(set[stage], type, binding, buffer);
// vkUpdateDescriptorSets(VulkanDevice::device, 1, &write, 0, nullptr);
// }
// void Write(std::uint32_t stage, VkDescriptorType type, std::uint32_t binding, VkDescriptorImageInfo* buffer) {
// VkWriteDescriptorSet write = vks::initializers::writeDescriptorSet(set[stage], type, binding, buffer);
// vkUpdateDescriptorSets(VulkanDevice::device, 1, &write, 0, nullptr);
// }
}; };
} }

View file

@ -31,6 +31,10 @@ import :VulkanBuffer;
import :Types; import :Types;
namespace Crafter { namespace Crafter {
/**
* @brief Holder for a indexed mesh.
* @tparam VertexType The vertex type to use that is internally stored, this must match the type the glsl shader expects.
*/
export template <typename VertexType> export template <typename VertexType>
class Mesh { class Mesh {
public: public:
@ -49,8 +53,8 @@ namespace Crafter {
} }
/** /**
* @brief Constructs Mesh from an in memory char buffer * @brief Constructs Mesh from an in memory char buffer.
* @param asset pointer to the char buffer * @param asset pointer to the char buffer.
*/ */
Mesh(const char* asset) requires(std::same_as<VertexType, Vertex>) : vertexCount(reinterpret_cast<const std::uint32_t*>(asset)[0]), indexCount(((reinterpret_cast<const std::uint32_t*>(asset)[1]) + 63) & ~63), verticies(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, vertexCount), indicies(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, indexCount) { Mesh(const char* asset) requires(std::same_as<VertexType, Vertex>) : vertexCount(reinterpret_cast<const std::uint32_t*>(asset)[0]), indexCount(((reinterpret_cast<const std::uint32_t*>(asset)[1]) + 63) & ~63), verticies(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, vertexCount), indicies(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, indexCount) {
uint32_t indexCountNoPadding = reinterpret_cast<const std::uint32_t*>(asset)[1]; uint32_t indexCountNoPadding = reinterpret_cast<const std::uint32_t*>(asset)[1];
@ -73,8 +77,8 @@ namespace Crafter {
/** /**
* @brief Constructs UV Mesh from an in memory char buffer * @brief Constructs UV Mesh from an in memory char buffer.
* @param asset pointer to the char buffer * @param asset pointer to the char buffer.
*/ */
Mesh(const char* asset) requires(std::same_as<VertexType, VertexUV>) : vertexCount(reinterpret_cast<const std::uint32_t*>(asset)[0]), indexCount(((reinterpret_cast<const std::uint32_t*>(asset)[1]) + 63) & ~63), verticies(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, vertexCount), indicies(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, indexCount) { Mesh(const char* asset) requires(std::same_as<VertexType, VertexUV>) : vertexCount(reinterpret_cast<const std::uint32_t*>(asset)[0]), indexCount(((reinterpret_cast<const std::uint32_t*>(asset)[1]) + 63) & ~63), verticies(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, vertexCount), indicies(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, indexCount) {
uint32_t indexCountNoPadding = reinterpret_cast<const std::uint32_t*>(asset)[1]; uint32_t indexCountNoPadding = reinterpret_cast<const std::uint32_t*>(asset)[1];
@ -96,11 +100,11 @@ namespace Crafter {
} }
/** /**
* @brief Constructs heightmap Mesh from an in memory char buffer * @brief Constructs heightmap Mesh from an in memory char buffer.
* @param heights pointer to heights * @param heights pointer to heights.
* @param sizeX size in the X dimension * @param sizeX size in the X dimension.
* @param sizeZ size in the Y dimension * @param sizeZ size in the Y dimension.
* @param spacing spacing between the points * @param spacing spacing between the points .
*/ */
Mesh(float* heights, uint32_t sizeX, uint32_t sizeZ, float spacing) : vertexCount(sizeX*sizeZ), indexCount(((((sizeX-1)*(sizeZ-1))*6)+ 63) & ~63), verticies(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, vertexCount), indicies(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, indexCount) { Mesh(float* heights, uint32_t sizeX, uint32_t sizeZ, float spacing) : vertexCount(sizeX*sizeZ), indexCount(((((sizeX-1)*(sizeZ-1))*6)+ 63) & ~63), verticies(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, vertexCount), indicies(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, indexCount) {
uint32_t indexCountNoPadding = ((sizeX-1)*(sizeZ-1))*6; uint32_t indexCountNoPadding = ((sizeX-1)*(sizeZ-1))*6;

View file

@ -35,6 +35,10 @@ import :DescriptorSet;
import Crafter.Math; import Crafter.Math;
namespace Crafter { namespace Crafter {
/**
* @brief Shader for rendering indexed meshes
* @tparam VertexType The vertex type to use that is internally stored, this must match the type the glsl shader expects.
*/
export template <typename VertexType> export template <typename VertexType>
class MeshShader { class MeshShader {
public: public:
@ -43,18 +47,40 @@ namespace Crafter {
Camera* camera; Camera* camera;
Buffer<MatrixRowMajor<float, 4, 4, 1>> mvp; Buffer<MatrixRowMajor<float, 4, 4, 1>> mvp;
std::uint32_t threadCount; std::uint32_t threadCount;
private:
EventListener<void> cameraUpdate; EventListener<void> cameraUpdate;
public:
/**
* @brief Constructs the MeshShader with a mesh.
* The Model-View-Projection (MVP) matrix and the transform matrix are initialized to the identity matrix.
*
* @param mesh Pointer to the mesh to use. The mesh must remain valid for the lifetime of this object.
*/
MeshShader(Mesh<VertexType>* mesh) : threadCount(std::ceil(static_cast<double>(mesh->indexCount)/64/3)), mvp(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), mesh(mesh), camera(nullptr) { MeshShader(Mesh<VertexType>* mesh) : threadCount(std::ceil(static_cast<double>(mesh->indexCount)/64/3)), mvp(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), mesh(mesh), camera(nullptr) {
transform = MatrixRowMajor<float, 4, 4, 1>::Identity(); transform = MatrixRowMajor<float, 4, 4, 1>::Identity();
*mvp.value = MatrixRowMajor<float, 4, 4, 1>::Identity(); *mvp.value = MatrixRowMajor<float, 4, 4, 1>::Identity();
} }
/**
* @brief Constructs the MeshShader with a mesh.
* The transform is initialized to identity, the transform is initialized to identity and the mvp to the camera's projectionView.
*
* @param mesh Pointer to the mesh to use. The mesh must remain valid for the lifetime of this object.
* @param mesh Pointer to the camera to use. The camera must remain valid for the lifetime of this object.
*/
MeshShader(Mesh<VertexType>* mesh, Camera* camera) : threadCount(std::ceil(static_cast<double>(mesh->indexCount)/64/3)), mvp(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), mesh(mesh), camera(camera), cameraUpdate( MeshShader(Mesh<VertexType>* mesh, Camera* camera) : threadCount(std::ceil(static_cast<double>(mesh->indexCount)/64/3)), mvp(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), mesh(mesh), camera(camera), cameraUpdate(
&camera->onUpdate, [this](){ &camera->onUpdate, [this](){
Update(); Update();
} }
) { ) {
transform = MatrixRowMajor<float, 4, 4, 1>::Identity(); transform = MatrixRowMajor<float, 4, 4, 1>::Identity();
*mvp.value = camera->projectionView;
} }
/**
* @brief Writes this class's 3 descriptors to the set, this method must be called before rendering with this shader.
* Slot 0 mvp: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER.
* Slot 1 vertex: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER.
* Slot 2 index: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER.
*/
void WriteDescriptors(VkDescriptorSet set) { void WriteDescriptors(VkDescriptorSet set) {
VkWriteDescriptorSet write[3] = { VkWriteDescriptorSet write[3] = {
vks::initializers::writeDescriptorSet(set, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &mvp.descriptor), vks::initializers::writeDescriptorSet(set, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &mvp.descriptor),

View file

@ -32,12 +32,21 @@ import :VulkanPipeline;
import :DescriptorSet; import :DescriptorSet;
namespace Crafter { namespace Crafter {
/**
* @brief Creates a sampler for a provided VulkanTexture<PixelType>.
* @tparam PixelType The pixeltype to use.
*/
export template <typename PixelType> export template <typename PixelType>
class TextureShader { class TextureShader {
public: private:
VkSampler textureSampler; VkSampler textureSampler;
VkDescriptorImageInfo imageInfo; VkDescriptorImageInfo imageInfo;
VulkanTexture<PixelType>* texture; VulkanTexture<PixelType>* texture;
public:
/**
* @brief Creates a sampler for a texture.
* @param texture A pointer to the texture to create the sampler for, the texture must remain valid for the lifetime of this object.
*/
TextureShader(VulkanTexture<PixelType>* texture) : texture(texture) { TextureShader(VulkanTexture<PixelType>* texture) : texture(texture) {
VkSamplerCreateInfo samplerInfo{}; VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
@ -62,6 +71,10 @@ namespace Crafter {
imageInfo.imageView = texture->imageView; imageInfo.imageView = texture->imageView;
imageInfo.sampler = textureSampler; imageInfo.sampler = textureSampler;
} }
/**
* @brief Writes this class's 1 descriptor to the set, this method must be called before rendering with this shader.
* Slot 0: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER.
*/
void WriteDescriptors(VkDescriptorSet set) { void WriteDescriptors(VkDescriptorSet set) {
VkWriteDescriptorSet write = vks::initializers::writeDescriptorSet(set, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &imageInfo); VkWriteDescriptorSet write = vks::initializers::writeDescriptorSet(set, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &imageInfo);
vkUpdateDescriptorSets(VulkanDevice::device, 1, &write, 0, nullptr); vkUpdateDescriptorSets(VulkanDevice::device, 1, &write, 0, nullptr);

View file

@ -28,6 +28,10 @@ import Crafter.Event;
import :Types; import :Types;
namespace Crafter { namespace Crafter {
/**
* @brief General use UiElement for handeling input events.
* Add to a window's elements member to start recieving events.
*/
export class UiElement { export class UiElement {
public: public:
Event<MouseMoveEvent> onMouseMove; Event<MouseMoveEvent> onMouseMove;

View file

@ -28,13 +28,31 @@ export module Crafter.Graphics:VulkanBuffer;
import :VulkanDevice; import :VulkanDevice;
namespace Crafter { namespace Crafter {
/**
* @brief VkBuffer holder.
* Stores a value and handles buffer mapping and lifetime management.
* @tparam T The value to store.
*/
export template <typename T> export template <typename T>
class Buffer { class Buffer {
public: public:
T* value; T* value;
VkDescriptorBufferInfo descriptor; VkDescriptorBufferInfo descriptor;
VkBuffer buffer = VK_NULL_HANDLE; public:
VkDeviceMemory memory = VK_NULL_HANDLE; /**
* @brief Creates and initializes a Vulkan buffer with the specified usage and memory properties.
*
* This constructor allocates a buffer capable of holding `count` elements of type T.
* The buffer usage and memory property flags control how the buffer will be used
* and how its memory is managed.
*
* @param usageFlags Vulkan buffer usage flags that define allowed operations on the buffer
* (e.g., vertex buffer, index buffer, uniform buffer).
* @param memoryPropertyFlags Vulkan memory property flags specifying the desired memory
* properties (e.g., device local, host visible).
* @param count Number of elements to allocate space for in the buffer. The total buffer size
* will be `count * sizeof(T)`. Must be above 0.
*/
Buffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, std::uint32_t count = 1) { Buffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, std::uint32_t count = 1) {
VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(usageFlags, sizeof(T)*count); VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(usageFlags, sizeof(T)*count);
VulkanDevice::CHECK_VK_RESULT(vkCreateBuffer(VulkanDevice::device, &bufferCreateInfo, nullptr, &buffer)); VulkanDevice::CHECK_VK_RESULT(vkCreateBuffer(VulkanDevice::device, &bufferCreateInfo, nullptr, &buffer));
@ -66,6 +84,9 @@ namespace Crafter {
VulkanDevice::CHECK_VK_RESULT(vkBindBufferMemory(VulkanDevice::device, buffer, memory, 0)); VulkanDevice::CHECK_VK_RESULT(vkBindBufferMemory(VulkanDevice::device, buffer, memory, 0));
VulkanDevice::CHECK_VK_RESULT(vkMapMemory(VulkanDevice::device, memory, 0, sizeof(T)*count, 0, reinterpret_cast<void**>(&value))); VulkanDevice::CHECK_VK_RESULT(vkMapMemory(VulkanDevice::device, memory, 0, sizeof(T)*count, 0, reinterpret_cast<void**>(&value)));
} }
/**
* @brief Frees all resources assosiacted with the buffer.
*/
~Buffer() { ~Buffer() {
vkUnmapMemory(VulkanDevice::device, memory); vkUnmapMemory(VulkanDevice::device, memory);
vkDestroyBuffer(VulkanDevice::device, buffer, nullptr); vkDestroyBuffer(VulkanDevice::device, buffer, nullptr);
@ -75,5 +96,7 @@ namespace Crafter {
VkDeviceSize alignment = 0; VkDeviceSize alignment = 0;
VkMemoryPropertyFlags memoryPropertyFlags; VkMemoryPropertyFlags memoryPropertyFlags;
VkBufferUsageFlags usageFlags; VkBufferUsageFlags usageFlags;
VkBuffer buffer = VK_NULL_HANDLE;
VkDeviceMemory memory = VK_NULL_HANDLE;
}; };
} }

View file

@ -46,7 +46,27 @@ export namespace Crafter {
* @brief Creates the vulkan device, this must be called before any use of vulkan. * @brief Creates the vulkan device, this must be called before any use of vulkan.
*/ */
static void CreateDevice(); static void CreateDevice();
/**
* @brief Checks if result is VK_SUCCESS.
* @param result The VkResult to check.
* @throws std::runtime_error If result != VK_SUCCESS.
*/
static void CHECK_VK_RESULT(VkResult result); static void CHECK_VK_RESULT(VkResult result);
/**
* @brief Finds a suitable memory type index for the device based on required properties.
*
* This function searches through the memory types supported by the physical device to find
* a memory type index that matches the specified bitmask and has the requested property flags.
*
* @param typeBits A bitmask representing the memory types that are suitable. Each bit corresponds
* to a memory type index; if the bit is set, that memory type is considered.
* @param properties A bitmask of VkMemoryPropertyFlags specifying the desired memory properties,
* such as device local, host visible, etc.
*
* @return The index of a suitable memory type that fulfills the requirements.
*
* @throws std::runtime_error If no suitable memory type is found matching the criteria.
*/
static std::uint32_t GetMemoryType(std::uint32_t typeBits, VkMemoryPropertyFlags properties); static std::uint32_t GetMemoryType(std::uint32_t typeBits, VkMemoryPropertyFlags properties);
}; };
} }

View file

@ -32,9 +32,25 @@ import :VulkanShader;
import :WindowWaylandVulkan; import :WindowWaylandVulkan;
namespace Crafter { namespace Crafter {
export template <typename MeshShader, typename FragmentShader> class DescriptorSet;
/**
* @brief A generic Vulkan graphics pipeline wrapper using template-based shaders.
*
* This class encapsulates the creation and management of a Vulkan graphics pipeline
* with a specified mesh shader and fragment shader. It provides static members for
* the pipeline, pipeline layout, and descriptor set layouts, which are shared across
* all instances of this template specialization.
*
* @tparam MeshShader The mesh shader type used in the pipeline.
* @tparam FragmentShader The fragment shader type used in the pipeline.
*
* @note Before using this pipeline, the CreatePipeline() function must be called,
* and all shader modules specified by the template parameters must be created.
*/
export template <typename MeshShader, typename FragmentShader> export template <typename MeshShader, typename FragmentShader>
class VulkanPipeline { class VulkanPipeline {
private: private:
friend class DescriptorSet<MeshShader, FragmentShader>;
template <typename Shader, VkShaderStageFlagBits Flag> template <typename Shader, VkShaderStageFlagBits Flag>
consteval static std::array<VkDescriptorSetLayoutBinding, Shader::descriptorCount> GetDescriptorSet() { consteval static std::array<VkDescriptorSetLayoutBinding, Shader::descriptorCount> GetDescriptorSet() {
std::array<VkDescriptorSetLayoutBinding, Shader::descriptorCount> set; std::array<VkDescriptorSetLayoutBinding, Shader::descriptorCount> set;
@ -45,11 +61,10 @@ namespace Crafter {
return set; return set;
} }
inline static VkDescriptorSetLayout descriptorSetLayout[2];
public: public:
inline static VkPipeline pipeline; inline static VkPipeline pipeline;
inline static VkPipelineLayout pipelineLayout; inline static VkPipelineLayout pipelineLayout;
inline static VkDescriptorSetLayout descriptorSetLayout[2];
/** /**
* @brief Creates the vulkan pipeline, this must be called before any use of this pipeline and all shaders must be created before this pipeline is created. * @brief Creates the vulkan pipeline, this must be called before any use of this pipeline and all shaders must be created before this pipeline is created.

View file

@ -46,6 +46,22 @@ namespace Crafter {
std::uint32_t slot; std::uint32_t slot;
}; };
/**
* @brief Represents a Vulkan shader module with specified configuration.
*
* This class template encapsulates a Vulkan shader, parametrized by the shader's
* source path, entry point, shader stage, and its descriptor bindings.
*
* @tparam path A compile-time string literal specifying the file path to the shader source or binary.
* @tparam entrypoint A compile-time string literal specifying the entry point function name within the shader.
* @tparam stage The Vulkan shader stage flag indicating the shader type (e.g., vertex, fragment).
* @tparam DescriptorCount The number of descriptor bindings used by the shader.
* @tparam Descriptors An array of descriptor binding configurations used by the shader.
*
* This class facilitates compile-time specification of shader resources and metadata,
* allowing for type-safe shader management and potentially more efficient shader pipeline creation.
* CreateShader must be called before using this shader in a pipeline.
*/
export template < export template <
StringLiteral path, StringLiteral path,
StringLiteral entrypoint, StringLiteral entrypoint,
@ -55,11 +71,11 @@ namespace Crafter {
> >
class VulkanShader { class VulkanShader {
public: public:
inline static VkShaderModule shader;
constexpr static std::uint32_t descriptorCount = DescriptorCount;
constexpr static std::array<DescriptorBinding, DescriptorCount> descriptors = Descriptors;
constexpr static StringLiteral _entrypoint = entrypoint;
constexpr static VkShaderStageFlagBits _stage = stage; constexpr static VkShaderStageFlagBits _stage = stage;
constexpr static std::array<DescriptorBinding, DescriptorCount> descriptors = Descriptors;
constexpr static std::uint32_t descriptorCount = DescriptorCount;
constexpr static StringLiteral _entrypoint = entrypoint;
inline static VkShaderModule shader;
/** /**
* @brief Creates the vulkan shader, this must be called before any use of this shader. * @brief Creates the vulkan shader, this must be called before any use of this shader.
*/ */

View file

@ -31,15 +31,37 @@ import :VulkanBuffer;
namespace Crafter { namespace Crafter {
/**
* @brief Represents a Vulkan texture with pixel data of a specified type.
*
* This class manages a Vulkan image resource along with its associated memory,
* buffer, and image view. It provides functionality to create textures either
* by specifying dimensions or loading from an asset, and to update the texture
* data on the GPU using command buffers.
*
* @tparam PixelType The type of the pixel data stored in the texture.
*/
export template <typename PixelType> export template <typename PixelType>
class VulkanTexture { class VulkanTexture {
public: public:
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
private:
VkImage image; VkImage image;
VkDeviceMemory imageMemory; VkDeviceMemory imageMemory;
Buffer<PixelType> buffer; Buffer<PixelType> buffer;
VkImageView imageView; VkImageView imageView;
public:
/**
* @brief Constructs a VulkanTexture with the given dimensions.
*
* Creates a Vulkan texture image with the specified width and height,
* initializing necessary resources.
*
* @param width The width of the texture.
* @param height The height of the texture.
* @param cmd Vulkan command buffer used for resource initialization.
*/
VulkanTexture(std::uint32_t width, std::uint32_t height, VkCommandBuffer cmd) : width(width), height(height), buffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, width*height) { VulkanTexture(std::uint32_t width, std::uint32_t height, VkCommandBuffer cmd) : width(width), height(height), buffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, width*height) {
VkImageCreateInfo imageInfo{}; VkImageCreateInfo imageInfo{};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
@ -84,11 +106,27 @@ namespace Crafter {
TransitionImageLayout(cmd, buffer, image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); TransitionImageLayout(cmd, buffer, image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
} }
/**
* @brief Constructs a VulkanTexture by loading from an in memory asset.
*
* Loads texture pixel data from the specified asset and initializes
* the Vulkan image resource accordingly.
*
* @param asset Pointer to the in memory asset.
* @param cmd Vulkan command buffer used for resource initialization.
*/
VulkanTexture(const char* asset, VkCommandBuffer cmd) : VulkanTexture(reinterpret_cast<const std::uint32_t*>(asset)[0], reinterpret_cast<const std::uint32_t*>(asset)[1], cmd) { VulkanTexture(const char* asset, VkCommandBuffer cmd) : VulkanTexture(reinterpret_cast<const std::uint32_t*>(asset)[0], reinterpret_cast<const std::uint32_t*>(asset)[1], cmd) {
Update(reinterpret_cast<const PixelType*>(reinterpret_cast<const std::uint32_t*>(asset)+2), cmd); Update(reinterpret_cast<const PixelType*>(reinterpret_cast<const std::uint32_t*>(asset)+2), cmd);
} }
/**
* @brief Updates the texture with new pixel data.
*
* Copies the given pixel data into the texture's buffer and issues Vulkan
* commands to upload the data to the GPU image.
*
* @param bufferdata Pointer to the new pixel data.
* @param cmd Vulkan command buffer used for the update operation.
*/
void Update(const PixelType* bufferdata, VkCommandBuffer cmd) { void Update(const PixelType* bufferdata, VkCommandBuffer cmd) {
memcpy(buffer.value, bufferdata, height*width*sizeof(PixelType)); memcpy(buffer.value, bufferdata, height*width*sizeof(PixelType));
TransitionImageLayout(cmd, buffer, image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); TransitionImageLayout(cmd, buffer, image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);

View file

@ -37,6 +37,13 @@ export namespace Crafter {
int32_t height; int32_t height;
}; };
/**
* @brief Represents a GUI window handling input events, mouse states, keyboard states, and UI elements.
*
* The Window class encapsulates event handling for mouse and keyboard interactions,
* manages the state of the mouse and keyboard, and stores UI elements contained within the window.
* It also holds window-specific properties such as name, dimensions, and scaling factor.
*/
class Window { class Window {
public: public:
Event<MousePoint> onMouseRightClick; Event<MousePoint> onMouseRightClick;
@ -68,7 +75,19 @@ export namespace Crafter {
std::uint32_t height; std::uint32_t height;
float scale = 1; float scale = 1;
bool open = true; bool open = true;
/**
* @brief Constructs a Window with a given name and dimensions.
* @param name The title of the window.
* @param width The width of the window in pixels.
* @param height The height of the window in pixels.
*/
Window(std::string name, std::uint32_t width, std::uint32_t height); Window(std::string name, std::uint32_t width, std::uint32_t height);
/**
* @brief Calculates the real position and size of an UiElement
*
* @param element The UI element to get the position from.
* @return The actual position and size of the element after scaling.
*/
ScaleData ScaleElement(const UiElement& element); ScaleData ScaleElement(const UiElement& element);
}; };
} }

View file

@ -33,10 +33,26 @@ import :Types;
import :Window; import :Window;
export namespace Crafter { export namespace Crafter {
/**
* @class WindowWayland
* @brief A window using the Wayland display server protocol.
*
* This class inherits from the base Window class and provides
* functionality specific to Wayland for creating and managing
* windows.
*/
class WindowWayland : public Window { class WindowWayland : public Window {
public: public:
Pixel_BU8_GU8_RU8_AU8* framebuffer = NULL; /**
* @brief Constructs a Wayland window with a given name and size.
* @param name The title for the window.
* @param width The width of the window in pixels.
* @param height The height of the window in pixels.
*/
WindowWayland(std::string name, std::uint32_t width, std::uint32_t height); WindowWayland(std::string name, std::uint32_t width, std::uint32_t height);
/**
* @brief Destructor cleans up Wayland-specific window resources.
*/
~WindowWayland(); ~WindowWayland();
protected: protected:
bool configured = false; bool configured = false;

View file

@ -45,14 +45,59 @@ namespace Crafter {
VkSemaphore renderComplete; VkSemaphore renderComplete;
}; };
/**
* @class WindowWaylandVulkan
* @brief A Wayland window specialized for Vulkan rendering.
*
* This class extends the WindowWayland base class to support Vulkan graphics
* integration within a Wayland environment. It provides methods for initializing
* Vulkan command buffers and managing drawing operations either synchronously or asynchronously.
*
* The class exposes an event `onDraw` which is called for every frame.
* @pre VulkanDevice::CreateDevice() must be called before creating or using this class.
*/
export class WindowWaylandVulkan : public WindowWayland { export class WindowWaylandVulkan : public WindowWayland {
public: public:
Event<VkCommandBuffer> onDraw; Event<VkCommandBuffer> onDraw;
/**
* @brief Constructs a WindowWaylandVulkan instance.
*
* @param name The title of the window.
* @param width The width of the window in pixels.
* @param height The height of the window in pixels.
*/
WindowWaylandVulkan(std::string name, std::uint32_t width, std::uint32_t height); WindowWaylandVulkan(std::string name, std::uint32_t width, std::uint32_t height);
/**
* @brief Destructor for the WindowWaylandVulkan.
*
* Cleans up Vulkan and Wayland resources associated with this window.
*/
~WindowWaylandVulkan(); ~WindowWaylandVulkan();
/**
* @brief Starts Vulkan initialization and returns a command buffer.
*
* This command buffer can be used to record Vulkan setup commands.
*
* @return VkCommandBuffer A Vulkan command buffer for recording initialization commands.
*/
VkCommandBuffer StartInit(); VkCommandBuffer StartInit();
/**
* @brief Completes Vulkan initialization.
*
* Finalizes any remaining setup required after recording commands returned by StartInit().
*/
void FinishInit(); void FinishInit();
/**
* @brief Starts the event loop asynchronously.
*
* This method triggers rendering without blocking the caller.
*/
void StartAsync(); void StartAsync();
/**
* @brief Starts the event loop synchronously.
*
* This method blocks the caller until the event loop stops.
*/
void StartSync(); void StartSync();
private: private:
void CreateSwapchain(); void CreateSwapchain();

View file

@ -29,11 +29,40 @@ import Crafter.Event;
import :WindowWayland; import :WindowWayland;
export namespace Crafter { export namespace Crafter {
/**
* @brief A specialized Wayland window implementation for direct drawing.
*
* This class inherits from `WindowWayland` and provides a framebuffer using the pixel format `Pixel_BU8_GU8_RU8_AU8`.
*/
class WindowWaylandWayland : public WindowWayland { class WindowWaylandWayland : public WindowWayland {
public: public:
/**
* @brief Framebuffer for the window using the BGRA 8-bit unsigned pixel format, use this for direct drawing to the window.
*/
Pixel_BU8_GU8_RU8_AU8* framebuffer = NULL;
/**
* @brief Constructs a new WindowWaylandWayland object.
*
* @param name The title of the window.
* @param width The width of the window in pixels.
* @param height The height of the window in pixels.
*/
WindowWaylandWayland(std::string name, std::uint32_t width, std::uint32_t height); WindowWaylandWayland(std::string name, std::uint32_t width, std::uint32_t height);
/**
* @brief Destructor cleans up Wayland-specific window resources and framebuffer.
*/
~WindowWaylandWayland(); ~WindowWaylandWayland();
/**
* @brief Starts the event loop asynchronously.
*
* This method triggers rendering without blocking the caller.
*/
void StartAsync(); void StartAsync();
/**
* @brief Starts the event loop synchronously.
*
* This method blocks the caller until the event loop stops.
*/
void StartSync(); void StartSync();
private: private:
std::thread thread; std::thread thread;