203 lines
5.6 KiB
Go
203 lines
5.6 KiB
Go
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}
|
|
}
|