diff --git a/Crafter.Graphics-VulkanElement.cpp b/Crafter.Graphics-VulkanElement.cpp new file mode 100644 index 0000000..a873b91 --- /dev/null +++ b/Crafter.Graphics-VulkanElement.cpp @@ -0,0 +1,15 @@ +module; + +#include +#include + +module Crafter.Graphics; +using namespace Crafter; + +VulkanElement::VulkanElement(VkPipelineLayout pipelineLayout, VkDescriptorSet* descriptorSet, VkPipeline pipeline) : pipelineLayout(pipelineLayout), descriptorSet(descriptorSet), pipeline(pipeline) { + +} + +VulkanElement::VulkanElement(VkPipelineLayout pipelineLayout, VkDescriptorSet* descriptorSet, VkPipeline pipeline, std::uint32_t sizeX, std::uint32_t sizeY, std::uint32_t sizeZ) : pipelineLayout(pipelineLayout), descriptorSet(descriptorSet), pipeline(pipeline), sizeX(sizeX), sizeY(sizeY), sizeZ(sizeZ) { + +} \ No newline at end of file diff --git a/Crafter.Graphics-VulkanElement.cppm b/Crafter.Graphics-VulkanElement.cppm new file mode 100644 index 0000000..e561d5e --- /dev/null +++ b/Crafter.Graphics-VulkanElement.cppm @@ -0,0 +1,31 @@ +module; + +#include +#include + +export module Crafter.Graphics:VulkanElement; +import Crafter.Component; + +namespace Crafter { + export class VulkanElement : public Component { + public: + VkPipelineLayout pipelineLayout; + VkDescriptorSet* descriptorSet; + VkPipeline pipeline; + std::uint32_t sizeX; + std::uint32_t sizeY; + std::uint32_t sizeZ; + VulkanElement(VkPipelineLayout pipelineLayout, VkDescriptorSet* descriptorSet, VkPipeline pipeline); + VulkanElement(VkPipelineLayout pipelineLayout, VkDescriptorSet* descriptorSet, VkPipeline pipeline, std::uint32_t sizeX, std::uint32_t sizeY, std::uint32_t sizeZ); + + template + static VulkanElement FromPipeline() { + return VulkanElement(Pipeline::pipelineLayout, &Pipeline::descriptorSet, Pipeline::pipeline); + } + + template + static VulkanElement FromPipeline(std::uint32_t sizeX, std::uint32_t sizeY, std::uint32_t sizeZ) { + return VulkanElement(Pipeline::pipelineLayout, &Pipeline::descriptorSet, Pipeline::pipeline, sizeX, sizeY, sizeZ); + } + }; +} diff --git a/Crafter.Graphics-VulkanPipeline.cppm b/Crafter.Graphics-VulkanPipeline.cppm index 047bef0..5076506 100644 --- a/Crafter.Graphics-VulkanPipeline.cppm +++ b/Crafter.Graphics-VulkanPipeline.cppm @@ -13,6 +13,7 @@ module; #include #include "VulkanBuffer.h" #include "camera.hpp" +#include export module Crafter.Graphics:VulkanPipeline; import :VulkanDevice; @@ -20,8 +21,88 @@ import :VulkanShader; import :WindowWaylandVulkan; namespace Crafter { + struct DescriptorEntry { + VkDescriptorType type; + std::uint32_t occurrences = 0; + }; + export template class VulkanPipeline { + private: + constexpr static std::uint32_t totalDescriptorCount = MeshShader::descriptorCount+FragmentShader::descriptorCount; + consteval static std::uint32_t GetUniqueDiscriptorCount() { + DescriptorEntry 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}}; + + for(const DescriptorBinding& binding : MeshShader::descriptors) { + for(DescriptorEntry& type : types) { + if(type.type == binding.type) { + type.occurrences++; + } + } + } + + for(const DescriptorBinding& binding : FragmentShader::descriptors) { + for(DescriptorEntry& type : types) { + if(type.type == binding.type) { + type.occurrences++; + } + } + } + + std::uint32_t size = 0; + for(DescriptorEntry& type : types) { + size+=type.occurrences; + } + + return size; + } + constexpr static std::uint32_t uniqueDescriptorCount = GetUniqueDiscriptorCount(); + consteval static std::array GetPoolSizes() { + std::array types = {}; + std::uint32_t i = 0; + + for(const DescriptorBinding& binding : MeshShader::descriptors) { + for(VkDescriptorPoolSize& type : types) { + if(type.type == binding.type) { + type.descriptorCount++; + goto next; + } + } + types[i].type = binding.type; + types[i].descriptorCount = 1; + next:; + } + + for(const DescriptorBinding& binding : FragmentShader::descriptors) { + for(VkDescriptorPoolSize& type : types) { + if(type.type == binding.type) { + type.descriptorCount++; + goto next2; + } + } + types[i].type = binding.type; + types[i].descriptorCount = 1; + next2:; + } + + return types; + } + consteval static std::array GetDescriptorSet() { + std::array set; + + std::uint32_t i = 0; + for(const DescriptorBinding& binding : MeshShader::descriptors) { + set[i] = {binding.slot, binding.type, 1, VK_SHADER_STAGE_MESH_BIT_EXT, nullptr}; + i++; + } + + for(const DescriptorBinding& binding : FragmentShader::descriptors) { + set[i] = {binding.slot, binding.type, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}; + i++; + } + + return set; + } public: inline static VkPipeline pipeline; inline static VkPipelineLayout pipelineLayout; @@ -51,34 +132,31 @@ namespace Crafter { memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); // Pool - std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(static_cast(poolSizes.size()), poolSizes.data(), 1); + std::array poolSizes = GetPoolSizes(); + VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(uniqueDescriptorCount, poolSizes.data(), 1); VulkanDevice::CHECK_VK_RESULT(vkCreateDescriptorPool(VulkanDevice::device, &descriptorPoolInfo, nullptr, &descriptorPool)); // Layout - std::vector setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_MESH_BIT_EXT, 0), - }; - VkDescriptorSetLayoutCreateInfo descriptorLayoutInfo = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); + constexpr std::array setLayoutBindings = GetDescriptorSet(); + VkDescriptorSetLayoutCreateInfo descriptorLayoutInfo = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), totalDescriptorCount); VulkanDevice::CHECK_VK_RESULT(vkCreateDescriptorSetLayout(VulkanDevice::device, &descriptorLayoutInfo, nullptr, &descriptorSetLayout)); // Set VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); VulkanDevice::CHECK_VK_RESULT(vkAllocateDescriptorSets(VulkanDevice::device, &allocInfo, &descriptorSet)); + std::vector modelWriteDescriptorSets = { vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), }; - vkUpdateDescriptorSets(VulkanDevice::device, static_cast(modelWriteDescriptorSets.size()), modelWriteDescriptorSets.data(), 0, nullptr); + // Layout VkPipelineLayoutCreateInfo pipelineLayoutInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); VulkanDevice::CHECK_VK_RESULT(vkCreatePipelineLayout(VulkanDevice::device, &pipelineLayoutInfo, nullptr, &pipelineLayout)); // Pipeline VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE, 0); + VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); diff --git a/Crafter.Graphics-VulkanShader.cppm b/Crafter.Graphics-VulkanShader.cppm index e13fec1..7aa5724 100644 --- a/Crafter.Graphics-VulkanShader.cppm +++ b/Crafter.Graphics-VulkanShader.cppm @@ -6,6 +6,7 @@ module; #include #include #include +#include export module Crafter.Graphics:VulkanShader; import :VulkanDevice; @@ -20,13 +21,26 @@ namespace Crafter { char value[N]; }; - export template + export struct DescriptorBinding { + VkDescriptorType type; + std::uint32_t slot; + }; + + export template < + StringLiteral path, + StringLiteral entrypoint, + VkShaderStageFlagBits stage, + std::uint32_t DescriptorCount, + std::array Descriptors + > class VulkanShader { public: - inline static VkShaderModule shader; - constexpr static StringLiteral _entrypoint = entrypoint; - constexpr static VkShaderStageFlagBits _stage = stage; - static void CreateShader() { + inline static VkShaderModule shader; + constexpr static std::uint32_t descriptorCount = DescriptorCount; + constexpr static std::array descriptors = Descriptors; + constexpr static StringLiteral _entrypoint = entrypoint; + constexpr static VkShaderStageFlagBits _stage = stage; + static void CreateShader() { std::ifstream file(path.value, std::ios::binary); if (!file) { std::cerr << "Error: Could not open file " << path.value << std::endl; diff --git a/Crafter.Graphics-WindowWaylandVulkan.cpp b/Crafter.Graphics-WindowWaylandVulkan.cpp index 5ad9378..b9b3a07 100644 --- a/Crafter.Graphics-WindowWaylandVulkan.cpp +++ b/Crafter.Graphics-WindowWaylandVulkan.cpp @@ -418,14 +418,12 @@ void WindowWaylandVulkan::Start() { VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, VulkanPipeline, VulkanShader<"test2.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT>>::pipelineLayout, 0, 1, &VulkanPipeline, VulkanShader<"test2.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT>>::descriptorSet, 0, NULL); - - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, VulkanPipeline, VulkanShader<"test2.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT>>::pipeline); - - // Use mesh and task shader to draw the scene - VulkanDevice::vkCmdDrawMeshTasksEXTProc(drawCmdBuffers[i], 3, 1, 1); - - VulkanDevice::vkCmdEndRenderingKHRProc(drawCmdBuffers[i]); + for(VulkanElement* element : vulkanElements.components) { + vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, element->pipelineLayout, 0, 1, element->descriptorSet, 0, NULL); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, element->pipeline); + VulkanDevice::vkCmdDrawMeshTasksEXTProc(drawCmdBuffers[i], element->sizeX, element->sizeY, element->sizeZ); + VulkanDevice::vkCmdEndRenderingKHRProc(drawCmdBuffers[i]); + } image_layout_transition(drawCmdBuffers[i], images[i], diff --git a/Crafter.Graphics-WindowWaylandVulkan.cppm b/Crafter.Graphics-WindowWaylandVulkan.cppm index 52c4736..fffd388 100644 --- a/Crafter.Graphics-WindowWaylandVulkan.cppm +++ b/Crafter.Graphics-WindowWaylandVulkan.cppm @@ -10,6 +10,7 @@ module; export module Crafter.Graphics:WindowWaylandVulkan; import Crafter.Event; import :WindowWayland; +import :VulkanElement; import Crafter.Component; namespace Crafter { @@ -28,6 +29,7 @@ namespace Crafter { export class WindowWaylandVulkan : public WindowWayland { public: + ComponentRefVector vulkanElements; WindowWaylandVulkan(std::string name, std::uint32_t width, std::uint32_t height); ~WindowWaylandVulkan(); void Start(); diff --git a/Crafter.Graphics.cppm b/Crafter.Graphics.cppm index a51ec86..aaa5758 100644 --- a/Crafter.Graphics.cppm +++ b/Crafter.Graphics.cppm @@ -8,4 +8,5 @@ export import :UiElement; export import :Types; export import :VulkanDevice; export import :VulkanPipeline; -export import :VulkanShader; \ No newline at end of file +export import :VulkanShader; +export import :VulkanElement; \ No newline at end of file diff --git a/main.cpp b/main.cpp index 40515a5..f64750f 100644 --- a/main.cpp +++ b/main.cpp @@ -5,6 +5,10 @@ import Crafter.Graphics; using namespace Crafter; +typedef VulkanShader<"test.spirv", "main", VK_SHADER_STAGE_MESH_BIT_EXT, 1, {{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0}}> MeshShader; +typedef VulkanShader<"test2.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT, 0, {}> FragmentShader; +typedef VulkanPipeline, VulkanShader<"test2.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT, 0, {}>> Pipeline; + int main() { // WindowWaylandWayland window("test", 128, 128); // UiElement test( @@ -28,10 +32,12 @@ int main() { // } VulkanDevice::CreateDevice(); - WindowWaylandVulkan window("bruh", 128, 128); - VulkanShader<"test.spirv", "main", VK_SHADER_STAGE_MESH_BIT_EXT>::CreateShader(); - VulkanShader<"test2.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT>::CreateShader(); - VulkanPipeline, VulkanShader<"test2.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT>>::CreatePipeline(); + WindowWaylandVulkan window("Crafter.Graphics", 128, 128); + MeshShader::CreateShader(); + FragmentShader::CreateShader(); + Pipeline::CreatePipeline(); + VulkanElement test = VulkanElement::FromPipeline(3, 1, 1); + window.vulkanElements.AddComponent(&test); window.Start(); while(true) { diff --git a/project.json b/project.json index 0aff66f..9045a7e 100644 --- a/project.json +++ b/project.json @@ -4,9 +4,9 @@ { "name": "base", "standard": "c++26", - "source_files": ["Crafter.Graphics-Window","Crafter.Graphics-WindowWayland","Crafter.Graphics-WindowWaylandWayland", "Crafter.Graphics-UiElement", "Crafter.Graphics-VulkanDevice", "Crafter.Graphics-WindowWaylandVulkan", "VulkanBuffer", "VulkanTools"], + "source_files": ["Crafter.Graphics-Window","Crafter.Graphics-WindowWayland","Crafter.Graphics-WindowWaylandWayland", "Crafter.Graphics-UiElement", "Crafter.Graphics-VulkanDevice", "Crafter.Graphics-WindowWaylandVulkan", "VulkanBuffer", "VulkanTools", "Crafter.Graphics-VulkanElement"], "c_files": ["wayland-xdg-decoration-unstable-v1-client-protocol", "xdg-shell-protocol", "shm"], - "module_files": ["Crafter.Graphics-Window","Crafter.Graphics-WindowWayland","Crafter.Graphics-WindowWaylandWayland", "Crafter.Graphics", "Crafter.Graphics-UiElement", "Crafter.Graphics-Types", "Crafter.Graphics-VulkanDevice", "Crafter.Graphics-VulkanPipeline", "Crafter.Graphics-VulkanShader", "Crafter.Graphics-WindowWaylandVulkan"], + "module_files": ["Crafter.Graphics-Window","Crafter.Graphics-WindowWayland","Crafter.Graphics-WindowWaylandWayland", "Crafter.Graphics", "Crafter.Graphics-UiElement", "Crafter.Graphics-Types", "Crafter.Graphics-VulkanDevice", "Crafter.Graphics-VulkanPipeline", "Crafter.Graphics-VulkanShader", "Crafter.Graphics-WindowWaylandVulkan", "Crafter.Graphics-VulkanElement"], "build_dir": "./build", "output_dir": "./bin", "type":"library", diff --git a/test.spirv b/test.spirv deleted file mode 100644 index d9dcb78..0000000 Binary files a/test.spirv and /dev/null differ diff --git a/test2.spirv b/test2.spirv deleted file mode 100644 index fc2aac6..0000000 Binary files a/test2.spirv and /dev/null differ