changeset 1171:dc6e1660831d compiletime-tests

merge
author sam <sam@basx.dev>
date Wed, 26 Jun 2024 17:46:36 +0700
parents 58694b30b9cb (current diff) 2addc5f6804f (diff)
children 2e0b527c2753
files semicongine/renderer.nim semicongine/vulkan/renderpass.nim
diffstat 7 files changed, 181 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/semicongine/audio.nim	Sat Jun 22 08:45:14 2024 +0700
+++ b/semicongine/audio.nim	Wed Jun 26 17:46:36 2024 +0700
@@ -16,8 +16,8 @@
 
 export audiotypes
 
-const NBUFFERS = 4
-const BUFFERSAMPLECOUNT = 2048
+const NBUFFERS = 32
+const BUFFERSAMPLECOUNT = 256
 
 type
   Playback = object
@@ -202,6 +202,11 @@
 
 proc updateSoundBuffer(mixer: var Mixer) =
   let t = getMonoTime()
+
+  let tDebug = getTime()
+  # echo ""
+  # echo tDebug
+
   let dt = (t - mixer.lastUpdate).inNanoseconds.float64 / 1_000_000_000'f64
   mixer.lastUpdate = t
 
@@ -237,7 +242,9 @@
           track.playing.del(id)
       mixer.buffers[mixer.currentBuffer][i] = mixedSample
   # send data to sound device
+  # echo getTime() - tDebug
   mixer.device.WriteSoundData(mixer.currentBuffer)
+  # echo getTime() - tDebug
   mixer.currentBuffer = (mixer.currentBuffer + 1) mod mixer.buffers.len
 
 # DSP functions
--- a/semicongine/engine.nim	Sat Jun 22 08:45:14 2024 +0700
+++ b/semicongine/engine.nim	Wed Jun 26 17:46:36 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) =
@@ -195,6 +197,12 @@
 func Limits*(engine: Engine): VkPhysicalDeviceLimits =
   engine.device.physicalDevice.properties.limits
 
+func MaxFramebufferSampleCount*(engine: Engine, maxSamples = VK_SAMPLE_COUNT_8_BIT): VkSampleCountFlagBits =
+  let available = VkSampleCountFlags(
+    engine.Limits.framebufferColorSampleCounts.uint32 and engine.Limits.framebufferDepthSampleCounts.uint32
+  ).toEnums
+  return min(max(available), maxSamples)
+
 proc UpdateInputs*(engine: Engine): bool =
   UpdateInputs(engine.window.PendingEvents())
 
--- a/semicongine/renderer.nim	Sat Jun 22 08:45:14 2024 +0700
+++ b/semicongine/renderer.nim	Wed Jun 26 17:46:36 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	Sat Jun 22 08:45:14 2024 +0700
+++ b/semicongine/vulkan/image.nim	Wed Jun 26 17:46:36 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	Sat Jun 22 08:45:14 2024 +0700
+++ b/semicongine/vulkan/pipeline.nim	Wed Jun 26 17:46:36 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	Sat Jun 22 08:45:14 2024 +0700
+++ b/semicongine/vulkan/renderpass.nim	Wed Jun 26 17:46:36 2024 +0700
@@ -1,72 +1,116 @@
 import ../core
+import ../material
+import ./device
+import ./physicaldevice
+import ./pipeline
+import ./shader
 import ./framebuffer
 
+type
+  RenderPass* = object
+    vk*: VkRenderPass
+    device*: Device
+    shaderPipelines*: seq[(MaterialType, ShaderPipeline)]
+    clearColor*: Vec4f
+
 proc CreateRenderPass*(
-  device: VkDevice,
-  format: VkFormat,
-): VkRenderPass =
+  device: Device,
+  shaders: openArray[(MaterialType, ShaderConfiguration)],
+  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
 
-  var
-    attachments = @[VkAttachmentDescription(
-        format: format,
-        samples: VK_SAMPLE_COUNT_1_BIT,
+  # some asserts
+  for (materialtype, shaderconfig) in shaders:
+    shaderconfig.AssertCanRender(materialtype)
+
+  var attachments = @[
+      VkAttachmentDescription(
+        format: device.physicalDevice.GetSurfaceFormats().FilterSurfaceFormat().format,
+        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,
     )
-  checkVkResult device.vkCreateRenderPass(addr(createInfo), nil, addr(result))
+  result.device = device
+  result.clearColor = clearColor
+  checkVkResult device.vk.vkCreateRenderPass(addr(createInfo), nil, addr(result.vk))
 
-proc BeginRenderCommands*(commandBuffer: VkCommandBuffer, renderpass: VkRenderPass, framebuffer: Framebuffer, oneTimeSubmit: bool, clearColor: Vec4f) =
+  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, samples = samples))
+
+proc BeginRenderCommands*(commandBuffer: VkCommandBuffer, renderpass: RenderPass, framebuffer: Framebuffer, oneTimeSubmit: bool) =
   assert commandBuffer.Valid
+  assert renderpass.vk.Valid
   assert framebuffer.vk.Valid
   let
     w = framebuffer.dimension.x
     h = framebuffer.dimension.y
 
-  var clearColors = [VkClearValue(color: VkClearColorValue(float32: clearColor))]
+  var clearColors = [VkClearValue(color: VkClearColorValue(float32: renderpass.clearColor))]
   var
     beginInfo = VkCommandBufferBeginInfo(
       sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
@@ -75,7 +119,7 @@
     )
     renderPassInfo = VkRenderPassBeginInfo(
       sType: VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
-      renderPass: renderpass,
+      renderPass: renderPass.vk,
       framebuffer: framebuffer.vk,
       renderArea: VkRect2D(
         offset: VkOffset2D(x: 0, y: 0),
@@ -105,3 +149,12 @@
 proc EndRenderCommands*(commandBuffer: VkCommandBuffer) =
   commandBuffer.vkCmdEndRenderPass()
   checkVkResult commandBuffer.vkEndCommandBuffer()
+
+
+proc Destroy*(renderPass: var RenderPass) =
+  assert renderPass.device.vk.Valid
+  assert renderPass.vk.Valid
+  renderPass.device.vk.vkDestroyRenderPass(renderPass.vk, nil)
+  renderPass.vk.Reset
+  for _, pipeline in renderPass.shaderPipelines.mitems:
+    pipeline.Destroy()
--- a/semicongine/vulkan/swapchain.nim	Sat Jun 22 08:45:14 2024 +0700
+++ b/semicongine/vulkan/swapchain.nim	Wed Jun 26 17:46:36 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,
   )