comparison static_utils.nim @ 1179:e1830f9b8af4 compiletime-tests

sync to notebook in bedroom
author sam <sam@basx.dev>
date Mon, 01 Jul 2024 20:32:00 +0700
parents ec4ff70299f2
children d554f8185815
comparison
equal deleted inserted replaced
1178:ec4ff70299f2 1179:e1830f9b8af4
10 import semicongine/core/utils 10 import semicongine/core/utils
11 import semicongine/core/imagetypes 11 import semicongine/core/imagetypes
12 import semicongine/core/vector 12 import semicongine/core/vector
13 import semicongine/core/matrix 13 import semicongine/core/matrix
14 import semicongine/core/vulkanapi 14 import semicongine/core/vulkanapi
15 import semicongine/vulkan/buffer 15
16 16 template VertexAttribute {.pragma.}
17 template VertexAttribute* {.pragma.} 17 template InstanceAttribute {.pragma.}
18 template InstanceAttribute* {.pragma.} 18 template Pass {.pragma.}
19 template Pass* {.pragma.} 19 template PassFlat {.pragma.}
20 template PassFlat* {.pragma.} 20 template ShaderOutput {.pragma.}
21 template ShaderOutput* {.pragma.} 21 template VertexIndices{.pragma.}
22 template VertexIndices*{.pragma.}
23 22
24 const INFLIGHTFRAMES = 2'u32 23 const INFLIGHTFRAMES = 2'u32
24 const ACTIVE_DESCRIPTORSETS = 2
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 BUFFER_ALIGNMENT = 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 # some globals that will (likely?) never change during the life time of the engine
28 type 29 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] 30 VulkanGlobals = object
30 ShaderObject*[TShader] = object 31 instance: VkInstance
32 device: VkDevice
33 physicalDevice: VkPhysicalDevice
34 queueFamilyIndex: uint32
35 queue: VkQueue
36 var vulkan: VulkanGlobals
37
38 type
39 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]
40 ShaderObject[TShader] = object
31 vertexShader: VkShaderModule 41 vertexShader: VkShaderModule
32 fragmentShader: VkShaderModule 42 fragmentShader: VkShaderModule
33 43
34 func alignedTo[T: SomeInteger](value: T, alignment: T) = 44 func alignedTo[T: SomeInteger](value: T, alignment: T): T =
35 let remainder = value mod alignment 45 let remainder = value mod alignment
36 if remainder == 0: 46 if remainder == 0:
37 return value 47 return value
38 else: 48 else:
39 return value + alignment - remainder 49 return value + alignment - remainder
121 elif T is TMat4[float32]: "mat4" 131 elif T is TMat4[float32]: "mat4"
122 elif T is TMat4[float64]: "dmat4" 132 elif T is TMat4[float64]: "dmat4"
123 elif T is Texture: "sampler2D" 133 elif T is Texture: "sampler2D"
124 else: {.error: "Unsupported data type on GPU".} 134 else: {.error: "Unsupported data type on GPU".}
125 135
126 template ForVertexDataFields*(inputData: typed, fieldname, valuename, isinstancename, body: untyped): untyped = 136 template ForVertexDataFields(shader: typed, fieldname, valuename, isinstancename, body: untyped): untyped =
127 for theFieldname, value in fieldPairs(inputData): 137 for theFieldname, value in fieldPairs(shader):
128 when hasCustomPragma(value, VertexAttribute) or hasCustomPragma(value, InstanceAttribute): 138 when hasCustomPragma(value, VertexAttribute) or hasCustomPragma(value, InstanceAttribute):
129 when not typeof(value) is seq: 139 when not typeof(value) is seq:
130 {.error: "field '" & theFieldname & "' needs to be a seq".} 140 {.error: "field '" & theFieldname & "' needs to be a seq".}
131 when not typeof(value) is SupportedGPUType: 141 when not typeof(value) is SupportedGPUType:
132 {.error: "field '" & theFieldname & "' is not a supported GPU type".} 142 {.error: "field '" & theFieldname & "' is not a supported GPU type".}
133 block: 143 block:
134 let `fieldname` {.inject.} = theFieldname 144 const `fieldname` {.inject.} = theFieldname
135 let `valuename` {.inject.} = value 145 let `valuename` {.inject.} = value
136 let `isinstancename` {.inject.} = hasCustomPragma(value, InstanceAttribute) 146 const `isinstancename` {.inject.} = hasCustomPragma(value, InstanceAttribute)
137 body 147 body
138 148
139 template ForDescriptorFields*(inputData: typed, fieldname, typename, countname, bindingNumber, body: untyped): untyped = 149 template ForDescriptorFields(shader: typed, fieldname, typename, countname, bindingNumber, body: untyped): untyped =
140 var `bindingNumber` {.inject.} = 1'u32 150 var `bindingNumber` {.inject.} = 1'u32
141 for theFieldname, value in fieldPairs(inputData): 151 for theFieldname, value in fieldPairs(shader):
142 let `fieldname` {.inject.} = theFieldname 152 const `fieldname` {.inject.} = theFieldname
143 when typeof(value) is Texture: 153 when typeof(value) is Texture:
144 block: 154 block:
145 let `typename` {.inject.} = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER 155 const `typename` {.inject.} = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
146 let `countname` {.inject.} = 1'u32 156 const `countname` {.inject.} = 1'u32
147 body 157 body
148 `bindingNumber`.inc 158 `bindingNumber`.inc
149 elif typeof(value) is object: 159 elif typeof(value) is object:
150 block: 160 block:
151 let `typename` {.inject.} = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER 161 const `typename` {.inject.} = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
152 let `countname` {.inject.} = 1'u32 162 const `countname` {.inject.} = 1'u32
153 body 163 body
154 `bindingNumber`.inc 164 `bindingNumber`.inc
155 elif typeof(value) is array: 165 elif typeof(value) is array:
156 when elementType(value) is Texture: 166 when elementType(value) is Texture:
157 block: 167 block:
158 let `typename` {.inject.} = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER 168 const `typename` {.inject.} = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
159 let `countname` {.inject.} = uint32(typeof(value).len) 169 const `countname` {.inject.} = uint32(typeof(value).len)
160 body 170 body
161 `bindingNumber`.inc 171 `bindingNumber`.inc
162 elif elementType(value) is object: 172 elif elementType(value) is object:
163 block: 173 block:
164 let `typename` {.inject.} = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER 174 const `typename` {.inject.} = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
165 let `countname` {.inject.} = uint32(typeof(value).len) 175 const `countname` {.inject.} = uint32(typeof(value).len)
166 body 176 body
167 `bindingNumber`.inc 177 `bindingNumber`.inc
168 178
169 func NumberOfVertexInputAttributeDescriptors[T: SupportedGPUType|Texture](value: T): uint32 = 179 func NumberOfVertexInputAttributeDescriptors[T: SupportedGPUType|Texture](value: T): uint32 =
170 when T is TMat2[float32] or T is TMat2[float64] or T is TMat23[float32] or T is TMat23[float64]: 180 when T is TMat2[float32] or T is TMat2[float64] or T is TMat23[float32] or T is TMat23[float64]:
236 GPUData = GPUArray | GPUValue 246 GPUData = GPUArray | GPUValue
237 247
238 Pipeline[TShader] = object 248 Pipeline[TShader] = object
239 pipeline: VkPipeline 249 pipeline: VkPipeline
240 layout: VkPipelineLayout 250 layout: VkPipelineLayout
241 descriptorSetLayout: VkDescriptorSetLayout 251 descriptorSetLayouts: array[ACTIVE_DESCRIPTORSETS, VkDescriptorSetLayout]
242 BufferType = enum 252 BufferType = enum
243 VertexBuffer, IndexBuffer, UniformBuffer 253 VertexBuffer, IndexBuffer, UniformBuffer
244 RenderData = object 254 RenderData = object
245 descriptorPool: VkDescriptorPool 255 descriptorPool: VkDescriptorPool
246 # tuple is memory and offset to next free allocation in that memory 256 # tuple is memory and offset to next free allocation in that memory
247 indirectMemory: seq[tuple[memory: IndirectGPUMemory, nextFree: uint64]] 257 indirectMemory: seq[tuple[memory: IndirectGPUMemory, usedOffset: uint64]]
248 directMemory: seq[tuple[memory: DirectGPUMemory, nextFree: uint64]] 258 directMemory: seq[tuple[memory: DirectGPUMemory, usedOffset: uint64]]
249 indirectBuffers: seq[tuple[buffer: Buffer[IndirectGPUMemory], btype: BufferType, nextFree: uint64]] 259 indirectBuffers: seq[tuple[buffer: Buffer[IndirectGPUMemory], btype: BufferType, usedOffset: uint64]]
250 directBuffers: seq[tuple[buffer: Buffer[DirectGPUMemory], btype: BufferType, nextFree: uint64]] 260 directBuffers: seq[tuple[buffer: Buffer[DirectGPUMemory], btype: BufferType, usedOffset: uint64]]
251 261
252 template UsesIndirectMemory(gpuData: GPUData): untyped = 262 template UsesIndirectMemory(gpuData: GPUData): untyped =
253 get(genericParams(typeof(gpuData)), 1) is IndirectGPUMemory 263 get(genericParams(typeof(gpuData)), 1) is IndirectGPUMemory
254 template UsesDirectMemory(gpuData: GPUData): untyped = 264 template UsesDirectMemory(gpuData: GPUData): untyped =
255 get(genericParams(typeof(gpuData)), 1) is DirectGPUMemory 265 get(genericParams(typeof(gpuData)), 1) is DirectGPUMemory
256 266
257 template size(gpuArray: GPUArray): uint64 = 267 template size(gpuArray: GPUArray): uint64 =
258 result += (gpuArray.data.len * sizeof(elementType(gpuArray.data))).uint64 268 (gpuArray.data.len * sizeof(elementType(gpuArray.data))).uint64
259 template size(gpuValue: GPUValue): uint64 = 269 template size(gpuValue: GPUValue): uint64 =
260 result += sizeof(gpuValue.data).uint64 270 sizeof(gpuValue.data).uint64
261 271
262 proc GetPhysicalDevice(): VkPhysicalDevice = 272 template datapointer(gpuArray: GPUArray): pointer =
273 addr(gpuArray.data[0])
274 template datapointer(gpuValue: GPUValue): pointer =
275 addr(gpuValue.data)
276
277 proc AllocationSize(buffer: Buffer): uint64 =
278 var req: VkMemoryRequirements
279 vkGetBufferMemoryRequirements(vulkan.device, buffer.vk, addr(req))
280 return req.size
281
282 proc GetPhysicalDevice(instance: VkInstance): VkPhysicalDevice =
263 var nDevices: uint32 283 var nDevices: uint32
264 checkVkResult vkEnumeratePhysicalDevices(instance.vk, addr(nDevices), nil) 284 checkVkResult vkEnumeratePhysicalDevices(instance, addr(nDevices), nil)
265 var devices = newSeq[VkPhysicalDevice](nDevices) 285 var devices = newSeq[VkPhysicalDevice](nDevices)
266 checkVkResult vkEnumeratePhysicalDevices(instance.vk, addr(nDevices), devices.ToCPointer) 286 checkVkResult vkEnumeratePhysicalDevices(instance, addr(nDevices), devices.ToCPointer)
267 287
268 var score = 0 288 var score = 0'u32
269 for pDevice in devices: 289 for pDevice in devices:
270 var props: VkPhysicalDeviceProperties 290 var props: VkPhysicalDeviceProperties
271 vkGetPhysicalDeviceProperties(pDevice, addr(props)) 291 vkGetPhysicalDeviceProperties(pDevice, addr(props))
272 if props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU and props.maxImageDimension2D > score: 292 if props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU and props.limits.maxImageDimension2D > score:
273 score = props.maxImageDimension2D 293 score = props.limits.maxImageDimension2D
274 result = pDevice 294 result = pDevice
275 295
276 if score == 0 296 if score == 0:
277 for pDevice in devices: 297 for pDevice in devices:
278 var props: VkPhysicalDeviceProperties 298 var props: VkPhysicalDeviceProperties
279 vkGetPhysicalDeviceProperties(pDevice, addr(props)) 299 vkGetPhysicalDeviceProperties(pDevice, addr(props))
280 if props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU and props.maxImageDimension2D > score: 300 if props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU and props.limits.maxImageDimension2D > score:
281 score = props.maxImageDimension2D 301 score = props.limits.maxImageDimension2D
282 result = pDevice 302 result = pDevice
283 303
284 assert score > 0, "Unable to find integrated or discrete GPU" 304 assert score > 0, "Unable to find integrated or discrete GPU"
285 305
286 306
287 proc GetDirectMemoryTypeIndex() 307 proc GetDirectMemoryTypeIndex(): uint32 =
288 var physicalProperties: VkPhysicalDeviceMemoryProperties 308 var physicalProperties: VkPhysicalDeviceMemoryProperties
289 checkVkResult vkGetPhysicalDeviceMemoryProperties(GetPhysicalDevice(), addr physicalProperties) 309 vkGetPhysicalDeviceMemoryProperties(vulkan.physicalDevice, addr(physicalProperties))
290 310
291 var biggestHeap: uint64 = 0 311 var biggestHeap: uint64 = 0
292 result = high(uint32) 312 result = high(uint32)
293 # try to find host-visible type 313 # try to find host-visible type
294 for i in 0 ..< physicalProperties.memoryTypeCount: 314 for i in 0'u32 ..< physicalProperties.memoryTypeCount:
295 let flags = toEnums(physicalProperties.memoryTypes[i].propertyFlags) 315 let flags = toEnums(physicalProperties.memoryTypes[i].propertyFlags)
296 if VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in flags: 316 if VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in flags:
297 let size = physicalProperties.memoryHeaps[physicalProperties.memoryTypes[i].heapIndex].size 317 let size = physicalProperties.memoryHeaps[physicalProperties.memoryTypes[i].heapIndex].size
298 if size > biggestHeap: 318 if size > biggestHeap:
299 biggestHeap = size 319 biggestHeap = size
300 result = i 320 result = i
301 assert result != high(uint32), "There is not host visible memory. This is likely a driver bug." 321 assert result != high(uint32), "There is not host visible memory. This is likely a driver bug."
302 322
303 proc GetQueueFamily(device: VkDevice, qType = VK_QUEUE_GRAPHICS_BIT): VkQueue = 323 proc GetQueueFamily(pDevice: VkPhysicalDevice, qType: VkQueueFlagBits): uint32 =
304 assert device.vk.Valid
305 var nQueuefamilies: uint32 324 var nQueuefamilies: uint32
306 checkVkResult vkGetPhysicalDeviceQueueFamilyProperties(device.vk, addr nQueuefamilies, nil) 325 vkGetPhysicalDeviceQueueFamilyProperties(pDevice, addr nQueuefamilies, nil)
307 var queuFamilies = newSeq[VkQueueFamilyProperties](nQueuefamilies) 326 var queuFamilies = newSeq[VkQueueFamilyProperties](nQueuefamilies)
308 checkVkResult vkGetPhysicalDeviceQueueFamilyProperties(device.vk, addr nQueuefamilies, queuFamilies.ToCPointer) 327 vkGetPhysicalDeviceQueueFamilyProperties(pDevice, addr nQueuefamilies, queuFamilies.ToCPointer)
309 for i in 0 ..< nQueuefamilies: 328 for i in 0'u32 ..< nQueuefamilies:
310 if qType in toEnums(queuFamilies[i].queueFlags): 329 if qType in toEnums(queuFamilies[i].queueFlags):
311 return i 330 return i
312 assert false, &"Queue of type {qType} not found" 331 assert false, &"Queue of type {qType} not found"
313 332
314 proc GetQueue(device: VkDevice, qType = VK_QUEUE_GRAPHICS_BIT): VkQueue = 333 proc GetQueue(device: VkDevice, queueFamilyIndex: uint32, qType: VkQueueFlagBits): VkQueue =
315 checkVkResult vkGetDeviceQueue( 334 vkGetDeviceQueue(
316 device, 335 device,
317 GetQueueFamily(device, qType), 336 queueFamilyIndex,
318 0, 337 0,
319 addr(result), 338 addr(result),
320 ) 339 )
321 340
322 #[ 341 proc GetSurfaceFormat(): VkFormat =
323 TODO: Finish this, allow fore easy access to main format 342 # EVERY windows driver and almost every linux driver should support this
324 proc GetSurfaceFormat*(device: PhysicalDevice): VkFormat = 343 VK_FORMAT_B8G8R8A8_SRGB
325 var n_formats: uint32 344
326 checkVkResult vkGetPhysicalDeviceSurfaceFormatsKHR(device.vk, device.surface, addr(n_formats), nil) 345 template WithSingleUseCommandBuffer(device: VkDevice, cmd, body: untyped): untyped =
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: 346 block:
334 var commandBufferPool: VkCommandPool 347 var
335 createInfo = VkCommandPoolCreateInfo( 348 commandBufferPool: VkCommandPool
349 createInfo = VkCommandPoolCreateInfo(
336 sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 350 sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
337 flags: toBits [VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT], 351 flags: toBits [VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT],
338 queueFamilyIndex: GetQueueFamily(device), 352 queueFamilyIndex: vulkan.queueFamilyIndex,
339 ) 353 )
340 checkVkResult vkCreateCommandPool(device, addr createInfo, nil, addr(commandBufferPool)) 354 checkVkResult vkCreateCommandPool(device, addr createInfo, nil, addr(commandBufferPool))
341 var 355 var
342 `cmd` {.inject.}: VkCommandBuffer 356 `cmd` {.inject.}: VkCommandBuffer
343 allocInfo = VkCommandBufferAllocateInfo( 357 allocInfo = VkCommandBufferAllocateInfo(
344 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 358 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
345 commandPool: commandBufferPool, 359 commandPool: commandBufferPool,
346 level: VK_COMMAND_BUFFER_LEVEL_PRIMARY, 360 level: VK_COMMAND_BUFFER_LEVEL_PRIMARY,
347 commandBufferCount: 1, 361 commandBufferCount: 1,
348 ) 362 )
349 checkVkResult device.vk.vkAllocateCommandBuffers(addr allocInfo, addr(`cmd`)) 363 checkVkResult device.vkAllocateCommandBuffers(addr allocInfo, addr(`cmd`))
350 beginInfo = VkCommandBufferBeginInfo( 364 var beginInfo = VkCommandBufferBeginInfo(
351 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 365 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
352 flags: VkCommandBufferUsageFlags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT), 366 flags: VkCommandBufferUsageFlags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT),
353 ) 367 )
354 checkVkResult `cmd`.vkBeginCommandBuffer(addr beginInfo) 368 checkVkResult `cmd`.vkBeginCommandBuffer(addr beginInfo)
355 369
359 var submitInfo = VkSubmitInfo( 373 var submitInfo = VkSubmitInfo(
360 sType: VK_STRUCTURE_TYPE_SUBMIT_INFO, 374 sType: VK_STRUCTURE_TYPE_SUBMIT_INFO,
361 commandBufferCount: 1, 375 commandBufferCount: 1,
362 pCommandBuffers: addr(`cmd`), 376 pCommandBuffers: addr(`cmd`),
363 ) 377 )
364 checkVkResult vkQueueSubmit(GetQueue(), 1, addr submitInfo, VkFence(0)) 378
365 checkVkResult vkQueueWaitIdle(GetQueue()) # because we want to destroy the commandbuffer pool 379 var
380 fence: VkFence
381 fenceInfo = VkFenceCreateInfo(
382 sType: VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
383 # flags: toBits [VK_FENCE_CREATE_SIGNALED_BIT]
384 )
385 checkVkResult device.vkCreateFence(addr(fenceInfo), nil, addr(fence))
386 checkVkResult vkQueueSubmit(vulkan.queue, 1, addr(submitInfo), fence)
387 checkVkResult vkWaitForFences(device, 1, addr fence, false, high(uint64))
366 vkDestroyCommandPool(device, commandBufferPool, nil) 388 vkDestroyCommandPool(device, commandBufferPool, nil)
367 389
368 390
369 proc UpdateGPUBuffer*(device: VkDevice, gpuData: GPUArray) = 391 proc UpdateGPUBuffer(gpuData: GPUData) =
392 if gpuData.size == 0:
393 return
370 when UsesDirectMemory(gpuData): 394 when UsesDirectMemory(gpuData):
371 copyMem(cast[pointer](cast[uint64](gpuData.buffer.memory.data) + gpuData.buffer.offset + gpuData.offset), addr(gpuData.data[0]), gpuData.size) 395 copyMem(cast[pointer](cast[uint64](gpuData.buffer.memory.data) + gpuData.buffer.offset + gpuData.offset), gpuData.datapointer, gpuData.size)
372 else: 396 else:
373 var 397 var
374 stagingBuffer: VkBuffer 398 stagingBuffer: VkBuffer
375 createInfo = VkBufferCreateInfo( 399 createInfo = VkBufferCreateInfo(
376 sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 400 sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
378 size: gpuData.size, 402 size: gpuData.size,
379 usage: toBits([VK_BUFFER_USAGE_TRANSFER_SRC_BIT]), 403 usage: toBits([VK_BUFFER_USAGE_TRANSFER_SRC_BIT]),
380 sharingMode: VK_SHARING_MODE_EXCLUSIVE, 404 sharingMode: VK_SHARING_MODE_EXCLUSIVE,
381 ) 405 )
382 checkVkResult vkCreateBuffer( 406 checkVkResult vkCreateBuffer(
383 device = device, 407 device = vulkan.device,
384 pCreateInfo = addr(createInfo), 408 pCreateInfo = addr(createInfo),
385 pAllocator = nil, 409 pAllocator = nil,
386 pBuffer = addr(stagingBuffer), 410 pBuffer = addr(stagingBuffer),
387 ) 411 )
388 var 412 var
389 stagingMemory: VkDeviceMemory 413 stagingMemory: VkDeviceMemory
390 stagingPtr: pointer 414 stagingPtr: pointer
391 memoryAllocationInfo = VkMemoryAllocateInfo( 415 memoryAllocationInfo = VkMemoryAllocateInfo(
392 sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 416 sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
393 allocationSize: gpuData.size, 417 allocationSize: gpuData.buffer.AllocationSize(),
394 memoryTypeIndex: GetDirectMemoryTypeIndex(), 418 memoryTypeIndex: GetDirectMemoryTypeIndex(),
395 ) 419 )
396 checkVkResult vkAllocateMemory( 420 checkVkResult vkAllocateMemory(
397 device, 421 vulkan.device,
398 addr(memoryAllocationInfo), 422 addr(memoryAllocationInfo),
399 nil, 423 nil,
400 addr(stagingMemory), 424 addr(stagingMemory),
401 ) 425 )
402 checkVkResult vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0) 426 checkVkResult vkBindBufferMemory(vulkan.device, stagingBuffer, stagingMemory, 0)
403 checkVkResult vkMapMemory( 427 checkVkResult vkMapMemory(
404 device = device, 428 device = vulkan.device,
405 memory = stagingMemory, 429 memory = stagingMemory,
406 offset = 0'u64, 430 offset = 0'u64,
407 size = VK_WHOLE_SIZE, 431 size = VK_WHOLE_SIZE,
408 flags = VkMemoryMapFlags(0), 432 flags = VkMemoryMapFlags(0),
409 ppData = stagingPtr 433 ppData = addr(stagingPtr)
410 ) 434 )
411 copyMem(stagingPtr, addr(gpuData.data[0]), gpuData.size) 435 copyMem(stagingPtr, gpuData.datapointer, gpuData.size)
412 var stagingRange = VkMappedMemoryRange( 436 var stagingRange = VkMappedMemoryRange(
413 sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 437 sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
414 memory: stagingMemory, 438 memory: stagingMemory,
415 size: VK_WHOLE_SIZE, 439 size: VK_WHOLE_SIZE,
416 ) 440 )
417 checkVkResult vkFlushMappedMemoryRanges(device, 1, addr(stagingRange)) 441 checkVkResult vkFlushMappedMemoryRanges(vulkan.device, 1, addr(stagingRange))
418 442
419 WithSingleUseCommandBuffer(device, commandBuffer): 443 WithSingleUseCommandBuffer(vulkan.device, commandBuffer):
420 var copyRegion = VkBufferCopy(size: gpuData.size) 444 var copyRegion = VkBufferCopy(size: gpuData.size)
421 vkCmdCopyBuffer(commandBuffer, stagingBuffer, gpuData.buffer.vk, 1, addr(copyRegion)) 445 vkCmdCopyBuffer(commandBuffer, stagingBuffer, gpuData.buffer.vk, 1, addr(copyRegion))
422 446
423 checkVkResult vkDestroyBuffer(device, stagingBuffer, nil) 447 vkDestroyBuffer(vulkan.device, stagingBuffer, nil)
424 checkVkResult vkFreeMemory(device, stagingMemory, nil) 448 vkFreeMemory(vulkan.device, stagingMemory, nil)
449
450 proc UpdateAllGPUBuffers[T](value: T) =
451 for name, fieldvalue in value.fieldPairs():
452 when typeof(fieldvalue) is GPUData:
453 UpdateGPUBuffer(fieldvalue)
425 454
426 converter toVkIndexType(indexType: IndexType): VkIndexType = 455 converter toVkIndexType(indexType: IndexType): VkIndexType =
427 case indexType: 456 case indexType:
428 of None: VK_INDEX_TYPE_NONE_KHR 457 of None: VK_INDEX_TYPE_NONE_KHR
429 of UInt8: VK_INDEX_TYPE_UINT8_EXT 458 of UInt8: VK_INDEX_TYPE_UINT8_EXT
430 of UInt16: VK_INDEX_TYPE_UINT16 459 of UInt16: VK_INDEX_TYPE_UINT16
431 of UInt32: VK_INDEX_TYPE_UINT32 460 of UInt32: VK_INDEX_TYPE_UINT32
432 461
433 proc CreateRenderPass*( 462 proc CreateRenderPass(format: VkFormat): VkRenderPass =
434 device: VkDevice,
435 format: VkFormat,
436 ): VkRenderPass =
437
438 var 463 var
439 attachments = @[VkAttachmentDescription( 464 attachments = @[VkAttachmentDescription(
440 format: format, 465 format: format,
441 samples: VK_SAMPLE_COUNT_1_BIT, 466 samples: VK_SAMPLE_COUNT_1_BIT,
442 loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR, 467 loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR,
483 subpassCount: uint32(subpassesList.len), 508 subpassCount: uint32(subpassesList.len),
484 pSubpasses: subpassesList.ToCPointer, 509 pSubpasses: subpassesList.ToCPointer,
485 dependencyCount: uint32(dependencies.len), 510 dependencyCount: uint32(dependencies.len),
486 pDependencies: dependencies.ToCPointer, 511 pDependencies: dependencies.ToCPointer,
487 ) 512 )
488 checkVkResult device.vkCreateRenderPass(addr(createInfo), nil, addr(result)) 513 checkVkResult vulkan.device.vkCreateRenderPass(addr(createInfo), nil, addr(result))
489 514
490 proc compileGlslToSPIRV(stage: VkShaderStageFlagBits, shaderSource: string): seq[uint32] {.compileTime.} = 515 proc compileGlslToSPIRV(stage: VkShaderStageFlagBits, shaderSource: string): seq[uint32] {.compileTime.} =
491 func stage2string(stage: VkShaderStageFlagBits): string {.compileTime.} = 516 func stage2string(stage: VkShaderStageFlagBits): string {.compileTime.} =
492 case stage 517 case stage
493 of VK_SHADER_STAGE_VERTEX_BIT: "vert" 518 of VK_SHADER_STAGE_VERTEX_BIT: "vert"
603 uniforms & 628 uniforms &
604 samplers & 629 samplers &
605 fsOutput & 630 fsOutput &
606 @[shader.fragmentCode]).join("\n") 631 @[shader.fragmentCode]).join("\n")
607 632
608 proc CompileShader[TShader](device: VkDevice, shader: static TShader): ShaderObject[TShader] = 633 proc CompileShader[TShader](shader: static TShader): ShaderObject[TShader] =
609 const (vertexShaderSource, fragmentShaderSource) = generateShaderSource(shader) 634 const (vertexShaderSource, fragmentShaderSource) = generateShaderSource(shader)
610 635
611 let vertexBinary = compileGlslToSPIRV(VK_SHADER_STAGE_VERTEX_BIT, vertexShaderSource) 636 let vertexBinary = compileGlslToSPIRV(VK_SHADER_STAGE_VERTEX_BIT, vertexShaderSource)
612 let fragmentBinary = compileGlslToSPIRV(VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShaderSource) 637 let fragmentBinary = compileGlslToSPIRV(VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShaderSource)
613 638
614 var createInfoVertex = VkShaderModuleCreateInfo( 639 var createInfoVertex = VkShaderModuleCreateInfo(
615 sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, 640 sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
616 codeSize: csize_t(vertexBinary.len * sizeof(uint32)), 641 codeSize: csize_t(vertexBinary.len * sizeof(uint32)),
617 pCode: vertexBinary.ToCPointer, 642 pCode: vertexBinary.ToCPointer,
618 ) 643 )
619 checkVkResult device.vkCreateShaderModule(addr(createInfoVertex), nil, addr(result.vertexShader)) 644 checkVkResult vulkan.device.vkCreateShaderModule(addr(createInfoVertex), nil, addr(result.vertexShader))
620 var createInfoFragment = VkShaderModuleCreateInfo( 645 var createInfoFragment = VkShaderModuleCreateInfo(
621 sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, 646 sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
622 codeSize: csize_t(fragmentBinary.len * sizeof(uint32)), 647 codeSize: csize_t(fragmentBinary.len * sizeof(uint32)),
623 pCode: fragmentBinary.ToCPointer, 648 pCode: fragmentBinary.ToCPointer,
624 ) 649 )
625 checkVkResult device.vkCreateShaderModule(addr(createInfoFragment), nil, addr(result.fragmentShader)) 650 checkVkResult vulkan.device.vkCreateShaderModule(addr(createInfoFragment), nil, addr(result.fragmentShader))
626 651
627 652
628 proc CreatePipeline*[TShader]( 653 proc CreatePipeline[TShader](
629 device: VkDevice,
630 renderPass: VkRenderPass, 654 renderPass: VkRenderPass,
631 shader: ShaderObject[TShader], 655 shader: ShaderObject[TShader],
632 topology: VkPrimitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 656 topology: VkPrimitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
633 polygonMode: VkPolygonMode = VK_POLYGON_MODE_FILL, 657 polygonMode: VkPolygonMode = VK_POLYGON_MODE_FILL,
634 cullMode: VkCullModeFlagBits = VK_CULL_MODE_BACK_BIT, 658 cullMode: VkCullModeFlagBits = VK_CULL_MODE_BACK_BIT,
645 stageFlags: VkShaderStageFlags(VK_SHADER_STAGE_ALL_GRAPHICS), 669 stageFlags: VkShaderStageFlags(VK_SHADER_STAGE_ALL_GRAPHICS),
646 pImmutableSamplers: nil, 670 pImmutableSamplers: nil,
647 ) 671 )
648 var layoutCreateInfo = VkDescriptorSetLayoutCreateInfo( 672 var layoutCreateInfo = VkDescriptorSetLayoutCreateInfo(
649 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, 673 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
650 bindingCount: uint32(layoutbindings.len), 674 bindingCount: layoutbindings.len.uint32,
651 pBindings: layoutbindings.ToCPointer 675 pBindings: layoutbindings.ToCPointer
652 ) 676 )
653 checkVkResult vkCreateDescriptorSetLayout(device, addr(layoutCreateInfo), nil, addr(result.descriptorSetLayout)) 677 checkVkResult vkCreateDescriptorSetLayout(vulkan.device, addr(layoutCreateInfo), nil, addr(result.descriptorSetLayouts))
654 let pipelineLayoutInfo = VkPipelineLayoutCreateInfo( 678 let pipelineLayoutInfo = VkPipelineLayoutCreateInfo(
655 sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 679 sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
656 setLayoutCount: 1, 680 setLayoutCount: result.descriptorSetLayouts.len.uint32,
657 pSetLayouts: addr(result.descriptorSetLayout), 681 pSetLayouts: descriptorSetLayouts.ToCPointer,
658 # pushConstantRangeCount: uint32(pushConstants.len), 682 # pushConstantRangeCount: uint32(pushConstants.len),
659 # pPushConstantRanges: pushConstants.ToCPointer, 683 # pPushConstantRanges: pushConstants.ToCPointer,
660 ) 684 )
661 checkVkResult vkCreatePipelineLayout(device, addr(pipelineLayoutInfo), nil, addr(result.layout)) 685 checkVkResult vkCreatePipelineLayout(vulkan.device, addr(pipelineLayoutInfo), nil, addr(result.layout))
662 686
663 let stages = [ 687 let stages = [
664 VkPipelineShaderStageCreateInfo( 688 VkPipelineShaderStageCreateInfo(
665 sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 689 sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
666 stage: VK_SHADER_STAGE_VERTEX_BIT, 690 stage: VK_SHADER_STAGE_VERTEX_BIT,
776 subpass: 0, 800 subpass: 0,
777 basePipelineHandle: VkPipeline(0), 801 basePipelineHandle: VkPipeline(0),
778 basePipelineIndex: -1, 802 basePipelineIndex: -1,
779 ) 803 )
780 checkVkResult vkCreateGraphicsPipelines( 804 checkVkResult vkCreateGraphicsPipelines(
781 device, 805 vulkan.device,
782 VkPipelineCache(0), 806 VkPipelineCache(0),
783 1, 807 1,
784 addr(createInfo), 808 addr(createInfo),
785 nil, 809 nil,
786 addr(result.pipeline) 810 addr(result.pipeline)
787 ) 811 )
788 812
789 proc AllocateIndirectMemory(device: VkDevice, pDevice: VkPhysicalDevice, size: uint64): IndirectGPUMemory = 813 proc AllocateIndirectMemory(size: uint64): IndirectGPUMemory =
790 # chooses biggest memory type that has NOT VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT 814 # chooses biggest memory type that has NOT VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
791 result.size = size 815 result.size = size
792 result.needsTransfer = true 816 result.needsTransfer = true
793 817
794 # find a good memory type 818 # find a good memory type
795 var physicalProperties: VkPhysicalDeviceMemoryProperties 819 var physicalProperties: VkPhysicalDeviceMemoryProperties
796 checkVkResult vkGetPhysicalDeviceMemoryProperties(pDevice, addr physicalProperties) 820 vkGetPhysicalDeviceMemoryProperties(vulkan.physicalDevice, addr physicalProperties)
797 821
798 var biggestHeap: uint64 = 0 822 var biggestHeap: uint64 = 0
799 var memoryTypeIndex = high(uint32) 823 var memoryTypeIndex = high(uint32)
800 # try to find non-host-visible type 824 # try to find non-host-visible type
801 for i in 0'u32 ..< physicalProperties.memoryTypeCount: 825 for i in 0'u32 ..< physicalProperties.memoryTypeCount:
819 sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 843 sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
820 allocationSize: result.size, 844 allocationSize: result.size,
821 memoryTypeIndex: memoryTypeIndex, 845 memoryTypeIndex: memoryTypeIndex,
822 ) 846 )
823 checkVkResult vkAllocateMemory( 847 checkVkResult vkAllocateMemory(
824 device, 848 vulkan.device,
825 addr allocationInfo, 849 addr allocationInfo,
826 nil, 850 nil,
827 addr result.vk 851 addr result.vk
828 ) 852 )
829 853
830 proc AllocateDirectMemory(device: VkDevice, pDevice: VkPhysicalDevice, size: uint64): DirectGPUMemory = 854 proc AllocateDirectMemory(size: uint64): DirectGPUMemory =
831 result.size = size 855 result.size = size
832 result.needsFlush = true 856 result.needsFlush = true
833 857
834 # find a good memory type 858 # find a good memory type
835 var physicalProperties: VkPhysicalDeviceMemoryProperties 859 var physicalProperties: VkPhysicalDeviceMemoryProperties
836 checkVkResult vkGetPhysicalDeviceMemoryProperties(pDevice, addr physicalProperties) 860 vkGetPhysicalDeviceMemoryProperties(vulkan.physicalDevice, addr physicalProperties)
837 861
838 var biggestHeap: uint64 = 0 862 var biggestHeap: uint64 = 0
839 var memoryTypeIndex = high(uint32) 863 var memoryTypeIndex = high(uint32)
840 # try to find host-visible type 864 # try to find host-visible type
841 for i in 0 ..< physicalProperties.memoryTypeCount: 865 for i in 0 ..< physicalProperties.memoryTypeCount:
849 873
850 assert memoryTypeIndex != high(uint32), "Unable to find indirect memory type" 874 assert memoryTypeIndex != high(uint32), "Unable to find indirect memory type"
851 var allocationInfo = VkMemoryAllocateInfo( 875 var allocationInfo = VkMemoryAllocateInfo(
852 sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 876 sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
853 allocationSize: result.size, 877 allocationSize: result.size,
854 memoryTypeIndex: FindDirectMemoryTypeIndex(pDevice), 878 memoryTypeIndex: GetDirectMemoryTypeIndex(),
855 ) 879 )
856 checkVkResult vkAllocateMemory( 880 checkVkResult vkAllocateMemory(
857 device, 881 vulkan.device,
858 addr allocationInfo, 882 addr allocationInfo,
859 nil, 883 nil,
860 addr result.vk 884 addr result.vk
861 ) 885 )
862 checkVkResult vkMapMemory( 886 checkVkResult vkMapMemory(
863 device = device, 887 device = vulkan.device,
864 memory = result.vk, 888 memory = result.vk,
865 offset = 0'u64, 889 offset = 0'u64,
866 size = result.size, 890 size = result.size,
867 flags = VkMemoryMapFlags(0), 891 flags = VkMemoryMapFlags(0),
868 ppData = addr(result.data) 892 ppData = addr(result.data)
869 ) 893 )
870 894
871 proc AllocateIndirectBuffer(device: VkDevice, renderData: var RenderData, size: uint64, btype: BufferType) = 895 proc AllocateIndirectBuffer(renderData: var RenderData, size: uint64, btype: BufferType) =
872 assert size > 0, "Buffer sizes must be larger than 0" 896 if size == 0:
897 return
873 var buffer = Buffer[IndirectGPUMemory](size: size) 898 var buffer = Buffer[IndirectGPUMemory](size: size)
874 899
875 let usageFlags = case btype: 900 let usageFlags = case btype:
876 of VertexBuffer: [VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] 901 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] 902 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] 903 of UniformBuffer: [VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT]
879 904
880 # iterate through memory areas to find big enough free space 905 # iterate through memory areas to find big enough free space
881 for (memory, offset) in renderData.indirectMemory.mitems: 906 # TODO: dynamically expand memory allocations
882 if memory.size - offset >= size: 907 for (memory, usedOffset) in renderData.indirectMemory.mitems:
883 buffer.offset = offset 908 if memory.size - usedOffset >= size:
909 buffer.offset = usedOffset
884 # create buffer 910 # create buffer
885 var createInfo = VkBufferCreateInfo( 911 var createInfo = VkBufferCreateInfo(
886 sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 912 sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
887 flags: VkBufferCreateFlags(0), 913 flags: VkBufferCreateFlags(0),
888 size: buffer.size, 914 size: buffer.size,
889 usage: toBits(usageFlags), 915 usage: toBits(usageFlags),
890 sharingMode: VK_SHARING_MODE_EXCLUSIVE, 916 sharingMode: VK_SHARING_MODE_EXCLUSIVE,
891 ) 917 )
892 checkVkResult vkCreateBuffer( 918 checkVkResult vkCreateBuffer(
893 device = device, 919 device = vulkan.device,
894 pCreateInfo = addr createInfo, 920 pCreateInfo = addr createInfo,
895 pAllocator = nil, 921 pAllocator = nil,
896 pBuffer = addr(buffer.vk) 922 pBuffer = addr(buffer.vk)
897 ) 923 )
898 checkVkResult vkBindBufferMemory(device, buffer.vk, memory.vk, buffer.offset) 924 checkVkResult vkBindBufferMemory(vulkan.device, buffer.vk, memory.vk, buffer.offset)
899 renderData.indirectBuffers.add (buffer, btype, 0'u64) 925 renderData.indirectBuffers.add (buffer, btype, 0'u64)
900 # update memory area offset 926 # update memory area offset
901 offset = alignedTo(offset + size, MEMORY_ALIGNMENT) 927 usedOffset = alignedTo(usedOffset + size, MEMORY_ALIGNMENT)
902 return 928 return
903 929
904 assert false, "Did not find allocated memory region with enough space" 930 assert false, "Did not find allocated memory region with enough space"
905 931
906 proc AllocateDirectBuffer(device: VkDevice, renderData: var RenderData, size: uint64, btype: BufferType) = 932 proc AllocateDirectBuffer(renderData: var RenderData, size: uint64, btype: BufferType) =
907 assert size > 0, "Buffer sizes must be larger than 0" 933 if size == 0:
934 return
935
908 var buffer = Buffer[DirectGPUMemory](size: size) 936 var buffer = Buffer[DirectGPUMemory](size: size)
909 937
910 let usageFlags = case btype: 938 let usageFlags = case btype:
911 of VertexBuffer: [VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] 939 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] 940 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] 941 of UniformBuffer: [VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT]
914 942
915 # iterate through memory areas to find big enough free space 943 # iterate through memory areas to find big enough free space
916 for (memory, offset) in renderData.directMemory.mitems: 944 # TODO: dynamically expand memory allocations
917 if memory.size - offset >= size: 945 for (memory, usedOffset) in renderData.directMemory.mitems:
918 buffer.offset = offset 946 if memory.size - usedOffset >= size:
947 buffer.offset = usedOffset
919 # create buffer 948 # create buffer
920 var createInfo = VkBufferCreateInfo( 949 var createInfo = VkBufferCreateInfo(
921 sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 950 sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
922 flags: VkBufferCreateFlags(0), 951 flags: VkBufferCreateFlags(0),
923 size: buffer.size, 952 size: buffer.size,
924 usage: toBits(usageFlags), 953 usage: toBits(usageFlags),
925 sharingMode: VK_SHARING_MODE_EXCLUSIVE, 954 sharingMode: VK_SHARING_MODE_EXCLUSIVE,
926 ) 955 )
927 checkVkResult vkCreateBuffer( 956 checkVkResult vkCreateBuffer(
928 device = device, 957 device = vulkan.device,
929 pCreateInfo = addr createInfo, 958 pCreateInfo = addr createInfo,
930 pAllocator = nil, 959 pAllocator = nil,
931 pBuffer = addr(buffer.vk) 960 pBuffer = addr(buffer.vk)
932 ) 961 )
933 checkVkResult vkBindBufferMemory(device, buffer.vk, memory.vk, buffer.offset) 962 checkVkResult vkBindBufferMemory(vulkan.device, buffer.vk, memory.vk, buffer.offset)
934 renderData.directBuffers.add (buffer, btype, 0'u64) 963 renderData.directBuffers.add (buffer, btype, 0'u64)
935 # update memory area offset 964 # update memory area offset
936 offset = alignedTo(offset + size, MEMORY_ALIGNMENT) 965 usedOffset = alignedTo(usedOffset + size, MEMORY_ALIGNMENT)
937 return 966 return
938 967
939 assert false, "Did not find allocated memory region with enough space" 968 assert false, "Did not find allocated memory region with enough space"
940 969
941 proc InitRenderData(device: VkDevice, pDevice: VkPhysicalDevice, descriptorPoolLimit = 1024'u32): RenderData = 970 proc InitRenderData(descriptorPoolLimit = 1024'u32): RenderData =
942 # allocate descriptor pools 971 # allocate descriptor pools
943 var poolSizes = [ 972 var poolSizes = [
944 VkDescriptorPoolSize(thetype: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, descriptorCount: descriptorPoolLimit), 973 VkDescriptorPoolSize(thetype: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, descriptorCount: descriptorPoolLimit),
945 VkDescriptorPoolSize(thetype: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: descriptorPoolLimit), 974 VkDescriptorPoolSize(thetype: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: descriptorPoolLimit),
946 ] 975 ]
948 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, 977 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
949 poolSizeCount: poolSizes.len.uint32, 978 poolSizeCount: poolSizes.len.uint32,
950 pPoolSizes: poolSizes.ToCPointer, 979 pPoolSizes: poolSizes.ToCPointer,
951 maxSets: descriptorPoolLimit, 980 maxSets: descriptorPoolLimit,
952 ) 981 )
953 checkVkResult vkCreateDescriptorPool(device, addr(poolInfo), nil, addr(result.descriptorPool)) 982 checkVkResult vkCreateDescriptorPool(vulkan.device, addr(poolInfo), nil, addr(result.descriptorPool))
954 983
955 # allocate some memory 984 # allocate some memory
956 var initialAllocationSize = 1_000_000_000'u64 # TODO: make this more dynamic or something 985 var initialAllocationSize = 1_000_000_000'u64 # TODO: make this more dynamic or something
957 result.indirectMemory = @[(AllocateIndirectMemory(device, pDevice, size = initialAllocationSize), 0'u64)] 986 result.indirectMemory = @[(memory: AllocateIndirectMemory(size = initialAllocationSize), usedOffset: 0'u64)]
958 result.directMemory = @[(AllocateDirectMemory(device, pDevice, size = initialAllocationSize), 0'u64)] 987 result.directMemory = @[(memory: AllocateDirectMemory(size = initialAllocationSize), usedOffset: 0'u64)]
988
989 proc FlushDirectMemory(renderData: RenderData) =
990 var flushRegions = newSeqOfCap[VkMappedMemoryRange](renderData.directMemory.len)
991 for entry in renderData.directMemory:
992 if entry.usedOffset > 0:
993 flushRegions.add VkMappedMemoryRange(
994 sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
995 memory: entry.memory.vk,
996 size: entry.usedOffset,
997 )
998 if flushRegions.len > 0:
999 checkVkResult vkFlushMappedMemoryRanges(vulkan.device, flushRegions.len.uint32, flushRegions.ToCPointer())
959 1000
960 # For the Get*BufferSize: 1001 # For the Get*BufferSize:
961 # BUFFER_ALIGNMENT is just added for a rough estimate, to ensure we have enough space to align when binding 1002 # BUFFER_ALIGNMENT is just added for a rough estimate, to ensure we have enough space to align when binding
962 proc GetIndirectBufferSizes[T](data: T): uint64 = 1003 proc GetIndirectBufferSizes[T](data: T): uint64 =
963 for name, value in fieldPairs(data): 1004 for name, value in fieldPairs(data):
984 static: assert typeof(value) is GPUArray, "Index buffers must be of type GPUArray" 1025 static: assert typeof(value) is GPUArray, "Index buffers must be of type GPUArray"
985 static: assert elementType(value.data) is uint8 or elementType(value.data) is uint16 or elementType(value.data) is uint32 1026 static: assert elementType(value.data) is uint8 or elementType(value.data) is uint16 or elementType(value.data) is uint32
986 when UsesDirectMemory(value): 1027 when UsesDirectMemory(value):
987 result += value.size + BUFFER_ALIGNMENT 1028 result += value.size + BUFFER_ALIGNMENT
988 1029
989 proc AssignIndirectBuffers[T](data: T, renderdata: var RenderData, btype: BufferType) = 1030 proc AssignIndirectBuffers[T](renderdata: var RenderData, btype: BufferType, data: var T) =
990 for name, value in fieldPairs(data): 1031 for name, value in fieldPairs(data):
991 when typeof(value) is GPUData: 1032 when typeof(value) is GPUData:
992 when UsesIndirectMemory(value): 1033 when UsesIndirectMemory(value):
993 # find next buffer of correct type with enough free space 1034 # find next buffer of correct type with enough free space
994 var foundBuffer = false 1035 if btype == IndexBuffer == value.hasCustomPragma(VertexIndices):
995 for (buffer, bt, offset) in renderData.indirectBuffers.mitems: 1036 var foundBuffer = false
996 if bt == btype and buffer.size - offset >= size: 1037 for (buffer, bt, offset) in renderData.indirectBuffers.mitems:
997 assert not value.buffer.vk.Valid, "GPUData-Buffer has already been assigned" 1038 if bt == btype and buffer.size - offset >= value.size:
998 assert buffer.vk.Valid, "RenderData-Buffer has not yet been created" 1039 assert not value.buffer.vk.Valid, "GPUData-Buffer has already been assigned"
999 value.buffer = buffer 1040 assert buffer.vk.Valid, "RenderData-Buffer has not yet been created"
1000 value.offset = offset 1041 value.buffer = buffer
1001 offset = alignedTo(offset + value.size, BUFFER_ALIGNMENT) 1042 value.offset = offset
1002 foundBuffer = true 1043 offset = alignedTo(offset + value.size, BUFFER_ALIGNMENT)
1003 break 1044 foundBuffer = true
1004 assert foundBuffer, &"Unable to find large enough '{btype}' for '{data}'" 1045 break
1005 proc AssignDirectBuffers[T](data: T, renderdata: var RenderData, btype: BufferType) = 1046 assert foundBuffer, &"Unable to find large enough '{btype}' for '{data}'"
1047 proc AssignDirectBuffers[T](renderdata: var RenderData, btype: BufferType, data: var T) =
1006 for name, value in fieldPairs(data): 1048 for name, value in fieldPairs(data):
1007 when typeof(value) is GPUData: 1049 when typeof(value) is GPUData:
1008 when UsesDirectMemory(value): 1050 when UsesDirectMemory(value):
1009 # find next buffer of correct type with enough free space 1051 # find next buffer of correct type with enough free space
1010 var foundBuffer = false 1052 if btype == IndexBuffer == value.hasCustomPragma(VertexIndices):
1011 for (buffer, bt, offset) in renderData.directBuffers.mitems: 1053 var foundBuffer = false
1012 if bt == btype and buffer.size - offset >= size: 1054 for (buffer, bt, offset) in renderData.directBuffers.mitems:
1013 assert not value.buffer.vk.Valid, "GPUData-Buffer has already been assigned" 1055 if bt == btype and buffer.size - offset >= value.size:
1014 assert buffer.vk.Valid, "RenderData-Buffer has not yet been created" 1056 assert not value.buffer.vk.Valid, "GPUData-Buffer has already been assigned"
1015 value.buffer = buffer 1057 assert buffer.vk.Valid, "RenderData-Buffer has not yet been created"
1016 value.offset = offset 1058 value.buffer = buffer
1017 offset = alignedTo(offset + value.size, BUFFER_ALIGNMENT) 1059 value.offset = offset
1018 foundBuffer = true 1060 offset = alignedTo(offset + value.size, BUFFER_ALIGNMENT)
1019 break 1061 foundBuffer = true
1020 assert foundBuffer, &"Unable to find large enough '{btype}' for '{data}'" 1062 break
1021 1063 assert foundBuffer, &"Unable to find large enough '{btype}' for '{data}'"
1022 proc WriteDescriptors[TShader](device: VkDevice, descriptorSets: array[INFLIGHTFRAMES.int, VkDescriptorSet]) = 1064
1065 proc HasGPUValueField[T](name: static string): bool {.compileTime.} =
1066 for fieldname, value in default(T).fieldPairs():
1067 when typeof(value) is GPUValue and fieldname == name: return true
1068 return false
1069
1070 template WithGPUValueField(obj: object, name: static string, fieldvalue, body: untyped): untyped =
1071 # HasGPUValueField MUST be used to check if this is supported
1072 for fieldname, value in obj.fieldPairs():
1073 when fieldname == name:
1074 block:
1075 let `fieldvalue` {.inject.} = value
1076 body
1077
1078 proc WriteDescriptors[TShader, TUniforms, TGlobals](renderData: RenderData, uniforms: TUniforms, globals: TGlobals) =
1023 var descriptorSetWrites: seq[VkWriteDescriptorSet] 1079 var descriptorSetWrites: seq[VkWriteDescriptorSet]
1024 # map (buffer + offset + range) to descriptor 1080 # map (buffer + offset + range) to descriptor
1025 # map (texture) to descriptor 1081 # map (texture) to descriptor
1026 ForDescriptorFields(default(TShader), fieldName, descriptorType, descriptorCount, descriptorBindingNumber): 1082 ForDescriptorFields(default(TShader), fieldName, descriptorType, descriptorCount, descriptorBindingNumber):
1027 for frameInFlight in 0 ..< descriptorSets.len: 1083 static: echo fieldName, " ", descriptorType, " ", descriptorCount
1084 for frameInFlight in 0 ..< renderData.descriptorSets.len:
1028 when descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 1085 when descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1029 # TODO 1086 when HasGPUValueField[TUniforms](fieldName):
1030 let bufferInfo = VkDescriptorBufferInfo( 1087 WithGPUValueField(uniforms, fieldName, gpuValue):
1031 buffer: VkBuffer(0), 1088 let bufferInfo = VkDescriptorBufferInfo(
1032 offset: 0, 1089 buffer: gpuValue.buffer.vk,
1033 range: 1, 1090 offset: gpuValue.buffer.offset,
1034 ) 1091 range: gpuValue.buffer.size,
1035 descriptorSetWrites.add VkWriteDescriptorSet( 1092 )
1036 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 1093 descriptorSetWrites.add VkWriteDescriptorSet(
1037 dstSet: descriptorSets[frameInFlight], 1094 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1038 dstBinding: descriptorBindingNumber, 1095 dstSet: renderData.descriptorSets[frameInFlight],
1039 dstArrayElement: uint32(0), 1096 dstBinding: descriptorBindingNumber,
1040 descriptorType: descriptorType, 1097 dstArrayElement: uint32(0),
1041 descriptorCount: descriptorCount, 1098 descriptorType: descriptorType,
1042 pImageInfo: nil, 1099 descriptorCount: descriptorCount,
1043 pBufferInfo: addr(bufferInfo), 1100 pImageInfo: nil,
1044 ) 1101 pBufferInfo: addr(bufferInfo),
1102 )
1103 elif HasGPUValueField[TGlobals](fieldName):
1104 WithGPUValueField(globals, fieldName, theValue):
1105 let bufferInfo = VkDescriptorBufferInfo(
1106 buffer: theValue.buffer.vk,
1107 offset: theValue.buffer.offset,
1108 range: theValue.buffer.size,
1109 )
1110 descriptorSetWrites.add VkWriteDescriptorSet(
1111 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1112 dstSet: renderData.descriptorSets[frameInFlight],
1113 dstBinding: descriptorBindingNumber,
1114 dstArrayElement: uint32(0),
1115 descriptorType: descriptorType,
1116 descriptorCount: descriptorCount,
1117 pImageInfo: nil,
1118 pBufferInfo: addr(bufferInfo),
1119 )
1120 else:
1121 {.error: "Unable to find field '" & fieldName & "' in uniforms or globals".}
1045 elif descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 1122 elif descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1046 # TODO 1123 # TODO
1047 let imageInfo = VkDescriptorImageInfo( 1124 let imageInfo = VkDescriptorImageInfo(
1048 sampler: VkSampler(0), 1125 sampler: VkSampler(0),
1049 imageView: VkImageView(0), 1126 imageView: VkImageView(0),
1050 imageLayout: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1127 imageLayout: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
1051 ) 1128 )
1052 descriptorSetWrites.add VkWriteDescriptorSet( 1129 descriptorSetWrites.add VkWriteDescriptorSet(
1053 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 1130 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1054 dstSet: descriptorSets[frameInFlight], 1131 dstSet: renderData.descriptorSets[frameInFlight],
1055 dstBinding: descriptorBindingNumber, 1132 dstBinding: descriptorBindingNumber,
1056 dstArrayElement: uint32(0), 1133 dstArrayElement: 0'u32,
1057 descriptorType: descriptorType, 1134 descriptorType: descriptorType,
1058 descriptorCount: descriptorCount, 1135 descriptorCount: descriptorCount,
1059 pImageInfo: addr(imageInfo), 1136 pImageInfo: addr(imageInfo),
1060 pBufferInfo: nil, 1137 pBufferInfo: nil,
1061 ) 1138 )
1062 checkVkResult vkUpdateDescriptorSets(device, uint32(descriptorSetWrites.len), descriptorSetWrites.ToCPointer, 0, nil) 1139 else:
1140 assert false, "Unsupported descriptor type"
1141 echo descriptorSetWrites
1142 vkUpdateDescriptorSets(vulkan.device, uint32(descriptorSetWrites.len), descriptorSetWrites.ToCPointer, 0, nil)
1063 1143
1064 proc Bind[T](pipeline: Pipeline[T], commandBuffer: VkCommandBuffer, currentFrameInFlight: int) = 1144 proc Bind[T](pipeline: Pipeline[T], commandBuffer: VkCommandBuffer, currentFrameInFlight: int) =
1065 commandBuffer.vkCmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline) 1145 commandBuffer.vkCmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline)
1066 #[ 1146 #[
1067 commandBuffer.vkCmdBindDescriptorSets( 1147 commandBuffer.vkCmdBindDescriptorSets(
1252 vertexCode: string = "void main() {}" 1332 vertexCode: string = "void main() {}"
1253 fragmentCode: string = "void main() {}" 1333 fragmentCode: string = "void main() {}"
1254 1334
1255 let w = CreateWindow("test2") 1335 let w = CreateWindow("test2")
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") 1336 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")
1257 let vulkan = w.CreateInstance( 1337
1338 # TODO: remove those ugly wrappers
1339 let theInstance = w.CreateInstance(
1258 vulkanVersion = VK_MAKE_API_VERSION(0, 1, 3, 0), 1340 vulkanVersion = VK_MAKE_API_VERSION(0, 1, 3, 0),
1259 instanceExtensions = @[], 1341 instanceExtensions = @[],
1260 layers = @["VK_LAYER_KHRONOS_validation"], 1342 layers = @["VK_LAYER_KHRONOS_validation"],
1261 ) 1343 )
1262 1344
1263 let dev = vulkan.CreateDevice( 1345 let dev = theInstance.CreateDevice(
1264 GetPhysicalDevice(), 1346 theInstance.GetPhysicalDevices().FilterBestGraphics(),
1265 enabledExtensions = @[], 1347 enabledExtensions = @[],
1266 [GetQueueFamily()], 1348 theInstance.GetPhysicalDevices().FilterBestGraphics().FilterForGraphicsPresentationQueues()
1267 ) 1349 ).vk
1268 let frameWidth = 100'u32 1350 let frameWidth = 100'u32
1269 let frameHeight = 100'u32 1351 let frameHeight = 100'u32
1352
1353 # TODO: pack this stuff into a setup method and condense everything a bit
1354 let pDevice = theInstance.vk.GetPhysicalDevice()
1355 let qfi = pDevice.GetQueueFamily(VK_QUEUE_GRAPHICS_BIT)
1356 vulkan = VulkanGlobals(
1357 instance: theInstance.vk,
1358 device: dev,
1359 physicalDevice: pDevice,
1360 queueFamilyIndex: qfi,
1361 queue: dev.GetQueue(qfi, VK_QUEUE_GRAPHICS_BIT)
1362 )
1270 1363
1271 var myMesh1 = MeshA( 1364 var myMesh1 = MeshA(
1272 position: GPUArray[Vec3f, IndirectGPUMemory](data: @[NewVec3f(0, 0, ), NewVec3f(0, 0, ), NewVec3f(0, 0, )]), 1365 position: GPUArray[Vec3f, IndirectGPUMemory](data: @[NewVec3f(0, 0, ), NewVec3f(0, 0, ), NewVec3f(0, 0, )]),
1273 ) 1366 )
1274 var uniforms1 = UniformsA( 1367 var uniforms1 = UniformsA(
1288 objPosition: GPUArray[Vec3f, IndirectGPUMemory](data: @[NewVec3f(0, 0, 0), NewVec3f(1, 1, 1)]), 1381 objPosition: GPUArray[Vec3f, IndirectGPUMemory](data: @[NewVec3f(0, 0, 0), NewVec3f(1, 1, 1)]),
1289 ) 1382 )
1290 var myGlobals: GlobalsA 1383 var myGlobals: GlobalsA
1291 1384
1292 # setup for rendering (TODO: swapchain & framebuffers) 1385 # setup for rendering (TODO: swapchain & framebuffers)
1293 1386 let renderpass = CreateRenderPass(GetSurfaceFormat())
1294 # renderpass
1295 let renderpass = CreateRenderPass(dev.vk, dev.physicalDevice.GetSurfaceFormats().FilterSurfaceFormat().format)
1296 1387
1297 # shaders 1388 # shaders
1298 const shader = ShaderA() 1389 const shader = ShaderA()
1299 let shaderObject = dev.vk.CompileShader(shader) 1390 let shaderObject = CompileShader(shader)
1300 var pipeline1 = CreatePipeline(device = dev.vk, renderPass = renderpass, shader = shaderObject) 1391 var pipeline1 = CreatePipeline(renderPass = renderpass, shader = shaderObject)
1301 1392
1302 var renderdata = InitRenderData(dev.vk, dev.physicalDevice.vk) 1393 var renderdata = InitRenderData()
1303 1394
1304 # create descriptor sets 1395 # TODO: Textures
1305 #[
1306 var descriptorSets: array[INFLIGHTFRAMES.int, VkDescriptorSet]
1307 var layouts = newSeqWith(descriptorSets.len, pipeline.descriptorSetLayout)
1308 var allocInfo = VkDescriptorSetAllocateInfo(
1309 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1310 descriptorPool: pool,
1311 descriptorSetCount: uint32(layouts.len),
1312 pSetLayouts: layouts.ToCPointer,
1313 )
1314 checkVkResult vkAllocateDescriptorSets(device, addr(allocInfo), descriptorSets.ToCPointer)
1315 ]#
1316
1317 #[
1318 # TODO:
1319 #
1320 # assign indirect buffers to vertex data, can happen through the GPUArray/GPUValue-wrappers, they know buffers
1321 # assign direct buffers to vertex data
1322 # assign indirect buffers to uniform data
1323 # assign direct buffers to uniform data
1324 #
1325 # upload all textures 1396 # upload all textures
1326 # write descriptors for textures and uniform buffers 1397 # write descriptors for textures and uniform buffers
1327 #
1328 ]#
1329 1398
1330 # buffer allocation 1399 # buffer allocation
1331 var 1400 var
1332 indirectVertexSizes = 0'u64 1401 indirectVertexSizes = 0'u64
1333 directVertexSizes = 0'u64 1402 directVertexSizes = 0'u64
1334 indirectIndexSizes = 0'u64 1403 indirectIndexSizes = 0'u64
1335 directIndexSizes = 0'u64 1404 directIndexSizes = 0'u64
1336 indirectUniformSizes = 0'u64 1405 indirectUniformSizes = 0'u64
1337 directUniformSizes = 0'u64 1406 directUniformSizes = 0'u64
1338 1407
1408 # buffer allocation
1409
1410 echo "Allocating GPU buffers"
1339 indirectVertexSizes += GetIndirectBufferSizes(myMesh1) 1411 indirectVertexSizes += GetIndirectBufferSizes(myMesh1)
1340 indirectVertexSizes += GetIndirectBufferSizes(instances1) 1412 indirectVertexSizes += GetIndirectBufferSizes(instances1)
1341 if indirectVertexSizes > 0: 1413 AllocateIndirectBuffer(renderdata, indirectVertexSizes, VertexBuffer)
1342 AllocateIndirectBuffer(dev.vk, renderdata, indirectVertexSizes, VertexBuffer)
1343 1414
1344 directVertexSizes += GetDirectBufferSizes(myMesh1) 1415 directVertexSizes += GetDirectBufferSizes(myMesh1)
1345 directVertexSizes += GetDirectBufferSizes(instances1) 1416 directVertexSizes += GetDirectBufferSizes(instances1)
1346 if directVertexSizes > 0: 1417 AllocateDirectBuffer(renderdata, directVertexSizes, VertexBuffer)
1347 AllocateDirectBuffer(dev.vk, renderdata, directVertexSizes, VertexBuffer)
1348 1418
1349 indirectIndexSizes += GetIndirectIndexBufferSizes(myMesh1) 1419 indirectIndexSizes += GetIndirectIndexBufferSizes(myMesh1)
1350 if indirectIndexSizes > 0: 1420 AllocateIndirectBuffer(renderdata, indirectIndexSizes, IndexBuffer)
1351 AllocateIndirectBuffer(dev.vk, renderdata, indirectIndexSizes, IndexBuffer)
1352 1421
1353 directIndexSizes += GetDirectIndexBufferSizes(myMesh1) 1422 directIndexSizes += GetDirectIndexBufferSizes(myMesh1)
1354 if directIndexSizes > 0: 1423 AllocateDirectBuffer(renderdata, directIndexSizes, IndexBuffer)
1355 AllocateDirectBuffer(dev.vk, renderdata, directIndexSizes, IndexBuffer)
1356 1424
1357 indirectUniformSizes += GetIndirectBufferSizes(uniforms1) 1425 indirectUniformSizes += GetIndirectBufferSizes(uniforms1)
1358 indirectUniformSizes += GetIndirectBufferSizes(myGlobals) 1426 indirectUniformSizes += GetIndirectBufferSizes(myGlobals)
1359 if indirectUniformSizes > 0: 1427 AllocateIndirectBuffer(renderdata, indirectUniformSizes, UniformBuffer)
1360 AllocateIndirectBuffer(dev.vk, renderdata, indirectUniformSizes, UniformBuffer)
1361 1428
1362 directUniformSizes += GetDirectBufferSizes(uniforms1) 1429 directUniformSizes += GetDirectBufferSizes(uniforms1)
1363 directUniformSizes += GetDirectBufferSizes(myGlobals) 1430 directUniformSizes += GetDirectBufferSizes(myGlobals)
1364 if directUniformSizes > 0: 1431 AllocateDirectBuffer(renderdata, directUniformSizes, UniformBuffer)
1365 AllocateDirectBuffer(dev.vk, renderdata, directUniformSizes, UniformBuffer)
1366 1432
1367 # buffer assignment 1433 # buffer assignment
1368 1434 #
1369 AssignIndirectBuffers(data = myMesh1, renderdata = RenderData, btype = VertexBuffer) 1435 echo "Assigning buffers to GPUData fields"
1370 AssignDirectBuffers(data = myMesh1, renderdata = RenderData, btype = VertexBuffer) 1436
1371 AssignIndirectBuffers(data = myMesh1, renderdata = RenderData, btype = IndexBuffer) 1437 # for meshes we do:
1372 AssignDirectBuffers(data = myMesh1, renderdata = RenderData, btype = IndexBuffer) 1438 renderdata.AssignIndirectBuffers(VertexBuffer, myMesh1)
1373 1439 renderdata.AssignDirectBuffers(VertexBuffer, myMesh1)
1374 AssignIndirectBuffers(data = instances1, renderdata = RenderData, btype = VertexBuffer) 1440 renderdata.AssignIndirectBuffers(IndexBuffer, myMesh1)
1375 AssignDirectBuffers(data = instances1, renderdata = RenderData, btype = VertexBuffer) 1441 renderdata.AssignDirectBuffers(IndexBuffer, myMesh1)
1376 1442
1377 AssignIndirectBuffers(data = uniforms1, renderdata = RenderData, btype = UniformBuffer) 1443 # for instances we do:
1378 AssignDirectBuffers(data = uniforms1, renderdata = RenderData, btype = UniformBuffer) 1444 renderdata.AssignIndirectBuffers(VertexBuffer, instances1)
1379 AssignIndirectBuffers(data = myGlobals, renderdata = RenderData, btype = UniformBuffer) 1445 renderdata.AssignDirectBuffers(VertexBuffer, instances1)
1380 AssignDirectBuffers(data = myGlobals, renderdata = RenderData, btype = UniformBuffer) 1446
1381 1447 # for uniforms/globals we do:
1382 UpdateGPUBuffer() 1448 renderdata.AssignIndirectBuffers(UniformBuffer, uniforms1)
1449 renderdata.AssignDirectBuffers(UniformBuffer, uniforms1)
1450 renderdata.AssignIndirectBuffers(UniformBuffer, myGlobals)
1451 renderdata.AssignDirectBuffers(UniformBuffer, myGlobals)
1452
1453 # buffer filling
1454
1455 echo "Copying all data to GPU memory"
1456
1457 # copy everything to GPU
1458 UpdateAllGPUBuffers(myMesh1)
1459 UpdateAllGPUBuffers(instances1)
1460 UpdateAllGPUBuffers(uniforms1)
1461 UpdateAllGPUBuffers(myGlobals)
1462 renderdata.FlushDirectMemory()
1383 1463
1384 # descriptors 1464 # descriptors
1385 # WriteDescriptors(dev.vk, pipeline1) 1465 WriteDescriptors[ShaderA, UniformsA, GlobalsA](renderdata, uniforms1, myGlobals)
1466
1467 # create descriptor sets
1468 #[
1469 var descriptorSets: array[INFLIGHTFRAMES.int, VkDescriptorSet]
1470 var layouts = newSeqWith(descriptorSets.len, pipeline.descriptorSetLayouts)
1471 var allocInfo = VkDescriptorSetAllocateInfo(
1472 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1473 descriptorPool: pool,
1474 descriptorSetCount: uint32(layouts.len),
1475 pSetLayouts: layouts.ToCPointer,
1476 )
1477 checkVkResult vkAllocateDescriptorSets(device, addr(allocInfo), descriptorSets.ToCPointer)
1478 ]#
1479
1480
1386 1481
1387 # command buffer 1482 # command buffer
1388 var 1483 var
1389 commandBufferPool: VkCommandPool 1484 commandBufferPool: VkCommandPool
1390 createInfo = VkCommandPoolCreateInfo( 1485 createInfo = VkCommandPoolCreateInfo(
1391 sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 1486 sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
1392 flags: toBits [VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT], 1487 flags: toBits [VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT],
1393 queueFamilyIndex: GetQueueFamily(dev.vk), 1488 queueFamilyIndex: vulkan.queueFamilyIndex,
1394 ) 1489 )
1395 checkVkResult vkCreateCommandPool(dev.vk, addr createInfo, nil, addr commandBufferPool) 1490 checkVkResult vkCreateCommandPool(vulkan.device, addr createInfo, nil, addr commandBufferPool)
1396 var 1491 var
1397 cmdBuffers: array[INFLIGHTFRAMES.int, VkCommandBuffer] 1492 cmdBuffers: array[INFLIGHTFRAMES.int, VkCommandBuffer]
1398 allocInfo = VkCommandBufferAllocateInfo( 1493 allocInfo = VkCommandBufferAllocateInfo(
1399 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 1494 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
1400 commandPool: commandBufferPool, 1495 commandPool: commandBufferPool,
1401 level: VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1496 level: VK_COMMAND_BUFFER_LEVEL_PRIMARY,
1402 commandBufferCount: INFLIGHTFRAMES, 1497 commandBufferCount: INFLIGHTFRAMES,
1403 ) 1498 )
1404 checkVkResult vkAllocateCommandBuffers(dev.vk, addr allocInfo, cmdBuffers.ToCPointer) 1499 checkVkResult vkAllocateCommandBuffers(vulkan.device, addr allocInfo, cmdBuffers.ToCPointer)
1405 1500
1406 # start command buffer 1501 # start command buffer
1407 block: 1502 block:
1408 let 1503 let
1409 currentFramebuffer = VkFramebuffer(0) # TODO 1504 currentFramebuffer = VkFramebuffer(0) # TODO
1441 ) 1536 )
1442 scissor = VkRect2D( 1537 scissor = VkRect2D(
1443 offset: VkOffset2D(x: 0, y: 0), 1538 offset: VkOffset2D(x: 0, y: 0),
1444 extent: VkExtent2D(width: frameWidth, height: frameHeight) 1539 extent: VkExtent2D(width: frameWidth, height: frameHeight)
1445 ) 1540 )
1446 checkVkResult vkCmdBeginRenderPass(cmd, addr(renderPassInfo), VK_SUBPASS_CONTENTS_INLINE) 1541 vkCmdBeginRenderPass(cmd, addr(renderPassInfo), VK_SUBPASS_CONTENTS_INLINE)
1447 1542
1448 # setup viewport 1543 # setup viewport
1449 vkCmdSetViewport(cmd, firstViewport = 0, viewportCount = 1, addr(viewport)) 1544 vkCmdSetViewport(cmd, firstViewport = 0, viewportCount = 1, addr(viewport))
1450 vkCmdSetScissor(cmd, firstScissor = 0, scissorCount = 1, addr(scissor)) 1545 vkCmdSetScissor(cmd, firstScissor = 0, scissorCount = 1, addr(scissor))
1451 1546