view semiconginev2/rendering/renderpasses.nim @ 1229:5dcb503ef0c0

did: refactor renderpass a bit, enable depth buffering and msaa on offscreen-rendering
author sam <sam@basx.dev>
date Thu, 18 Jul 2024 21:32:41 +0700
parents 56781cc0fc7c
children
line wrap: on
line source

proc CreateDirectPresentationRenderPass*(depthBuffer: bool, samples = VK_SAMPLE_COUNT_1_BIT): RenderPass =
  assert vulkan.instance.Valid, "Vulkan not initialized"
  result = RenderPass(depthBuffer: depthBuffer, samples: samples)

  var attachments = @[VkAttachmentDescription(
    format: SURFACE_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: if samples == VK_SAMPLE_COUNT_1_BIT: VK_IMAGE_LAYOUT_PRESENT_SRC_KHR else: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
  )]
  if depthBuffer:
    attachments.add VkAttachmentDescription(
      format: DEPTH_FORMAT,
      samples: samples,
      loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR,
      storeOp: VK_ATTACHMENT_STORE_OP_DONT_CARE,
      stencilLoadOp: VK_ATTACHMENT_LOAD_OP_DONT_CARE,
      stencilStoreOp: VK_ATTACHMENT_STORE_OP_DONT_CARE,
      initialLayout: VK_IMAGE_LAYOUT_UNDEFINED,
      finalLayout: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
    )
  if samples != VK_SAMPLE_COUNT_1_BIT:
    attachments.add VkAttachmentDescription(
      format: SURFACE_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 = @[
      VkSubpassDependency(
        srcSubpass: VK_SUBPASS_EXTERNAL,
        dstSubpass: 0,
        srcStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT],
        dstStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT],
        srcAccessMask: toBits [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT],
        dstAccessMask: toBits [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT],
      )
    ]
    colorAttachment = VkAttachmentReference(
      attachment: 0,
      layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
    )
    depthAttachment = VkAttachmentReference(
      attachment: 1,
      layout: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
    )
    resolveAttachment = VkAttachmentReference(
      attachment: (attachments.len - 1).uint32, # depending on whether depthBuffer is used or not
      layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
    )

  result.vk = svkCreateRenderPass(
    attachments = attachments,
    colorAttachments = [colorAttachment],
    depthAttachments = if depthBuffer: @[depthAttachment] else: @[],
    resolveAttachments = if samples > VK_SAMPLE_COUNT_1_BIT: @[resolveAttachment] else: @[],
    dependencies = dependencies,
  )

