Mercurial > games > semicongine
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, |