comparison semiconginev2/rendering/renderer.nim @ 1239:69489a678141

add: better syncing, better swapchain access, correct font offset, two font-rendering tests
author sam <sam@basx.dev>
date Mon, 22 Jul 2024 00:46:10 +0700
parents 176383220123
children 42eeb59f3a43
comparison
equal deleted inserted replaced
1238:03634915bbdb 1239:69489a678141
2 cast[pointer](cast[T](p) + offset) 2 cast[pointer](cast[T](p) + offset)
3 3
4 func usage(bType: BufferType): seq[VkBufferUsageFlagBits] = 4 func usage(bType: BufferType): seq[VkBufferUsageFlagBits] =
5 case bType: 5 case bType:
6 of VertexBuffer: @[VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] 6 of VertexBuffer: @[VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT]
7 of VertexBufferMapped: @[VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] 7 of VertexBufferMapped: @[VK_BUFFER_USAGE_VERTEX_BUFFER_BIT]
8 of IndexBuffer: @[VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] 8 of IndexBuffer: @[VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT]
9 of IndexBufferMapped: @[VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] 9 of IndexBufferMapped: @[VK_BUFFER_USAGE_INDEX_BUFFER_BIT]
10 of UniformBuffer: @[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] 10 of UniformBuffer: @[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT]
11 of UniformBufferMapped: @[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] 11 of UniformBufferMapped: @[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT]
12 12
13 proc GetVkFormat(grayscale: bool, usage: openArray[VkImageUsageFlagBits]): VkFormat = 13 proc GetVkFormat(grayscale: bool, usage: openArray[VkImageUsageFlagBits]): VkFormat =
14 let formats = if grayscale: [VK_FORMAT_R8_SRGB, VK_FORMAT_R8_UNORM] 14 let formats = if grayscale: [VK_FORMAT_R8_SRGB, VK_FORMAT_R8_UNORM]
15 else: [VK_FORMAT_B8G8R8A8_SRGB, VK_FORMAT_B8G8R8A8_UNORM] 15 else: [VK_FORMAT_B8G8R8A8_SRGB, VK_FORMAT_B8G8R8A8_UNORM]
16 16
277 result.memory = selectedBlock.vk 277 result.memory = selectedBlock.vk
278 result.memoryOffset = selectedBlock.offsetNextFree 278 result.memoryOffset = selectedBlock.offsetNextFree
279 result.rawPointer = selectedBlock.rawPointer.pointerAddOffset(selectedBlock.offsetNextFree) 279 result.rawPointer = selectedBlock.rawPointer.pointerAddOffset(selectedBlock.offsetNextFree)
280 renderData.memory[memoryType][selectedBlockI].offsetNextFree += memoryRequirements.size 280 renderData.memory[memoryType][selectedBlockI].offsetNextFree += memoryRequirements.size
281 281
282 proc UpdateGPUBuffer*(gpuData: GPUData, flush = false) = 282 proc UpdateGPUBuffer*(gpuData: GPUData, flush = false, allFrames = false) =
283 if gpuData.size == 0: 283 if gpuData.size == 0:
284 return 284 return
285
285 when NeedsMapping(gpuData): 286 when NeedsMapping(gpuData):
286 copyMem(pointerAddOffset(gpuData.buffer.rawPointer, gpuData.offset), gpuData.rawPointer, gpuData.size) 287 copyMem(pointerAddOffset(gpuData.buffer.rawPointer, gpuData.offset), gpuData.rawPointer, gpuData.size)
287 if flush: 288 if flush:
288 FlushBuffer(gpuData.buffer) 289 FlushBuffer(gpuData.buffer)
289 else: 290 else:
290 WithStagingBuffer((gpuData.buffer.vk, gpuData.offset), gpuData.size, stagingPtr): 291 WithStagingBuffer((gpuData.buffer.vk, gpuData.offset), gpuData.size, stagingPtr):
291 copyMem(stagingPtr, gpuData.rawPointer, gpuData.size) 292 copyMem(stagingPtr, gpuData.rawPointer, gpuData.size)
292 293
293 proc UpdateAllGPUBuffers*[T](value: T, flush = false) = 294 proc UpdateAllGPUBuffers*[T](value: T, flush = false, allFrames = false) =
294 for name, fieldvalue in value.fieldPairs(): 295 for name, fieldvalue in value.fieldPairs():
295 when typeof(fieldvalue) is GPUData: 296 when typeof(fieldvalue) is GPUData:
296 UpdateGPUBuffer(fieldvalue, flush = flush) 297 UpdateGPUBuffer(fieldvalue, flush = flush, allFrames = allFrames)
297 when typeof(fieldvalue) is array: 298 when typeof(fieldvalue) is array:
298 when elementType(fieldvalue) is GPUData: 299 when elementType(fieldvalue) is GPUData:
299 for entry in fieldvalue: 300 for entry in fieldvalue:
300 UpdateGPUBuffer(entry, flush = flush) 301 UpdateGPUBuffer(entry, flush = flush, allFrames = allFrames)
301 302
302 proc AssignGPUData(renderdata: var RenderData, value: var GPUData) = 303 proc AllocateGPUData(
304 renderdata: var RenderData,
305 bufferType: BufferType,
306 size: uint64,
307 needsFrameInFlight = -1
308 ): (Buffer, uint64) =
309
303 # find buffer that has space 310 # find buffer that has space
304 var selectedBufferI = -1 311 var selectedBufferI = -1
305 312
306 for i in 0 ..< renderData.buffers[value.bufferType].len: 313 for i in 0 ..< renderData.buffers[bufferType].len:
307 let buffer = renderData.buffers[value.bufferType][i] 314 let buffer = renderData.buffers[bufferType][i]
308 if buffer.size - alignedTo(buffer.offsetNextFree, BUFFER_ALIGNMENT) >= value.size: 315 if needsFrameInFlight == -1 or buffer.useForFrameInFlight == needsFrameInFlight:
309 selectedBufferI = i 316 if buffer.size - alignedTo(buffer.offsetNextFree, BUFFER_ALIGNMENT) >= size:
317 selectedBufferI = i
310 318
311 # otherwise create new buffer 319 # otherwise create new buffer
312 if selectedBufferI < 0: 320 if selectedBufferI < 0:
313 selectedBufferI = renderdata.buffers[value.bufferType].len 321 selectedBufferI = renderdata.buffers[bufferType].len
314 renderdata.buffers[value.bufferType].add renderdata.AllocateNewBuffer( 322 renderdata.buffers[bufferType].add renderdata.AllocateNewBuffer(
315 size = max(value.size, BUFFER_ALLOCATION_SIZE), 323 size = max(size, BUFFER_ALLOCATION_SIZE),
316 bufferType = value.bufferType, 324 bufferType = bufferType,
317 ) 325 )
326 if needsFrameInFlight >= 0:
327 renderdata.buffers[bufferType][selectedBufferI].useForFrameInFlight = needsFrameInFlight
318 328
319 # assigne value 329 # assigne value
320 let selectedBuffer = renderdata.buffers[value.bufferType][selectedBufferI] 330 let selectedBuffer = renderdata.buffers[bufferType][selectedBufferI]
321 renderdata.buffers[value.bufferType][selectedBufferI].offsetNextFree = alignedTo( 331 renderdata.buffers[bufferType][selectedBufferI].offsetNextFree = alignedTo(
322 selectedBuffer.offsetNextFree, 332 selectedBuffer.offsetNextFree,
323 BUFFER_ALIGNMENT 333 BUFFER_ALIGNMENT
324 ) 334 )
325 value.buffer = selectedBuffer 335
326 value.offset = renderdata.buffers[value.bufferType][selectedBufferI].offsetNextFree 336 result[0] = selectedBuffer
327 renderdata.buffers[value.bufferType][selectedBufferI].offsetNextFree += value.size 337 result[1] = renderdata.buffers[bufferType][selectedBufferI].offsetNextFree
338 renderdata.buffers[bufferType][selectedBufferI].offsetNextFree += size
328 339
329 proc AssignBuffers*[T](renderdata: var RenderData, data: var T, uploadData = true) = 340 proc AssignBuffers*[T](renderdata: var RenderData, data: var T, uploadData = true) =
330 for name, value in fieldPairs(data): 341 for name, value in fieldPairs(data):
331 342
332 when typeof(value) is GPUData: 343 when typeof(value) is GPUData:
333 AssignGPUData(renderdata, value) 344 (value.buffer, value.offset) = AllocateGPUData(renderdata, value.bufferType, value.size)
334 345
335 elif typeof(value) is DescriptorSet: 346 elif typeof(value) is DescriptorSet:
336 AssignBuffers(renderdata, value.data, uploadData = uploadData) 347 AssignBuffers(renderdata, value.data, uploadData = uploadData)
337 348
338 elif typeof(value) is array: 349 elif typeof(value) is array:
339 when elementType(value) is GPUValue: 350 when elementType(value) is GPUValue:
340 for v in value.mitems: 351 for v in value.mitems:
341 AssignGPUData(renderdata, v) 352 (v.buffer, v.offset) = AllocateGPUData(renderdata, v.bufferType, v.size)
342 353
343 if uploadData: 354 if uploadData:
344 UpdateAllGPUBuffers(data) 355 UpdateAllGPUBuffers(data, flush = true, allFrames = true)
345 356
346 proc AssignBuffers*(renderdata: var RenderData, descriptorSet: var DescriptorSet, uploadData = true) = 357 proc AssignBuffers*(renderdata: var RenderData, descriptorSet: var DescriptorSet, uploadData = true) =
347 AssignBuffers(renderdata, descriptorSet.data, uploadData = uploadData) 358 AssignBuffers(renderdata, descriptorSet.data, uploadData = uploadData)
348 359
349 proc InitRenderData*(descriptorPoolLimit = 1024'u32): RenderData = 360 proc InitRenderData*(descriptorPoolLimit = 1024'u32): RenderData =
532 when fieldname == name: 543 when fieldname == name:
533 block: 544 block:
534 let `fieldvalue` {.inject.} = value 545 let `fieldvalue` {.inject.} = value
535 body 546 body
536 547
537 template WithBind*[A, B, C, D](commandBuffer: VkCommandBuffer, sets: (DescriptorSet[A], DescriptorSet[B], DescriptorSet[C], DescriptorSet[D]), pipeline: Pipeline, currentFiF: int, body: untyped): untyped = 548 template WithBind*[A, B, C, D](commandBuffer: VkCommandBuffer, sets: (DescriptorSet[A], DescriptorSet[B], DescriptorSet[C], DescriptorSet[D]), pipeline: Pipeline, body: untyped): untyped =
538 block: 549 block:
539 var descriptorSets: seq[VkDescriptorSet] 550 var descriptorSets: seq[VkDescriptorSet]
540 for dSet in sets.fields: 551 for dSet in sets.fields:
541 assert dSet.vk[currentFiF].Valid, "DescriptorSet not initialized, maybe forgot to call InitDescriptorSet" 552 assert dSet.vk[currentFiF()].Valid, "DescriptorSet not initialized, maybe forgot to call InitDescriptorSet"
542 descriptorSets.add dSet.vk[currentFiF] 553 descriptorSets.add dSet.vk[currentFiF()]
543 svkCmdBindDescriptorSets(commandBuffer, descriptorSets, pipeline.layout) 554 svkCmdBindDescriptorSets(commandBuffer, descriptorSets, pipeline.layout)
544 body 555 body
545 template WithBind*[A, B, C](commandBuffer: VkCommandBuffer, sets: (DescriptorSet[A], DescriptorSet[B], DescriptorSet[C]), pipeline: Pipeline, currentFiF: int, body: untyped): untyped = 556 template WithBind*[A, B, C](commandBuffer: VkCommandBuffer, sets: (DescriptorSet[A], DescriptorSet[B], DescriptorSet[C]), pipeline: Pipeline, body: untyped): untyped =
546 block: 557 block:
547 var descriptorSets: seq[VkDescriptorSet] 558 var descriptorSets: seq[VkDescriptorSet]
548 for dSet in sets.fields: 559 for dSet in sets.fields:
549 assert dSet.vk[currentFiF].Valid, "DescriptorSet not initialized, maybe forgot to call InitDescriptorSet" 560 assert dSet.vk[currentFiF()].Valid, "DescriptorSet not initialized, maybe forgot to call InitDescriptorSet"
550 descriptorSets.add dSet.vk[currentFiF] 561 descriptorSets.add dSet.vk[currentFiF()]
551 svkCmdBindDescriptorSets(commandBuffer, descriptorSets, pipeline.layout) 562 svkCmdBindDescriptorSets(commandBuffer, descriptorSets, pipeline.layout)
552 body 563 body
553 template WithBind*[A, B](commandBuffer: VkCommandBuffer, sets: (DescriptorSet[A], DescriptorSet[B]), pipeline: Pipeline, currentFiF: int, body: untyped): untyped = 564 template WithBind*[A, B](commandBuffer: VkCommandBuffer, sets: (DescriptorSet[A], DescriptorSet[B]), pipeline: Pipeline, body: untyped): untyped =
554 block: 565 block:
555 var descriptorSets: seq[VkDescriptorSet] 566 var descriptorSets: seq[VkDescriptorSet]
556 for dSet in sets.fields: 567 for dSet in sets.fields:
557 assert dSet.vk[currentFiF].Valid, "DescriptorSet not initialized, maybe forgot to call InitDescriptorSet" 568 assert dSet.vk[currentFiF()].Valid, "DescriptorSet not initialized, maybe forgot to call InitDescriptorSet"
558 descriptorSets.add dSet.vk[currentFiF] 569 descriptorSets.add dSet.vk[currentFiF()]
559 svkCmdBindDescriptorSets(commandBuffer, descriptorSets, pipeline.layout) 570 svkCmdBindDescriptorSets(commandBuffer, descriptorSets, pipeline.layout)
560 body 571 body
561 template WithBind*[A](commandBuffer: VkCommandBuffer, sets: (DescriptorSet[A], ), pipeline: Pipeline, currentFiF: int, body: untyped): untyped = 572 template WithBind*[A](commandBuffer: VkCommandBuffer, sets: (DescriptorSet[A], ), pipeline: Pipeline, body: untyped): untyped =
562 block: 573 block:
563 var descriptorSets: seq[VkDescriptorSet] 574 var descriptorSets: seq[VkDescriptorSet]
564 for dSet in sets.fields: 575 for dSet in sets.fields:
565 assert dSet.vk[currentFiF].Valid, "DescriptorSet not initialized, maybe forgot to call InitDescriptorSet" 576 assert dSet.vk[currentFiF()].Valid, "DescriptorSet not initialized, maybe forgot to call InitDescriptorSet"
566 descriptorSets.add dSet.vk[currentFiF] 577 descriptorSets.add dSet.vk[currentFiF()]
567 svkCmdBindDescriptorSets(commandBuffer, descriptorSets, pipeline.layout) 578 svkCmdBindDescriptorSets(commandBuffer, descriptorSets, pipeline.layout)
568 body 579 body
569 580
570 proc Render*[TShader, TMesh, TInstance]( 581 proc Render*[TShader, TMesh, TInstance](
571 commandBuffer: VkCommandBuffer, 582 commandBuffer: VkCommandBuffer,