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 |
