import vulkan as nvk , vkTypes , vulkan_record , vulkan_utils , ../utils/[lets , etc ] , bitops , strutils , vkTypes , swapchain , gpu , ../wain/waindow_object , dbg , device , semaphores , buffer import ../memory/[ utils ] const needed_validation_layers* = ["VK_LAYER_KHRONOS_validation"] proc check_validation_layers( ) = when defined windows: vkEnumerateInstanceLayerProperties = cast[proc( pPropertyCount: ptr uint32 , pProperties: ptr VkLayerProperties ): VkResult {.stdcall.}] (vkGetProcAddress("vkEnumerateInstanceLayerProperties")) var layer_count: uint32 = 0 discard vkEnumerateInstanceLayerProperties( addr layer_count , nil ) var layers = newSeq[VkLayerProperties] (layer_count) discard vkEnumerateInstanceLayerProperties( addr layer_count , addr layers[0] ) for validated_layer in needed_validation_layers: var found = false for layer in layers: if cstring(unsafeAddr layer.layerName) == validated_layer: found = true break if not found: echo validated_layer & " layer is not supported" proc create_vulkan_instance*(vulkan_record: var Vulkan_Record ) = var validationFeatureEnables: array[3, VkValidationFeatureEnableEXT] = [ VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT , VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT , VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT ] validationFeatures = VkValidationFeaturesEXT( sType: VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT , pNext: nil , enabledValidationFeatureCount: 3 , pEnabledValidationFeatures: addr validationFeatureEnables[0] , disabledValidationFeatureCount: 0 , pDisabledValidationFeatures: nil ) instance: VkInstance appInfo = newVkApplicationInfo( pApplicationName = "p0", applicationVersion = vkMakeVersion(1, 0, 0), pEngineName = "engine_p0", engineVersion = vkMakeVersion(1, 0, 0), apiVersion = vkApiVersion1_3 ) var exts = allocCStringArray(["VK_KHR_surface" , "VK_EXT_debug_utils" ] ) when defined linux: exts[2] = "VK_KHR_xcb_surface" when defined windows: exts[2] = "VK_KHR_win32_surface" var instanceCreateInfo = newVkInstanceCreateInfo( pApplicationInfo = appInfo.addr , enabledExtensionCount = 3 #TODO make dynamic , ppEnabledExtensionNames = exts #, enabledLayerCount = 0 #, ppEnabledLayerNames = val , pNext = addr validationFeatures ) vulkan_create_instance_result = vkCreateInstance( instanceCreateInfo.addr , nil , addr instance ) #echo repr vulkan_create_instance_result vulkan_record.instance = instance when defined windows: vkEnumerateInstanceExtensionProperties = cast[proc(pLayerName: cstring , pPropertyCount: ptr uint32 , pProperties: ptr VkExtensionProperties ): VkResult {.stdcall.}] (vkGetProcAddress("vkEnumerateInstanceExtensionProperties")) var extensionCount: uint32 = 0 discard vkEnumerateInstanceExtensionProperties( nil , extensionCount.addr , nil ) var extensions = newSeq[VkExtensionProperties] ( extensionCount ) discard vkEnumerateInstanceExtensionProperties( nil , extensionCount.addr , extensions[0].addr ) var debugUtilsMessenger: VkDebugUtilsMessengerEXT debugUtilsMessengerCI: VkDebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCI.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT debugUtilsMessengerCI.messageSeverity = VkDebugUtilsMessageSeverityFlagsEXT bitor( VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT.int , VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT.int , VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT.int) debugUtilsMessengerCI.messageType = VkDebugUtilsMessageTypeFlagsEXT bitor( VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT.int , VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT.int , VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT.int) debugUtilsMessengerCI.pfnUserCallback = debugUtilsMessengerCallback vkCreateDebugUtilsMessengerEXT = cast[proc(instance: VkInstance, pCreateInfo: ptr VkDebugUtilsMessengerCreateInfoEXT , pAllocator: ptr VkAllocationCallbacks , pMessenger: ptr VkDebugUtilsMessengerEXT ): VkResult {.stdcall.}] (vkGetInstanceProcAddr(vulkan_record.instance, "vkCreateDebugUtilsMessengerEXT")) discard vkCreateDebugUtilsMessengerEXT(vulkan_record.instance, addr debugUtilsMessengerCI, nil, addr debugUtilsMessenger) proc load_vulkan_device_extensions( instance: VkInstance , device: VkDevice ) = vkGetDeviceProcAddr = cast[proc(device: VkDevice, pName: cstring ): PFN_vkVoidFunction {.stdcall.}] ( vkGetInstanceProcAddr( instance , "vkGetDeviceProcAddr" ) ) vkCreateBuffer = cast[ proc( device: VkDevice , pCreateInfo: ptr VkBufferCreateInfo , pAllocator: ptr VkAllocationCallbacks , pBuffer: ptr VkBuffer ): VkResult {.stdcall.} ] (vkGetDeviceProcAddr( device , "vkCreateBuffer" ) ) vkGetBufferMemoryRequirements =cast[ proc(device: VkDevice , buffer: VkBuffer , pMemoryRequirements: ptr VkMemoryRequirements ): void {.stdcall.}] ((vkGetDeviceProcAddr( device , "vkGetBufferMemoryRequirements" ) )) vkBindBufferMemory = cast[proc(device: VkDevice, buffer: VkBuffer, memory: VkDeviceMemory, memoryOffset: VkDeviceSize): VkResult {.stdcall.}] (vkGetDeviceProcAddr( device , "vkBindBufferMemory" )) proc setup_vulkan*( wain: var Waindow ): Vulkan_Record = result = Vulkan_Record( swapchain: Swapchain() ) vkLoad1_0() result.create_vulkan_instance() echo "Created vulkan_instance!" loadVK_KHR_surface(result.instance) loadVK_KHR_swapchain(result.instance) result.gpu = result.instance.get_gpu result.gpu.handle.getSupportedDepthFormat result.swapchain.depthFormat result.createLogicalDevice result.vk_device = result.logical_device load_vulkan_device_extensions(result.instance , result.vk_device ) #result.current_descriptor_pool = create_descriptor_pool( result.vk_device ) when defined windows: vkGetDeviceQueue = cast[proc(device: VkDevice, queueFamilyIndex: uint32, queueIndex: uint32, pQueue: ptr VkQueue ): void {.stdcall.}] (vkGetInstanceProcAddr(result.instance , "vkGetDeviceQueue" ) ) #TODO: properly check and set default(?) q index for the family vkGetDeviceQueue( result.vk_device , result.qfi.graphics , 0 , addr result.queue ) #TODO: put this in a function when defined linux: vkCreateXcbSurfaceKHR = cast[proc(instance: VkInstance, pCreateInfo: ptr VkXcbSurfaceCreateInfoKHR , pAllocator: ptr VkAllocationCallbacks , pSurface: ptr VkSurfaceKHR ): VkResult {.stdcall.}](vkGetProc("vkCreateXcbSurfaceKHR")) vkGetPhysicalDeviceXcbPresentationSupportKHR = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, connection: ptr xcb_connection_t , visual_id: xcb_visualid_t): VkBool32 {.stdcall.}](vkGetProc("vkGetPhysicalDeviceXcbPresentationSupportKHR")) var surfaceCreateInfo: VkXcbSurfaceCreateInfoKHR surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR surfaceCreateInfo.connection = cast[ptr nvk.xcb_connection_t](wain.conn) surfaceCreateInfo.window = cast[nvk.xcb_window_t](wain.window) var surface_res = vkCreateXcbSurfaceKHR( result.instance , addr surfaceCreateInfo , nil , addr result.swapchain.surface ) assert surface_res == VK_SUCCESS, "surface_res failed: " & $surface_res when defined windows: vkCreateWin32SurfaceKHR = cast[proc(instance: VkInstance, pCreateInfo: ptr VkWin32SurfaceCreateInfoKHR , pAllocator: ptr VkAllocationCallbacks , pSurface: ptr VkSurfaceKHR ): VkResult {.stdcall.}] (vkGetInstanceProcAddr(result.instance , "vkCreateWin32SurfaceKHR" ) ) vkGetPhysicalDeviceWin32PresentationSupportKHR = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32): VkBool32 {.stdcall.}] (vkGetInstanceProcAddr(result.instance , "vkGetPhysicalDeviceWin32PresentationSupportKHR" ) ) var surfaceCreateInfo: VkWin32SurfaceCreateInfoKHR surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR surfaceCreateInfo.hinstance = cast[nvk.HINSTANCE] ( addr wain.h_instance ) surfaceCreateInfo.hwnd = cast[nvk.HWND] (wain.hwnd) var surface_res = vkCreateWin32SurfaceKHR( result.instance , addr surfaceCreateInfo , nil , addr result.swapchain.surface ) assert surface_res == VK_SUCCESS, "ERROR: vkCreateWin32SurfaceKHR is: " & $surface_res result.gpu.handle.check_surface_support( result.swapchain , result.qni , result.instance ) create_swapchain( result.vk_device , result.swapchain , result.gpu.handle , result.current_viewport ) #TODO: actually properly check device extensions exist on the used GPU result.gpu.handle.check_gpu_extensions result.create_logical_command_pool result.draw_command_buffers = result.vk_device.create_command_buffers( result.command_pool ) result.master_vertex_buffer = a_vulkan_buffer( result.vk_device , result.gpu.memory_properties , VkBufferUsageFlags bitor( VK_BUFFER_USAGE_VERTEX_BUFFER_BIT.ord , VK_BUFFER_USAGE_TRANSFER_DST_BIT.ord ) , VkMemoryPropertyFlags VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT , MiB_vkds(256) ) result.master_index_buffer = a_vulkan_buffer( result.vk_device , result.gpu.memory_properties , VkBufferUsageFlags bitor( VK_BUFFER_USAGE_INDEX_BUFFER_BIT.ord , VK_BUFFER_USAGE_TRANSFER_DST_BIT.ord ) , VkMemoryPropertyFlags VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT , MiB_vkds(128) ) result.master_uniform_buffer = a_vulkan_buffer( result.vk_device , result.gpu.memory_properties , VkBufferUsageFlags VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT , VkMemoryPropertyFlags ( VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT.ord or VK_MEMORY_PROPERTY_HOST_COHERENT_BIT.ord ) , MiB_vkds(256) ) #[ result.master_vertex_buffer = a_vulkan_buffer( result.vk_device , result.gpu.memory_properties , VkBufferUsageFlags bitor( VK_BUFFER_USAGE_VERTEX_BUFFER_BIT.ord , VK_BUFFER_USAGE_TRANSFER_DST_BIT.ord ) , VkMemoryPropertyFlags VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT , MiB_vkds(256) ) ]# #[ master_index_buffer = a_vulkan_buffer( ) master_uniform_buffer = a_vulkan_buffer( ) ]# proc suballocate_vertex_buffer*( vulkan_record: var Vulkan_Record , vertex_data: pointer ) = copymem( vertex_data , addr vulkan_record.master_vertex_buffer.data[vulkan_record.master_vertex_buffer.current_data_offset] , Natural vertex_data.sizeof ) # memcpy( &dst[dstIdx], &src[srcIdx], numElementsToCopy * sizeof( Element ) ); vulkan_record.master_vertex_buffer.current_data_offset += vertex_data.sizeof proc suballocate_index_buffer*( vulkan_record: var Vulkan_Record , index_data: pointer ) = copymem( index_data , addr vulkan_record.master_index_buffer.data[vulkan_record.master_index_buffer.current_data_offset] , Natural index_data.sizeof ) # memcpy( &dst[dstIdx], &src[srcIdx], numElementsToCopy * sizeof( Element ) ); vulkan_record.master_index_buffer.current_data_offset += index_data.sizeof proc suballocate_uniform_buffer*( vulkan_record: var Vulkan_Record , uniform_buffer_data: pointer ) = # memcpy( &dst[dstIdx], &src[srcIdx], numElementsToCopy * sizeof( Element ) ); copyMem( uniform_buffer_data , addr vulkan_record.master_uniform_buffer.data[vulkan_record.master_uniform_buffer.current_data_offset] , sizeof uniform_buffer_data ) vulkan_record.master_uniform_buffer.current_data_offset += uniform_buffer_data.sizeof