This commit is contained in:
Jorijn van der Graaf 2026-01-28 23:37:12 +01:00
commit 9f62233a07
20 changed files with 298 additions and 322 deletions

View file

@ -1,23 +0,0 @@
# HelloWindow Example
## Description
This example showcases how to use the camera to get a rotating 3D cube.
## Expected Result
A blue tinted vulkan window with a white rotating 3D cube.
## Highlighted Code Snippet
```cpp
Camera camera(ToRadian(90), 1280.0f / 720.0f, 0.01, 512);
camera.view = MatrixRowMajor<float, 4, 4, 1>::Translation(0, 0, -5);
camera.Update();
```
## How to Run
```bash
crafter-build build executable -r
```

View file

@ -1,86 +0,0 @@
#include <vulkan/vulkan.h>
import Crafter.Math;
import Crafter.Event;
import Crafter.Graphics;
using namespace Crafter;
typedef VulkanShader<"MeshShaderXYZ.spirv", "main", VK_SHADER_STAGE_MESH_BIT_EXT, 3, {{{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0}, {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2}}}> MeshShaderSpirv;
typedef VulkanShader<"FragmentShaderSolidWhite.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT, 0, {}> FragmentShader;
typedef VulkanPipeline<MeshShaderSpirv, FragmentShader> Pipeline;
int main() {
VulkanDevice::CreateDevice();
MeshShaderSpirv::CreateShader();
FragmentShader::CreateShader();
Pipeline::CreatePipeline();
WindowWaylandVulkan window("HelloWindow", 1280, 720);
/*
Load the verticies and indicies for our cube.
*/
Mesh<Vertex> cube(8, 12);
Vertex verticies[] {
{-0.5f, -0.5f, -0.5f, 1.0f},
{-0.5f, -0.5f, 0.5f, 1.0f},
{-0.5f, 0.5f, -0.5f, 1.0f},
{-0.5f, 0.5f, 0.5f, 1.0f},
{0.5f, -0.5f, -0.5f, 1.0f},
{0.5f, -0.5f, 0.5f, 1.0f},
{0.5f, 0.5f, -0.5f, 1.0f},
{0.5f, 0.5f, 0.5f, 1.0f}
};
std::memcpy(cube.verticies.value, &verticies, sizeof(verticies));
uint32_t indicies[]
{
0, 2, 1,
1, 2, 3,
4, 5, 6,
5, 7, 6,
0, 1, 5,
0, 5, 4,
2, 6, 7,
2, 7, 3,
0, 4, 6,
0, 6, 2,
1, 3, 7,
1, 7, 5
};
std::memcpy(cube.indicies.value, &indicies, sizeof(indicies));
/*
Defines a perspective camera, with an FOV of 90, an aspect ratio of 16/9 a near clip of 0.01 and a far clip of 512.
*/
Camera camera(ToRadian(90), 1280.0f / 720.0f, 0.01, 512);
camera.view = MatrixRowMajor<float, 4, 4, 1>::Translation(0, 0, -5);
/*
Calculates the viewprojection, must be called each time after updating the camera.
*/
camera.Update();
MeshShader<Vertex> meshShader(&cube, &camera);
DescriptorSet<MeshShaderSpirv, FragmentShader> descriptors;
meshShader.WriteDescriptors(descriptors.set[0]);
/*
Calculates the modelviewprojection matrix.
*/
meshShader.Update();
float counter = 0;
EventListener<VkCommandBuffer> listener(&window.onDraw, [&descriptors, &meshShader, &counter](VkCommandBuffer cmd){
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, Pipeline::pipelineLayout, 0, 2, &descriptors.set[0], 0, NULL);
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, Pipeline::pipeline);
VulkanDevice::vkCmdDrawMeshTasksEXTProc(cmd, meshShader.threadCount, 1, 1);
meshShader.transform = MatrixRowMajor<float, 4, 4, 1>::Rotation(counter, counter, 0);
/*
We edited the transform so must recalculate the model view projection matrix.
*/
meshShader.Update();
counter+=0.01;
});
window.StartSync();
}

View file

@ -1,22 +0,0 @@
{
"name": "crafter-graphics",
"configurations": [
{
"name": "example",
"standard": "c++26",
"source_files": ["main"],
"module_files": [],
"build_dir": "build",
"output_dir": "bin",
"type":"executable",
"libs": [],
"flags": ["-Wno-uninitialized"],
"dependencies": [
{
"path":"../../project.json",
"configuration":"lib-debug"
}
]
}
]
}

