From 9f62233a07379d4c219c8fc8c7f003eaecd3160a Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Wed, 28 Jan 2026 23:37:12 +0100 Subject: [PATCH] shader --- examples/VulkanCube/README.md | 23 --- examples/VulkanCube/main.cpp | 86 --------- examples/VulkanCube/project.json | 22 --- examples/VulkanShader/CustomShader.glsl | 49 ----- examples/VulkanShader/README.md | 32 ---- examples/VulkanShader/main.cpp | 60 ------- examples/VulkanShader/project.json | 29 --- examples/VulkanTriangle/closesthit.glsl | 0 examples/VulkanTriangle/main.cpp | 5 + examples/VulkanTriangle/miss.glsl | 0 examples/VulkanTriangle/project.json | 7 + examples/VulkanTriangle/raygen.glsl | 12 ++ .../Crafter.Graphics-VulkanDevice.cpp | 21 +-- .../Crafter.Graphics-Window_vulkan.cpp | 5 +- .../Crafter.Graphics-DescriptorSetVulkan.cppm | 167 ++++++++++++++++++ interfaces/Crafter.Graphics-ShaderVulkan.cppm | 85 +++++++++ interfaces/Crafter.Graphics-Types.cppm | 12 +- interfaces/Crafter.Graphics-VulkanDevice.cppm | 1 - interfaces/Crafter.Graphics.cppm | 2 + project.json | 2 +- 20 files changed, 298 insertions(+), 322 deletions(-) delete mode 100644 examples/VulkanCube/README.md delete mode 100644 examples/VulkanCube/main.cpp delete mode 100644 examples/VulkanCube/project.json delete mode 100644 examples/VulkanShader/CustomShader.glsl delete mode 100644 examples/VulkanShader/README.md delete mode 100644 examples/VulkanShader/main.cpp delete mode 100644 examples/VulkanShader/project.json create mode 100644 examples/VulkanTriangle/closesthit.glsl create mode 100644 examples/VulkanTriangle/miss.glsl create mode 100644 examples/VulkanTriangle/raygen.glsl create mode 100644 interfaces/Crafter.Graphics-DescriptorSetVulkan.cppm create mode 100644 interfaces/Crafter.Graphics-ShaderVulkan.cppm diff --git a/examples/VulkanCube/README.md b/examples/VulkanCube/README.md deleted file mode 100644 index 09e3dcb..0000000 --- a/examples/VulkanCube/README.md +++ /dev/null @@ -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::Translation(0, 0, -5); -camera.Update(); -``` - -## How to Run - -```bash -crafter-build build executable -r -``` \ No newline at end of file diff --git a/examples/VulkanCube/main.cpp b/examples/VulkanCube/main.cpp deleted file mode 100644 index 922a4aa..0000000 --- a/examples/VulkanCube/main.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include - -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 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 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::Translation(0, 0, -5); - /* - Calculates the viewprojection, must be called each time after updating the camera. - */ - camera.Update(); - - MeshShader meshShader(&cube, &camera); - DescriptorSet descriptors; - meshShader.WriteDescriptors(descriptors.set[0]); - - /* - Calculates the modelviewprojection matrix. - */ - meshShader.Update(); - - float counter = 0; - EventListener 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::Rotation(counter, counter, 0); - /* - We edited the transform so must recalculate the model view projection matrix. - */ - meshShader.Update(); - counter+=0.01; - }); - - window.StartSync(); -} diff --git a/examples/VulkanCube/project.json b/examples/VulkanCube/project.json deleted file mode 100644 index 2a743e7..0000000 --- a/examples/VulkanCube/project.json +++ /dev/null @@ -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" - } - ] - } - ] -} diff --git a/examples/VulkanShader/CustomShader.glsl b/examples/VulkanShader/CustomShader.glsl deleted file mode 100644 index b3b70c4..0000000 --- a/examples/VulkanShader/CustomShader.glsl +++ /dev/null @@ -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); -} diff --git a/examples/VulkanShader/README.md b/examples/VulkanShader/README.md deleted file mode 100644 index 50ac474..0000000 --- a/examples/VulkanShader/README.md +++ /dev/null @@ -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> colors; - CustomShader(const std::vector>& 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)); - } - 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 -``` diff --git a/examples/VulkanShader/main.cpp b/examples/VulkanShader/main.cpp deleted file mode 100644 index 9367d67..0000000 --- a/examples/VulkanShader/main.cpp +++ /dev/null @@ -1,60 +0,0 @@ - -#include "../../lib/VulkanInitializers.hpp" -#include - -//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 Pipeline; - - -class CustomShader { - public: - /* - Define a buffer holding our color vectors. - */ - Buffer> colors; - /* - Initialze our buffer as shader visible storage buffer with the size of the colors vector. - */ - CustomShader(const std::vector>& 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)); - } - 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 descriptors; - CustomShader customShader({{1,0,0,1}, {0,1,0,1}, {0,0,1,1}}); - customShader.WriteDescriptors(descriptors.set[0]); - - EventListener 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(); -} diff --git a/examples/VulkanShader/project.json b/examples/VulkanShader/project.json deleted file mode 100644 index 78a4fe1..0000000 --- a/examples/VulkanShader/project.json +++ /dev/null @@ -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" - } - ] - } - ] -} diff --git a/examples/VulkanTriangle/closesthit.glsl b/examples/VulkanTriangle/closesthit.glsl new file mode 100644 index 0000000..e69de29 diff --git a/examples/VulkanTriangle/main.cpp b/examples/VulkanTriangle/main.cpp index 103d500..f10af52 100644 --- a/examples/VulkanTriangle/main.cpp +++ b/examples/VulkanTriangle/main.cpp @@ -4,13 +4,18 @@ import Crafter.Graphics; using namespace Crafter; 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() { + /* This sets up all necessary things and creates the vulkan device. This must be called before any vulkan related things. Things like VkDevice are static members of the VulkanDevice class. */ VulkanDevice::CreateDevice(); + Raygenspv::CreateShader(); + WindowVulkan window(1280, 720, "HelloVulkan"); /* diff --git a/examples/VulkanTriangle/miss.glsl b/examples/VulkanTriangle/miss.glsl new file mode 100644 index 0000000..e69de29 diff --git a/examples/VulkanTriangle/project.json b/examples/VulkanTriangle/project.json index a4b0e06..5e7d608 100644 --- a/examples/VulkanTriangle/project.json +++ b/examples/VulkanTriangle/project.json @@ -9,6 +9,13 @@ "path":"../../project.json", "configuration":"lib-vulkan" } + ], + "shaders": [ + { + "path":"raygen.glsl", + "type":6, + "entrypoint":"main" + } ] } ] diff --git a/examples/VulkanTriangle/raygen.glsl b/examples/VulkanTriangle/raygen.glsl new file mode 100644 index 0000000..c7b8e5c --- /dev/null +++ b/examples/VulkanTriangle/raygen.glsl @@ -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)); +} \ No newline at end of file diff --git a/implementations/Crafter.Graphics-VulkanDevice.cpp b/implementations/Crafter.Graphics-VulkanDevice.cpp index 955a2ff..7213643 100644 --- a/implementations/Crafter.Graphics-VulkanDevice.cpp +++ b/implementations/Crafter.Graphics-VulkanDevice.cpp @@ -45,6 +45,7 @@ const char* const deviceExtensionNames[] = { "VK_KHR_dynamic_rendering", "VK_KHR_acceleration_structure", "VK_KHR_deferred_host_operations", + "VK_KHR_ray_tracing_pipeline" }; const char* const layerNames[] = { "VK_LAYER_KHRONOS_validation" @@ -213,8 +214,14 @@ void VulkanDevice::CreateDevice() { queueCreateInfo.queueCount = 1; queueCreateInfo.pQueuePriorities = &priority; + VkPhysicalDeviceRayTracingPipelineFeaturesKHR physicalDeviceRayTracingPipelineFeatures{ + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR, + .rayTracingPipeline = VK_TRUE + }; + VkPhysicalDeviceBufferDeviceAddressFeatures deviceBufferDeviceAddressFeature = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES, + .pNext = &physicalDeviceRayTracingPipelineFeatures, .bufferDeviceAddress = VK_TRUE }; @@ -279,20 +286,6 @@ void VulkanDevice::CreateDevice() { vkGetPhysicalDeviceMemoryProperties(physDevice, &memoryProperties); - std::vector formatList = { - VK_FORMAT_D32_SFLOAT, - }; - - for (auto& format : formatList) { - VkFormatProperties formatProps; - vkGetPhysicalDeviceFormatProperties(physDevice, format, &formatProps); - if (formatProps.optimalTilingFeatures) - { - depthFormat = format; - break; - } - } - vkCmdDrawMeshTasksEXTProc = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdDrawMeshTasksEXT")); vkCmdBeginRenderingKHRProc = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdBeginRenderingKHR")); vkCmdEndRenderingKHRProc = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCmdEndRenderingKHR")); diff --git a/implementations/Crafter.Graphics-Window_vulkan.cpp b/implementations/Crafter.Graphics-Window_vulkan.cpp index 1dd3bca..b417fa3 100644 --- a/implementations/Crafter.Graphics-Window_vulkan.cpp +++ b/implementations/Crafter.Graphics-Window_vulkan.cpp @@ -395,10 +395,7 @@ void WindowVulkan::Render() { VkCommandBufferBeginInfo cmdBufInfo {}; cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - - VkClearValue clearValues[1]; - clearValues[0].color = { }; - + VulkanDevice::CheckVkResult(vkBeginCommandBuffer(drawCmdBuffers[currentBuffer], &cmdBufInfo)); VkImageSubresourceRange range{}; diff --git a/interfaces/Crafter.Graphics-DescriptorSetVulkan.cppm b/interfaces/Crafter.Graphics-DescriptorSetVulkan.cppm new file mode 100644 index 0000000..c4077c5 --- /dev/null +++ b/interfaces/Crafter.Graphics-DescriptorSetVulkan.cppm @@ -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 +#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 + class DescriptorPool { + public: + inline static Event onDescriptorRefresh; + inline static std::uint32_t setIndex = 0; + inline static std::vector sets; + inline static VkDescriptorPool descriptorPool[PoolCount] = { VK_NULL_HANDLE }; + + private: + template + consteval static void GetOccuringDescriptors(std::array& 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 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(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 GetPoolSizes() { + std::array 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 + consteval static std::array GetDescriptorSet() { + std::array 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 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 setLayoutBindingsMesh = GetDescriptorSet(); + 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 \ No newline at end of file diff --git a/interfaces/Crafter.Graphics-ShaderVulkan.cppm b/interfaces/Crafter.Graphics-ShaderVulkan.cppm new file mode 100644 index 0000000..6f9e767 --- /dev/null +++ b/interfaces/Crafter.Graphics-ShaderVulkan.cppm @@ -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 +#endif +export module Crafter.Graphics:ShaderVulkan; +#ifdef CRAFTER_GRAPHICS_VULKAN +import std; +import :VulkanDevice; +import :Types; + +export namespace Crafter { + template + 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 Descriptors + > + class VulkanShader { + public: + constexpr static VkShaderStageFlagBits _stage = stage; + constexpr static std::array 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 spirv(size / sizeof(std::uint32_t)); + + // Read the data into the vector + if (!file.read(reinterpret_cast(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 \ No newline at end of file diff --git a/interfaces/Crafter.Graphics-Types.cppm b/interfaces/Crafter.Graphics-Types.cppm index 59b3296..8027d43 100644 --- a/interfaces/Crafter.Graphics-Types.cppm +++ b/interfaces/Crafter.Graphics-Types.cppm @@ -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 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - +module; +#ifdef CRAFTER_GRAPHICS_VULKAN +#include +#endif export module Crafter.Graphics:Types; import std; @@ -339,4 +342,11 @@ export namespace Crafter { CrafterKeysMax }; + + #ifdef CRAFTER_GRAPHICS_VULKAN + struct DescriptorBinding { + VkDescriptorType type; + std::uint32_t slot; + }; + #endif } diff --git a/interfaces/Crafter.Graphics-VulkanDevice.cppm b/interfaces/Crafter.Graphics-VulkanDevice.cppm index 9855cf8..1b4e937 100644 --- a/interfaces/Crafter.Graphics-VulkanDevice.cppm +++ b/interfaces/Crafter.Graphics-VulkanDevice.cppm @@ -45,7 +45,6 @@ export namespace Crafter { inline static PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR; inline static PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR; inline static VkPhysicalDeviceMemoryProperties memoryProperties; - inline static VkFormat depthFormat = VK_FORMAT_UNDEFINED; static void CreateDevice(); static void CheckVkResult(VkResult result); static std::uint32_t GetMemoryType(std::uint32_t typeBits, VkMemoryPropertyFlags properties); diff --git a/interfaces/Crafter.Graphics.cppm b/interfaces/Crafter.Graphics.cppm index 3c56413..d3ca9c3 100644 --- a/interfaces/Crafter.Graphics.cppm +++ b/interfaces/Crafter.Graphics.cppm @@ -36,6 +36,8 @@ export import :Mesh; export import :VulkanDevice; export import :VulkanTransition; export import :VulkanBuffer; +export import :DescriptorSetVulkan; +export import :ShaderVulkan; export import :RenderingElement3DVulkan; #endif diff --git a/project.json b/project.json index d1a5fb4..188c807 100644 --- a/project.json +++ b/project.json @@ -4,7 +4,7 @@ { "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"], - "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" }, {