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

201 lines
5.3 KiB
Go
Raw Normal View History

2024-01-09 00:02:30 +08:00
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
}