update descriptor handling

This commit is contained in:
Matthew 2025-11-06 07:48:24 +11:00
parent 614ee40d85
commit b4d7f4fb16

407
vulkan.d
View File

@ -3,9 +3,9 @@ import vulkan_logging;
import vulkan_util;
import std.stdio;
import std.algorithm.comparison;
import core.stdc.string : strcmp, memcpy;
import core.stdc.stdio : Printf = printf;
import std.format : sformat;
import core.stdc.string : strcmp, memcpy;
import core.stdc.stdio : Printf = printf;
import std.format : sformat;
import std.math.rounding : Ceil = ceil;
version(VULKAN_DEBUG)
@ -17,17 +17,17 @@ else
const BUILD_DEBUG = false;
}
alias InitRenderer = Init;
alias Renderer = Vulkan;
alias Shader = VkShaderModule;
alias Pipeline = u32;
alias Attribute = VkVertexInputAttributeDescription;
alias SpecEntry = VkSpecializationMapEntry;
alias RenderPass = VkRenderPass;
alias DescSetLayout = VkDescriptorSetLayout;
alias PipelineLayout = VkPipelineLayout;
alias InitRenderer = Init;
alias Renderer = Vulkan;
alias Shader = VkShaderModule;
alias Pipeline = u32;
alias Attribute = VkVertexInputAttributeDescription;
alias SpecEntry = VkSpecializationMapEntry;
alias RenderPass = VkRenderPass;
alias DescSetLayout = VkDescriptorSetLayout;
alias PipelineLayout = VkPipelineLayout;
alias DescLayoutBinding = VkDescriptorSetLayoutBinding;
alias DescWrite = VkWriteDescriptorSet;
alias DescWrite = VkWriteDescriptorSet;
struct DescSet
{
@ -45,16 +45,13 @@ else
bool g_DEBUG_PRINTF = false;
}
const FRAME_OVERLAP = 2;
const MAX_SETS = 1000;
const FRAME_OVERLAP = 2;
const MAX_SETS = 1000;
const DESC_ARRAY_SIZE = 256;
version(linux)
{
const string[] VULKAN_LIBS = [
"libvulkan.so.1",
"libvulkan.so",
];
const string[] VULKAN_LIBS = [ "libvulkan.so.1", "libvulkan.so" ];
struct PlatformHandles
{
@ -65,9 +62,7 @@ version(linux)
version(Windows)
{
const string[] VULKAN_LIBS = [
"vulkan-1.dll",
];
const string[] VULKAN_LIBS = [ "vulkan-1.dll" ];
struct PlatformHandles
{
@ -118,18 +113,18 @@ const VkFormat[] VK_IMAGE_FORMATS = [
enum ShaderStage : VkShaderStageFlagBits
{
None = cast(VkShaderStageFlagBits)0,
Vertex = VK_SHADER_STAGE_VERTEX_BIT,
None = cast(VkShaderStageFlagBits)0,
Vertex = VK_SHADER_STAGE_VERTEX_BIT,
Fragment = VK_SHADER_STAGE_FRAGMENT_BIT,
Compute = VK_SHADER_STAGE_COMPUTE_BIT,
All = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT,
Compute = VK_SHADER_STAGE_COMPUTE_BIT,
All = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT,
}
alias SS = ShaderStage;
enum InputRate : int
{
Vertex = VK_VERTEX_INPUT_RATE_VERTEX,
Vertex = VK_VERTEX_INPUT_RATE_VERTEX,
Instance = VK_VERTEX_INPUT_RATE_INSTANCE,
}
@ -137,13 +132,12 @@ alias IR = InputRate;
enum ImageUsage : VkImageUsageFlagBits
{
None = cast(VkImageUsageFlagBits)0,
Draw = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
Depth = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
Texture = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
Convert = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
Storage = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
None = cast(VkImageUsageFlagBits)0,
Draw = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
Depth = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
Texture = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
Convert = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
Storage = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
Swapchain = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
}
@ -152,36 +146,36 @@ alias IU = ImageUsage;
enum FrontFace: VkFrontFace
{
CCW = VK_FRONT_FACE_COUNTER_CLOCKWISE,
CW = VK_FRONT_FACE_CLOCKWISE,
CW = VK_FRONT_FACE_CLOCKWISE,
}
alias FF = FrontFace;
enum Format : VkFormat
{
UINT = VK_FORMAT_R32_UINT,
R_F32 = VK_FORMAT_R32_SFLOAT,
RG_F32 = VK_FORMAT_R32G32_SFLOAT,
RGB_F32 = VK_FORMAT_R32G32B32_SFLOAT,
RGBA_F32 = VK_FORMAT_R32G32B32A32_SFLOAT,
RGBA_UINT = VK_FORMAT_B8G8R8A8_UINT,
R_U32 = VK_FORMAT_R32_UINT,
RG_U32 = VK_FORMAT_R32G32_UINT,
UINT = VK_FORMAT_R32_UINT,
R_F32 = VK_FORMAT_R32_SFLOAT,
RG_F32 = VK_FORMAT_R32G32_SFLOAT,
RGB_F32 = VK_FORMAT_R32G32B32_SFLOAT,
RGBA_F32 = VK_FORMAT_R32G32B32A32_SFLOAT,
RGBA_UINT = VK_FORMAT_B8G8R8A8_UINT,
R_U32 = VK_FORMAT_R32_UINT,
RG_U32 = VK_FORMAT_R32G32_UINT,
RGBA_UNORM = VK_FORMAT_R8G8B8A8_UNORM,
RGBA_SRGB = VK_FORMAT_R8G8B8A8_SRGB,
D_SF32 = VK_FORMAT_D32_SFLOAT,
RGBA_SRGB = VK_FORMAT_R8G8B8A8_SRGB,
D_SF32 = VK_FORMAT_D32_SFLOAT,
}
alias FMT = Format;
enum BufferType : VkBufferUsageFlagBits
{
None = cast(VkBufferUsageFlagBits)0,
Vertex = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
Index = VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
Uniform = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
Storage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
Staging = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
None = cast(VkBufferUsageFlagBits)0,
Vertex = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
Index = VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
Uniform = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
Storage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
Staging = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
BufferView = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
}
@ -189,8 +183,8 @@ alias BT = BufferType;
enum ImageLayout : VkImageLayout
{
Undefined = VK_IMAGE_LAYOUT_UNDEFINED,
General = VK_IMAGE_LAYOUT_GENERAL,
Undefined = VK_IMAGE_LAYOUT_UNDEFINED,
General = VK_IMAGE_LAYOUT_GENERAL,
ColorAttach = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
}
@ -208,7 +202,7 @@ struct Image
struct BufferView
{
Buffer base;
Buffer base;
VkBufferView view;
alias base this;
@ -216,7 +210,7 @@ struct BufferView
struct ImageView
{
Image base;
Image base;
VkImageView view;
alias base this;
@ -230,6 +224,19 @@ struct Buffer
bool dynamic;
}
struct Descriptor
{
DescType type;
u32 binding;
union
{
Buffer buf;
Image image;
ImageView view;
BufferView buf_view;
}
}
struct ShaderUniforms
{
f32 placeholder;
@ -245,36 +252,36 @@ alias PT = PipelineType;
enum BlendFactor : VkBlendFactor
{
Zero = VK_BLEND_FACTOR_ZERO,
One = VK_BLEND_FACTOR_ONE,
SrcColor = VK_BLEND_FACTOR_SRC_COLOR,
OneMinusSrcColor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
DstColor = VK_BLEND_FACTOR_DST_COLOR,
OneMinusDstColor = VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
SrcAlpha = VK_BLEND_FACTOR_SRC_ALPHA,
OneMinusSrcAlpha = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
DstAlpha = VK_BLEND_FACTOR_DST_ALPHA,
OneMinusDstAlpha = VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
ConstColor = VK_BLEND_FACTOR_CONSTANT_COLOR,
Zero = VK_BLEND_FACTOR_ZERO,
One = VK_BLEND_FACTOR_ONE,
SrcColor = VK_BLEND_FACTOR_SRC_COLOR,
OneMinusSrcColor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
DstColor = VK_BLEND_FACTOR_DST_COLOR,
OneMinusDstColor = VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
SrcAlpha = VK_BLEND_FACTOR_SRC_ALPHA,
OneMinusSrcAlpha = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
DstAlpha = VK_BLEND_FACTOR_DST_ALPHA,
OneMinusDstAlpha = VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
ConstColor = VK_BLEND_FACTOR_CONSTANT_COLOR,
OneMinusConstColor = VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
ConstAlpha = VK_BLEND_FACTOR_CONSTANT_ALPHA,
ConstAlpha = VK_BLEND_FACTOR_CONSTANT_ALPHA,
OneMinusConstAlpha = VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA,
SrcAlphaSaturate = VK_BLEND_FACTOR_SRC_ALPHA_SATURATE,
Src1Color = VK_BLEND_FACTOR_SRC1_COLOR,
OneMinusSrc1Color = VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR,
Src1Alpha = VK_BLEND_FACTOR_SRC1_ALPHA,
OneMinusSrc1Alpha = VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA,
SrcAlphaSaturate = VK_BLEND_FACTOR_SRC_ALPHA_SATURATE,
Src1Color = VK_BLEND_FACTOR_SRC1_COLOR,
OneMinusSrc1Color = VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR,
Src1Alpha = VK_BLEND_FACTOR_SRC1_ALPHA,
OneMinusSrc1Alpha = VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA,
}
alias BF = BlendFactor;
enum BlendOp : VkBlendOp
{
Add = VK_BLEND_OP_ADD,
Sub = VK_BLEND_OP_SUBTRACT,
Add = VK_BLEND_OP_ADD,
Sub = VK_BLEND_OP_SUBTRACT,
ReverseSub = VK_BLEND_OP_REVERSE_SUBTRACT,
Min = VK_BLEND_OP_MIN,
Max = VK_BLEND_OP_MAX,
Min = VK_BLEND_OP_MIN,
Max = VK_BLEND_OP_MAX,
}
alias BO = BlendOp;
@ -350,20 +357,10 @@ enum DescType : VkDescriptorType
alias DT = DescType;
enum PresentMode : VkPresentModeKHR
{
Vsync = VK_PRESENT_MODE_FIFO_KHR,
NoVsync = VK_PRESENT_MODE_IMMEDIATE_KHR,
VsyncUncapped = VK_PRESENT_MODE_MAILBOX_KHR,
VsyncRelaxed = VK_PRESENT_MODE_FIFO_RELAXED_KHR,
Max,
}
struct MappedBuffer(T)
{
Buffer base;
T[] data;
T[] data;
u64 offset;
alias base this;
@ -371,38 +368,36 @@ struct MappedBuffer(T)
struct Vulkan
{
Arena arena;
Arena[FRAME_OVERLAP] frame_arenas;
Arena arena;
Arena[FRAME_OVERLAP] frame_arenas;
u32 frame_index;
u32 semaphore_index;
u32 frame_index;
u32 semaphore_index;
SLList!(SI) cleanup_list;
SLList!(SI) cleanup_list;
PlatformHandles platform_handles;
u32 window_h, window_w;
PlatformHandles platform_handles;
u32 window_h, window_w;
VkDebugUtilsMessengerEXT dbg_msg;
VkInstance instance;
VkSurfaceKHR surface;
VkPhysicalDevice physical_device;
VkDevice device;
VmaAllocator vma;
VkSwapchainKHR swapchain;
VkDebugUtilsMessengerEXT dbg_msg;
VkInstance instance;
VkSurfaceKHR surface;
VkPhysicalDevice physical_device;
VkDevice device;
VmaAllocator vma;
VkSwapchainKHR swapchain;
VkSurfaceFormatKHR surface_format;
PresentMode present_mode;
VkExtent3D swapchain_extent;
PresentMode[] present_modes;
bool swapchain_dirty;
VkSurfaceFormatKHR surface_format;
VkPresentModeKHR present_mode;
VkExtent3D swapchain_extent;
VkRenderPass render_pass;
VkFramebuffer framebuffer;
ImageView[] present_images;
u32 image_index;
VkRenderPass render_pass;
VkFramebuffer framebuffer;
ImageView[] present_images;
u32 image_index;
ImageView draw_image;
ImageView depth_image;
ImageView draw_image;
ImageView depth_image;
VkCommandPool[FRAME_OVERLAP] cmd_pools;
VkCommandBuffer[FRAME_OVERLAP] cmds;
@ -411,9 +406,9 @@ struct Vulkan
VkCommandBuffer comp_cmd;
VkFence comp_fence;
VkSemaphore[] submit_sems;
VkSemaphore[FRAME_OVERLAP] acquire_sems;
VkFence[FRAME_OVERLAP] render_fences;
VkSemaphore[] submit_sems;
VkSemaphore[FRAME_OVERLAP] acquire_sems;
VkFence[FRAME_OVERLAP] render_fences;
VkCommandPool imm_pool;
VkCommandBuffer imm_cmd;
@ -470,9 +465,9 @@ struct PipelineHandles
struct QueueInfo
{
i32 gfx_index, tfer_index;
i32 gfx_index, tfer_index;
VkQueue gfx_queue, tfer_queue;
bool single_queue;
bool single_queue;
}
u8[] CONVERT_SHADER_BYTES = cast(u8[])import("convert.comp.spv");
@ -765,12 +760,7 @@ BeginFrame(Vulkan* vk)
VkCheckA("BeginFrame failure: vkResetFences error", result);
result = vkAcquireNextImageKHR(vk.device, vk.swapchain, 1000000000, vk.acquire_sems[vk.frame_index], null, &vk.image_index);
if(vk.swapchain_dirty && (result == VK_SUCCESS || result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR))
{
RecreateSwapchain(vk);
vk.swapchain_dirty = false;
}
else if(result == VK_ERROR_OUT_OF_DATE_KHR)
if(result == VK_ERROR_OUT_OF_DATE_KHR)
{
RecreateSwapchain(vk);
}
@ -2264,102 +2254,49 @@ InitGlobalDescSet(Vulkan* vk)
}
void
Write(Vulkan* vk, DescSet set, ImageView* view, u32 binding, DescType type)
Write(Vulkan* vk, DescSet set, Descriptor[] descs)
{
VkDescriptorImageInfo info = {
imageView: view.view,
imageLayout: view.layout,
};
Arena* arena = vk.frame_arenas.ptr + vk.frame_index;
VkWriteDescriptorSet write = {
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
dstSet: set.handle,
dstBinding: binding,
descriptorCount: 1,
descriptorType: type,
pImageInfo: &info,
};
VkWriteDescriptorSet[] writes = Alloc!(VkWriteDescriptorSet)(arena, descs.length);
vkUpdateDescriptorSets(vk.device, 1, &write, 0, null);
}
for(u64 i = 0; i < descs.length; i += 1)
{
VkWriteDescriptorSet* write = writes.ptr + i;
void
Write(Vulkan* vk, DescSet set, Buffer* buffer, u32 binding, DescType type)
{
VkDescriptorBufferInfo info = {
buffer: buffer.buffer,
range: buffer.size,
offset: 0,
};
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write.descriptorType = descs[i].type;
write.dstSet = set;
write.dstBinding = descs[i].binding;
write.descriptorCount = 1;
VkWriteDescriptorSet write = {
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
dstSet: set.handle,
dstBinding: binding,
descriptorCount: 1,
descriptorType: type,
pBufferInfo: &info,
};
vkUpdateDescriptorSets(vk.device, 1, &write, 0, null);
}
void
Write(Vulkan* vk, DescSet set, Buffer* buffer, u32 binding, u32 index, DescType type)
{
VkDescriptorBufferInfo info = {
buffer: buffer.buffer,
range: buffer.size,
offset: 0,
};
VkWriteDescriptorSet write = {
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
dstSet: set.handle,
dstBinding: binding,
dstArrayElement: index,
descriptorCount: 1,
descriptorType: type,
pBufferInfo: &info,
};
vkUpdateDescriptorSets(vk.device, 1, &write, 0, null);
}
void
WriteGUI(Vulkan* vk, DescSet set, ImageView* atlas, Buffer* buf)
{
VkDescriptorImageInfo image_info = {
imageView: atlas.view,
imageLayout: atlas.layout,
};
VkDescriptorBufferInfo buf_info = {
buffer: buf.buffer,
range: buf.size,
offset: 0,
};
VkWriteDescriptorSet[2] writes = [
switch(descs[i].type) with(DescType)
{
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
dstSet: set.handle,
dstBinding: 0,
descriptorCount: 1,
descriptorType: VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
pImageInfo: &image_info,
},
{
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
dstSet: set.handle,
dstBinding: 1,
descriptorCount: 1,
descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
pBufferInfo: &buf_info,
case Image, StorageImage, InputAttach:
{
VkDescriptorImageInfo* info = Alloc!(VkDescriptorImageInfo)(arena);
info.imageView = descs[i].view.view;
info.imageLayout = descs[i].view.layout;
write.pImageInfo = info;
} break;
case Uniform, Storage:
{
VkDescriptorBufferInfo* info = Alloc!(VkDescriptorBufferInfo)(arena);
info.buffer = descs[i].buf.buffer;
info.offset = cast(VkDeviceSize)0;
info.range = cast(VkDeviceSize)descs[i].buf.size;
write.pBufferInfo = info;
} break;
case UniformTexelBuf, StorageTexelBuf:
{
write.pTexelBufferView = &descs[i].buf_view.view;
} break;
}
];
}
vkUpdateDescriptorSets(vk.device, cast(u32)writes.length, writes.ptr, 0, null);
vkUpdateDescriptorSets(vk.device, writes.length, writes.ptr, 0, null);
}
void
@ -2643,8 +2580,18 @@ SelectSwapchainFormats(Vulkan* vk)
u32 mode_count;
vkGetPhysicalDeviceSurfacePresentModesKHR(vk.physical_device, vk.surface, &mode_count, null);
vk.present_modes = Alloc!(PresentMode)(arena, mode_count);
vkGetPhysicalDeviceSurfacePresentModesKHR(vk.physical_device, vk.surface, &mode_count, cast(VkPresentModeKHR*)vk.present_modes.ptr);
VkPresentModeKHR[] modes = Alloc!(VkPresentModeKHR)(arena, mode_count);
vkGetPhysicalDeviceSurfacePresentModesKHR(vk.physical_device, vk.surface, &mode_count, modes.ptr);
VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
foreach(mode; modes)
{
if(mode == VK_PRESENT_MODE_MAILBOX_KHR)
{
present_mode = VK_PRESENT_MODE_MAILBOX_KHR;
break;
}
}
VkSurfaceFormatKHR surface_format = formats[0];
foreach(format; formats)
@ -2657,39 +2604,7 @@ SelectSwapchainFormats(Vulkan* vk)
}
vk.surface_format = surface_format;
vk.present_mode = PresentMode.Vsync;
}
PresentMode[]
AvailablePresentModes(Vulkan* vk)
{
return vk.present_modes;
}
bool
SetPresentMode(Vulkan* vk, PresentMode mode)
{
bool result = false;
foreach(pm; vk.present_modes)
{
if(pm == mode)
{
result = true;
break;
}
}
if(result)
{
if(vk.present_mode != mode)
{
vk.swapchain_dirty = true;
}
vk.present_mode = mode;
}
return result;
vk.present_mode = present_mode;
}
bool