comparison static_utils.nim @ 1187:b14861786b61 compiletime-tests

sync from bedroom to office
author sam <sam@basx.dev>
date Sun, 07 Jul 2024 15:08:04 +0700
parents 52e926efaac5
children aceb7697d37c
comparison
equal deleted inserted replaced
1186:52e926efaac5 1187:b14861786b61
58 rawPointer: pointer # if not nil, buffer is using mapped memory 58 rawPointer: pointer # if not nil, buffer is using mapped memory
59 offsetNextFree: uint64 59 offsetNextFree: uint64
60 60
61 Texture[T: TextureType] = object 61 Texture[T: TextureType] = object
62 vk: VkImage 62 vk: VkImage
63 memory: MemoryBlock
64 format: VkFormat
65 imageview: VkImageView 63 imageview: VkImageView
66 sampler: VkSampler 64 sampler: VkSampler
67 offset: uint64 65 # offset: uint64
68 size: uint64 66 # size: uint64
69 width: uint32 67 width: uint32
70 height: uint32 68 height: uint32
71 data: seq[T] 69 data: seq[T]
72 70
73 GPUArray[T: SupportedGPUType, TBuffer: static BufferType] = object 71 GPUArray[T: SupportedGPUType, TBuffer: static BufferType] = object
93 descriptorSetLayouts: array[DescriptorSetType, VkDescriptorSetLayout] 91 descriptorSetLayouts: array[DescriptorSetType, VkDescriptorSetLayout]
94 RenderData = object 92 RenderData = object
95 descriptorPool: VkDescriptorPool 93 descriptorPool: VkDescriptorPool
96 memory: array[VK_MAX_MEMORY_TYPES.int, seq[MemoryBlock]] 94 memory: array[VK_MAX_MEMORY_TYPES.int, seq[MemoryBlock]]
97 buffers: array[BufferType, seq[Buffer]] 95 buffers: array[BufferType, seq[Buffer]]
98
99 func size(texture: Texture): uint64 =
100 texture.data.len * sizeof(elementType(texture.data))
101 96
102 func depth(texture: Texture): int = 97 func depth(texture: Texture): int =
103 default(elementType(texture.data)).len 98 default(elementType(texture.data)).len
104 99
105 func pointerAddOffset[T: SomeInteger](p: pointer, offset: T): pointer = 100 func pointerAddOffset[T: SomeInteger](p: pointer, offset: T): pointer =
328 return 2 323 return 2
329 else: 324 else:
330 return 1 325 return 1
331 326
332 template sType(descriptorSet: DescriptorSet): untyped = 327 template sType(descriptorSet: DescriptorSet): untyped =
333 get(genericParams(typeof(gpuData)), 1) 328 get(genericParams(typeof(descriptorSet)), 1)
329
330 # template bufferType[T: SupportedGPUType, TBuffer: static BufferType](gpuArray: GPUArray[T, TBuffer]): untyped =
331 # TBuffer
332 # template bufferType[T: SupportedGPUType, TBuffer: static BufferType](gpuValue: GPUValue[T, TBuffer]): untyped =
333 # TBuffer
334 334
335 template bufferType(gpuData: GPUData): untyped = 335 template bufferType(gpuData: GPUData): untyped =
336 get(genericParams(typeof(gpuData)), 1) 336 typeof(gpuData).TBuffer
337 func NeedsMapping(bType: BufferType): bool = 337 func NeedsMapping(bType: BufferType): bool =
338 bType in [VertexBufferMapped, IndexBufferMapped, UniformBufferMapped] 338 bType in [VertexBufferMapped, IndexBufferMapped, UniformBufferMapped]
339 template NeedsMapping(gpuData: GPUData): untyped = 339 template NeedsMapping(gpuData: GPUData): untyped =
340 gpuData.bufferType.NeedsMapping 340 gpuData.bufferType.NeedsMapping
341 341
342 template size(gpuArray: GPUArray): uint64 = 342 template size(gpuArray: GPUArray): uint64 =
343 (gpuArray.data.len * sizeof(elementType(gpuArray.data))).uint64 343 (gpuArray.data.len * sizeof(elementType(gpuArray.data))).uint64
344 template size(gpuValue: GPUValue): uint64 = 344 template size(gpuValue: GPUValue): uint64 =
345 sizeof(gpuValue.data).uint64 345 sizeof(gpuValue.data).uint64
346 func size(texture: Texture): uint64 =
347 texture.data.len.uint64 * sizeof(elementType(texture.data)).uint64
346 348
347 template rawPointer(gpuArray: GPUArray): pointer = 349 template rawPointer(gpuArray: GPUArray): pointer =
348 addr(gpuArray.data[0]) 350 addr(gpuArray.data[0])
349 template rawPointer(gpuValue: GPUValue): pointer = 351 template rawPointer(gpuValue: GPUValue): pointer =
350 addr(gpuValue.data) 352 addr(gpuValue.data)
356 checkVkResult vkEnumeratePhysicalDevices(instance, addr(nDevices), devices.ToCPointer) 358 checkVkResult vkEnumeratePhysicalDevices(instance, addr(nDevices), devices.ToCPointer)
357 359
358 var score = 0'u32 360 var score = 0'u32
359 for pDevice in devices: 361 for pDevice in devices:
360 var props: VkPhysicalDeviceProperties 362 var props: VkPhysicalDeviceProperties
363 # CANNOT use svkGetPhysicalDeviceProperties (not initialized yet)
361 vkGetPhysicalDeviceProperties(pDevice, addr(props)) 364 vkGetPhysicalDeviceProperties(pDevice, addr(props))
362 if props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU and props.limits.maxImageDimension2D > score: 365 if props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU and props.limits.maxImageDimension2D > score:
363 score = props.limits.maxImageDimension2D 366 score = props.limits.maxImageDimension2D
364 result = pDevice 367 result = pDevice
365 368
366 if score == 0: 369 if score == 0:
367 for pDevice in devices: 370 for pDevice in devices:
368 var props: VkPhysicalDeviceProperties 371 var props: VkPhysicalDeviceProperties
372 # CANNOT use svkGetPhysicalDeviceProperties (not initialized yet)
369 vkGetPhysicalDeviceProperties(pDevice, addr(props)) 373 vkGetPhysicalDeviceProperties(pDevice, addr(props))
370 if props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU and props.limits.maxImageDimension2D > score: 374 if props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU and props.limits.maxImageDimension2D > score:
371 score = props.limits.maxImageDimension2D 375 score = props.limits.maxImageDimension2D
372 result = pDevice 376 result = pDevice
373 377
896 for memoryBlock in memoryBlocks: 900 for memoryBlock in memoryBlocks:
897 if memoryBlock.rawPointer != nil and memoryBlock.offsetNextFree > 0: 901 if memoryBlock.rawPointer != nil and memoryBlock.offsetNextFree > 0:
898 flushRegions.add VkMappedMemoryRange( 902 flushRegions.add VkMappedMemoryRange(
899 sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 903 sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
900 memory: memoryBlock.vk, 904 memory: memoryBlock.vk,
901 size: memoryBlock.offsetNextFree, 905 size: alignedTo(memoryBlock.offsetNextFree, svkGetPhysicalDeviceProperties().limits.nonCoherentAtomSize),
902 ) 906 )
903 if flushRegions.len > 0: 907 if flushRegions.len > 0:
904 checkVkResult vkFlushMappedMemoryRanges(vulkan.device, flushRegions.len.uint32, flushRegions.ToCPointer()) 908 checkVkResult vkFlushMappedMemoryRanges(vulkan.device, flushRegions.len.uint32, flushRegions.ToCPointer())
905 909
906 proc AllocateNewBuffer(renderData: var RenderData, size: uint64, bufferType: BufferType): Buffer = 910 proc AllocateNewBuffer(renderData: var RenderData, size: uint64, bufferType: BufferType): Buffer =
922 break 926 break
923 # otherwise, allocate a new block of memory and use that 927 # otherwise, allocate a new block of memory and use that
924 if selectedBlockI < 0: 928 if selectedBlockI < 0:
925 selectedBlockI = renderData.memory[memoryType].len 929 selectedBlockI = renderData.memory[memoryType].len
926 renderData.memory[memoryType].add AllocateNewMemoryBlock( 930 renderData.memory[memoryType].add AllocateNewMemoryBlock(
927 size = max(size, MEMORY_BLOCK_ALLOCATION_SIZE), 931 size = max(memoryRequirements.size, MEMORY_BLOCK_ALLOCATION_SIZE),
928 mType = memoryType 932 mType = memoryType
929 ) 933 )
930 934
931 let selectedBlock = renderData.memory[memoryType][selectedBlockI] 935 let selectedBlock = renderData.memory[memoryType][selectedBlockI]
932 renderData.memory[memoryType][selectedBlockI].offsetNextFree = alignedTo( 936 renderData.memory[memoryType][selectedBlockI].offsetNextFree = alignedTo(
956 # otherwise create new buffer 960 # otherwise create new buffer
957 if selectedBufferI < 0: 961 if selectedBufferI < 0:
958 selectedBufferI = renderdata.buffers[value.bufferType].len 962 selectedBufferI = renderdata.buffers[value.bufferType].len
959 renderdata.buffers[value.bufferType].add renderdata.AllocateNewBuffer( 963 renderdata.buffers[value.bufferType].add renderdata.AllocateNewBuffer(
960 size = max(value.size, BUFFER_ALLOCATION_SIZE), 964 size = max(value.size, BUFFER_ALLOCATION_SIZE),
961 bType = value.bufferType, 965 bufferType = value.bufferType,
962 mappable = value.NeedsMapping,
963 ) 966 )
964 967
965 # assigne value 968 # assigne value
966 let selectedBuffer = renderdata.buffers[value.bufferType][selectedBufferI] 969 let selectedBuffer = renderdata.buffers[value.bufferType][selectedBufferI]
967 renderdata.buffers[value.bufferType][selectedBufferI].offsetNextFree = alignedTo( 970 renderdata.buffers[value.bufferType][selectedBufferI].offsetNextFree = alignedTo(
969 BUFFER_ALIGNMENT 972 BUFFER_ALIGNMENT
970 ) 973 )
971 value.buffer = selectedBuffer 974 value.buffer = selectedBuffer
972 value.offset = renderdata.buffers[value.bufferType][selectedBufferI].offsetNextFree 975 value.offset = renderdata.buffers[value.bufferType][selectedBufferI].offsetNextFree
973 renderdata.buffers[value.bufferType][selectedBufferI].offsetNextFree += value.size 976 renderdata.buffers[value.bufferType][selectedBufferI].offsetNextFree += value.size
977 proc AssignBuffers(renderdata: var RenderData, descriptorSet: var DescriptorSet) =
978 AssignBuffers(renderdata, descriptorSet.data)
974 979
975 proc UpdateGPUBuffer(gpuData: GPUData) = 980 proc UpdateGPUBuffer(gpuData: GPUData) =
976 if gpuData.size == 0: 981 if gpuData.size == 0:
977 return 982 return
978 when NeedsMapping(gpuData): 983 when NeedsMapping(gpuData):
979 copyMem(pointerAddOffset(gpuData.buffer.rawPointer, gpuData.offset), gpuData.rawPointer, gpuData.size) 984 copyMem(pointerAddOffset(gpuData.buffer.rawPointer, gpuData.offset), gpuData.rawPointer, gpuData.size)
980 else: 985 else:
981 WithStagingBuffer((gpuData.buffer.vk, gpuData.offset), gpuData.buffer.size, stagingPtr): 986 WithStagingBuffer((gpuData.buffer.vk, gpuData.offset), gpuData.size, stagingPtr):
982 copyMem(stagingPtr, gpuData.rawPointer, gpuData.size) 987 copyMem(stagingPtr, gpuData.rawPointer, gpuData.size)
983 988
984 proc UpdateAllGPUBuffers[T](value: T) = 989 proc UpdateAllGPUBuffers[T](value: T) =
985 for name, fieldvalue in value.fieldPairs(): 990 for name, fieldvalue in value.fieldPairs():
986 when typeof(fieldvalue) is GPUData: 991 when typeof(fieldvalue) is GPUData:
1097 ) 1102 )
1098 checkVkResult vkCreateSampler(vulkan.device, addr(samplerInfo), nil, addr(result)) 1103 checkVkResult vkCreateSampler(vulkan.device, addr(samplerInfo), nil, addr(result))
1099 1104
1100 proc createTextureImage(renderData: var RenderData, texture: var Texture) = 1105 proc createTextureImage(renderData: var RenderData, texture: var Texture) =
1101 assert texture.vk == VkImage(0) 1106 assert texture.vk == VkImage(0)
1102 assert texture.offset == 0
1103 const usage = [VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_USAGE_SAMPLED_BIT] 1107 const usage = [VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_USAGE_SAMPLED_BIT]
1104 1108 let format = GetVkFormat(texture.depth, usage = usage)
1105 texture.format = GetVkFormat(texture.depth, usage = usage) 1109
1106 texture.vk = svkCreate2DImage(texture.width, texture.height, texture.format, usage) 1110 texture.vk = svkCreate2DImage(texture.width, texture.height, format, usage)
1107 let reqs = texture.vk.svkGetImageMemoryRequirements() 1111 texture.sampler = createSampler()
1108 1112
1109 # TODO 1113 let memoryRequirements = texture.vk.svkGetImageMemoryRequirements()
1110 1114 let memoryType = BestMemory(mappable = false, filter = memoryRequirements.memoryTypes)
1111 for (memory, usedOffset) in renderData.indirectMemory.mitems: 1115 # check if there is an existing allocated memory block that is large enough to be used
1112 if memory.size - usedOffset >= size: 1116 var selectedBlockI = -1
1113 texture.memory = memory 1117 for i in 0 ..< renderData.memory[memoryType].len:
1114 texture.offset = usedOffset 1118 let memoryBlock = renderData.memory[memoryType][i]
1115 # update memory area offset 1119 if memoryBlock.size - alignedTo(memoryBlock.offsetNextFree, memoryRequirements.alignment) >= memoryRequirements.size:
1116 usedOffset = alignedTo(usedOffset + size, MEMORY_ALIGNMENT) 1120 selectedBlockI = i
1117 break 1121 break
1122 # otherwise, allocate a new block of memory and use that
1123 if selectedBlockI < 0:
1124 selectedBlockI = renderData.memory[memoryType].len
1125 renderData.memory[memoryType].add AllocateNewMemoryBlock(
1126 size = max(memoryRequirements.size, MEMORY_BLOCK_ALLOCATION_SIZE),
1127 mType = memoryType
1128 )
1129 let selectedBlock = renderData.memory[memoryType][selectedBlockI]
1130 renderData.memory[memoryType][selectedBlockI].offsetNextFree = alignedTo(
1131 selectedBlock.offsetNextFree,
1132 memoryRequirements.alignment,
1133 )
1118 1134
1119 checkVkResult vkBindImageMemory( 1135 checkVkResult vkBindImageMemory(
1120 vulkan.device, 1136 vulkan.device,
1121 texture.vk, 1137 texture.vk,
1122 texture.memory.vk, 1138 selectedBlock.vk,
1123 texture.offset, 1139 renderData.memory[memoryType][selectedBlockI].offsetNextFree,
1124 ) 1140 )
1141 renderData.memory[memoryType][selectedBlockI].offsetNextFree += memoryRequirements.size
1142
1143 # imageview can only be created after memory is bound
1144 texture.imageview = createImageView(texture.vk, format)
1125 1145
1126 # data transfer and layout transition 1146 # data transfer and layout transition
1127 TransitionImageLayout(texture.vk, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) 1147 TransitionImageLayout(texture.vk, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
1128 WithStagingBuffer((texture.vk, texture.imageview, texture.width, texture.height), size, stagingPtr): 1148 WithStagingBuffer(
1129 copyMem(stagingPtr, texture.data.ToCPointer, size) 1149 (texture.vk, texture.width, texture.height),
1130 TransitionImageLayout(texture.vk, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) 1150 memoryRequirements.size,
1131 1151 stagingPtr
1132 texture.imageview = createImageView(texture.vk, texture.format) 1152 ):
1133 texture.sampler = createSampler() 1153 copyMem(stagingPtr, texture.data.ToCPointer, texture.size)
1154 TransitionImageLayout(texture.vk, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
1155
1134 1156
1135 proc UploadTextures(renderdata: var RenderData, descriptorSet: var DescriptorSet) = 1157 proc UploadTextures(renderdata: var RenderData, descriptorSet: var DescriptorSet) =
1136 for name, value in fieldPairs(descriptorSet.data): 1158 for name, value in fieldPairs(descriptorSet.data):
1137 when typeof(value) is Texture: 1159 when typeof(value) is Texture:
1138 echo "Upload texture '", name, "'" 1160 echo "Upload texture '", name, "'"
1365 var renderdata = InitRenderData() 1387 var renderdata = InitRenderData()
1366 1388
1367 # buffer assignment 1389 # buffer assignment
1368 echo "Assigning buffers to GPUData fields" 1390 echo "Assigning buffers to GPUData fields"
1369 1391
1370 renderdata.AssignBuffers(myMesh1) 1392 AssignBuffers(renderdata, myMesh1)
1371 renderdata.AssignBuffers(instances1) 1393 AssignBuffers(renderdata, instances1)
1372 renderdata.AssignBuffers(myGlobals) 1394 AssignBuffers(renderdata, myGlobals)
1373 renderdata.AssignBuffers(uniforms1) 1395 AssignBuffers(renderdata, uniforms1)
1374 1396
1375 renderdata.UploadTextures(myGlobals) 1397 renderdata.UploadTextures(myGlobals)
1376 renderdata.UploadTextures(uniforms1) 1398 renderdata.UploadTextures(uniforms1)
1377 1399
1378 # copy everything to GPU 1400 # copy everything to GPU