View file

@ -1,49 +0,0 @@
/*
Crafter®.Graphics
Copyright (C) 2025 Catcrafts®
Catcrafts.net
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#version 450
#extension GL_EXT_mesh_shader : require
layout (binding = 0) buffer COLORS
{
vec4 colors[];
} colors;
layout (location = 0) out PerVertexData
{
vec4 color;
} outVert[];
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout(triangles, max_vertices = 3, max_primitives = 1) out;
void main()
{
SetMeshOutputsEXT(3, 1);
gl_MeshVerticesEXT[0].gl_Position = vec4(0, -0.3, 0, 1);
gl_MeshVerticesEXT[1].gl_Position = vec4(0.3, 0.3, 0, 1);
gl_MeshVerticesEXT[2].gl_Position = vec4(-0.3, 0.3, 0, 1);
outVert[0].color = colors.colors[0];
outVert[1].color = colors.colors[1];
outVert[2].color = colors.colors[2];
gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);
}

View file

@ -1,32 +0,0 @@
# HelloWindow Example
## Description
This example showcases how to define a custom shader.
## Expected Result
A RGB triangle.
## Highlighted Code Snippet
```cpp
class CustomShader {
public:
Buffer<Vector<float, 4>> colors;
CustomShader(const std::vector<Vector<float, 4>>& colors) : colors(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, colors.size()) {
memcpy(this->colors.value, colors.data(), colors.size()*sizeof(Vector<float, 4>));
}
void WriteDescriptors(VkDescriptorSet set) {
VkWriteDescriptorSet write[1] = {
vks::initializers::writeDescriptorSet(set, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &colors.descriptor),
};
vkUpdateDescriptorSets(VulkanDevice::device, 1, &write[0], 0, nullptr);
}
};
```
## How to Run
```bash
crafter-build build executable -r
```

View file

@ -1,60 +0,0 @@
#include "../../lib/VulkanInitializers.hpp"
#include <vulkan/vulkan.h>
//required for the camera matrix.
import Crafter.Math;
import Crafter.Event;
import std;
import Crafter.Graphics;
using namespace Crafter;
typedef VulkanShader<"CustomShader.spirv", "main", VK_SHADER_STAGE_MESH_BIT_EXT, 1, {{{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0}}}> CustomShaderSpirv;
typedef VulkanShader<"FragmentShaderVertexColor.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT, 0, {}> FragmentShader;
typedef VulkanPipeline<CustomShaderSpirv, FragmentShader> Pipeline;
class CustomShader {
public:
/*
Define a buffer holding our color vectors.
*/
Buffer<Vector<float, 4>> colors;
/*
Initialze our buffer as shader visible storage buffer with the size of the colors vector.
*/
CustomShader(const std::vector<Vector<float, 4>>& colors) : colors(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, colors.size()) {
std::memcpy(this->colors.value, colors.data(), colors.size()*sizeof(Vector<float, 4>));
}
void WriteDescriptors(VkDescriptorSet set) {
/*
Write the color buffer descriptor to the set.
*/
VkWriteDescriptorSet write[1] = {
vks::initializers::writeDescriptorSet(set, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &colors.descriptor),
};
vkUpdateDescriptorSets(VulkanDevice::device, 1, &write[0], 0, nullptr);
}
};
int main() {
VulkanDevice::CreateDevice();
CustomShaderSpirv::CreateShader();
FragmentShader::CreateShader();
Pipeline::CreatePipeline();
WindowWaylandVulkan window("HelloWindow", 1280, 720);
DescriptorSet<CustomShaderSpirv, FragmentShader> descriptors;
CustomShader customShader({{1,0,0,1}, {0,1,0,1}, {0,0,1,1}});
customShader.WriteDescriptors(descriptors.set[0]);
EventListener<VkCommandBuffer> listener(&window.onDraw, [&descriptors](VkCommandBuffer cmd){
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, Pipeline::pipelineLayout, 0, 2, &descriptors.set[0], 0, NULL);
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, Pipeline::pipeline);
VulkanDevice::vkCmdDrawMeshTasksEXTProc(cmd, 1, 1, 1);
});
window.StartSync();
}

View file

