new descriptor layout 2

This commit is contained in:
Jorijn van der Graaf 2026-02-03 21:03:11 +01:00
commit d1b8e45fb6
13 changed files with 412 additions and 128 deletions

View file

@ -34,19 +34,16 @@ export namespace Crafter {
bool occured = true;
};
class DescriptorPool {
public:
Event<void> onDescriptorRefresh;
std::uint32_t setIndex = 0;
std::vector<VkDescriptorSet> sets;
VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
template <typename Shader>
consteval static void GetOccuringDescriptors(std::array<DescriptorEntry, 20>& types) {
for (const DescriptorBinding& binding : Shader::descriptors) {
for (const VkDescriptorSetLayoutBinding& binding : Shader::descriptors) {
for (DescriptorEntry& type : types) {
if (type.type == binding.type) {
if (type.type == binding.descriptorType) {
type.occured = true;
}
}
@ -77,10 +74,10 @@ export namespace Crafter {
}
([&] {
for (const DescriptorBinding& binding : Shaders::descriptors) {
for (const VkDescriptorSetLayoutBinding& binding : Shaders::descriptors) {
bool found = false;
for(VkDescriptorPoolSize& type : types) {
if(type.type == binding.type && type.descriptorCount != 12345) {
if(type.type == binding.descriptorType && type.descriptorCount != 12345) {
type.descriptorCount += 1;
found = true;
}
@ -88,7 +85,7 @@ export namespace Crafter {
if(!found) {
for(std::uint32_t i = 0; i < GetUniqueDiscriptorCount<Shaders...>(); i++){
if(types[i].descriptorCount == 12345) {
types[i].type = binding.type;
types[i].type = binding.descriptorType;
types[i].descriptorCount = 1;
break;
}
@ -125,10 +122,6 @@ export namespace Crafter {
};
VulkanDevice::CheckVkResult(vkAllocateDescriptorSets(VulkanDevice::device, &allocInfo, sets.data()));
setIndex = 0;
onDescriptorRefresh.Invoke();
}
};
}

View file

@ -0,0 +1,48 @@
/*
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:DescriptorSetLayoutVulkan;
#ifdef CRAFTER_GRAPHICS_VULKAN
import std;
import :VulkanDevice;
import :Types;
import Crafter.Event;
export namespace Crafter {
template<std::uint32_t DescriptorCount, const std::array<VkDescriptorSetLayoutBinding, DescriptorCount> Descriptors>
class DescriptorSetLayoutVulkan {
public:
inline static VkDescriptorSetLayout layout;
constexpr static std::span<const VkDescriptorSetLayoutBinding> descriptors = Descriptors;
static void Init() {
VkDescriptorSetLayoutCreateInfo descriptorLayoutInfoMesh = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = DescriptorCount,
.pBindings = Descriptors.data()
};
VulkanDevice::CheckVkResult(vkCreateDescriptorSetLayout(VulkanDevice::device, &descriptorLayoutInfoMesh, nullptr, &layout));
}
};
}
#endif

View file

@ -0,0 +1,174 @@
/*
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:ImageVulkan;
import std;
import :VulkanBuffer;
export namespace Crafter {
#ifdef CRAFTER_GRAPHICS_VULKAN
template <typename PixelType>
class ImageVulkan {
public:
std::uint32_t width;
std::uint32_t height;
VkImage image;
VkDeviceMemory imageMemory;
VulkanBuffer<PixelType, true, false, false> buffer;
VkImageView imageView;
VkDescriptorImageInfo descr;
ImageVulkan(std::uint32_t width, std::uint32_t height, VkCommandBuffer cmd, VkFormat format) : width(width), height(height) {
buffer.Create(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, width * height);
VkImageCreateInfo imageInfo{};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.extent.width = width;
imageInfo.extent.height = height;
imageInfo.extent.depth = 1;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.format = format;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VulkanDevice::CheckVkResult(vkCreateImage(VulkanDevice::device, &imageInfo, nullptr, &image));
VkMemoryRequirements memRequirements;
vkGetImageMemoryRequirements(VulkanDevice::device, image, &memRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = VulkanDevice::GetMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VulkanDevice::CheckVkResult(vkAllocateMemory(VulkanDevice::device, &allocInfo, nullptr, &imageMemory));
vkBindImageMemory(VulkanDevice::device, image, imageMemory, 0);
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = image;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = format;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1;
VulkanDevice::CheckVkResult(vkCreateImageView(VulkanDevice::device, &viewInfo, nullptr, &imageView));
TransitionImageLayout(cmd, image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
void Update(const PixelType* bufferdata, VkCommandBuffer cmd) {
std::memcpy(buffer.value, bufferdata, height*width*sizeof(PixelType));
buffer.FlushDevice(cmd, VK_ACCESS_MEMORY_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
TransitionImageLayout(cmd, image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
VkBufferImageCopy region{};
region.bufferOffset = 0;
region.bufferRowLength = 0;
region.bufferImageHeight = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = 0;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
region.imageOffset = {0, 0, 0};
region.imageExtent = { width, height, 1};
vkCmdCopyBufferToImage(
cmd,
buffer.buffer,
image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
&region
);
TransitionImageLayout(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
private:
void TransitionImageLayout(VkCommandBuffer cmd, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout) {
VkImageMemoryBarrier barrier{};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = oldLayout;
barrier.newLayout = newLayout;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
barrier.srcAccessMask = 0;
barrier.dstAccessMask = 0;
VkPipelineStageFlags sourceStage;
VkPipelineStageFlags destinationStage;
if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
} else {
throw std::invalid_argument("unsupported layout transition!");
}
vkCmdPipelineBarrier(
cmd,
sourceStage, destinationStage,
0,
0, nullptr,
0, nullptr,
1, &barrier
);
}
};
#endif
}

View file

@ -0,0 +1,64 @@
/*
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:SamplerVulkan;
import std;
import :VulkanBuffer;
import :ImageVulkan;
export namespace Crafter {
#ifdef CRAFTER_GRAPHICS_VULKAN
template <typename PixelType>
class SamplerVulkan {
public:
VkSampler textureSampler;
VkDescriptorImageInfo imageInfo;
SamplerVulkan(ImageVulkan<PixelType>& texture) {
VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = VK_FILTER_LINEAR;
samplerInfo.minFilter = VK_FILTER_LINEAR;
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.anisotropyEnable = VK_FALSE;
samplerInfo.maxAnisotropy = 1;
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
samplerInfo.unnormalizedCoordinates = VK_FALSE;
samplerInfo.compareEnable = VK_FALSE;
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
samplerInfo.mipLodBias = 0.0f;
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = 0.0f;
VulkanDevice::CheckVkResult(vkCreateSampler(VulkanDevice::device, &samplerInfo, nullptr, &textureSampler));
imageInfo = {
.sampler = textureSampler
};
}
};
#endif
}

View file

@ -40,27 +40,13 @@ export namespace Crafter {
template <
StringLiteral path,
StringLiteral entrypoint,
VkShaderStageFlagBits stage,
std::uint32_t DescriptorCount,
const std::array<DescriptorBinding, DescriptorCount> Descriptors
VkShaderStageFlagBits stage
>
class VulkanShader {
public:
constexpr static VkShaderStageFlagBits _stage = stage;
constexpr static StringLiteral _entrypoint = entrypoint;
constexpr static std::span<const DescriptorBinding> descriptors = Descriptors;
inline static VkShaderModule shader;
inline static VkDescriptorSetLayout layout;
consteval static std::array<VkDescriptorSetLayoutBinding, DescriptorCount> GetDescriptorSet() {
std::array<VkDescriptorSetLayoutBinding, DescriptorCount> set;
for(std::uint32_t i = 0; i < Descriptors.size(); i++) {
set[i] = {Descriptors[i].slot, Descriptors[i].type, 1, stage, nullptr};
}
return set;
}
static void CreateShader() {
std::ifstream file(path.value, std::ios::binary);
@ -88,14 +74,6 @@ export namespace Crafter {
VkShaderModule shader_module;
VulkanDevice::CheckVkResult(vkCreateShaderModule(VulkanDevice::device, &module_info, nullptr, &shader));
constexpr std::array<VkDescriptorSetLayoutBinding, DescriptorCount> setLayoutBindingsMesh = GetDescriptorSet();
VkDescriptorSetLayoutCreateInfo descriptorLayoutInfoMesh = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = DescriptorCount,
.pBindings = setLayoutBindingsMesh.data()
};
VulkanDevice::CheckVkResult(vkCreateDescriptorSetLayout(VulkanDevice::device, &descriptorLayoutInfoMesh, nullptr, &layout));
}
};
}

View file

@ -76,6 +76,12 @@ export namespace Crafter {
std::uint8_t a;
};
struct __attribute__((packed)) Pixel_RU8_GU8_BU8 {
std::uint8_t r;
std::uint8_t g;
std::uint8_t b;
};
// struct __attribute__((packed)) Vertex {
// float x;
// float y;

View file

@ -383,14 +383,15 @@ export namespace Crafter {
.preferred_scale = xdg_surface_handle_preferred_scale,
};
void CreateSwapchain();
static constexpr std::uint32_t numFrames = 3;
VkSurfaceKHR vulkanSurface = VK_NULL_HANDLE;
VkSwapchainKHR swapChain = VK_NULL_HANDLE;
VkFormat colorFormat;
VkColorSpaceKHR colorSpace;
std::vector<VkImage> images;
std::vector<VkImageView> imageViews;
VkImage images[numFrames];
VkImageView imageViews[numFrames];
std::thread thread;
std::vector<VkCommandBuffer> drawCmdBuffers;
VkCommandBuffer drawCmdBuffers[numFrames];
VkSubmitInfo submitInfo;
Semaphores semaphores;
uint32_t currentBuffer = 0;

View file

@ -41,6 +41,9 @@ export import :ShaderVulkan;
export import :ShaderBindingTableVulkan;
export import :PipelineRTVulkan;
export import :RenderingElement3DVulkan;
export import :ImageVulkan;
export import :SamplerVulkan;
export import :DescriptorSetLayoutVulkan;
#endif
// export import :WindowWaylandVulkan;