# HG changeset patch # User sam # Date 1721224854 -25200 # Node ID f819a874058ff18e6c084a870df3c24b615bc52c # Parent 8b5558b29387067288eaea2b56e6bbced6e1e66d# Parent 04e446a7eb2bd45c7cd711118880294d1c3eb58f merge diff -r 8b5558b29387 -r f819a874058f semicongine/core/utils.nim --- a/semicongine/core/utils.nim Wed Jul 17 21:00:37 2024 +0700 +++ b/semicongine/core/utils.nim Wed Jul 17 21:00:54 2024 +0700 @@ -30,3 +30,13 @@ func Size*[T: seq](list: T): uint64 = uint64(list.len * sizeof(get(genericParams(typeof(list)), 0))) + +template TimeAndLog*(body: untyped): untyped = + let t0 = getMonoTime() + body + echo (getMonoTime() - t0).inNanoseconds.float / 1_000_000 + +template TimeAndLog*(name: string, body: untyped): untyped = + let t0 = getMonoTime() + body + echo name, ": ", (getMonoTime() - t0).inNanoseconds.float / 1_000_000 diff -r 8b5558b29387 -r f819a874058f semicongine/rendering.nim --- a/semicongine/rendering.nim Wed Jul 17 21:00:37 2024 +0700 +++ b/semicongine/rendering.nim Wed Jul 17 21:00:54 2024 +0700 @@ -47,8 +47,8 @@ samples*: VkSampleCountFlagBits # populated through InitSwapchain proc vk: VkSwapchainKHR - width: uint32 - height: uint32 + width*: uint32 + height*: uint32 msaaImage: VkImage msaaMemory: VkDeviceMemory msaaImageView: VkImageView @@ -72,7 +72,7 @@ type # type aliases SupportedGPUType = float32 | float64 | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | TVec2[int32] | TVec2[int64] | TVec3[int32] | TVec3[int64] | TVec4[int32] | TVec4[int64] | TVec2[uint32] | TVec2[uint64] | TVec3[uint32] | TVec3[uint64] | TVec4[uint32] | TVec4[uint64] | TVec2[float32] | TVec2[float64] | TVec3[float32] | TVec3[float64] | TVec4[float32] | TVec4[float64] | TMat2[float32] | TMat2[float64] | TMat23[float32] | TMat23[float64] | TMat32[float32] | TMat32[float64] | TMat3[float32] | TMat3[float64] | TMat34[float32] | TMat34[float64] | TMat43[float32] | TMat43[float64] | TMat4[float32] | TMat4[float64] - TextureType = TVec1[uint8] | TVec2[uint8] | TVec3[uint8] | TVec4[uint8] + TextureType = TVec1[uint8] | TVec4[uint8] # shader related types DescriptorSet*[T: object] = object @@ -108,9 +108,10 @@ height*: uint32 interpolation*: VkFilter = VK_FILTER_LINEAR data*: seq[T] - vk: VkImage - imageview: VkImageView - sampler: VkSampler + vk*: VkImage + imageview*: VkImageView + sampler*: VkSampler + isRenderTarget*: bool = false GPUArray*[T: SupportedGPUType, TBuffer: static BufferType] = object data*: seq[T] buffer*: Buffer diff -r 8b5558b29387 -r f819a874058f semicongine/rendering/renderer.nim --- a/semicongine/rendering/renderer.nim Wed Jul 17 21:00:37 2024 +0700 +++ b/semicongine/rendering/renderer.nim Wed Jul 17 21:00:54 2024 +0700 @@ -1,6 +1,3 @@ -func depth(texture: Texture): int = - default(elementType(texture.data)).len - func pointerAddOffset[T: SomeInteger](p: pointer, offset: T): pointer = cast[pointer](cast[T](p) + offset) @@ -13,17 +10,12 @@ of UniformBuffer: @[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] of UniformBufferMapped: @[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] -proc GetVkFormat(depth: int, usage: openArray[VkImageUsageFlagBits]): VkFormat = - const DEPTH_FORMAT_MAP = [ - 0: [VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED], - 1: [VK_FORMAT_R8_SRGB, VK_FORMAT_R8_UNORM], - 2: [VK_FORMAT_R8G8_SRGB, VK_FORMAT_R8G8_UNORM], - 3: [VK_FORMAT_R8G8B8_SRGB, VK_FORMAT_R8G8B8_UNORM], - 4: [VK_FORMAT_R8G8B8A8_SRGB, VK_FORMAT_R8G8B8A8_UNORM], - ] +proc GetVkFormat(grayscale: bool, usage: openArray[VkImageUsageFlagBits]): VkFormat = + let formats = if grayscale: [VK_FORMAT_R8_SRGB, VK_FORMAT_R8_UNORM] + else: [VK_FORMAT_B8G8R8A8_SRGB, VK_FORMAT_B8G8R8A8_UNORM] var formatProperties = VkImageFormatProperties2(sType: VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2) - for format in DEPTH_FORMAT_MAP[depth]: + for format in formats: var formatInfo = VkPhysicalDeviceImageFormatInfo2( sType: VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, format: format, @@ -446,9 +438,11 @@ checkVkResult vkCreateSampler(vulkan.device, addr(samplerInfo), nil, addr(result)) proc createTextureImage(renderData: var RenderData, texture: var Texture) = - assert texture.vk == VkImage(0) - const usage = [VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_USAGE_SAMPLED_BIT] - let format = GetVkFormat(texture.depth, usage = usage) + assert texture.vk == VkImage(0), "Texture has already been created" + var usage = @[VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_USAGE_SAMPLED_BIT] + if texture.isRenderTarget: + usage.add VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + let format = GetVkFormat(elementType(texture.data) is TVec1[uint8], usage = usage) texture.vk = svkCreate2DImage(texture.width, texture.height, format, usage) renderData.images.add texture.vk diff -r 8b5558b29387 -r f819a874058f semicongine/rendering/renderpasses.nim --- a/semicongine/rendering/renderpasses.nim Wed Jul 17 21:00:37 2024 +0700 +++ b/semicongine/rendering/renderpasses.nim Wed Jul 17 21:00:54 2024 +0700 @@ -1,4 +1,4 @@ -proc CreatePresentationRenderPass*(samples = VK_SAMPLE_COUNT_1_BIT): VkRenderPass = +proc CreateDirectPresentationRenderPass*(samples = VK_SAMPLE_COUNT_1_BIT): VkRenderPass = assert vulkan.instance.Valid, "Vulkan not initialized" let format = DefaultSurfaceFormat() @@ -24,14 +24,16 @@ 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], - 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], - )] + 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], + dstAccessMask: toBits [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT], + ) + ] colorAttachment = VkAttachmentReference( attachment: 0, layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, @@ -41,28 +43,88 @@ layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, ) - 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, + if samples == VK_SAMPLE_COUNT_1_BIT: + return svkCreateRenderPass(attachments, [colorAttachment], [], dependencies) + else: + return svkCreateRenderPass(attachments, [colorAttachment], [resolveAttachment], dependencies) + +proc CreateIndirectPresentationRenderPass*(): (VkRenderPass, VkRenderPass) = + assert vulkan.instance.Valid, "Vulkan not initialized" + + # first renderpass, drawing + let format = DefaultSurfaceFormat() + var + attachments = @[VkAttachmentDescription( + format: 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_SHADER_READ_ONLY_OPTIMAL, + )] + + dependencies = @[ + 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], + ), + 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, + ) + + # second renderpass, presentation + var + presentAttachments = @[VkAttachmentDescription( + format: 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 = ( + svkCreateRenderPass(attachments, [colorAttachment], [], dependencies), + svkCreateRenderPass(presentAttachments, [presentColorAttachment], [], presentDependencies) ) - var createInfo = VkRenderPassCreateInfo( - sType: VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - attachmentCount: uint32(attachments.len), - pAttachments: attachments.ToCPointer, - subpassCount: 1, - pSubpasses: addr(subpass), - dependencyCount: uint32(dependencies.len), - pDependencies: dependencies.ToCPointer, - ) - checkVkResult vulkan.device.vkCreateRenderPass(addr(createInfo), nil, addr(result)) template WithRenderPass*( theRenderpass: VkRenderPass, diff -r 8b5558b29387 -r f819a874058f semicongine/rendering/vulkan_wrappers.nim --- a/semicongine/rendering/vulkan_wrappers.nim Wed Jul 17 21:00:37 2024 +0700 +++ b/semicongine/rendering/vulkan_wrappers.nim Wed Jul 17 21:00:54 2024 +0700 @@ -225,6 +225,37 @@ pDynamicOffsets = nil ) + +proc svkCreateRenderPass( + attachments: openArray[VkAttachmentDescription], + colorAttachments: openArray[VkAttachmentReference], + resolveAttachments: openArray[VkAttachmentReference], + dependencies: openArray[VkSubpassDependency], +): VkRenderPass = + assert colorAttachments.len == resolveAttachments.len or resolveAttachments.len == 0 + var subpass = VkSubpassDescription( + flags: VkSubpassDescriptionFlags(0), + pipelineBindPoint: VK_PIPELINE_BIND_POINT_GRAPHICS, + inputAttachmentCount: 0, + pInputAttachments: nil, + colorAttachmentCount: colorAttachments.len.uint32, + pColorAttachments: colorAttachments.ToCPointer, + pResolveAttachments: resolveAttachments.ToCPointer, + 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: 1, + pSubpasses: addr(subpass), + dependencyCount: uint32(dependencies.len), + pDependencies: dependencies.ToCPointer, + ) + checkVkResult vkCreateRenderPass(vulkan.device, addr(createInfo), nil, addr(result)) + proc BestMemory*(mappable: bool, filter: seq[uint32] = @[]): uint32 = var physicalProperties: VkPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties(vulkan.physicalDevice, addr(physicalProperties)) diff -r 8b5558b29387 -r f819a874058f semiconginev2.nim --- a/semiconginev2.nim Wed Jul 17 21:00:37 2024 +0700 +++ b/semiconginev2.nim Wed Jul 17 21:00:54 2024 +0700 @@ -6,6 +6,7 @@ import std/marshal import std/math import std/macros +import std/monotimes import std/os import std/options import std/paths @@ -14,6 +15,7 @@ import std/strformat import std/strutils import std/tables +import std/times import std/typetraits include ./semicongine/rendering/vulkan/api diff -r 8b5558b29387 -r f819a874058f tests/test_rendering.nim --- a/tests/test_rendering.nim Wed Jul 17 21:00:37 2024 +0700 +++ b/tests/test_rendering.nim Wed Jul 17 21:00:54 2024 +0700 @@ -7,7 +7,7 @@ mainRenderpass: VkRenderPass swapchain: Swapchain -proc test_01_triangle(nFrames: int) = +proc test_01_triangle(nFrames: int, renderPass: VkRenderPass, samples = VK_SAMPLE_COUNT_1_BIT) = var renderdata = InitRenderData() type @@ -33,12 +33,12 @@ renderdata.FlushAllMemory() var - pipeline = CreatePipeline[TrianglShader](renderPass = mainRenderpass, samples = swapchain.samples) + pipeline = CreatePipeline[TrianglShader](renderPass = renderPass, samples = samples) var c = 0 while UpdateInputs() and c < nFrames: WithNextFrame(swapchain, framebuffer, commandbuffer): - WithRenderPass(mainRenderpass, framebuffer, commandbuffer, swapchain.width, swapchain.height, NewVec4f(0, 0, 0, 0)): + WithRenderPass(renderPass, framebuffer, commandbuffer, swapchain.width, swapchain.height, NewVec4f(0, 0, 0, 0)): WithPipeline(commandbuffer, pipeline): Render(commandbuffer = commandbuffer, pipeline = pipeline, mesh = mesh) inc c @@ -49,7 +49,7 @@ DestroyRenderData(renderdata) -proc test_02_triangle_quad_instanced(nFrames: int) = +proc test_02_triangle_quad_instanced(nFrames: int, renderPass: VkRenderPass, samples = VK_SAMPLE_COUNT_1_BIT) = var renderdata = InitRenderData() type @@ -101,12 +101,12 @@ AssignBuffers(renderdata, instancesB) renderdata.FlushAllMemory() - var pipeline = CreatePipeline[SomeShader](renderPass = mainRenderpass, samples = swapchain.samples) + var pipeline = CreatePipeline[SomeShader](renderPass = renderPass, samples = samples) var c = 0 while UpdateInputs() and c < nFrames: WithNextFrame(swapchain, framebuffer, commandbuffer): - WithRenderPass(mainRenderpass, framebuffer, commandbuffer, swapchain.width, swapchain.height, NewVec4f(0, 0, 0, 0)): + WithRenderPass(renderPass, framebuffer, commandbuffer, swapchain.width, swapchain.height, NewVec4f(0, 0, 0, 0)): WithPipeline(commandbuffer, pipeline): Render(commandbuffer = commandbuffer, pipeline = pipeline, mesh = quad, instances = instancesA) Render(commandbuffer = commandbuffer, pipeline = pipeline, mesh = quad, instances = instancesB) @@ -119,7 +119,7 @@ DestroyPipeline(pipeline) DestroyRenderData(renderdata) -proc test_03_simple_descriptorset(nFrames: int) = +proc test_03_simple_descriptorset(nFrames: int, renderPass: VkRenderPass, samples = VK_SAMPLE_COUNT_1_BIT) = var renderdata = InitRenderData() type @@ -128,7 +128,7 @@ Uniforms = object material: GPUValue[Material, UniformBuffer] - texture1: Texture[TVec3[uint8]] + texture1: Texture[TVec4[uint8]] QuadShader = object position {.VertexAttribute.}: Vec3f @@ -149,10 +149,10 @@ position: GPUArray[Vec3f, VertexBuffer] indices: GPUArray[uint16, IndexBuffer] - let R = TVec3[uint8]([255'u8, 0'u8, 0'u8]) - let G = TVec3[uint8]([0'u8, 255'u8, 0'u8]) - let B = TVec3[uint8]([0'u8, 0'u8, 255'u8]) - let W = TVec3[uint8]([255'u8, 255'u8, 255'u8]) + let R = TVec4[uint8]([255'u8, 0'u8, 0'u8, 255'u8]) + let G = TVec4[uint8]([0'u8, 255'u8, 0'u8, 255'u8]) + let B = TVec4[uint8]([0'u8, 0'u8, 255'u8, 255'u8]) + let W = TVec4[uint8]([255'u8, 255'u8, 255'u8, 255'u8]) var quad = QuadMesh( position: asGPUArray([NewVec3f(-0.5, -0.5), NewVec3f(-0.5, 0.5), NewVec3f(0.5, 0.5), NewVec3f(0.5, -0.5)], VertexBuffer), @@ -161,14 +161,14 @@ uniforms1 = asDescriptorSet( Uniforms( material: asGPUValue(Material(baseColor: NewVec3f(1, 1, 1)), UniformBuffer), - texture1: Texture[TVec3[uint8]](width: 3, height: 3, data: @[R, G, B, G, B, R, B, R, G], interpolation: VK_FILTER_NEAREST), + texture1: Texture[TVec4[uint8]](width: 3, height: 3, data: @[R, G, B, G, B, R, B, R, G], interpolation: VK_FILTER_NEAREST), ) ) uniforms2 = asDescriptorSet( Uniforms( material: asGPUValue(Material(baseColor: NewVec3f(0.5, 0.5, 0.5)), UniformBuffer), - texture1: Texture[TVec3[uint8]](width: 2, height: 2, data: @[R, G, B, W]), - ) + texture1: Texture[TVec4[uint8]](width: 2, height: 2, data: @[R, G, B, W]), + ) ) AssignBuffers(renderdata, quad) @@ -178,7 +178,7 @@ UploadTextures(renderdata, uniforms2) renderdata.FlushAllMemory() - var pipeline = CreatePipeline[QuadShader](renderPass = mainRenderpass, samples = swapchain.samples) + var pipeline = CreatePipeline[QuadShader](renderPass = renderPass, samples = samples) InitDescriptorSet(renderdata, pipeline.descriptorSetLayouts[0], uniforms1) InitDescriptorSet(renderdata, pipeline.descriptorSetLayouts[0], uniforms2) @@ -186,7 +186,7 @@ var c = 0 while UpdateInputs() and c < nFrames: WithNextFrame(swapchain, framebuffer, commandbuffer): - WithRenderPass(mainRenderpass, framebuffer, commandbuffer, swapchain.width, swapchain.height, NewVec4f(0, 0, 0, 0)): + WithRenderPass(renderPass, framebuffer, commandbuffer, swapchain.width, swapchain.height, NewVec4f(0, 0, 0, 0)): WithPipeline(commandbuffer, pipeline): WithBind(commandbuffer, (uniforms1, ), pipeline, swapchain.currentFiF): Render(commandbuffer = commandbuffer, pipeline = pipeline, mesh = quad) @@ -199,7 +199,7 @@ DestroyPipeline(pipeline) DestroyRenderData(renderdata) -proc test_04_multiple_descriptorsets(nFrames: int) = +proc test_04_multiple_descriptorsets(nFrames: int, renderPass: VkRenderPass, samples = VK_SAMPLE_COUNT_1_BIT) = var renderdata = InitRenderData() type @@ -286,7 +286,7 @@ UploadTextures(renderdata, mainset) renderdata.FlushAllMemory() - var pipeline = CreatePipeline[QuadShader](renderPass = mainRenderpass, samples = swapchain.samples) + var pipeline = CreatePipeline[QuadShader](renderPass = renderPass, samples = samples) InitDescriptorSet(renderdata, pipeline.descriptorSetLayouts[0], constset) InitDescriptorSet(renderdata, pipeline.descriptorSetLayouts[1], mainset) @@ -295,13 +295,14 @@ var c = 0 while UpdateInputs() and c < nFrames: - WithNextFrame(swapchain, framebuffer, commandbuffer): - WithRenderPass(mainRenderpass, framebuffer, commandbuffer, swapchain.width, swapchain.height, NewVec4f(0, 0, 0, 0)): - WithPipeline(commandbuffer, pipeline): - WithBind(commandbuffer, (constset, mainset, otherset1), pipeline, swapchain.currentFiF): - Render(commandbuffer = commandbuffer, pipeline = pipeline, mesh = quad) - WithBind(commandbuffer, (constset, mainset, otherset2), pipeline, swapchain.currentFiF): - Render(commandbuffer = commandbuffer, pipeline = pipeline, mesh = quad) + TimeAndLog: + WithNextFrame(swapchain, framebuffer, commandbuffer): + WithRenderPass(renderPass, framebuffer, commandbuffer, swapchain.width, swapchain.height, NewVec4f(0, 0, 0, 0)): + WithPipeline(commandbuffer, pipeline): + WithBind(commandbuffer, (constset, mainset, otherset1), pipeline, swapchain.currentFiF): + Render(commandbuffer = commandbuffer, pipeline = pipeline, mesh = quad) + WithBind(commandbuffer, (constset, mainset, otherset2), pipeline, swapchain.currentFiF): + Render(commandbuffer = commandbuffer, pipeline = pipeline, mesh = quad) mainset.data.renderSettings.data.brigthness = (c.float32 / nFrames.float32) otherset1.data.objectSettings.data.scale = 0.5 + (c.float32 / nFrames.float32) UpdateGPUBuffer(mainset.data.renderSettings) @@ -314,26 +315,134 @@ DestroyPipeline(pipeline) DestroyRenderData(renderdata) +proc test_05_triangle_2pass(nFrames: int, samples = VK_SAMPLE_COUNT_1_BIT) = + var + (offscreenRP, presentRP) = CreateIndirectPresentationRenderPass() + swapchain = InitSwapchain(renderpass = presentRP).get() + + var renderdata = InitRenderData() + + type + Uniforms = object + frameTexture: Texture[TVec4[uint8]] + TriangleShader = object + position {.VertexAttribute.}: Vec3f + color {.VertexAttribute.}: Vec3f + fragmentColor {.Pass.}: Vec3f + outColor {.ShaderOutput.}: Vec4f + # code + vertexCode: string = """void main() { + fragmentColor = color; + gl_Position = vec4(position, 1);}""" + fragmentCode: string = """void main() { + outColor = vec4(fragmentColor, 1);}""" + PresentShader = object + position {.VertexAttribute.}: Vec2f + uv {.Pass.}: Vec2f + outColor {.ShaderOutput.}: Vec4f + descriptorSets {.DescriptorSets.}: (Uniforms, ) + # code + vertexCode: string = """void main() { + uv = ((position + 1) * 0.5) * vec2(1, -1); + gl_Position = vec4(position, 0, 1);}""" + fragmentCode: string = """void main() { + vec2 uv1 = uv + vec2(0.001, 0.001); + vec2 uv2 = uv + vec2(0.001, -0.001); + vec2 uv3 = uv + vec2(-0.001, 0.001); + vec2 uv4 = uv + vec2(-0.001, -0.001); + outColor = ( + texture(frameTexture, uv1) + + texture(frameTexture, uv2) + + texture(frameTexture, uv3) + + texture(frameTexture, uv4) + ) / 4; + }""" + TriangleMesh = object + position: GPUArray[Vec3f, VertexBuffer] + color: GPUArray[Vec3f, VertexBuffer] + QuadMesh = object + position: GPUArray[Vec2f, VertexBuffer] + indices: GPUArray[uint16, IndexBuffer] + var mesh = TriangleMesh( + position: asGPUArray([NewVec3f(-0.5, -0.5), NewVec3f(0, 0.5), NewVec3f(0.5, -0.5)], VertexBuffer), + color: asGPUArray([NewVec3f(0, 0, 1), NewVec3f(0, 1, 0), NewVec3f(1, 0, 0)], VertexBuffer), + ) + var quad = QuadMesh( + position: asGPUArray([NewVec2f(-1, -1), NewVec2f(-1, 1), NewVec2f(1, 1), NewVec2f(1, -1)], VertexBuffer), + indices: asGPUArray([0'u16, 1'u16, 2'u16, 2'u16, 3'u16, 0'u16], IndexBuffer), + ) + var uniforms1 = asDescriptorSet( + Uniforms( + frameTexture: Texture[TVec4[uint8]](width: swapchain.width, height: swapchain.height, isRenderTarget: true), + ) + ) + var uniforms2 = asDescriptorSet( + Uniforms( + frameTexture: Texture[TVec4[uint8]](width: swapchain.width, height: swapchain.height, isRenderTarget: true), + ) + ) + AssignBuffers(renderdata, mesh) + AssignBuffers(renderdata, quad) + UploadTextures(renderdata, uniforms1) + UploadTextures(renderdata, uniforms2) + renderdata.FlushAllMemory() + + var + drawPipeline = CreatePipeline[TriangleShader](renderPass = offscreenRP, samples = samples) + presentPipeline = CreatePipeline[PresentShader](renderPass = presentRP, samples = samples) + + InitDescriptorSet(renderdata, presentPipeline.descriptorSetLayouts[0], uniforms1) + InitDescriptorSet(renderdata, presentPipeline.descriptorSetLayouts[0], uniforms2) + + var offscreenFB = svkCreateFramebuffer(offscreenRP, swapchain.width, swapchain.height, [uniforms1.data.frameTexture.imageview]) + + var c = 0 + while UpdateInputs() and c < nFrames: + + TimeAndLog: + WithNextFrame(swapchain, framebuffer, commandbuffer): + + WithRenderPass(offscreenRP, offscreenFB, commandbuffer, swapchain.width, swapchain.height, NewVec4f(0, 0, 0, 0)): + WithPipeline(commandbuffer, drawPipeline): + Render(commandbuffer = commandbuffer, pipeline = drawPipeline, mesh = mesh) + + WithRenderPass(presentRP, framebuffer, commandbuffer, swapchain.width, swapchain.height, NewVec4f(0, 0, 0, 0)): + WithPipeline(commandbuffer, presentPipeline): + WithBind(commandbuffer, (uniforms1, ), presentPipeline, swapchain.currentFiF): + Render(commandbuffer = commandbuffer, pipeline = presentPipeline, mesh = quad) + inc c + + # cleanup + checkVkResult vkDeviceWaitIdle(vulkan.device) + DestroyPipeline(presentPipeline) + DestroyPipeline(drawPipeline) + DestroyRenderData(renderdata) + vkDestroyRenderPass(vulkan.device, offscreenRP, nil) + vkDestroyRenderPass(vulkan.device, presentRP, nil) + vkDestroyFramebuffer(vulkan.device, offscreenFB, nil) + DestroySwapchain(swapchain) + when isMainModule: var nFrames = 2000 InitVulkan() + # test normal block: - mainRenderpass = CreatePresentationRenderPass() + mainRenderpass = CreateDirectPresentationRenderPass() swapchain = InitSwapchain(renderpass = mainRenderpass).get() # tests a simple triangle with minimalistic shader and vertex format - test_01_triangle(nFrames) + test_01_triangle(nFrames, renderPass = mainRenderpass) # tests instanced triangles and quads, mixing meshes and instances - test_02_triangle_quad_instanced(nFrames) + test_02_triangle_quad_instanced(nFrames, renderPass = mainRenderpass) # teste descriptor sets - test_03_simple_descriptorset(nFrames) + test_03_simple_descriptorset(nFrames, renderPass = mainRenderpass) # tests multiple descriptor sets and arrays - test_04_multiple_descriptorsets(nFrames) + test_04_multiple_descriptorsets(nFrames, renderPass = mainRenderpass) checkVkResult vkDeviceWaitIdle(vulkan.device) vkDestroyRenderPass(vulkan.device, mainRenderpass, nil) @@ -341,13 +450,17 @@ # test MSAA block: - mainRenderpass = CreatePresentationRenderPass(samples = VK_SAMPLE_COUNT_4_BIT) + mainRenderpass = CreateDirectPresentationRenderPass(samples = VK_SAMPLE_COUNT_4_BIT) swapchain = InitSwapchain(renderpass = mainRenderpass, samples = VK_SAMPLE_COUNT_4_BIT).get() - test_01_triangle(99999999) + test_01_triangle(nFrames, renderPass = mainRenderpass, VK_SAMPLE_COUNT_4_BIT) checkVkResult vkDeviceWaitIdle(vulkan.device) vkDestroyRenderPass(vulkan.device, mainRenderpass, nil) DestroySwapchain(swapchain) + # test multiple render passes + block: + test_05_triangle_2pass(999999999) + DestroyVulkan()