zworld-demo/engine/render/vulkan/instance/vulkan_help.go

203 lines
5.6 KiB
Go
Raw Normal View History

2024-01-08 22:01:42 +08:00
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"
2024-01-09 00:02:30 +08:00
"github.com/vkngwrapper/extensions/v2/khr_surface"
2024-01-08 22:01:42 +08:00
"zworld/engine/window"
)
2024-01-09 00:02:30 +08:00
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
}
2024-01-08 22:01:42 +08:00
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
}
2024-01-09 00:02:30 +08:00
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}
}