package instance import ( "github.com/pkg/errors" "github.com/vkngwrapper/core/v2/core1_0" "github.com/vkngwrapper/extensions/v2/khr_portability_subset" "github.com/vkngwrapper/extensions/v2/khr_surface" "github.com/vkngwrapper/extensions/v2/khr_swapchain" vkng_sdl2 "github.com/vkngwrapper/integrations/sdl2/v2" ) func (e *FInstance) createSurface() error { surfaceLoader := khr_surface.CreateExtensionFromInstance(e.ptr) surface, err := vkng_sdl2.CreateSurface(e.ptr, surfaceLoader, e.win.GetInstance()) if err != nil { return err } e.surface = surface return nil } func (e *FInstance) pickPhysicalDevice() error { physicalDevices, _, err := e.ptr.EnumeratePhysicalDevices() if err != nil { return err } for _, device := range physicalDevices { if help.isDeviceSuitable(device) { e.physicalDevice = device break } } if e.physicalDevice == nil { return errors.New("failed to find a suitable GPU!") } return nil } func (e *FInstance) createLogicalDevice() error { indices, err := help.findQueueFamilies(e.physicalDevice) if err != nil { return err } uniqueQueueFamilies := []int{*indices.GraphicsFamily} if uniqueQueueFamilies[0] != *indices.PresentFamily { uniqueQueueFamilies = append(uniqueQueueFamilies, *indices.PresentFamily) } var queueFamilyOptions []core1_0.DeviceQueueCreateInfo queuePriority := float32(1.0) for _, queueFamily := range uniqueQueueFamilies { queueFamilyOptions = append(queueFamilyOptions, core1_0.DeviceQueueCreateInfo{ QueueFamilyIndex: queueFamily, QueuePriorities: []float32{queuePriority}, }) } var extensionNames []string extensionNames = append(extensionNames, deviceExtensions...) // Makes this example compatible with vulkan portability, necessary to run on mobile & mac extensions, _, err := e.physicalDevice.EnumerateDeviceExtensionProperties() if err != nil { return err } _, supported := extensions[khr_portability_subset.ExtensionName] if supported { extensionNames = append(extensionNames, khr_portability_subset.ExtensionName) } e.device, _, err = e.physicalDevice.CreateDevice(nil, core1_0.DeviceCreateInfo{ QueueCreateInfos: queueFamilyOptions, EnabledFeatures: &core1_0.PhysicalDeviceFeatures{}, EnabledExtensionNames: extensionNames, }) if err != nil { return err } e.graphicsQueue = e.device.GetQueue(*indices.GraphicsFamily, 0) e.presentQueue = e.device.GetQueue(*indices.PresentFamily, 0) return nil } func (e *FInstance) createSwapchain() error { e.swapchainExtension = khr_swapchain.CreateExtensionFromDevice(e.device) swapchainSupport, err := help.querySwapChainSupport(e.physicalDevice) if err != nil { return err } surfaceFormat := help.chooseSwapSurfaceFormat(swapchainSupport.Formats) presentMode := help.chooseSwapPresentMode(swapchainSupport.PresentModes) extent := help.chooseSwapExtent(swapchainSupport.Capabilities) imageCount := swapchainSupport.Capabilities.MinImageCount + 1 if swapchainSupport.Capabilities.MaxImageCount > 0 && swapchainSupport.Capabilities.MaxImageCount < imageCount { imageCount = swapchainSupport.Capabilities.MaxImageCount } sharingMode := core1_0.SharingModeExclusive var queueFamilyIndices []int indices, err := help.findQueueFamilies(e.physicalDevice) if err != nil { return err } if *indices.GraphicsFamily != *indices.PresentFamily { sharingMode = core1_0.SharingModeConcurrent queueFamilyIndices = append(queueFamilyIndices, *indices.GraphicsFamily, *indices.PresentFamily) } swapchain, _, err := e.swapchainExtension.CreateSwapchain(e.device, nil, khr_swapchain.SwapchainCreateInfo{ Surface: e.surface, MinImageCount: imageCount, ImageFormat: surfaceFormat.Format, ImageColorSpace: surfaceFormat.ColorSpace, ImageExtent: extent, ImageArrayLayers: 1, ImageUsage: core1_0.ImageUsageColorAttachment, ImageSharingMode: sharingMode, QueueFamilyIndices: queueFamilyIndices, PreTransform: swapchainSupport.Capabilities.CurrentTransform, CompositeAlpha: khr_surface.CompositeAlphaOpaque, PresentMode: presentMode, Clipped: true, }) if err != nil { return err } e.swapchainExtent = extent e.swapchain = swapchain e.swapchainImageFormat = surfaceFormat.Format images, _, err := swapchain.SwapchainImages() if err != nil { return err } e.swapchainImages = images var imageViews []core1_0.ImageView for _, image := range images { view, _, err := e.device.CreateImageView(nil, core1_0.ImageViewCreateInfo{ ViewType: core1_0.ImageViewType2D, Image: image, Format: surfaceFormat.Format, Components: core1_0.ComponentMapping{ R: core1_0.ComponentSwizzleIdentity, G: core1_0.ComponentSwizzleIdentity, B: core1_0.ComponentSwizzleIdentity, A: core1_0.ComponentSwizzleIdentity, }, SubresourceRange: core1_0.ImageSubresourceRange{ AspectMask: core1_0.ImageAspectColor, BaseMipLevel: 0, LevelCount: 1, BaseArrayLayer: 0, LayerCount: 1, }, }) if err != nil { return err } imageViews = append(imageViews, view) } e.swapchainImageViews = imageViews return nil } func (e *FInstance) Init() error { help.vulkan = e err := e.createSurface() if err != nil { return err } err = e.pickPhysicalDevice() if err != nil { return err } err = e.createLogicalDevice() if err != nil { return err } err = e.createSwapchain() if err != nil { return err } return nil }