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

@ -6,9 +6,9 @@ import std;
import Crafter.Event; import Crafter.Event;
import Crafter.Math; import Crafter.Math;
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; typedef VulkanShader<"raygen.spv", "main", VK_SHADER_STAGE_RAYGEN_BIT_KHR> Raygenspv;
typedef VulkanShader<"closesthit.spv", "main", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 0, {{}}> Closesthitspv; typedef VulkanShader<"closesthit.spv", "main", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR> Closesthitspv;
typedef VulkanShader<"miss.spv", "main", VK_SHADER_STAGE_MISS_BIT_KHR, 0, {{}}> Misspv; typedef VulkanShader<"miss.spv", "main", VK_SHADER_STAGE_MISS_BIT_KHR> Misspv;
typedef std::tuple<Raygenspv, Misspv, Closesthitspv> AllShaders; typedef std::tuple<Raygenspv, Misspv, Closesthitspv> AllShaders;
typedef std::tuple< typedef std::tuple<
ShaderGroup<0, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR>, ShaderGroup<0, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR>,
@ -16,6 +16,22 @@ typedef std::tuple<
ShaderGroup<VK_SHADER_UNUSED_KHR, 2, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR> ShaderGroup<VK_SHADER_UNUSED_KHR, 2, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR>
> ShaderGroups; > ShaderGroups;
typedef PipelineRTVulkan<AllShaders, ShaderGroups> Pipeline; typedef PipelineRTVulkan<AllShaders, ShaderGroups> Pipeline;
typedef DescriptorSetLayoutVulkan<1, {{
{
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR,
},
}}> descriptorSetLayoutTlas;
typedef DescriptorSetLayoutVulkan<1, {{
{
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR,
}
}}> descriptorSetLayoutImage;
int main() { int main() {
VulkanDevice::CreateDevice(); VulkanDevice::CreateDevice();
@ -27,13 +43,17 @@ int main() {
Misspv::CreateShader(); Misspv::CreateShader();
ShaderBindingTableVulkan<AllShaders>::Init(); ShaderBindingTableVulkan<AllShaders>::Init();
std::array<VkDescriptorSetLayout, 3> layouts {{Raygenspv::layout, Raygenspv::layout, Raygenspv::layout}};
Pipeline::Init(cmd, layouts); descriptorSetLayoutTlas::Init();
window.SetPipelineRT<Pipeline>(); descriptorSetLayoutImage::Init();
std::array<VkDescriptorSetLayout, 4> layouts {{descriptorSetLayoutTlas::layout, descriptorSetLayoutImage::layout, descriptorSetLayoutImage::layout, descriptorSetLayoutImage::layout}};
DescriptorPool pool; DescriptorPool pool;
pool.sets.resize(3); pool.sets.resize(4);
pool.BuildPool(DescriptorPool::GetPoolSizes<Raygenspv, Raygenspv, Raygenspv>(), layouts); pool.BuildPool(DescriptorPool::GetPoolSizes<descriptorSetLayoutTlas, descriptorSetLayoutImage, descriptorSetLayoutImage, descriptorSetLayoutImage>(), layouts);
Pipeline::Init(cmd, layouts);
window.SetPipelineRT<Pipeline>();
Mesh triangleMesh; Mesh triangleMesh;
std::array<Vertex, 3> verts {{{-150, -150, 100}, {0, 150, 100}, {150, -150, 100}}}; std::array<Vertex, 3> verts {{{-150, -150, 100}, {0, 150, 100}, {150, -150, 100}}};
@ -43,14 +63,24 @@ int main() {
MatrixRowMajor<float, 4, 3, 1> transform = MatrixRowMajor<float, 4, 3, 1>::Identity(); MatrixRowMajor<float, 4, 3, 1> transform = MatrixRowMajor<float, 4, 3, 1>::Identity();
std::memcpy(el.instance.transform.matrix, transform.m, sizeof(transform.m)); std::memcpy(el.instance.transform.matrix, transform.m, sizeof(transform.m));
RenderingElement3DVulkan::tlases.resize(3); RenderingElement3DVulkan::tlases.resize(WindowVulkan::numFrames);
RenderingElement3DVulkan::BuildTLAS(cmd, 0); RenderingElement3DVulkan::BuildTLAS(cmd, 0);
RenderingElement3DVulkan::BuildTLAS(cmd, 1); RenderingElement3DVulkan::BuildTLAS(cmd, 1);
RenderingElement3DVulkan::BuildTLAS(cmd, 2); RenderingElement3DVulkan::BuildTLAS(cmd, 2);
VkDescriptorImageInfo imageInfo = { VkDescriptorImageInfo imageInfo[WindowVulkan::numFrames] = {
{
.imageView = window.imageViews[0], .imageView = window.imageViews[0],
.imageLayout = VK_IMAGE_LAYOUT_GENERAL .imageLayout = VK_IMAGE_LAYOUT_GENERAL
},
{
.imageView = window.imageViews[1],
.imageLayout = VK_IMAGE_LAYOUT_GENERAL
},
{
.imageView = window.imageViews[2],
.imageLayout = VK_IMAGE_LAYOUT_GENERAL
},
}; };
VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorSetAccelerationStructure { VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorSetAccelerationStructure {
@ -59,8 +89,9 @@ int main() {
.pAccelerationStructures = &RenderingElement3DVulkan::tlases[0].accelerationStructure .pAccelerationStructures = &RenderingElement3DVulkan::tlases[0].accelerationStructure
}; };
VkWriteDescriptorSet write[2] = { VkWriteDescriptorSet write[4];
{
write[0] = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.pNext = &writeDescriptorSetAccelerationStructure, .pNext = &writeDescriptorSetAccelerationStructure,
.dstSet = pool.sets[0], .dstSet = pool.sets[0],
@ -68,19 +99,21 @@ int main() {
.dstArrayElement = 0, .dstArrayElement = 0,
.descriptorCount = 1, .descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, .descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
}, };
{
for(std::uint32_t i = 0; i < WindowVulkan::numFrames; i++) {
write[i+1] = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = pool.sets[0], .dstSet = pool.sets[i+1],
.dstBinding = 1, .dstBinding = 0,
.dstArrayElement = 0, .dstArrayElement = 0,
.descriptorCount = 1, .descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.pImageInfo = &imageInfo .pImageInfo = &imageInfo[i]
}
}; };
vkUpdateDescriptorSets(VulkanDevice::device, 2, write, 0, nullptr); }
window.descriptorsRt = {pool.sets[0]}; vkUpdateDescriptorSets(VulkanDevice::device, 4, write, 0, nullptr);
window.descriptorsRt = {pool.sets[0], pool.sets[1]};
/* /*
FinishInit executes all commands recorded to StartInit. FinishInit executes all commands recorded to StartInit.
@ -104,10 +137,6 @@ int main() {
MatrixRowMajor<float, 4, 3, 1> transform = MatrixRowMajor<float, 4, 3, 1>::Translation(value, 0, 0); MatrixRowMajor<float, 4, 3, 1> transform = MatrixRowMajor<float, 4, 3, 1>::Translation(value, 0, 0);
std::memcpy(el.instance.transform.matrix, transform.m, sizeof(transform.m)); std::memcpy(el.instance.transform.matrix, transform.m, sizeof(transform.m));
RenderingElement3DVulkan::BuildTLAS(window.drawCmdBuffers[window.currentBuffer], window.currentBuffer); RenderingElement3DVulkan::BuildTLAS(window.drawCmdBuffers[window.currentBuffer], window.currentBuffer);
VkDescriptorImageInfo imageInfo = {
.imageView = window.imageViews[window.currentBuffer],
.imageLayout = VK_IMAGE_LAYOUT_GENERAL
};
VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorSetAccelerationStructure { VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorSetAccelerationStructure {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
@ -115,28 +144,18 @@ int main() {
.pAccelerationStructures = &RenderingElement3DVulkan::tlases[window.currentBuffer].accelerationStructure .pAccelerationStructures = &RenderingElement3DVulkan::tlases[window.currentBuffer].accelerationStructure
}; };
VkWriteDescriptorSet write[2] = { VkWriteDescriptorSet write = {
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.pNext = &writeDescriptorSetAccelerationStructure, .pNext = &writeDescriptorSetAccelerationStructure,
.dstSet = pool.sets[window.currentBuffer], .dstSet = pool.sets[0],
.dstBinding = 0, .dstBinding = 0,
.dstArrayElement = 0, .dstArrayElement = 0,
.descriptorCount = 1, .descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, .descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
},
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = pool.sets[window.currentBuffer],
.dstBinding = 1,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.pImageInfo = &imageInfo
}
}; };
vkUpdateDescriptorSets(VulkanDevice::device, 2, write, 0, nullptr); vkUpdateDescriptorSets(VulkanDevice::device, 1, &write, 0, nullptr);
window.descriptorsRt[0] = pool.sets[window.currentBuffer];
window.descriptorsRt[1] = pool.sets[window.currentBuffer+1];
}); });
window.Render(); window.Render();

View file

@ -3,7 +3,7 @@
#extension GL_EXT_shader_image_load_formatted : enable #extension GL_EXT_shader_image_load_formatted : enable
layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS;
layout(binding = 1, set = 0, rgba8) uniform writeonly image2D image; layout(binding = 0, set = 1, rgba8) uniform writeonly image2D image;
layout(location = 0) rayPayloadEXT vec3 hitValue; layout(location = 0) rayPayloadEXT vec3 hitValue;

View file

@ -6,9 +6,9 @@ import std;
import Crafter.Event; import Crafter.Event;
import Crafter.Math; import Crafter.Math;
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; typedef VulkanShader<"raygen.spv", "main", VK_SHADER_STAGE_RAYGEN_BIT_KHR> Raygenspv;
typedef VulkanShader<"closesthit.spv", "main", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 0, {{}}> Closesthitspv; typedef VulkanShader<"closesthit.spv", "main", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR> Closesthitspv;
typedef VulkanShader<"miss.spv", "main", VK_SHADER_STAGE_MISS_BIT_KHR, 0, {{}}> Misspv; typedef VulkanShader<"miss.spv", "main", VK_SHADER_STAGE_MISS_BIT_KHR> Misspv;
typedef std::tuple<Raygenspv, Misspv, Closesthitspv> AllShaders; typedef std::tuple<Raygenspv, Misspv, Closesthitspv> AllShaders;
typedef std::tuple< typedef std::tuple<
ShaderGroup<0, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR>, ShaderGroup<0, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR>,
@ -16,6 +16,20 @@ typedef std::tuple<
ShaderGroup<VK_SHADER_UNUSED_KHR, 2, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR> ShaderGroup<VK_SHADER_UNUSED_KHR, 2, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR>
> ShaderGroups; > ShaderGroups;
typedef PipelineRTVulkan<AllShaders, ShaderGroups> Pipeline; typedef PipelineRTVulkan<AllShaders, ShaderGroups> Pipeline;
typedef DescriptorSetLayoutVulkan<2, {{
{
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR,
},
{
.binding = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR,
}
}}> descriptorSetLayout;
int main() { int main() {
VulkanDevice::CreateDevice(); VulkanDevice::CreateDevice();
@ -26,11 +40,15 @@ int main() {
Closesthitspv::CreateShader(); Closesthitspv::CreateShader();
Misspv::CreateShader(); Misspv::CreateShader();
ShaderBindingTableVulkan<AllShaders>::Init(); ShaderBindingTableVulkan<AllShaders>::Init();
std::array<VkDescriptorSetLayout, 1> layouts {{Raygenspv::layout}};
Pipeline::Init(cmd, layouts); descriptorSetLayout::Init();
std::array<VkDescriptorSetLayout, 1> layouts {{descriptorSetLayout::layout}};
DescriptorPool pool; DescriptorPool pool;
pool.sets.resize(1); pool.sets.resize(1);
pool.BuildPool(DescriptorPool::GetPoolSizes<Raygenspv>(), layouts); pool.BuildPool(DescriptorPool::GetPoolSizes<descriptorSetLayout>(), layouts);
Pipeline::Init(cmd, layouts);
Mesh triangleMesh; Mesh triangleMesh;
std::array<Vertex, 3> verts {{{-150, -150, 100}, {0, 150, 100}, {150, -150, 100}}}; std::array<Vertex, 3> verts {{{-150, -150, 100}, {0, 150, 100}, {150, -150, 100}}};

View file

@ -92,13 +92,6 @@ void WindowVulkan::CreateSwapchain()
// This mode waits for the vertical blank ("v-sync") // This mode waits for the vertical blank ("v-sync")
VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
// Determine the number of images
uint32_t desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1;
if ((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount))
{
desiredNumberOfSwapchainImages = surfCaps.maxImageCount;
}
// Find the transformation of the surface // Find the transformation of the surface
VkSurfaceTransformFlagsKHR preTransform; VkSurfaceTransformFlagsKHR preTransform;
if (surfCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) if (surfCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
@ -130,7 +123,7 @@ void WindowVulkan::CreateSwapchain()
VkSwapchainCreateInfoKHR swapchainCI = {}; VkSwapchainCreateInfoKHR swapchainCI = {};
swapchainCI.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapchainCI.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapchainCI.surface = vulkanSurface; swapchainCI.surface = vulkanSurface;
swapchainCI.minImageCount = desiredNumberOfSwapchainImages; swapchainCI.minImageCount = numFrames;
swapchainCI.imageFormat = colorFormat; swapchainCI.imageFormat = colorFormat;
swapchainCI.imageColorSpace = colorSpace; swapchainCI.imageColorSpace = colorSpace;
swapchainCI.imageExtent = { swapchainExtent.width, swapchainExtent.height }; swapchainCI.imageExtent = { swapchainExtent.width, swapchainExtent.height };
@ -145,22 +138,14 @@ void WindowVulkan::CreateSwapchain()
// Setting clipped to VK_TRUE allows the implementation to discard rendering outside of the surface area // Setting clipped to VK_TRUE allows the implementation to discard rendering outside of the surface area
swapchainCI.clipped = VK_TRUE; swapchainCI.clipped = VK_TRUE;
swapchainCI.compositeAlpha = compositeAlpha; swapchainCI.compositeAlpha = compositeAlpha;
// Enable transfer source on swap chain images if supported
if (surfCaps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
swapchainCI.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT; swapchainCI.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
}
// Enable transfer destination on swap chain images if supported
if (surfCaps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
swapchainCI.imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT; swapchainCI.imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
}
VulkanDevice::CheckVkResult(vkCreateSwapchainKHR(VulkanDevice::device, &swapchainCI, nullptr, &swapChain)); VulkanDevice::CheckVkResult(vkCreateSwapchainKHR(VulkanDevice::device, &swapchainCI, nullptr, &swapChain));
// If an existing swap chain is re-created, destroy the old swap chain and the ressources owned by the application (image views, images are owned by the swap chain) // If an existing swap chain is re-created, destroy the old swap chain and the ressources owned by the application (image views, images are owned by the swap chain)
if (oldSwapchain != VK_NULL_HANDLE) { if (oldSwapchain != VK_NULL_HANDLE) {
for (auto i = 0; i < images.size(); i++) { for (auto i = 0; i < numFrames; i++) {
vkDestroyImageView(VulkanDevice::device, imageViews[i], nullptr); vkDestroyImageView(VulkanDevice::device, imageViews[i], nullptr);
} }
vkDestroySwapchainKHR(VulkanDevice::device, oldSwapchain, nullptr); vkDestroySwapchainKHR(VulkanDevice::device, oldSwapchain, nullptr);
@ -169,12 +154,9 @@ void WindowVulkan::CreateSwapchain()
VulkanDevice::CheckVkResult(vkGetSwapchainImagesKHR(VulkanDevice::device, swapChain, &imageCount, nullptr)); VulkanDevice::CheckVkResult(vkGetSwapchainImagesKHR(VulkanDevice::device, swapChain, &imageCount, nullptr));
// Get the swap chain images // Get the swap chain images
images.resize(imageCount); VulkanDevice::CheckVkResult(vkGetSwapchainImagesKHR(VulkanDevice::device, swapChain, &imageCount, images));
VulkanDevice::CheckVkResult(vkGetSwapchainImagesKHR(VulkanDevice::device, swapChain, &imageCount, images.data()));
// Get the swap chain buffers containing the image and imageview for (auto i = 0; i < numFrames; i++)
imageViews.resize(imageCount);
for (auto i = 0; i < images.size(); i++)
{ {
VkImageViewCreateInfo colorAttachmentView = {}; VkImageViewCreateInfo colorAttachmentView = {};
colorAttachmentView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; colorAttachmentView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
@ -297,14 +279,12 @@ WindowVulkan::WindowVulkan(std::uint32_t width, std::uint32_t height) : Window(w
subpassDescription.pPreserveAttachments = nullptr; subpassDescription.pPreserveAttachments = nullptr;
subpassDescription.pResolveAttachments = nullptr; subpassDescription.pResolveAttachments = nullptr;
drawCmdBuffers.resize(images.size());
VkCommandBufferAllocateInfo cmdBufAllocateInfo {}; VkCommandBufferAllocateInfo cmdBufAllocateInfo {};
cmdBufAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; cmdBufAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
cmdBufAllocateInfo.commandPool = VulkanDevice::commandPool; cmdBufAllocateInfo.commandPool = VulkanDevice::commandPool;
cmdBufAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; cmdBufAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
cmdBufAllocateInfo.commandBufferCount = static_cast<uint32_t>(drawCmdBuffers.size()); cmdBufAllocateInfo.commandBufferCount = numFrames;
VulkanDevice::CheckVkResult(vkAllocateCommandBuffers(VulkanDevice::device, &cmdBufAllocateInfo, drawCmdBuffers.data())); VulkanDevice::CheckVkResult(vkAllocateCommandBuffers(VulkanDevice::device, &cmdBufAllocateInfo, drawCmdBuffers));
VkSemaphoreCreateInfo semaphoreCreateInfo {}; VkSemaphoreCreateInfo semaphoreCreateInfo {};
semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;

View file

@ -34,19 +34,16 @@ export namespace Crafter {
bool occured = true; bool occured = true;
}; };
class DescriptorPool { class DescriptorPool {
public: public:
Event<void> onDescriptorRefresh;
std::uint32_t setIndex = 0;
std::vector<VkDescriptorSet> sets; std::vector<VkDescriptorSet> sets;
VkDescriptorPool descriptorPool = VK_NULL_HANDLE; VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
template <typename Shader> template <typename Shader>
consteval static void GetOccuringDescriptors(std::array<DescriptorEntry, 20>& types) { 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) { for (DescriptorEntry& type : types) {
if (type.type == binding.type) { if (type.type == binding.descriptorType) {
type.occured = true; 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; bool found = false;
for(VkDescriptorPoolSize& type : types) { for(VkDescriptorPoolSize& type : types) {
if(type.type == binding.type && type.descriptorCount != 12345) { if(type.type == binding.descriptorType && type.descriptorCount != 12345) {
type.descriptorCount += 1; type.descriptorCount += 1;
found = true; found = true;
} }
@ -88,7 +85,7 @@ export namespace Crafter {
if(!found) { if(!found) {
for(std::uint32_t i = 0; i < GetUniqueDiscriptorCount<Shaders...>(); i++){ for(std::uint32_t i = 0; i < GetUniqueDiscriptorCount<Shaders...>(); i++){
if(types[i].descriptorCount == 12345) { if(types[i].descriptorCount == 12345) {
types[i].type = binding.type; types[i].type = binding.descriptorType;
types[i].descriptorCount = 1; types[i].descriptorCount = 1;
break; break;
} }
@ -125,10 +122,6 @@ export namespace Crafter {
}; };
VulkanDevice::CheckVkResult(vkAllocateDescriptorSets(VulkanDevice::device, &allocInfo, sets.data())); 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 < template <
StringLiteral path, StringLiteral path,
StringLiteral entrypoint, StringLiteral entrypoint,
VkShaderStageFlagBits stage, VkShaderStageFlagBits stage
std::uint32_t DescriptorCount,
const std::array<DescriptorBinding, DescriptorCount> Descriptors
> >
class VulkanShader { class VulkanShader {
public: public:
constexpr static VkShaderStageFlagBits _stage = stage; constexpr static VkShaderStageFlagBits _stage = stage;
constexpr static StringLiteral _entrypoint = entrypoint; constexpr static StringLiteral _entrypoint = entrypoint;
constexpr static std::span<const DescriptorBinding> descriptors = Descriptors;
inline static VkShaderModule shader; 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() { static void CreateShader() {
std::ifstream file(path.value, std::ios::binary); std::ifstream file(path.value, std::ios::binary);
@ -88,14 +74,6 @@ export namespace Crafter {
VkShaderModule shader_module; VkShaderModule shader_module;
VulkanDevice::CheckVkResult(vkCreateShaderModule(VulkanDevice::device, &module_info, nullptr, &shader)); 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; 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 { // struct __attribute__((packed)) Vertex {
// float x; // float x;
// float y; // float y;

View file

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

View file

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

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/Crafter.Graphics-DescriptorPoolVulkan", "interfaces/Crafter.Graphics-ShaderVulkan", "interfaces/Crafter.Graphics-PipelineRTVulkan", "interfaces/Crafter.Graphics-ShaderBindingTableVulkan"], "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-DescriptorPoolVulkan", "interfaces/Crafter.Graphics-ShaderVulkan", "interfaces/Crafter.Graphics-PipelineRTVulkan", "interfaces/Crafter.Graphics-ShaderBindingTableVulkan", "interfaces/Crafter.Graphics-ImageVulkan", "interfaces/Crafter.Graphics-SamplerVulkan", "interfaces/Crafter.Graphics-DescriptorSetLayoutVulkan"],
"type": "library" "type": "library"
}, },
{ {