1361 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			1361 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								package main
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import (
							 | 
						||
| 
								 | 
							
									"bytes"
							 | 
						||
| 
								 | 
							
									"embed"
							 | 
						||
| 
								 | 
							
									"encoding/binary"
							 | 
						||
| 
								 | 
							
									"github.com/pkg/errors"
							 | 
						||
| 
								 | 
							
									"github.com/veandco/go-sdl2/sdl"
							 | 
						||
| 
								 | 
							
									"github.com/vkngwrapper/core/v2"
							 | 
						||
| 
								 | 
							
									"github.com/vkngwrapper/core/v2/common"
							 | 
						||
| 
								 | 
							
									"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_portability_subset"
							 | 
						||
| 
								 | 
							
									"github.com/vkngwrapper/extensions/v2/khr_surface"
							 | 
						||
| 
								 | 
							
									"github.com/vkngwrapper/extensions/v2/khr_swapchain"
							 | 
						||
| 
								 | 
							
									vkng_sdl2 "github.com/vkngwrapper/integrations/sdl2/v2"
							 | 
						||
| 
								 | 
							
									"log"
							 | 
						||
| 
								 | 
							
									"unsafe"
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//go:embed shaders
							 | 
						||
| 
								 | 
							
								var shaders embed.FS
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const MaxFramesInFlight = 2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var validationLayers = []string{"VK_LAYER_KHRONOS_validation"}
							 | 
						||
| 
								 | 
							
								var deviceExtensions = []string{khr_swapchain.ExtensionName}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const enableValidationLayers = true
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								type Vertex struct {
							 | 
						||
| 
								 | 
							
									X, Y    float32 // Could also be Position Vector2 - as long as Vector2 is a value, not a pointer
							 | 
						||
| 
								 | 
							
									R, G, B float32 // Could also be Color Vector3
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func getVertexBindingDescription() []core1_0.VertexInputBindingDescription {
							 | 
						||
| 
								 | 
							
									v := Vertex{}
							 | 
						||
| 
								 | 
							
									return []core1_0.VertexInputBindingDescription{
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											Binding:   0,
							 | 
						||
| 
								 | 
							
											Stride:    int(unsafe.Sizeof(v)),
							 | 
						||
| 
								 | 
							
											InputRate: core1_0.VertexInputRateVertex,
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func getVertexAttributeDescriptions() []core1_0.VertexInputAttributeDescription {
							 | 
						||
| 
								 | 
							
									v := Vertex{}
							 | 
						||
| 
								 | 
							
									return []core1_0.VertexInputAttributeDescription{
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											Binding:  0,
							 | 
						||
| 
								 | 
							
											Location: 0,
							 | 
						||
| 
								 | 
							
											Format:   core1_0.FormatR32G32SignedFloat,
							 | 
						||
| 
								 | 
							
											Offset:   int(unsafe.Offsetof(v.X)),
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											Binding:  0,
							 | 
						||
| 
								 | 
							
											Location: 1,
							 | 
						||
| 
								 | 
							
											Format:   core1_0.FormatR32G32B32SignedFloat,
							 | 
						||
| 
								 | 
							
											Offset:   int(unsafe.Offsetof(v.R)),
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var vertices = []Vertex{
							 | 
						||
| 
								 | 
							
									{X: -0.5, Y: -0.5, R: 1, G: 0, B: 0},
							 | 
						||
| 
								 | 
							
									{X: 0.5, Y: -0.5, R: 0, G: 1, B: 0},
							 | 
						||
| 
								 | 
							
									{X: 0.5, Y: 0.5, R: 0, G: 0, B: 1},
							 | 
						||
| 
								 | 
							
									{X: -0.5, Y: 0.5, R: 1, G: 1, B: 1},
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var indices = []uint16{0, 1, 2, 2, 3, 0}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								type HelloTriangleApplication struct {
							 | 
						||
| 
								 | 
							
									window *sdl.Window
							 | 
						||
| 
								 | 
							
									loader core.Loader
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									instance       core1_0.Instance
							 | 
						||
| 
								 | 
							
									debugMessenger ext_debug_utils.DebugUtilsMessenger
							 | 
						||
| 
								 | 
							
									surface        khr_surface.Surface
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									physicalDevice core1_0.PhysicalDevice
							 | 
						||
| 
								 | 
							
									device         core1_0.Device
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									graphicsQueue core1_0.Queue
							 | 
						||
| 
								 | 
							
									presentQueue  core1_0.Queue
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									swapchainExtension    khr_swapchain.Extension
							 | 
						||
| 
								 | 
							
									swapchain             khr_swapchain.Swapchain
							 | 
						||
| 
								 | 
							
									swapchainImages       []core1_0.Image
							 | 
						||
| 
								 | 
							
									swapchainImageFormat  core1_0.Format
							 | 
						||
| 
								 | 
							
									swapchainExtent       core1_0.Extent2D
							 | 
						||
| 
								 | 
							
									swapchainImageViews   []core1_0.ImageView
							 | 
						||
| 
								 | 
							
									swapchainFramebuffers []core1_0.Framebuffer
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									renderPass       core1_0.RenderPass
							 | 
						||
| 
								 | 
							
									pipelineLayout   core1_0.PipelineLayout
							 | 
						||
| 
								 | 
							
									graphicsPipeline core1_0.Pipeline
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									commandPool    core1_0.CommandPool
							 | 
						||
| 
								 | 
							
									commandBuffers []core1_0.CommandBuffer
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									imageAvailableSemaphore []core1_0.Semaphore
							 | 
						||
| 
								 | 
							
									renderFinishedSemaphore []core1_0.Semaphore
							 | 
						||
| 
								 | 
							
									inFlightFence           []core1_0.Fence
							 | 
						||
| 
								 | 
							
									imagesInFlight          []core1_0.Fence
							 | 
						||
| 
								 | 
							
									currentFrame            int
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									vertexBuffer       core1_0.Buffer
							 | 
						||
| 
								 | 
							
									vertexBufferMemory core1_0.DeviceMemory
							 | 
						||
| 
								 | 
							
									indexBuffer        core1_0.Buffer
							 | 
						||
| 
								 | 
							
									indexBufferMemory  core1_0.DeviceMemory
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) Run() error {
							 | 
						||
| 
								 | 
							
									err := app.initWindow()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.initVulkan()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									defer app.cleanup()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return app.mainLoop()
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) initWindow() error {
							 | 
						||
| 
								 | 
							
									if err := sdl.Init(sdl.INIT_VIDEO); err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									window, err := sdl.CreateWindow("Vulkan", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, 800, 600, sdl.WINDOW_SHOWN|sdl.WINDOW_VULKAN|sdl.WINDOW_RESIZABLE)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									app.window = window
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									app.loader, err = core.CreateLoaderFromProcAddr(sdl.VulkanGetVkGetInstanceProcAddr())
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) initVulkan() error {
							 | 
						||
| 
								 | 
							
									err := app.createInstance()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.setupDebugMessenger()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createSurface()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.pickPhysicalDevice()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createLogicalDevice()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createSwapchain()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createImageViews()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createRenderPass()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createGraphicsPipeline()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createFramebuffers()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createCommandPool()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createVertexBuffer()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createIndexBuffer()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createCommandBuffers()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return app.createSyncObjects()
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) mainLoop() error {
							 | 
						||
| 
								 | 
							
									rendering := true
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								appLoop:
							 | 
						||
| 
								 | 
							
									for true {
							 | 
						||
| 
								 | 
							
										for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
							 | 
						||
| 
								 | 
							
											switch e := event.(type) {
							 | 
						||
| 
								 | 
							
											case *sdl.QuitEvent:
							 | 
						||
| 
								 | 
							
												break appLoop
							 | 
						||
| 
								 | 
							
											case *sdl.WindowEvent:
							 | 
						||
| 
								 | 
							
												switch e.Event {
							 | 
						||
| 
								 | 
							
												case sdl.WINDOWEVENT_MINIMIZED:
							 | 
						||
| 
								 | 
							
													rendering = false
							 | 
						||
| 
								 | 
							
												case sdl.WINDOWEVENT_RESTORED:
							 | 
						||
| 
								 | 
							
													rendering = true
							 | 
						||
| 
								 | 
							
												case sdl.WINDOWEVENT_RESIZED:
							 | 
						||
| 
								 | 
							
													w, h := app.window.GetSize()
							 | 
						||
| 
								 | 
							
													if w > 0 && h > 0 {
							 | 
						||
| 
								 | 
							
														rendering = true
							 | 
						||
| 
								 | 
							
														app.recreateSwapChain()
							 | 
						||
| 
								 | 
							
													} else {
							 | 
						||
| 
								 | 
							
														rendering = false
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										if rendering {
							 | 
						||
| 
								 | 
							
											err := app.drawFrame()
							 | 
						||
| 
								 | 
							
											if err != nil {
							 | 
						||
| 
								 | 
							
												return err
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									_, err := app.device.WaitIdle()
							 | 
						||
| 
								 | 
							
									return err
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) cleanupSwapChain() {
							 | 
						||
| 
								 | 
							
									for _, framebuffer := range app.swapchainFramebuffers {
							 | 
						||
| 
								 | 
							
										framebuffer.Destroy(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									app.swapchainFramebuffers = []core1_0.Framebuffer{}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if len(app.commandBuffers) > 0 {
							 | 
						||
| 
								 | 
							
										app.device.FreeCommandBuffers(app.commandBuffers)
							 | 
						||
| 
								 | 
							
										app.commandBuffers = []core1_0.CommandBuffer{}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if app.graphicsPipeline != nil {
							 | 
						||
| 
								 | 
							
										app.graphicsPipeline.Destroy(nil)
							 | 
						||
| 
								 | 
							
										app.graphicsPipeline = nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if app.pipelineLayout != nil {
							 | 
						||
| 
								 | 
							
										app.pipelineLayout.Destroy(nil)
							 | 
						||
| 
								 | 
							
										app.pipelineLayout = nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if app.renderPass != nil {
							 | 
						||
| 
								 | 
							
										app.renderPass.Destroy(nil)
							 | 
						||
| 
								 | 
							
										app.renderPass = nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for _, imageView := range app.swapchainImageViews {
							 | 
						||
| 
								 | 
							
										imageView.Destroy(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									app.swapchainImageViews = []core1_0.ImageView{}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if app.swapchain != nil {
							 | 
						||
| 
								 | 
							
										app.swapchain.Destroy(nil)
							 | 
						||
| 
								 | 
							
										app.swapchain = nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) cleanup() {
							 | 
						||
| 
								 | 
							
									app.cleanupSwapChain()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if app.indexBuffer != nil {
							 | 
						||
| 
								 | 
							
										app.indexBuffer.Destroy(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if app.indexBufferMemory != nil {
							 | 
						||
| 
								 | 
							
										app.indexBufferMemory.Free(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if app.vertexBuffer != nil {
							 | 
						||
| 
								 | 
							
										app.vertexBuffer.Destroy(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if app.vertexBufferMemory != nil {
							 | 
						||
| 
								 | 
							
										app.vertexBufferMemory.Free(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for _, fence := range app.inFlightFence {
							 | 
						||
| 
								 | 
							
										fence.Destroy(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for _, semaphore := range app.renderFinishedSemaphore {
							 | 
						||
| 
								 | 
							
										semaphore.Destroy(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for _, semaphore := range app.imageAvailableSemaphore {
							 | 
						||
| 
								 | 
							
										semaphore.Destroy(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if app.commandPool != nil {
							 | 
						||
| 
								 | 
							
										app.commandPool.Destroy(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if app.device != nil {
							 | 
						||
| 
								 | 
							
										app.device.Destroy(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if app.debugMessenger != nil {
							 | 
						||
| 
								 | 
							
										app.debugMessenger.Destroy(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if app.surface != nil {
							 | 
						||
| 
								 | 
							
										app.surface.Destroy(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if app.instance != nil {
							 | 
						||
| 
								 | 
							
										app.instance.Destroy(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if app.window != nil {
							 | 
						||
| 
								 | 
							
										app.window.Destroy()
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									sdl.Quit()
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) recreateSwapChain() error {
							 | 
						||
| 
								 | 
							
									w, h := app.window.VulkanGetDrawableSize()
							 | 
						||
| 
								 | 
							
									if w == 0 || h == 0 {
							 | 
						||
| 
								 | 
							
										return nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if (app.window.GetFlags() & sdl.WINDOW_MINIMIZED) != 0 {
							 | 
						||
| 
								 | 
							
										return nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									_, err := app.device.WaitIdle()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									app.cleanupSwapChain()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createSwapchain()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createImageViews()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createRenderPass()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createGraphicsPipeline()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createFramebuffers()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = app.createCommandBuffers()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									app.imagesInFlight = []core1_0.Fence{}
							 | 
						||
| 
								 | 
							
									for i := 0; i < len(app.swapchainImages); i++ {
							 | 
						||
| 
								 | 
							
										app.imagesInFlight = append(app.imagesInFlight, nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) createInstance() error {
							 | 
						||
| 
								 | 
							
									instanceOptions := core1_0.InstanceCreateInfo{
							 | 
						||
| 
								 | 
							
										ApplicationName:    "Hello Triangle",
							 | 
						||
| 
								 | 
							
										ApplicationVersion: common.CreateVersion(1, 0, 0),
							 | 
						||
| 
								 | 
							
										EngineName:         "No Engine",
							 | 
						||
| 
								 | 
							
										EngineVersion:      common.CreateVersion(1, 0, 0),
							 | 
						||
| 
								 | 
							
										APIVersion:         common.Vulkan1_2,
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Add extensions
							 | 
						||
| 
								 | 
							
									sdlExtensions := app.window.VulkanGetInstanceExtensions()
							 | 
						||
| 
								 | 
							
									extensions, _, err := app.loader.AvailableExtensions()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for _, ext := range sdlExtensions {
							 | 
						||
| 
								 | 
							
										_, hasExt := extensions[ext]
							 | 
						||
| 
								 | 
							
										if !hasExt {
							 | 
						||
| 
								 | 
							
											return errors.Errorf("createinstance: cannot initialize sdl: missing extension %s", ext)
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										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
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Add layers
							 | 
						||
| 
								 | 
							
									layers, _, err := app.loader.AvailableLayers()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if enableValidationLayers {
							 | 
						||
| 
								 | 
							
										for _, layer := range validationLayers {
							 | 
						||
| 
								 | 
							
											_, hasValidation := layers[layer]
							 | 
						||
| 
								 | 
							
											if !hasValidation {
							 | 
						||
| 
								 | 
							
												return errors.Errorf("createInstance: cannot add validation- layer %s not available- install LunarG Vulkan SDK", layer)
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											instanceOptions.EnabledLayerNames = append(instanceOptions.EnabledLayerNames, layer)
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Add debug messenger
							 | 
						||
| 
								 | 
							
										instanceOptions.Next = app.debugMessengerOptions()
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									app.instance, _, err = app.loader.CreateInstance(nil, instanceOptions)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) debugMessengerOptions() ext_debug_utils.DebugUtilsMessengerCreateInfo {
							 | 
						||
| 
								 | 
							
									return ext_debug_utils.DebugUtilsMessengerCreateInfo{
							 | 
						||
| 
								 | 
							
										MessageSeverity: ext_debug_utils.SeverityError | ext_debug_utils.SeverityWarning,
							 | 
						||
| 
								 | 
							
										MessageType:     ext_debug_utils.TypeGeneral | ext_debug_utils.TypeValidation | ext_debug_utils.TypePerformance,
							 | 
						||
| 
								 | 
							
										UserCallback:    app.logDebug,
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) setupDebugMessenger() error {
							 | 
						||
| 
								 | 
							
									if !enableValidationLayers {
							 | 
						||
| 
								 | 
							
										return nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var err error
							 | 
						||
| 
								 | 
							
									debugLoader := ext_debug_utils.CreateExtensionFromInstance(app.instance)
							 | 
						||
| 
								 | 
							
									app.debugMessenger, _, err = debugLoader.CreateDebugUtilsMessenger(app.instance, nil, app.debugMessengerOptions())
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) createSurface() error {
							 | 
						||
| 
								 | 
							
									surfaceLoader := khr_surface.CreateExtensionFromInstance(app.instance)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									surface, err := vkng_sdl2.CreateSurface(app.instance, surfaceLoader, app.window)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									app.surface = surface
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) pickPhysicalDevice() error {
							 | 
						||
| 
								 | 
							
									physicalDevices, _, err := app.instance.EnumeratePhysicalDevices()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for _, device := range physicalDevices {
							 | 
						||
| 
								 | 
							
										if app.isDeviceSuitable(device) {
							 | 
						||
| 
								 | 
							
											app.physicalDevice = device
							 | 
						||
| 
								 | 
							
											break
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if app.physicalDevice == nil {
							 | 
						||
| 
								 | 
							
										return errors.Errorf("failed to find a suitable GPU!")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) createLogicalDevice() error {
							 | 
						||
| 
								 | 
							
									indices, err := app.findQueueFamilies(app.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 := app.physicalDevice.EnumerateDeviceExtensionProperties()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									_, supported := extensions[khr_portability_subset.ExtensionName]
							 | 
						||
| 
								 | 
							
									if supported {
							 | 
						||
| 
								 | 
							
										extensionNames = append(extensionNames, khr_portability_subset.ExtensionName)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									app.device, _, err = app.physicalDevice.CreateDevice(nil, core1_0.DeviceCreateInfo{
							 | 
						||
| 
								 | 
							
										QueueCreateInfos:      queueFamilyOptions,
							 | 
						||
| 
								 | 
							
										EnabledFeatures:       &core1_0.PhysicalDeviceFeatures{},
							 | 
						||
| 
								 | 
							
										EnabledExtensionNames: extensionNames,
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									app.graphicsQueue = app.device.GetQueue(*indices.GraphicsFamily, 0)
							 | 
						||
| 
								 | 
							
									app.presentQueue = app.device.GetQueue(*indices.PresentFamily, 0)
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) createSwapchain() error {
							 | 
						||
| 
								 | 
							
									app.swapchainExtension = khr_swapchain.CreateExtensionFromDevice(app.device)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									swapchainSupport, err := app.querySwapChainSupport(app.physicalDevice)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									surfaceFormat := app.chooseSwapSurfaceFormat(swapchainSupport.Formats)
							 | 
						||
| 
								 | 
							
									presentMode := app.chooseSwapPresentMode(swapchainSupport.PresentModes)
							 | 
						||
| 
								 | 
							
									extent := app.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 := app.findQueueFamilies(app.physicalDevice)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if *indices.GraphicsFamily != *indices.PresentFamily {
							 | 
						||
| 
								 | 
							
										sharingMode = core1_0.SharingModeConcurrent
							 | 
						||
| 
								 | 
							
										queueFamilyIndices = append(queueFamilyIndices, *indices.GraphicsFamily, *indices.PresentFamily)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									swapchain, _, err := app.swapchainExtension.CreateSwapchain(app.device, nil, khr_swapchain.SwapchainCreateInfo{
							 | 
						||
| 
								 | 
							
										Surface: app.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
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									app.swapchainExtent = extent
							 | 
						||
| 
								 | 
							
									app.swapchain = swapchain
							 | 
						||
| 
								 | 
							
									app.swapchainImageFormat = surfaceFormat.Format
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) createImageViews() error {
							 | 
						||
| 
								 | 
							
									images, _, err := app.swapchain.SwapchainImages()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									app.swapchainImages = images
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var imageViews []core1_0.ImageView
							 | 
						||
| 
								 | 
							
									for _, image := range images {
							 | 
						||
| 
								 | 
							
										view, _, err := app.device.CreateImageView(nil, core1_0.ImageViewCreateInfo{
							 | 
						||
| 
								 | 
							
											ViewType: core1_0.ImageViewType2D,
							 | 
						||
| 
								 | 
							
											Image:    image,
							 | 
						||
| 
								 | 
							
											Format:   app.swapchainImageFormat,
							 | 
						||
| 
								 | 
							
											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)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									app.swapchainImageViews = imageViews
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) createRenderPass() error {
							 | 
						||
| 
								 | 
							
									renderPass, _, err := app.device.CreateRenderPass(nil, core1_0.RenderPassCreateInfo{
							 | 
						||
| 
								 | 
							
										Attachments: []core1_0.AttachmentDescription{
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												Format:         app.swapchainImageFormat,
							 | 
						||
| 
								 | 
							
												Samples:        core1_0.Samples1,
							 | 
						||
| 
								 | 
							
												LoadOp:         core1_0.AttachmentLoadOpClear,
							 | 
						||
| 
								 | 
							
												StoreOp:        core1_0.AttachmentStoreOpStore,
							 | 
						||
| 
								 | 
							
												StencilLoadOp:  core1_0.AttachmentLoadOpDontCare,
							 | 
						||
| 
								 | 
							
												StencilStoreOp: core1_0.AttachmentStoreOpDontCare,
							 | 
						||
| 
								 | 
							
												InitialLayout:  core1_0.ImageLayoutUndefined,
							 | 
						||
| 
								 | 
							
												FinalLayout:    khr_swapchain.ImageLayoutPresentSrc,
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										Subpasses: []core1_0.SubpassDescription{
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												PipelineBindPoint: core1_0.PipelineBindPointGraphics,
							 | 
						||
| 
								 | 
							
												ColorAttachments: []core1_0.AttachmentReference{
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														Attachment: 0,
							 | 
						||
| 
								 | 
							
														Layout:     core1_0.ImageLayoutColorAttachmentOptimal,
							 | 
						||
| 
								 | 
							
													},
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										SubpassDependencies: []core1_0.SubpassDependency{
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												SrcSubpass: core1_0.SubpassExternal,
							 | 
						||
| 
								 | 
							
												DstSubpass: 0,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												SrcStageMask:  core1_0.PipelineStageColorAttachmentOutput,
							 | 
						||
| 
								 | 
							
												SrcAccessMask: 0,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												DstStageMask:  core1_0.PipelineStageColorAttachmentOutput,
							 | 
						||
| 
								 | 
							
												DstAccessMask: core1_0.AccessColorAttachmentWrite,
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									app.renderPass = renderPass
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func bytesToBytecode(b []byte) []uint32 {
							 | 
						||
| 
								 | 
							
									byteCode := make([]uint32, len(b)/4)
							 | 
						||
| 
								 | 
							
									for i := 0; i < len(byteCode); i++ {
							 | 
						||
| 
								 | 
							
										byteIndex := i * 4
							 | 
						||
| 
								 | 
							
										byteCode[i] = 0
							 | 
						||
| 
								 | 
							
										byteCode[i] |= uint32(b[byteIndex])
							 | 
						||
| 
								 | 
							
										byteCode[i] |= uint32(b[byteIndex+1]) << 8
							 | 
						||
| 
								 | 
							
										byteCode[i] |= uint32(b[byteIndex+2]) << 16
							 | 
						||
| 
								 | 
							
										byteCode[i] |= uint32(b[byteIndex+3]) << 24
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return byteCode
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) createGraphicsPipeline() error {
							 | 
						||
| 
								 | 
							
									// Load vertex shader
							 | 
						||
| 
								 | 
							
									vertShaderBytes, err := shaders.ReadFile("shaders/vert.spv")
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									vertShader, _, err := app.device.CreateShaderModule(nil, core1_0.ShaderModuleCreateInfo{
							 | 
						||
| 
								 | 
							
										Code: bytesToBytecode(vertShaderBytes),
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									defer vertShader.Destroy(nil)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Load fragment shader
							 | 
						||
| 
								 | 
							
									fragShaderBytes, err := shaders.ReadFile("shaders/frag.spv")
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									fragShader, _, err := app.device.CreateShaderModule(nil, core1_0.ShaderModuleCreateInfo{
							 | 
						||
| 
								 | 
							
										Code: bytesToBytecode(fragShaderBytes),
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									defer fragShader.Destroy(nil)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									vertexInput := &core1_0.PipelineVertexInputStateCreateInfo{
							 | 
						||
| 
								 | 
							
										VertexBindingDescriptions:   getVertexBindingDescription(),
							 | 
						||
| 
								 | 
							
										VertexAttributeDescriptions: getVertexAttributeDescriptions(),
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									inputAssembly := &core1_0.PipelineInputAssemblyStateCreateInfo{
							 | 
						||
| 
								 | 
							
										Topology:               core1_0.PrimitiveTopologyTriangleList,
							 | 
						||
| 
								 | 
							
										PrimitiveRestartEnable: false,
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									vertStage := core1_0.PipelineShaderStageCreateInfo{
							 | 
						||
| 
								 | 
							
										Stage:  core1_0.StageVertex,
							 | 
						||
| 
								 | 
							
										Module: vertShader,
							 | 
						||
| 
								 | 
							
										Name:   "main",
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									fragStage := core1_0.PipelineShaderStageCreateInfo{
							 | 
						||
| 
								 | 
							
										Stage:  core1_0.StageFragment,
							 | 
						||
| 
								 | 
							
										Module: fragShader,
							 | 
						||
| 
								 | 
							
										Name:   "main",
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									viewport := &core1_0.PipelineViewportStateCreateInfo{
							 | 
						||
| 
								 | 
							
										Viewports: []core1_0.Viewport{
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												X:        0,
							 | 
						||
| 
								 | 
							
												Y:        0,
							 | 
						||
| 
								 | 
							
												Width:    float32(app.swapchainExtent.Width),
							 | 
						||
| 
								 | 
							
												Height:   float32(app.swapchainExtent.Height),
							 | 
						||
| 
								 | 
							
												MinDepth: 0,
							 | 
						||
| 
								 | 
							
												MaxDepth: 1,
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										Scissors: []core1_0.Rect2D{
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												Offset: core1_0.Offset2D{X: 0, Y: 0},
							 | 
						||
| 
								 | 
							
												Extent: app.swapchainExtent,
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									rasterization := &core1_0.PipelineRasterizationStateCreateInfo{
							 | 
						||
| 
								 | 
							
										DepthClampEnable:        false,
							 | 
						||
| 
								 | 
							
										RasterizerDiscardEnable: false,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										PolygonMode: core1_0.PolygonModeFill,
							 | 
						||
| 
								 | 
							
										CullMode:    core1_0.CullModeBack,
							 | 
						||
| 
								 | 
							
										FrontFace:   core1_0.FrontFaceClockwise,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										DepthBiasEnable: false,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										LineWidth: 1.0,
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									multisample := &core1_0.PipelineMultisampleStateCreateInfo{
							 | 
						||
| 
								 | 
							
										SampleShadingEnable:  false,
							 | 
						||
| 
								 | 
							
										RasterizationSamples: core1_0.Samples1,
							 | 
						||
| 
								 | 
							
										MinSampleShading:     1.0,
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									colorBlend := &core1_0.PipelineColorBlendStateCreateInfo{
							 | 
						||
| 
								 | 
							
										LogicOpEnabled: false,
							 | 
						||
| 
								 | 
							
										LogicOp:        core1_0.LogicOpCopy,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										BlendConstants: [4]float32{0, 0, 0, 0},
							 | 
						||
| 
								 | 
							
										Attachments: []core1_0.PipelineColorBlendAttachmentState{
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												BlendEnabled:   false,
							 | 
						||
| 
								 | 
							
												ColorWriteMask: core1_0.ColorComponentRed | core1_0.ColorComponentGreen | core1_0.ColorComponentBlue | core1_0.ColorComponentAlpha,
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									app.pipelineLayout, _, err = app.device.CreatePipelineLayout(nil, core1_0.PipelineLayoutCreateInfo{})
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									pipelines, _, err := app.device.CreateGraphicsPipelines(nil, nil, []core1_0.GraphicsPipelineCreateInfo{
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											Stages: []core1_0.PipelineShaderStageCreateInfo{
							 | 
						||
| 
								 | 
							
												vertStage,
							 | 
						||
| 
								 | 
							
												fragStage,
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
											VertexInputState:   vertexInput,
							 | 
						||
| 
								 | 
							
											InputAssemblyState: inputAssembly,
							 | 
						||
| 
								 | 
							
											ViewportState:      viewport,
							 | 
						||
| 
								 | 
							
											RasterizationState: rasterization,
							 | 
						||
| 
								 | 
							
											MultisampleState:   multisample,
							 | 
						||
| 
								 | 
							
											ColorBlendState:    colorBlend,
							 | 
						||
| 
								 | 
							
											Layout:             app.pipelineLayout,
							 | 
						||
| 
								 | 
							
											RenderPass:         app.renderPass,
							 | 
						||
| 
								 | 
							
											Subpass:            0,
							 | 
						||
| 
								 | 
							
											BasePipelineIndex:  -1,
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									app.graphicsPipeline = pipelines[0]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) createFramebuffers() error {
							 | 
						||
| 
								 | 
							
									for _, imageView := range app.swapchainImageViews {
							 | 
						||
| 
								 | 
							
										framebuffer, _, err := app.device.CreateFramebuffer(nil, core1_0.FramebufferCreateInfo{
							 | 
						||
| 
								 | 
							
											RenderPass: app.renderPass,
							 | 
						||
| 
								 | 
							
											Layers:     1,
							 | 
						||
| 
								 | 
							
											Attachments: []core1_0.ImageView{
							 | 
						||
| 
								 | 
							
												imageView,
							 | 
						||
| 
								 | 
							
											},
							 | 
						||
| 
								 | 
							
											Width:  app.swapchainExtent.Width,
							 | 
						||
| 
								 | 
							
											Height: app.swapchainExtent.Height,
							 | 
						||
| 
								 | 
							
										})
							 | 
						||
| 
								 | 
							
										if err != nil {
							 | 
						||
| 
								 | 
							
											return err
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										app.swapchainFramebuffers = append(app.swapchainFramebuffers, framebuffer)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) createCommandPool() error {
							 | 
						||
| 
								 | 
							
									indices, err := app.findQueueFamilies(app.physicalDevice)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									pool, _, err := app.device.CreateCommandPool(nil, core1_0.CommandPoolCreateInfo{
							 | 
						||
| 
								 | 
							
										QueueFamilyIndex: *indices.GraphicsFamily,
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									app.commandPool = pool
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func writeData(memory core1_0.DeviceMemory, offset int, data any) error {
							 | 
						||
| 
								 | 
							
									bufferSize := binary.Size(data)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									memoryPtr, _, err := memory.Map(offset, bufferSize, 0)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									defer memory.Unmap()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									dataBuffer := unsafe.Slice((*byte)(memoryPtr), bufferSize)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									buf := &bytes.Buffer{}
							 | 
						||
| 
								 | 
							
									err = binary.Write(buf, common.ByteOrder, data)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									copy(dataBuffer, buf.Bytes())
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) createVertexBuffer() error {
							 | 
						||
| 
								 | 
							
									var err error
							 | 
						||
| 
								 | 
							
									bufferSize := binary.Size(vertices)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									stagingBuffer, stagingBufferMemory, err := app.createBuffer(bufferSize, core1_0.BufferUsageTransferSrc, core1_0.MemoryPropertyHostVisible|core1_0.MemoryPropertyHostCoherent)
							 | 
						||
| 
								 | 
							
									if stagingBuffer != nil {
							 | 
						||
| 
								 | 
							
										defer stagingBuffer.Destroy(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if stagingBufferMemory != nil {
							 | 
						||
| 
								 | 
							
										defer stagingBufferMemory.Free(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = writeData(stagingBufferMemory, 0, vertices)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									app.vertexBuffer, app.vertexBufferMemory, err = app.createBuffer(bufferSize, core1_0.BufferUsageTransferDst|core1_0.BufferUsageVertexBuffer, core1_0.MemoryPropertyDeviceLocal)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return app.copyBuffer(stagingBuffer, app.vertexBuffer, bufferSize)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) createIndexBuffer() error {
							 | 
						||
| 
								 | 
							
									bufferSize := binary.Size(indices)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									stagingBuffer, stagingBufferMemory, err := app.createBuffer(bufferSize, core1_0.BufferUsageTransferSrc, core1_0.MemoryPropertyHostVisible|core1_0.MemoryPropertyHostCoherent)
							 | 
						||
| 
								 | 
							
									if stagingBuffer != nil {
							 | 
						||
| 
								 | 
							
										defer stagingBuffer.Destroy(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if stagingBufferMemory != nil {
							 | 
						||
| 
								 | 
							
										defer stagingBufferMemory.Free(nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err = writeData(stagingBufferMemory, 0, indices)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									app.indexBuffer, app.indexBufferMemory, err = app.createBuffer(bufferSize, core1_0.BufferUsageTransferDst|core1_0.BufferUsageIndexBuffer, core1_0.MemoryPropertyDeviceLocal)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return app.copyBuffer(stagingBuffer, app.indexBuffer, bufferSize)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) createBuffer(size int, usage core1_0.BufferUsageFlags, properties core1_0.MemoryPropertyFlags) (core1_0.Buffer, core1_0.DeviceMemory, error) {
							 | 
						||
| 
								 | 
							
									buffer, _, err := app.device.CreateBuffer(nil, core1_0.BufferCreateInfo{
							 | 
						||
| 
								 | 
							
										Size:        size,
							 | 
						||
| 
								 | 
							
										Usage:       usage,
							 | 
						||
| 
								 | 
							
										SharingMode: core1_0.SharingModeExclusive,
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return nil, nil, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									memRequirements := buffer.MemoryRequirements()
							 | 
						||
| 
								 | 
							
									memoryTypeIndex, err := app.findMemoryType(memRequirements.MemoryTypeBits, properties)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return buffer, nil, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									memory, _, err := app.device.AllocateMemory(nil, core1_0.MemoryAllocateInfo{
							 | 
						||
| 
								 | 
							
										AllocationSize:  memRequirements.Size,
							 | 
						||
| 
								 | 
							
										MemoryTypeIndex: memoryTypeIndex,
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return buffer, nil, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									_, err = buffer.BindBufferMemory(memory, 0)
							 | 
						||
| 
								 | 
							
									return buffer, memory, err
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) copyBuffer(srcBuffer core1_0.Buffer, dstBuffer core1_0.Buffer, size int) error {
							 | 
						||
| 
								 | 
							
									buffers, _, err := app.device.AllocateCommandBuffers(core1_0.CommandBufferAllocateInfo{
							 | 
						||
| 
								 | 
							
										CommandPool:        app.commandPool,
							 | 
						||
| 
								 | 
							
										Level:              core1_0.CommandBufferLevelPrimary,
							 | 
						||
| 
								 | 
							
										CommandBufferCount: 1,
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									buffer := buffers[0]
							 | 
						||
| 
								 | 
							
									_, err = buffer.Begin(core1_0.CommandBufferBeginInfo{
							 | 
						||
| 
								 | 
							
										Flags: core1_0.CommandBufferUsageOneTimeSubmit,
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									defer app.device.FreeCommandBuffers(buffers)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									buffer.CmdCopyBuffer(srcBuffer, dstBuffer, []core1_0.BufferCopy{
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											SrcOffset: 0,
							 | 
						||
| 
								 | 
							
											DstOffset: 0,
							 | 
						||
| 
								 | 
							
											Size:      size,
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									_, err = buffer.End()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									_, err = app.graphicsQueue.Submit(nil, []core1_0.SubmitInfo{
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											CommandBuffers: []core1_0.CommandBuffer{buffer},
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									_, err = app.graphicsQueue.WaitIdle()
							 | 
						||
| 
								 | 
							
									return err
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) findMemoryType(typeFilter uint32, properties core1_0.MemoryPropertyFlags) (int, error) {
							 | 
						||
| 
								 | 
							
									memProperties := app.physicalDevice.MemoryProperties()
							 | 
						||
| 
								 | 
							
									for i, memoryType := range memProperties.MemoryTypes {
							 | 
						||
| 
								 | 
							
										typeBit := uint32(1 << i)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (typeFilter&typeBit) != 0 && (memoryType.PropertyFlags&properties) == properties {
							 | 
						||
| 
								 | 
							
											return i, nil
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return 0, errors.Errorf("failed to find any suitable memory type!")
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) createCommandBuffers() error {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									buffers, _, err := app.device.AllocateCommandBuffers(core1_0.CommandBufferAllocateInfo{
							 | 
						||
| 
								 | 
							
										CommandPool:        app.commandPool,
							 | 
						||
| 
								 | 
							
										Level:              core1_0.CommandBufferLevelPrimary,
							 | 
						||
| 
								 | 
							
										CommandBufferCount: len(app.swapchainImages),
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									app.commandBuffers = buffers
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for bufferIdx, buffer := range buffers {
							 | 
						||
| 
								 | 
							
										_, err = buffer.Begin(core1_0.CommandBufferBeginInfo{})
							 | 
						||
| 
								 | 
							
										if err != nil {
							 | 
						||
| 
								 | 
							
											return err
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										err = buffer.CmdBeginRenderPass(core1_0.SubpassContentsInline,
							 | 
						||
| 
								 | 
							
											core1_0.RenderPassBeginInfo{
							 | 
						||
| 
								 | 
							
												RenderPass:  app.renderPass,
							 | 
						||
| 
								 | 
							
												Framebuffer: app.swapchainFramebuffers[bufferIdx],
							 | 
						||
| 
								 | 
							
												RenderArea: core1_0.Rect2D{
							 | 
						||
| 
								 | 
							
													Offset: core1_0.Offset2D{X: 0, Y: 0},
							 | 
						||
| 
								 | 
							
													Extent: app.swapchainExtent,
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
												ClearValues: []core1_0.ClearValue{
							 | 
						||
| 
								 | 
							
													core1_0.ClearValueFloat{0, 0, 0, 1},
							 | 
						||
| 
								 | 
							
												},
							 | 
						||
| 
								 | 
							
											})
							 | 
						||
| 
								 | 
							
										if err != nil {
							 | 
						||
| 
								 | 
							
											return err
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										buffer.CmdBindPipeline(core1_0.PipelineBindPointGraphics, app.graphicsPipeline)
							 | 
						||
| 
								 | 
							
										buffer.CmdBindVertexBuffers(0, []core1_0.Buffer{app.vertexBuffer}, []int{0})
							 | 
						||
| 
								 | 
							
										buffer.CmdBindIndexBuffer(app.indexBuffer, 0, core1_0.IndexTypeUInt16)
							 | 
						||
| 
								 | 
							
										buffer.CmdDrawIndexed(len(indices), 1, 0, 0, 0)
							 | 
						||
| 
								 | 
							
										buffer.CmdEndRenderPass()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										_, err = buffer.End()
							 | 
						||
| 
								 | 
							
										if err != nil {
							 | 
						||
| 
								 | 
							
											return err
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) createSyncObjects() error {
							 | 
						||
| 
								 | 
							
									for i := 0; i < MaxFramesInFlight; i++ {
							 | 
						||
| 
								 | 
							
										semaphore, _, err := app.device.CreateSemaphore(nil, core1_0.SemaphoreCreateInfo{})
							 | 
						||
| 
								 | 
							
										if err != nil {
							 | 
						||
| 
								 | 
							
											return err
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										app.imageAvailableSemaphore = append(app.imageAvailableSemaphore, semaphore)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										semaphore, _, err = app.device.CreateSemaphore(nil, core1_0.SemaphoreCreateInfo{})
							 | 
						||
| 
								 | 
							
										if err != nil {
							 | 
						||
| 
								 | 
							
											return err
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										app.renderFinishedSemaphore = append(app.renderFinishedSemaphore, semaphore)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										fence, _, err := app.device.CreateFence(nil, core1_0.FenceCreateInfo{
							 | 
						||
| 
								 | 
							
											Flags: core1_0.FenceCreateSignaled,
							 | 
						||
| 
								 | 
							
										})
							 | 
						||
| 
								 | 
							
										if err != nil {
							 | 
						||
| 
								 | 
							
											return err
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										app.inFlightFence = append(app.inFlightFence, fence)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for i := 0; i < len(app.swapchainImages); i++ {
							 | 
						||
| 
								 | 
							
										app.imagesInFlight = append(app.imagesInFlight, nil)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) drawFrame() error {
							 | 
						||
| 
								 | 
							
									fences := []core1_0.Fence{app.inFlightFence[app.currentFrame]}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									_, err := app.device.WaitForFences(true, common.NoTimeout, fences)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									imageIndex, res, err := app.swapchain.AcquireNextImage(common.NoTimeout, app.imageAvailableSemaphore[app.currentFrame], nil)
							 | 
						||
| 
								 | 
							
									if res == khr_swapchain.VKErrorOutOfDate {
							 | 
						||
| 
								 | 
							
										return app.recreateSwapChain()
							 | 
						||
| 
								 | 
							
									} else if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if app.imagesInFlight[imageIndex] != nil {
							 | 
						||
| 
								 | 
							
										_, err := app.imagesInFlight[imageIndex].Wait(common.NoTimeout)
							 | 
						||
| 
								 | 
							
										if err != nil {
							 | 
						||
| 
								 | 
							
											return err
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									app.imagesInFlight[imageIndex] = app.inFlightFence[app.currentFrame]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									_, err = app.device.ResetFences(fences)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									_, err = app.graphicsQueue.Submit(app.inFlightFence[app.currentFrame], []core1_0.SubmitInfo{
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											WaitSemaphores:   []core1_0.Semaphore{app.imageAvailableSemaphore[app.currentFrame]},
							 | 
						||
| 
								 | 
							
											WaitDstStageMask: []core1_0.PipelineStageFlags{core1_0.PipelineStageColorAttachmentOutput},
							 | 
						||
| 
								 | 
							
											CommandBuffers:   []core1_0.CommandBuffer{app.commandBuffers[imageIndex]},
							 | 
						||
| 
								 | 
							
											SignalSemaphores: []core1_0.Semaphore{app.renderFinishedSemaphore[app.currentFrame]},
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									res, err = app.swapchainExtension.QueuePresent(app.presentQueue, khr_swapchain.PresentInfo{
							 | 
						||
| 
								 | 
							
										WaitSemaphores: []core1_0.Semaphore{app.renderFinishedSemaphore[app.currentFrame]},
							 | 
						||
| 
								 | 
							
										Swapchains:     []khr_swapchain.Swapchain{app.swapchain},
							 | 
						||
| 
								 | 
							
										ImageIndices:   []int{imageIndex},
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
									if res == khr_swapchain.VKErrorOutOfDate || res == khr_swapchain.VKSuboptimal {
							 | 
						||
| 
								 | 
							
										return app.recreateSwapChain()
							 | 
						||
| 
								 | 
							
									} else if err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									app.currentFrame = (app.currentFrame + 1) % MaxFramesInFlight
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) 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 (app *HelloTriangleApplication) chooseSwapPresentMode(availablePresentModes []khr_surface.PresentMode) khr_surface.PresentMode {
							 | 
						||
| 
								 | 
							
									for _, presentMode := range availablePresentModes {
							 | 
						||
| 
								 | 
							
										if presentMode == khr_surface.PresentModeMailbox {
							 | 
						||
| 
								 | 
							
											return presentMode
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return khr_surface.PresentModeFIFO
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) chooseSwapExtent(capabilities *khr_surface.SurfaceCapabilities) core1_0.Extent2D {
							 | 
						||
| 
								 | 
							
									if capabilities.CurrentExtent.Width != -1 {
							 | 
						||
| 
								 | 
							
										return capabilities.CurrentExtent
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									widthInt, heightInt := app.window.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}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) querySwapChainSupport(device core1_0.PhysicalDevice) (SwapChainSupportDetails, error) {
							 | 
						||
| 
								 | 
							
									var details SwapChainSupportDetails
							 | 
						||
| 
								 | 
							
									var err error
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									details.Capabilities, _, err = app.surface.PhysicalDeviceSurfaceCapabilities(device)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return details, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									details.Formats, _, err = app.surface.PhysicalDeviceSurfaceFormats(device)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return details, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									details.PresentModes, _, err = app.surface.PhysicalDeviceSurfacePresentModes(device)
							 | 
						||
| 
								 | 
							
									return details, err
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) isDeviceSuitable(device core1_0.PhysicalDevice) bool {
							 | 
						||
| 
								 | 
							
									indices, err := app.findQueueFamilies(device)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return false
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									extensionsSupported := app.checkDeviceExtensionSupport(device)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var swapChainAdequate bool
							 | 
						||
| 
								 | 
							
									if extensionsSupported {
							 | 
						||
| 
								 | 
							
										swapChainSupport, err := app.querySwapChainSupport(device)
							 | 
						||
| 
								 | 
							
										if err != nil {
							 | 
						||
| 
								 | 
							
											return false
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										swapChainAdequate = len(swapChainSupport.Formats) > 0 && len(swapChainSupport.PresentModes) > 0
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return indices.IsComplete() && extensionsSupported && swapChainAdequate
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (app *HelloTriangleApplication) 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 (app *HelloTriangleApplication) findQueueFamilies(device core1_0.PhysicalDevice) (QueueFamilyIndices, error) {
							 | 
						||
| 
								 | 
							
									indices := QueueFamilyIndices{}
							 | 
						||
| 
								 | 
							
									queueFamilies := device.QueueFamilyProperties()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for queueFamilyIdx, queueFamily := range queueFamilies {
							 | 
						||
| 
								 | 
							
										if (queueFamily.QueueFlags & core1_0.QueueGraphics) != 0 {
							 | 
						||
| 
								 | 
							
											indices.GraphicsFamily = new(int)
							 | 
						||
| 
								 | 
							
											*indices.GraphicsFamily = queueFamilyIdx
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										supported, _, err := app.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 (app *HelloTriangleApplication) logDebug(msgType ext_debug_utils.DebugUtilsMessageTypeFlags, severity ext_debug_utils.DebugUtilsMessageSeverityFlags, data *ext_debug_utils.DebugUtilsMessengerCallbackData) bool {
							 | 
						||
| 
								 | 
							
									log.Printf("[%s %s] - %s", severity, msgType, data.Message)
							 | 
						||
| 
								 | 
							
									return false
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func main() {
							 | 
						||
| 
								 | 
							
									app := &HelloTriangleApplication{}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									err := app.Run()
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										log.Fatalf("%+v\n", err)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |