Mercurial > games > semicongine
comparison static_utils.nim @ 1178:ec4ff70299f2 compiletime-tests
sync from bedroom to office
| author | sam <sam@basx.dev> |
|---|---|
| date | Mon, 01 Jul 2024 19:16:09 +0700 |
| parents | 4ef959278451 |
| children | e1830f9b8af4 |
comparison
equal
deleted
inserted
replaced
| 1177:4ef959278451 | 1178:ec4ff70299f2 |
|---|---|
| 21 template ShaderOutput* {.pragma.} | 21 template ShaderOutput* {.pragma.} |
| 22 template VertexIndices*{.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 BUFFERALIGNMENT = 64'u64 # align offsets inside buffers along this alignment | 26 const BUFFER_ALIGNMENT = 64'u64 # align offsets inside buffers along this alignment |
| 27 | 27 |
| 28 type | 28 type |
| 29 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] | 29 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] |
| 30 ShaderObject*[TShader] = object | 30 ShaderObject*[TShader] = object |
| 31 vertexShader: VkShaderModule | 31 vertexShader: VkShaderModule |
| 32 fragmentShader: VkShaderModule | 32 fragmentShader: VkShaderModule |
| 33 | |
| 34 func alignedTo[T: SomeInteger](value: T, alignment: T) = | |
| 35 let remainder = value mod alignment | |
| 36 if remainder == 0: | |
| 37 return value | |
| 38 else: | |
| 39 return value + alignment - remainder | |
| 33 | 40 |
| 34 func VkType[T: SupportedGPUType](value: T): VkFormat = | 41 func VkType[T: SupportedGPUType](value: T): VkFormat = |
| 35 when T is float32: VK_FORMAT_R32_SFLOAT | 42 when T is float32: VK_FORMAT_R32_SFLOAT |
| 36 elif T is float64: VK_FORMAT_R64_SFLOAT | 43 elif T is float64: VK_FORMAT_R64_SFLOAT |
| 37 elif T is int8: VK_FORMAT_R8_SINT | 44 elif T is int8: VK_FORMAT_R8_SINT |
| 211 data: pointer | 218 data: pointer |
| 212 needsFlush: bool # usually true | 219 needsFlush: bool # usually true |
| 213 GPUMemory = IndirectGPUMemory | DirectGPUMemory | 220 GPUMemory = IndirectGPUMemory | DirectGPUMemory |
| 214 | 221 |
| 215 Buffer[TMemory: GPUMemory] = object | 222 Buffer[TMemory: GPUMemory] = object |
| 223 memory: TMemory | |
| 216 vk: VkBuffer | 224 vk: VkBuffer |
| 217 offset: uint64 | 225 offset: uint64 |
| 218 size: uint64 | 226 size: uint64 |
| 219 | 227 |
| 220 GPUArray[T: SupportedGPUType, TMemory: GPUMemory] = object | 228 GPUArray[T: SupportedGPUType, TMemory: GPUMemory] = object |
| 223 offset: uint64 | 231 offset: uint64 |
| 224 GPUValue[T: object|array, TMemory: GPUMemory] = object | 232 GPUValue[T: object|array, TMemory: GPUMemory] = object |
| 225 data: T | 233 data: T |
| 226 buffer: Buffer[TMemory] | 234 buffer: Buffer[TMemory] |
| 227 offset: uint64 | 235 offset: uint64 |
| 228 | 236 GPUData = GPUArray | GPUValue |
| 229 Renderable[TMesh, TInstance] = object | |
| 230 vertexBuffers: seq[VkBuffer] | |
| 231 bufferOffsets: seq[VkDeviceSize] | |
| 232 instanceCount: uint32 | |
| 233 case indexType: IndexType | |
| 234 of None: | |
| 235 vertexCount: uint32 | |
| 236 else: | |
| 237 indexBuffer: VkBuffer | |
| 238 indexCount: uint32 | |
| 239 indexBufferOffset: VkDeviceSize | |
| 240 | 237 |
| 241 Pipeline[TShader] = object | 238 Pipeline[TShader] = object |
| 242 pipeline: VkPipeline | 239 pipeline: VkPipeline |
| 243 layout: VkPipelineLayout | 240 layout: VkPipelineLayout |
| 244 descriptorSetLayout: VkDescriptorSetLayout | 241 descriptorSetLayout: VkDescriptorSetLayout |
| 242 BufferType = enum | |
| 243 VertexBuffer, IndexBuffer, UniformBuffer | |
| 245 RenderData = object | 244 RenderData = object |
| 246 descriptorPool: VkDescriptorPool | 245 descriptorPool: VkDescriptorPool |
| 247 # tuple is memory and offset to next free allocation in that memory | 246 # tuple is memory and offset to next free allocation in that memory |
| 248 indirectMemory: seq[tuple[memory: IndirectGPUMemory, nextFree: uint64]] | 247 indirectMemory: seq[tuple[memory: IndirectGPUMemory, nextFree: uint64]] |
| 249 directMemory: seq[tuple[memory: DirectGPUMemory, nextFree: uint64]] | 248 directMemory: seq[tuple[memory: DirectGPUMemory, nextFree: uint64]] |
| 250 indirectBuffers: seq[Buffer[IndirectGPUMemory]] | 249 indirectBuffers: seq[tuple[buffer: Buffer[IndirectGPUMemory], btype: BufferType, nextFree: uint64]] |
| 251 directBuffers: seq[Buffer[DirectGPUMemory]] | 250 directBuffers: seq[tuple[buffer: Buffer[DirectGPUMemory], btype: BufferType, nextFree: uint64]] |
| 252 | 251 |
| 253 template IsDirectMemory(gpuArray: GPUArray): untyped = | 252 template UsesIndirectMemory(gpuData: GPUData): untyped = |
| 254 get(genericParams(typeof(gpuArray)), 1) is DirectGPUMemory | 253 get(genericParams(typeof(gpuData)), 1) is IndirectGPUMemory |
| 255 template IsDirectMemory(gpuValue: GPUValue): untyped = | 254 template UsesDirectMemory(gpuData: GPUData): untyped = |
| 256 get(genericParams(typeof(gpuValue)), 1) is DirectGPUMemory | 255 get(genericParams(typeof(gpuData)), 1) is DirectGPUMemory |
| 256 | |
| 257 template size(gpuArray: GPUArray): uint64 = | |
| 258 result += (gpuArray.data.len * sizeof(elementType(gpuArray.data))).uint64 | |
| 259 template size(gpuValue: GPUValue): uint64 = | |
| 260 result += sizeof(gpuValue.data).uint64 | |
| 261 | |
| 262 proc GetPhysicalDevice(): VkPhysicalDevice = | |
| 263 var nDevices: uint32 | |
| 264 checkVkResult vkEnumeratePhysicalDevices(instance.vk, addr(nDevices), nil) | |
| 265 var devices = newSeq[VkPhysicalDevice](nDevices) | |
| 266 checkVkResult vkEnumeratePhysicalDevices(instance.vk, addr(nDevices), devices.ToCPointer) | |
| 267 | |
| 268 var score = 0 | |
| 269 for pDevice in devices: | |
| 270 var props: VkPhysicalDeviceProperties | |
| 271 vkGetPhysicalDeviceProperties(pDevice, addr(props)) | |
| 272 if props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU and props.maxImageDimension2D > score: | |
| 273 score = props.maxImageDimension2D | |
| 274 result = pDevice | |
| 275 | |
| 276 if score == 0 | |
| 277 for pDevice in devices: | |
| 278 var props: VkPhysicalDeviceProperties | |
| 279 vkGetPhysicalDeviceProperties(pDevice, addr(props)) | |
| 280 if props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU and props.maxImageDimension2D > score: | |
| 281 score = props.maxImageDimension2D | |
| 282 result = pDevice | |
| 283 | |
| 284 assert score > 0, "Unable to find integrated or discrete GPU" | |
| 285 | |
| 286 | |
| 287 proc GetDirectMemoryTypeIndex() | |
| 288 var physicalProperties: VkPhysicalDeviceMemoryProperties | |
| 289 checkVkResult vkGetPhysicalDeviceMemoryProperties(GetPhysicalDevice(), addr physicalProperties) | |
| 290 | |
| 291 var biggestHeap: uint64 = 0 | |
| 292 result = high(uint32) | |
| 293 # try to find host-visible type | |
| 294 for i in 0 ..< physicalProperties.memoryTypeCount: | |
| 295 let flags = toEnums(physicalProperties.memoryTypes[i].propertyFlags) | |
| 296 if VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in flags: | |
| 297 let size = physicalProperties.memoryHeaps[physicalProperties.memoryTypes[i].heapIndex].size | |
| 298 if size > biggestHeap: | |
| 299 biggestHeap = size | |
| 300 result = i | |
| 301 assert result != high(uint32), "There is not host visible memory. This is likely a driver bug." | |
| 302 | |
| 303 proc GetQueueFamily(device: VkDevice, qType = VK_QUEUE_GRAPHICS_BIT): VkQueue = | |
| 304 assert device.vk.Valid | |
| 305 var nQueuefamilies: uint32 | |
| 306 checkVkResult vkGetPhysicalDeviceQueueFamilyProperties(device.vk, addr nQueuefamilies, nil) | |
| 307 var queuFamilies = newSeq[VkQueueFamilyProperties](nQueuefamilies) | |
| 308 checkVkResult vkGetPhysicalDeviceQueueFamilyProperties(device.vk, addr nQueuefamilies, queuFamilies.ToCPointer) | |
| 309 for i in 0 ..< nQueuefamilies: | |
| 310 if qType in toEnums(queuFamilies[i].queueFlags): | |
| 311 return i | |
| 312 assert false, &"Queue of type {qType} not found" | |
| 313 | |
| 314 proc GetQueue(device: VkDevice, qType = VK_QUEUE_GRAPHICS_BIT): VkQueue = | |
| 315 checkVkResult vkGetDeviceQueue( | |
| 316 device, | |
| 317 GetQueueFamily(device, qType), | |
| 318 0, | |
| 319 addr(result), | |
| 320 ) | |
| 321 | |
| 322 #[ | |
| 323 TODO: Finish this, allow fore easy access to main format | |
| 324 proc GetSurfaceFormat*(device: PhysicalDevice): VkFormat = | |
| 325 var n_formats: uint32 | |
| 326 checkVkResult vkGetPhysicalDeviceSurfaceFormatsKHR(device.vk, device.surface, addr(n_formats), nil) | |
| 327 result = newSeq[VkSurfaceFormatKHR](n_formats) | |
| 328 checkVkResult vkGetPhysicalDeviceSurfaceFormatsKHR(device.vk, device.surface, addr(n_formats), result.ToCPointer) | |
| 329 ]# | |
| 330 | |
| 331 template WithSingleUseCommandBuffer*(device: VkDevice, cmd, body: untyped): untyped = | |
| 332 # TODO? This is super slow, because we call vkQueueWaitIdle | |
| 333 block: | |
| 334 var commandBufferPool: VkCommandPool | |
| 335 createInfo = VkCommandPoolCreateInfo( | |
| 336 sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, | |
| 337 flags: toBits [VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT], | |
| 338 queueFamilyIndex: GetQueueFamily(device), | |
| 339 ) | |
| 340 checkVkResult vkCreateCommandPool(device, addr createInfo, nil, addr(commandBufferPool)) | |
| 341 var | |
| 342 `cmd` {.inject.}: VkCommandBuffer | |
| 343 allocInfo = VkCommandBufferAllocateInfo( | |
| 344 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, | |
| 345 commandPool: commandBufferPool, | |
| 346 level: VK_COMMAND_BUFFER_LEVEL_PRIMARY, | |
| 347 commandBufferCount: 1, | |
| 348 ) | |
| 349 checkVkResult device.vk.vkAllocateCommandBuffers(addr allocInfo, addr(`cmd`)) | |
| 350 beginInfo = VkCommandBufferBeginInfo( | |
| 351 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, | |
| 352 flags: VkCommandBufferUsageFlags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT), | |
| 353 ) | |
| 354 checkVkResult `cmd`.vkBeginCommandBuffer(addr beginInfo) | |
| 355 | |
| 356 body | |
| 357 | |
| 358 checkVkResult `cmd`.vkEndCommandBuffer() | |
| 359 var submitInfo = VkSubmitInfo( | |
| 360 sType: VK_STRUCTURE_TYPE_SUBMIT_INFO, | |
| 361 commandBufferCount: 1, | |
| 362 pCommandBuffers: addr(`cmd`), | |
| 363 ) | |
| 364 checkVkResult vkQueueSubmit(GetQueue(), 1, addr submitInfo, VkFence(0)) | |
| 365 checkVkResult vkQueueWaitIdle(GetQueue()) # because we want to destroy the commandbuffer pool | |
| 366 vkDestroyCommandPool(device, commandBufferPool, nil) | |
| 367 | |
| 368 | |
| 369 proc UpdateGPUBuffer*(device: VkDevice, gpuData: GPUArray) = | |
| 370 when UsesDirectMemory(gpuData): | |
| 371 copyMem(cast[pointer](cast[uint64](gpuData.buffer.memory.data) + gpuData.buffer.offset + gpuData.offset), addr(gpuData.data[0]), gpuData.size) | |
| 372 else: | |
| 373 var | |
| 374 stagingBuffer: VkBuffer | |
| 375 createInfo = VkBufferCreateInfo( | |
| 376 sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | |
| 377 flags: VkBufferCreateFlags(0), | |
| 378 size: gpuData.size, | |
| 379 usage: toBits([VK_BUFFER_USAGE_TRANSFER_SRC_BIT]), | |
| 380 sharingMode: VK_SHARING_MODE_EXCLUSIVE, | |
| 381 ) | |
| 382 checkVkResult vkCreateBuffer( | |
| 383 device = device, | |
| 384 pCreateInfo = addr(createInfo), | |
| 385 pAllocator = nil, | |
| 386 pBuffer = addr(stagingBuffer), | |
| 387 ) | |
| 388 var | |
| 389 stagingMemory: VkDeviceMemory | |
| 390 stagingPtr: pointer | |
| 391 memoryAllocationInfo = VkMemoryAllocateInfo( | |
| 392 sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, | |
| 393 allocationSize: gpuData.size, | |
| 394 memoryTypeIndex: GetDirectMemoryTypeIndex(), | |
| 395 ) | |
| 396 checkVkResult vkAllocateMemory( | |
| 397 device, | |
| 398 addr(memoryAllocationInfo), | |
| 399 nil, | |
| 400 addr(stagingMemory), | |
| 401 ) | |
| 402 checkVkResult vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0) | |
| 403 checkVkResult vkMapMemory( | |
| 404 device = device, | |
| 405 memory = stagingMemory, | |
| 406 offset = 0'u64, | |
| 407 size = VK_WHOLE_SIZE, | |
| 408 flags = VkMemoryMapFlags(0), | |
| 409 ppData = stagingPtr | |
| 410 ) | |
| 411 copyMem(stagingPtr, addr(gpuData.data[0]), gpuData.size) | |
| 412 var stagingRange = VkMappedMemoryRange( | |
| 413 sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, | |
| 414 memory: stagingMemory, | |
| 415 size: VK_WHOLE_SIZE, | |
| 416 ) | |
| 417 checkVkResult vkFlushMappedMemoryRanges(device, 1, addr(stagingRange)) | |
| 418 | |
| 419 WithSingleUseCommandBuffer(device, commandBuffer): | |
| 420 var copyRegion = VkBufferCopy(size: gpuData.size) | |
| 421 vkCmdCopyBuffer(commandBuffer, stagingBuffer, gpuData.buffer.vk, 1, addr(copyRegion)) | |
| 422 | |
| 423 checkVkResult vkDestroyBuffer(device, stagingBuffer, nil) | |
| 424 checkVkResult vkFreeMemory(device, stagingMemory, nil) | |
| 257 | 425 |
| 258 converter toVkIndexType(indexType: IndexType): VkIndexType = | 426 converter toVkIndexType(indexType: IndexType): VkIndexType = |
| 259 case indexType: | 427 case indexType: |
| 260 of None: VK_INDEX_TYPE_NONE_KHR | 428 of None: VK_INDEX_TYPE_NONE_KHR |
| 261 of UInt8: VK_INDEX_TYPE_UINT8_EXT | 429 of UInt8: VK_INDEX_TYPE_UINT8_EXT |
| 623 result.size = size | 791 result.size = size |
| 624 result.needsTransfer = true | 792 result.needsTransfer = true |
| 625 | 793 |
| 626 # find a good memory type | 794 # find a good memory type |
| 627 var physicalProperties: VkPhysicalDeviceMemoryProperties | 795 var physicalProperties: VkPhysicalDeviceMemoryProperties |
| 628 vkGetPhysicalDeviceMemoryProperties(pDevice, addr physicalProperties) | 796 checkVkResult vkGetPhysicalDeviceMemoryProperties(pDevice, addr physicalProperties) |
| 629 | 797 |
| 630 var biggestHeap: uint64 = 0 | 798 var biggestHeap: uint64 = 0 |
| 631 var memoryTypeIndex = high(uint32) | 799 var memoryTypeIndex = high(uint32) |
| 632 # try to find non-host-visible type | 800 # try to find non-host-visible type |
| 633 for i in 0'u32 ..< physicalProperties.memoryTypeCount: | 801 for i in 0'u32 ..< physicalProperties.memoryTypeCount: |
| 663 result.size = size | 831 result.size = size |
| 664 result.needsFlush = true | 832 result.needsFlush = true |
| 665 | 833 |
| 666 # find a good memory type | 834 # find a good memory type |
| 667 var physicalProperties: VkPhysicalDeviceMemoryProperties | 835 var physicalProperties: VkPhysicalDeviceMemoryProperties |
| 668 vkGetPhysicalDeviceMemoryProperties(pDevice, addr physicalProperties) | 836 checkVkResult vkGetPhysicalDeviceMemoryProperties(pDevice, addr physicalProperties) |
| 669 | 837 |
| 670 var biggestHeap: uint64 = 0 | 838 var biggestHeap: uint64 = 0 |
| 671 var memoryTypeIndex = high(uint32) | 839 var memoryTypeIndex = high(uint32) |
| 672 # try to find host-visible type | 840 # try to find host-visible type |
| 673 for i in 0 ..< physicalProperties.memoryTypeCount: | 841 for i in 0 ..< physicalProperties.memoryTypeCount: |
| 681 | 849 |
| 682 assert memoryTypeIndex != high(uint32), "Unable to find indirect memory type" | 850 assert memoryTypeIndex != high(uint32), "Unable to find indirect memory type" |
| 683 var allocationInfo = VkMemoryAllocateInfo( | 851 var allocationInfo = VkMemoryAllocateInfo( |
| 684 sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, | 852 sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, |
| 685 allocationSize: result.size, | 853 allocationSize: result.size, |
| 686 memoryTypeIndex: memoryTypeIndex, | 854 memoryTypeIndex: FindDirectMemoryTypeIndex(pDevice), |
| 687 ) | 855 ) |
| 688 checkVkResult vkAllocateMemory( | 856 checkVkResult vkAllocateMemory( |
| 689 device, | 857 device, |
| 690 addr allocationInfo, | 858 addr allocationInfo, |
| 691 nil, | 859 nil, |
| 698 size = result.size, | 866 size = result.size, |
| 699 flags = VkMemoryMapFlags(0), | 867 flags = VkMemoryMapFlags(0), |
| 700 ppData = addr(result.data) | 868 ppData = addr(result.data) |
| 701 ) | 869 ) |
| 702 | 870 |
| 703 proc AllocateIndirectBuffer(device: VkDevice, renderData: var RenderData, size: uint64, usage: openArray[VkBufferUsageFlagBits]) = | 871 proc AllocateIndirectBuffer(device: VkDevice, renderData: var RenderData, size: uint64, btype: BufferType) = |
| 704 assert size > 0, "Buffer sizes must be larger than 0" | 872 assert size > 0, "Buffer sizes must be larger than 0" |
| 705 var buffer = Buffer[IndirectGPUMemory](size: size) | 873 var buffer = Buffer[IndirectGPUMemory](size: size) |
| 874 | |
| 875 let usageFlags = case btype: | |
| 876 of VertexBuffer: [VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | |
| 877 of IndexBuffer: [VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | |
| 878 of UniformBuffer: [VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | |
| 706 | 879 |
| 707 # iterate through memory areas to find big enough free space | 880 # iterate through memory areas to find big enough free space |
| 708 for (memory, offset) in renderData.indirectMemory.mitems: | 881 for (memory, offset) in renderData.indirectMemory.mitems: |
| 709 if memory.size - offset >= size: | 882 if memory.size - offset >= size: |
| 710 buffer.offset = offset | 883 buffer.offset = offset |
| 711 # create buffer | 884 # create buffer |
| 712 var createInfo = VkBufferCreateInfo( | 885 var createInfo = VkBufferCreateInfo( |
| 713 sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | 886 sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
| 714 flags: VkBufferCreateFlags(0), | 887 flags: VkBufferCreateFlags(0), |
| 715 size: buffer.size, | 888 size: buffer.size, |
| 716 usage: toBits(@usage & @[VK_BUFFER_USAGE_TRANSFER_DST_BIT]), # ensure we can transfer to this buffer | 889 usage: toBits(usageFlags), |
| 717 sharingMode: VK_SHARING_MODE_EXCLUSIVE, | 890 sharingMode: VK_SHARING_MODE_EXCLUSIVE, |
| 718 ) | 891 ) |
| 719 checkVkResult vkCreateBuffer( | 892 checkVkResult vkCreateBuffer( |
| 720 device = device, | 893 device = device, |
| 721 pCreateInfo = addr createInfo, | 894 pCreateInfo = addr createInfo, |
| 722 pAllocator = nil, | 895 pAllocator = nil, |
| 723 pBuffer = addr(buffer.vk) | 896 pBuffer = addr(buffer.vk) |
| 724 ) | 897 ) |
| 725 checkVkResult vkBindBufferMemory(device, buffer.vk, memory.vk, buffer.offset) | 898 checkVkResult vkBindBufferMemory(device, buffer.vk, memory.vk, buffer.offset) |
| 726 renderData.indirectBuffers.add buffer | 899 renderData.indirectBuffers.add (buffer, btype, 0'u64) |
| 727 # update memory area offset | 900 # update memory area offset |
| 728 offset = offset + size | 901 offset = alignedTo(offset + size, MEMORY_ALIGNMENT) |
| 729 if offset mod MEMORY_ALIGNMENT != 0: | |
| 730 offset = offset + MEMORY_ALIGNMENT - (offset mod MEMORY_ALIGNMENT) | |
| 731 return | 902 return |
| 732 | 903 |
| 733 assert false, "Did not find allocated memory region with enough space" | 904 assert false, "Did not find allocated memory region with enough space" |
| 734 | 905 |
| 735 proc AllocateDirectBuffer(device: VkDevice, renderData: var RenderData, size: uint64, usage: openArray[VkBufferUsageFlagBits]) = | 906 proc AllocateDirectBuffer(device: VkDevice, renderData: var RenderData, size: uint64, btype: BufferType) = |
| 736 assert size > 0, "Buffer sizes must be larger than 0" | 907 assert size > 0, "Buffer sizes must be larger than 0" |
| 737 var buffer = Buffer[DirectGPUMemory](size: size) | 908 var buffer = Buffer[DirectGPUMemory](size: size) |
| 909 | |
| 910 let usageFlags = case btype: | |
| 911 of VertexBuffer: [VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | |
| 912 of IndexBuffer: [VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | |
| 913 of UniformBuffer: [VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | |
| 738 | 914 |
| 739 # iterate through memory areas to find big enough free space | 915 # iterate through memory areas to find big enough free space |
| 740 for (memory, offset) in renderData.directMemory.mitems: | 916 for (memory, offset) in renderData.directMemory.mitems: |
| 741 if memory.size - offset >= size: | 917 if memory.size - offset >= size: |
| 742 buffer.offset = offset | 918 buffer.offset = offset |
| 743 # create buffer | 919 # create buffer |
| 744 var createInfo = VkBufferCreateInfo( | 920 var createInfo = VkBufferCreateInfo( |
| 745 sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | 921 sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
| 746 flags: VkBufferCreateFlags(0), | 922 flags: VkBufferCreateFlags(0), |
| 747 size: buffer.size, | 923 size: buffer.size, |
| 748 usage: toBits(usage), | 924 usage: toBits(usageFlags), |
| 749 sharingMode: VK_SHARING_MODE_EXCLUSIVE, | 925 sharingMode: VK_SHARING_MODE_EXCLUSIVE, |
| 750 ) | 926 ) |
| 751 checkVkResult vkCreateBuffer( | 927 checkVkResult vkCreateBuffer( |
| 752 device = device, | 928 device = device, |
| 753 pCreateInfo = addr createInfo, | 929 pCreateInfo = addr createInfo, |
| 754 pAllocator = nil, | 930 pAllocator = nil, |
| 755 pBuffer = addr(buffer.vk) | 931 pBuffer = addr(buffer.vk) |
| 756 ) | 932 ) |
| 757 checkVkResult vkBindBufferMemory(device, buffer.vk, memory.vk, buffer.offset) | 933 checkVkResult vkBindBufferMemory(device, buffer.vk, memory.vk, buffer.offset) |
| 758 renderData.directBuffers.add buffer | 934 renderData.directBuffers.add (buffer, btype, 0'u64) |
| 759 # update memory area offset | 935 # update memory area offset |
| 760 offset = offset + size | 936 offset = alignedTo(offset + size, MEMORY_ALIGNMENT) |
| 761 if offset mod MEMORY_ALIGNMENT != 0: | |
| 762 offset = offset + MEMORY_ALIGNMENT - (offset mod MEMORY_ALIGNMENT) | |
| 763 return | 937 return |
| 764 | 938 |
| 765 assert false, "Did not find allocated memory region with enough space" | 939 assert false, "Did not find allocated memory region with enough space" |
| 766 | 940 |
| 767 proc InitRenderData(device: VkDevice, pDevice: VkPhysicalDevice, descriptorPoolLimit = 1024'u32): RenderData = | 941 proc InitRenderData(device: VkDevice, pDevice: VkPhysicalDevice, descriptorPoolLimit = 1024'u32): RenderData = |
| 781 # allocate some memory | 955 # allocate some memory |
| 782 var initialAllocationSize = 1_000_000_000'u64 # TODO: make this more dynamic or something | 956 var initialAllocationSize = 1_000_000_000'u64 # TODO: make this more dynamic or something |
| 783 result.indirectMemory = @[(AllocateIndirectMemory(device, pDevice, size = initialAllocationSize), 0'u64)] | 957 result.indirectMemory = @[(AllocateIndirectMemory(device, pDevice, size = initialAllocationSize), 0'u64)] |
| 784 result.directMemory = @[(AllocateDirectMemory(device, pDevice, size = initialAllocationSize), 0'u64)] | 958 result.directMemory = @[(AllocateDirectMemory(device, pDevice, size = initialAllocationSize), 0'u64)] |
| 785 | 959 |
| 960 # For the Get*BufferSize: | |
| 961 # BUFFER_ALIGNMENT is just added for a rough estimate, to ensure we have enough space to align when binding | |
| 786 proc GetIndirectBufferSizes[T](data: T): uint64 = | 962 proc GetIndirectBufferSizes[T](data: T): uint64 = |
| 787 # return buffer sizes for direct and indirect buffers | |
| 788 # BUFFER_ALIGNMENT is just added for a rough estimate, to ensure we have enough space to align when binding | |
| 789 for name, value in fieldPairs(data): | 963 for name, value in fieldPairs(data): |
| 790 when not hasCustomPragma(value, VertexIndices) | 964 when not hasCustomPragma(value, VertexIndices): |
| 791 when typeof(value) is GPUArray: | 965 when typeof(value) is GPUData: |
| 792 if not IsDirectMemory(value): | 966 when UsesIndirectMemory(value): |
| 793 result += (value.data.len * sizeof(elementType(value.data))).uint64 + BUFFER_ALIGNMENT | 967 result += value.size + BUFFER_ALIGNMENT |
| 794 when typeof(value) is GPUValue: | |
| 795 if not IsDirectMemory(value): | |
| 796 result += sizeof(value.data).uint64 + BUFFER_ALIGNMENT | |
| 797 proc GetDirectBufferSizes[T](data: T): uint64 = | 968 proc GetDirectBufferSizes[T](data: T): uint64 = |
| 798 # return buffer sizes for direct and indirect buffers | |
| 799 # BUFFER_ALIGNMENT is just added for a rough estimate, to ensure we have enough space to align when binding | |
| 800 for name, value in fieldPairs(data): | 969 for name, value in fieldPairs(data): |
| 801 when not hasCustomPragma(value, VertexIndices) | 970 when not hasCustomPragma(value, VertexIndices): |
| 802 when typeof(value) is GPUArray: | 971 when typeof(value) is GPUData: |
| 803 if IsDirectMemory(value): | 972 when UsesDirectMemory(value): |
| 804 result += (value.data.len * sizeof(elementType(value.data))).uint64 + BUFFER_ALIGNMENT | 973 result += value.size + BUFFER_ALIGNMENT |
| 805 when typeof(value) is GPUValue: | |
| 806 if IsDirectMemory(value): | |
| 807 result += sizeof(value.data).uint64 + BUFFER_ALIGNMENT | |
| 808 | |
| 809 proc GetIndirectIndexBufferSizes[T](data: T): uint64 = | 974 proc GetIndirectIndexBufferSizes[T](data: T): uint64 = |
| 810 for name, value in fieldPairs(data): | 975 for name, value in fieldPairs(data): |
| 811 when hasCustomPragma(value, VertexIndices): | 976 when hasCustomPragma(value, VertexIndices): |
| 812 static: assert typeof(value) is GPUArray, "Index buffers must be of type GPUArray" | 977 static: assert typeof(value) is GPUArray, "Index buffers must be of type GPUArray" |
| 813 static: assert elementType(value.data) is uint8 or elementType(value.data) is uint16 or elementType(value.data) is uint32 | 978 static: assert elementType(value.data) is uint8 or elementType(value.data) is uint16 or elementType(value.data) is uint32 |
| 814 if not IsDirectMemory(value): | 979 when UsesIndirectMemory(value): |
| 815 result += (value.data.len * sizeof(elementType(value.data))).uint64 + BUFFER_ALIGNMENT | 980 result += value.size + BUFFER_ALIGNMENT |
| 816 | |
| 817 proc GetDirectIndexBufferSizes[T](data: T): uint64 = | 981 proc GetDirectIndexBufferSizes[T](data: T): uint64 = |
| 818 for name, value in fieldPairs(data): | 982 for name, value in fieldPairs(data): |
| 819 when hasCustomPragma(value, VertexIndices): | 983 when hasCustomPragma(value, VertexIndices): |
| 820 static: assert typeof(value) is GPUArray, "Index buffers must be of type GPUArray" | 984 static: assert typeof(value) is GPUArray, "Index buffers must be of type GPUArray" |
| 821 static: assert elementType(value.data) is uint8 or elementType(value.data) is uint16 or elementType(value.data) is uint32 | 985 static: assert elementType(value.data) is uint8 or elementType(value.data) is uint16 or elementType(value.data) is uint32 |
| 822 if IsDirectMemory(value): | 986 when UsesDirectMemory(value): |
| 823 result += (value.data.len * sizeof(elementType(value.data))).uint64 + BUFFER_ALIGNMENT | 987 result += value.size + BUFFER_ALIGNMENT |
| 824 | 988 |
| 989 proc AssignIndirectBuffers[T](data: T, renderdata: var RenderData, btype: BufferType) = | |
| 990 for name, value in fieldPairs(data): | |
| 991 when typeof(value) is GPUData: | |
| 992 when UsesIndirectMemory(value): | |
| 993 # find next buffer of correct type with enough free space | |
| 994 var foundBuffer = false | |
| 995 for (buffer, bt, offset) in renderData.indirectBuffers.mitems: | |
| 996 if bt == btype and buffer.size - offset >= size: | |
| 997 assert not value.buffer.vk.Valid, "GPUData-Buffer has already been assigned" | |
| 998 assert buffer.vk.Valid, "RenderData-Buffer has not yet been created" | |
| 999 value.buffer = buffer | |
| 1000 value.offset = offset | |
| 1001 offset = alignedTo(offset + value.size, BUFFER_ALIGNMENT) | |
| 1002 foundBuffer = true | |
| 1003 break | |
| 1004 assert foundBuffer, &"Unable to find large enough '{btype}' for '{data}'" | |
| 1005 proc AssignDirectBuffers[T](data: T, renderdata: var RenderData, btype: BufferType) = | |
| 1006 for name, value in fieldPairs(data): | |
| 1007 when typeof(value) is GPUData: | |
| 1008 when UsesDirectMemory(value): | |
| 1009 # find next buffer of correct type with enough free space | |
| 1010 var foundBuffer = false | |
| 1011 for (buffer, bt, offset) in renderData.directBuffers.mitems: | |
| 1012 if bt == btype and buffer.size - offset >= size: | |
| 1013 assert not value.buffer.vk.Valid, "GPUData-Buffer has already been assigned" | |
| 1014 assert buffer.vk.Valid, "RenderData-Buffer has not yet been created" | |
| 1015 value.buffer = buffer | |
| 1016 value.offset = offset | |
| 1017 offset = alignedTo(offset + value.size, BUFFER_ALIGNMENT) | |
| 1018 foundBuffer = true | |
| 1019 break | |
| 1020 assert foundBuffer, &"Unable to find large enough '{btype}' for '{data}'" | |
| 825 | 1021 |
| 826 proc WriteDescriptors[TShader](device: VkDevice, descriptorSets: array[INFLIGHTFRAMES.int, VkDescriptorSet]) = | 1022 proc WriteDescriptors[TShader](device: VkDevice, descriptorSets: array[INFLIGHTFRAMES.int, VkDescriptorSet]) = |
| 827 var descriptorSetWrites: seq[VkWriteDescriptorSet] | 1023 var descriptorSetWrites: seq[VkWriteDescriptorSet] |
| 828 # map (buffer + offset + range) to descriptor | 1024 # map (buffer + offset + range) to descriptor |
| 829 # map (texture) to descriptor | 1025 # map (texture) to descriptor |
| 861 descriptorType: descriptorType, | 1057 descriptorType: descriptorType, |
| 862 descriptorCount: descriptorCount, | 1058 descriptorCount: descriptorCount, |
| 863 pImageInfo: addr(imageInfo), | 1059 pImageInfo: addr(imageInfo), |
| 864 pBufferInfo: nil, | 1060 pBufferInfo: nil, |
| 865 ) | 1061 ) |
| 866 vkUpdateDescriptorSets(device, uint32(descriptorSetWrites.len), descriptorSetWrites.ToCPointer, 0, nil) | 1062 checkVkResult vkUpdateDescriptorSets(device, uint32(descriptorSetWrites.len), descriptorSetWrites.ToCPointer, 0, nil) |
| 867 | 1063 |
| 868 proc Bind[T](pipeline: Pipeline[T], commandBuffer: VkCommandBuffer, currentFrameInFlight: int) = | 1064 proc Bind[T](pipeline: Pipeline[T], commandBuffer: VkCommandBuffer, currentFrameInFlight: int) = |
| 869 commandBuffer.vkCmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline) | 1065 commandBuffer.vkCmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline) |
| 870 #[ | 1066 #[ |
| 871 commandBuffer.vkCmdBindDescriptorSets( | 1067 commandBuffer.vkCmdBindDescriptorSets( |
| 969 assert typeof(globalValue.data) is typeof(inputValue), "Shader input " & tt.name(TShader) & "." & inputName & " is of type '" & tt.name(typeof(inputValue)) & "' but global attribute is of type '" & tt.name(typeof(globalValue.data)) & "'" | 1165 assert typeof(globalValue.data) is typeof(inputValue), "Shader input " & tt.name(TShader) & "." & inputName & " is of type '" & tt.name(typeof(inputValue)) & "' but global attribute is of type '" & tt.name(typeof(globalValue.data)) & "'" |
| 970 foundField = true | 1166 foundField = true |
| 971 assert foundField, "Shader input '" & tt.name(TShader) & "." & inputName & ": " & tt.name(typeof(inputValue)) & "' not found in '" & tt.name(TMesh) & "|" & tt.name(TGlobals) & "'" | 1167 assert foundField, "Shader input '" & tt.name(TShader) & "." & inputName & ": " & tt.name(typeof(inputValue)) & "' not found in '" & tt.name(TMesh) & "|" & tt.name(TGlobals) & "'" |
| 972 | 1168 |
| 973 | 1169 |
| 974 proc Render[TShader, TMesh, TInstance, TUniforms, TGlobals]( | 1170 proc Render[TShader, TUniforms, TGlobals, TMesh, TInstance]( |
| 1171 commandBuffer: VkCommandBuffer, | |
| 975 pipeline: Pipeline[TShader], | 1172 pipeline: Pipeline[TShader], |
| 976 renderable: Renderable[TMesh, TInstance], | |
| 977 uniforms: TUniforms, | 1173 uniforms: TUniforms, |
| 978 globals: TGlobals, | 1174 globals: TGlobals, |
| 979 commandBuffer: VkCommandBuffer, | 1175 mesh: TMesh, |
| 1176 instances: TInstance, | |
| 980 ) = | 1177 ) = |
| 981 static: AssertCompatible(TShader, TMesh, TInstance, TUniforms, TGlobals) | 1178 static: AssertCompatible(TShader, TMesh, TInstance, TUniforms, TGlobals) |
| 1179 #[ | |
| 982 if renderable.vertexBuffers.len > 0: | 1180 if renderable.vertexBuffers.len > 0: |
| 983 commandBuffer.vkCmdBindVertexBuffers( | 1181 commandBuffer.vkCmdBindVertexBuffers( |
| 984 firstBinding = 0'u32, | 1182 firstBinding = 0'u32, |
| 985 bindingCount = uint32(renderable.vertexBuffers.len), | 1183 bindingCount = uint32(renderable.vertexBuffers.len), |
| 986 pBuffers = renderable.vertexBuffers.ToCPointer(), | 1184 pBuffers = renderable.vertexBuffers.ToCPointer(), |
| 1004 vertexCount = renderable.vertexCount, | 1202 vertexCount = renderable.vertexCount, |
| 1005 instanceCount = renderable.instanceCount, | 1203 instanceCount = renderable.instanceCount, |
| 1006 firstVertex = 0, | 1204 firstVertex = 0, |
| 1007 firstInstance = 0 | 1205 firstInstance = 0 |
| 1008 ) | 1206 ) |
| 1207 ]# | |
| 1009 | 1208 |
| 1010 when isMainModule: | 1209 when isMainModule: |
| 1011 import semicongine/platform/window | 1210 import semicongine/platform/window |
| 1012 import semicongine/vulkan/instance | 1211 import semicongine/vulkan/instance |
| 1013 import semicongine/vulkan/device | 1212 import semicongine/vulkan/device |
| 1053 vertexCode: string = "void main() {}" | 1252 vertexCode: string = "void main() {}" |
| 1054 fragmentCode: string = "void main() {}" | 1253 fragmentCode: string = "void main() {}" |
| 1055 | 1254 |
| 1056 let w = CreateWindow("test2") | 1255 let w = CreateWindow("test2") |
| 1057 putEnv("VK_LAYER_ENABLES", "VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_AMD,VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_NVIDIA,VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXTVK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT,VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT") | 1256 putEnv("VK_LAYER_ENABLES", "VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_AMD,VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_NVIDIA,VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXTVK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT,VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT") |
| 1058 let i = w.CreateInstance( | 1257 let vulkan = w.CreateInstance( |
| 1059 vulkanVersion = VK_MAKE_API_VERSION(0, 1, 3, 0), | 1258 vulkanVersion = VK_MAKE_API_VERSION(0, 1, 3, 0), |
| 1060 instanceExtensions = @[], | 1259 instanceExtensions = @[], |
| 1061 layers = @["VK_LAYER_KHRONOS_validation"], | 1260 layers = @["VK_LAYER_KHRONOS_validation"], |
| 1062 ) | 1261 ) |
| 1063 | 1262 |
| 1064 let selectedPhysicalDevice = i.GetPhysicalDevices().FilterBestGraphics() | 1263 let dev = vulkan.CreateDevice( |
| 1065 let dev = i.CreateDevice( | 1264 GetPhysicalDevice(), |
| 1066 selectedPhysicalDevice, | |
| 1067 enabledExtensions = @[], | 1265 enabledExtensions = @[], |
| 1068 selectedPhysicalDevice.FilterForGraphicsPresentationQueues() | 1266 [GetQueueFamily()], |
| 1069 ) | 1267 ) |
| 1070 let frameWidth = 100'u32 | 1268 let frameWidth = 100'u32 |
| 1071 let frameHeight = 100'u32 | 1269 let frameHeight = 100'u32 |
| 1072 | 1270 |
| 1073 var myMesh1 = MeshA( | 1271 var myMesh1 = MeshA( |
| 1092 var myGlobals: GlobalsA | 1290 var myGlobals: GlobalsA |
| 1093 | 1291 |
| 1094 # setup for rendering (TODO: swapchain & framebuffers) | 1292 # setup for rendering (TODO: swapchain & framebuffers) |
| 1095 | 1293 |
| 1096 # renderpass | 1294 # renderpass |
| 1097 let renderpass = dev.vk.CreateRenderPass(dev.physicalDevice.GetSurfaceFormats().FilterSurfaceFormat().format) | 1295 let renderpass = CreateRenderPass(dev.vk, dev.physicalDevice.GetSurfaceFormats().FilterSurfaceFormat().format) |
| 1098 | 1296 |
| 1099 # shaders | 1297 # shaders |
| 1100 const shader = ShaderA() | 1298 const shader = ShaderA() |
| 1101 let shaderObject = dev.vk.CompileShader(shader) | 1299 let shaderObject = dev.vk.CompileShader(shader) |
| 1102 var pipeline1 = CreatePipeline(dev.vk, renderPass = renderpass, shaderObject) | 1300 var pipeline1 = CreatePipeline(device = dev.vk, renderPass = renderpass, shader = shaderObject) |
| 1103 | 1301 |
| 1104 var renderdata = InitRenderData(dev.vk, dev.physicalDevice.vk) | 1302 var renderdata = InitRenderData(dev.vk, dev.physicalDevice.vk) |
| 1105 | 1303 |
| 1106 # create descriptor sets | 1304 # create descriptor sets |
| 1107 #[ | 1305 #[ |
| 1126 # | 1324 # |
| 1127 # upload all textures | 1325 # upload all textures |
| 1128 # write descriptors for textures and uniform buffers | 1326 # write descriptors for textures and uniform buffers |
| 1129 # | 1327 # |
| 1130 ]# | 1328 ]# |
| 1131 var myRenderable: Renderable[MeshA, InstanceA] | 1329 |
| 1132 | 1330 # buffer allocation |
| 1133 var | 1331 var |
| 1134 indirectVertexSizes = 0'u64 | 1332 indirectVertexSizes = 0'u64 |
| 1135 directVertexSizes = 0'u64 | 1333 directVertexSizes = 0'u64 |
| 1136 indirectIndexSizes = 0'u64 | 1334 indirectIndexSizes = 0'u64 |
| 1137 directIndexSizes = 0'u64 | 1335 directIndexSizes = 0'u64 |
| 1139 directUniformSizes = 0'u64 | 1337 directUniformSizes = 0'u64 |
| 1140 | 1338 |
| 1141 indirectVertexSizes += GetIndirectBufferSizes(myMesh1) | 1339 indirectVertexSizes += GetIndirectBufferSizes(myMesh1) |
| 1142 indirectVertexSizes += GetIndirectBufferSizes(instances1) | 1340 indirectVertexSizes += GetIndirectBufferSizes(instances1) |
| 1143 if indirectVertexSizes > 0: | 1341 if indirectVertexSizes > 0: |
| 1144 AllocateIndirectBuffer(dev.vk, renderdata, indirectVertexSizes, [VK_BUFFER_USAGE_VERTEX_BUFFER_BIT]) | 1342 AllocateIndirectBuffer(dev.vk, renderdata, indirectVertexSizes, VertexBuffer) |
| 1145 | 1343 |
| 1146 directVertexSizes += GetDirectBufferSizes(myMesh1) | 1344 directVertexSizes += GetDirectBufferSizes(myMesh1) |
| 1147 directVertexSizes += GetDirectBufferSizes(instances1) | 1345 directVertexSizes += GetDirectBufferSizes(instances1) |
| 1148 if directVertexSizes > 0: | 1346 if directVertexSizes > 0: |
| 1149 AllocateDirectBuffer(dev.vk, renderdata, directVertexSizes, [VK_BUFFER_USAGE_VERTEX_BUFFER_BIT]) | 1347 AllocateDirectBuffer(dev.vk, renderdata, directVertexSizes, VertexBuffer) |
| 1150 | 1348 |
| 1151 indirectIndexSizes += GetIndirectIndexBufferSizes(myMesh1) | 1349 indirectIndexSizes += GetIndirectIndexBufferSizes(myMesh1) |
| 1152 if indirectIndexSizes > 0: | 1350 if indirectIndexSizes > 0: |
| 1153 AllocateIndirectBuffer(dev.vk, renderdata, indirectIndexSizes, [VK_BUFFER_USAGE_INDEX_BUFFER_BIT]) | 1351 AllocateIndirectBuffer(dev.vk, renderdata, indirectIndexSizes, IndexBuffer) |
| 1154 | 1352 |
| 1155 directIndexSizes += GetDirectIndexBufferSizes(myMesh1) | 1353 directIndexSizes += GetDirectIndexBufferSizes(myMesh1) |
| 1156 if directIndexSizes > 0: | 1354 if directIndexSizes > 0: |
| 1157 AllocateIndirectBuffer(dev.vk, renderdata, directIndexSizes, [VK_BUFFER_USAGE_INDEX_BUFFER_BIT]) | 1355 AllocateDirectBuffer(dev.vk, renderdata, directIndexSizes, IndexBuffer) |
| 1158 | 1356 |
| 1159 indirectUniformSizes += GetIndirectBufferSizes(uniforms1) | 1357 indirectUniformSizes += GetIndirectBufferSizes(uniforms1) |
| 1160 indirectUniformSizes += GetIndirectBufferSizes(myGlobals) | 1358 indirectUniformSizes += GetIndirectBufferSizes(myGlobals) |
| 1161 if indirectUniformSizes > 0: | 1359 if indirectUniformSizes > 0: |
| 1162 AllocateIndirectBuffer(dev.vk, renderdata, indirectUniformSizes, [VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT]) | 1360 AllocateIndirectBuffer(dev.vk, renderdata, indirectUniformSizes, UniformBuffer) |
| 1163 | 1361 |
| 1164 directUniformSizes += GetDirectBufferSizes(uniforms1) | 1362 directUniformSizes += GetDirectBufferSizes(uniforms1) |
| 1165 directUniformSizes += GetDirectBufferSizes(myGlobals) | 1363 directUniformSizes += GetDirectBufferSizes(myGlobals) |
| 1166 if directUniformSizes > 0: | 1364 if directUniformSizes > 0: |
| 1167 AllocateDirectBuffer(dev.vk, renderdata, directUniformSizes, [VK_BUFFER_USAGE_VERTEX_BUFFER_BIT]) | 1365 AllocateDirectBuffer(dev.vk, renderdata, directUniformSizes, UniformBuffer) |
| 1366 | |
| 1367 # buffer assignment | |
| 1368 | |
| 1369 AssignIndirectBuffers(data = myMesh1, renderdata = RenderData, btype = VertexBuffer) | |
| 1370 AssignDirectBuffers(data = myMesh1, renderdata = RenderData, btype = VertexBuffer) | |
| 1371 AssignIndirectBuffers(data = myMesh1, renderdata = RenderData, btype = IndexBuffer) | |
| 1372 AssignDirectBuffers(data = myMesh1, renderdata = RenderData, btype = IndexBuffer) | |
| 1373 | |
| 1374 AssignIndirectBuffers(data = instances1, renderdata = RenderData, btype = VertexBuffer) | |
| 1375 AssignDirectBuffers(data = instances1, renderdata = RenderData, btype = VertexBuffer) | |
| 1376 | |
| 1377 AssignIndirectBuffers(data = uniforms1, renderdata = RenderData, btype = UniformBuffer) | |
| 1378 AssignDirectBuffers(data = uniforms1, renderdata = RenderData, btype = UniformBuffer) | |
| 1379 AssignIndirectBuffers(data = myGlobals, renderdata = RenderData, btype = UniformBuffer) | |
| 1380 AssignDirectBuffers(data = myGlobals, renderdata = RenderData, btype = UniformBuffer) | |
| 1381 | |
| 1382 UpdateGPUBuffer() | |
| 1168 | 1383 |
| 1169 # descriptors | 1384 # descriptors |
| 1170 # WriteDescriptors(dev.vk, pipeline1) | 1385 # WriteDescriptors(dev.vk, pipeline1) |
| 1171 | 1386 |
| 1172 # command buffer | 1387 # command buffer |
| 1173 var | 1388 var |
| 1174 commandBufferPool: VkCommandPool | 1389 commandBufferPool: VkCommandPool |
| 1175 cmdBuffers: array[INFLIGHTFRAMES.int, VkCommandBuffer] | |
| 1176 createInfo = VkCommandPoolCreateInfo( | 1390 createInfo = VkCommandPoolCreateInfo( |
| 1177 sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, | 1391 sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, |
| 1178 flags: toBits [VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT], | 1392 flags: toBits [VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT], |
| 1179 queueFamilyIndex: dev.FirstGraphicsQueue().get().family.index, | 1393 queueFamilyIndex: GetQueueFamily(dev.vk), |
| 1180 ) | 1394 ) |
| 1181 checkVkResult vkCreateCommandPool(dev.vk, addr createInfo, nil, addr commandBufferPool) | 1395 checkVkResult vkCreateCommandPool(dev.vk, addr createInfo, nil, addr commandBufferPool) |
| 1182 var allocInfo = VkCommandBufferAllocateInfo( | 1396 var |
| 1183 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, | 1397 cmdBuffers: array[INFLIGHTFRAMES.int, VkCommandBuffer] |
| 1184 commandPool: commandBufferPool, | 1398 allocInfo = VkCommandBufferAllocateInfo( |
| 1185 level: VK_COMMAND_BUFFER_LEVEL_PRIMARY, | 1399 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, |
| 1186 commandBufferCount: INFLIGHTFRAMES, | 1400 commandPool: commandBufferPool, |
| 1187 ) | 1401 level: VK_COMMAND_BUFFER_LEVEL_PRIMARY, |
| 1402 commandBufferCount: INFLIGHTFRAMES, | |
| 1403 ) | |
| 1188 checkVkResult vkAllocateCommandBuffers(dev.vk, addr allocInfo, cmdBuffers.ToCPointer) | 1404 checkVkResult vkAllocateCommandBuffers(dev.vk, addr allocInfo, cmdBuffers.ToCPointer) |
| 1189 | 1405 |
| 1190 # start command buffer | 1406 # start command buffer |
| 1191 block: | 1407 block: |
| 1192 let | 1408 let |
| 1205 var | 1421 var |
| 1206 clearColors = [VkClearValue(color: VkClearColorValue(float32: [0, 0, 0, 0]))] | 1422 clearColors = [VkClearValue(color: VkClearColorValue(float32: [0, 0, 0, 0]))] |
| 1207 renderPassInfo = VkRenderPassBeginInfo( | 1423 renderPassInfo = VkRenderPassBeginInfo( |
| 1208 sType: VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, | 1424 sType: VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, |
| 1209 renderPass: renderpass, | 1425 renderPass: renderpass, |
| 1210 framebuffer: currentFramebuffer, | 1426 framebuffer: currentFramebuffer, # TODO |
| 1211 renderArea: VkRect2D( | 1427 renderArea: VkRect2D( |
| 1212 offset: VkOffset2D(x: 0, y: 0), | 1428 offset: VkOffset2D(x: 0, y: 0), |
| 1213 extent: VkExtent2D(width: frameWidth, height: frameHeight), | 1429 extent: VkExtent2D(width: frameWidth, height: frameHeight), |
| 1214 ), | 1430 ), |
| 1215 clearValueCount: uint32(clearColors.len), | 1431 clearValueCount: uint32(clearColors.len), |
| 1225 ) | 1441 ) |
| 1226 scissor = VkRect2D( | 1442 scissor = VkRect2D( |
| 1227 offset: VkOffset2D(x: 0, y: 0), | 1443 offset: VkOffset2D(x: 0, y: 0), |
| 1228 extent: VkExtent2D(width: frameWidth, height: frameHeight) | 1444 extent: VkExtent2D(width: frameWidth, height: frameHeight) |
| 1229 ) | 1445 ) |
| 1230 vkCmdBeginRenderPass(cmd, addr(renderPassInfo), VK_SUBPASS_CONTENTS_INLINE) | 1446 checkVkResult vkCmdBeginRenderPass(cmd, addr(renderPassInfo), VK_SUBPASS_CONTENTS_INLINE) |
| 1231 | 1447 |
| 1232 # setup viewport | 1448 # setup viewport |
| 1233 vkCmdSetViewport(cmd, firstViewport = 0, viewportCount = 1, addr(viewport)) | 1449 vkCmdSetViewport(cmd, firstViewport = 0, viewportCount = 1, addr(viewport)) |
| 1234 vkCmdSetScissor(cmd, firstScissor = 0, scissorCount = 1, addr(scissor)) | 1450 vkCmdSetScissor(cmd, firstScissor = 0, scissorCount = 1, addr(scissor)) |
| 1235 | 1451 |
| 1237 block: | 1453 block: |
| 1238 Bind(pipeline1, cmd, currentFrameInFlight = currentFrameInFlight) | 1454 Bind(pipeline1, cmd, currentFrameInFlight = currentFrameInFlight) |
| 1239 | 1455 |
| 1240 # render object, will be loop | 1456 # render object, will be loop |
| 1241 block: | 1457 block: |
| 1242 Render(pipeline1, myRenderable, uniforms1, myGlobals, cmd) | 1458 Render(cmd, pipeline1, uniforms1, myGlobals, myMesh1, instances1) |
| 1243 | 1459 |
| 1244 vkCmdEndRenderPass(cmd) | 1460 vkCmdEndRenderPass(cmd) |
| 1245 checkVkResult cmd.vkEndCommandBuffer() | 1461 checkVkResult cmd.vkEndCommandBuffer() |
