Mercurial > games > semicongine
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 |