Mercurial > games > semicongine
comparison static_utils.nim @ 1184:3f43c7163029 compiletime-tests
sync from bedroom to office
| author | sam <sam@basx.dev> |
|---|---|
| date | Sat, 06 Jul 2024 00:31:17 +0700 |
| parents | 850450bfe2a2 |
| children | 565fcfde427a |
comparison
equal
deleted
inserted
replaced
| 1183:850450bfe2a2 | 1184:3f43c7163029 |
|---|---|
| 10 import semicongine/core/utils | 10 import semicongine/core/utils |
| 11 import semicongine/core/vector | 11 import semicongine/core/vector |
| 12 import semicongine/core/matrix | 12 import semicongine/core/matrix |
| 13 import semicongine/core/vulkanapi | 13 import semicongine/core/vulkanapi |
| 14 | 14 |
| 15 import ./vulkan_utils | |
| 16 | |
| 15 template VertexAttribute {.pragma.} | 17 template VertexAttribute {.pragma.} |
| 16 template InstanceAttribute {.pragma.} | 18 template InstanceAttribute {.pragma.} |
| 17 template Pass {.pragma.} | 19 template Pass {.pragma.} |
| 18 template PassFlat {.pragma.} | 20 template PassFlat {.pragma.} |
| 19 template ShaderOutput {.pragma.} | 21 template ShaderOutput {.pragma.} |
| 24 const BUFFER_ALIGNMENT = 64'u64 # align offsets inside buffers along this alignment | 26 const BUFFER_ALIGNMENT = 64'u64 # align offsets inside buffers along this alignment |
| 25 | 27 |
| 26 # some globals that will (likely?) never change during the life time of the engine | 28 # some globals that will (likely?) never change during the life time of the engine |
| 27 type | 29 type |
| 28 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 SupportedGPUType = float32 | float64 | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | TVec2[int32] | TVec2[int64] | TVec3[int32] | TVec3[int64] | TVec4[int32] | TVec4[int64] | TVec2[uint32] | TVec2[uint64] | TVec3[uint32] | TVec3[uint64] | TVec4[uint32] | TVec4[uint64] | TVec2[float32] | TVec2[float64] | TVec3[float32] | TVec3[float64] | TVec4[float32] | TVec4[float64] | TMat2[float32] | TMat2[float64] | TMat23[float32] | TMat23[float64] | TMat32[float32] | TMat32[float64] | TMat3[float32] | TMat3[float64] | TMat34[float32] | TMat34[float64] | TMat43[float32] | TMat43[float64] | TMat4[float32] | TMat4[float64] |
| 31 TextureType = TVec1[uint8] | TVec2[uint8] | TVec3[uint8] | TVec4[uint8] | |
| 29 | 32 |
| 30 ShaderObject[TShader] = object | 33 ShaderObject[TShader] = object |
| 31 vertexShader: VkShaderModule | 34 vertexShader: VkShaderModule |
| 32 fragmentShader: VkShaderModule | 35 fragmentShader: VkShaderModule |
| 33 | |
| 34 VulkanGlobals = object | |
| 35 instance: VkInstance | |
| 36 device: VkDevice | |
| 37 physicalDevice: VkPhysicalDevice | |
| 38 queueFamilyIndex: uint32 | |
| 39 queue: VkQueue | |
| 40 | 36 |
| 41 IndexType = enum | 37 IndexType = enum |
| 42 None, UInt8, UInt16, UInt32 | 38 None, UInt8, UInt16, UInt32 |
| 43 | 39 |
| 44 IndirectGPUMemory = object | 40 IndirectGPUMemory = object |
| 55 Buffer[TMemory: GPUMemory] = object | 51 Buffer[TMemory: GPUMemory] = object |
| 56 memory: TMemory | 52 memory: TMemory |
| 57 vk: VkBuffer | 53 vk: VkBuffer |
| 58 offset: uint64 | 54 offset: uint64 |
| 59 size: uint64 | 55 size: uint64 |
| 60 Texture[Channels: static int, TMemory: GPUMemory] = object | 56 Texture[T: TextureType, TMemory: GPUMemory] = object |
| 61 memory: TMemory | 57 memory: TMemory |
| 62 vk: VkImage | 58 vk: VkImage |
| 59 format: VkFormat | |
| 63 imageview: VkImageView | 60 imageview: VkImageView |
| 64 sampler: VkSampler | 61 sampler: VkSampler |
| 65 offset: uint64 | 62 offset: uint64 |
| 66 size: uint64 | 63 size: uint64 |
| 67 width: int | 64 width: uint32 |
| 68 data: seq[array[Channels, uint8]] | 65 height: uint32 |
| 66 data: seq[T] | |
| 69 | 67 |
| 70 GPUArray[T: SupportedGPUType, TMemory: GPUMemory] = object | 68 GPUArray[T: SupportedGPUType, TMemory: GPUMemory] = object |
| 71 data: seq[T] | 69 data: seq[T] |
| 72 buffer: Buffer[TMemory] | 70 buffer: Buffer[TMemory] |
| 73 offset: uint64 | 71 offset: uint64 |
| 96 indirectMemory: seq[tuple[memory: IndirectGPUMemory, usedOffset: uint64]] | 94 indirectMemory: seq[tuple[memory: IndirectGPUMemory, usedOffset: uint64]] |
| 97 directMemory: seq[tuple[memory: DirectGPUMemory, usedOffset: uint64]] | 95 directMemory: seq[tuple[memory: DirectGPUMemory, usedOffset: uint64]] |
| 98 indirectBuffers: seq[tuple[buffer: Buffer[IndirectGPUMemory], btype: BufferType, usedOffset: uint64]] | 96 indirectBuffers: seq[tuple[buffer: Buffer[IndirectGPUMemory], btype: BufferType, usedOffset: uint64]] |
| 99 directBuffers: seq[tuple[buffer: Buffer[DirectGPUMemory], btype: BufferType, usedOffset: uint64]] | 97 directBuffers: seq[tuple[buffer: Buffer[DirectGPUMemory], btype: BufferType, usedOffset: uint64]] |
| 100 | 98 |
| 101 var vulkan: VulkanGlobals | 99 func size(texture: Texture): uint64 = |
| 100 texture.data.len * sizeof(elementType(texture.data)) | |
| 101 | |
| 102 func depth(texture: Texture): int = | |
| 103 default(elementType(texture.data)).len | |
| 104 | |
| 105 proc GetVkFormat(depth: int, usage: openArray[VkImageUsageFlagBits]): VkFormat = | |
| 106 const DEPTH_FORMAT_MAP = [ | |
| 107 0: [VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED], | |
| 108 1: [VK_FORMAT_R8_SRGB, VK_FORMAT_R8_UNORM], | |
| 109 2: [VK_FORMAT_R8G8_SRGB, VK_FORMAT_R8G8_UNORM], | |
| 110 3: [VK_FORMAT_R8G8B8_SRGB, VK_FORMAT_R8G8B8_UNORM], | |
| 111 4: [VK_FORMAT_R8G8B8A8_SRGB, VK_FORMAT_R8G8B8A8_UNORM], | |
| 112 ] | |
| 113 | |
| 114 var formatProperties = VkImageFormatProperties2(sType: VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2) | |
| 115 for format in DEPTH_FORMAT_MAP[depth]: | |
| 116 var formatInfo = VkPhysicalDeviceImageFormatInfo2( | |
| 117 sType: VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, | |
| 118 format: format, | |
| 119 thetype: VK_IMAGE_TYPE_2D, | |
| 120 tiling: VK_IMAGE_TILING_OPTIMAL, | |
| 121 usage: usage.toBits, | |
| 122 ) | |
| 123 let formatCheck = vkGetPhysicalDeviceImageFormatProperties2( | |
| 124 vulkan.physicalDevice, | |
| 125 addr formatInfo, | |
| 126 addr formatProperties, | |
| 127 ) | |
| 128 if formatCheck == VK_SUCCESS: # found suitable format | |
| 129 return format | |
| 130 elif formatCheck == VK_ERROR_FORMAT_NOT_SUPPORTED: # nope, try to find other format | |
| 131 continue | |
| 132 else: # raise error | |
| 133 checkVkResult formatCheck | |
| 134 | |
| 135 assert false, "Unable to find format for textures" | |
| 136 | |
| 102 | 137 |
| 103 func alignedTo[T: SomeInteger](value: T, alignment: T): T = | 138 func alignedTo[T: SomeInteger](value: T, alignment: T): T = |
| 104 let remainder = value mod alignment | 139 let remainder = value mod alignment |
| 105 if remainder == 0: | 140 if remainder == 0: |
| 106 return value | 141 return value |
| 298 template datapointer(gpuArray: GPUArray): pointer = | 333 template datapointer(gpuArray: GPUArray): pointer = |
| 299 addr(gpuArray.data[0]) | 334 addr(gpuArray.data[0]) |
| 300 template datapointer(gpuValue: GPUValue): pointer = | 335 template datapointer(gpuValue: GPUValue): pointer = |
| 301 addr(gpuValue.data) | 336 addr(gpuValue.data) |
| 302 | 337 |
| 303 proc AllocationSize(buffer: Buffer): uint64 = | 338 proc RequiredMemorySize(buffer: VkBuffer): uint64 = |
| 304 var req: VkMemoryRequirements | 339 var req: VkMemoryRequirements |
| 305 vkGetBufferMemoryRequirements(vulkan.device, buffer.vk, addr(req)) | 340 vkGetBufferMemoryRequirements(vulkan.device, buffer, addr(req)) |
| 341 return req.size | |
| 342 | |
| 343 proc RequiredMemorySize(image: VkImage): uint64 = | |
| 344 var req: VkMemoryRequirements | |
| 345 vkGetImageMemoryRequirements(vulkan.device, image, addr req) | |
| 306 return req.size | 346 return req.size |
| 307 | 347 |
| 308 proc GetPhysicalDevice(instance: VkInstance): VkPhysicalDevice = | 348 proc GetPhysicalDevice(instance: VkInstance): VkPhysicalDevice = |
| 309 var nDevices: uint32 | 349 var nDevices: uint32 |
| 310 checkVkResult vkEnumeratePhysicalDevices(instance, addr(nDevices), nil) | 350 checkVkResult vkEnumeratePhysicalDevices(instance, addr(nDevices), nil) |
| 366 | 406 |
| 367 proc GetSurfaceFormat(): VkFormat = | 407 proc GetSurfaceFormat(): VkFormat = |
| 368 # EVERY windows driver and almost every linux driver should support this | 408 # EVERY windows driver and almost every linux driver should support this |
| 369 VK_FORMAT_B8G8R8A8_SRGB | 409 VK_FORMAT_B8G8R8A8_SRGB |
| 370 | 410 |
| 371 template WithSingleUseCommandBuffer(device: VkDevice, cmd, body: untyped): untyped = | 411 template WithSingleUseCommandBuffer(cmd, body: untyped): untyped = |
| 372 block: | 412 block: |
| 373 var | 413 var |
| 374 commandBufferPool: VkCommandPool | 414 commandBufferPool: VkCommandPool |
| 375 createInfo = VkCommandPoolCreateInfo( | 415 createInfo = VkCommandPoolCreateInfo( |
| 376 sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, | 416 sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, |
| 377 flags: toBits [VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT], | 417 flags: toBits [VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT], |
| 378 queueFamilyIndex: vulkan.queueFamilyIndex, | 418 queueFamilyIndex: vulkan.queueFamilyIndex, |
| 379 ) | 419 ) |
| 380 checkVkResult vkCreateCommandPool(device, addr createInfo, nil, addr(commandBufferPool)) | 420 checkVkResult vkCreateCommandPool(vulkan.device, addr createInfo, nil, addr(commandBufferPool)) |
| 381 var | 421 var |
| 382 `cmd` {.inject.}: VkCommandBuffer | 422 `cmd` {.inject.}: VkCommandBuffer |
| 383 allocInfo = VkCommandBufferAllocateInfo( | 423 allocInfo = VkCommandBufferAllocateInfo( |
| 384 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, | 424 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, |
| 385 commandPool: commandBufferPool, | 425 commandPool: commandBufferPool, |
| 386 level: VK_COMMAND_BUFFER_LEVEL_PRIMARY, | 426 level: VK_COMMAND_BUFFER_LEVEL_PRIMARY, |
| 387 commandBufferCount: 1, | 427 commandBufferCount: 1, |
| 388 ) | 428 ) |
| 389 checkVkResult device.vkAllocateCommandBuffers(addr allocInfo, addr(`cmd`)) | 429 checkVkResult vulkan.device.vkAllocateCommandBuffers(addr allocInfo, addr(`cmd`)) |
| 390 var beginInfo = VkCommandBufferBeginInfo( | 430 var beginInfo = VkCommandBufferBeginInfo( |
| 391 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, | 431 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, |
| 392 flags: VkCommandBufferUsageFlags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT), | 432 flags: VkCommandBufferUsageFlags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT), |
| 393 ) | 433 ) |
| 394 checkVkResult `cmd`.vkBeginCommandBuffer(addr beginInfo) | 434 checkVkResult `cmd`.vkBeginCommandBuffer(addr beginInfo) |
| 406 fence: VkFence | 446 fence: VkFence |
| 407 fenceInfo = VkFenceCreateInfo( | 447 fenceInfo = VkFenceCreateInfo( |
| 408 sType: VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, | 448 sType: VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, |
| 409 # flags: toBits [VK_FENCE_CREATE_SIGNALED_BIT] | 449 # flags: toBits [VK_FENCE_CREATE_SIGNALED_BIT] |
| 410 ) | 450 ) |
| 411 checkVkResult device.vkCreateFence(addr(fenceInfo), nil, addr(fence)) | 451 checkVkResult vulkan.device.vkCreateFence(addr(fenceInfo), nil, addr(fence)) |
| 412 checkVkResult vkQueueSubmit(vulkan.queue, 1, addr(submitInfo), fence) | 452 checkVkResult vkQueueSubmit(vulkan.queue, 1, addr(submitInfo), fence) |
| 413 checkVkResult vkWaitForFences(device, 1, addr fence, false, high(uint64)) | 453 checkVkResult vkWaitForFences(vulkan.device, 1, addr fence, false, high(uint64)) |
| 414 vkDestroyCommandPool(device, commandBufferPool, nil) | 454 vkDestroyCommandPool(vulkan.device, commandBufferPool, nil) |
| 415 | 455 |
| 416 | 456 |
| 417 proc UpdateGPUBuffer(gpuData: GPUData) = | 457 proc UpdateGPUBuffer(gpuData: GPUData) = |
| 418 if gpuData.size == 0: | 458 if gpuData.size == 0: |
| 419 return | 459 return |
| 420 when UsesDirectMemory(gpuData): | 460 when UsesDirectMemory(gpuData): |
| 421 copyMem(cast[pointer](cast[uint64](gpuData.buffer.memory.data) + gpuData.buffer.offset + gpuData.offset), gpuData.datapointer, gpuData.size) | 461 copyMem(cast[pointer](cast[uint64](gpuData.buffer.memory.data) + gpuData.buffer.offset + gpuData.offset), gpuData.datapointer, gpuData.size) |
| 422 else: | 462 else: |
| 423 var | 463 WithStagingBuffer(gpuData.buffer.vk, gpuData.buffer.vk.RequiredMemorySize(), GetDirectMemoryTypeIndex(), stagingPtr): |
| 424 stagingBuffer: VkBuffer | 464 copyMem(stagingPtr, gpuData.datapointer, gpuData.size) |
| 425 createInfo = VkBufferCreateInfo( | |
| 426 sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | |
| 427 flags: VkBufferCreateFlags(0), | |
| 428 size: gpuData.size, | |
| 429 usage: toBits([VK_BUFFER_USAGE_TRANSFER_SRC_BIT]), | |
| 430 sharingMode: VK_SHARING_MODE_EXCLUSIVE, | |
| 431 ) | |
| 432 checkVkResult vkCreateBuffer( | |
| 433 device = vulkan.device, | |
| 434 pCreateInfo = addr(createInfo), | |
| 435 pAllocator = nil, | |
| 436 pBuffer = addr(stagingBuffer), | |
| 437 ) | |
| 438 var | |
| 439 stagingMemory: VkDeviceMemory | |
| 440 stagingPtr: pointer | |
| 441 memoryAllocationInfo = VkMemoryAllocateInfo( | |
| 442 sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, | |
| 443 allocationSize: gpuData.buffer.AllocationSize(), | |
| 444 memoryTypeIndex: GetDirectMemoryTypeIndex(), | |
| 445 ) | |
| 446 checkVkResult vkAllocateMemory( | |
| 447 vulkan.device, | |
| 448 addr(memoryAllocationInfo), | |
| 449 nil, | |
| 450 addr(stagingMemory), | |
| 451 ) | |
| 452 checkVkResult vkBindBufferMemory(vulkan.device, stagingBuffer, stagingMemory, 0) | |
| 453 checkVkResult vkMapMemory( | |
| 454 device = vulkan.device, | |
| 455 memory = stagingMemory, | |
| 456 offset = 0'u64, | |
| 457 size = VK_WHOLE_SIZE, | |
| 458 flags = VkMemoryMapFlags(0), | |
| 459 ppData = addr(stagingPtr) | |
| 460 ) | |
| 461 copyMem(stagingPtr, gpuData.datapointer, gpuData.size) | |
| 462 var stagingRange = VkMappedMemoryRange( | |
| 463 sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, | |
| 464 memory: stagingMemory, | |
| 465 size: VK_WHOLE_SIZE, | |
| 466 ) | |
| 467 checkVkResult vkFlushMappedMemoryRanges(vulkan.device, 1, addr(stagingRange)) | |
| 468 | |
| 469 WithSingleUseCommandBuffer(vulkan.device, commandBuffer): | |
| 470 var copyRegion = VkBufferCopy(size: gpuData.size) | |
| 471 vkCmdCopyBuffer(commandBuffer, stagingBuffer, gpuData.buffer.vk, 1, addr(copyRegion)) | |
| 472 | |
| 473 vkDestroyBuffer(vulkan.device, stagingBuffer, nil) | |
| 474 vkFreeMemory(vulkan.device, stagingMemory, nil) | |
| 475 | 465 |
| 476 proc UpdateAllGPUBuffers[T](value: T) = | 466 proc UpdateAllGPUBuffers[T](value: T) = |
| 477 for name, fieldvalue in value.fieldPairs(): | 467 for name, fieldvalue in value.fieldPairs(): |
| 478 when typeof(fieldvalue) is GPUData: | 468 when typeof(fieldvalue) is GPUData: |
| 479 UpdateGPUBuffer(fieldvalue) | 469 UpdateGPUBuffer(fieldvalue) |
| 500 pSetLayouts: layouts.ToCPointer, | 490 pSetLayouts: layouts.ToCPointer, |
| 501 ) | 491 ) |
| 502 checkVkResult vkAllocateDescriptorSets(vulkan.device, addr(allocInfo), descriptorSet.vk.ToCPointer) | 492 checkVkResult vkAllocateDescriptorSets(vulkan.device, addr(allocInfo), descriptorSet.vk.ToCPointer) |
| 503 | 493 |
| 504 # write | 494 # write |
| 505 var descriptorSetWrites = newSeq[VkWriteDescriptorSet](descriptorSet.vk.len) | 495 var descriptorSetWrites = newSeqOfCap[VkWriteDescriptorSet](1024) |
| 506 | 496 var imageWrites = newSeqOfCap[VkDescriptorImageInfo](1024) |
| 507 var descriptorBinding = 0 | 497 var bufferWrites = newSeqOfCap[VkDescriptorBufferInfo](1024) |
| 498 | |
| 508 ForDescriptorFields(descriptorSet.data, fieldName, fieldValue, descriptorType, descriptorCount, descriptorBindingNumber): | 499 ForDescriptorFields(descriptorSet.data, fieldName, fieldValue, descriptorType, descriptorCount, descriptorBindingNumber): |
| 509 for i in 0 ..< descriptorSet.vk.len: | 500 for i in 0 ..< descriptorSet.vk.len: |
| 510 when typeof(fieldValue) is GPUValue: | 501 when typeof(fieldValue) is GPUValue: |
| 511 let bufferInfo = VkDescriptorBufferInfo( | 502 bufferWrites.add VkDescriptorBufferInfo( |
| 512 buffer: fieldValue.buffer.vk, | 503 buffer: fieldValue.buffer.vk, |
| 513 offset: fieldValue.buffer.offset, | 504 offset: fieldValue.buffer.offset, |
| 514 range: fieldValue.buffer.size, | 505 range: fieldValue.buffer.size, |
| 515 ) | 506 ) |
| 516 descriptorSetWrites[i] = VkWriteDescriptorSet( | 507 descriptorSetWrites.add VkWriteDescriptorSet( |
| 517 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | 508 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, |
| 518 dstSet: descriptorSet.vk[i], | 509 dstSet: descriptorSet.vk[i], |
| 519 dstBinding: descriptorBindingNumber, | 510 dstBinding: descriptorBindingNumber, |
| 520 dstArrayElement: uint32(0), | 511 dstArrayElement: 0, |
| 521 descriptorType: descriptorType, | 512 descriptorType: descriptorType, |
| 522 descriptorCount: descriptorCount, | 513 descriptorCount: descriptorCount, |
| 523 pImageInfo: nil, | 514 pImageInfo: nil, |
| 524 pBufferInfo: addr(bufferInfo), | 515 pBufferInfo: addr(bufferWrites[^1]), |
| 525 ) | 516 ) |
| 526 elif typeof(fieldValue) is Texture: | 517 elif typeof(fieldValue) is Texture: |
| 527 let imageInfo = VkDescriptorImageInfo( | 518 imageWrites.add VkDescriptorImageInfo( |
| 528 sampler: fieldValue.sampler, | 519 sampler: fieldValue.sampler, |
| 529 imageView: fieldValue.imageView, | 520 imageView: fieldValue.imageView, |
| 530 imageLayout: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, | 521 imageLayout: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, |
| 531 ) | 522 ) |
| 532 descriptorSetWrites[i] = VkWriteDescriptorSet( | 523 descriptorSetWrites.add VkWriteDescriptorSet( |
| 533 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | 524 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, |
| 534 dstSet: descriptorSet.vk[i], | 525 dstSet: descriptorSet.vk[i], |
| 535 dstBinding: descriptorBindingNumber, | 526 dstBinding: descriptorBindingNumber, |
| 536 dstArrayElement: uint32(0), | 527 dstArrayElement: 0, |
| 537 descriptorType: descriptorType, | 528 descriptorType: descriptorType, |
| 538 descriptorCount: descriptorCount, | 529 descriptorCount: descriptorCount, |
| 539 pImageInfo: addr(imageInfo), | 530 pImageInfo: addr(imageWrites[^1]), |
| 540 pBufferInfo: nil, | 531 pBufferInfo: nil, |
| 541 ) | 532 ) |
| 533 elif typeof(fieldValue) is array: | |
| 534 discard | |
| 535 when elementType(fieldValue) is Texture: | |
| 536 echo "Add texture array descriptor set write for set " & $i & " " & fieldName | |
| 537 for textureIndex in 0 ..< descriptorCount: | |
| 538 imageWrites.add VkDescriptorImageInfo( | |
| 539 sampler: fieldValue[textureIndex].sampler, | |
| 540 imageView: fieldValue[textureIndex].imageView, | |
| 541 imageLayout: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, | |
| 542 ) | |
| 543 descriptorSetWrites.add VkWriteDescriptorSet( | |
| 544 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | |
| 545 dstSet: descriptorSet.vk[i], | |
| 546 dstBinding: descriptorBindingNumber, | |
| 547 dstArrayElement: 0, | |
| 548 descriptorType: descriptorType, | |
| 549 descriptorCount: descriptorCount, | |
| 550 pImageInfo: addr(imageWrites[^fieldValue.len]), | |
| 551 pBufferInfo: nil, | |
| 552 ) | |
| 553 else: | |
| 554 {.error: "Unsupported descriptor type: " & tt.name(typeof(fieldValue)).} | |
| 542 else: | 555 else: |
| 543 {.error: "Unsupported descriptor type: " & tt.name(typeof(fieldValue)).} | 556 {.error: "Unsupported descriptor type: " & tt.name(typeof(fieldValue)).} |
| 544 | 557 |
| 545 | |
| 546 vkUpdateDescriptorSets(vulkan.device, descriptorSetWrites.len.uint32, descriptorSetWrites.ToCPointer, 0, nil) | 558 vkUpdateDescriptorSets(vulkan.device, descriptorSetWrites.len.uint32, descriptorSetWrites.ToCPointer, 0, nil) |
| 547 | |
| 548 #[ | |
| 549 proc WriteDescriptors[TShader, TUniforms, TGlobals](renderData: RenderData, uniforms: TUniforms, globals: TGlobals) = | |
| 550 var descriptorSetWrites: seq[VkWriteDescriptorSet] | |
| 551 ForDescriptorFields(default(TShader), fieldName, descriptorType, descriptorCount, descriptorBindingNumber): | |
| 552 for frameInFlight in 0 ..< renderData.descriptorSets.len: | |
| 553 when descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: | |
| 554 when HasGPUValueField[TUniforms](fieldName): | |
| 555 WithGPUValueField(uniforms, fieldName, gpuValue): | |
| 556 let bufferInfo = VkDescriptorBufferInfo( | |
| 557 buffer: gpuValue.buffer.vk, | |
| 558 offset: gpuValue.buffer.offset, | |
| 559 range: gpuValue.buffer.size, | |
| 560 ) | |
| 561 descriptorSetWrites.add VkWriteDescriptorSet( | |
| 562 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | |
| 563 dstSet: renderData.descriptorSets[frameInFlight], | |
| 564 dstBinding: descriptorBindingNumber, | |
| 565 dstArrayElement: uint32(0), | |
| 566 descriptorType: descriptorType, | |
| 567 descriptorCount: descriptorCount, | |
| 568 pImageInfo: nil, | |
| 569 pBufferInfo: addr(bufferInfo), | |
| 570 ) | |
| 571 elif HasGPUValueField[TGlobals](fieldName): | |
| 572 WithGPUValueField(globals, fieldName, theValue): | |
| 573 let bufferInfo = VkDescriptorBufferInfo( | |
| 574 buffer: theValue.buffer.vk, | |
| 575 offset: theValue.buffer.offset, | |
| 576 range: theValue.buffer.size, | |
| 577 ) | |
| 578 descriptorSetWrites.add VkWriteDescriptorSet( | |
| 579 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | |
| 580 dstSet: renderData.descriptorSets[frameInFlight], | |
| 581 dstBinding: descriptorBindingNumber, | |
| 582 dstArrayElement: uint32(0), | |
| 583 descriptorType: descriptorType, | |
| 584 descriptorCount: descriptorCount, | |
| 585 pImageInfo: nil, | |
| 586 pBufferInfo: addr(bufferInfo), | |
| 587 ) | |
| 588 else: | |
| 589 {.error: "Unable to find field '" & fieldName & "' in uniforms or globals".} | |
| 590 elif descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: | |
| 591 # TODO | |
| 592 let imageInfo = VkDescriptorImageInfo( | |
| 593 sampler: VkSampler(0), | |
| 594 imageView: VkImageView(0), | |
| 595 imageLayout: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, | |
| 596 ) | |
| 597 descriptorSetWrites.add VkWriteDescriptorSet( | |
| 598 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | |
| 599 dstSet: renderData.descriptorSets[frameInFlight], | |
| 600 dstBinding: descriptorBindingNumber, | |
| 601 dstArrayElement: 0'u32, | |
| 602 descriptorType: descriptorType, | |
| 603 descriptorCount: descriptorCount, | |
| 604 pImageInfo: addr(imageInfo), | |
| 605 pBufferInfo: nil, | |
| 606 ) | |
| 607 else: | |
| 608 assert false, "Unsupported descriptor type" | |
| 609 vkUpdateDescriptorSets(vulkan.device, uint32(descriptorSetWrites.len), descriptorSetWrites.ToCPointer, 0, nil) | |
| 610 ]# | |
| 611 | |
| 612 | 559 |
| 613 converter toVkIndexType(indexType: IndexType): VkIndexType = | 560 converter toVkIndexType(indexType: IndexType): VkIndexType = |
| 614 case indexType: | 561 case indexType: |
| 615 of None: VK_INDEX_TYPE_NONE_KHR | 562 of None: VK_INDEX_TYPE_NONE_KHR |
| 616 of UInt8: VK_INDEX_TYPE_UINT8_EXT | 563 of UInt8: VK_INDEX_TYPE_UINT8_EXT |
| 1021 if size > biggestHeap: | 968 if size > biggestHeap: |
| 1022 biggestHeap = size | 969 biggestHeap = size |
| 1023 memoryTypeIndex = i | 970 memoryTypeIndex = i |
| 1024 | 971 |
| 1025 assert memoryTypeIndex != high(uint32), "Unable to find indirect memory type" | 972 assert memoryTypeIndex != high(uint32), "Unable to find indirect memory type" |
| 1026 var allocationInfo = VkMemoryAllocateInfo( | 973 result.vk = svkAllocateMemory(result.size, memoryTypeIndex) |
| 1027 sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, | |
| 1028 allocationSize: result.size, | |
| 1029 memoryTypeIndex: memoryTypeIndex, | |
| 1030 ) | |
| 1031 checkVkResult vkAllocateMemory( | |
| 1032 vulkan.device, | |
| 1033 addr allocationInfo, | |
| 1034 nil, | |
| 1035 addr result.vk | |
| 1036 ) | |
| 1037 | 974 |
| 1038 proc AllocateDirectMemory(size: uint64): DirectGPUMemory = | 975 proc AllocateDirectMemory(size: uint64): DirectGPUMemory = |
| 1039 result.size = size | 976 result.size = size |
| 1040 result.needsFlush = true | 977 result.needsFlush = true |
| 1041 | 978 |
| 1054 biggestHeap = size | 991 biggestHeap = size |
| 1055 memoryTypeIndex = i | 992 memoryTypeIndex = i |
| 1056 result.needsFlush = not (VK_MEMORY_PROPERTY_HOST_COHERENT_BIT in flags) | 993 result.needsFlush = not (VK_MEMORY_PROPERTY_HOST_COHERENT_BIT in flags) |
| 1057 | 994 |
| 1058 assert memoryTypeIndex != high(uint32), "Unable to find indirect memory type" | 995 assert memoryTypeIndex != high(uint32), "Unable to find indirect memory type" |
| 1059 var allocationInfo = VkMemoryAllocateInfo( | 996 result.vk = svkAllocateMemory(result.size, GetDirectMemoryTypeIndex()) |
| 1060 sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, | |
| 1061 allocationSize: result.size, | |
| 1062 memoryTypeIndex: GetDirectMemoryTypeIndex(), | |
| 1063 ) | |
| 1064 checkVkResult vkAllocateMemory( | |
| 1065 vulkan.device, | |
| 1066 addr allocationInfo, | |
| 1067 nil, | |
| 1068 addr result.vk | |
| 1069 ) | |
| 1070 checkVkResult vkMapMemory( | 997 checkVkResult vkMapMemory( |
| 1071 device = vulkan.device, | 998 device = vulkan.device, |
| 1072 memory = result.vk, | 999 memory = result.vk, |
| 1073 offset = 0'u64, | 1000 offset = 0'u64, |
| 1074 size = result.size, | 1001 size = result.size, |
| 1086 of IndexBuffer: [VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | 1013 of IndexBuffer: [VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] |
| 1087 of UniformBuffer: [VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | 1014 of UniformBuffer: [VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] |
| 1088 | 1015 |
| 1089 # iterate through memory areas to find big enough free space | 1016 # iterate through memory areas to find big enough free space |
| 1090 # TODO: dynamically expand memory allocations | 1017 # TODO: dynamically expand memory allocations |
| 1018 # TODO: use RequiredMemorySize() | |
| 1091 for (memory, usedOffset) in renderData.indirectMemory.mitems: | 1019 for (memory, usedOffset) in renderData.indirectMemory.mitems: |
| 1092 if memory.size - usedOffset >= size: | 1020 if memory.size - usedOffset >= size: |
| 1093 buffer.offset = usedOffset | 1021 buffer.offset = usedOffset |
| 1094 # create buffer | 1022 # create buffer |
| 1095 var createInfo = VkBufferCreateInfo( | 1023 buffer.vk = svkCreateBuffer(buffer.size, usageFlags) |
| 1096 sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | |
| 1097 flags: VkBufferCreateFlags(0), | |
| 1098 size: buffer.size, | |
| 1099 usage: toBits(usageFlags), | |
| 1100 sharingMode: VK_SHARING_MODE_EXCLUSIVE, | |
| 1101 ) | |
| 1102 checkVkResult vkCreateBuffer( | |
| 1103 device = vulkan.device, | |
| 1104 pCreateInfo = addr createInfo, | |
| 1105 pAllocator = nil, | |
| 1106 pBuffer = addr(buffer.vk) | |
| 1107 ) | |
| 1108 checkVkResult vkBindBufferMemory(vulkan.device, buffer.vk, memory.vk, buffer.offset) | 1024 checkVkResult vkBindBufferMemory(vulkan.device, buffer.vk, memory.vk, buffer.offset) |
| 1109 renderData.indirectBuffers.add (buffer, btype, 0'u64) | 1025 renderData.indirectBuffers.add (buffer, btype, 0'u64) |
| 1110 # update memory area offset | 1026 # update memory area offset |
| 1111 usedOffset = alignedTo(usedOffset + size, MEMORY_ALIGNMENT) | 1027 usedOffset = alignedTo(usedOffset + size, MEMORY_ALIGNMENT) |
| 1112 return | 1028 return |
| 1124 of IndexBuffer: [VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | 1040 of IndexBuffer: [VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] |
| 1125 of UniformBuffer: [VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] | 1041 of UniformBuffer: [VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] |
| 1126 | 1042 |
| 1127 # iterate through memory areas to find big enough free space | 1043 # iterate through memory areas to find big enough free space |
| 1128 # TODO: dynamically expand memory allocations | 1044 # TODO: dynamically expand memory allocations |
| 1045 # TODO: use RequiredMemorySize() | |
| 1129 for (memory, usedOffset) in renderData.directMemory.mitems: | 1046 for (memory, usedOffset) in renderData.directMemory.mitems: |
| 1130 if memory.size - usedOffset >= size: | 1047 if memory.size - usedOffset >= size: |
| 1131 buffer.offset = usedOffset | 1048 buffer.offset = usedOffset |
| 1132 # create buffer | 1049 buffer.vk = svkCreateBuffer(buffer.size, usageFlags) |
| 1133 var createInfo = VkBufferCreateInfo( | |
| 1134 sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | |
| 1135 flags: VkBufferCreateFlags(0), | |
| 1136 size: buffer.size, | |
| 1137 usage: toBits(usageFlags), | |
| 1138 sharingMode: VK_SHARING_MODE_EXCLUSIVE, | |
| 1139 ) | |
| 1140 checkVkResult vkCreateBuffer( | |
| 1141 device = vulkan.device, | |
| 1142 pCreateInfo = addr createInfo, | |
| 1143 pAllocator = nil, | |
| 1144 pBuffer = addr(buffer.vk) | |
| 1145 ) | |
| 1146 checkVkResult vkBindBufferMemory(vulkan.device, buffer.vk, memory.vk, buffer.offset) | 1050 checkVkResult vkBindBufferMemory(vulkan.device, buffer.vk, memory.vk, buffer.offset) |
| 1147 renderData.directBuffers.add (buffer, btype, 0'u64) | 1051 renderData.directBuffers.add (buffer, btype, 0'u64) |
| 1148 # update memory area offset | 1052 # update memory area offset |
| 1149 usedOffset = alignedTo(usedOffset + size, MEMORY_ALIGNMENT) | 1053 usedOffset = alignedTo(usedOffset + size, MEMORY_ALIGNMENT) |
| 1150 return | 1054 return |
| 1252 break | 1156 break |
| 1253 assert foundBuffer, &"Unable to find large enough '{btype}' for '{data}'" | 1157 assert foundBuffer, &"Unable to find large enough '{btype}' for '{data}'" |
| 1254 proc AssignDirectBuffers(renderdata: var RenderData, btype: BufferType, data: var DescriptorSet) = | 1158 proc AssignDirectBuffers(renderdata: var RenderData, btype: BufferType, data: var DescriptorSet) = |
| 1255 AssignDirectBuffers(renderdata, btype, data.data) | 1159 AssignDirectBuffers(renderdata, btype, data.data) |
| 1256 | 1160 |
| 1161 proc TransitionImageLayout(image: VkImage, oldLayout, newLayout: VkImageLayout) = | |
| 1162 var | |
| 1163 barrier = VkImageMemoryBarrier( | |
| 1164 sType: VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | |
| 1165 oldLayout: oldLayout, | |
| 1166 newLayout: newLayout, | |
| 1167 srcQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED, | |
| 1168 dstQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED, | |
| 1169 image: image, | |
| 1170 subresourceRange: VkImageSubresourceRange( | |
| 1171 aspectMask: toBits [VK_IMAGE_ASPECT_COLOR_BIT], | |
| 1172 baseMipLevel: 0, | |
| 1173 levelCount: 1, | |
| 1174 baseArrayLayer: 0, | |
| 1175 layerCount: 1, | |
| 1176 ), | |
| 1177 ) | |
| 1178 srcStage: VkPipelineStageFlagBits | |
| 1179 dstStage: VkPipelineStageFlagBits | |
| 1180 | |
| 1181 if oldLayout == VK_IMAGE_LAYOUT_UNDEFINED and newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: | |
| 1182 srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | |
| 1183 barrier.srcAccessMask = VkAccessFlags(0) | |
| 1184 dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT | |
| 1185 barrier.dstAccessMask = [VK_ACCESS_TRANSFER_WRITE_BIT].toBits | |
| 1186 elif oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL and newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: | |
| 1187 srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT | |
| 1188 barrier.srcAccessMask = [VK_ACCESS_TRANSFER_WRITE_BIT].toBits | |
| 1189 dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | |
| 1190 barrier.dstAccessMask = [VK_ACCESS_SHADER_READ_BIT].toBits | |
| 1191 else: | |
| 1192 raise newException(Exception, "Unsupported layout transition!") | |
| 1193 | |
| 1194 WithSingleUseCommandBuffer(commandBuffer): | |
| 1195 vkCmdPipelineBarrier( | |
| 1196 commandBuffer, | |
| 1197 srcStageMask = [srcStage].toBits, | |
| 1198 dstStageMask = [dstStage].toBits, | |
| 1199 dependencyFlags = VkDependencyFlags(0), | |
| 1200 memoryBarrierCount = 0, | |
| 1201 pMemoryBarriers = nil, | |
| 1202 bufferMemoryBarrierCount = 0, | |
| 1203 pBufferMemoryBarriers = nil, | |
| 1204 imageMemoryBarrierCount = 1, | |
| 1205 pImageMemoryBarriers = addr(barrier), | |
| 1206 ) | |
| 1207 | |
| 1208 proc createImageView(image: VkImage, format: VkFormat): VkImageView = | |
| 1209 var createInfo = VkImageViewCreateInfo( | |
| 1210 sType: VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | |
| 1211 image: image, | |
| 1212 viewType: VK_IMAGE_VIEW_TYPE_2D, | |
| 1213 format: format, | |
| 1214 components: VkComponentMapping( | |
| 1215 r: VK_COMPONENT_SWIZZLE_IDENTITY, | |
| 1216 g: VK_COMPONENT_SWIZZLE_IDENTITY, | |
| 1217 b: VK_COMPONENT_SWIZZLE_IDENTITY, | |
| 1218 a: VK_COMPONENT_SWIZZLE_IDENTITY, | |
| 1219 ), | |
| 1220 subresourceRange: VkImageSubresourceRange( | |
| 1221 aspectMask: VkImageAspectFlags(VK_IMAGE_ASPECT_COLOR_BIT), | |
| 1222 baseMipLevel: 0, | |
| 1223 levelCount: 1, | |
| 1224 baseArrayLayer: 0, | |
| 1225 layerCount: 1, | |
| 1226 ), | |
| 1227 ) | |
| 1228 checkVkResult vkCreateImageView(vulkan.device, addr(createInfo), nil, addr(result)) | |
| 1229 | |
| 1230 proc createSampler( | |
| 1231 magFilter = VK_FILTER_LINEAR, | |
| 1232 minFilter = VK_FILTER_LINEAR, | |
| 1233 addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT, | |
| 1234 addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT, | |
| 1235 ): VkSampler = | |
| 1236 | |
| 1237 let samplerInfo = VkSamplerCreateInfo( | |
| 1238 sType: VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, | |
| 1239 magFilter: magFilter, | |
| 1240 minFilter: minFilter, | |
| 1241 addressModeU: addressModeU, | |
| 1242 addressModeV: addressModeV, | |
| 1243 addressModeW: VK_SAMPLER_ADDRESS_MODE_REPEAT, | |
| 1244 anisotropyEnable: vulkan.anisotropy > 0, | |
| 1245 maxAnisotropy: vulkan.anisotropy, | |
| 1246 borderColor: VK_BORDER_COLOR_INT_OPAQUE_BLACK, | |
| 1247 unnormalizedCoordinates: VK_FALSE, | |
| 1248 compareEnable: VK_FALSE, | |
| 1249 compareOp: VK_COMPARE_OP_ALWAYS, | |
| 1250 mipmapMode: VK_SAMPLER_MIPMAP_MODE_LINEAR, | |
| 1251 mipLodBias: 0, | |
| 1252 minLod: 0, | |
| 1253 maxLod: 0, | |
| 1254 ) | |
| 1255 checkVkResult vkCreateSampler(vulkan.device, addr(samplerInfo), nil, addr(result)) | |
| 1256 | |
| 1257 proc createTextureImage(renderData: var RenderData, texture: var Texture) = | |
| 1258 assert texture.vk == VkImage(0) | |
| 1259 assert texture.offset == 0 | |
| 1260 const usage = [VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_USAGE_SAMPLED_BIT] | |
| 1261 | |
| 1262 texture.format = GetVkFormat(texture.depth, usage = usage) | |
| 1263 texture.vk = svkCreate2DImage(texture.width, texture.height, texture.format, usage) | |
| 1264 let size = texture.vk.RequiredMemorySize() | |
| 1265 | |
| 1266 when genericParams(typeof(texture)).get(1) is IndirectGPUMemory: | |
| 1267 for (memory, usedOffset) in renderData.indirectMemory.mitems: | |
| 1268 if memory.size - usedOffset >= size: | |
| 1269 texture.memory = memory | |
| 1270 texture.offset = usedOffset | |
| 1271 # update memory area offset | |
| 1272 usedOffset = alignedTo(usedOffset + size, MEMORY_ALIGNMENT) | |
| 1273 break | |
| 1274 elif genericParams(typeof(texture)).get(1) is DirectGPUMemory: | |
| 1275 for (memory, usedOffset) in renderData.directMemory.mitems: | |
| 1276 if memory.size - usedOffset >= size: | |
| 1277 texture.memory = memory | |
| 1278 texture.offset = usedOffset | |
| 1279 # update memory area offset | |
| 1280 usedOffset = alignedTo(usedOffset + size, MEMORY_ALIGNMENT) | |
| 1281 break | |
| 1282 | |
| 1283 checkVkResult vkBindImageMemory( | |
| 1284 vulkan.device, | |
| 1285 texture.vk, | |
| 1286 texture.memory.vk, | |
| 1287 texture.offset, | |
| 1288 ) | |
| 1289 | |
| 1290 # data transfer and layout transition | |
| 1291 TransitionImageLayout(texture.vk, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) | |
| 1292 WithStagingBuffer((texture.vk, texture.imageview, texture.width, texture.height), size, GetDirectMemoryTypeIndex(), stagingPtr): | |
| 1293 copyMem(stagingPtr, texture.data.ToCPointer, size) | |
| 1294 TransitionImageLayout(texture.vk, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) | |
| 1295 | |
| 1296 texture.imageview = createImageView(texture.vk, texture.format) | |
| 1297 texture.sampler = createSampler() | |
| 1298 | |
| 1299 proc UploadTextures(renderdata: var RenderData, descriptorSet: var DescriptorSet) = | |
| 1300 for name, value in fieldPairs(descriptorSet.data): | |
| 1301 when typeof(value) is Texture: | |
| 1302 renderdata.createTextureImage(value) | |
| 1303 | |
| 1257 proc HasGPUValueField[T](name: static string): bool {.compileTime.} = | 1304 proc HasGPUValueField[T](name: static string): bool {.compileTime.} = |
| 1258 for fieldname, value in default(T).fieldPairs(): | 1305 for fieldname, value in default(T).fieldPairs(): |
| 1259 when typeof(value) is GPUValue and fieldname == name: return true | 1306 when typeof(value) is GPUValue and fieldname == name: return true |
| 1260 return false | 1307 return false |
| 1261 | 1308 |
| 1378 objPosition: GPUArray[Vec3f, IndirectGPUMemory] | 1425 objPosition: GPUArray[Vec3f, IndirectGPUMemory] |
| 1379 MaterialA = object | 1426 MaterialA = object |
| 1380 reflection: float32 | 1427 reflection: float32 |
| 1381 baseColor: Vec3f | 1428 baseColor: Vec3f |
| 1382 UniformsA = object | 1429 UniformsA = object |
| 1383 defaultTexture: Texture[3, IndirectGPUMemory] | 1430 defaultTexture: Texture[TVec3[uint8], IndirectGPUMemory] |
| 1384 defaultMaterial: GPUValue[MaterialA, IndirectGPUMemory] | 1431 defaultMaterial: GPUValue[MaterialA, IndirectGPUMemory] |
| 1385 materials: GPUValue[array[3, MaterialA], IndirectGPUMemory] | 1432 materials: GPUValue[array[3, MaterialA], IndirectGPUMemory] |
| 1386 materialTextures: array[3, Texture[3, IndirectGPUMemory]] | 1433 materialTextures: array[3, Texture[TVec3[uint8], IndirectGPUMemory]] |
| 1387 ShaderSettings = object | 1434 ShaderSettings = object |
| 1388 gamma: float32 | 1435 gamma: float32 |
| 1389 GlobalsA = object | 1436 GlobalsA = object |
| 1390 fontAtlas: Texture[1, IndirectGPUMemory] | 1437 fontAtlas: Texture[TVec3[uint8], IndirectGPUMemory] |
| 1391 settings: GPUValue[ShaderSettings, IndirectGPUMemory] | 1438 settings: GPUValue[ShaderSettings, IndirectGPUMemory] |
| 1392 | 1439 |
| 1393 ShaderA = object | 1440 ShaderA = object |
| 1394 # vertex input | 1441 # vertex input |
| 1395 position {.VertexAttribute.}: Vec3f | 1442 position {.VertexAttribute.}: Vec3f |
| 1445 MaterialA(reflection: 0, baseColor: NewVec3f(1, 0, 0)), | 1492 MaterialA(reflection: 0, baseColor: NewVec3f(1, 0, 0)), |
| 1446 MaterialA(reflection: 0.1, baseColor: NewVec3f(0, 1, 0)), | 1493 MaterialA(reflection: 0.1, baseColor: NewVec3f(0, 1, 0)), |
| 1447 MaterialA(reflection: 0.5, baseColor: NewVec3f(0, 0, 1)), | 1494 MaterialA(reflection: 0.5, baseColor: NewVec3f(0, 0, 1)), |
| 1448 ]), | 1495 ]), |
| 1449 materialTextures: [ | 1496 materialTextures: [ |
| 1450 Texture[3, IndirectGPUMemory](), | 1497 Texture[TVec3[uint8], IndirectGPUMemory](), |
| 1451 Texture[3, IndirectGPUMemory](), | 1498 Texture[TVec3[uint8], IndirectGPUMemory](), |
| 1452 Texture[3, IndirectGPUMemory](), | 1499 Texture[TVec3[uint8], IndirectGPUMemory](), |
| 1453 ] | 1500 ] |
| 1454 ) | 1501 ) |
| 1455 ) | 1502 ) |
| 1456 var instances1 = InstanceA( | 1503 var instances1 = InstanceA( |
| 1457 rotation: GPUArray[Vec4f, IndirectGPUMemory](data: @[NewVec4f(1, 0, 0, 0.1), NewVec4f(0, 1, 0, 0.1)]), | 1504 rotation: GPUArray[Vec4f, IndirectGPUMemory](data: @[NewVec4f(1, 0, 0, 0.1), NewVec4f(0, 1, 0, 0.1)]), |
| 1467 let shaderObject = CompileShader(shader) | 1514 let shaderObject = CompileShader(shader) |
| 1468 var pipeline1 = CreatePipeline(renderPass = renderpass, shader = shaderObject) | 1515 var pipeline1 = CreatePipeline(renderPass = renderpass, shader = shaderObject) |
| 1469 | 1516 |
| 1470 var renderdata = InitRenderData() | 1517 var renderdata = InitRenderData() |
| 1471 | 1518 |
| 1472 # TODO: Textures | |
| 1473 # upload all textures | |
| 1474 # write descriptors for textures and uniform buffers | |
| 1475 | |
| 1476 # buffer allocation | 1519 # buffer allocation |
| 1477 var | |
| 1478 indirectVertexSizes = 0'u64 | |
| 1479 directVertexSizes = 0'u64 | |
| 1480 indirectIndexSizes = 0'u64 | |
| 1481 directIndexSizes = 0'u64 | |
| 1482 indirectUniformSizes = 0'u64 | |
| 1483 directUniformSizes = 0'u64 | |
| 1484 | |
| 1485 # buffer allocation | |
| 1486 | |
| 1487 echo "Allocating GPU buffers" | 1520 echo "Allocating GPU buffers" |
| 1521 | |
| 1522 var indirectVertexSizes = 0'u64 | |
| 1488 indirectVertexSizes += GetIndirectBufferSizes(myMesh1) | 1523 indirectVertexSizes += GetIndirectBufferSizes(myMesh1) |
| 1489 indirectVertexSizes += GetIndirectBufferSizes(instances1) | 1524 indirectVertexSizes += GetIndirectBufferSizes(instances1) |
| 1490 AllocateIndirectBuffer(renderdata, indirectVertexSizes, VertexBuffer) | 1525 AllocateIndirectBuffer(renderdata, indirectVertexSizes, VertexBuffer) |
| 1491 | 1526 |
| 1527 var directVertexSizes = 0'u64 | |
| 1492 directVertexSizes += GetDirectBufferSizes(myMesh1) | 1528 directVertexSizes += GetDirectBufferSizes(myMesh1) |
| 1493 directVertexSizes += GetDirectBufferSizes(instances1) | 1529 directVertexSizes += GetDirectBufferSizes(instances1) |
| 1494 AllocateDirectBuffer(renderdata, directVertexSizes, VertexBuffer) | 1530 AllocateDirectBuffer(renderdata, directVertexSizes, VertexBuffer) |
| 1495 | 1531 |
| 1532 var indirectIndexSizes = 0'u64 | |
| 1496 indirectIndexSizes += GetIndirectIndexBufferSizes(myMesh1) | 1533 indirectIndexSizes += GetIndirectIndexBufferSizes(myMesh1) |
| 1497 AllocateIndirectBuffer(renderdata, indirectIndexSizes, IndexBuffer) | 1534 AllocateIndirectBuffer(renderdata, indirectIndexSizes, IndexBuffer) |
| 1498 | 1535 |
| 1536 var directIndexSizes = 0'u64 | |
| 1499 directIndexSizes += GetDirectIndexBufferSizes(myMesh1) | 1537 directIndexSizes += GetDirectIndexBufferSizes(myMesh1) |
| 1500 AllocateDirectBuffer(renderdata, directIndexSizes, IndexBuffer) | 1538 AllocateDirectBuffer(renderdata, directIndexSizes, IndexBuffer) |
| 1501 | 1539 |
| 1540 var indirectUniformSizes = 0'u64 | |
| 1502 indirectUniformSizes += GetIndirectBufferSizes(uniforms1) | 1541 indirectUniformSizes += GetIndirectBufferSizes(uniforms1) |
| 1503 indirectUniformSizes += GetIndirectBufferSizes(myGlobals) | 1542 indirectUniformSizes += GetIndirectBufferSizes(myGlobals) |
| 1504 AllocateIndirectBuffer(renderdata, indirectUniformSizes, UniformBuffer) | 1543 AllocateIndirectBuffer(renderdata, indirectUniformSizes, UniformBuffer) |
| 1505 | 1544 |
| 1545 var directUniformSizes = 0'u64 | |
| 1506 directUniformSizes += GetDirectBufferSizes(uniforms1) | 1546 directUniformSizes += GetDirectBufferSizes(uniforms1) |
| 1507 directUniformSizes += GetDirectBufferSizes(myGlobals) | 1547 directUniformSizes += GetDirectBufferSizes(myGlobals) |
| 1508 AllocateDirectBuffer(renderdata, directUniformSizes, UniformBuffer) | 1548 AllocateDirectBuffer(renderdata, directUniformSizes, UniformBuffer) |
| 1509 | 1549 |
| 1550 | |
| 1510 # buffer assignment | 1551 # buffer assignment |
| 1511 # | |
| 1512 echo "Assigning buffers to GPUData fields" | 1552 echo "Assigning buffers to GPUData fields" |
| 1513 | 1553 |
| 1514 # for meshes we do: | 1554 # for meshes we do: |
| 1515 renderdata.AssignIndirectBuffers(VertexBuffer, myMesh1) | 1555 renderdata.AssignIndirectBuffers(VertexBuffer, myMesh1) |
| 1516 renderdata.AssignDirectBuffers(VertexBuffer, myMesh1) | 1556 renderdata.AssignDirectBuffers(VertexBuffer, myMesh1) |
| 1525 renderdata.AssignIndirectBuffers(UniformBuffer, uniforms1) | 1565 renderdata.AssignIndirectBuffers(UniformBuffer, uniforms1) |
| 1526 renderdata.AssignDirectBuffers(UniformBuffer, uniforms1) | 1566 renderdata.AssignDirectBuffers(UniformBuffer, uniforms1) |
| 1527 renderdata.AssignIndirectBuffers(UniformBuffer, myGlobals) | 1567 renderdata.AssignIndirectBuffers(UniformBuffer, myGlobals) |
| 1528 renderdata.AssignDirectBuffers(UniformBuffer, myGlobals) | 1568 renderdata.AssignDirectBuffers(UniformBuffer, myGlobals) |
| 1529 | 1569 |
| 1530 # buffer filling | 1570 renderdata.UploadTextures(uniforms1) |
| 1531 | 1571 renderdata.UploadTextures(myGlobals) |
| 1572 | |
| 1573 echo uniforms1.data.materialTextures | |
| 1574 | |
| 1575 | |
| 1576 # copy everything to GPU | |
| 1532 echo "Copying all data to GPU memory" | 1577 echo "Copying all data to GPU memory" |
| 1533 | |
| 1534 # copy everything to GPU | |
| 1535 UpdateAllGPUBuffers(myMesh1) | 1578 UpdateAllGPUBuffers(myMesh1) |
| 1536 UpdateAllGPUBuffers(instances1) | 1579 UpdateAllGPUBuffers(instances1) |
| 1537 UpdateAllGPUBuffers(uniforms1) | 1580 UpdateAllGPUBuffers(uniforms1) |
| 1538 UpdateAllGPUBuffers(myGlobals) | 1581 UpdateAllGPUBuffers(myGlobals) |
| 1539 renderdata.FlushDirectMemory() | 1582 renderdata.FlushDirectMemory() |
| 1540 | 1583 |
| 1541 | 1584 |
| 1542 # descriptors | 1585 # descriptors |
| 1543 # TODO: I think we can write and assign descriptors directly after creation | 1586 echo "Writing descriptors" |
| 1544 InitDescriptorSet(renderdata, pipeline1.descriptorSetLayouts[GlobalSet], myGlobals) | 1587 InitDescriptorSet(renderdata, pipeline1.descriptorSetLayouts[GlobalSet], myGlobals) |
| 1545 InitDescriptorSet(renderdata, pipeline1.descriptorSetLayouts[MaterialSet], uniforms1) | 1588 InitDescriptorSet(renderdata, pipeline1.descriptorSetLayouts[MaterialSet], uniforms1) |
| 1546 # WriteDescriptors[ShaderA, UniformsA, GlobalsA](renderdata, uniforms1, myGlobals) | |
| 1547 | 1589 |
| 1548 | 1590 |
| 1549 # command buffer | 1591 # command buffer |
| 1550 var | 1592 var |
| 1551 commandBufferPool: VkCommandPool | 1593 commandBufferPool: VkCommandPool |
