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() |