diff --git a/vulkan.d b/vulkan.d index d25d09b..705c7b4 100644 --- a/vulkan.d +++ b/vulkan.d @@ -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