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 |