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