@ -1,29 +0,0 @@
{
"name": "crafter-graphics",
"configurations": [
{
"name": "example",
"standard": "c++26",
"source_files": ["main"],
"module_files": [],
"build_dir": "build",
"output_dir": "bin",
"type":"executable",
"libs": [],
"flags": ["-Wno-uninitialized"],
"dependencies": [
{
"path":"../../project.json",
"configuration":"lib-debug"
}
],
"shaders": [
{
"path":"CustomShader.glsl",
"type":13,
"entrypoint":"main"
}
]
}
]
}

View file

View file

@ -4,13 +4,18 @@ import Crafter.Graphics;
using namespace Crafter; using namespace Crafter;
import std; import std;
typedef VulkanShader<"raygen.spv", "main", VK_SHADER_STAGE_RAYGEN_BIT_KHR, 2, {{{VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0}, {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1}}}> Raygenspv;
int main() { int main() {
/* /*
This sets up all necessary things and creates the vulkan device. This sets up all necessary things and creates the vulkan device.
This must be called before any vulkan related things. This must be called before any vulkan related things.
Things like VkDevice are static members of the VulkanDevice class. Things like VkDevice are static members of the VulkanDevice class.
*/ */
VulkanDevice::CreateDevice(); VulkanDevice::CreateDevice();
Raygenspv::CreateShader();
WindowVulkan window(1280, 720, "HelloVulkan"); WindowVulkan window(1280, 720, "HelloVulkan");
/* /*

View file

View file

@ -9,6 +9,13 @@
"path":"../../project.json", "path":"../../project.json",
"configuration":"lib-vulkan" "configuration":"lib-vulkan"
} }
],
"shaders": [
{
"path":"raygen.glsl",
"type":6,
"entrypoint":"main"
}
] ]
} }
] ]

View file

@ -0,0 +1,12 @@
#version 460
#extension GL_EXT_ray_tracing : enable
#extension GL_EXT_shader_image_load_formatted : enable
layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS;
layout(binding = 1, set = 0) uniform image2D image;
layout(location = 0) rayPayloadEXT vec3 hitValue;
void main() {
imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(1,1,1, 0.0));
}

View file

@ -45,6 +45,7 @@ const char* const deviceExtensionNames[] = {
"VK_KHR_dynamic_rendering", "VK_KHR_dynamic_rendering",
"VK_KHR_acceleration_structure", "VK_KHR_acceleration_structure",
"VK_KHR_deferred_host_operations", "VK_KHR_deferred_host_operations",
"VK_KHR_ray_tracing_pipeline"
}; };
const char* const layerNames[] = { const char* const layerNames[] = {
"VK_LAYER_KHRONOS_validation" "VK_LAYER_KHRONOS_validation"
@ -213,8 +214,14 @@ void VulkanDevice::CreateDevice() {
queueCreateInfo.queueCount = 1; queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &priority; queueCreateInfo.pQueuePriorities = &priority;
VkPhysicalDeviceRayTracingPipelineFeaturesKHR physicalDeviceRayTracingPipelineFeatures{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR,
.rayTracingPipeline = VK_TRUE
};
VkPhysicalDeviceBufferDeviceAddressFeatures deviceBufferDeviceAddressFeature = { VkPhysicalDeviceBufferDeviceAddressFeatures deviceBufferDeviceAddressFeature = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES, .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES,
.pNext = &physicalDeviceRayTracingPipelineFeatures,
.bufferDeviceAddress = VK_TRUE .bufferDeviceAddress = VK_TRUE
}; };
@ -279,20 +286,6 @@ void VulkanDevice::CreateDevice() {
vkGetPhysicalDeviceMemoryProperties(physDevice, &memoryProperties); vkGetPhysicalDeviceMemoryProperties(physDevice, &memoryProperties);
std::vector<VkFormat> formatList = {
VK_FORMAT_D32_SFLOAT,
};
for (auto& format : formatList) {
VkFormatProperties formatProps;
vkGetPhysicalDeviceFormatProperties(physDevice, format, &formatProps);
if (formatProps.optimalTilingFeatures)
{
depthFormat = format;
break;
}
}
vkCmdDrawMeshTasksEXTProc = reinterpret_cast<PFN_vkCmdDrawMeshTasksEXT>(vkGetDeviceProcAddr(device, "vkCmdDrawMeshTasksEXT")); vkCmdDrawMeshTasksEXTProc = reinterpret_cast<PFN_vkCmdDrawMeshTasksEXT>(vkGetDeviceProcAddr(device, "vkCmdDrawMeshTasksEXT"));
vkCmdBeginRenderingKHRProc = reinterpret_cast<PFN_vkCmdBeginRenderingKHR>(vkGetInstanceProcAddr(instance, "vkCmdBeginRenderingKHR")); vkCmdBeginRenderingKHRProc = reinterpret_cast<PFN_vkCmdBeginRenderingKHR>(vkGetInstanceProcAddr(instance, "vkCmdBeginRenderingKHR"));
vkCmdEndRenderingKHRProc = reinterpret_cast<PFN_vkCmdEndRenderingKHR>(vkGetInstanceProcAddr(instance, "vkCmdEndRenderingKHR")); vkCmdEndRenderingKHRProc = reinterpret_cast<PFN_vkCmdEndRenderingKHR>(vkGetInstanceProcAddr(instance, "vkCmdEndRenderingKHR"));

View file

@ -395,10 +395,7 @@ void WindowVulkan::Render() {
VkCommandBufferBeginInfo cmdBufInfo {}; VkCommandBufferBeginInfo cmdBufInfo {};
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
VkClearValue clearValues[1];
clearValues[0].color = { };
VulkanDevice::CheckVkResult(vkBeginCommandBuffer(drawCmdBuffers[currentBuffer], &cmdBufInfo)); VulkanDevice::CheckVkResult(vkBeginCommandBuffer(drawCmdBuffers[currentBuffer], &cmdBufInfo));
VkImageSubresourceRange range{}; VkImageSubresourceRange range{};

View file

@ -0,0 +1,167 @@
/*
Crafter®.Graphics
Copyright (C) 2026 Catcrafts®
catcrafts.net
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 3.0 as published by the Free Software Foundation;
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
module;
#ifdef CRAFTER_GRAPHICS_VULKAN
#include <vulkan/vulkan.h>
#endif
export module Crafter.Graphics:DescriptorSetVulkan;
#ifdef CRAFTER_GRAPHICS_VULKAN
import std;
import :VulkanDevice;
import :Types;
import Crafter.Event;
export namespace Crafter {
struct DescriptorEntry {
VkDescriptorType type;
bool occured = true;
};
template <std::uint32_t PoolCount, typename... Shaders>
class DescriptorPool {
public:
inline static Event<void> onDescriptorRefresh;
inline static std::uint32_t setIndex = 0;
inline static std::vector<VkDescriptorSet> sets;
inline static VkDescriptorPool descriptorPool[PoolCount] = { VK_NULL_HANDLE };
private:
template <typename Shader>
consteval static void GetOccuringDescriptors(std::array<DescriptorEntry, 20>& types) {
for (const DescriptorBinding& binding : Shader::descriptors) {
for (DescriptorEntry& type : types) {
if (type.type == binding.type) {
type.occured = true;
}
}
}
}
consteval static std::uint32_t GetUniqueDiscriptorCount() {
std::array<DescriptorEntry, 20> types = {{{VK_DESCRIPTOR_TYPE_SAMPLER, 0},{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0},{VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 0},{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 0},{VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 0},{VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 0},{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0},{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0},{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 0},{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 0},{VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 0},{VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK, 0},{VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0},{VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV, 0},{VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM, 0},{VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM, 0},{VK_DESCRIPTOR_TYPE_MUTABLE_EXT, 0},{VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV, 0},{VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT, 0},{VK_DESCRIPTOR_TYPE_MUTABLE_VALVE, 0}}};
(GetOccuringDescriptors<Shaders>(types), ... );
std::uint32_t size = 0;
for(DescriptorEntry& type : types) {
if(type.occured) {
size++;
}
}
return size;
}
constexpr static std::uint32_t uniqueDescriptorCount = GetUniqueDiscriptorCount();
consteval static std::array<VkDescriptorPoolSize, uniqueDescriptorCount> GetPoolSizes() {
std::array<VkDescriptorPoolSize, uniqueDescriptorCount> types = {};
for(std::uint32_t i = 0; i < uniqueDescriptorCount; i++){
types[i].descriptorCount = 12345;
}
([&] {
for (const DescriptorBinding& binding : Shaders::descriptors) {
bool found = false;
for(VkDescriptorPoolSize& type : types) {
if(type.type == binding.type && type.descriptorCount != 12345) {
type.descriptorCount += 1;
found = true;
}
}
if(!found) {
for(std::uint32_t i = 0; i < uniqueDescriptorCount; i++){
if(types[i].descriptorCount == 12345) {
types[i].type = binding.type;
types[i].descriptorCount = 1;
break;
}
}
}
}
}(),
...);
return types;
}
template <typename Shader>
consteval static std::array<VkDescriptorSetLayoutBinding, Shader::descriptorCount> GetDescriptorSet() {
std::array<VkDescriptorSetLayoutBinding, Shader::descriptorCount> set;
for(std::uint32_t i = 0; i < Shader::descriptors.size(); i++) {
set[i] = {Shader::descriptors[i].slot, Shader::descriptors[i].type, 1, Shader::_stage, nullptr};
}
return set;
}
public:
static void BuildPool(std::uint32_t poolIndex) {
if(descriptorPool[poolIndex] != VK_NULL_HANDLE) {
vkDestroyDescriptorPool(VulkanDevice::device, descriptorPool, nullptr);
}
std::array<VkDescriptorPoolSize, uniqueDescriptorCount> poolSizes = GetPoolSizes();
for(VkDescriptorPoolSize& size : poolSizes) {
size.descriptorCount *= sets.size();
}
VkDescriptorPoolCreateInfo descriptorPoolInfo {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.poolSizeCount = uniqueDescriptorCount,
.pPoolSizes = poolSizes.data(),
.maxSets = sets.size()
};
VulkanDevice::CheckVkResult(vkCreateDescriptorPool(VulkanDevice::device, &descriptorPoolInfo, nullptr, &descriptorPool[poolIndex]));
VkDescriptorSetLayout descriptorSetLayout[sizeof...(Shaders)];
std::uint32_t shaderIndex = 0;
([&] {
constexpr std::array<VkDescriptorSetLayoutBinding, Shaders::descriptorCount> setLayoutBindingsMesh = GetDescriptorSet<Shaders>();
VkDescriptorSetLayoutCreateInfo descriptorLayoutInfoMesh = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.pBindings = setLayoutBindingsMesh.data(),
.bindingCount = Shaders::descriptorCount
};
VulkanDevice::CheckVkResult(vkCreateDescriptorSetLayout(VulkanDevice::device, &descriptorLayoutInfoMesh, nullptr, &descriptorSetLayout[shaderIndex++]));
}(),
...);
VkDescriptorSetAllocateInfo allocInfo {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = descriptorPool[poolIndex],
.pSetLayouts = descriptorSetLayout,
.descriptorSetCount = sets.size()
};
VulkanDevice::CheckVkResult(vkAllocateDescriptorSets(VulkanDevice::device, &allocInfo, sets.data()));
setIndex = 0;
onDescriptorRefresh.Invoke();
}
};
}
#endif

View file

@ -0,0 +1,85 @@
/*
Crafter®.Graphics
Copyright (C) 2026 Catcrafts®
catcrafts.net
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 3.0 as published by the Free Software Foundation;
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
module;
#ifdef CRAFTER_GRAPHICS_VULKAN
#include <vulkan/vulkan.h>
#endif
export module Crafter.Graphics:ShaderVulkan;
#ifdef CRAFTER_GRAPHICS_VULKAN
import std;
import :VulkanDevice;
import :Types;
export namespace Crafter {
template<size_t N>
struct StringLiteral {
constexpr StringLiteral(const char (&str)[N]) {
std::copy_n(str, N, value);
}
char value[N];
};
template <
StringLiteral path,
StringLiteral entrypoint,
VkShaderStageFlagBits stage,
std::uint32_t DescriptorCount,
const std::array<DescriptorBinding, DescriptorCount> Descriptors
>
class VulkanShader {
public:
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;
static void CreateShader() {
std::ifstream file(path.value, std::ios::binary);
if (!file) {
std::cerr << "Error: Could not open file " << path.value << std::endl;
}
// Move to the end of the file to determine its size
file.seekg(0, std::ios::end);
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<std::uint32_t> spirv(size / sizeof(std::uint32_t));
// Read the data into the vector
if (!file.read(reinterpret_cast<char*>(spirv.data()), size)) {
std::cerr << "Error: Could not read data from file" << std::endl;
}
file.close();
VkShaderModuleCreateInfo module_info{VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO};
module_info.codeSize = spirv.size() * sizeof(uint32_t);
module_info.pCode = spirv.data();
VkShaderModule shader_module;
VulkanDevice::CheckVkResult(vkCreateShaderModule(VulkanDevice::device, &module_info, nullptr, &shader));
}
};
}
#endif

View file

@ -17,7 +17,10 @@ You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
module;
#ifdef CRAFTER_GRAPHICS_VULKAN
#include <vulkan/vulkan.h>
#endif
export module Crafter.Graphics:Types; export module Crafter.Graphics:Types;
import std; import std;
@ -339,4 +342,11 @@ export namespace Crafter {
CrafterKeysMax CrafterKeysMax
}; };
#ifdef CRAFTER_GRAPHICS_VULKAN
struct DescriptorBinding {
VkDescriptorType type;
std::uint32_t slot;
};
#endif
} }

View file

@ -45,7 +45,6 @@ export namespace Crafter {
inline static PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR; inline static PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR;
inline static PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR; inline static PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR;
inline static VkPhysicalDeviceMemoryProperties memoryProperties; inline static VkPhysicalDeviceMemoryProperties memoryProperties;
inline static VkFormat depthFormat = VK_FORMAT_UNDEFINED;
static void CreateDevice(); static void CreateDevice();
static void CheckVkResult(VkResult result); static void CheckVkResult(VkResult result);
static std::uint32_t GetMemoryType(std::uint32_t typeBits, VkMemoryPropertyFlags properties); static std::uint32_t GetMemoryType(std::uint32_t typeBits, VkMemoryPropertyFlags properties);

View file

@ -36,6 +36,8 @@ export import :Mesh;
export import :VulkanDevice; export import :VulkanDevice;
export import :VulkanTransition; export import :VulkanTransition;
export import :VulkanBuffer; export import :VulkanBuffer;
export import :DescriptorSetVulkan;
export import :ShaderVulkan;
export import :RenderingElement3DVulkan; export import :RenderingElement3DVulkan;
#endif #endif

View file

@ -4,7 +4,7 @@
{ {
"name": "base", "name": "base",
"implementations": ["implementations/Crafter.Graphics-Font", "implementations/Crafter.Graphics-Shm", "implementations/Crafter.Graphics-Window", "implementations/Crafter.Graphics-MouseElement", "implementations/Crafter.Graphics-Transform", "implementations/Crafter.Graphics-GridElement", "implementations/Crafter.Graphics-Image"], "implementations": ["implementations/Crafter.Graphics-Font", "implementations/Crafter.Graphics-Shm", "implementations/Crafter.Graphics-Window", "implementations/Crafter.Graphics-MouseElement", "implementations/Crafter.Graphics-Transform", "implementations/Crafter.Graphics-GridElement", "implementations/Crafter.Graphics-Image"],
"interfaces": ["interfaces/Crafter.Graphics-Window", "interfaces/Crafter.Graphics", "interfaces/Crafter.Graphics-Types", "interfaces/Crafter.Graphics-Font", "interfaces/Crafter.Graphics-Image", "interfaces/Crafter.Graphics-Shm", "interfaces/Crafter.Graphics-Animation", "interfaces/Crafter.Graphics-RenderingElement", "interfaces/Crafter.Graphics-MouseElement", "interfaces/Crafter.Graphics-Transform", "interfaces/Crafter.Graphics-GridElement", "interfaces/Crafter.Graphics-VulkanDevice", "interfaces/Crafter.Graphics-VulkanTransition", "interfaces/Crafter.Graphics-Mesh", "interfaces/Crafter.Graphics-VulkanBuffer", "interfaces/Crafter.Graphics-RenderingElement3DVulkan"], "interfaces": ["interfaces/Crafter.Graphics-Window", "interfaces/Crafter.Graphics", "interfaces/Crafter.Graphics-Types", "interfaces/Crafter.Graphics-Font", "interfaces/Crafter.Graphics-Image", "interfaces/Crafter.Graphics-Shm", "interfaces/Crafter.Graphics-Animation", "interfaces/Crafter.Graphics-RenderingElement", "interfaces/Crafter.Graphics-MouseElement", "interfaces/Crafter.Graphics-Transform", "interfaces/Crafter.Graphics-GridElement", "interfaces/Crafter.Graphics-VulkanDevice", "interfaces/Crafter.Graphics-VulkanTransition", "interfaces/Crafter.Graphics-Mesh", "interfaces/Crafter.Graphics-VulkanBuffer", "interfaces/Crafter.Graphics-RenderingElement3DVulkan", "interfaces/Crafter.Graphics-DescriptorSetVulkan", "interfaces/Crafter.Graphics-ShaderVulkan"],
"type": "library" "type": "library"
}, },
{ {