From d3baa63701f4c56f0f2ec5df090e666844855db6 Mon Sep 17 00:00:00 2001 From: matthew Date: Fri, 15 Aug 2025 04:58:31 +1000 Subject: [PATCH] move vulkan renderer to git submodule to also use elsewhere --- .gitmodules | 3 + dub.json | 4 +- src/VulkanRenderer | 1 + src/gears/vulkan.d | 3305 ------------------------------------ src/gears/vulkan_funcs.d | 278 --- src/gears/vulkan_logging.d | 166 -- src/shared/util.d | 2 +- 7 files changed, 7 insertions(+), 3752 deletions(-) create mode 100644 .gitmodules create mode 160000 src/VulkanRenderer delete mode 100644 src/gears/vulkan.d delete mode 100644 src/gears/vulkan_funcs.d delete mode 100644 src/gears/vulkan_logging.d diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..d3f8adc --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/VulkanRenderer"] + path = src/VulkanRenderer + url = https://git.sleepy.day/sleepy-day/VulkanRenderer.git diff --git a/dub.json b/dub.json index 8ee7943..557156c 100644 --- a/dub.json +++ b/dub.json @@ -9,8 +9,8 @@ "targetPath": "build", "sourceFiles-linux": ["build/libvma.a", "build/libstb_image.a", "build/libm3d.a", "build/libcglm.a"], "sourceFiles-windows": [], - "importPaths": ["src/gears", "src/shared", "external/xxhash", "external/inteli"], - "sourcePaths": ["src/gears", "src/shared", "external/xxhash", "external/inteli"], + "importPaths": ["src/gears", "src/shared", "external/xxhash", "external/inteli", "src/VulkanRenderer"], + "sourcePaths": ["src/gears", "src/shared", "external/xxhash", "external/inteli", "src/VulkanRenderer"], "libs-linux": ["xcb", "X11", "X11-xcb", "vulkan", "stdc++", "xcb-xfixes", "freetype"], "libs-windows": [], "preGenerateCommands-linux": ["./build.sh"], diff --git a/src/VulkanRenderer b/src/VulkanRenderer new file mode 160000 index 0000000..b6a93e9 --- /dev/null +++ b/src/VulkanRenderer @@ -0,0 +1 @@ +Subproject commit b6a93e91777f73445e50796324bd0737b0f3921f diff --git a/src/gears/vulkan.d b/src/gears/vulkan.d deleted file mode 100644 index ff9cbdf..0000000 --- a/src/gears/vulkan.d +++ /dev/null @@ -1,3305 +0,0 @@ -import vulkan_funcs; -import vulkan_logging; -import aliases; -import std.stdio; -import std.algorithm.comparison; -import core.stdc.string : strcmp, memcpy; -import core.stdc.stdio : Printf = printf; -import std.format : sformat; -import util; -import alloc; -import platform; -import assets; -import game; -import std.math.rounding : Ceil = ceil; -import math; - -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; - -struct DescSet -{ - VkDescriptorSet handle; - u32 dynamic_count; -} - -bool g_VLAYER_SUPPORT = false; -bool g_DEBUG_PRINTF = false; - -const FRAME_OVERLAP = 2; -const MAX_SETS = 1000; -const DESC_ARRAY_SIZE = 256; - -version(linux) -{ - const string[] VULKAN_LIBS = [ - "libvulkan.so.1", - "libvulkan.so", - ]; -} - -version(Windows) -{ - const string[] VULKAN_LIBS = [ - "vulkan-1.dll", - ]; -} - -const char*[] VK_INSTANCE_LAYERS = []; -const char*[] VK_INSTANCE_LAYERS_DEBUG = [ "VK_LAYER_KHRONOS_validation" ]; - -version(linux) -{ - const char*[] VK_INSTANCE_EXT = [ cast(char*)VK_KHR_SURFACE_EXTENSION_NAME, cast(char*)VK_KHR_XCB_SURFACE_EXTENSION_NAME ]; - const char*[] VK_INSTANCE_EXT_DEBUG = VK_INSTANCE_EXT ~ [ cast(char*)VK_EXT_DEBUG_UTILS_EXTENSION_NAME ]; -} - -version(Windows) -{ - const char*[] VK_INSTANCE_EXT = [ cast(char*)VK_KHR_SURFACE_EXTENSION_NAME, cast(char*)VK_KHR_WIN32_SURFACE_EXTENSION_NAME ]; - const char*[] VK_INSTANCE_EXT_DEBUG = VK_INSTANCE_EXT ~ [ cast(char*)VK_EXT_DEBUG_UTILS_EXTENSION_NAME ]; -} - -const char*[] VK_BASE_DEVICE_EXTENSIONS = [ - cast(char*)VK_KHR_SWAPCHAIN_EXTENSION_NAME, - cast(char*)VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME, - cast(char*)VK_KHR_8BIT_STORAGE_EXTENSION_NAME, - cast(char*)VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME, -]; - -const char*[] VK_AMD_DEVICE_EXTENSIONS = [ - cast(char*)VK_AMD_SHADER_INFO_EXTENSION_NAME, -]; - -version(AMD_GPU) -{ - debug - { - const char*[] VK_DEVICE_EXTENSIONS = VK_AMD_DEVICE_EXTENSIONS ~ VK_BASE_DEVICE_EXTENSIONS; - } -} -else -{ - const char*[] VK_DEVICE_EXTENSIONS = VK_BASE_DEVICE_EXTENSIONS; -} - -const VkFormat[] VK_IMAGE_FORMATS = [ - VK_FORMAT_R16G16B16A16_UNORM, - VK_FORMAT_R8G8B8A8_UNORM, -]; - -enum InputRate : int -{ - Vertex = VK_VERTEX_INPUT_RATE_VERTEX, - Instance = VK_VERTEX_INPUT_RATE_INSTANCE, -} - -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, - Swapchain = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, -} - -alias IU = ImageUsage; - -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, - RGBA_UNORM = VK_FORMAT_R8G8B8A8_UNORM, - 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, - BufferView = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, -} - -alias BT = BufferType; - -enum ImageLayout : VkImageLayout -{ - Undefined = VK_IMAGE_LAYOUT_UNDEFINED, - General = VK_IMAGE_LAYOUT_GENERAL, - ColorAttach = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, -} - -struct GlobalUniforms -{ - Mat4 view_matrix = Mat4Identity(); - Mat4 projection_matrix = Mat4Identity(); - Mat4 projection_view = Mat4Identity(); - Vec4 light_color; - Vec4 ambient_color; - Vec3 light_direction; - f32 padding; - Vec2 res; -} - -struct Image -{ - VkImage image; - VmaAllocation alloc; - Format format; - VkImageLayout layout; - u32 w; - u32 h; - bool depth_image; - ImageUsage usage; -} - -struct BufferView -{ - Buffer base; - VkBufferView view; - - alias base this; -} - -struct ImageView -{ - Image base; - VkImageView view; - - alias base this; -} - -struct Buffer -{ - VkBuffer buffer; - VmaAllocation alloc; - u64 size; - bool dynamic; -} - -struct ShaderUniforms -{ - f32 placeholder; -} - -enum PipelineType : int -{ - Graphics, - Compute, -} - -alias PT = PipelineType; - -struct Specialization -{ - u64 size; - SpecEntry[] entries; - void* data; -} - -struct GfxPipelineInfo -{ - string vertex_shader; - string frag_shader; - InputRate input_rate; - u32 input_rate_stride; - Attribute[] vertex_attributes; - Specialization vert_spec; - Specialization frag_spec; - bool self_dependency; - PipelineLayout layout; -} - -struct CompPipelineInfo -{ - string shader; - Specialization spec; - PipelineLayout layout; -} - -enum StepInitialized : u32 -{ - Renderer = 1, - Instance, - Debug, - Surface, - Device, - Vma, - Buffers, - FrameStructures, - Swapchain, - DrawImages, - DescriptorPools, - Pipelines, -} - -alias SI = StepInitialized; - -enum DescType : u32 -{ - - - Max, -} - -alias DT = DescType; - -struct MappedBuffer(T) -{ - Buffer base; - T[] data; - u64 offset; - - alias base this; -} - -struct DescBindings -{ - u32[] free; - u64 count; - HashTable!(string, u32) lookup_table; -} - -struct Vulkan -{ - Arena arena; - Arena[FRAME_OVERLAP] frame_arenas; - - u32 frame_index; - u32 semaphore_index; - - SLList!(SI) cleanup_list; - - PlatformWindow* window; - - VkDebugUtilsMessengerEXT dbg_msg; - VkInstance instance; - VkSurfaceKHR surface; - VkPhysicalDevice physical_device; - VkDevice device; - VmaAllocator vma; - VkSwapchainKHR swapchain; - - VkSurfaceFormatKHR surface_format; - VkPresentModeKHR present_mode; - VkExtent3D swapchain_extent; - - VkRenderPass render_pass; - VkFramebuffer framebuffer; - ImageView[] present_images; - u32 image_index; - - ImageView draw_image; - ImageView depth_image; - - VkCommandPool[FRAME_OVERLAP] cmd_pools; - VkCommandBuffer[FRAME_OVERLAP] cmds; - - VkCommandPool comp_cmd_pool; - VkCommandBuffer comp_cmd; - VkFence comp_fence; - - VkSemaphore[] submit_sems; - VkSemaphore[FRAME_OVERLAP] acquire_sems; - VkFence[FRAME_OVERLAP] render_fences; - - VkCommandPool imm_pool; - VkCommandBuffer imm_cmd; - VkFence imm_fence; - - VkDescriptorPool active_pool; - SLList!(VkDescriptorPool) full_pools; - - VkSampler nearest_sampler; - VkSampler oit_sampler; - - PipelineHandles[] pipeline_handles; - u32 pipeline_count; - VkPipeline[FRAME_OVERLAP] last_pipeline; - DescSetLayout global_set_layout; - DescSet global_set; - - MappedBuffer!(u8) transfer_buf; - MappedBuffer!(UIVertex) ui_vert_buf; - MappedBuffer!(u32) ui_index_buf; - MappedBuffer!(GlobalUniforms) global_buf; - MappedBuffer!(ShaderUniforms) shader_buf; - - QueueInfo queues; - - Pipeline r_to_rgba_pipeline; - Pipeline rg_to_rgba_pipeline; - Pipeline rgb_to_rgba_pipeline; - DescSet conv_desc_set; - VkDescriptorSetLayout conv_desc_layout; - VkPipelineLayout conv_pipeline_layout; - - VkPipeline last_comp_pipeline; - bool compute_pass_started; - - BufferView a_buffer_view; - ImageView aux_image; - - alias queues this; -} - -struct ConvPushConst -{ - u32 x; - u32 y; -} - -struct PipelineHandles -{ - VkPipeline handle; - VkPipelineBindPoint type; - VkPipelineLayout layout; - Pipeline index; -} - -struct QueueInfo -{ - i32 gfx_index, tfer_index; - VkQueue gfx_queue, tfer_queue; - bool single_queue; -} - -Vulkan -Init(PlatformWindow* window, u64 permanent_mem, u64 frame_mem) -{ - bool success = true; - - Vulkan vk = { - arena: CreateArena(permanent_mem), - frame_arenas: [ - CreateArena(frame_mem), - CreateArena(frame_mem), - ], - window: window, - }; - - Push(&vk, SI.Renderer); - - success = LoadGlobalFunctions(); - - if (success) success = InitInstance(&vk); - - if (success) - { - LoadInstanceFunctions(&vk); - EnableVLayers(&vk); - } - - if (success) success = InitSurface(&vk); - if (success) success = InitDevice(&vk); - if (success) success = InitVMA(&vk); - if (success) success = CreateSwapchain(&vk); - if (success) success = CreateDrawImages(&vk); - if (success) success = InitFrameStructures(&vk); - if (success) InitDescriptors(&vk); - if (success) success = InitGlobalDescSet(&vk); - if (success) InitPipelines(&vk); - if (success) InitBuffers(&vk); - if (success) InitConversionPipeline(&vk); - if (success) InitFramebufferAndRenderPass(&vk); - - assert(success, "Error initializing vulkan"); - - return vk; -} - -void -InitPipelines(Vulkan* vk) -{ - vk.pipeline_handles = AllocArray!(PipelineHandles)(&vk.arena, 128); - vk.pipeline_count += 1; -} - -DescSetLayout -CreateDescSetLayout(Vulkan* vk, DescLayoutBinding[] bindings) -{ - VkDescriptorSetLayoutCreateInfo layout_info = { - sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - bindingCount: cast(u32)bindings.length, - pBindings: bindings.ptr, - }; - - DescSetLayout layout; - VkResult result = vkCreateDescriptorSetLayout(vk.device, &layout_info, null, &layout); - VkCheckA("vkCreateDescriptorSetLayout failure", result); - - return layout; -} - -DescSet -AllocDescSet(Vulkan* vk, DescSetLayout layout, u32 dynamic_count = 0) -{ - VkDescriptorSetAllocateInfo alloc_info = { - sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - descriptorSetCount: 1, - pSetLayouts: &layout, - descriptorPool: vk.active_pool, - }; - - DescSet set = { - dynamic_count: dynamic_count, - }; - VkResult result = vkAllocateDescriptorSets(vk.device, &alloc_info, &set.handle); - if (result == VK_ERROR_OUT_OF_POOL_MEMORY || result == VK_ERROR_FRAGMENTED_POOL) - { - PushDescriptorPool(vk); - - alloc_info.descriptorPool = vk.active_pool; - - result = vkAllocateDescriptorSets(vk.device, &alloc_info, &set.handle); - VkCheckA("vkAllocateDescriptorSets failure", result); // TODO: look more into how to handle this - } - - return set; -} - -PipelineLayout -CreatePipelineLayout(T)(Vulkan* vk, T layouts, u32 push_const_size, bool compute = false) if (is(T: DescSetLayout) || is(T: DescSetLayout[])) -{ - VkShaderStageFlagBits stage = (compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); - - DescSetLayout[] desc_layouts; - - static if (is(T: DescSetLayout)) - { - desc_layouts = AllocArray!(DescSetLayout)(&vk.frame_arenas[vk.frame_index], 2); - desc_layouts[0] = vk.global_set_layout; - desc_layouts[1] = layouts; - } - else static if (is(T: DescSetLayout[])) - { - desc_layouts = AllocArray!(DescSetLayout)(&vk.frame_arenas[vk.frame_index], layouts.length + 1); - desc_layouts[0] = vk.global_set_layout; - - foreach(i; 1 .. layouts.length) - { - desc_layouts[i] = layouts[i-1]; - } - } - - VkPushConstantRange const_range = { - offset: 0, - size: cast(VkDeviceSize)push_const_size, - stageFlags: stage, - }; - - VkPipelineLayoutCreateInfo layout_info = { - sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - setLayoutCount: cast(u32)desc_layouts.length, - pSetLayouts: desc_layouts.ptr, - pushConstantRangeCount: (push_const_size > 0 ? 1 : 0), - pPushConstantRanges: (push_const_size > 0 ? &const_range : null), - }; - - PipelineLayout layout; - VkResult result = vkCreatePipelineLayout(vk.device, &layout_info, null, &layout); - VkCheckA("CreatePipelineLayout failure", result); - - return layout; -} - -void -InitConversionPipeline(Vulkan* vk) -{ - Push(vk, SI.Pipelines); - - VkDescriptorSetLayoutBinding[2] layout_bindings = [ - { binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_COMPUTE_BIT }, - { binding: 1, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_COMPUTE_BIT }, - ]; - - vk.conv_desc_layout = CreateDescSetLayout(vk, layout_bindings); - vk.conv_desc_set = AllocDescSet(vk, vk.conv_desc_layout); - vk.conv_pipeline_layout = CreatePipelineLayout(vk, vk.conv_desc_layout, ConvPushConst.sizeof, true); - - u32 channels = 1; - SpecEntry[1] entries = [ - { - constantID: 0, - size: u32.sizeof, - offset: 0, - } - ]; - CompPipelineInfo conv_info = { - shader: "shaders/convert.comp.spv", - layout: vk.conv_pipeline_layout, - spec: { - data: &channels, - size: u32.sizeof, - entries: entries, - }, - }; - - vk.r_to_rgba_pipeline = CreateComputePipeline(vk, &conv_info); - - channels = 2; - vk.rg_to_rgba_pipeline = CreateComputePipeline(vk, &conv_info); - - channels = 3; - vk.rgb_to_rgba_pipeline = CreateComputePipeline(vk, &conv_info); -} - -void -CreateBuffer(Vulkan* vk, Buffer* buf, BufferType type, u64 size, bool host_visible, bool dynamic = false) -{ - assert(type != BT.None, "CreateBuffer failure: type is None"); - - u64 buffer_size = (dynamic ? size * FRAME_OVERLAP : size); - - VkBufferCreateInfo buffer_info = { - sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - usage: type, - size: buffer_size, - }; - - VmaAllocationCreateInfo alloc_info = { - usage: VMA_MEMORY_USAGE_UNKNOWN, - flags: VMA_ALLOCATION_CREATE_MAPPED_BIT, - }; - - if (host_visible) - { - alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - alloc_info.preferredFlags = VK_MEMORY_PROPERTY_HOST_CACHED_BIT; - } - else - { - buffer_info.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; - alloc_info.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - } - - u32[2] indices = [vk.queues.gfx_index, vk.queues.tfer_index]; - if (vk.queues.gfx_index != vk.queues.tfer_index) - { - buffer_info.sharingMode = VK_SHARING_MODE_CONCURRENT; - buffer_info.queueFamilyIndexCount = 2; - buffer_info.pQueueFamilyIndices = indices.ptr; - } - - VmaAllocationInfo vma_info; - VkResult result = vmaCreateBuffer(vk.vma, &buffer_info, &alloc_info, &buf.buffer, &buf.alloc, &vma_info); - // TODO: handle errors here then reallocate buffer - assert(VkCheck("CreateBuffer failure: vmaCreateBuffer error", result), "CreateBuffer failure"); - - buf.size = buffer_size; - buf.dynamic = dynamic; -} - -void -UpdateIndexBuffer(Vulkan* vk, Model* model) -{ - assert(Transfer(vk, &model.index_buffer, model.indices), "UpdateIndexBuffer failure"); -} - -void -InitBuffers(Vulkan* vk) -{ - Push(vk, SI.Buffers); - - vk.global_buf = CreateMappedBuffer!(GlobalUniforms)(vk, BT.Uniform, 1); - vk.shader_buf = CreateMappedBuffer!(ShaderUniforms)(vk, BT.Uniform, 1); - - u64 transfer_size = MB(64); - vk.transfer_buf = CreateMappedBuffer!(u8)(vk, BT.Staging, transfer_size); - - u64 ui_size = MB(30); - vk.ui_vert_buf = CreateMappedBuffer!(UIVertex)(vk, BT.Vertex, ui_size / UIVertex.sizeof); - vk.ui_index_buf = CreateMappedBuffer!(u32)(vk, BT.Index, ui_size / u32.sizeof); -} - -void -BindUIBuffers(Vulkan* vk) -{ - VkDeviceSize offset = 0; - - vkCmdBindIndexBuffer(vk.cmds[vk.frame_index], vk.ui_index_buf.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdBindVertexBuffers(vk.cmds[vk.frame_index], 0, 1, &vk.ui_vert_buf.buffer, &offset); -} - -void -BindBuffers(Vulkan* vk, Buffer* index_buffer, Buffer* vertex_buffer) -{ - VkDeviceSize offset = 0; - - vkCmdBindIndexBuffer(vk.cmds[vk.frame_index], index_buffer.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdBindVertexBuffers(vk.cmds[vk.frame_index], 0, 1, &vertex_buffer.buffer, &offset); -} - -MappedBuffer!(T) -CreateMappedBuffer(T)(Vulkan* vk, BufferType type, u64 count) -{ - MappedBuffer!(T) buf; - CreateBuffer(vk, &buf.base, type, T.sizeof * count, true); - buf.data = MapBuffer!(T)(vk, &buf.base, count); - return buf; -} - -T[] -MapBuffer(T)(Vulkan* vk, Buffer* buffer, u64 count) -{ - void* ptr; - vmaMapMemory(vk.vma, buffer.alloc, &ptr); - return (cast(T*)ptr)[0 .. count]; -} - -VkImage -CurrentImage(Vulkan* vk) -{ - return vk.present_images[vk.image_index].image; -} - -UIVertex[] -GetUIVertexBuffer(Vulkan* vk) -{ - return vk.ui_vert_buf.data; -} - -u32[] -GetUIIndexBuffer(Vulkan* vk) -{ - return vk.ui_index_buf.data; -} - -void -BeginFrame(Vulkan* vk) -{ - // TODO: move vkWaitForFences so it no longer holds up the frame, will need to change how fences are handled in regards to images though - VkResult result = vkWaitForFences(vk.device, 1, vk.render_fences.ptr + vk.frame_index, VK_TRUE, 1000000000); - VkCheckA("BeginFrame failure: vkWaitForFences error", result); - - result = vkResetFences(vk.device, 1, vk.render_fences.ptr + vk.frame_index); - VkCheckA("BeginFrame failure: vkResetFences error", result); - - result = vkAcquireNextImageKHR(vk.device, vk.swapchain, 1000000000, vk.acquire_sems[vk.frame_index], null, &vk.image_index); - if (result == VK_ERROR_OUT_OF_DATE_KHR) - { - RecreateSwapchain(vk); - } - else if (result != VK_SUBOPTIMAL_KHR) - { - VkCheckA("BeginFrame failure: vkAcquireNextImageKHR error", result); - } - - result = vkResetCommandBuffer(vk.cmds[vk.frame_index], 0); - VkCheckA("BeginFrame failure: vkResetCommandBuffer failure", result); - - VkCommandBufferBeginInfo cmd_info = { - sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - flags: VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, - }; - - result = vkBeginCommandBuffer(vk.cmds[vk.frame_index], &cmd_info); - VkCheckA("BeginFrame failure: vkBeginCommandBuffer error", result); -} - -void -BeginRendering(Vulkan* vk) -{ - Transition(vk.cmds[vk.frame_index], &vk.draw_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - Transition(vk.cmds[vk.frame_index], &vk.depth_image, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL); - - VkImage image = CurrentImage(vk); - Transition(vk.cmds[vk.frame_index], image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - VkClearValue[2] clear_color = [ - { - color: { - float32: [0.0, 0.0, 0.0, 1.0], - }, - }, - { - color: { - float32: [0.0, 0.0, 0.0, 0.0], - }, - }, - ]; - - VkRenderPassBeginInfo pass_info = { - sType: VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - renderPass: vk.render_pass, - framebuffer: vk.framebuffer, - renderArea: { - offset: { - x: 0, - y: 0, - }, - extent: { - width: vk.swapchain_extent.width, - height: vk.swapchain_extent.height, - }, - }, - clearValueCount: cast(u32)clear_color.length, - pClearValues: clear_color.ptr, - }; - - vkCmdBeginRenderPass(vk.cmds[vk.frame_index], &pass_info, VK_SUBPASS_CONTENTS_INLINE); -} - -pragma(inline): void -ResizeDrawImageIfNeeded(Vulkan* vk, ImageView* view) -{ - UVec2 ext = GetExtent(vk); - - if (view.w != ext.x || view.h != ext.y) - { - Destroy(vk, view); - CreateImageView(vk, view, ext.x, ext.y, view.format, view.usage, view.depth_image); - } -} - -pragma(inline): UVec2 -GetExtent(Vulkan* vk) -{ - return UVec2(vk.swapchain_extent.width, vk.swapchain_extent.height); -} - -pragma(inline): f32 -GetAspect(Vulkan* vk) -{ - return cast(f32)(vk.swapchain_extent.width) / cast(f32)(vk.swapchain_extent.height); -} - -void -PrepAuxImage(Vulkan* vk, ImageView* view) -{ - Transition(vk.cmds[vk.frame_index], view, VK_IMAGE_LAYOUT_GENERAL); -} - -void -PrepComputeDrawImage(Vulkan* vk) -{ - Transition(vk.cmds[vk.frame_index], &vk.draw_image, VK_IMAGE_LAYOUT_GENERAL); -} - -void -FinishRendering(Vulkan* vk) -{ - vkCmdEndRenderPass(vk.cmds[vk.frame_index]); -} - -void -SubmitAndPresent(Vulkan* vk) -{ - scope(exit) - { - vk.last_pipeline[vk.frame_index] = null; - vk.frame_index = (vk.frame_index + 1) % FRAME_OVERLAP; - } - - VkImage image = CurrentImage(vk); - VkSemaphore acquire_sem = vk.acquire_sems[vk.frame_index]; - VkSemaphore submit_sem = vk.submit_sems[vk.image_index]; - - Transition(vk.cmds[vk.frame_index], &vk.draw_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - - VkExtent2D extent = { - width: vk.swapchain_extent.width, - height: vk.swapchain_extent.height, - }; - - // TODO: Find out how to copy from same dimension images (pretty sure its not blitting) - Copy(vk.cmds[vk.frame_index], &vk.draw_image.base, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, extent, extent); - - Transition(vk.cmds[vk.frame_index], image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); - - VkResult result = vkEndCommandBuffer(vk.cmds[vk.frame_index]); - VkCheckA("FinishFrame failure: vkEndCommandBuffer error", result); - - VkCommandBufferSubmitInfo cmd_info = { - sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO, - commandBuffer: vk.cmds[vk.frame_index], - }; - - VkSemaphoreSubmitInfo wait_info = { - sType: VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, - semaphore: acquire_sem, - stageMask: VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, - value: 1, - }; - - VkSemaphoreSubmitInfo signal_info = { - sType: VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, - semaphore: submit_sem, - stageMask: VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT, - value: 1, - }; - - VkSubmitInfo2 submit_info = { - sType: VK_STRUCTURE_TYPE_SUBMIT_INFO_2, - waitSemaphoreInfoCount: 1, - pWaitSemaphoreInfos: &wait_info, - signalSemaphoreInfoCount: 1, - pSignalSemaphoreInfos: &signal_info, - commandBufferInfoCount: 1, - pCommandBufferInfos: &cmd_info, - }; - - result = vkQueueSubmit2(vk.queues.gfx_queue, 1, &submit_info, vk.render_fences[vk.frame_index]); - VkCheckA("FinishFrame failure: vkQueueSubmit2 error", result); - - VkPresentInfoKHR present_info = { - sType: VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, - swapchainCount: 1, - pSwapchains: &vk.swapchain, - waitSemaphoreCount: 1, - pWaitSemaphores: &submit_sem, - pImageIndices: &vk.image_index, - }; - - result = vkQueuePresentKHR(vk.queues.gfx_queue, &present_info); - if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) - { - RecreateSwapchain(vk); - } - else - { - VkCheckA("FinishFrame failure: vkQueuePresentKHR failure", result); - } -} - -void -Draw(Vulkan* vk, u32 index_count, u32 instance_count) -{ - vkCmdDraw(vk.cmds[vk.frame_index], index_count, instance_count, 0, 0); -} - -void -DrawIndexed(Vulkan* vk, u32 index_count, u32 instance_count, u32 index_offset) -{ - vkCmdDrawIndexed(vk.cmds[vk.frame_index], index_count, instance_count, index_offset, 0, 0); -} - -bool -ImmSubmitStart(Vulkan* vk) -{ - VkResult result = vkWaitForFences(vk.device, 1, &vk.imm_fence, true, 999999999); - bool success = VkCheck("ImmSubmit failure: vkWaitForFences error", result); - - if (success) - { - result = vkResetFences(vk.device, 1, &vk.imm_fence); - success = VkCheck("ImmSubmit failure: vkResetFences error", result); - } - - if (success) - { - result = vkResetCommandBuffer(vk.imm_cmd, 0); - success = VkCheck("ImmSubmit failure: vkResetCommandBuffer error", result); - } - - if (success) - { - VkCommandBufferBeginInfo cmd_info = { - sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - flags: VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, - }; - - result = vkBeginCommandBuffer(vk.imm_cmd, &cmd_info); - success = VkCheck("ImmSubmit failure: vkBeginCommandBuffer error", result); - } - - return success; -} - -bool -ImmSubmitFinish(Vulkan* vk) -{ - VkCommandBufferSubmitInfo cmd_info = { - sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO, - commandBuffer: vk.imm_cmd, - }; - - VkSubmitInfo2 submit_info = { - sType: VK_STRUCTURE_TYPE_SUBMIT_INFO_2, - commandBufferInfoCount: 1, - pCommandBufferInfos: &cmd_info, - }; - - VkResult result = vkQueueSubmit2(vk.tfer_queue, 1, &submit_info, vk.imm_fence); - return VkCheck("ImmSubmit failure: vkQueueSubmit2 error", result); -} - -bool -ImmSubmit(Vulkan* vk, Image* image, VkBufferImageCopy copy, void function(Vulkan*, Image*, VkBufferImageCopy) fn) -{ - bool success = ImmSubmitStart(vk); - - if (success) - { - fn(vk, image, copy); - - VkResult result = vkEndCommandBuffer(vk.imm_cmd); - success = VkCheck("ImmSubmit failure: vkEndCommandBuffer error", result); - } - - if (success) - { - success = ImmSubmitFinish(vk); - } - - return success; -} - -bool -ImmSubmit(Vulkan* vk, Buffer* buf, VkBufferCopy copy, void function(Vulkan*, Buffer*, VkBufferCopy) fn) -{ - bool success = ImmSubmitStart(vk); - - if (success) - { - fn(vk, buf, copy); - - VkResult result = vkEndCommandBuffer(vk.imm_cmd); - success = VkCheck("ImmSubmit failure: vkEndCommandBuffer error", result); - } - - if (success) - { - success = ImmSubmitFinish(vk); - } - - return success; -} - - - -bool -TransferAssets(Vulkan* vk) -{ - return true; -} - -void -WaitForTransfers(Vulkan* vk) -{ - vkWaitForFences(vk.device, 1, &vk.imm_fence, VK_TRUE, u64.max); -} - -pragma(inline): void -CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, u32 ch, u8[] data) -{ - CreateImageView(vk, view, w, h, FMT.RGBA_UNORM, IU.Texture); - - if (ch == 4) - { - assert(Transfer(vk, view, data, w, h), "CreateImageView failure: Image Transfer error"); - } - else - { - Buffer buf; - CreateBuffer(vk, &buf, BT.Storage, w * h * ch, false); - assert(Transfer(vk, &buf, data), "CreateImageView failure: Buffer Transfer error"); - - ImageView conv_view; - CreateImageView(vk, &conv_view, w, h, FMT.RGBA_F32, IU.Convert); - - WriteConvDescriptor(vk, &buf); - WriteConvDescriptor(vk, &conv_view); - - BeginComputePass(vk); - - Pipeline pipeline = ch == 1 ? vk.r_to_rgba_pipeline : - ch == 2 ? vk.rg_to_rgba_pipeline : - vk.rgb_to_rgba_pipeline; - - Bind(vk, pipeline, vk.conv_desc_set, true); - - ConvPushConst pc = { - x: w, - y: h, - }; - - vkCmdPushConstants( - vk.comp_cmd, - vk.conv_pipeline_layout, - VK_SHADER_STAGE_COMPUTE_BIT, - 0, - ConvPushConst.sizeof, - &pc - ); - - Transition(vk.comp_cmd, &conv_view, VK_IMAGE_LAYOUT_GENERAL); - - Dispatch(vk, vk.comp_cmd); - - Transition(vk.comp_cmd, view, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - VkExtent2D extent = { width: w, height: h }; - Copy(vk.comp_cmd, &conv_view.base, &view.base, extent, extent); - - Transition(vk.comp_cmd, view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - FinishComputePass(vk); - - vkWaitForFences(vk.device, 1, &vk.comp_fence, VK_TRUE, u64.max); - - vkQueueWaitIdle(vk.tfer_queue); - - Destroy(vk, &buf); - Destroy(vk, &conv_view); - } -} - -pragma(inline): void -BeginComputePass(Vulkan* vk) -{ - VkResult result = vkWaitForFences(vk.device, 1, &vk.comp_fence, VK_TRUE, 1000000000); - VkCheckA("BeginComputePass failure: vkWaitForFences error", result); - - result = vkResetFences(vk.device, 1, &vk.comp_fence); - VkCheckA("BeginComputepass failure: vkResetFences error", result); - - - result = vkResetCommandBuffer(vk.comp_cmd, 0); - VkCheckA("BeginComputePass failure: vkResetCommandBuffer error", result); - - VkCommandBufferBeginInfo cmd_info = { - sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - flags: VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, - }; - - result = vkBeginCommandBuffer(vk.comp_cmd, &cmd_info); - VkCheckA("BeginComputePass failure: vkBeginCommandBuffer error", result); -} - -pragma(inline): void -FinishComputePass(Vulkan* vk) -{ - VkResult result = vkEndCommandBuffer(vk.comp_cmd); - VkCheckA("FinishComputePass failure: vkEndCommandBuffer error", result); - - VkCommandBufferSubmitInfo cmd_info = { - sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO, - commandBuffer: vk.comp_cmd, - }; - - VkSubmitInfo2 submit_info = { - sType: VK_STRUCTURE_TYPE_SUBMIT_INFO_2, - commandBufferInfoCount: 1, - pCommandBufferInfos: &cmd_info, - }; - - result = vkQueueSubmit2(vk.gfx_queue, 1, &submit_info, vk.comp_fence); - VkCheckA("FinishComputePass failure: vkQueueSubmit2 error", result); -} - -pragma(inline): void -CreateBufferView(Vulkan* vk, BufferView* view, u64 size, Format format) -{ - CreateBuffer(vk, &view.base, BT.BufferView, size, false); - - VkBufferViewCreateInfo info = { - sType: VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, - buffer: view.buffer, - format: format, - range: size, - }; - - VkResult result = vkCreateBufferView(vk.device, &info, null, &view.view); - VkCheckA("CreateBufferView failure: vkCreateBufferView failed", result); - - view.size = size; -} - -pragma(inline): void -CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format, ImageUsage usage, bool depth_image = false) -{ - VmaAllocationCreateInfo alloc_info = { - usage: VMA_MEMORY_USAGE_GPU_ONLY, - requiredFlags: VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - }; - - VkImageCreateInfo image_info = { - sType: VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - imageType: VK_IMAGE_TYPE_2D, - mipLevels: 1, - arrayLayers: 1, - format: format, - tiling: VK_IMAGE_TILING_OPTIMAL, - initialLayout: VK_IMAGE_LAYOUT_UNDEFINED, - usage: usage, - samples: VK_SAMPLE_COUNT_1_BIT, - extent: { - width: w, - height: h, - depth: 1, - }, - }; - - u32[2] indices = [vk.gfx_index, vk.tfer_index]; - if (vk.gfx_index != vk.tfer_index) - { - image_info.sharingMode = VK_SHARING_MODE_CONCURRENT; - image_info.queueFamilyIndexCount = 2; - image_info.pQueueFamilyIndices = indices.ptr; - } - - VkResult result = vmaCreateImage(vk.vma, &image_info, &alloc_info, &view.image, &view.alloc, null); - // TODO: handle errors and realloc - assert(VkCheck("CreateImageView failure: vmaCreateImage error", result), "CreateImageView failure"); - - VkImageViewCreateInfo view_info = { - sType: VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - image: view.image, - viewType: VK_IMAGE_VIEW_TYPE_2D, - format: format, - subresourceRange: { - aspectMask: (depth_image ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT), - levelCount: 1, - layerCount: 1, - }, - }; - - result = vkCreateImageView(vk.device, &view_info, null, &view.view); - // TODO: also handle here - assert(VkCheck("CreateImageView failure: vkCreateImageView error", result), "CreateImageView failure"); - - view.layout = VK_IMAGE_LAYOUT_UNDEFINED; - view.format = format; - view.w = w; - view.h = h; - view.depth_image = depth_image; - view.usage = usage; -} - -void -PushConstants(T)(Vulkan* vk, Pipeline pipeline_id, T* pc) -{ - assert(pipeline_id > 0, "PushConstants pipeline_id == 0"); - PipelineHandles* pipeline = vk.pipeline_handles.ptr + pipeline_id; - VkShaderStageFlags stage = (pipeline.type == VK_PIPELINE_BIND_POINT_GRAPHICS ? - VK_SHADER_STAGE_VERTEX_BIT|VK_SHADER_STAGE_FRAGMENT_BIT : - VK_SHADER_STAGE_COMPUTE_BIT); - - vkCmdPushConstants( - vk.cmds[vk.frame_index], - pipeline.layout, - stage, - 0, - T.sizeof, - pc - ); -} - -void -ImageBarrier(Vulkan* vk) -{ - VkMemoryBarrier2 barrier = { - sType: VK_STRUCTURE_TYPE_MEMORY_BARRIER_2, - srcStageMask: VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - srcAccessMask: VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, - dstStageMask: VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - dstAccessMask: VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, - }; - - VkDependencyInfo dependency = { - sType: VK_STRUCTURE_TYPE_DEPENDENCY_INFO, - dependencyFlags: VK_DEPENDENCY_BY_REGION_BIT, - memoryBarrierCount: 1, - pMemoryBarriers: &barrier, - }; - - vkCmdPipelineBarrier2(vk.cmds[vk.frame_index], &dependency); -} - -bool -Transfer(T)(Vulkan* vk, Buffer* buf, T[] data) -{ - u8[] u8_data = (cast(u8*)(data.ptr))[0 .. T.sizeof * data.length]; - return Transfer(vk, buf, u8_data); -} - -bool -Transfer(Vulkan* vk, Buffer* buf, u8[] data) -{ - bool success = TransferReady(vk); - - u64 copied = 0; - while(copied != data.length && success) - { - if (copied != 0) - { - success = TransferReady(vk); - if (!success) - { - break; - } - } - - u64 transfer_length = cast(u64)vk.transfer_buf.data.length; - u64 data_length = cast(u64)data.length - copied; - u64 copy_length = transfer_length > data_length ? data_length : transfer_length; - - vk.transfer_buf.data[0 .. copy_length] = data[copied .. copy_length]; - - auto fn = function(Vulkan* vk, Buffer* buf, VkBufferCopy copy) - { - vkCmdCopyBuffer(vk.imm_cmd, vk.transfer_buf.buffer, buf.buffer, 1, ©); - }; - - VkBufferCopy copy = { - srcOffset: 0, - dstOffset: copied, - size: copy_length, - }; - - success = ImmSubmit(vk, buf, copy, fn); - - copied += copy_length; - } - - WaitForTransfers(vk); - - return success; -} - -bool -Transfer(T)(Vulkan* vk, Buffer* buf, T* ptr) -{ - assert(T.sizeof < vk.transfer_buf.data.length, "Transfer failure: structure size is too large"); - - bool success = TransferReady(vk); - if (success) - { - memcpy(vk.transfer_buf.data.ptr, ptr, T.sizeof); - - auto fn = function(Vulkan* vk, Buffer* buf, VkBufferCopy copy) - { - vkCmdCopyBuffer(vk.imm_cmd, vk.transfer_buf.buffer, buf.buffer, 1, ©); - }; - - VkBufferCopy copy = { - srcOffset: 0, - dstOffset: 0, - size: T.sizeof, - }; - - success = ImmSubmit(vk, buf, copy, fn); - } - - WaitForTransfers(vk); - - return success; -} - -// Needs to be done before writing to the transfer buffer as otherwise it'll overwrite it while previous transfers are occurring -bool -TransferReady(Vulkan* vk) -{ - VkResult result = vkWaitForFences(vk.device, 1, &vk.imm_fence, true, 999999999); - return VkCheck("Transfer failure: vkWaitForFences error", result); -} - -pragma(inline): bool -Transfer(Vulkan* vk, ImageView* view, u8[] data, u32 w, u32 h) -{ - return Transfer(vk, &view.base, data, w, h); -} - -bool -Transfer(Vulkan* vk, Image* image, u8[] data, u32 w, u32 h) -{ - bool success = true; - - u64 copied = 0; - while(copied != data.length) - { - u64 transfer_length = cast(u64)vk.transfer_buf.data.length; - u64 data_length = cast(u64)data.length - copied; - u64 copy_length = transfer_length > data_length ? data_length : transfer_length; - - vk.transfer_buf.data[0 .. copy_length] = data[copied .. copy_length]; - - auto fn = function(Vulkan* vk, Image* image, VkBufferImageCopy copy) - { - Transition(vk.imm_cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - vkCmdCopyBufferToImage(vk.imm_cmd, vk.transfer_buf.buffer, image.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©); - - Transition(vk.imm_cmd, image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - }; - - VkBufferImageCopy copy = { - bufferRowLength: w, - bufferImageHeight: h, - imageSubresource: { - aspectMask: VK_IMAGE_ASPECT_COLOR_BIT, - layerCount: 1, - }, - imageExtent: { - width: w, - height: h, - depth: 1, - }, - bufferOffset: copied, - }; - - success = ImmSubmit(vk, image, copy, fn); - - copied += copy_length; - } - - WaitForTransfers(vk); - - return success; -} - -pragma(inline): void -Copy(VkCommandBuffer cmd, Image* src, Image* dst, VkExtent2D src_ext, VkExtent2D dst_ext) -{ - Copy(cmd, src.image, dst.image, src.layout, dst.layout, src_ext, dst_ext); -} - -pragma(inline): void -Copy(VkCommandBuffer cmd, Image* src, VkImage dst, VkImageLayout dst_layout, VkExtent2D src_ext, VkExtent2D dst_ext) -{ - Copy(cmd, src.image, dst, src.layout, dst_layout, src_ext, dst_ext); -} - -pragma(inline): void -Copy(VkCommandBuffer cmd, VkImage src, VkImage dst, VkImageLayout src_layout, VkImageLayout dst_layout, VkExtent2D src_ext, VkExtent2D dst_ext) -{ - VkImageBlit blit = { - srcOffsets: [ - { x: 0, y: 0 }, - { x: cast(i32)src_ext.width, y: cast(i32)src_ext.height, z: 1 }, - ], - dstOffsets: [ - { x: 0, y: 0 }, - { x: cast(i32)dst_ext.width, y: cast(i32)dst_ext.height, z: 1 }, - ], - srcSubresource: { - aspectMask: VK_IMAGE_ASPECT_COLOR_BIT, - baseArrayLayer: 0, - layerCount: 1, - mipLevel: 0, - }, - dstSubresource: { - aspectMask: VK_IMAGE_ASPECT_COLOR_BIT, - baseArrayLayer: 0, - layerCount: 1, - mipLevel: 0, - }, - }; - - vkCmdBlitImage( - cmd, - src, - src_layout, - dst, - dst_layout, - 1, - &blit, - VK_FILTER_LINEAR - ); -} - -void -Bind(Vulkan* vk, Pipeline pipeline_handle, DescSet[] sets, bool compute = false) -{ - assert(pipeline_handle > 0, "Bind failure: pipeline is 0"); - - VkCommandBuffer cmd = (compute ? vk.comp_cmd : vk.cmds[vk.frame_index]); - PipelineHandles* pipeline = vk.pipeline_handles.ptr + pipeline_handle; - BindPipeline(vk, cmd, pipeline); - - u32[] offsets; - if (vk.global_set.dynamic_count > 0) - { - offsets = AllocArray!(u32)(&vk.frame_arenas[vk.frame_index], vk.global_set.dynamic_count); - } - - vkCmdBindDescriptorSets( - cmd, - pipeline.type, - pipeline.layout, - 0, - 1, - &vk.global_set.handle, - cast(u32)offsets.length, - offsets.ptr - ); - - u32 offset_count; - VkDescriptorSet[] handles = AllocArray!(VkDescriptorSet)(&vk.frame_arenas[vk.frame_index], sets.length); - - foreach(i, set; sets) - { - handles[i] = set.handle; - offset_count += set.dynamic_count; - } - - if (offset_count > 0) - { - offsets = AllocArray!(u32)(&vk.frame_arenas[vk.frame_index], offset_count); - } - - vkCmdBindDescriptorSets( - cmd, - pipeline.type, - pipeline.layout, - 1, - cast(u32)handles.length, - handles.ptr, - cast(u32)offsets.length, - offsets.ptr - ); -} - -PipelineHandles* -NewPipeline(Vulkan* vk) -{ - PipelineHandles* pipeline = vk.pipeline_handles.ptr + vk.pipeline_count; - pipeline.index = vk.pipeline_count; - vk.pipeline_count += 1; - - return pipeline; -} - -void -Bind(Vulkan* vk, Pipeline pipeline_handle, DescSet set, bool compute = false) -{ - assert(pipeline_handle > 0, "Bind failure: pipeline is 0"); - - VkCommandBuffer cmd = (compute ? vk.comp_cmd : vk.cmds[vk.frame_index]); - PipelineHandles* pipeline = vk.pipeline_handles.ptr + pipeline_handle; - BindPipeline(vk, cmd, pipeline); - - u32[] offsets; - if (vk.global_set.dynamic_count > 0) - { - offsets = AllocArray!(u32)(&vk.frame_arenas[vk.frame_index], vk.global_set.dynamic_count); - } - - vkCmdBindDescriptorSets( - cmd, - pipeline.type, - pipeline.layout, - 0, - 1, - &vk.global_set.handle, - cast(u32)offsets.length, - offsets.ptr - ); - - if (set.dynamic_count > 0) - { - offsets = AllocArray!(u32)(&vk.frame_arenas[vk.frame_index], set.dynamic_count); - } - - vkCmdBindDescriptorSets( - cmd, - pipeline.type, - pipeline.layout, - 1, - 1, - &set.handle, - cast(u32)offsets.length, - offsets.ptr - ); -} - -pragma(inline): void -BindPipeline(Vulkan* vk, VkCommandBuffer cmd, PipelineHandles* pipeline) -{ - vkCmdBindPipeline(cmd, pipeline.type, pipeline.handle); - vk.last_pipeline[vk.frame_index] = pipeline.handle; - - VkViewport viewport = { - x: 0.0, - y: 0.0, - width: cast(f32)vk.swapchain_extent.width, - height: cast(f32)vk.swapchain_extent.height, - minDepth: 0.0, - maxDepth: 1.0, - }; - - vkCmdSetViewport(cmd, 0, 1, &viewport); - - VkRect2D scissor = { - extent: { - width: vk.swapchain_extent.width, - height: vk.swapchain_extent.height, - }, - }; - - vkCmdSetScissor(cmd, 0, 1, &scissor); -} - -pragma(inline): void -Transition(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout) -{ - VkImageMemoryBarrier2 barrier = { - sType: VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, - srcStageMask: VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, - srcAccessMask: VK_ACCESS_2_MEMORY_WRITE_BIT, - dstStageMask: VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, - dstAccessMask: VK_ACCESS_2_MEMORY_WRITE_BIT | VK_ACCESS_2_MEMORY_READ_BIT, - oldLayout: current_layout, - newLayout: new_layout, - image: image, - subresourceRange: { - aspectMask: new_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT, - baseMipLevel: 0, - levelCount: VK_REMAINING_MIP_LEVELS, - baseArrayLayer: 0, - layerCount: VK_REMAINING_ARRAY_LAYERS, - }, - }; - - VkDependencyInfo dep_info = { - sType: VK_STRUCTURE_TYPE_DEPENDENCY_INFO, - imageMemoryBarrierCount: 1, - pImageMemoryBarriers: &barrier, - }; - - vkCmdPipelineBarrier2(cmd, &dep_info); -} - -pragma(inline): void -Transition(VkCommandBuffer cmd, ImageView* view, VkImageLayout new_layout) -{ - Transition(cmd, view.image, view.layout, new_layout); - view.layout = new_layout; -} - -pragma(inline): void -Transition(VkCommandBuffer cmd, Image* image, VkImageLayout new_layout) -{ - Transition(cmd, image.image, image.layout, new_layout); - image.layout = new_layout; -} - -Result!(Shader) -BuildShader(Vulkan* vk, u8[] bytes) -{ - Result!(Shader) shader; - - VkShaderModuleCreateInfo shader_info = { - sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - codeSize: bytes.length, - pCode: cast(uint*)bytes.ptr, - }; - - VkResult result = vkCreateShaderModule(vk.device, &shader_info, null, &shader.value); - shader.ok = VkCheck("vkCreateShaderModule failure", result); - - return shader; -} - -void -InitFramebufferAndRenderPass(Vulkan* vk) -{ - VkAttachmentDescription[2] attach_descriptions = [ - { - format: vk.draw_image.format, - samples: VK_SAMPLE_COUNT_1_BIT, - loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR, - storeOp: VK_ATTACHMENT_STORE_OP_STORE, - stencilLoadOp: VK_ATTACHMENT_LOAD_OP_DONT_CARE, - stencilStoreOp: VK_ATTACHMENT_STORE_OP_DONT_CARE, - initialLayout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - finalLayout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - }, - { - format: vk.depth_image.format, - samples: VK_SAMPLE_COUNT_1_BIT, - loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR, - storeOp: VK_ATTACHMENT_STORE_OP_STORE, - initialLayout: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - finalLayout: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - }, - ]; - - VkAttachmentReference color_ref = { - attachment: 0, - layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - }; - - VkAttachmentReference depth_ref = { - attachment: 1, - layout: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - }; - - VkSubpassDescription subpass = { - pipelineBindPoint: VK_PIPELINE_BIND_POINT_GRAPHICS, - colorAttachmentCount: 1, - pColorAttachments: &color_ref, - pDepthStencilAttachment: &depth_ref, - }; - - VkSubpassDependency self_dependency = { - srcSubpass: 0, - dstSubpass: 0, - srcStageMask: VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - dstStageMask: VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - srcAccessMask: VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, - dstAccessMask: VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, - dependencyFlags: VK_DEPENDENCY_BY_REGION_BIT, - }; - - VkRenderPassCreateInfo pass_info = { - sType: VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - attachmentCount: cast(u32)attach_descriptions.length, - pAttachments: attach_descriptions.ptr, - subpassCount: 1, - pSubpasses: &subpass, - dependencyCount: 1, - pDependencies: &self_dependency, - }; - - VkResult result = vkCreateRenderPass(vk.device, &pass_info, null, &vk.render_pass); - VkCheckA("vkCreateRenderPass failure", result); - - CreateFramebuffer(vk); -} - -void -CreateFramebuffer(Vulkan* vk) -{ - - VkFramebufferCreateInfo framebuffer_info = { - sType: VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - renderPass: vk.render_pass, - attachmentCount: 2, - pAttachments: [vk.draw_image.view, vk.depth_image.view], - width: vk.swapchain_extent.width, - height: vk.swapchain_extent.height, - layers: 1, - }; - - VkResult result = vkCreateFramebuffer(vk.device, &framebuffer_info, null, &vk.framebuffer); - VkCheckA("vkCreateFramebuffer failure", result); -} - -Pipeline -CreateGraphicsPipeline(Vulkan* vk, GfxPipelineInfo* build_info) -{ - PipelineHandles* pipeline = NewPipeline(vk); - pipeline.type = VK_PIPELINE_BIND_POINT_GRAPHICS; - pipeline.layout = build_info.layout; - - VkDynamicState[2] dyn_state = [ VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR ]; - - VkPipelineDynamicStateCreateInfo dyn_info = { - sType: VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, - pDynamicStates: dyn_state.ptr, - dynamicStateCount: cast(u32)dyn_state.length, - }; - - VkPipelineInputAssemblyStateCreateInfo assembly_info = { - sType: VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, - topology: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, - primitiveRestartEnable: VK_FALSE, - }; - - VkPipelineRasterizationStateCreateInfo rasterization_info = { - sType: VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - cullMode: VK_CULL_MODE_BACK_BIT, - polygonMode: VK_POLYGON_MODE_FILL, - lineWidth: 1.0, - frontFace: VK_FRONT_FACE_COUNTER_CLOCKWISE, - }; - - VkPipelineMultisampleStateCreateInfo multisample_info = { - sType: VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - rasterizationSamples: VK_SAMPLE_COUNT_1_BIT, - minSampleShading: 1.0, - alphaToCoverageEnable: VK_FALSE, - alphaToOneEnable: VK_FALSE, - }; - - VkPipelineDepthStencilStateCreateInfo depth_info = { - sType: VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, - depthTestEnable: VK_TRUE, - depthWriteEnable: VK_TRUE, - depthCompareOp: VK_COMPARE_OP_GREATER_OR_EQUAL, - depthBoundsTestEnable: VK_FALSE, - stencilTestEnable: VK_FALSE, - minDepthBounds: 0.0, - maxDepthBounds: 1.0, - }; - - VkPipelineRenderingCreateInfo rendering_info = { - sType: VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, - colorAttachmentCount: 1, - pColorAttachmentFormats: cast(VkFormat*)&vk.draw_image.format, - depthAttachmentFormat: vk.depth_image.format, - }; - - VkPipelineColorBlendAttachmentState blend_state = { - colorWriteMask: VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, - blendEnable: VK_TRUE, - srcColorBlendFactor: VK_BLEND_FACTOR_SRC_ALPHA, - dstColorBlendFactor: VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, - colorBlendOp: VK_BLEND_OP_ADD, - srcAlphaBlendFactor: VK_BLEND_FACTOR_SRC_ALPHA, - dstAlphaBlendFactor: VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, - alphaBlendOp: VK_BLEND_OP_ADD, - }; - - VkPipelineColorBlendStateCreateInfo blend_info = { - sType: VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, - logicOpEnable: VK_FALSE, - logicOp: VK_LOGIC_OP_COPY, - attachmentCount: 1, - pAttachments: &blend_state, - }; - - VkVertexInputBindingDescription vertex_input_desc = { - binding: 0, - inputRate: cast(VkVertexInputRate)build_info.input_rate, - stride: build_info.input_rate_stride, - }; - - VkPipelineVertexInputStateCreateInfo input_info = { - sType: VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - vertexBindingDescriptionCount: 1, - pVertexBindingDescriptions: &vertex_input_desc, - vertexAttributeDescriptionCount: cast(u32)build_info.vertex_attributes.length, - pVertexAttributeDescriptions: build_info.vertex_attributes.ptr, - }; - - VkPipelineViewportStateCreateInfo viewport_info = { - sType: VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, - viewportCount: 1, - scissorCount: 1, - }; - - VkPipelineShaderStageCreateInfo[2] shader_info = [ - { - sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - stage: VK_SHADER_STAGE_FRAGMENT_BIT, - pName: "main", - }, - { - sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - stage: VK_SHADER_STAGE_VERTEX_BIT, - pName: "main", - }, - ]; - - Arena* arena = &vk.frame_arenas[0]; - - u8[] frag_bytes = LoadAssetData(arena, build_info.frag_shader); - u8[] vert_bytes = LoadAssetData(arena, build_info.vertex_shader); - - assert(vert_bytes && frag_bytes, "Unable to load shaders"); - - Result!(Shader) frag_module = BuildShader(vk, frag_bytes); - Result!(Shader) vert_module = BuildShader(vk, vert_bytes); - - assert(vert_module.ok && frag_module.ok, "Unable to build vulkan shaders"); - - scope(exit) - { - Destroy(vk, frag_module.value); - Destroy(vk, vert_module.value); - } - - __traits(getMember, shader_info.ptr + 0, "module") = frag_module.value; - __traits(getMember, shader_info.ptr + 1, "module") = vert_module.value; - - VkSpecializationInfo vert_spec_info = { - dataSize: build_info.vert_spec.size, - mapEntryCount: cast(u32)build_info.vert_spec.entries.length, - pMapEntries: build_info.vert_spec.entries.ptr, - pData: build_info.vert_spec.data, - }; - - if (build_info.vert_spec.entries.length > 0) - { - shader_info[0].pSpecializationInfo = &vert_spec_info; - } - - VkSpecializationInfo frag_spec_info = { - dataSize: build_info.frag_spec.size, - mapEntryCount: cast(u32)build_info.frag_spec.entries.length, - pMapEntries: build_info.frag_spec.entries.ptr, - pData: build_info.frag_spec.data, - }; - - if (build_info.frag_spec.entries.length > 0) - { - shader_info[1].pSpecializationInfo = &frag_spec_info; - } - - VkGraphicsPipelineCreateInfo create_info = { - sType: VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - pNext: &rendering_info, - pVertexInputState: &input_info, - pInputAssemblyState: &assembly_info, - pViewportState: &viewport_info, - pRasterizationState: &rasterization_info, - pMultisampleState: &multisample_info, - pColorBlendState: &blend_info, - pDepthStencilState: &depth_info, - pDynamicState: &dyn_info, - stageCount: cast(u32)shader_info.length, - pStages: shader_info.ptr, - renderPass: vk.render_pass, - layout: build_info.layout, - }; - - VkResult result = vkCreateGraphicsPipelines(vk.device, null, 1, &create_info, null, &pipeline.handle); - assert(VkCheck("CreateGraphicsPipeline failure", result), "Unable to build pipeline"); - - return pipeline.index; -} - -Pipeline -CreateComputePipeline(Vulkan* vk, CompPipelineInfo* comp_info) -{ - VkComputePipelineCreateInfo info = { - sType: VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - layout: comp_info.layout, - stage: { - sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - stage: VK_SHADER_STAGE_COMPUTE_BIT, - pName: "main", - }, - }; - - u8[] comp_bytes = LoadAssetData(&vk.frame_arenas[0], comp_info.shader); - assert(comp_bytes != null, "Unable to load compute shader data"); - - Result!(Shader) comp_module = BuildShader(vk, comp_bytes); - assert(comp_module.ok, "Unable to build compute shader"); - scope(exit) Destroy(vk, comp_module.value); - - __traits(getMember, &info.stage, "module") = comp_module.value; - - VkSpecializationInfo spec_info = { - dataSize: comp_info.spec.size, - mapEntryCount: cast(u32)comp_info.spec.entries.length, - pMapEntries: comp_info.spec.entries.ptr, - pData: comp_info.spec.data, - }; - - if (comp_info.spec.entries.length > 0) - { - info.stage.pSpecializationInfo = &spec_info; - } - - PipelineHandles* pipeline = NewPipeline(vk); - pipeline.type = VK_PIPELINE_BIND_POINT_COMPUTE; - pipeline.layout = comp_info.layout; - - Pipeline pipeline_handle = pipeline.index; - - VkResult result = vkCreateComputePipelines(vk.device, null, 1, &info, null, &pipeline.handle); - assert(VkCheck("CreateComputePipeline failure", result), "Unable to build pipeline"); - - return pipeline_handle; -} - -void -ClearColor(Vulkan* vk, ImageView* view, Vec4 color) -{ - VkImageSubresourceRange clear_range = { - aspectMask: (view.depth_image ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT), - levelCount: 1, - layerCount: 1, - }; - - vkCmdClearColorImage( - vk.cmds[vk.frame_index], - view.image, - view.layout, - cast(VkClearColorValue*)color.v, - 1, - &clear_range - ); -} - -void -WaitIdle(Vulkan* vk) -{ - vkDeviceWaitIdle(vk.device); -} - -void -Destroy(Vulkan* vk, Shader shader) -{ - vkDestroyShaderModule(vk.device, shader, null); -} - -void -Destroy(Vulkan* vk, Pipeline pipeline) -{ - vkDestroyPipeline(vk.device, vk.pipeline_handles[pipeline].handle, null); -} - -void -Destroy(Vulkan* vk) -{ - vkDeviceWaitIdle(vk.device); - - alias N = Node!(SI); - assert(vk.cleanup_list.first != null, "node null"); - for(N* node = vk.cleanup_list.first; node != null; node = node.next) - { - switch (node.value) - { - case SI.Renderer: - DestroyRenderer(vk); - break; - case SI.Instance: - Destroy(vk.instance); - break; - case SI.Debug: - Destroy(vk.dbg_msg, vk.instance); - break; - case SI.Surface: - Destroy(vk.surface, vk.instance); - break; - case SI.Device: - Destroy(vk.device); - break; - case SI.Vma: - Destroy(vk.vma); - break; - case SI.FrameStructures: - DestroyFS(vk); - break; - case SI.Swapchain: - Destroy(vk.swapchain, vk.present_images, vk.device); - break; - case SI.DrawImages: - Destroy(vk, &vk.draw_image); - Destroy(vk, &vk.depth_image); - break; - case SI.DescriptorPools: - DestroyDescriptorPools(vk); - break; - case SI.Buffers: - Destroy(vk, &vk.transfer_buf); - Destroy(vk, &vk.ui_vert_buf); - Destroy(vk, &vk.ui_index_buf); - Destroy(vk, &vk.global_buf); - Destroy(vk, &vk.shader_buf); - break; - case SI.Pipelines: - DestroyPipelines(vk); - break; - default: - break; - } - } -} - -void -DestroyDescriptorPools(Vulkan* vk) -{ - vkDestroyDescriptorPool(vk.device, vk.active_pool, null); - - Node!(VkDescriptorPool)* node = vk.full_pools.first; - for(;;) - { - if (node == null) - { - break; - } - - vkDestroyDescriptorPool(vk.device, node.value, null); - - node = node.next; - } -} - -void -DestroyPipelines(Vulkan* vk) -{ - if (vk.conv_pipeline_layout) - { - vkDestroyPipelineLayout(vk.device, vk.conv_pipeline_layout, null); - } - - if (vk.conv_desc_layout) - { - vkDestroyDescriptorSetLayout(vk.device, vk.conv_desc_layout, null); - } - - if (vk.r_to_rgba_pipeline) - { - vkDestroyPipeline(vk.device, vk.pipeline_handles[vk.r_to_rgba_pipeline].handle, null); - } - - if (vk.rg_to_rgba_pipeline) - { - vkDestroyPipeline(vk.device, vk.pipeline_handles[vk.rg_to_rgba_pipeline].handle, null); - } - - if (vk.rgb_to_rgba_pipeline) - { - vkDestroyPipeline(vk.device, vk.pipeline_handles[vk.rgb_to_rgba_pipeline].handle, null); - } -} - -void -Destroy(T)(Vulkan* vk, MappedBuffer!(T)* buf) -{ - vmaUnmapMemory(vk.vma, buf.alloc); - Destroy(vk, &buf.base); -} - -void -Destroy(Vulkan* vk, Buffer* buf) -{ - vmaDestroyBuffer(vk.vma, buf.buffer, buf.alloc); -} - -void -InitDescriptors(Vulkan* vk) -{ - Push(vk, SI.DescriptorPools); - - PushDescriptorPool(vk); -} - -void -PushDescriptorPool(Vulkan* vk) -{ - VkDescriptorPoolSize[7] pool_sizes = [ - { type: VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, descriptorCount: 4096 }, - { type: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 4096 }, - { type: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, descriptorCount: 4096 }, - { type: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, descriptorCount: 4096 }, - { type: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, descriptorCount: 4096 }, - { type: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 4096 }, - { type: VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, descriptorCount: 4096 }, - ]; - - VkDescriptorPoolCreateInfo pool_info = { - sType: VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - poolSizeCount: cast(u32)pool_sizes.length, - pPoolSizes: pool_sizes.ptr, - maxSets: MAX_SETS, - }; - - VkDescriptorPool pool; - VkResult result = vkCreateDescriptorPool(vk.device, &pool_info, null, &pool); - bool success = VkCheck("vkCreateDescriptorPool failure", result); - assert(success, "vkCreateDescriptorPool error"); - - if (vk.active_pool == null || vk.active_pool == VK_NULL_HANDLE) - { - Node!(VkDescriptorPool)* node = Alloc!(Node!(VkDescriptorPool)); - node.value = vk.active_pool; - PushFront(&vk.full_pools, node, null); - } - - vk.active_pool = pool; -} - -bool -InitGlobalDescSet(Vulkan* vk) -{ - VkPhysicalDeviceProperties props; - vkGetPhysicalDeviceProperties(vk.physical_device, &props); - - VkSamplerCreateInfo sampler_info = { - sType: VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, - magFilter: VK_FILTER_NEAREST, - minFilter: VK_FILTER_NEAREST, - addressModeU: VK_SAMPLER_ADDRESS_MODE_REPEAT, - addressModeV: VK_SAMPLER_ADDRESS_MODE_REPEAT, - addressModeW: VK_SAMPLER_ADDRESS_MODE_REPEAT, - anisotropyEnable: VK_TRUE, - maxAnisotropy: props.limits.maxSamplerAnisotropy, - borderColor: VK_BORDER_COLOR_INT_OPAQUE_BLACK, - compareOp: VK_COMPARE_OP_ALWAYS, - mipmapMode: VK_SAMPLER_MIPMAP_MODE_LINEAR, - }; - - VkResult result = vkCreateSampler(vk.device, &sampler_info, null, &vk.nearest_sampler); - bool success = VkCheck("vkCreateSampler failure", result); - - if (success) - { - DescLayoutBinding[2] layout_bindings = [ - { binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL }, - { binding: 1, descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL }, - ]; - - vk.global_set_layout = CreateDescSetLayout(vk, layout_bindings); - vk.global_set = AllocDescSet(vk, vk.global_set_layout); - - WriteDrawImageDesc(vk); - - VkDescriptorImageInfo sampler_desc_info = { - sampler: vk.nearest_sampler, - }; - - VkWriteDescriptorSet write = { - sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - dstSet: vk.global_set.handle, - dstBinding: 1, - descriptorCount: 1, - descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER, - pImageInfo: &sampler_desc_info, - }; - - vkUpdateDescriptorSets(vk.device, 1, &write, 0, null); - } - - - return success; -} - -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 = [ - { - 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, - } - ]; - - vkUpdateDescriptorSets(vk.device, cast(u32)writes.length, writes.ptr, 0, null); -} - -void -WriteDrawImageDesc(Vulkan* vk) -{ - VkDescriptorImageInfo draw_image_info = { - imageView: vk.draw_image.view, - imageLayout: VK_IMAGE_LAYOUT_GENERAL, - }; - - VkWriteDescriptorSet write = { - sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - dstSet: vk.global_set.handle, - dstBinding: 0, - descriptorCount: 1, - descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, - pImageInfo: &draw_image_info, - }; - - vkUpdateDescriptorSets(vk.device, 1, &write, 0, null); -} - -void -WriteConvDescriptor(Vulkan* vk, Buffer* buf) -{ - VkDescriptorBufferInfo buf_info = { - buffer: buf.buffer, - range: buf.size, - offset: 0, - }; - - VkWriteDescriptorSet write = { - sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - dstSet: vk.conv_desc_set.handle, - dstBinding: 1, - descriptorCount: 1, - descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - pBufferInfo: &buf_info, - }; - - vkUpdateDescriptorSets(vk.device, 1, &write, 0, null); -} - -void -WriteConvDescriptor(Vulkan* vk, ImageView* view) -{ - VkDescriptorImageInfo image_info = { - imageView: view.view, - imageLayout: VK_IMAGE_LAYOUT_GENERAL, - }; - - VkWriteDescriptorSet write = { - sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - dstSet: vk.conv_desc_set.handle, - dstBinding: 0, - descriptorCount: 1, - descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, - pImageInfo: &image_info, - }; - - vkUpdateDescriptorSets(vk.device, 1, &write, 0, null); -} - -pragma(inline): void -Dispatch(Vulkan* vk, VkCommandBuffer cmd) -{ - f32 w = Ceil(cast(f32)(vk.swapchain_extent.width) / 16.0F); - f32 h = Ceil(cast(f32)(vk.swapchain_extent.height) / 16.0F); - vkCmdDispatch(cmd, cast(u32)w, cast(u32)h, 1); -} - -pragma(inline): void -Dispatch(Vulkan* vk) -{ - Dispatch(vk, vk.cmds[vk.frame_index]); -} - -bool -VkCheck(string message, VkResult result) -{ - bool success = true; - - // TODO: Handle error cases that can be handled - if (result == VK_ERROR_OUT_OF_DEVICE_MEMORY) - { - assert(false, "Handle VK_ERROR_OUT_OF_DEVICE_MEMORY"); - } - else if (result == VK_ERROR_OUT_OF_HOST_MEMORY) - { - assert(false, "Handle VK_ERROR_OUT_OF_HOST_MEMORY"); - } - else if (result != VK_SUCCESS) - { - success = false; - char[512] buf; - buf[] = '\0'; - buf.sformat("%s: %s", message, VkResultStr(result)); - Logf("%r", buf); - } - - return success; -} - -void -VkCheckA(string message, VkResult result) -{ - assert(VkCheck(message, result), "Aborting program due to failure"); -} - -bool -InitFrameStructures(Vulkan* vk) -{ - Push(vk, SI.FrameStructures); - - bool success = true; - Arena* arena = &vk.frame_arenas[0]; - - VkSemaphoreCreateInfo sem_info = { sType: VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; - - VkCommandPoolCreateInfo pool_info = { - sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - flags: VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, - }; - - VkFenceCreateInfo fence_info = { - sType: VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, - flags: VK_FENCE_CREATE_SIGNALED_BIT, - }; - - VkCommandBufferAllocateInfo cmd_info = { - sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, - commandBufferCount: 1, - level: VK_COMMAND_BUFFER_LEVEL_PRIMARY, - }; - - u32 sem_count = cast(u32)vk.present_images.length; - vk.submit_sems = AllocArray!(VkSemaphore)(arena, sem_count); - - foreach(i; 0 .. sem_count) - { - if (success) - { - VkResult result = vkCreateSemaphore(vk.device, &sem_info, null, vk.submit_sems.ptr + i); - success = VkCheck("vkCreateSemaphore failure", result); - } - } - - foreach(i; 0 .. FRAME_OVERLAP) - { - VkResult result; - - if (success) - { - pool_info.queueFamilyIndex = vk.gfx_index; - result = vkCreateCommandPool(vk.device, &pool_info, null, vk.cmd_pools.ptr + i); - success = VkCheck("vkCreateCommandPool failure", result); - } - - if (success) - { - cmd_info.commandPool = vk.cmd_pools[i]; - result = vkAllocateCommandBuffers(vk.device, &cmd_info, vk.cmds.ptr + i); - success = VkCheck("vkAllocateCommandBuffers failure", result); - } - - if (success) - { - result = vkCreateFence(vk.device, &fence_info, null, vk.render_fences.ptr + i); - success = VkCheck("vkCreateFence failure", result); - } - - if (success) - { - result = vkCreateSemaphore(vk.device, &sem_info, null, vk.acquire_sems.ptr + i); - success = VkCheck("vkCreateSemaphore failure", result); - } - } - - if (success) - { - pool_info.queueFamilyIndex = vk.tfer_index; - VkResult result = vkCreateCommandPool(vk.device, &pool_info, null, &vk.imm_pool); - success = VkCheck("vkCreateCommandPool failure", result); - } - - if (success) - { - cmd_info.commandPool = vk.imm_pool; - VkResult result = vkAllocateCommandBuffers(vk.device, &cmd_info, &vk.imm_cmd); - success = VkCheck("vkAllocateCommandBuffers failure", result); - } - - if (success) - { - VkResult result = vkCreateFence(vk.device, &fence_info, null, &vk.imm_fence); - success = VkCheck("vkCreateFence failure", result); - } - - if (success) - { - pool_info.queueFamilyIndex = vk.gfx_index; - VkResult result = vkCreateCommandPool(vk.device, &pool_info, null, &vk.comp_cmd_pool); - success = VkCheck("vkCreateCommandPool failure", result); - } - - if (success) - { - cmd_info.commandPool = vk.comp_cmd_pool; - VkResult result = vkAllocateCommandBuffers(vk.device, &cmd_info, &vk.comp_cmd); - success = VkCheck("vkCreateCommandPool failure", result); - } - - if (success) - { - VkResult result = vkCreateFence(vk.device, &fence_info, null, &vk.comp_fence); - success = VkCheck("vkCreateFence failure", result); - } - - return success; -} - -Format -GetDrawImageFormat(Vulkan* vk) -{ - VkFormat selected_format; - foreach(format; VK_IMAGE_FORMATS) - { - VkImageFormatProperties props; - VkResult result = vkGetPhysicalDeviceImageFormatProperties( - vk.physical_device, - format, - VK_IMAGE_TYPE_2D, - VK_IMAGE_TILING_OPTIMAL, - IU.Draw, - 0, - &props - ); - if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) - { - continue; - } - - if (result == VK_SUCCESS) - { - selected_format = format; - break; - } - } - - return cast(Format)selected_format; -} - -bool -CreateDrawImages(Vulkan* vk) -{ - Push(vk, SI.DrawImages); - - bool success = true; - - Format draw_format = cast(Format)GetDrawImageFormat(vk); - Format depth_format = cast(Format)VK_FORMAT_D32_SFLOAT; - - u32 w = vk.swapchain_extent.width; - u32 h = vk.swapchain_extent.height; - - CreateImageView(vk, &vk.draw_image, w, h, draw_format, IU.Draw, false); - CreateImageView(vk, &vk.depth_image, w, h, depth_format, IU.Depth, true); - - return success; -} - -void -SelectSwapchainFormats(Vulkan* vk) -{ - Arena* arena = &vk.frame_arenas[0]; - - u32 format_count; - vkGetPhysicalDeviceSurfaceFormatsKHR(vk.physical_device, vk.surface, &format_count, null); - VkSurfaceFormatKHR[] formats = AllocArray!(VkSurfaceFormatKHR)(arena, format_count); - vkGetPhysicalDeviceSurfaceFormatsKHR(vk.physical_device, vk.surface, &format_count, formats.ptr); - - u32 mode_count; - vkGetPhysicalDeviceSurfacePresentModesKHR(vk.physical_device, vk.surface, &mode_count, null); - VkPresentModeKHR[] modes = AllocArray!(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; - } - } - - vk.surface_format = formats[0]; - vk.present_mode = present_mode; -} - -bool -CreateSwapchain(Vulkan* vk) -{ - Push(vk, SI.Swapchain); - - bool success = true; - Arena* arena = &vk.frame_arenas[0]; - - VkSurfaceCapabilitiesKHR cap; - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk.physical_device, vk.surface, &cap); - - static bool initialized = false; - if (!initialized) - { - SelectSwapchainFormats(vk); - } - - VkSwapchainCreateInfoKHR info = { - sType: VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, - imageArrayLayers: 1, - imageUsage: IU.Swapchain, - compositeAlpha: VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, - clipped: VK_TRUE, - imageSharingMode: VK_SHARING_MODE_EXCLUSIVE, - minImageCount: cap.minImageCount + 1, - surface: vk.surface, - imageFormat: vk.surface_format.format, - imageColorSpace: vk.surface_format.colorSpace, - imageExtent: { - width: clamp(cast(u32)vk.window.w, cap.minImageExtent.width, cap.maxImageExtent.width), - height: clamp(cast(u32)vk.window.h, cap.minImageExtent.height, cap.maxImageExtent.height), - }, - preTransform: cap.currentTransform, - presentMode: vk.present_mode, - }; - - VkResult result = vkCreateSwapchainKHR(vk.device, &info, null, &vk.swapchain); - success = VkCheck("vkCreateSwapchainKHR failure", result); - - u32 count; - vkGetSwapchainImagesKHR(vk.device, vk.swapchain, &count, null); - VkImage[] images = AllocArray!(VkImage)(arena, count); - vkGetSwapchainImagesKHR(vk.device, vk.swapchain, &count, images.ptr); - VkImageView[] views = AllocArray!(VkImageView)(arena, count); - - vk.present_images = AllocArray!(ImageView)(&vk.arena, count); - - VkImageViewCreateInfo view_info = { - sType: VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - viewType: VK_IMAGE_VIEW_TYPE_2D, - components: { - r: VK_COMPONENT_SWIZZLE_IDENTITY, - g: VK_COMPONENT_SWIZZLE_IDENTITY, - b: VK_COMPONENT_SWIZZLE_IDENTITY, - a: VK_COMPONENT_SWIZZLE_IDENTITY, - }, - subresourceRange: { - aspectMask: VK_IMAGE_ASPECT_COLOR_BIT, - baseMipLevel: 0, - levelCount: 1, - baseArrayLayer: 0, - layerCount: 1, - }, - }; - - VkFramebufferCreateInfo framebuffer_info = { - sType: VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - }; - - foreach(i, image; vk.present_images) - { - vk.present_images[i].image = images[i]; - vk.present_images[i].format = cast(Format)vk.surface_format.format; - view_info.image = images[i]; - view_info.format = vk.surface_format.format; - - result = vkCreateImageView(vk.device, &view_info, null, &vk.present_images[i].view); - success = VkCheck("vkCreateImageView failure", result); - } - - vk.swapchain_extent.width = info.imageExtent.width; - vk.swapchain_extent.height = info.imageExtent.height; - vk.swapchain_extent.depth = 1; - - if (!initialized && success) - { - initialized = true; - } - - return success; -} - -void -RecreateSwapchain(Vulkan* vk) -{ - vkDeviceWaitIdle(vk.device); - - Destroy(vk.swapchain, vk.present_images, vk.device); - Destroy(vk, &vk.draw_image); - Destroy(vk, &vk.depth_image); - vkDestroyFramebuffer(vk.device, vk.framebuffer, null); - - CreateSwapchain(vk); - CreateDrawImages(vk); - WriteDrawImageDesc(vk); - CreateFramebuffer(vk); -} - -bool -InitVMA(Vulkan* vk) -{ - Push(vk, SI.Vma); - - bool success = true; - - VmaVulkanFunctions vk_functions = { - vkGetInstanceProcAddr: vkGetInstanceProcAddr, - vkGetDeviceProcAddr: vkGetDeviceProcAddr, - }; - - VmaAllocatorCreateInfo info = { - flags: VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT, - vulkanApiVersion: VK_MAKE_API_VERSION(0, 1, 2, 0), - pVulkanFunctions: &vk_functions, - physicalDevice: vk.physical_device, - device: vk.device, - instance: vk.instance, - }; - - VkResult result = vmaCreateAllocator(&info, &vk.vma); - success = VkCheck("vmaCreateAllocator failure", result); - - return success; -} - -bool -InitDevice(Vulkan* vk) -{ - Push(vk, SI.Device); - - bool success = false; - Arena* arena = &vk.frame_arenas[0]; - - u32 count; - vkEnumeratePhysicalDevices(vk.instance, &count, null); - VkPhysicalDevice[] devices = AllocArray!(VkPhysicalDevice)(arena, count); - vkEnumeratePhysicalDevices(vk.instance, &count, devices.ptr); - - VkPhysicalDevice physical_device = null; - bool discrete_candidate = false; - QueueInfo candidate = { - gfx_index: -1, - tfer_index: -1, - single_queue: false, - }; - - foreach(dev; devices) - { - QueueInfo current = CheckQueueProperties(arena, dev, vk.surface); - b32 discrete = false; - - if (current.gfx_index < 0) - continue; - if (!CheckDeviceProperties(arena, dev, vk.surface, &discrete)) - continue; - if (discrete_candidate && !discrete) - continue; - if (!CheckDeviceFeatures(dev)) - continue; - - discrete_candidate = cast(bool)discrete; - candidate = current; - physical_device = dev; - - if (discrete_candidate && !candidate.single_queue) - continue; - } - - if (physical_device) - { - VkDeviceQueueCreateInfo[2] queue_info; - f32 priority = 1.0f; - count = 1; - - queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_info[0].queueFamilyIndex = candidate.gfx_index; - queue_info[0].queueCount = 1; - queue_info[0].pQueuePriorities = &priority; - queue_info[0].flags = 0; - - if (!candidate.single_queue) - { - queue_info[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_info[1].queueFamilyIndex = candidate.tfer_index; - queue_info[1].queueCount = 1; - queue_info[1].pQueuePriorities = &priority; - queue_info[1].flags = 0; - - count += 1; - } - - VkPhysicalDeviceSynchronization2Features synchronization2 = { - sType: VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES, - synchronization2: VK_TRUE, - }; - - VkPhysicalDeviceVulkan12Features features_12 = { - sType: VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, - pNext: &synchronization2, - descriptorIndexing: VK_TRUE, - bufferDeviceAddress: VK_TRUE, - descriptorBindingUniformBufferUpdateAfterBind: VK_TRUE, - descriptorBindingSampledImageUpdateAfterBind: VK_TRUE, - descriptorBindingStorageImageUpdateAfterBind: VK_TRUE, - descriptorBindingStorageBufferUpdateAfterBind: VK_TRUE, - descriptorBindingStorageTexelBufferUpdateAfterBind: VK_TRUE, - descriptorBindingPartiallyBound: VK_TRUE, - shaderSampledImageArrayNonUniformIndexing: VK_TRUE, - shaderUniformBufferArrayNonUniformIndexing: VK_TRUE, - runtimeDescriptorArray: VK_TRUE, - storageBuffer8BitAccess: VK_TRUE, - }; - - VkPhysicalDeviceVulkan11Features features_11 = { - sType: VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES, - pNext: &features_12, - }; - - VkPhysicalDeviceFeatures2 features = { - sType: VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, - pNext: &features_11, - features: { - shaderUniformBufferArrayDynamicIndexing: VK_TRUE, - shaderSampledImageArrayDynamicIndexing: VK_TRUE, - shaderStorageBufferArrayDynamicIndexing: VK_TRUE, - shaderStorageImageArrayDynamicIndexing: VK_TRUE, - samplerAnisotropy: VK_TRUE, - fragmentStoresAndAtomics: VK_TRUE, - }, - }; - - VkDeviceCreateInfo device_info = { - sType: VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - pNext: &features, - ppEnabledExtensionNames: VK_DEVICE_EXTENSIONS.ptr, - enabledExtensionCount: cast(u32)VK_DEVICE_EXTENSIONS.length, - queueCreateInfoCount: count, - pQueueCreateInfos: queue_info.ptr, - pEnabledFeatures: null, - }; - - VkResult result = vkCreateDevice(physical_device, &device_info, null, &vk.device); - if (result != VK_SUCCESS) - { - Logf("vkCreateDevices failure: %s", VkResultStr(result)); - } - else - { - LoadDeviceFunctions(vk); - - vkGetDeviceQueue( - vk.device, - candidate.gfx_index, - 0, - &candidate.gfx_queue - ); - - if (!candidate.single_queue) - { - vkGetDeviceQueue( - vk.device, - candidate.tfer_index, - candidate.tfer_index == candidate.gfx_index ? 1 : 0, - &candidate.tfer_queue - ); - } - else - { - candidate.tfer_queue = candidate.gfx_queue; - candidate.tfer_index = candidate.gfx_index; - } - - vk.physical_device = physical_device; - vk.queues = candidate; - - success = true; - } - } - - return success; -} - -bool -CheckDeviceFeatures(VkPhysicalDevice device) -{ - VkPhysicalDeviceFeatures2 features2 = { sType: VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 }; - VkPhysicalDeviceVulkan12Features features_12 = { sType: VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES }; - - features2.pNext = &features_12; - vkGetPhysicalDeviceFeatures2(device, &features2); - - VkPhysicalDeviceFeatures features = features2.features; - bool result = true; - - result &= cast(bool)features.fragmentStoresAndAtomics; - result &= cast(bool)features.shaderUniformBufferArrayDynamicIndexing; - result &= cast(bool)features.shaderSampledImageArrayDynamicIndexing; - result &= cast(bool)features.shaderStorageBufferArrayDynamicIndexing; - result &= cast(bool)features.shaderStorageImageArrayDynamicIndexing; - result &= cast(bool)features.samplerAnisotropy; - - result &= cast(bool)features_12.descriptorIndexing; - result &= cast(bool)features_12.bufferDeviceAddress; - result &= cast(bool)features_12.descriptorBindingUniformBufferUpdateAfterBind; - result &= cast(bool)features_12.descriptorBindingStorageTexelBufferUpdateAfterBind; - result &= cast(bool)features_12.descriptorBindingSampledImageUpdateAfterBind; - result &= cast(bool)features_12.descriptorBindingStorageImageUpdateAfterBind; - result &= cast(bool)features_12.descriptorBindingStorageBufferUpdateAfterBind; - result &= cast(bool)features_12.descriptorBindingPartiallyBound; - result &= cast(bool)features_12.runtimeDescriptorArray; - result &= cast(bool)features_12.shaderSampledImageArrayNonUniformIndexing; - result &= cast(bool)features_12.shaderUniformBufferArrayNonUniformIndexing; - result &= cast(bool)features_12.timelineSemaphore; - result &= cast(bool)features_12.storageBuffer8BitAccess; - - return result; -} - -bool -CheckDeviceProperties(Arena *arena, VkPhysicalDevice device, VkSurfaceKHR surface, b32* discrete) -{ - bool success = false; - - VkPhysicalDeviceProperties props; - vkGetPhysicalDeviceProperties(device, &props); - - if (VK_API_VERSION_MINOR(props.apiVersion) >= 3) - { - u32 ext_count; - vkEnumerateDeviceExtensionProperties(device, null, &ext_count, null); - VkExtensionProperties[] ext_props = AllocArray!(VkExtensionProperties)(arena, ext_count); - vkEnumerateDeviceExtensionProperties(device, null, &ext_count, ext_props.ptr); - - i32 matched = 0; - foreach(prop; ext_props) - { - foreach(ext; VK_DEVICE_EXTENSIONS) - { - if (strcmp(cast(char*)prop.extensionName, ext) == 0) - { - matched += 1; - break; - } - } - } - - if (matched == VK_DEVICE_EXTENSIONS.length) - { - u32 fmt_count, present_count; - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &fmt_count, null); - vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &present_count, null); - - *discrete = props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU; - success = fmt_count && present_count; - } - } - - return success; -} - -QueueInfo -CheckQueueProperties(Arena *arena, VkPhysicalDevice device, VkSurfaceKHR surface) -{ - const u32 T_BIT = VK_QUEUE_TRANSFER_BIT; - const u32 C_BIT = VK_QUEUE_COMPUTE_BIT; - const u32 G_BIT = VK_QUEUE_GRAPHICS_BIT; - const u32 S_BIT = VK_QUEUE_SPARSE_BINDING_BIT; - - QueueInfo current = { - gfx_index: -1, - tfer_index: -1, - single_queue: false, - }; - - u32 count; - vkGetPhysicalDeviceQueueFamilyProperties(device, &count, null); - VkQueueFamilyProperties[] properties = AllocArray!(VkQueueFamilyProperties)(arena, count); - vkGetPhysicalDeviceQueueFamilyProperties(device, &count, properties.ptr); - - if (count == 1 && properties[0].queueCount == 1 && BitEq(properties[0].queueFlags, T_BIT | C_BIT | G_BIT)) - { - current.gfx_index = current.tfer_index = 0; - current.single_queue = true; - } - else - { - bool sparse = false, tfer_only = false; - - foreach(i, prop; properties) - { - b32 surface_support; - vkGetPhysicalDeviceSurfaceSupportKHR(device, cast(u32)i, surface, &surface_support); - - if (current.gfx_index < 0 && surface_support && BitEq(prop.queueFlags, G_BIT)) - { - current.gfx_index = cast(i32)i; - continue; - } - - if (BitEq(prop.queueFlags, T_BIT | S_BIT) && !BitEq(prop.queueFlags, G_BIT | C_BIT)) - { - sparse = true; - tfer_only = true; - current.tfer_index = cast(i32)i; - continue; - } - - if (!(sparse && tfer_only) && BitEq(prop.queueFlags, T_BIT | S_BIT)) - { - sparse = true; - current.tfer_index = cast(i32)i; - continue; - } - - if (!sparse && !BitEq(prop.queueFlags, T_BIT) && BitEq(prop.queueFlags, C_BIT)) - { - tfer_only = true; - current.tfer_index = cast(i32)i; - continue; - } - - if (!sparse && !tfer_only && BitEq(prop.queueFlags, C_BIT)) - { - current.tfer_index = cast(i32)i; - } - } - - if (current.tfer_index < 0) - { - current.tfer_index = current.gfx_index; - } - } - - return current; -} - -pragma(inline): void -Push(Vulkan* vk, StepInitialized step) -{ - Node!(SI)* node = Alloc!(Node!(SI)); - node.value = step; - PushFront(&vk.cleanup_list, node, null); -} - -void -DestroyRenderer(Vulkan* vk) -{ - foreach(i, arena; vk.frame_arenas) - { - Free(vk.frame_arenas.ptr + i); - } - - Free(&vk.arena); -} - -void -Destroy(VkInstance instance) -{ - if (instance) - { - vkDestroyInstance(instance, null); - } -} - -void -Destroy(VkDebugUtilsMessengerEXT dbg, VkInstance instance) -{ - debug - { - if (dbg) - { - vkDestroyDebugUtilsMessengerEXT(instance, dbg, null); - } - } -} - -void -Destroy(VkSurfaceKHR surface, VkInstance instance) -{ - if (surface) - { - vkDestroySurfaceKHR(instance, surface, null); - } -} - -void -Destroy(VkDevice device) -{ - if (device) - { - vkDestroyDevice(device, null); - } -} - -void -Destroy(VmaAllocator vma) -{ - if (vma) - { - vmaDestroyAllocator(vma); - } -} - -void -Destroy(VkSwapchainKHR swapchain, ImageView[] views, VkDevice device) -{ - foreach(view; views) - { - if (view.view) - { - vkDestroyImageView(device, view.view, null); - } - } - - if (swapchain) - { - vkDestroySwapchainKHR(device, swapchain, null); - } -} - -void -Destroy(Vulkan* vk, ImageView* view) -{ - if (view.view) - { - vkDestroyImageView(vk.device, view.view, null); - } - - if (view.image) - { - vmaDestroyImage(vk.vma, view.image, view.alloc); - } -} - -void -Destroy(VkDescriptorPool pool, VkDescriptorSetLayout[] layouts, VkPipelineLayout pipeline_layout, VkSampler sampler, VkDevice device) -{ - if (sampler) - { - vkDestroySampler(device, sampler, null); - } - - if (pipeline_layout) - { - vkDestroyPipelineLayout(device, pipeline_layout, null); - } - - foreach(layout; layouts) - { - if (layout) - { - vkDestroyDescriptorSetLayout(device, layout, null); - } - } - - if (pool) - { - vkDestroyDescriptorPool(device, pool, null); - } -} - -void -DestroyFS(Vulkan* vk) -{ - if (vk.imm_fence) - { - vkDestroyFence(vk.device, vk.imm_fence, null); - } - - if (vk.imm_cmd) - { - vkFreeCommandBuffers(vk.device, vk.imm_pool, 1, &vk.imm_cmd); - } - - if (vk.imm_pool) - { - vkDestroyCommandPool(vk.device, vk.imm_pool, null); - } - - if (vk.comp_cmd) - { - vkFreeCommandBuffers(vk.device, vk.comp_cmd_pool, 1, &vk.comp_cmd); - } - - if (vk.comp_cmd_pool) - { - vkDestroyCommandPool(vk.device, vk.comp_cmd_pool, null); - } - - if (vk.comp_fence) - { - vkDestroyFence(vk.device, vk.comp_fence, null); - } - - foreach(sem; vk.submit_sems) - { - if (sem) - { - vkDestroySemaphore(vk.device, sem, null); - } - } - - foreach(i; 0 .. FRAME_OVERLAP) - { - if (vk.render_fences[i]) - { - vkDestroyFence(vk.device, vk.render_fences[i], null); - } - - if (vk.cmd_pools[i]) - { - vkFreeCommandBuffers(vk.device, vk.cmd_pools[i], 1, &vk.cmds[i]); - } - - if (vk.cmd_pools[i]) - { - vkDestroyCommandPool(vk.device, vk.cmd_pools[i], null); - } - - if (vk.acquire_sems[i]) - { - vkDestroySemaphore(vk.device, vk.acquire_sems[i], null); - } - } -} - -bool -InitInstance(Vulkan* vk) -{ - Push(vk, SI.Instance); - - bool success = true; - Arena* arena = &vk.frame_arenas[0]; - - u32 count; - vkEnumerateInstanceLayerProperties(&count, null); - VkLayerProperties[] layers = AllocArray!(VkLayerProperties)(arena, count); - vkEnumerateInstanceLayerProperties(&count, layers.ptr); - - foreach(i, layer; layers) - { - if (strcmp(cast(char*)&layer.layerName, "VK_LAYER_KHRONOS_validation") == 0) - { - g_VLAYER_SUPPORT = true; - break; - } - } - - const char*[] instance_layers = g_VLAYER_SUPPORT && BUILD_DEBUG ? VK_INSTANCE_LAYERS_DEBUG : VK_INSTANCE_LAYERS; - const char*[] instance_ext = g_VLAYER_SUPPORT && BUILD_DEBUG ? VK_INSTANCE_EXT_DEBUG : VK_INSTANCE_EXT; - - VkApplicationInfo app_info = { - sType: VK_STRUCTURE_TYPE_APPLICATION_INFO, - pApplicationName: "Video Game", - applicationVersion: VK_MAKE_API_VERSION(0, 0, 0, 1), - pEngineName: "Gears", - engineVersion: VK_MAKE_API_VERSION(0, 0, 0, 1), - apiVersion: VK_MAKE_API_VERSION(0, 1, 2, 0), - }; - - VkInstanceCreateInfo instance_info = { - sType: VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - pApplicationInfo: &app_info, - enabledLayerCount: cast(u32)instance_layers.length, - ppEnabledLayerNames: instance_layers.ptr, - enabledExtensionCount: cast(u32)instance_ext.length, - ppEnabledExtensionNames: instance_ext.ptr, - }; - - VkValidationFeatureEnableEXT validation_enable = VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT; - - VkValidationFeaturesEXT validation_features = { - sType: VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT, - enabledValidationFeatureCount: 1, - pEnabledValidationFeatures: &validation_enable, - }; - - debug - { - if (g_VLAYER_SUPPORT && g_DEBUG_PRINTF) - { - instance_info.pNext = &validation_features; - } - } - - VkResult result = vkCreateInstance(&instance_info, null, &vk.instance); - success = VkCheck("vkCreateInstance failure", result); - - return success; -} - -bool -InitSurface(Vulkan* vk) -{ - Push(vk, SI.Surface); - -version(linux) -{ - VkXcbSurfaceCreateInfoKHR surface_info = { - sType: VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, - connection: vk.window.conn, - window: vk.window.window, - }; - - VkResult result = vkCreateXcbSurfaceKHR(vk.instance, &surface_info, null, &vk.surface); -} - -version(Windows) -{ - VkWin32SurfaceCreateInfoKHR surface_info = { - sType: VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, - hinstance: vk.window.instance, - hwnd: vk.window.handle, - }; - - VkResult result = vkCreateWin32SurfaceKHR(vk.instance, &surface_info, null, &vk.surface); -} - - bool success = VkCheck("InitSurface failure", result); - - return success; -} - -void -EnableVLayers(Vulkan* vk) -{ - debug - { - Push(vk, SI.Debug); - - if (g_VLAYER_SUPPORT) - { - VkDebugUtilsMessengerCreateInfoEXT info = { - sType: VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, - messageSeverity: VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, - messageType: VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, - pfnUserCallback: cast(PFN_vkDebugUtilsMessengerCallbackEXT)&DebugCallback, - }; - - if (g_DEBUG_PRINTF) - { - info.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT; - } - - VkResult result = vkCreateDebugUtilsMessengerEXT(vk.instance, &info, null, &vk.dbg_msg); - if (result != VK_SUCCESS) - { - Logf("EnableVLayers failed to initialize, will continue without validation: %s", VkResultStr(result)); - } - } - else - { - Logf("EnableVLayers warning: Not supported on current device, continuing without"); - } - } -} - -void -PrintShaderDisassembly(Vulkan* vk, Pipeline pipeline_id, VkShaderStageFlagBits stage) -{ - version(AMD_GPU) - { - PipelineHandles* pipeline = vk.pipeline_handles.ptr + pipeline_id; - - debug - { - u64 size; - VkResult result = vkGetShaderInfoAMD(vk.device, pipeline.handle, stage, VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD, &size, null); - if (result == VK_SUCCESS) - { - u8[] buf = AllocArray!(u8)(&vk.frame_arenas[vk.frame_index], size); - vkGetShaderInfoAMD(vk.device, pipeline.handle, stage, VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD, &size, buf.ptr); - Logf("DISASSEMBLY:\n%r", buf); - } - } - } -} diff --git a/src/gears/vulkan_funcs.d b/src/gears/vulkan_funcs.d deleted file mode 100644 index acc0a42..0000000 --- a/src/gears/vulkan_funcs.d +++ /dev/null @@ -1,278 +0,0 @@ -public import includes; -import platform; -import vulkan : Vulkan, VULKAN_LIBS; - -@nogc: - -// Global Functions - -PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = null; -PFN_vkCreateInstance vkCreateInstance = null; -PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties = null; - -// Instance Functions - -PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices = null; -PFN_vkCreateDevice vkCreateDevice = null; -PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties = null; -PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR = null; -PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties = null; -PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2 = null; -PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties = null; -PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR = null; -PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR = null; -PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR = null; -PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties = null; -PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = null; -PFN_vkDestroyInstance vkDestroyInstance = null; -PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR = null; - -debug -{ - PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = null; - PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = null; -} - -// Platform Functions - -version(linux) -{ - PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR = null; -}; - -version(Windows) -{ - PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR = null; -}; - - -version(AMD_GPU) -{ - debug - { - PFN_vkGetShaderInfoAMD vkGetShaderInfoAMD = null; - } -} - - -// Device Functions - -PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = null; -PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass = null; -PFN_vkCmdEndRenderPass vkCmdEndRenderPass = null; -PFN_vkCreateFramebuffer vkCreateFramebuffer = null; -PFN_vkDestroyFramebuffer vkDestroyFramebuffer = null; -PFN_vkCreateRenderPass vkCreateRenderPass = null; -PFN_vkDestroyRenderPass vkDestroyRenderPass = null; -PFN_vkCreateImage vkCreateImage = null; -PFN_vkCreateImageView vkCreateImageView = null; -PFN_vkCreateBufferView vkCreateBufferView = null; -PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR = null; -PFN_vkGetDeviceQueue vkGetDeviceQueue = null; -PFN_vkCreateSemaphore vkCreateSemaphore = null; -PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers = null; -PFN_vkCreateCommandPool vkCreateCommandPool = null; -PFN_vkCreateFence vkCreateFence = null; -PFN_vkCreateDescriptorPool vkCreateDescriptorPool = null; -PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout = null; -PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets = null; -PFN_vkCreatePipelineLayout vkCreatePipelineLayout = null; -PFN_vkResetDescriptorPool vkResetDescriptorPool = null; -PFN_vkCreateShaderModule vkCreateShaderModule = null; -PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines = null; -PFN_vkCreateComputePipelines vkCreateComputePipelines = null; -PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets = null; -PFN_vkDestroyDevice vkDestroyDevice = null; -PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool = null; -PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR = null; -PFN_vkQueueSubmit2 vkQueueSubmit2 = null; -PFN_vkDestroyImage vkDestroyImage = null; -PFN_vkCmdBlitImage vkCmdBlitImage = null; -PFN_vkDestroyImageView vkDestroyImageView = null; -PFN_vkDestroyCommandPool vkDestroyCommandPool = null; -PFN_vkDestroySemaphore vkDestroySemaphore = null; -PFN_vkDestroyFence vkDestroyFence = null; -PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout = null; -PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier = null; -PFN_vkCmdPipelineBarrier2 vkCmdPipelineBarrier2 = null; -PFN_vkDestroyPipeline vkDestroyPipeline = null; -PFN_vkWaitForFences vkWaitForFences = null; -PFN_vkBeginCommandBuffer vkBeginCommandBuffer = null; -PFN_vkEndCommandBuffer vkEndCommandBuffer = null; -PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR = null; -PFN_vkCmdBindPipeline vkCmdBindPipeline = null; -PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets = null; -PFN_vkCmdDispatch vkCmdDispatch = null; -PFN_vkCmdSetViewport vkCmdSetViewport = null; -PFN_vkCmdSetScissor vkCmdSetScissor = null; -PFN_vkCmdPushConstants vkCmdPushConstants = null; -PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer = null; -PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers = null; -PFN_vkCmdDrawIndexed vkCmdDrawIndexed = null; -PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage = null; -PFN_vkCmdCopyBuffer vkCmdCopyBuffer = null; -PFN_vkResetFences vkResetFences = null; -PFN_vkResetCommandBuffer vkResetCommandBuffer = null; -PFN_vkFreeCommandBuffers vkFreeCommandBuffers = null; -PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout = null; -PFN_vkDestroyShaderModule vkDestroyShaderModule = null; -PFN_vkQueuePresentKHR vkQueuePresentKHR = null; -PFN_vkCmdDraw vkCmdDraw = null; -PFN_vkDeviceWaitIdle vkDeviceWaitIdle = null; -PFN_vkCmdClearColorImage vkCmdClearColorImage = null; -PFN_vkCreateSampler vkCreateSampler = null; -PFN_vkDestroySampler vkDestroySampler = null; -PFN_vkGetBufferDeviceAddress vkGetBufferDeviceAddress = null; -PFN_vkWaitSemaphores vkWaitSemaphores = null; -PFN_vkQueueWaitIdle vkQueueWaitIdle = null; - -bool -LoadGlobalFunctions() -{ - Library lib; - Function fn; - foreach(name; VULKAN_LIBS) - { - lib = LoadLibrary(name); - if (lib.ptr) - { - fn = LoadFunction(lib, "vkGetInstanceProcAddr"); - vkGetInstanceProcAddr = cast(PFN_vkGetInstanceProcAddr)fn.ptr; - } - } - - if (fn.ptr) - { - vkGetInstanceProcAddr = cast(PFN_vkGetInstanceProcAddr)vkGetInstanceProcAddr(null, "vkGetInstanceProcAddr"); - assert(vkGetInstanceProcAddr != null, "LoadGlobalFunctions failure: Unable to load vkGetInstanceProcAddr"); - - vkCreateInstance = cast(PFN_vkCreateInstance)vkGetInstanceProcAddr(null, "vkCreateInstance"); - assert(vkCreateInstance != null, "LoadGlobalFunctions failure: Unable to load VkCreateInstance"); - - vkEnumerateInstanceLayerProperties = cast(PFN_vkEnumerateInstanceLayerProperties)vkGetInstanceProcAddr(null, "vkEnumerateInstanceLayerProperties"); - assert(vkEnumerateInstanceLayerProperties != null, "LoadGlobalFunctions failure: Unable to load vkEnumerateInstanceLayerProperties"); - } - - return fn.ptr != null; -} - -void -LoadDeviceFunctions(Vulkan* vk) -{ - vkCreateSwapchainKHR = cast(PFN_vkCreateSwapchainKHR)vkGetDeviceProcAddr(vk.device, "vkCreateSwapchainKHR"); - vkCmdBeginRenderPass = cast(PFN_vkCmdBeginRenderPass)vkGetDeviceProcAddr(vk.device, "vkCmdBeginRenderPass"); - vkCmdEndRenderPass = cast(PFN_vkCmdEndRenderPass)vkGetDeviceProcAddr(vk.device, "vkCmdEndRenderPass"); - vkCreateFramebuffer = cast(PFN_vkCreateFramebuffer)vkGetDeviceProcAddr(vk.device, "vkCreateFramebuffer"); - vkDestroyFramebuffer = cast(PFN_vkDestroyFramebuffer)vkGetDeviceProcAddr(vk.device, "vkDestroyFramebuffer"); - vkCreateRenderPass = cast(PFN_vkCreateRenderPass)vkGetDeviceProcAddr(vk.device, "vkCreateRenderPass"); - vkDestroyRenderPass = cast(PFN_vkDestroyRenderPass)vkGetDeviceProcAddr(vk.device, "vkDestroyRenderPass"); - vkCreateImage = cast(PFN_vkCreateImage)vkGetDeviceProcAddr(vk.device, "vkCreateImage"); - vkCreateImageView = cast(PFN_vkCreateImageView)vkGetDeviceProcAddr(vk.device, "vkCreateImageView"); - vkQueueSubmit2 = cast(PFN_vkQueueSubmit2KHR)vkGetDeviceProcAddr(vk.device, "vkQueueSubmit2KHR"); - vkCreateBufferView = cast(PFN_vkCreateBufferView)vkGetDeviceProcAddr(vk.device, "vkCreateBufferView"); - vkGetSwapchainImagesKHR = cast(PFN_vkGetSwapchainImagesKHR)vkGetDeviceProcAddr(vk.device, "vkGetSwapchainImagesKHR"); - vkGetDeviceQueue = cast(PFN_vkGetDeviceQueue)vkGetDeviceProcAddr(vk.device, "vkGetDeviceQueue"); - vkCreateSemaphore = cast(PFN_vkCreateSemaphore)vkGetDeviceProcAddr(vk.device, "vkCreateSemaphore"); - vkAllocateCommandBuffers = cast(PFN_vkAllocateCommandBuffers)vkGetDeviceProcAddr(vk.device, "vkAllocateCommandBuffers"); - vkCreateCommandPool = cast(PFN_vkCreateCommandPool)vkGetDeviceProcAddr(vk.device, "vkCreateCommandPool"); - vkCmdPipelineBarrier = cast(PFN_vkCmdPipelineBarrier)vkGetDeviceProcAddr(vk.device, "vkCmdPipelineBarrier"); - vkCmdPipelineBarrier2 = cast(PFN_vkCmdPipelineBarrier2KHR)vkGetDeviceProcAddr(vk.device, "vkCmdPipelineBarrier2KHR"); - vkCreateFence = cast(PFN_vkCreateFence)vkGetDeviceProcAddr(vk.device, "vkCreateFence"); - vkCreateDescriptorPool = cast(PFN_vkCreateDescriptorPool)vkGetDeviceProcAddr(vk.device, "vkCreateDescriptorPool"); - vkCreateDescriptorSetLayout = cast(PFN_vkCreateDescriptorSetLayout)vkGetDeviceProcAddr(vk.device, "vkCreateDescriptorSetLayout"); - vkAllocateDescriptorSets = cast(PFN_vkAllocateDescriptorSets)vkGetDeviceProcAddr(vk.device, "vkAllocateDescriptorSets"); - vkCreatePipelineLayout = cast(PFN_vkCreatePipelineLayout)vkGetDeviceProcAddr(vk.device, "vkCreatePipelineLayout"); - vkResetDescriptorPool = cast(PFN_vkResetDescriptorPool)vkGetDeviceProcAddr(vk.device, "vkResetDescriptorPool"); - vkCreateShaderModule = cast(PFN_vkCreateShaderModule)vkGetDeviceProcAddr(vk.device, "vkCreateShaderModule"); - vkCreateGraphicsPipelines = cast(PFN_vkCreateGraphicsPipelines)vkGetDeviceProcAddr(vk.device, "vkCreateGraphicsPipelines"); - vkCreateComputePipelines = cast(PFN_vkCreateComputePipelines)vkGetDeviceProcAddr(vk.device, "vkCreateComputePipelines"); - vkUpdateDescriptorSets = cast(PFN_vkUpdateDescriptorSets)vkGetDeviceProcAddr(vk.device, "vkUpdateDescriptorSets"); - vkDestroyDevice = cast(PFN_vkDestroyDevice)vkGetDeviceProcAddr(vk.device, "vkDestroyDevice"); - vkDestroyDescriptorPool = cast(PFN_vkDestroyDescriptorPool)vkGetDeviceProcAddr(vk.device, "vkDestroyDescriptorPool"); - vkDestroySwapchainKHR = cast(PFN_vkDestroySwapchainKHR)vkGetDeviceProcAddr(vk.device, "vkDestroySwapchainKHR"); - vkDestroyImage = cast(PFN_vkDestroyImage)vkGetDeviceProcAddr(vk.device, "vkDestroyImage"); - vkDestroyImageView = cast(PFN_vkDestroyImageView)vkGetDeviceProcAddr(vk.device, "vkDestroyImageView"); - vkDestroyCommandPool = cast(PFN_vkDestroyCommandPool)vkGetDeviceProcAddr(vk.device, "vkDestroyCommandPool"); - vkDestroySemaphore = cast(PFN_vkDestroySemaphore)vkGetDeviceProcAddr(vk.device, "vkDestroySemaphore"); - vkDestroyFence = cast(PFN_vkDestroyFence)vkGetDeviceProcAddr(vk.device, "vkDestroyFence"); - vkDestroyPipelineLayout = cast(PFN_vkDestroyPipelineLayout)vkGetDeviceProcAddr(vk.device, "vkDestroyPipelineLayout"); - vkDestroyPipeline = cast(PFN_vkDestroyPipeline)vkGetDeviceProcAddr(vk.device, "vkDestroyPipeline"); - vkWaitForFences = cast(PFN_vkWaitForFences)vkGetDeviceProcAddr(vk.device, "vkWaitForFences"); - vkBeginCommandBuffer = cast(PFN_vkBeginCommandBuffer)vkGetDeviceProcAddr(vk.device, "vkBeginCommandBuffer"); - vkEndCommandBuffer = cast(PFN_vkEndCommandBuffer)vkGetDeviceProcAddr(vk.device, "vkEndCommandBuffer"); - vkAcquireNextImageKHR = cast(PFN_vkAcquireNextImageKHR)vkGetDeviceProcAddr(vk.device, "vkAcquireNextImageKHR"); - vkCmdBindPipeline = cast(PFN_vkCmdBindPipeline)vkGetDeviceProcAddr(vk.device, "vkCmdBindPipeline"); - vkCmdBindDescriptorSets = cast(PFN_vkCmdBindDescriptorSets)vkGetDeviceProcAddr(vk.device, "vkCmdBindDescriptorSets"); - vkCmdDispatch = cast(PFN_vkCmdDispatch)vkGetDeviceProcAddr(vk.device, "vkCmdDispatch"); - vkCmdSetViewport = cast(PFN_vkCmdSetViewport)vkGetDeviceProcAddr(vk.device, "vkCmdSetViewport"); - vkCmdSetScissor = cast(PFN_vkCmdSetScissor)vkGetDeviceProcAddr(vk.device, "vkCmdSetScissor"); - vkCmdPushConstants = cast(PFN_vkCmdPushConstants)vkGetDeviceProcAddr(vk.device, "vkCmdPushConstants"); - vkCmdBindIndexBuffer = cast(PFN_vkCmdBindIndexBuffer)vkGetDeviceProcAddr(vk.device, "vkCmdBindIndexBuffer"); - vkCmdBindVertexBuffers = cast(PFN_vkCmdBindVertexBuffers)vkGetDeviceProcAddr(vk.device, "vkCmdBindVertexBuffers"); - vkCmdDrawIndexed = cast(PFN_vkCmdDrawIndexed)vkGetDeviceProcAddr(vk.device, "vkCmdDrawIndexed"); - vkCmdBlitImage = cast(PFN_vkCmdBlitImage)vkGetDeviceProcAddr(vk.device, "vkCmdBlitImage"); - vkCmdCopyBufferToImage = cast(PFN_vkCmdCopyBufferToImage)vkGetDeviceProcAddr(vk.device, "vkCmdCopyBufferToImage"); - vkCmdCopyBuffer = cast(PFN_vkCmdCopyBuffer)vkGetDeviceProcAddr(vk.device, "vkCmdCopyBuffer"); - vkResetFences = cast(PFN_vkResetFences)vkGetDeviceProcAddr(vk.device, "vkResetFences"); - vkResetCommandBuffer = cast(PFN_vkResetCommandBuffer)vkGetDeviceProcAddr(vk.device, "vkResetCommandBuffer"); - vkFreeCommandBuffers = cast(PFN_vkFreeCommandBuffers)vkGetDeviceProcAddr(vk.device, "vkFreeCommandBuffers"); - vkDestroyDescriptorSetLayout = cast(PFN_vkDestroyDescriptorSetLayout)vkGetDeviceProcAddr(vk.device, "vkDestroyDescriptorSetLayout"); - vkDestroyShaderModule = cast(PFN_vkDestroyShaderModule)vkGetDeviceProcAddr(vk.device, "vkDestroyShaderModule"); - vkQueuePresentKHR = cast(PFN_vkQueuePresentKHR)vkGetDeviceProcAddr(vk.device, "vkQueuePresentKHR"); - vkCmdDraw = cast(PFN_vkCmdDraw)vkGetDeviceProcAddr(vk.device, "vkCmdDraw"); - vkDeviceWaitIdle = cast(PFN_vkDeviceWaitIdle)vkGetDeviceProcAddr(vk.device, "vkDeviceWaitIdle"); - vkCmdClearColorImage = cast(PFN_vkCmdClearColorImage)vkGetDeviceProcAddr(vk.device, "vkCmdClearColorImage"); - vkCreateSampler = cast(PFN_vkCreateSampler)vkGetDeviceProcAddr(vk.device, "vkCreateSampler"); - vkDestroySampler = cast(PFN_vkDestroySampler)vkGetDeviceProcAddr(vk.device, "vkDestroySampler"); - vkGetBufferDeviceAddress = cast(PFN_vkGetBufferDeviceAddress)vkGetDeviceProcAddr(vk.device, "vkGetBufferDeviceAddress"); - vkWaitSemaphores = cast(PFN_vkWaitSemaphores)vkGetDeviceProcAddr(vk.device, "vkWaitSemaphores"); - vkQueueWaitIdle = cast(PFN_vkQueueWaitIdle)vkGetDeviceProcAddr(vk.device, "vkQueueWaitIdle"); - - version(AMD_GPU) - { - debug - { - vkGetShaderInfoAMD = cast(PFN_vkGetShaderInfoAMD)vkGetDeviceProcAddr(vk.device, "vkGetShaderInfoAMD"); - assert(vkGetShaderInfoAMD != null, "vkGetShaderInfoAMD pointer is null"); - } - } - - assert(vkCreateSwapchainKHR != null, "LoadDeviceFunctions failure: function pointer is null"); -} - -void -LoadInstanceFunctions(Vulkan* vk) -{ - vkEnumeratePhysicalDevices = cast(PFN_vkEnumeratePhysicalDevices)vkGetInstanceProcAddr(vk.instance, "vkEnumeratePhysicalDevices"); - vkDestroySurfaceKHR = cast(PFN_vkDestroySurfaceKHR)vkGetInstanceProcAddr(vk.instance, "vkDestroySurfaceKHR"); - vkDestroyInstance = cast(PFN_vkDestroyInstance)vkGetInstanceProcAddr(vk.instance, "vkDestroyInstance"); - vkCreateDevice = cast(PFN_vkCreateDevice)vkGetInstanceProcAddr(vk.instance, "vkCreateDevice"); - vkGetPhysicalDeviceQueueFamilyProperties = cast(PFN_vkGetPhysicalDeviceQueueFamilyProperties)vkGetInstanceProcAddr(vk.instance, "vkGetPhysicalDeviceQueueFamilyProperties"); - vkGetPhysicalDeviceSurfaceSupportKHR = cast(PFN_vkGetPhysicalDeviceSurfaceSupportKHR)vkGetInstanceProcAddr(vk.instance, "vkGetPhysicalDeviceSurfaceSupportKHR"); - vkGetPhysicalDeviceProperties = cast(PFN_vkGetPhysicalDeviceProperties)vkGetInstanceProcAddr(vk.instance, "vkGetPhysicalDeviceProperties"); - vkGetPhysicalDeviceFeatures2 = cast(PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(vk.instance, "vkGetPhysicalDeviceFeatures2"); - vkEnumerateDeviceExtensionProperties = cast(PFN_vkEnumerateDeviceExtensionProperties)vkGetInstanceProcAddr(vk.instance, "vkEnumerateDeviceExtensionProperties"); - vkGetPhysicalDeviceSurfacePresentModesKHR = cast(PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)vkGetInstanceProcAddr(vk.instance, "vkGetPhysicalDeviceSurfacePresentModesKHR"); - vkGetPhysicalDeviceSurfaceFormatsKHR = cast(PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)vkGetInstanceProcAddr(vk.instance, "vkGetPhysicalDeviceSurfaceFormatsKHR"); - vkGetPhysicalDeviceSurfaceCapabilitiesKHR = cast(PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)vkGetInstanceProcAddr(vk.instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); - vkGetPhysicalDeviceImageFormatProperties = cast(PFN_vkGetPhysicalDeviceImageFormatProperties)vkGetInstanceProcAddr(vk.instance, "vkGetPhysicalDeviceImageFormatProperties"); - vkGetDeviceProcAddr = cast(PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr(vk.instance, "vkGetDeviceProcAddr"); - -version(linux) -{ - vkCreateXcbSurfaceKHR = cast(PFN_vkCreateXcbSurfaceKHR)vkGetInstanceProcAddr(vk.instance, "vkCreateXcbSurfaceKHR"); -} - -version(Windows) -{ - vkCreateWin32SurfaceKHR = cast(PFN_vkCreateWin32SurfaceKHR)vkGetInstanceProcAddr(vk.instance, "vkCreateWin32SurfaceKHR"); -} - -debug -{ - vkCreateDebugUtilsMessengerEXT = cast(PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(vk.instance, "vkCreateDebugUtilsMessengerEXT"); - vkDestroyDebugUtilsMessengerEXT = cast(PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(vk.instance, "vkDestroyDebugUtilsMessengerEXT"); -} - - assert(vkEnumeratePhysicalDevices != null, "LoadInstanceFunctions failure: failed to load function"); -} diff --git a/src/gears/vulkan_logging.d b/src/gears/vulkan_logging.d deleted file mode 100644 index 2accfc5..0000000 --- a/src/gears/vulkan_logging.d +++ /dev/null @@ -1,166 +0,0 @@ -public import includes; -import std.stdio; -import vulkan : Vulkan; -import std.conv; -import std.string; -import core.stdc.string : strlen, strcmp; - -extern(System) VkBool32 -DebugCallback( - VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, - VkDebugUtilsMessageTypeFlagsEXT message_type, - const VkDebugUtilsMessengerCallbackDataEXT* callback_data, - void* user_data -) -{ - string ms, mt; - - const(char)[] msg = callback_data.pMessage[0 .. strlen(callback_data.pMessage)]; - bool debug_printf = strcmp(callback_data.pMessageIdName, "WARNING-DEBUG-PRINTF") == 0; - - switch (message_severity) { - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: - ms = "VERBOSE"; - break; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: - ms = "INFO"; - break; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: - ms = "WARNING"; - break; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: - ms = "ERROR"; - break; - default: - ms = "UNKNOWN"; - break; - } - - switch (message_type) { - case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT: - mt = "General"; - break; - case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT: - mt = "Validation"; - break; - case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT: - mt = "Validation | General"; - break; - case VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT: - mt = "Performance"; - break; - case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT: - mt = "General | Performance"; - break; - case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT: - mt = "Validation | Performance"; - break; - case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT: - mt = "General | Validation | Performance"; - break; - default: - mt = "Unknown"; - break; - } - - if (debug_printf) - { - writefln("SHADER PRINT: %s", msg); - } - else - { - writefln("[%s: %s]\n%r\n", ms, mt, msg); - } - - return VK_FALSE; -} - -string -VkResultStr(VkResult result) -{ - switch (result) - { - case VK_SUCCESS: - return "VK_SUCCESS"; - case VK_NOT_READY: - return "VK_NOT_READY"; - case VK_TIMEOUT: - return "VK_TIMEOUT"; - case VK_EVENT_SET: - return "VK_EVENT_SET"; - case VK_EVENT_RESET: - return "VK_EVENT_RESET"; - case VK_INCOMPLETE: - return "VK_INCOMPLETE"; - case VK_ERROR_OUT_OF_HOST_MEMORY: - return "VK_ERROR_OUT_OF_HOST_MEMORY"; - case VK_ERROR_OUT_OF_DEVICE_MEMORY: - return "VK_ERROR_OUT_OF_DEVICE_MEMORY"; - case VK_ERROR_INITIALIZATION_FAILED: - return "VK_ERROR_INITIALIZATION_FAILED"; - case VK_ERROR_DEVICE_LOST: - return "VK_ERROR_DEVICE_LOST"; - case VK_ERROR_MEMORY_MAP_FAILED: - return "VK_ERROR_MEMORY_MAP_FAILED"; - case VK_ERROR_LAYER_NOT_PRESENT: - return "VK_ERROR_LAYER_NOT_PRESENT"; - case VK_ERROR_EXTENSION_NOT_PRESENT: - return "VK_ERROR_EXTENSION_NOT_PRESENT"; - case VK_ERROR_FEATURE_NOT_PRESENT: - return "VK_ERROR_FEATURE_NOT_PRESENT"; - case VK_ERROR_INCOMPATIBLE_DRIVER: - return "VK_ERROR_INCOMPATIBLE_DRIVER"; - case VK_ERROR_TOO_MANY_OBJECTS: - return "VK_ERROR_TOO_MANY_OBJECTS"; - case VK_ERROR_FORMAT_NOT_SUPPORTED: - return "VK_ERROR_FORMAT_NOT_SUPPORTED"; - case VK_ERROR_FRAGMENTED_POOL: - return "VK_ERROR_FRAGMENTED_POOL"; - case VK_ERROR_UNKNOWN: - return "VK_ERROR_UNKNOWN"; - case VK_ERROR_OUT_OF_POOL_MEMORY: - return "VK_ERROR_OUT_OF_POOL_MEMORY"; - case VK_ERROR_INVALID_EXTERNAL_HANDLE: - return "VK_ERROR_INVALID_EXTERNAL_HANDLE"; - case VK_ERROR_FRAGMENTATION: - return "VK_ERROR_FRAGMENTATION"; - case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS: - return "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS"; - case VK_PIPELINE_COMPILE_REQUIRED: - return "VK_PIPELINE_COMPILE_REQUIRED"; - case VK_ERROR_SURFACE_LOST_KHR: - return "VK_ERROR_SURFACE_LOST_KHR"; - case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: - return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"; - case VK_SUBOPTIMAL_KHR: - return "VK_SUBOPTIMAL_KHR"; - case VK_ERROR_OUT_OF_DATE_KHR: - return "VK_ERROR_OUT_OF_DATE_KHR"; - case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: - return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR"; - case VK_ERROR_VALIDATION_FAILED_EXT: - return "VK_ERROR_VALIDATION_FAILED_EXT"; - case VK_ERROR_INVALID_SHADER_NV: - return "VK_ERROR_INVALID_SHADER_NV"; - case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT: - return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT"; - case VK_ERROR_NOT_PERMITTED_KHR: - return "VK_ERROR_NOT_PERMITTED_KHR"; - case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: - return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT"; - case VK_THREAD_IDLE_KHR: - return "VK_THREAD_IDLE_KHR"; - case VK_THREAD_DONE_KHR: - return "VK_THREAD_DONE_KHR"; - case VK_OPERATION_DEFERRED_KHR: - return "VK_OPERATION_DEFERRED_KHR"; - case VK_OPERATION_NOT_DEFERRED_KHR: - return "VK_OPERATION_NOT_DEFERRED_KHR"; - case VK_ERROR_COMPRESSION_EXHAUSTED_EXT: - return "VK_ERROR_COMPRESSION_EXHAUSTED_EXT"; - case VK_RESULT_MAX_ENUM: - return "VK_RESULT_MAX_ENUM"; - default: - return "UNKNOWN"; - } -} diff --git a/src/shared/util.d b/src/shared/util.d index 374755f..104029a 100644 --- a/src/shared/util.d +++ b/src/shared/util.d @@ -7,7 +7,7 @@ import alloc; import core.simd; import std.conv; import std.string; - + j struct DynSlice(T) { T[][] slices;