diff --git a/vulkan/convert.comp.glsl b/vulkan/convert.comp.glsl index 5811268..e041ad0 100644 --- a/vulkan/convert.comp.glsl +++ b/vulkan/convert.comp.glsl @@ -2,23 +2,23 @@ #extension GL_EXT_shader_8bit_storage : require -layout (local_size_x = 32, local_size_y = 32) in; - layout (constant_id = 0) const int CHANNELS = 3; -layout (push_constant) uniform Constants -{ +layout (local_size_x = 32, local_size_y = 32) in; + +layout (push_constant) uniform Constants { uint x; uint y; } PC; -layout (set = 0, binding = 0, rgba32f) uniform image2D dst; +layout (set = 1, binding = 0, rgba32f) uniform image2D dst; -layout (set = 0, binding = 1) buffer input_array +layout (set = 1, binding = 1) buffer input_array { uint8_t src[]; }; + void main() { uint x = gl_GlobalInvocationID.x; @@ -33,23 +33,23 @@ void main() { uint index = x + y * PC.x; - vec4 col = vec4(vec3(uint(src[index]) / 255.0), 1.0); + vec4 col = vec4(vec3(uint(src[index]) / 255.0), 1.0); imageStore(dst, ivec2(x, y), col); } else if(CHANNELS == 2) { uint index = (x + y * PC.x) * 2; - float f = uint(src[index]) / 255.0; - float a = uint(src[index+1]) / 255.0; - vec4 col = vec4(f, f, f, a); + float f = uint(src[index]) / 255.0; + float a = uint(src[index+1]) / 255.0; + vec4 col = vec4(f, f, f, a); imageStore(dst, ivec2(x, y), col); } else if(CHANNELS == 3) { uint index = (x + y * PC.x) * 3; - vec4 col = vec4(uint(src[index]) / 255.0, uint(src[index+1]) / 255.0, uint(src[index+2]) / 255.0, 1.0); + vec4 col = vec4(uint(src[index]) / 255.0, uint(src[index+1]) / 255.0, uint(src[index+2]) / 255.0, 1.0); imageStore(dst, ivec2(x, y), col); } } diff --git a/vulkan/vulkan.d b/vulkan/vulkan.d index de85623..588c5ec 100644 --- a/vulkan/vulkan.d +++ b/vulkan/vulkan.d @@ -493,12 +493,12 @@ struct Vulkan bool recreate_swapchain; VkRenderPass render_pass; - VkFramebuffer[] framebuffers; - u32 image_index; + VkFramebuffer framebuffer; Descriptor[] present_images; - Descriptor depth_image; - Format present_image_format; + u32 image_index; + Descriptor draw_image; + Descriptor depth_image; VkCommandPool[FRAME_OVERLAP] cmd_pools; VkCommandBuffer[FRAME_OVERLAP] cmds; @@ -541,19 +541,77 @@ struct Vulkan f32[4] color_clear; f32[4] depth_clear; - @property VkCommandPool cmd_pool() => this.cmd_pools[this.frame_index]; - @property VkCommandBuffer cmd() => this.cmds[this.frame_index]; - @property VkSemaphore acquire_sem() => this.acquire_sems[this.frame_index]; - @property VkSemaphore* acquire_sem_ptr() => this.acquire_sems.ptr + this.frame_index; - @property VkFence render_fence() => this.render_fences[this.frame_index]; - @property VkFence* render_fence_ptr() => this.render_fences.ptr + this.frame_index; - @property VkPipeline last_pipeline() => this.last_pipelines[this.frame_index]; - @property VkPipeline last_pipeline(VkPipeline pipeline) => this.last_pipelines[this.frame_index] = pipeline; - @property VkSemaphore submit_sem() => this.submit_sems[this.image_index]; - @property ref Descriptor present_image() => this.present_images[this.image_index]; - @property Descriptor* present_image_ptr() => this.present_images.ptr + this.image_index; - @property VkFramebuffer framebuffer() => this.framebuffers[this.image_index]; - @property Arena* frame_arena() => &this.frame_arenas[this.frame_index]; + @property VkCommandPool + cmd_pool() + { + return this.cmd_pools[this.frame_index]; + } + + @property VkCommandBuffer + cmd() + { + return this.cmds[this.frame_index]; + } + + @property VkSemaphore + acquire_sem() + { + return this.acquire_sems[this.frame_index]; + } + + @property VkSemaphore* + acquire_sem_ptr() + { + return this.acquire_sems.ptr + this.frame_index; + } + + @property VkFence + render_fence() + { + return this.render_fences[this.frame_index]; + } + + @property VkFence* + render_fence_ptr() + { + return this.render_fences.ptr + this.frame_index; + } + + @property VkPipeline + last_pipeline() + { + return this.last_pipelines[this.frame_index]; + } + + @property VkPipeline + last_pipeline(VkPipeline pipeline) + { + return this.last_pipelines[this.frame_index] = pipeline; + } + + @property VkSemaphore + submit_sem() + { + return this.submit_sems[this.image_index]; + } + + @property ref Descriptor + present_image() + { + return this.present_images[this.image_index]; + } + + @property Descriptor* + present_image_ptr() + { + return this.present_images.ptr + this.image_index; + } + + Arena* + FrameArena() + { + return &this.frame_arenas[this.frame_index]; + } alias queues this; } @@ -635,17 +693,23 @@ CreatePipelineLayout(T)(T layouts, u32 push_const_size, bool compute = false) if { VkShaderStageFlagBits stage = (compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); - u32 desc_layouts_length = 1; - DescSetLayout* desc_layouts; + DescSetLayout[] desc_layouts; static if(is(T: DescSetLayout)) { - desc_layouts = &layouts; + desc_layouts = Alloc!(DescSetLayout)(g_vk.FrameArena(), 2); + desc_layouts[0] = g_vk.global_set_layout; + desc_layouts[1] = layouts; } else static if(is(T: DescSetLayout[])) { - desc_layouts_length = cast(u32)layouts.length; - desc_layouts = layouts.ptr; + desc_layouts = Alloc!(DescSetLayout)(g_vk.FrameArena(), layouts.length + 1); + desc_layouts[0] = g_vk.global_set_layout; + + foreach(i; 0 .. layouts.length) + { + desc_layouts[i+1] = layouts[i]; + } } VkPushConstantRange const_range = { @@ -656,8 +720,8 @@ CreatePipelineLayout(T)(T layouts, u32 push_const_size, bool compute = false) if VkPipelineLayoutCreateInfo layout_info = { sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - setLayoutCount: desc_layouts_length, - pSetLayouts: desc_layouts, + 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), }; @@ -767,7 +831,7 @@ BeginFrame() result = vkResetFences(g_vk.device, 1, g_vk.render_fence_ptr); VkCheckA("BeginFrame failure: vkResetFences error", result); - Reset(g_vk.frame_arena); + Reset(g_vk.FrameArena()); // ?? dont know why this is 3 (should have commented it) for(u64 i = 0; i < 3; i += 1) @@ -816,9 +880,11 @@ SetClearColors(f32[4] color_clear, f32[4] depth_clear) void BeginRendering() { - Transition(g_vk.cmd, g_vk.present_image_ptr, IL.ColorAttach); + Transition(g_vk.cmd, &g_vk.draw_image, IL.ColorAttach); Transition(g_vk.cmd, &g_vk.depth_image, IL.DepthAttach); + Transition(g_vk.cmd, g_vk.present_image_ptr, IL.TransferDst); + VkClearValue[2] clear_color = [ { color: { float32: g_vk.color_clear } }, { color: { float32: g_vk.depth_clear } }, @@ -856,21 +922,9 @@ GetAspect() } void -PrepComputeImage(Descriptor* descriptor) +PrepComputeDrawImage() { - Transition(g_vk.cmd, descriptor, IL.General); -} - -void -CopyToPresentImage(Descriptor* descriptor, UVec2 extent) -{ - Transition(g_vk.cmd, descriptor, IL.TransferSrc); - Transition(g_vk.cmd, g_vk.present_image_ptr, IL.TransferDst); - - VkExtent2D src_extent = { width: extent.x, height: extent.y }; - VkExtent2D dst_extent = { width: g_vk.swapchain_extent.width, height: g_vk.swapchain_extent.height }; - - Copy(g_vk.cmd, descriptor, g_vk.present_image_ptr, src_extent, dst_extent); + Transition(g_vk.cmd, &g_vk.draw_image, IL.General); } void @@ -882,10 +936,27 @@ FinishRendering() void SubmitAndPresent() { + scope(exit) + { + g_vk.last_pipeline = null; + g_vk.frame_index = (g_vk.frame_index + 1) % FRAME_OVERLAP; + } + + VkImage image = g_vk.present_image.image.image; VkSemaphore acquire_sem = g_vk.acquire_sem; VkSemaphore submit_sem = g_vk.submit_sem; - Transition(g_vk.cmd, g_vk.present_image_ptr, IL.PresentSrc); + Transition(g_vk.cmd, &g_vk.draw_image, IL.TransferSrc); + + VkExtent2D extent = { + width: g_vk.swapchain_extent.width, + height: g_vk.swapchain_extent.height, + }; + + // TODO: Find out how to copy from same dimension images (pretty sure its not blitting) + Copy(g_vk.cmd, &g_vk.draw_image, image, IL.TransferDst, extent, extent); + + Transition(g_vk.cmd, image, IL.TransferDst, IL.PresentSrc); VkResult result = vkEndCommandBuffer(g_vk.cmd); VkCheckA("FinishFrame failure: vkEndCommandBuffer error", result); @@ -945,9 +1016,6 @@ SubmitAndPresent() { g_vk.frame_started = false; } - - g_vk.last_pipeline = null; - g_vk.frame_index = (g_vk.frame_index + 1) % FRAME_OVERLAP; } void @@ -1517,7 +1585,7 @@ Bind(Pipeline pipeline_handle, DescSet[] sets, bool compute = false) u32[] offsets; if(g_vk.global_set.dynamic_count > 0) { - offsets = Alloc!(u32)(g_vk.frame_arena, g_vk.global_set.dynamic_count); + offsets = Alloc!(u32)(g_vk.FrameArena(), g_vk.global_set.dynamic_count); } vkCmdBindDescriptorSets( @@ -1532,7 +1600,7 @@ Bind(Pipeline pipeline_handle, DescSet[] sets, bool compute = false) ); u32 offset_count; - VkDescriptorSet[] handles = Alloc!(VkDescriptorSet)(g_vk.frame_arena, sets.length); + VkDescriptorSet[] handles = Alloc!(VkDescriptorSet)(g_vk.FrameArena(), sets.length); foreach(i, set; sets) { @@ -1542,7 +1610,7 @@ Bind(Pipeline pipeline_handle, DescSet[] sets, bool compute = false) if(offset_count > 0) { - offsets = Alloc!(u32)(g_vk.frame_arena, offset_count); + offsets = Alloc!(u32)(g_vk.FrameArena(), offset_count); } vkCmdBindDescriptorSets( @@ -1579,7 +1647,7 @@ Bind(Pipeline pipeline_handle, DescSet set, bool compute = false) u32[] offsets; if(g_vk.global_set.dynamic_count > 0) { - offsets = Alloc!(u32)(g_vk.frame_arena, g_vk.global_set.dynamic_count); + offsets = Alloc!(u32)(g_vk.FrameArena(), g_vk.global_set.dynamic_count); } vkCmdBindDescriptorSets( @@ -1595,7 +1663,7 @@ Bind(Pipeline pipeline_handle, DescSet set, bool compute = false) if(set.dynamic_count > 0) { - offsets = Alloc!(u32)(g_vk.frame_arena, set.dynamic_count); + offsets = Alloc!(u32)(g_vk.FrameArena(), set.dynamic_count); } vkCmdBindDescriptorSets( @@ -1788,7 +1856,7 @@ CreateGraphicsPipeline(Pipeline* pipeline_handle, GfxPipelineInfo* build_info) VkPipelineRenderingCreateInfo rendering_info = { sType: VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, colorAttachmentCount: 1, - pColorAttachmentFormats: cast(VkFormat*)&g_vk.present_image_format, + pColorAttachmentFormats: cast(VkFormat*)&g_vk.draw_image.image.format, depthAttachmentFormat: g_vk.depth_image.image.format, }; @@ -1986,8 +2054,8 @@ ClearDepth(f32[4] color = [0.0, 0.0, 0.0, 0.0]) void ClearColor(f32[4] color) { - Transition(g_vk.cmd, g_vk.present_image_ptr, IL.TransferDst); - ClearColor(g_vk.present_image_ptr, color); + Transition(g_vk.cmd, &g_vk.draw_image, IL.TransferDst); + ClearColor(&g_vk.draw_image, color); } void @@ -2085,7 +2153,7 @@ PushDescriptorPool() void PrepareWrite(VkWriteDescriptorSet* write, DescSet set, Descriptor* desc) { - Arena* arena = g_vk.frame_arena; + Arena* arena = g_vk.FrameArena(); write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write.descriptorType = desc.type; @@ -2131,7 +2199,7 @@ PrepareWrite(VkWriteDescriptorSet* write, DescSet set, Descriptor* desc) void Write(DescSet set, Descriptor[] descs) { - Arena* arena = g_vk.frame_arena; + Arena* arena = g_vk.FrameArena(); VkWriteDescriptorSet[] writes = Alloc!(VkWriteDescriptorSet)(arena, descs.length); @@ -2351,12 +2419,13 @@ CreateSampler(Descriptor* desc, DescInfo* info) void CreateDrawImages() { - g_vk.present_image_format = cast(Format)GetDrawImageFormat(); - Format depth_format = cast(Format)VK_FORMAT_D32_SFLOAT; + Format draw_format = cast(Format)GetDrawImageFormat(); + Format depth_format = cast(Format)VK_FORMAT_D32_SFLOAT; u32 w = g_vk.swapchain_extent.width; u32 h = g_vk.swapchain_extent.height; + CreateDescriptor(&g_vk.draw_image, DescInfo(type: DT.StorageImage, format: draw_format, usage: IU.Draw, w: w, h: h, binding: 0)); CreateDescriptor(&g_vk.depth_image, DescInfo(type: DT.Image, format: depth_format, usage: IU.Depth, w: w, h: h, binding: 0)); } @@ -2364,7 +2433,7 @@ bool CreateSwapchain() { bool success = true; - Arena* arena = g_vk.frame_arena; + Arena* arena = g_vk.FrameArena(); VkSurfaceCapabilitiesKHR cap; vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_vk.physical_device, g_vk.surface, &cap); @@ -2458,37 +2527,33 @@ RecreateSwapchain() vkDeviceWaitIdle(g_vk.device); Destroy(g_vk.swapchain, g_vk.present_images, g_vk.device); + Destroy(&g_vk.draw_image); Destroy(&g_vk.depth_image); - foreach(i; 0 .. g_vk.framebuffers.length) - { - vkDestroyFramebuffer(g_vk.device, g_vk.framebuffers[i], null); - } + vkDestroyFramebuffer(g_vk.device, g_vk.framebuffer, null); CreateSwapchain(); CreateDrawImages(); - CreateFramebuffers(); + Write(g_vk.global_set, &g_vk.draw_image); + CreateFramebuffer(); g_vk.recreate_swapchain = false; } void -CreateFramebuffers() +CreateFramebuffer() { - foreach(i; 0 .. g_vk.framebuffers.length) - { - VkFramebufferCreateInfo framebuffer_info = { - sType: VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - renderPass: g_vk.render_pass, - attachmentCount: 2, - pAttachments: [g_vk.present_images[i].image.view, g_vk.depth_image.image.view], - width: g_vk.swapchain_extent.width, - height: g_vk.swapchain_extent.height, - layers: 1, - }; + VkFramebufferCreateInfo framebuffer_info = { + sType: VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + renderPass: g_vk.render_pass, + attachmentCount: 2, + pAttachments: [g_vk.draw_image.image.view, g_vk.depth_image.image.view], + width: g_vk.swapchain_extent.width, + height: g_vk.swapchain_extent.height, + layers: 1, + }; - VkResult result = vkCreateFramebuffer(g_vk.device, &framebuffer_info, null, &g_vk.framebuffers[i]); - VkCheckA("vkCreateFramebuffer failure", result); - } + VkResult result = vkCreateFramebuffer(g_vk.device, &framebuffer_info, null, &g_vk.framebuffer); + VkCheckA("vkCreateFramebuffer failure", result); } void @@ -2616,7 +2681,7 @@ PrintShaderDisassembly(Pipeline pipeline_id, VkShaderStageFlagBits stage) VkResult result = vkGetShaderInfoAMD(g_vk.device, pipeline.handle, stage, VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD, &size, null); if(result == VK_SUCCESS) { - u8[] buf = Alloc!(u8)(g_vk.frame_arena, size); + u8[] buf = Alloc!(u8)(g_vk.FrameArena(), size); vkGetShaderInfoAMD(g_vk.device, pipeline.handle, stage, VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD, &size, buf.ptr); Logf("DISASSEMBLY:\n%r", buf); } @@ -3288,8 +3353,24 @@ Init(VulkanBuildInfo build_info, u64 permanent_mem, u64 frame_mem) if(success) { - PushDescriptorPool(); + PushDescriptorPool(); + 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 }, + ]; + + g_vk.global_set_layout = CreateDescSetLayout(layout_bindings); + g_vk.global_set = AllocDescSet(g_vk.global_set_layout); + + Write(g_vk.global_set, [g_vk.draw_image]); + } + } + + if(success) + { g_vk.pipeline_handles = Alloc!(PipelineHandles)(&g_vk.arena, 128); g_vk.pipeline_count += 1; @@ -3297,15 +3378,15 @@ Init(VulkanBuildInfo build_info, u64 permanent_mem, u64 frame_mem) g_vk.transfer_buf = CreateMappedBuffer!(u8)(BT.Staging, transfer_size); VkDescriptorSetLayoutBinding[2] layout_bindings = [ - { binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_COMPUTE_BIT }, + { 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 }, ]; - g_vk.conv_desc_layout = CreateDescSetLayout(layout_bindings); - g_vk.conv_desc_set = AllocDescSet(g_vk.conv_desc_layout); + g_vk.conv_desc_layout = CreateDescSetLayout(layout_bindings); + g_vk.conv_desc_set = AllocDescSet(g_vk.conv_desc_layout); g_vk.conv_pipeline_layout = CreatePipelineLayout(g_vk.conv_desc_layout, ConvPushConst.sizeof, true); - u32 channels; + u32 channels = 1; SpecEntry[1] entries = [ { constantID: 0, @@ -3324,19 +3405,18 @@ Init(VulkanBuildInfo build_info, u64 permanent_mem, u64 frame_mem) }, }; - channels = 1; - g_vk.r_to_rgba_pipeline = CreateComputePipeline(&conv_info); + g_vk.r_to_rgba_pipeline = CreateComputePipeline(&conv_info); - channels = 2; - g_vk.rg_to_rgba_pipeline = CreateComputePipeline(&conv_info); + channels = 2; + g_vk.rg_to_rgba_pipeline = CreateComputePipeline(&conv_info); - channels = 3; + channels = 3; g_vk.rgb_to_rgba_pipeline = CreateComputePipeline(&conv_info); VkAttachmentDescription[2] attach_descriptions = [ { - format: g_vk.present_image_format, + format: g_vk.draw_image.image.format, samples: VK_SAMPLE_COUNT_1_BIT, loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR, storeOp: VK_ATTACHMENT_STORE_OP_STORE, @@ -3395,9 +3475,7 @@ Init(VulkanBuildInfo build_info, u64 permanent_mem, u64 frame_mem) VkResult result = vkCreateRenderPass(g_vk.device, &pass_info, null, &g_vk.render_pass); VkCheckA("vkCreateRenderPass failure", result); - g_vk.framebuffers = Alloc!(VkFramebuffer)(&g_vk.arena, g_vk.present_images.length); - - CreateFramebuffers(); + CreateFramebuffer(); } assert(success, "Error initializing vulkan");