comparison svk/api.nim @ 1490:81da4be50663 default tip

did: some stuff
author sam <sam@basx.dev>
date Fri, 23 May 2025 23:42:19 +0700
parents e6bd1f553c1b
children
comparison
equal deleted inserted replaced
1489:e6bd1f553c1b 1490:81da4be50663
56 when defined(windows): 56 when defined(windows):
57 type NativeWindow* = object 57 type NativeWindow* = object
58 hinstance*: HINSTANCE 58 hinstance*: HINSTANCE
59 hwnd*: HWND 59 hwnd*: HWND
60 g_wpPrev*: WINDOWPLACEMENT 60 g_wpPrev*: WINDOWPLACEMENT
61
61 else: 62 else:
62 type NativeWindow* = object 63 type NativeWindow* = object
63 display*: ptr Display 64 display*: ptr Display
64 window*: Window 65 window*: Window
65 emptyCursor*: Cursor 66 emptyCursor*: Cursor
66 ic*: XIC 67 ic*: XIC
67
68
69
70 68
71 # ============================================================================= 69 # =============================================================================
72 # VULKAN INSTANCE ============================================================= 70 # VULKAN INSTANCE =============================================================
73 # ============================================================================= 71 # =============================================================================
74 72
174 var allTypes: VkDebugUtilsMessageTypeFlagsEXT 172 var allTypes: VkDebugUtilsMessageTypeFlagsEXT
175 for t in VkDebugUtilsMessageTypeFlagBitsEXT: 173 for t in VkDebugUtilsMessageTypeFlagBitsEXT:
176 allTypes = allTypes or t 174 allTypes = allTypes or t
177 when not defined(release): 175 when not defined(release):
178 var debugMessengerCreateInfo = VkDebugUtilsMessengerCreateInfoEXT( 176 var debugMessengerCreateInfo = VkDebugUtilsMessengerCreateInfoEXT(
179 messageSeverity: VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT or VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT or VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT or VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 177 messageSeverity:
180 messageType: VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT or VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT or VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, 178 VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT or
179 VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT or
180 VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT or
181 VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
182 messageType:
183 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT or
184 VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT or
185 VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
181 pfnUserCallback: debugCallback, 186 pfnUserCallback: debugCallback,
182 ) 187 )
183 checkVkResult vkCreateDebugUtilsMessengerEXT( 188 checkVkResult vkCreateDebugUtilsMessengerEXT(
184 result.vkInstance, addr debugMessengerCreateInfo, nil, addr result.debugMessenger 189 result.vkInstance, addr debugMessengerCreateInfo, nil, addr result.debugMessenger
185 ) 190 )
186 191
187
188 result.window = createWindow(applicationName) 192 result.window = createWindow(applicationName)
189 when defined(windows): 193 when defined(windows):
190 var surfaceCreateInfo = VkWin32SurfaceCreateInfoKHR(hinstance: window.hinstance, hwnd: window.hwnd) 194 var surfaceCreateInfo =
191 checkVkResult vkCreateWin32SurfaceKHR(instance, addr surfaceCreateInfo, nil, addr result.vkSurface) 195 VkWin32SurfaceCreateInfoKHR(hinstance: window.hinstance, hwnd: window.hwnd)
196 checkVkResult vkCreateWin32SurfaceKHR(
197 instance, addr surfaceCreateInfo, nil, addr result.vkSurface
198 )
192 else: 199 else:
193 var surfaceCreateInfo = VkXlibSurfaceCreateInfoKHR(dpy: result.window.display, window: result.window.window) 200 var surfaceCreateInfo = VkXlibSurfaceCreateInfoKHR(
194 checkVkResult result.vkInstance.vkCreateXlibSurfaceKHR(addr surfaceCreateInfo, nil, addr result.vkSurface) 201 dpy: result.window.display, window: result.window.window
195 202 )
196 203 checkVkResult result.vkInstance.vkCreateXlibSurfaceKHR(
204 addr surfaceCreateInfo, nil, addr result.vkSurface
205 )
197 206
198 # ============================================================================= 207 # =============================================================================
199 # PHYSICAL DEVICES ============================================================ 208 # PHYSICAL DEVICES ============================================================
200 # ============================================================================= 209 # =============================================================================
201 210
203 SVkMemoryType* = object 212 SVkMemoryType* = object
204 size: uint64 213 size: uint64
205 deviceLocal: bool # fast for gpu access 214 deviceLocal: bool # fast for gpu access
206 hostCached: bool # fast for host access 215 hostCached: bool # fast for host access
207 hostVisible: bool # can use vkMapMemory 216 hostVisible: bool # can use vkMapMemory
208 hostCohorent: bool # does *not* require vkFlushMappedMemoryRanges and vkInvalidateMappedMemoryRanges 217 hostCohorent: bool
218 # does *not* require vkFlushMappedMemoryRanges and vkInvalidateMappedMemoryRanges
219
209 SVkQueueFamilies* = object 220 SVkQueueFamilies* = object
210 count: int 221 count: int
211 hasGraphics: bool # implies "hasTransfer" 222 hasGraphics: bool # implies "hasTransfer"
212 hasCompute: bool # implies "hasTransfer" 223 hasCompute: bool # implies "hasTransfer"
213 224
214 SVkPhysicalDevice* = object 225 SVkPhysicalDevice* = object
215 name*: string 226 name*: string
227 discreteGPU*: bool
216 vkPhysicalDevice*: VkPhysicalDevice 228 vkPhysicalDevice*: VkPhysicalDevice
217 vkPhysicalDeviceFeatures*: VkPhysicalDeviceFeatures 229 vkPhysicalDeviceFeatures*: VkPhysicalDeviceFeatures
218 vkPhysicalDeviceProperties*: VkPhysicalDeviceProperties 230 vkPhysicalDeviceProperties*: VkPhysicalDeviceProperties
219 memoryTypes*: seq[SVkMemoryType] 231 memoryTypes*: seq[SVkMemoryType]
220 queueFamily*: uint32 232 queueFamily*: uint32
221 233
222 proc getUsablePhysicalDevices*(instance: SVkInstance): seq[SVkPhysicalDevice] = 234 proc getUsablePhysicalDevices*(instance: SVkInstance): seq[SVkPhysicalDevice] =
223 var nDevices: uint32 235 var nDevices: uint32
224 checkVkResult instance.vkInstance.vkEnumeratePhysicalDevices(addr nDevices, nil) 236 checkVkResult instance.vkInstance.vkEnumeratePhysicalDevices(addr nDevices, nil)
225 var devices = newSeq[VkPhysicalDevice](nDevices) 237 var devices = newSeq[VkPhysicalDevice](nDevices)
226 checkVkResult instance.vkInstance.vkEnumeratePhysicalDevices(addr nDevices, addr devices[0]) 238 checkVkResult instance.vkInstance.vkEnumeratePhysicalDevices(
239 addr nDevices, addr devices[0]
240 )
227 for d in devices: 241 for d in devices:
228 var dev = SVkPhysicalDevice(vkPhysicalDevice: d) 242 var dev = SVkPhysicalDevice(vkPhysicalDevice: d)
229 d.vkGetPhysicalDeviceFeatures(addr dev.vkPhysicalDeviceFeatures) 243 d.vkGetPhysicalDeviceFeatures(addr dev.vkPhysicalDeviceFeatures)
230 d.vkGetPhysicalDeviceProperties(addr dev.vkPhysicalDeviceProperties) 244 d.vkGetPhysicalDeviceProperties(addr dev.vkPhysicalDeviceProperties)
231 245
232 if dev.vkPhysicalDeviceProperties.deviceType notin [VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU]: 246 if dev.vkPhysicalDeviceProperties.deviceType notin
247 [VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU]:
233 continue 248 continue
234 dev.name = $cast[cstring](addr dev.vkPhysicalDeviceProperties.deviceName[0]) 249 dev.name = $cast[cstring](addr dev.vkPhysicalDeviceProperties.deviceName[0])
250 dev.discreteGPU =
251 dev.vkPhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
235 252
236 var memoryProperties: VkPhysicalDeviceMemoryProperties 253 var memoryProperties: VkPhysicalDeviceMemoryProperties
237 d.vkGetPhysicalDeviceMemoryProperties(addr memoryProperties) 254 d.vkGetPhysicalDeviceMemoryProperties(addr memoryProperties)
238 for i in 0 ..< memoryProperties.memoryTypeCount: 255 for i in 0 ..< memoryProperties.memoryTypeCount:
239 let heapI = memoryProperties.memoryTypes[i].heapIndex 256 let heapI = memoryProperties.memoryTypes[i].heapIndex
240 dev.memoryTypes.add SVkMemoryType( 257 dev.memoryTypes.add SVkMemoryType(
241 size: memoryProperties.memoryHeaps[heapI].size.uint64, 258 size: memoryProperties.memoryHeaps[heapI].size.uint64,
242 deviceLocal: VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT in memoryProperties.memoryTypes[i].propertyFlags, 259 deviceLocal:
243 hostCached: VK_MEMORY_PROPERTY_HOST_CACHED_BIT in memoryProperties.memoryTypes[i].propertyFlags, 260 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT in
244 hostVisible: VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in memoryProperties.memoryTypes[i].propertyFlags, 261 memoryProperties.memoryTypes[i].propertyFlags,
245 hostCohorent: VK_MEMORY_PROPERTY_HOST_COHERENT_BIT in memoryProperties.memoryTypes[i].propertyFlags, 262 hostCached:
263 VK_MEMORY_PROPERTY_HOST_CACHED_BIT in
264 memoryProperties.memoryTypes[i].propertyFlags,
265 hostVisible:
266 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in
267 memoryProperties.memoryTypes[i].propertyFlags,
268 hostCohorent:
269 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT in
270 memoryProperties.memoryTypes[i].propertyFlags,
246 ) 271 )
247
248 272
249 var familyQueueCount: uint32 273 var familyQueueCount: uint32
250 var vkQueueFamilyProperties: seq[VkQueueFamilyProperties] 274 var vkQueueFamilyProperties: seq[VkQueueFamilyProperties]
251 d.vkGetPhysicalDeviceQueueFamilyProperties(addr familyQueueCount, nil) 275 d.vkGetPhysicalDeviceQueueFamilyProperties(addr familyQueueCount, nil)
252 vkQueueFamilyProperties.setLen(familyQueueCount) 276 vkQueueFamilyProperties.setLen(familyQueueCount)
253 d.vkGetPhysicalDeviceQueueFamilyProperties(addr familyQueueCount, addr vkQueueFamilyProperties[0]) 277 d.vkGetPhysicalDeviceQueueFamilyProperties(
278 addr familyQueueCount, addr vkQueueFamilyProperties[0]
279 )
254 dev.queueFamily = high(uint32) 280 dev.queueFamily = high(uint32)
255 for i in 0 ..< familyQueueCount: 281 for i in 0 ..< familyQueueCount:
256 let hasGraphics = VK_QUEUE_GRAPHICS_BIT in vkQueueFamilyProperties[i].queueFlags 282 let hasGraphics = VK_QUEUE_GRAPHICS_BIT in vkQueueFamilyProperties[i].queueFlags
257 let hasCompute = VK_QUEUE_COMPUTE_BIT in vkQueueFamilyProperties[i].queueFlags 283 let hasCompute = VK_QUEUE_COMPUTE_BIT in vkQueueFamilyProperties[i].queueFlags
258 let hasPresentation = VK_FALSE 284 let hasPresentation = VK_FALSE
259 checkVkResult dev.vkPhysicalDevice.vkGetPhysicalDeviceSurfaceSupportKHR(i, instance.vkSurface, addr hasPresentation) 285 checkVkResult dev.vkPhysicalDevice.vkGetPhysicalDeviceSurfaceSupportKHR(
286 i, instance.vkSurface, addr hasPresentation
287 )
260 288
261 if hasGraphics and hasCompute and bool(hasPresentation): 289 if hasGraphics and hasCompute and bool(hasPresentation):
262 dev.queueFamily = i 290 dev.queueFamily = i
263 break 291 break
264 if dev.queueFamily == high(uint32): 292 if dev.queueFamily == high(uint32):
265 raise newException(Exception, "Did not find queue family with graphics and compute support!") 293 raise newException(
294 Exception,
295 "Did not find queue family with graphics, compute and presentation support!",
296 )
266 297
267 result.add dev 298 result.add dev
299
300 # =============================================================================
301 # DEVICES =====================================================================
302 # =============================================================================
303
304 type SVkDevice* = object
305 vkDevice: VkDevice
306 vkQueue: VkQueue
307
308 proc `=copy`(a: var SVkDevice, b: SVkDevice) {.error.}
309
310 proc `=destroy`(a: SVkDevice) =
311 debugAssert a.vkDevice.pointer == nil
312 debugAssert a.vkQueue.pointer == nil
313
314 proc destroy*(a: var SVkDevice) =
315 if a.vkDevice.pointer != nil:
316 vkDestroyDevice(a.vkDevice, nil)
317 a.vkDevice = VkDevice(nil)
318 a.vkQueue = VkQueue(nil)
319
320 proc svkCreateDevice*(
321 instance: SVkInstance, physicalDevice: SVkPhysicalDevice
322 ): SVkDevice =
323 let
324 priority = cfloat(1)
325 queueInfo = VkDeviceQueueCreateInfo(
326 queueFamilyIndex: physicalDevice.queueFamily,
327 queueCount: 1,
328 pQueuePriorities: addr priority,
329 )
330 deviceExtensions = @["VK_KHR_swapchain"]
331 deviceExtensionsC = allocCStringArray(deviceExtensions)
332 enabledFeatures = VkPhysicalDeviceFeatures(
333 fillModeNonSolid: VK_TRUE,
334 depthClamp: VK_TRUE,
335 wideLines: VK_TRUE,
336 largePoints: VK_TRUE,
337 )
338 vk8bitExt = VkPhysicalDevice8BitStorageFeatures(
339 storageBuffer8BitAccess: VK_TRUE,
340 uniformAndStorageBuffer8BitAccess: VK_TRUE,
341 storagePushConstant8: VK_TRUE,
342 )
343 vk16bitExt = VkPhysicalDevice16BitStorageFeatures(
344 storageBuffer16BitAccess: VK_TRUE,
345 uniformAndStorageBuffer16BitAccess: VK_TRUE,
346 storagePushConstant16: VK_TRUE,
347 storageInputOutput16: VK_FALSE,
348 pNext: addr vk8bitExt,
349 )
350 createDeviceInfo = VkDeviceCreateInfo(
351 queueCreateInfoCount: 1,
352 pQueueCreateInfos: addr queueInfo,
353 enabledLayerCount: 0,
354 ppEnabledLayerNames: nil,
355 enabledExtensionCount: 1,
356 ppEnabledExtensionNames: deviceExtensionsC,
357 pEnabledFeatures: addr enabledFeatures,
358 pNext: addr vk16bitExt,
359 )
360 checkVkResult vkCreateDevice(
361 physicalDevice = physicalDevice.vkPhysicalDevice,
362 pCreateInfo = addr createDeviceInfo,
363 pAllocator = nil,
364 pDevice = addr result.vkDevice,
365 )
366 deviceExtensionsC.deallocCStringArray()
367 result.vkDevice.vkGetDeviceQueue(physicalDevice.queueFamily, 0, addr result.vkQueue)
368
369 # =============================================================================
370 # PLATFORM UTILS ==============================================================
371 # =============================================================================
268 372
269 when defined(windows): 373 when defined(windows):
270 proc createWindow(title: string): NativeWindow = 374 proc createWindow(title: string): NativeWindow =
271 result.hInstance = HINSTANCE(GetModuleHandle(nil)) 375 result.hInstance = HINSTANCE(GetModuleHandle(nil))
272 var 376 var
333 doAssert display.XGetWindowAttributes(rootWindow, addr(attribs)) != 0 437 doAssert display.XGetWindowAttributes(rootWindow, addr(attribs)) != 0
334 438
335 var attrs = XSetWindowAttributes( 439 var attrs = XSetWindowAttributes(
336 event_mask: 440 event_mask:
337 FocusChangeMask or KeyPressMask or KeyReleaseMask or ExposureMask or 441 FocusChangeMask or KeyPressMask or KeyReleaseMask or ExposureMask or
338 VisibilityChangeMask or StructureNotifyMask or ButtonMotionMask or ButtonPressMask or 442 VisibilityChangeMask or StructureNotifyMask or ButtonMotionMask or
339 ButtonReleaseMask 443 ButtonPressMask or ButtonReleaseMask
340 ) 444 )
341 let window = display.XCreateWindow( 445 let window = display.XCreateWindow(
342 rootWindow, 446 rootWindow,
343 (attribs.width - cint(width)) div 2, 447 (attribs.width - cint(width)) div 2,
344 (attribs.height - cint(height)) div 2, 448 (attribs.height - cint(height)) div 2,
376 # wait until window is shown 480 # wait until window is shown
377 var ev: XEvent 481 var ev: XEvent
378 while ev.theType != MapNotify: 482 while ev.theType != MapNotify:
379 discard display.XNextEvent(addr(ev)) 483 discard display.XNextEvent(addr(ev))
380 484
381 result = NativeWindow(display: display, window: window, emptyCursor: empty_cursor, ic: ic) 485 result =
486 NativeWindow(display: display, window: window, emptyCursor: empty_cursor, ic: ic)
382 487
383 proc destroyWindow*(window: NativeWindow) = 488 proc destroyWindow*(window: NativeWindow) =
384 doAssert XDestroyWindow(window.display, window.window) != 0 489 doAssert XDestroyWindow(window.display, window.window) != 0
385