From 97d08a7a0cfd1398548b901c9cab96c8a7a6c50d Mon Sep 17 00:00:00 2001 From: Marvin Blum Date: Sun, 6 Jun 2021 23:45:52 +0200 Subject: [PATCH] Started adding swap chain and fixing bugs... --- 01_Simple_Sprite/main.go | 179 ++++++++++++++++++++++++++++++++------- 1 file changed, 148 insertions(+), 31 deletions(-) diff --git a/01_Simple_Sprite/main.go b/01_Simple_Sprite/main.go index a84f114..1570575 100644 --- a/01_Simple_Sprite/main.go +++ b/01_Simple_Sprite/main.go @@ -9,10 +9,15 @@ import ( ) var ( - vkInstance vk.Instance - vkPhysicalDevice vk.PhysicalDevice - vkDevice vk.Device - vkQueue vk.Queue + vkInstance vk.Instance + vkPhysicalDevice vk.PhysicalDevice + vkDevice vk.Device + vkGraphicsQueue vk.Queue + vkPresentQueue vk.Queue + vkSurface vk.Surface + vkSwapchain vk.Swapchain + vkSwapchainImages []vk.Image + vkSwapchainImageViews []vk.ImageView ) func init() { @@ -24,6 +29,10 @@ func createWindow(title string, width, height int) (*glfw.Window, error) { return nil, err } + if !glfw.VulkanSupported() { + return nil, errors.New("missing required Vulkan support") + } + window, err := glfw.CreateWindow(width, height, title, nil, nil) if err != nil { @@ -31,12 +40,6 @@ func createWindow(title string, width, height int) (*glfw.Window, error) { } window.MakeContextCurrent() - - for !window.ShouldClose() { - window.SwapBuffers() - glfw.PollEvents() - } - return window, nil } @@ -45,7 +48,8 @@ func destroyWindow(window *glfw.Window) { glfw.Terminate() } -func initVk(window *glfw.Window) error { +func initVk(window *glfw.Window, width, height uint32) error { + log.Println("Initializing Vulkan...") vk.SetGetInstanceProcAddr(glfw.GetVulkanGetInstanceProcAddress()) if err := vk.Init(); err != nil { @@ -69,6 +73,15 @@ func initVk(window *glfw.Window) error { return errors.New("error creating Vulkan instance") } + // create surface + surface, err := window.CreateWindowSurface(vkInstance, nil) + + if err != nil { + return errors.New("error creating Vulkan surface") + } + + vkSurface = vk.SurfaceFromPointer(surface) + // select the first device with Vulkan support var deviceCount uint32 @@ -80,17 +93,16 @@ func initVk(window *glfw.Window) error { return errors.New("no device with Vulkan support found") } - var devices []vk.PhysicalDevice + devices := make([]vk.PhysicalDevice, 1) if result := vk.EnumeratePhysicalDevices(vkInstance, &deviceCount, devices); result != vk.Success { return errors.New("error listing Vulkan devices") } for _, d := range devices { - //var properties []vk.DisplayProperties - //vk.GetPhysicalDeviceDisplayProperties(d, nil, properties) + // TODO check suitability vkPhysicalDevice = d - break // TODO check suitability + break } if vkPhysicalDevice == nil { @@ -99,49 +111,154 @@ func initVk(window *glfw.Window) error { // find a graphics queue var queueCount uint32 - var queueProperties []vk.QueueFamilyProperties vk.GetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, &queueCount, nil) + queueProperties := make([]vk.QueueFamilyProperties, queueCount) vk.GetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, &queueCount, queueProperties) - var queueIndex uint32 - queueFound := false + var graphicsQueueIndex, presentQueueIndex uint32 + foundGraphicsQueue, foundPresentQueue := false, false for i, q := range queueProperties { - if vk.QueueFlagBits(q.QueueFlags)&vk.QueueGraphicsBit == 1 { - queueIndex = uint32(i) - queueFound = true - break + if !foundGraphicsQueue && vk.QueueFlagBits(q.QueueFlags)&vk.QueueGraphicsBit == 1 { + graphicsQueueIndex = uint32(i) + foundGraphicsQueue = true + + if foundPresentQueue { + break + } + } + + if !foundPresentQueue { + var presentSupport vk.Bool32 + vk.GetPhysicalDeviceSurfaceSupport(vkPhysicalDevice, uint32(i), vkSurface, &presentSupport) + + if presentSupport == 1 { + presentQueueIndex = uint32(i) + foundPresentQueue = true + + if foundGraphicsQueue { + break + } + } } } - if !queueFound { - return errors.New("no Vulkan graphics bit queue found") + if !foundGraphicsQueue { + return errors.New("no Vulkan graphics queue found") } - // create a logical device and get queue + if !foundPresentQueue { + return errors.New("no Vulkan present queue found") + } + + // create a logical device and queues queues := []vk.DeviceQueueCreateInfo{ { SType: vk.StructureTypeDeviceQueueCreateInfo, - QueueFamilyIndex: queueIndex, + QueueFamilyIndex: graphicsQueueIndex, QueueCount: 1, PQueuePriorities: []float32{1}, }, } result = vk.CreateDevice(vkPhysicalDevice, &vk.DeviceCreateInfo{ - SType: vk.StructureTypeDeviceCreateInfo, - QueueCreateInfoCount: 1, - PQueueCreateInfos: queues, + SType: vk.StructureTypeDeviceCreateInfo, + QueueCreateInfoCount: 1, + PQueueCreateInfos: queues, + EnabledExtensionCount: 1, + PpEnabledExtensionNames: []string{ + vk.KhrDisplaySwapchainExtensionName, + }, }, nil, &vkDevice) if result != vk.Success { return errors.New("error creating logical Vulkan device") } - vk.GetDeviceQueue(vkDevice, queueIndex, 0, &vkQueue) + vk.GetDeviceQueue(vkDevice, graphicsQueueIndex, 0, &vkGraphicsQueue) + vk.GetDeviceQueue(vkDevice, presentQueueIndex, 0, &vkPresentQueue) + + // create swap chain (screen buffer) and get the images + sharingMode := vk.SharingModeExclusive + queueFamilyIndexCount := 0 + var queueFamilyIndices []uint32 + + if graphicsQueueIndex != presentQueueIndex { + sharingMode = vk.SharingModeConcurrent + queueFamilyIndexCount = 2 + queueFamilyIndices = []uint32{graphicsQueueIndex, presentQueueIndex} + } + + result = vk.CreateSwapchain(vkDevice, &vk.SwapchainCreateInfo{ + SType: vk.StructureTypeSwapchainCreateInfo, + Surface: vkSurface, + MinImageCount: uint32(3), + ImageFormat: vk.FormatB8g8r8a8Uint, + ImageColorSpace: vk.ColorspaceSrgbNonlinear, + ImageExtent: vk.Extent2D{Width: width, Height: height}, + ImageArrayLayers: 1, + ImageUsage: vk.ImageUsageFlags(vk.ImageUsageColorAttachmentBit), + ImageSharingMode: sharingMode, + QueueFamilyIndexCount: uint32(queueFamilyIndexCount), + PQueueFamilyIndices: queueFamilyIndices, + //PreTransform + CompositeAlpha: vk.CompositeAlphaOpaqueBit, + PresentMode: vk.PresentModeMailbox, + Clipped: vk.True, + OldSwapchain: vk.NullSwapchain, + }, nil, &vkSwapchain) + + if result != vk.Success { + return errors.New("error creating Vulkan swap chain") + } + + var imgCount uint32 + vk.GetSwapchainImages(vkDevice, vkSwapchain, &imgCount, nil) + result = vk.GetSwapchainImages(vkDevice, vkSwapchain, &imgCount, vkSwapchainImages) + + if result != vk.Success { + return errors.New("error getting Vulkan swap chain images") + } + + // create image views for the swap chain images + vkSwapchainImageViews = make([]vk.ImageView, 0, imgCount) + + for i, img := range vkSwapchainImages { + result = vk.CreateImageView(vkDevice, &vk.ImageViewCreateInfo{ + SType: vk.StructureTypeImageViewCreateInfo, + Image: img, + ViewType: vk.ImageViewType2d, + Format: vk.FormatB8g8r8a8Uint, + Components: vk.ComponentMapping{ + R: vk.ComponentSwizzleR, + G: vk.ComponentSwizzleG, + B: vk.ComponentSwizzleB, + A: vk.ComponentSwizzleA, + }, + SubresourceRange: vk.ImageSubresourceRange{ + AspectMask: vk.ImageAspectFlags(vk.ImageAspectColorBit), + BaseMipLevel: uint32(0), + LevelCount: uint32(1), + BaseArrayLayer: uint32(0), + LayerCount: uint32(1), + }, + }, nil, &vkSwapchainImageViews[i]) + + if result != vk.Success { + return errors.New("error creating swap chain image view") + } + } + + log.Println("Done initializing Vulkan...") return nil } func cleanupVk() { + for _, img := range vkSwapchainImageViews { + vk.DestroyImageView(vkDevice, img, nil) + } + + vk.DestroySwapchain(vkDevice, vkSwapchain, nil) + vk.DestroySurface(vkInstance, vkSurface, nil) vk.DestroyDevice(vkDevice, nil) vk.DestroyInstance(vkInstance, nil) } @@ -167,7 +284,7 @@ func main() { defer destroyWindow(window) - if err := initVk(window); err != nil { + if err := initVk(window, 640, 480); err != nil { log.Fatalf("error initializing Vulkan: %s", err) }