package instance import ( "github.com/vkngwrapper/core/v2" "github.com/vkngwrapper/core/v2/core1_0" "github.com/vkngwrapper/extensions/v2/ext_debug_utils" "github.com/vkngwrapper/extensions/v2/khr_portability_enumeration" "github.com/vkngwrapper/extensions/v2/khr_surface" "zworld/engine/window" ) type FVulkanHelp struct { vulkan *FInstance } type QueueFamilyIndices struct { GraphicsFamily *int PresentFamily *int } func (i *QueueFamilyIndices) IsComplete() bool { return i.GraphicsFamily != nil && i.PresentFamily != nil } type SwapChainSupportDetails struct { Capabilities *khr_surface.SurfaceCapabilities Formats []khr_surface.SurfaceFormat PresentModes []khr_surface.PresentMode } func (h *FVulkanHelp) getCreateInstanceExtension(instanceOptions *core1_0.InstanceCreateInfo, loader *core.VulkanLoader, win *window.FSDLWindow) error { // Add extensions sdlExtensions := win.GetInstance().VulkanGetInstanceExtensions() extensions, _, err := loader.AvailableExtensions() if err != nil { return err } for _, ext := range sdlExtensions { _, hasExt := extensions[ext] if !hasExt { return nil } instanceOptions.EnabledExtensionNames = append(instanceOptions.EnabledExtensionNames, ext) } if enableValidationLayers { instanceOptions.EnabledExtensionNames = append(instanceOptions.EnabledExtensionNames, ext_debug_utils.ExtensionName) } _, enumerationSupported := extensions[khr_portability_enumeration.ExtensionName] if enumerationSupported { instanceOptions.EnabledExtensionNames = append(instanceOptions.EnabledExtensionNames, khr_portability_enumeration.ExtensionName) instanceOptions.Flags |= khr_portability_enumeration.InstanceCreateEnumeratePortability } return nil } func (h *FVulkanHelp) getCreateInstanceLayer(instanceOptions *core1_0.InstanceCreateInfo, loader *core.VulkanLoader, win *window.FSDLWindow) error { // Add extensions layers, _, err := loader.AvailableLayers() if err != nil { return err } if enableValidationLayers { for _, layer := range validationLayers { _, hasValidation := layers[layer] if !hasValidation { return nil } instanceOptions.EnabledLayerNames = append(instanceOptions.EnabledLayerNames, layer) } } return nil } func (h *FVulkanHelp) findQueueFamilies(device core1_0.PhysicalDevice) (QueueFamilyIndices, error) { indices := QueueFamilyIndices{} e := h.vulkan queueFamilies := device.QueueFamilyProperties() for queueFamilyIdx, queueFamily := range queueFamilies { if (queueFamily.QueueFlags & core1_0.QueueGraphics) != 0 { indices.GraphicsFamily = new(int) *indices.GraphicsFamily = queueFamilyIdx } supported, _, err := e.surface.PhysicalDeviceSurfaceSupport(device, queueFamilyIdx) if err != nil { return indices, err } if supported { indices.PresentFamily = new(int) *indices.PresentFamily = queueFamilyIdx } if indices.IsComplete() { break } } return indices, nil } func (h *FVulkanHelp) checkDeviceExtensionSupport(device core1_0.PhysicalDevice) bool { extensions, _, err := device.EnumerateDeviceExtensionProperties() if err != nil { return false } for _, extension := range deviceExtensions { _, hasExtension := extensions[extension] if !hasExtension { return false } } return true } func (h *FVulkanHelp) querySwapChainSupport(device core1_0.PhysicalDevice) (SwapChainSupportDetails, error) { e := h.vulkan var details SwapChainSupportDetails var err error details.Capabilities, _, err = e.surface.PhysicalDeviceSurfaceCapabilities(device) if err != nil { return details, err } details.Formats, _, err = e.surface.PhysicalDeviceSurfaceFormats(device) if err != nil { return details, err } details.PresentModes, _, err = e.surface.PhysicalDeviceSurfacePresentModes(device) return details, err } func (h *FVulkanHelp) isDeviceSuitable(device core1_0.PhysicalDevice) bool { indices, err := h.findQueueFamilies(device) if err != nil { return false } extensionsSupported := h.checkDeviceExtensionSupport(device) var swapChainAdequate bool if extensionsSupported { swapChainSupport, err := h.querySwapChainSupport(device) if err != nil { return false } swapChainAdequate = len(swapChainSupport.Formats) > 0 && len(swapChainSupport.PresentModes) > 0 } return indices.IsComplete() && extensionsSupported && swapChainAdequate } func (h *FVulkanHelp) chooseSwapSurfaceFormat(availableFormats []khr_surface.SurfaceFormat) khr_surface.SurfaceFormat { for _, format := range availableFormats { if format.Format == core1_0.FormatB8G8R8A8SRGB && format.ColorSpace == khr_surface.ColorSpaceSRGBNonlinear { return format } } return availableFormats[0] } func (h *FVulkanHelp) chooseSwapPresentMode(availablePresentModes []khr_surface.PresentMode) khr_surface.PresentMode { for _, presentMode := range availablePresentModes { if presentMode == khr_surface.PresentModeMailbox { return presentMode } } return khr_surface.PresentModeFIFO } func (h *FVulkanHelp) chooseSwapExtent(capabilities *khr_surface.SurfaceCapabilities) core1_0.Extent2D { if capabilities.CurrentExtent.Width != -1 { return capabilities.CurrentExtent } e := h.vulkan widthInt, heightInt := e.win.GetInstance().VulkanGetDrawableSize() width := int(widthInt) height := int(heightInt) if width < capabilities.MinImageExtent.Width { width = capabilities.MinImageExtent.Width } if width > capabilities.MaxImageExtent.Width { width = capabilities.MaxImageExtent.Width } if height < capabilities.MinImageExtent.Height { height = capabilities.MinImageExtent.Height } if height > capabilities.MaxImageExtent.Height { height = capabilities.MaxImageExtent.Height } return core1_0.Extent2D{Width: width, Height: height} }