Mercurial > games > semicongine
comparison static_utils.nim @ 1186:52e926efaac5 compiletime-tests
sync from bedroom to office
author | sam <sam@basx.dev> |
---|---|
date | Sun, 07 Jul 2024 00:36:15 +0700 |
parents | 565fcfde427a |
children | b14861786b61 |
comparison
equal
deleted
inserted
replaced
1185:565fcfde427a | 1186:52e926efaac5 |
---|---|
1 import std/algorithm | |
1 import std/os | 2 import std/os |
2 import std/enumerate | 3 import std/enumerate |
3 import std/hashes | 4 import std/hashes |
4 import std/macros | 5 import std/macros |
5 import std/strformat | 6 import std/strformat |
17 template VertexAttribute {.pragma.} | 18 template VertexAttribute {.pragma.} |
18 template InstanceAttribute {.pragma.} | 19 template InstanceAttribute {.pragma.} |
19 template Pass {.pragma.} | 20 template Pass {.pragma.} |
20 template PassFlat {.pragma.} | 21 template PassFlat {.pragma.} |
21 template ShaderOutput {.pragma.} | 22 template ShaderOutput {.pragma.} |
22 template VertexIndices {.pragma.} | |
23 | 23 |
24 const INFLIGHTFRAMES = 2'u32 | 24 const INFLIGHTFRAMES = 2'u32 |
25 const MEMORY_ALIGNMENT = 65536'u64 # Align buffers inside memory along this alignment | 25 const MEMORY_ALIGNMENT = 65536'u64 # Align buffers inside memory along this alignment |
26 const BUFFER_ALIGNMENT = 64'u64 # align offsets inside buffers along this alignment | 26 const BUFFER_ALIGNMENT = 64'u64 # align offsets inside buffers along this alignment |
27 const MEMORY_BLOCK_ALLOCATION_SIZE = 100_000_000'u64 # ca. 100mb per block, seems reasonable | |
28 const BUFFER_ALLOCATION_SIZE = 9_000_000'u64 # ca. 9mb per block, seems reasonable, can put 10 buffers into one memory block | |
27 | 29 |
28 # some globals that will (likely?) never change during the life time of the engine | 30 # some globals that will (likely?) never change during the life time of the engine |
29 type | 31 type |
30 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] | 32 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] |
31 TextureType = TVec1[uint8] | TVec2[uint8] | TVec3[uint8] | TVec4[uint8] | 33 TextureType = TVec1[uint8] | TVec2[uint8] | TVec3[uint8] | TVec4[uint8] |
35 fragmentShader: VkShaderModule | 37 fragmentShader: VkShaderModule |
36 | 38 |
37 IndexType = enum | 39 IndexType = enum |
38 None, UInt8, UInt16, UInt32 | 40 None, UInt8, UInt16, UInt32 |
39 | 41 |
40 IndirectGPUMemory = object | 42 MemoryBlock = object |
41 vk: VkDeviceMemory | 43 vk: VkDeviceMemory |
42 size: uint64 | 44 size: uint64 |
43 needsTransfer: bool # usually true | 45 rawPointer: pointer # if not nil, this is mapped memory |
44 DirectGPUMemory = object | 46 offsetNextFree: uint64 |
45 vk: VkDeviceMemory | 47 |
46 size: uint64 | 48 BufferType = enum |
47 rawPointer: pointer | 49 VertexBuffer |
48 GPUMemory = IndirectGPUMemory | DirectGPUMemory | 50 VertexBufferMapped |
49 | 51 IndexBuffer |
50 Buffer[TMemory: GPUMemory] = object | 52 IndexBufferMapped |
53 UniformBuffer | |
54 UniformBufferMapped | |
55 Buffer = object | |
51 vk: VkBuffer | 56 vk: VkBuffer |
52 size: uint64 | 57 size: uint64 |
53 rawPointer: pointer | 58 rawPointer: pointer # if not nil, buffer is using mapped memory |
54 Texture[T: TextureType, TMemory: GPUMemory] = object | 59 offsetNextFree: uint64 |
60 | |
61 Texture[T: TextureType] = object | |
55 vk: VkImage | 62 vk: VkImage |
56 memory: TMemory | 63 memory: MemoryBlock |
57 format: VkFormat | 64 format: VkFormat |
58 imageview: VkImageView | 65 imageview: VkImageView |
59 sampler: VkSampler | 66 sampler: VkSampler |
60 offset: uint64 | 67 offset: uint64 |
61 size: uint64 | 68 size: uint64 |
62 width: uint32 | 69 width: uint32 |
63 height: uint32 | 70 height: uint32 |
64 data: seq[T] | 71 data: seq[T] |
65 | 72 |
66 GPUArray[T: SupportedGPUType, TMemory: GPUMemory] = object | 73 GPUArray[T: SupportedGPUType, TBuffer: static BufferType] = object |
67 data: seq[T] | 74 data: seq[T] |
68 buffer: Buffer[TMemory] | 75 buffer: Buffer |
69 offset: uint64 | 76 offset: uint64 |
70 GPUValue[T: object|array, TMemory: GPUMemory] = object | 77 GPUValue[T: object|array, TBuffer: static BufferType] = object |
71 data: T | 78 data: T |
72 buffer: Buffer[TMemory] | 79 buffer: Buffer |
73 offset: uint64 | 80 offset: uint64 |
74 GPUData = GPUArray | GPUValue | 81 GPUData = GPUArray | GPUValue |
75 | 82 |
76 DescriptorSetType = enum | 83 DescriptorSetType = enum |
77 GlobalSet | 84 GlobalSet |
82 | 89 |
83 Pipeline[TShader] = object | 90 Pipeline[TShader] = object |
84 vk: VkPipeline | 91 vk: VkPipeline |
85 layout: VkPipelineLayout | 92 layout: VkPipelineLayout |
86 descriptorSetLayouts: array[DescriptorSetType, VkDescriptorSetLayout] | 93 descriptorSetLayouts: array[DescriptorSetType, VkDescriptorSetLayout] |
87 BufferType = enum | |
88 VertexBuffer, IndexBuffer, UniformBuffer | |
89 RenderData = object | 94 RenderData = object |
90 descriptorPool: VkDescriptorPool | 95 descriptorPool: VkDescriptorPool |
91 # tuple is memory and offset to next free allocation in that memory | 96 memory: array[VK_MAX_MEMORY_TYPES.int, seq[MemoryBlock]] |
92 indirectMemory: seq[tuple[memory: IndirectGPUMemory, usedOffset: uint64]] | 97 buffers: array[BufferType, seq[Buffer]] |
93 directMemory: seq[tuple[memory: DirectGPUMemory, usedOffset: uint64]] | |
94 indirectBuffers: seq[tuple[buffer: Buffer[IndirectGPUMemory], btype: BufferType, usedOffset: uint64]] | |
95 directBuffers: seq[tuple[buffer: Buffer[DirectGPUMemory], btype: BufferType, usedOffset: uint64]] | |
96 | 98 |
97 func size(texture: Texture): uint64 = | 99 func size(texture: Texture): uint64 = |
98 texture.data.len * sizeof(elementType(texture.data)) | 100 texture.data.len * sizeof(elementType(texture.data)) |
99 | 101 |
100 func depth(texture: Texture): int = | 102 func depth(texture: Texture): int = |
101 default(elementType(texture.data)).len | 103 default(elementType(texture.data)).len |
102 | 104 |
103 func pointerOffset[T: SomeInteger](p: pointer, offset: T): pointer = | 105 func pointerAddOffset[T: SomeInteger](p: pointer, offset: T): pointer = |
104 cast[pointer](cast[T](p) + offset) | 106 cast[pointer](cast[T](p) + offset) |
105 | 107 |
108 func usage(bType: BufferType): seq[VkBufferUsageFlagBits] = | |
109 case bType: | |
110 of VertexBuffer: @[VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | |
111 of VertexBufferMapped: @[VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | |
112 of IndexBuffer: @[VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | |
113 of IndexBufferMapped: @[VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | |
114 of UniformBuffer: @[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | |
115 of UniformBufferMapped: @[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | |
106 | 116 |
107 proc GetVkFormat(depth: int, usage: openArray[VkImageUsageFlagBits]): VkFormat = | 117 proc GetVkFormat(depth: int, usage: openArray[VkImageUsageFlagBits]): VkFormat = |
108 const DEPTH_FORMAT_MAP = [ | 118 const DEPTH_FORMAT_MAP = [ |
109 0: [VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED], | 119 0: [VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED], |
110 1: [VK_FORMAT_R8_SRGB, VK_FORMAT_R8_UNORM], | 120 1: [VK_FORMAT_R8_SRGB, VK_FORMAT_R8_UNORM], |
320 return 1 | 330 return 1 |
321 | 331 |
322 template sType(descriptorSet: DescriptorSet): untyped = | 332 template sType(descriptorSet: DescriptorSet): untyped = |
323 get(genericParams(typeof(gpuData)), 1) | 333 get(genericParams(typeof(gpuData)), 1) |
324 | 334 |
325 template UsesIndirectMemory(gpuData: GPUData): untyped = | 335 template bufferType(gpuData: GPUData): untyped = |
326 get(genericParams(typeof(gpuData)), 1) is IndirectGPUMemory | 336 get(genericParams(typeof(gpuData)), 1) |
327 template UsesDirectMemory(gpuData: GPUData): untyped = | 337 func NeedsMapping(bType: BufferType): bool = |
328 get(genericParams(typeof(gpuData)), 1) is DirectGPUMemory | 338 bType in [VertexBufferMapped, IndexBufferMapped, UniformBufferMapped] |
339 template NeedsMapping(gpuData: GPUData): untyped = | |
340 gpuData.bufferType.NeedsMapping | |
329 | 341 |
330 template size(gpuArray: GPUArray): uint64 = | 342 template size(gpuArray: GPUArray): uint64 = |
331 (gpuArray.data.len * sizeof(elementType(gpuArray.data))).uint64 | 343 (gpuArray.data.len * sizeof(elementType(gpuArray.data))).uint64 |
332 template size(gpuValue: GPUValue): uint64 = | 344 template size(gpuValue: GPUValue): uint64 = |
333 sizeof(gpuValue.data).uint64 | 345 sizeof(gpuValue.data).uint64 |
334 | 346 |
335 template rawPointer(gpuArray: GPUArray): pointer = | 347 template rawPointer(gpuArray: GPUArray): pointer = |
336 addr(gpuArray.data[0]) | 348 addr(gpuArray.data[0]) |
337 template rawPointer(gpuValue: GPUValue): pointer = | 349 template rawPointer(gpuValue: GPUValue): pointer = |
338 addr(gpuValue.data) | 350 addr(gpuValue.data) |
339 | |
340 proc RequiredMemorySize(buffer: VkBuffer): uint64 = | |
341 var req: VkMemoryRequirements | |
342 vkGetBufferMemoryRequirements(vulkan.device, buffer, addr(req)) | |
343 return req.size | |
344 | |
345 proc RequiredMemorySize(image: VkImage): uint64 = | |
346 var req: VkMemoryRequirements | |
347 vkGetImageMemoryRequirements(vulkan.device, image, addr req) | |
348 return req.size | |
349 | 351 |
350 proc GetPhysicalDevice(instance: VkInstance): VkPhysicalDevice = | 352 proc GetPhysicalDevice(instance: VkInstance): VkPhysicalDevice = |
351 var nDevices: uint32 | 353 var nDevices: uint32 |
352 checkVkResult vkEnumeratePhysicalDevices(instance, addr(nDevices), nil) | 354 checkVkResult vkEnumeratePhysicalDevices(instance, addr(nDevices), nil) |
353 var devices = newSeq[VkPhysicalDevice](nDevices) | 355 var devices = newSeq[VkPhysicalDevice](nDevices) |
369 score = props.limits.maxImageDimension2D | 371 score = props.limits.maxImageDimension2D |
370 result = pDevice | 372 result = pDevice |
371 | 373 |
372 assert score > 0, "Unable to find integrated or discrete GPU" | 374 assert score > 0, "Unable to find integrated or discrete GPU" |
373 | 375 |
374 | 376 proc IsMappable(memoryTypeIndex: uint32): bool = |
375 proc GetDirectMemoryType(): uint32 = | |
376 var physicalProperties: VkPhysicalDeviceMemoryProperties | 377 var physicalProperties: VkPhysicalDeviceMemoryProperties |
377 vkGetPhysicalDeviceMemoryProperties(vulkan.physicalDevice, addr(physicalProperties)) | 378 vkGetPhysicalDeviceMemoryProperties(vulkan.physicalDevice, addr(physicalProperties)) |
378 | 379 let flags = toEnums(physicalProperties.memoryTypes[memoryTypeIndex].propertyFlags) |
379 var biggestHeap: uint64 = 0 | 380 return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in flags |
380 result = high(uint32) | |
381 # try to find host-visible type | |
382 for i in 0'u32 ..< physicalProperties.memoryTypeCount: | |
383 let flags = toEnums(physicalProperties.memoryTypes[i].propertyFlags) | |
384 if VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in flags: | |
385 let size = physicalProperties.memoryHeaps[physicalProperties.memoryTypes[i].heapIndex].size | |
386 if size > biggestHeap: | |
387 biggestHeap = size | |
388 result = i | |
389 assert result != high(uint32), "There is not host visible memory. This is likely a driver bug." | |
390 | 381 |
391 proc GetQueueFamily(pDevice: VkPhysicalDevice, qType: VkQueueFlagBits): uint32 = | 382 proc GetQueueFamily(pDevice: VkPhysicalDevice, qType: VkQueueFlagBits): uint32 = |
392 var nQueuefamilies: uint32 | 383 var nQueuefamilies: uint32 |
393 vkGetPhysicalDeviceQueueFamilyProperties(pDevice, addr nQueuefamilies, nil) | 384 vkGetPhysicalDeviceQueueFamilyProperties(pDevice, addr nQueuefamilies, nil) |
394 var queuFamilies = newSeq[VkQueueFamilyProperties](nQueuefamilies) | 385 var queuFamilies = newSeq[VkQueueFamilyProperties](nQueuefamilies) |
400 | 391 |
401 proc GetSurfaceFormat(): VkFormat = | 392 proc GetSurfaceFormat(): VkFormat = |
402 # EVERY windows driver and almost every linux driver should support this | 393 # EVERY windows driver and almost every linux driver should support this |
403 VK_FORMAT_B8G8R8A8_SRGB | 394 VK_FORMAT_B8G8R8A8_SRGB |
404 | 395 |
405 proc UpdateGPUBuffer(gpuData: GPUData) = | |
406 if gpuData.size == 0: | |
407 return | |
408 when UsesDirectMemory(gpuData): | |
409 copyMem(pointerOffset(gpuData.buffer.rawPointer, gpuData.offset), gpuData.rawPointer, gpuData.size) | |
410 else: | |
411 WithStagingBuffer((gpuData.buffer.vk, gpuData.offset), gpuData.buffer.vk.RequiredMemorySize(), GetDirectMemoryType(), stagingPtr): | |
412 copyMem(stagingPtr, gpuData.rawPointer, gpuData.size) | |
413 | |
414 proc UpdateAllGPUBuffers[T](value: T) = | |
415 for name, fieldvalue in value.fieldPairs(): | |
416 when typeof(fieldvalue) is GPUData: | |
417 UpdateGPUBuffer(fieldvalue) | |
418 | |
419 proc InitDescriptorSet( | 396 proc InitDescriptorSet( |
420 renderData: RenderData, | 397 renderData: RenderData, |
421 layout: VkDescriptorSetLayout, | 398 layout: VkDescriptorSetLayout, |
422 descriptorSet: var DescriptorSet, | 399 descriptorSet: var DescriptorSet, |
423 ) = | 400 ) = |
424 # santization checks | 401 # santization checks |
425 for name, value in descriptorSet.data.fieldPairs: | 402 for name, value in descriptorSet.data.fieldPairs: |
426 when typeof(value) is GPUValue: | 403 when typeof(value) is GPUValue: |
427 assert value.buffer.vk.Valid | 404 assert value.buffer.vk.Valid |
428 # TODO: | 405 elif typeof(value) is Texture: |
429 # when typeof(value) is Texture: | 406 assert value.vk.Valid |
430 # assert value.texture.vk.Valid | 407 assert value.imageview.Valid |
431 | 408 assert value.sampler.Valid |
432 # TODO: missing stuff here? only for FiF, but not multiple different sets? | 409 |
433 # allocate | 410 # allocate |
434 var layouts = newSeqWith(descriptorSet.vk.len, layout) | 411 var layouts = newSeqWith(descriptorSet.vk.len, layout) |
435 var allocInfo = VkDescriptorSetAllocateInfo( | 412 var allocInfo = VkDescriptorSetAllocateInfo( |
436 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, | 413 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, |
437 descriptorPool: renderData.descriptorPool, | 414 descriptorPool: renderData.descriptorPool, |
894 addr(createInfo), | 871 addr(createInfo), |
895 nil, | 872 nil, |
896 addr(result.vk) | 873 addr(result.vk) |
897 ) | 874 ) |
898 | 875 |
899 proc AllocateIndirectMemory(size: uint64): IndirectGPUMemory = | 876 proc AllocateNewMemoryBlock(size: uint64, mType: uint32): MemoryBlock = |
900 # chooses biggest memory type that has NOT VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | 877 result = MemoryBlock( |
901 result.size = size | 878 vk: svkAllocateMemory(size, mType), |
902 result.needsTransfer = true | 879 size: size, |
903 | 880 rawPointer: nil, |
904 # find a good memory type | 881 offsetNextFree: 0, |
905 var physicalProperties: VkPhysicalDeviceMemoryProperties | 882 ) |
906 vkGetPhysicalDeviceMemoryProperties(vulkan.physicalDevice, addr physicalProperties) | 883 if mType.IsMappable(): |
907 | 884 checkVkResult vkMapMemory( |
908 var biggestHeap: uint64 = 0 | 885 device = vulkan.device, |
909 var memoryTypeIndex = high(uint32) | 886 memory = result.vk, |
910 # try to find non-host-visible type | 887 offset = 0'u64, |
911 for i in 0'u32 ..< physicalProperties.memoryTypeCount: | 888 size = result.size, |
912 if not (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in toEnums(physicalProperties.memoryTypes[i].propertyFlags)): | 889 flags = VkMemoryMapFlags(0), |
913 let size = physicalProperties.memoryHeaps[physicalProperties.memoryTypes[i].heapIndex].size | 890 ppData = addr(result.rawPointer) |
914 if size > biggestHeap: | 891 ) |
915 biggestHeap = size | 892 |
916 memoryTypeIndex = i | 893 proc FlushAllMemory(renderData: RenderData) = |
917 | 894 var flushRegions = newSeq[VkMappedMemoryRange]() |
918 # If we did not found a device-only memory type, let's just take the biggest overall | 895 for memoryBlocks in renderData.memory: |
919 if memoryTypeIndex == high(uint32): | 896 for memoryBlock in memoryBlocks: |
920 result.needsTransfer = false | 897 if memoryBlock.rawPointer != nil and memoryBlock.offsetNextFree > 0: |
921 for i in 0'u32 ..< physicalProperties.memoryTypeCount: | 898 flushRegions.add VkMappedMemoryRange( |
922 let size = physicalProperties.memoryHeaps[physicalProperties.memoryTypes[i].heapIndex].size | 899 sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, |
923 if size > biggestHeap: | 900 memory: memoryBlock.vk, |
924 biggestHeap = size | 901 size: memoryBlock.offsetNextFree, |
925 memoryTypeIndex = i | 902 ) |
926 | 903 if flushRegions.len > 0: |
927 assert memoryTypeIndex != high(uint32), "Unable to find indirect memory type" | 904 checkVkResult vkFlushMappedMemoryRanges(vulkan.device, flushRegions.len.uint32, flushRegions.ToCPointer()) |
928 result.vk = svkAllocateMemory(result.size, memoryTypeIndex) | 905 |
929 | 906 proc AllocateNewBuffer(renderData: var RenderData, size: uint64, bufferType: BufferType): Buffer = |
930 proc AllocateDirectMemory(size: uint64): DirectGPUMemory = | 907 result = Buffer( |
931 result.size = size | 908 vk: svkCreateBuffer(size, bufferType.usage), |
932 | 909 size: size, |
933 # find a good memory type | 910 rawPointer: nil, |
934 var physicalProperties: VkPhysicalDeviceMemoryProperties | 911 offsetNextFree: 0, |
935 vkGetPhysicalDeviceMemoryProperties(vulkan.physicalDevice, addr physicalProperties) | 912 ) |
936 | 913 let memoryRequirements = svkGetBufferMemoryRequirements(result.vk) |
937 var biggestHeap: uint64 = 0 | 914 let memoryType = BestMemory(mappable = bufferType.NeedsMapping, filter = memoryRequirements.memoryTypes) |
938 var memoryTypeIndex = high(uint32) | 915 |
939 # try to find host-visible type | 916 # check if there is an existing allocated memory block that is large enough to be used |
940 for i in 0 ..< physicalProperties.memoryTypeCount: | 917 var selectedBlockI = -1 |
941 let flags = toEnums(physicalProperties.memoryTypes[i].propertyFlags) | 918 for i in 0 ..< renderData.memory[memoryType].len: |
942 if VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in flags: | 919 let memoryBlock = renderData.memory[memoryType][i] |
943 let size = physicalProperties.memoryHeaps[physicalProperties.memoryTypes[i].heapIndex].size | 920 if memoryBlock.size - alignedTo(memoryBlock.offsetNextFree, memoryRequirements.alignment) >= memoryRequirements.size: |
944 if size > biggestHeap: | 921 selectedBlockI = i |
945 biggestHeap = size | 922 break |
946 memoryTypeIndex = i | 923 # otherwise, allocate a new block of memory and use that |
947 | 924 if selectedBlockI < 0: |
948 assert memoryTypeIndex != high(uint32), "Unable to find indirect memory type" | 925 selectedBlockI = renderData.memory[memoryType].len |
949 result.vk = svkAllocateMemory(result.size, GetDirectMemoryType()) | 926 renderData.memory[memoryType].add AllocateNewMemoryBlock( |
950 checkVkResult vkMapMemory( | 927 size = max(size, MEMORY_BLOCK_ALLOCATION_SIZE), |
951 device = vulkan.device, | 928 mType = memoryType |
952 memory = result.vk, | 929 ) |
953 offset = 0'u64, | 930 |
954 size = result.size, | 931 let selectedBlock = renderData.memory[memoryType][selectedBlockI] |
955 flags = VkMemoryMapFlags(0), | 932 renderData.memory[memoryType][selectedBlockI].offsetNextFree = alignedTo( |
956 ppData = addr(result.rawPointer) | 933 selectedBlock.offsetNextFree, |
957 ) | 934 memoryRequirements.alignment, |
958 | 935 ) |
959 proc AllocateIndirectBuffer(renderData: var RenderData, size: uint64, btype: BufferType) = | 936 checkVkResult vkBindBufferMemory( |
960 if size == 0: | 937 vulkan.device, |
938 result.vk, | |
939 selectedBlock.vk, | |
940 selectedBlock.offsetNextFree, | |
941 ) | |
942 result.rawPointer = selectedBlock.rawPointer.pointerAddOffset(selectedBlock.offsetNextFree) | |
943 renderData.memory[memoryType][selectedBlockI].offsetNextFree += memoryRequirements.size | |
944 | |
945 proc AssignBuffers[T](renderdata: var RenderData, data: var T) = | |
946 for name, value in fieldPairs(data): | |
947 when typeof(value) is GPUData: | |
948 | |
949 # find buffer that has space | |
950 var selectedBufferI = -1 | |
951 for i in 0 ..< renderData.buffers[value.bufferType].len: | |
952 let buffer = renderData.buffers[value.bufferType][i] | |
953 if buffer.size - alignedTo(buffer.offsetNextFree, BUFFER_ALIGNMENT) >= value.size: | |
954 selectedBufferI = i | |
955 | |
956 # otherwise create new buffer | |
957 if selectedBufferI < 0: | |
958 selectedBufferI = renderdata.buffers[value.bufferType].len | |
959 renderdata.buffers[value.bufferType].add renderdata.AllocateNewBuffer( | |
960 size = max(value.size, BUFFER_ALLOCATION_SIZE), | |
961 bType = value.bufferType, | |
962 mappable = value.NeedsMapping, | |
963 ) | |
964 | |
965 # assigne value | |
966 let selectedBuffer = renderdata.buffers[value.bufferType][selectedBufferI] | |
967 renderdata.buffers[value.bufferType][selectedBufferI].offsetNextFree = alignedTo( | |
968 selectedBuffer.offsetNextFree, | |
969 BUFFER_ALIGNMENT | |
970 ) | |
971 value.buffer = selectedBuffer | |
972 value.offset = renderdata.buffers[value.bufferType][selectedBufferI].offsetNextFree | |
973 renderdata.buffers[value.bufferType][selectedBufferI].offsetNextFree += value.size | |
974 | |
975 proc UpdateGPUBuffer(gpuData: GPUData) = | |
976 if gpuData.size == 0: | |
961 return | 977 return |
962 var buffer = Buffer[IndirectGPUMemory](size: size, rawPointer: nil) | 978 when NeedsMapping(gpuData): |
963 | 979 copyMem(pointerAddOffset(gpuData.buffer.rawPointer, gpuData.offset), gpuData.rawPointer, gpuData.size) |
964 let usageFlags = case btype: | 980 else: |
965 of VertexBuffer: [VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | 981 WithStagingBuffer((gpuData.buffer.vk, gpuData.offset), gpuData.buffer.size, stagingPtr): |
966 of IndexBuffer: [VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | 982 copyMem(stagingPtr, gpuData.rawPointer, gpuData.size) |
967 of UniformBuffer: [VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | 983 |
968 | 984 proc UpdateAllGPUBuffers[T](value: T) = |
969 # iterate through memory areas to find big enough free space | 985 for name, fieldvalue in value.fieldPairs(): |
970 # TODO: dynamically expand memory allocations | 986 when typeof(fieldvalue) is GPUData: |
971 # TODO: use RequiredMemorySize() | 987 UpdateGPUBuffer(fieldvalue) |
972 for (memory, usedOffset) in renderData.indirectMemory.mitems: | 988 |
973 if memory.size - usedOffset >= size: | |
974 # create buffer | |
975 buffer.vk = svkCreateBuffer(buffer.size, usageFlags) | |
976 checkVkResult vkBindBufferMemory(vulkan.device, buffer.vk, memory.vk, usedOffset) | |
977 renderData.indirectBuffers.add (buffer, btype, 0'u64) | |
978 # update memory area offset | |
979 usedOffset = alignedTo(usedOffset + size, MEMORY_ALIGNMENT) | |
980 return | |
981 | |
982 assert false, "Did not find allocated memory region with enough space" | |
983 | |
984 proc AllocateDirectBuffer(renderData: var RenderData, size: uint64, btype: BufferType) = | |
985 if size == 0: | |
986 return | |
987 | |
988 var buffer = Buffer[DirectGPUMemory](size: size) | |
989 | |
990 let usageFlags = case btype: | |
991 of VertexBuffer: [VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | |
992 of IndexBuffer: [VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | |
993 of UniformBuffer: [VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | |
994 | |
995 # iterate through memory areas to find big enough free space | |
996 # TODO: dynamically expand memory allocations | |
997 # TODO: use RequiredMemorySize() | |
998 for (memory, usedOffset) in renderData.directMemory.mitems: | |
999 if memory.size - usedOffset >= size: | |
1000 buffer.vk = svkCreateBuffer(buffer.size, usageFlags) | |
1001 checkVkResult vkBindBufferMemory(vulkan.device, buffer.vk, memory.vk, usedOffset) | |
1002 buffer.rawPointer = pointerOffset(memory.rawPointer, usedOffset) | |
1003 renderData.directBuffers.add (buffer, btype, 0'u64) | |
1004 # update memory area offset | |
1005 usedOffset = alignedTo(usedOffset + size, MEMORY_ALIGNMENT) | |
1006 return | |
1007 | |
1008 assert false, "Did not find allocated memory region with enough space" | |
1009 | 989 |
1010 proc InitRenderData(descriptorPoolLimit = 1024'u32): RenderData = | 990 proc InitRenderData(descriptorPoolLimit = 1024'u32): RenderData = |
1011 # allocate descriptor pools | 991 # allocate descriptor pools |
1012 var poolSizes = [ | 992 var poolSizes = [ |
1013 VkDescriptorPoolSize(thetype: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, descriptorCount: descriptorPoolLimit), | 993 VkDescriptorPoolSize(thetype: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, descriptorCount: descriptorPoolLimit), |
1018 poolSizeCount: poolSizes.len.uint32, | 998 poolSizeCount: poolSizes.len.uint32, |
1019 pPoolSizes: poolSizes.ToCPointer, | 999 pPoolSizes: poolSizes.ToCPointer, |
1020 maxSets: descriptorPoolLimit, | 1000 maxSets: descriptorPoolLimit, |
1021 ) | 1001 ) |
1022 checkVkResult vkCreateDescriptorPool(vulkan.device, addr(poolInfo), nil, addr(result.descriptorPool)) | 1002 checkVkResult vkCreateDescriptorPool(vulkan.device, addr(poolInfo), nil, addr(result.descriptorPool)) |
1023 | |
1024 # allocate some memory | |
1025 var initialAllocationSize = 1_000_000_000'u64 # TODO: make this more dynamic or something? | |
1026 result.indirectMemory = @[(memory: AllocateIndirectMemory(size = initialAllocationSize), usedOffset: 0'u64)] | |
1027 result.directMemory = @[(memory: AllocateDirectMemory(size = initialAllocationSize), usedOffset: 0'u64)] | |
1028 | |
1029 proc FlushDirectMemory(renderData: RenderData) = | |
1030 var flushRegions = newSeqOfCap[VkMappedMemoryRange](renderData.directMemory.len) | |
1031 for entry in renderData.directMemory: | |
1032 if entry.usedOffset > 0: | |
1033 flushRegions.add VkMappedMemoryRange( | |
1034 sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, | |
1035 memory: entry.memory.vk, | |
1036 size: entry.usedOffset, | |
1037 ) | |
1038 if flushRegions.len > 0: | |
1039 checkVkResult vkFlushMappedMemoryRanges(vulkan.device, flushRegions.len.uint32, flushRegions.ToCPointer()) | |
1040 | |
1041 # For the Get*BufferSize: | |
1042 # BUFFER_ALIGNMENT is just added for a rough estimate, to ensure we have enough space to align when binding | |
1043 proc GetIndirectBufferSizes[T](data: T): uint64 = | |
1044 for name, value in fieldPairs(data): | |
1045 when not hasCustomPragma(value, VertexIndices): | |
1046 when typeof(value) is GPUData: | |
1047 when UsesIndirectMemory(value): | |
1048 result += value.size + BUFFER_ALIGNMENT | |
1049 proc GetIndirectBufferSizes(data: DescriptorSet): uint64 = | |
1050 GetIndirectBufferSizes(data.data) | |
1051 proc GetDirectBufferSizes[T](data: T): uint64 = | |
1052 for name, value in fieldPairs(data): | |
1053 when not hasCustomPragma(value, VertexIndices): | |
1054 when typeof(value) is GPUData: | |
1055 when UsesDirectMemory(value): | |
1056 result += value.size + BUFFER_ALIGNMENT | |
1057 proc GetDirectBufferSizes(data: DescriptorSet): uint64 = | |
1058 GetDirectBufferSizes(data.data) | |
1059 proc GetIndirectIndexBufferSizes[T](data: T): uint64 = | |
1060 for name, value in fieldPairs(data): | |
1061 when hasCustomPragma(value, VertexIndices): | |
1062 static: assert typeof(value) is GPUArray, "Index buffers must be of type GPUArray" | |
1063 static: assert elementType(value.data) is uint8 or elementType(value.data) is uint16 or elementType(value.data) is uint32 | |
1064 when UsesIndirectMemory(value): | |
1065 result += value.size + BUFFER_ALIGNMENT | |
1066 proc GetDirectIndexBufferSizes[T](data: T): uint64 = | |
1067 for name, value in fieldPairs(data): | |
1068 when hasCustomPragma(value, VertexIndices): | |
1069 static: assert typeof(value) is GPUArray, "Index buffers must be of type GPUArray" | |
1070 static: assert elementType(value.data) is uint8 or elementType(value.data) is uint16 or elementType(value.data) is uint32 | |
1071 when UsesDirectMemory(value): | |
1072 result += value.size + BUFFER_ALIGNMENT | |
1073 | |
1074 proc AssignIndirectBuffers[T](renderdata: var RenderData, btype: BufferType, data: var T) = | |
1075 for name, value in fieldPairs(data): | |
1076 when typeof(value) is GPUData: | |
1077 when UsesIndirectMemory(value): | |
1078 # find next buffer of correct type with enough free space | |
1079 if btype == IndexBuffer == value.hasCustomPragma(VertexIndices): | |
1080 var foundBuffer = false | |
1081 for (buffer, bt, offset) in renderData.indirectBuffers.mitems: | |
1082 if bt == btype and buffer.size - offset >= value.size: | |
1083 assert not value.buffer.vk.Valid, "GPUData-Buffer has already been assigned" | |
1084 assert buffer.vk.Valid, "RenderData-Buffer has not yet been created" | |
1085 value.buffer = buffer | |
1086 value.offset = offset | |
1087 offset = alignedTo(offset + value.size, BUFFER_ALIGNMENT) | |
1088 foundBuffer = true | |
1089 break | |
1090 assert foundBuffer, &"Unable to find large enough '{btype}' for '{data}'" | |
1091 proc AssignIndirectBuffers(renderdata: var RenderData, btype: BufferType, data: var DescriptorSet) = | |
1092 AssignIndirectBuffers(renderdata, btype, data.data) | |
1093 proc AssignDirectBuffers[T](renderdata: var RenderData, btype: BufferType, data: var T) = | |
1094 for name, value in fieldPairs(data): | |
1095 when typeof(value) is GPUData: | |
1096 when UsesDirectMemory(value): | |
1097 # find next buffer of correct type with enough free space | |
1098 if btype == IndexBuffer == value.hasCustomPragma(VertexIndices): | |
1099 var foundBuffer = false | |
1100 for (buffer, bt, offset) in renderData.directBuffers.mitems: | |
1101 if bt == btype and buffer.size - offset >= value.size: | |
1102 assert not value.buffer.vk.Valid, "GPUData-Buffer has already been assigned" | |
1103 assert buffer.vk.Valid, "RenderData-Buffer has not yet been created" | |
1104 value.buffer = buffer | |
1105 value.offset = offset | |
1106 offset = alignedTo(offset + value.size, BUFFER_ALIGNMENT) | |
1107 foundBuffer = true | |
1108 break | |
1109 assert foundBuffer, &"Unable to find large enough '{btype}' for '{data}'" | |
1110 proc AssignDirectBuffers(renderdata: var RenderData, btype: BufferType, data: var DescriptorSet) = | |
1111 AssignDirectBuffers(renderdata, btype, data.data) | |
1112 | 1003 |
1113 proc TransitionImageLayout(image: VkImage, oldLayout, newLayout: VkImageLayout) = | 1004 proc TransitionImageLayout(image: VkImage, oldLayout, newLayout: VkImageLayout) = |
1114 var | 1005 var |
1115 barrier = VkImageMemoryBarrier( | 1006 barrier = VkImageMemoryBarrier( |
1116 sType: VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | 1007 sType: VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, |
1211 assert texture.offset == 0 | 1102 assert texture.offset == 0 |
1212 const usage = [VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_USAGE_SAMPLED_BIT] | 1103 const usage = [VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_USAGE_SAMPLED_BIT] |
1213 | 1104 |
1214 texture.format = GetVkFormat(texture.depth, usage = usage) | 1105 texture.format = GetVkFormat(texture.depth, usage = usage) |
1215 texture.vk = svkCreate2DImage(texture.width, texture.height, texture.format, usage) | 1106 texture.vk = svkCreate2DImage(texture.width, texture.height, texture.format, usage) |
1216 let size = texture.vk.RequiredMemorySize() | 1107 let reqs = texture.vk.svkGetImageMemoryRequirements() |
1217 | 1108 |
1218 when genericParams(typeof(texture)).get(1) is IndirectGPUMemory: | 1109 # TODO |
1219 for (memory, usedOffset) in renderData.indirectMemory.mitems: | 1110 |
1220 if memory.size - usedOffset >= size: | 1111 for (memory, usedOffset) in renderData.indirectMemory.mitems: |
1221 texture.memory = memory | 1112 if memory.size - usedOffset >= size: |
1222 texture.offset = usedOffset | 1113 texture.memory = memory |
1223 # update memory area offset | 1114 texture.offset = usedOffset |
1224 usedOffset = alignedTo(usedOffset + size, MEMORY_ALIGNMENT) | 1115 # update memory area offset |
1225 break | 1116 usedOffset = alignedTo(usedOffset + size, MEMORY_ALIGNMENT) |
1226 elif genericParams(typeof(texture)).get(1) is DirectGPUMemory: | 1117 break |
1227 for (memory, usedOffset) in renderData.directMemory.mitems: | |
1228 if memory.size - usedOffset >= size: | |
1229 texture.memory = memory | |
1230 texture.offset = usedOffset | |
1231 # update memory area offset | |
1232 usedOffset = alignedTo(usedOffset + size, MEMORY_ALIGNMENT) | |
1233 break | |
1234 | 1118 |
1235 checkVkResult vkBindImageMemory( | 1119 checkVkResult vkBindImageMemory( |
1236 vulkan.device, | 1120 vulkan.device, |
1237 texture.vk, | 1121 texture.vk, |
1238 texture.memory.vk, | 1122 texture.memory.vk, |
1239 texture.offset, | 1123 texture.offset, |
1240 ) | 1124 ) |
1241 | 1125 |
1242 # data transfer and layout transition | 1126 # data transfer and layout transition |
1243 TransitionImageLayout(texture.vk, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) | 1127 TransitionImageLayout(texture.vk, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) |
1244 WithStagingBuffer((texture.vk, texture.imageview, texture.width, texture.height), size, GetDirectMemoryType(), stagingPtr): | 1128 WithStagingBuffer((texture.vk, texture.imageview, texture.width, texture.height), size, stagingPtr): |
1245 copyMem(stagingPtr, texture.data.ToCPointer, size) | 1129 copyMem(stagingPtr, texture.data.ToCPointer, size) |
1246 TransitionImageLayout(texture.vk, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) | 1130 TransitionImageLayout(texture.vk, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) |
1247 | 1131 |
1248 texture.imageview = createImageView(texture.vk, texture.format) | 1132 texture.imageview = createImageView(texture.vk, texture.format) |
1249 texture.sampler = createSampler() | 1133 texture.sampler = createSampler() |
1374 import semicongine/vulkan/physicaldevice | 1258 import semicongine/vulkan/physicaldevice |
1375 import std/options | 1259 import std/options |
1376 | 1260 |
1377 type | 1261 type |
1378 MeshA = object | 1262 MeshA = object |
1379 position: GPUArray[Vec3f, IndirectGPUMemory] | 1263 position: GPUArray[Vec3f, VertexBuffer] |
1380 indices {.VertexIndices.}: GPUArray[uint16, IndirectGPUMemory] | 1264 indices: GPUArray[uint16, IndexBuffer] |
1381 InstanceA = object | 1265 InstanceA = object |
1382 rotation: GPUArray[Vec4f, IndirectGPUMemory] | 1266 rotation: GPUArray[Vec4f, VertexBuffer] |
1383 objPosition: GPUArray[Vec3f, IndirectGPUMemory] | 1267 objPosition: GPUArray[Vec3f, VertexBuffer] |
1384 MaterialA = object | 1268 MaterialA = object |
1385 reflection: float32 | 1269 reflection: float32 |
1386 baseColor: Vec3f | 1270 baseColor: Vec3f |
1387 UniformsA = object | 1271 UniformsA = object |
1388 defaultTexture: Texture[TVec3[uint8], IndirectGPUMemory] | 1272 defaultTexture: Texture[TVec3[uint8]] |
1389 defaultMaterial: GPUValue[MaterialA, IndirectGPUMemory] | 1273 defaultMaterial: GPUValue[MaterialA, UniformBuffer] |
1390 materials: GPUValue[array[3, MaterialA], IndirectGPUMemory] | 1274 materials: GPUValue[array[3, MaterialA], UniformBuffer] |
1391 materialTextures: array[3, Texture[TVec3[uint8], IndirectGPUMemory]] | 1275 materialTextures: array[3, Texture[TVec3[uint8]]] |
1392 ShaderSettings = object | 1276 ShaderSettings = object |
1393 gamma: float32 | 1277 gamma: float32 |
1394 GlobalsA = object | 1278 GlobalsA = object |
1395 fontAtlas: Texture[TVec3[uint8], IndirectGPUMemory] | 1279 fontAtlas: Texture[TVec3[uint8]] |
1396 settings: GPUValue[ShaderSettings, IndirectGPUMemory] | 1280 settings: GPUValue[ShaderSettings, UniformBuffer] |
1397 | 1281 |
1398 ShaderA = object | 1282 ShaderA = object |
1399 # vertex input | 1283 # vertex input |
1400 position {.VertexAttribute.}: Vec3f | 1284 position {.VertexAttribute.}: Vec3f |
1401 objPosition {.InstanceAttribute.}: Vec3f | 1285 objPosition {.InstanceAttribute.}: Vec3f |
1440 queueFamilyIndex: qfi, | 1324 queueFamilyIndex: qfi, |
1441 queue: svkGetDeviceQueue(dev, qfi, VK_QUEUE_GRAPHICS_BIT) | 1325 queue: svkGetDeviceQueue(dev, qfi, VK_QUEUE_GRAPHICS_BIT) |
1442 ) | 1326 ) |
1443 | 1327 |
1444 var myMesh1 = MeshA( | 1328 var myMesh1 = MeshA( |
1445 position: GPUArray[Vec3f, IndirectGPUMemory](data: @[NewVec3f(0, 0, ), NewVec3f(0, 0, ), NewVec3f(0, 0, )]), | 1329 position: GPUArray[Vec3f, VertexBuffer](data: @[NewVec3f(0, 0, ), NewVec3f(0, 0, ), NewVec3f(0, 0, )]), |
1446 ) | 1330 ) |
1447 var uniforms1 = DescriptorSet[UniformsA, MaterialSet]( | 1331 var uniforms1 = DescriptorSet[UniformsA, MaterialSet]( |
1448 data: UniformsA( | 1332 data: UniformsA( |
1449 defaultTexture: Texture[TVec3[uint8], IndirectGPUMemory](width: 1, height: 1, data: @[TVec3[uint8]([0'u8, 0'u8, 0'u8])]), | 1333 defaultTexture: Texture[TVec3[uint8]](width: 1, height: 1, data: @[TVec3[uint8]([0'u8, 0'u8, 0'u8])]), |
1450 materials: GPUValue[array[3, MaterialA], IndirectGPUMemory](data: [ | 1334 materials: GPUValue[array[3, MaterialA], UniformBuffer](data: [ |
1451 MaterialA(reflection: 0, baseColor: NewVec3f(1, 0, 0)), | 1335 MaterialA(reflection: 0, baseColor: NewVec3f(1, 0, 0)), |
1452 MaterialA(reflection: 0.1, baseColor: NewVec3f(0, 1, 0)), | 1336 MaterialA(reflection: 0.1, baseColor: NewVec3f(0, 1, 0)), |
1453 MaterialA(reflection: 0.5, baseColor: NewVec3f(0, 0, 1)), | 1337 MaterialA(reflection: 0.5, baseColor: NewVec3f(0, 0, 1)), |
1454 ]), | 1338 ]), |
1455 materialTextures: [ | 1339 materialTextures: [ |
1456 Texture[TVec3[uint8], IndirectGPUMemory](width: 1, height: 1, data: @[TVec3[uint8]([0'u8, 0'u8, 0'u8])]), | 1340 Texture[TVec3[uint8]](width: 1, height: 1, data: @[TVec3[uint8]([0'u8, 0'u8, 0'u8])]), |
1457 Texture[TVec3[uint8], IndirectGPUMemory](width: 1, height: 1, data: @[TVec3[uint8]([0'u8, 0'u8, 0'u8])]), | 1341 Texture[TVec3[uint8]](width: 1, height: 1, data: @[TVec3[uint8]([0'u8, 0'u8, 0'u8])]), |
1458 Texture[TVec3[uint8], IndirectGPUMemory](width: 1, height: 1, data: @[TVec3[uint8]([0'u8, 0'u8, 0'u8])]), | 1342 Texture[TVec3[uint8]](width: 1, height: 1, data: @[TVec3[uint8]([0'u8, 0'u8, 0'u8])]), |
1459 ] | 1343 ] |
1460 ) | 1344 ) |
1461 ) | 1345 ) |
1462 var instances1 = InstanceA( | 1346 var instances1 = InstanceA( |
1463 rotation: GPUArray[Vec4f, IndirectGPUMemory](data: @[NewVec4f(1, 0, 0, 0.1), NewVec4f(0, 1, 0, 0.1)]), | 1347 rotation: GPUArray[Vec4f, VertexBuffer](data: @[NewVec4f(1, 0, 0, 0.1), NewVec4f(0, 1, 0, 0.1)]), |
1464 objPosition: GPUArray[Vec3f, IndirectGPUMemory](data: @[NewVec3f(0, 0, 0), NewVec3f(1, 1, 1)]), | 1348 objPosition: GPUArray[Vec3f, VertexBuffer](data: @[NewVec3f(0, 0, 0), NewVec3f(1, 1, 1)]), |
1465 ) | 1349 ) |
1466 var myGlobals = DescriptorSet[GlobalsA, GlobalSet]( | 1350 var myGlobals = DescriptorSet[GlobalsA, GlobalSet]( |
1467 data: GlobalsA( | 1351 data: GlobalsA( |
1468 fontAtlas: Texture[TVec3[uint8], IndirectGPUMemory](width: 1, height: 1, data: @[TVec3[uint8]([0'u8, 0'u8, 0'u8])]), | 1352 fontAtlas: Texture[TVec3[uint8]](width: 1, height: 1, data: @[TVec3[uint8]([0'u8, 0'u8, 0'u8])]), |
1469 settings: GPUValue[ShaderSettings, IndirectGPUMemory](data: ShaderSettings(gamma: 1.0)) | 1353 settings: GPUValue[ShaderSettings, UniformBuffer](data: ShaderSettings(gamma: 1.0)) |
1470 ) | 1354 ) |
1471 ) | 1355 ) |
1472 | 1356 |
1473 # setup for rendering (TODO: swapchain & framebuffers) | 1357 # setup for rendering (TODO: swapchain & framebuffers) |
1474 let renderpass = CreateRenderPass(GetSurfaceFormat()) | 1358 let renderpass = CreateRenderPass(GetSurfaceFormat()) |
1478 let shaderObject = CompileShader(shader) | 1362 let shaderObject = CompileShader(shader) |
1479 var pipeline1 = CreatePipeline(renderPass = renderpass, shader = shaderObject) | 1363 var pipeline1 = CreatePipeline(renderPass = renderpass, shader = shaderObject) |
1480 | 1364 |
1481 var renderdata = InitRenderData() | 1365 var renderdata = InitRenderData() |
1482 | 1366 |
1483 # buffer allocation | |
1484 echo "Allocating GPU buffers" | |
1485 | |
1486 var indirectVertexSizes = 0'u64 | |
1487 indirectVertexSizes += GetIndirectBufferSizes(myMesh1) | |
1488 indirectVertexSizes += GetIndirectBufferSizes(instances1) | |
1489 AllocateIndirectBuffer(renderdata, indirectVertexSizes, VertexBuffer) | |
1490 | |
1491 var directVertexSizes = 0'u64 | |
1492 directVertexSizes += GetDirectBufferSizes(myMesh1) | |
1493 directVertexSizes += GetDirectBufferSizes(instances1) | |
1494 AllocateDirectBuffer(renderdata, directVertexSizes, VertexBuffer) | |
1495 | |
1496 var indirectIndexSizes = 0'u64 | |
1497 indirectIndexSizes += GetIndirectIndexBufferSizes(myMesh1) | |
1498 AllocateIndirectBuffer(renderdata, indirectIndexSizes, IndexBuffer) | |
1499 | |
1500 var directIndexSizes = 0'u64 | |
1501 directIndexSizes += GetDirectIndexBufferSizes(myMesh1) | |
1502 AllocateDirectBuffer(renderdata, directIndexSizes, IndexBuffer) | |
1503 | |
1504 var indirectUniformSizes = 0'u64 | |
1505 indirectUniformSizes += GetIndirectBufferSizes(uniforms1) | |
1506 indirectUniformSizes += GetIndirectBufferSizes(myGlobals) | |
1507 AllocateIndirectBuffer(renderdata, indirectUniformSizes, UniformBuffer) | |
1508 | |
1509 var directUniformSizes = 0'u64 | |
1510 directUniformSizes += GetDirectBufferSizes(uniforms1) | |
1511 directUniformSizes += GetDirectBufferSizes(myGlobals) | |
1512 AllocateDirectBuffer(renderdata, directUniformSizes, UniformBuffer) | |
1513 | |
1514 | |
1515 # buffer assignment | 1367 # buffer assignment |
1516 echo "Assigning buffers to GPUData fields" | 1368 echo "Assigning buffers to GPUData fields" |
1517 | 1369 |
1518 # for meshes we do: | 1370 renderdata.AssignBuffers(myMesh1) |
1519 renderdata.AssignIndirectBuffers(VertexBuffer, myMesh1) | 1371 renderdata.AssignBuffers(instances1) |
1520 renderdata.AssignDirectBuffers(VertexBuffer, myMesh1) | 1372 renderdata.AssignBuffers(myGlobals) |
1521 renderdata.AssignIndirectBuffers(IndexBuffer, myMesh1) | 1373 renderdata.AssignBuffers(uniforms1) |
1522 renderdata.AssignDirectBuffers(IndexBuffer, myMesh1) | |
1523 | |
1524 # for instances we do: | |
1525 renderdata.AssignIndirectBuffers(VertexBuffer, instances1) | |
1526 renderdata.AssignDirectBuffers(VertexBuffer, instances1) | |
1527 | |
1528 # for uniforms/globals we do: | |
1529 renderdata.AssignIndirectBuffers(UniformBuffer, uniforms1) | |
1530 renderdata.AssignDirectBuffers(UniformBuffer, uniforms1) | |
1531 renderdata.AssignIndirectBuffers(UniformBuffer, myGlobals) | |
1532 renderdata.AssignDirectBuffers(UniformBuffer, myGlobals) | |
1533 | 1374 |
1534 renderdata.UploadTextures(myGlobals) | 1375 renderdata.UploadTextures(myGlobals) |
1535 renderdata.UploadTextures(uniforms1) | 1376 renderdata.UploadTextures(uniforms1) |
1536 | 1377 |
1537 # copy everything to GPU | 1378 # copy everything to GPU |
1538 echo "Copying all data to GPU memory" | 1379 echo "Copying all data to GPU memory" |
1539 UpdateAllGPUBuffers(myMesh1) | 1380 UpdateAllGPUBuffers(myMesh1) |
1540 UpdateAllGPUBuffers(instances1) | 1381 UpdateAllGPUBuffers(instances1) |
1541 UpdateAllGPUBuffers(uniforms1) | 1382 UpdateAllGPUBuffers(uniforms1) |
1542 UpdateAllGPUBuffers(myGlobals) | 1383 UpdateAllGPUBuffers(myGlobals) |
1543 renderdata.FlushDirectMemory() | 1384 renderdata.FlushAllMemory() |
1544 | 1385 |
1545 | 1386 |
1546 # descriptors | 1387 # descriptors |
1547 echo "Writing descriptors" | 1388 echo "Writing descriptors" |
1548 InitDescriptorSet(renderdata, pipeline1.descriptorSetLayouts[GlobalSet], myGlobals) | 1389 InitDescriptorSet(renderdata, pipeline1.descriptorSetLayouts[GlobalSet], myGlobals) |