proc CreateIndirectPresentationRenderPass*(depthBuffer: bool, samples = VK_SAMPLE_COUNT_1_BIT): (RenderPass, RenderPass) =
  assert vulkan.instance.Valid, "Vulkan not initialized"

  result[0] = RenderPass(depthBuffer: depthBuffer, samples: samples)
  result[1] = RenderPass(depthBuffer: false, samples: VK_SAMPLE_COUNT_1_BIT)

  # first renderpass, drawing
  var
    attachments = @[VkAttachmentDescription(
      format: SURFACE_FORMAT, # not strictly necessary
      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_SHADER_READ_ONLY_OPTIMAL,
      finalLayout: if samples == VK_SAMPLE_COUNT_1_BIT: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL else: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
    )]
  if depthBuffer:
    attachments.add VkAttachmentDescription(
      format: DEPTH_FORMAT,
      samples: samples,
      loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR,
      storeOp: VK_ATTACHMENT_STORE_OP_DONT_CARE,
      stencilLoadOp: VK_ATTACHMENT_LOAD_OP_DONT_CARE,
      stencilStoreOp: VK_ATTACHMENT_STORE_OP_DONT_CARE,
      initialLayout: VK_IMAGE_LAYOUT_UNDEFINED,
      finalLayout: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
    )
  if samples != VK_SAMPLE_COUNT_1_BIT:
    attachments.add VkAttachmentDescription(
      format: SURFACE_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_SHADER_READ_ONLY_OPTIMAL,
    )

  var
    dependencies = @[
      VkSubpassDependency(
        srcSubpass: VK_SUBPASS_EXTERNAL,
        dstSubpass: 0,
        srcStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT],
        dstStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT],
        srcAccessMask: toBits [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT],
        dstAccessMask: toBits [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT],
      ),
      VkSubpassDependency(
        srcSubpass: VK_SUBPASS_EXTERNAL,
        dstSubpass: 0,
        srcStageMask: toBits [VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT],
        dstStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT],
        srcAccessMask: toBits [VK_ACCESS_SHADER_READ_BIT],
        dstAccessMask: toBits [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT],
      ),
      VkSubpassDependency(
        srcSubpass: 0,
        dstSubpass: VK_SUBPASS_EXTERNAL,
        srcStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT],
        dstStageMask: toBits [VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT],
        srcAccessMask: toBits [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT],
        dstAccessMask: toBits [VK_ACCESS_SHADER_READ_BIT],
      ),
    ]
    colorAttachment = VkAttachmentReference(
      attachment: 0,
      layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
    )
    depthAttachment = VkAttachmentReference(
      attachment: 1,
      layout: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
    )
    resolveAttachment = VkAttachmentReference(
      attachment: (attachments.len - 1).uint32, # depending on whether depthBuffer is used or not
      layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
    )
  result[0].vk = svkCreateRenderPass(
    attachments = attachments,
    colorAttachments = [colorAttachment],
    depthAttachments = if depthBuffer: @[depthAttachment] else: @[],
    resolveAttachments = if samples > VK_SAMPLE_COUNT_1_BIT: @[resolveAttachment] else: @[],
    dependencies = dependencies
  )

  # second renderpass, presentation
  var
    presentAttachments = @[VkAttachmentDescription(
      format: SURFACE_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_UNDEFINED,
      finalLayout: VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
    )]
    presentDependencies = @[VkSubpassDependency(
      srcSubpass: VK_SUBPASS_EXTERNAL,
      dstSubpass: 0,
      srcStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT],
      dstStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT],
      srcAccessMask: VkAccessFlags(0),
      dstAccessMask: toBits [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT],
    )]
    presentColorAttachment = VkAttachmentReference(
      attachment: 0,
      layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
    )

  result[1].vk = svkCreateRenderPass(
    attachments = presentAttachments,
    colorAttachments = [presentColorAttachment],
    depthAttachments = [],
    resolveAttachments = [],
    dependencies = presentDependencies
  )

template WithRenderPass*(
  theRenderpass: RenderPass,
  theFramebuffer: VkFramebuffer,
  commandbuffer: VkCommandBuffer,
  renderWidth: uint32,
  renderHeight: uint32,
  clearColor: Vec4f,
  body: untyped
): untyped =
  var
    clearColors = [
      VkClearValue(color: VkClearColorValue(float32: clearColor)),
      VkClearValue(depthStencil: VkClearDepthStencilValue(depth: 1'f32, stencil: 0))
    ]
    renderPassInfo = VkRenderPassBeginInfo(
      sType: VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
      renderPass: theRenderpass.vk,
      framebuffer: theFramebuffer,
      renderArea: VkRect2D(
        offset: VkOffset2D(x: 0, y: 0),
        extent: VkExtent2D(width: renderWidth, height: renderHeight),
      ),
      clearValueCount: clearColors.len.uint32,
      pClearValues: clearColors.ToCPointer(),
    )
    viewport = VkViewport(
      x: 0.0,
      y: renderHeight.float32,
      width: renderWidth.float32,
      height: -renderHeight.float32,
      minDepth: 0.0,
      maxDepth: 1.0,
    )
    scissor = VkRect2D(
      offset: VkOffset2D(x: 0, y: 0),
      extent: VkExtent2D(width: renderWidth, height: renderHeight)
    )

  vkCmdBeginRenderPass(commandbuffer, addr(renderPassInfo), VK_SUBPASS_CONTENTS_INLINE)

  # setup viewport
  vkCmdSetViewport(commandbuffer, firstViewport = 0, viewportCount = 1, addr(viewport))
  vkCmdSetScissor(commandbuffer, firstScissor = 0, scissorCount = 1, addr(scissor))

  block:
    body

  vkCmdEndRenderPass(commandbuffer)