Mercurial > games > semicongine
changeset 1167:cdf7ec8d04d2
add: MSAA, yipieee
author | sam <sam@basx.dev> |
---|---|
date | Tue, 25 Jun 2024 20:24:38 +0700 |
parents | 92691ddcb9fe |
children | 73eaec7e1690 d88f0286681b |
files | semicongine/engine.nim semicongine/renderer.nim semicongine/vulkan/image.nim semicongine/vulkan/pipeline.nim semicongine/vulkan/renderpass.nim semicongine/vulkan/swapchain.nim |
diffstat | 6 files changed, 122 insertions(+), 42 deletions(-) [+] |
line wrap: on
line diff
--- a/semicongine/engine.nim Tue Jun 25 17:42:10 2024 +0700 +++ b/semicongine/engine.nim Tue Jun 25 20:24:38 2024 +0700 @@ -114,6 +114,7 @@ backFaceCulling = true, vSync = false, inFlightFrames = 2, + samples = VK_SAMPLE_COUNT_1_BIT, ) = assert not engine.renderer.isSome @@ -130,6 +131,7 @@ backFaceCulling = backFaceCulling, vSync = vSync, inFlightFrames = inFlightFrames, + samples = samples, )) proc InitRenderer*(engine: var Engine, clearColor = NewVec4f(0, 0, 0, 0), vSync = false) =
--- a/semicongine/renderer.nim Tue Jun 25 17:42:10 2024 +0700 +++ b/semicongine/renderer.nim Tue Jun 25 20:24:38 2024 +0700 @@ -62,16 +62,23 @@ backFaceCulling = true, vSync = false, inFlightFrames = 2, + samples = VK_SAMPLE_COUNT_1_BIT, ): Renderer = assert device.vk.Valid result.device = device - result.renderPass = device.CreateRenderPass(shaders, clearColor = clearColor, backFaceCulling = backFaceCulling) + result.renderPass = device.CreateRenderPass( + shaders, + clearColor = clearColor, + backFaceCulling = backFaceCulling, + samples = samples + ) let swapchain = device.CreateSwapchain( result.renderPass.vk, device.physicalDevice.GetSurfaceFormats().FilterSurfaceFormat(), vSync = vSync, inFlightFrames = inFlightFrames, + samples = samples, ) if not swapchain.isSome: raise newException(Exception, "Unable to create swapchain")
--- a/semicongine/vulkan/image.nim Tue Jun 25 17:42:10 2024 +0700 +++ b/semicongine/vulkan/image.nim Tue Jun 25 20:24:38 2024 +0700 @@ -150,8 +150,38 @@ addr region ) +proc CreateImage*(device: Device, width, height, depth: uint32, format: VkFormat, samples: VkSampleCountFlagBits, usage: openArray[VkImageUsageFlagBits]): VulkanImage = + assert device.vk.Valid + assert width > 0 + assert height > 0 + + result.device = device + result.usage = @usage + + + result.width = width + result.height = height + result.depth = depth + result.format = format + + var imageInfo = VkImageCreateInfo( + sType: VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + imageType: VK_IMAGE_TYPE_2D, + extent: VkExtent3D(width: uint32(width), height: uint32(height), depth: 1), + mipLevels: 1, + arrayLayers: 1, + format: result.format, + tiling: VK_IMAGE_TILING_OPTIMAL, + initialLayout: VK_IMAGE_LAYOUT_UNDEFINED, + usage: toBits result.usage, + sharingMode: VK_SHARING_MODE_EXCLUSIVE, + samples: samples, + ) + checkVkResult device.vk.vkCreateImage(addr imageInfo, nil, addr result.vk) + result.allocateMemory(requireMappable = false, preferVRAM = true, preferAutoFlush = false) + # currently only usable for texture access from shader -proc createImage[T](device: Device, queue: Queue, width, height: uint32, depth: PixelDepth, image: Image[T]): VulkanImage = +proc createTextureImage[T](device: Device, queue: Queue, width, height: uint32, depth: PixelDepth, image: Image[T]): VulkanImage = assert device.vk.Valid assert width > 0 assert height > 0 @@ -319,9 +349,9 @@ proc UploadTexture*(device: Device, queue: Queue, texture: Texture): VulkanTexture = assert device.vk.Valid if texture.isGrayscale: - result.image = createImage(device = device, queue = queue, width = texture.grayImage.width, height = texture.grayImage.height, depth = 1, image = texture.grayImage) + result.image = createTextureImage(device = device, queue = queue, width = texture.grayImage.width, height = texture.grayImage.height, depth = 1, image = texture.grayImage) else: - result.image = createImage(device = device, queue = queue, width = texture.colorImage.width, height = texture.colorImage.height, depth = 4, image = texture.colorImage) + result.image = createTextureImage(device = device, queue = queue, width = texture.colorImage.width, height = texture.colorImage.height, depth = 4, image = texture.colorImage) result.imageView = result.image.CreateImageView() result.sampler = result.image.device.CreateSampler(texture.sampler)
--- a/semicongine/vulkan/pipeline.nim Tue Jun 25 17:42:10 2024 +0700 +++ b/semicongine/vulkan/pipeline.nim Tue Jun 25 20:24:38 2024 +0700 @@ -55,7 +55,7 @@ descriptor.imageviews.add emptyTexture.imageView descriptor.samplers.add emptyTexture.sampler -proc CreatePipeline*(device: Device, renderPass: VkRenderPass, shaderConfiguration: ShaderConfiguration, inFlightFrames: int, subpass = 0'u32, backFaceCulling = true): ShaderPipeline = +proc CreatePipeline*(device: Device, renderPass: VkRenderPass, shaderConfiguration: ShaderConfiguration, inFlightFrames: int, subpass = 0'u32, backFaceCulling = true, samples = VK_SAMPLE_COUNT_1_BIT): ShaderPipeline = assert renderPass.Valid assert device.vk.Valid @@ -128,7 +128,7 @@ multisampling = VkPipelineMultisampleStateCreateInfo( sType: VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, sampleShadingEnable: VK_FALSE, - rasterizationSamples: VK_SAMPLE_COUNT_1_BIT, + rasterizationSamples: samples, minSampleShading: 1.0, pSampleMask: nil, alphaToCoverageEnable: VK_FALSE,
--- a/semicongine/vulkan/renderpass.nim Tue Jun 25 17:42:10 2024 +0700 +++ b/semicongine/vulkan/renderpass.nim Tue Jun 25 20:24:38 2024 +0700 @@ -19,6 +19,7 @@ clearColor = Vec4f([0.8'f32, 0.8'f32, 0.8'f32, 1'f32]), backFaceCulling = true, inFlightFrames = 2, + samples = VK_SAMPLE_COUNT_1_BIT ): RenderPass = assert device.vk.Valid @@ -26,54 +27,69 @@ for (materialtype, shaderconfig) in shaders: shaderconfig.AssertCanRender(materialtype) - var - attachments = @[VkAttachmentDescription( + var attachments = @[ + VkAttachmentDescription( format: device.physicalDevice.GetSurfaceFormats().FilterSurfaceFormat().format, - samples: VK_SAMPLE_COUNT_1_BIT, + samples: samples, 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_UNDEFINED, - finalLayout: VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - )] + finalLayout: if samples == VK_SAMPLE_COUNT_1_BIT: VK_IMAGE_LAYOUT_PRESENT_SRC_KHR else: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + ), + ] + + if samples != VK_SAMPLE_COUNT_1_BIT: + attachments.add VkAttachmentDescription( + format: device.physicalDevice.GetSurfaceFormats().FilterSurfaceFormat().format, + samples: VK_SAMPLE_COUNT_1_BIT, + loadOp: VK_ATTACHMENT_LOAD_OP_DONT_CARE, + storeOp: VK_ATTACHMENT_STORE_OP_STORE, + stencilLoadOp: VK_ATTACHMENT_LOAD_OP_DONT_CARE, + stencilStoreOp: VK_ATTACHMENT_STORE_OP_DONT_CARE, + initialLayout: VK_IMAGE_LAYOUT_UNDEFINED, + finalLayout: VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + ) + + var # dependencies seems to be optional, TODO: benchmark difference dependencies = @[VkSubpassDependency( srcSubpass: VK_SUBPASS_EXTERNAL, dstSubpass: 0, - srcStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT], - srcAccessMask: VkAccessFlags(0), - dstStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT], - dstAccessMask: toBits [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT], + srcStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT], + srcAccessMask: toBits [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT], + dstStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT], + dstAccessMask: toBits [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT], )] - outputs = @[ - VkAttachmentReference( - attachment: 0, - layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - ) - ] + colorAttachment = VkAttachmentReference( + attachment: 0, + layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + ) + resolveAttachment = VkAttachmentReference( + attachment: 1, + layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + ) - var subpassesList = [ - VkSubpassDescription( - flags: VkSubpassDescriptionFlags(0), - pipelineBindPoint: VK_PIPELINE_BIND_POINT_GRAPHICS, - inputAttachmentCount: 0, - pInputAttachments: nil, - colorAttachmentCount: uint32(outputs.len), - pColorAttachments: outputs.ToCPointer, - pResolveAttachments: nil, - pDepthStencilAttachment: nil, - preserveAttachmentCount: 0, - pPreserveAttachments: nil, - ) - ] + var subpass = VkSubpassDescription( + flags: VkSubpassDescriptionFlags(0), + pipelineBindPoint: VK_PIPELINE_BIND_POINT_GRAPHICS, + inputAttachmentCount: 0, + pInputAttachments: nil, + colorAttachmentCount: 1, + pColorAttachments: addr(colorAttachment), + pResolveAttachments: if samples == VK_SAMPLE_COUNT_1_BIT: nil else: addr(resolveAttachment), + pDepthStencilAttachment: nil, + preserveAttachmentCount: 0, + pPreserveAttachments: nil, + ) var createInfo = VkRenderPassCreateInfo( sType: VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, attachmentCount: uint32(attachments.len), pAttachments: attachments.ToCPointer, - subpassCount: uint32(subpassesList.len), - pSubpasses: subpassesList.ToCPointer, + subpassCount: 1, + pSubpasses: addr(subpass), dependencyCount: uint32(dependencies.len), pDependencies: dependencies.ToCPointer, ) @@ -84,7 +100,7 @@ for (_, shaderconfig) in shaders: assert shaderconfig.outputs.len == 1 for (materialtype, shaderconfig) in shaders: - result.shaderPipelines.add (materialtype, device.CreatePipeline(result.vk, shaderconfig, inFlightFrames, 0, backFaceCulling = backFaceCulling)) + result.shaderPipelines.add (materialtype, device.CreatePipeline(result.vk, shaderconfig, inFlightFrames, 0, backFaceCulling = backFaceCulling, samples = samples)) proc BeginRenderCommands*(commandBuffer: VkCommandBuffer, renderpass: RenderPass, framebuffer: Framebuffer, oneTimeSubmit: bool) = assert commandBuffer.Valid
--- a/semicongine/vulkan/swapchain.nim Tue Jun 25 17:42:10 2024 +0700 +++ b/semicongine/vulkan/swapchain.nim Tue Jun 25 20:24:38 2024 +0700 @@ -17,6 +17,9 @@ nFramebuffers*: uint32 currentInFlight*: int currentFramebufferIndex: uint32 + samples: VkSampleCountFlagBits + colorImage: VulkanImage + colorImageView: ImageView framebufferViews*: seq[ImageView] framebuffers*: seq[Framebuffer] queueFinishedFence*: seq[Fence] @@ -35,9 +38,10 @@ renderPass: VkRenderPass, surfaceFormat: VkSurfaceFormatKHR, inFlightFrames: int, + samples: VkSampleCountFlagBits, desiredFramebufferCount = 3'u32, oldSwapchain = VkSwapchainKHR(0), - vSync = false + vSync = false, ): Option[Swapchain] = assert device.vk.Valid assert device.physicalDevice.vk.Valid @@ -79,9 +83,21 @@ dimension: TVec2[uint32]([capabilities.currentExtent.width, capabilities.currentExtent.height]), inFlightFrames: inFlightFrames, renderPass: renderPass, - vSync: vSync + vSync: vSync, + samples: samples, ) + if samples != VK_SAMPLE_COUNT_1_BIT: + swapchain.colorImage = device.CreateImage( + width = capabilities.currentExtent.width, + height = capabilities.currentExtent.height, + depth = 4, + samples = samples, + format = surfaceFormat.format, + usage = [VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT], + ) + swapchain.colorImageView = swapchain.colorImage.CreateImageView() + if device.vk.vkCreateSwapchainKHR(addr createInfo, nil, addr swapchain.vk) == VK_SUCCESS: checkVkResult device.vk.vkGetSwapchainImagesKHR(swapchain.vk, addr swapchain.nFramebuffers, nil) var framebuffers = newSeq[VkImage](swapchain.nFramebuffers) @@ -89,7 +105,10 @@ for framebuffer in framebuffers: let framebufferView = VulkanImage(vk: framebuffer, format: surfaceFormat.format, device: device).CreateImageView() swapchain.framebufferViews.add framebufferView - swapchain.framebuffers.add device.CreateFramebuffer(renderPass, [framebufferView], swapchain.dimension) + if samples == VK_SAMPLE_COUNT_1_BIT: + swapchain.framebuffers.add device.CreateFramebuffer(renderPass, [framebufferView], swapchain.dimension) + else: + swapchain.framebuffers.add device.CreateFramebuffer(renderPass, [swapchain.colorImageView, framebufferView], swapchain.dimension) for i in 0 ..< swapchain.inFlightFrames: swapchain.queueFinishedFence.add device.CreateFence() swapchain.imageAvailableSemaphore.add device.CreateSemaphore() @@ -97,6 +116,7 @@ debug &"Created swapchain with: {swapchain.nFramebuffers} framebuffers, {inFlightFrames} in-flight frames, {swapchain.dimension.x}x{swapchain.dimension.y}" assert device.FirstPresentationQueue().isSome, "No present queue found" swapchain.presentQueue = device.FirstPresentationQueue().get + result = some(swapchain) else: result = none(Swapchain) @@ -173,6 +193,10 @@ for framebuffer in swapchain.framebuffers.mitems: assert framebuffer.vk.Valid framebuffer.Destroy() + if swapchain.colorImage.vk.Valid: + swapchain.colorImage.Destroy() + if swapchain.colorImageView.vk.Valid: + swapchain.colorImageView.Destroy() for i in 0 ..< swapchain.inFlightFrames: assert swapchain.queueFinishedFence[i].vk.Valid assert swapchain.imageAvailableSemaphore[i].vk.Valid @@ -194,5 +218,6 @@ desiredFramebufferCount = swapchain.nFramebuffers, inFlightFrames = swapchain.inFlightFrames, oldSwapchain = swapchain.vk, - vSync = swapchain.vSync + vSync = swapchain.vSync, + samples = swapchain.samples, )