zworld-demo/engine/render/vulkan/instance/instance.go
2024-01-09 21:43:28 +08:00

156 lines
4.1 KiB
Go

package instance
//#cgo LDFLAGS: -LF:/Coding/GoModule/cgo -lvulkan
import "C"
import (
"github.com/vkngwrapper/core/v2"
"github.com/vkngwrapper/core/v2/common"
"github.com/vkngwrapper/core/v2/core1_0"
"github.com/vkngwrapper/extensions/v2/khr_surface"
"github.com/vkngwrapper/extensions/v2/khr_swapchain"
"zworld/engine/window"
)
type T interface {
EnumeratePhysicalDevices() []core1_0.PhysicalDevice
Destroy()
Init() error
DrawFrame() error
Ptr() core1_0.Instance
WaitIdle() (common.VkResult, error)
}
type FLoaderCreate func() *core.VulkanLoader
type FInstance struct {
loader *core.VulkanLoader
win *window.FSDLWindow
ptr core1_0.Instance
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
}
func New(appName string, win *window.FSDLWindow, LoaderCreate FLoaderCreate) T {
loader := LoaderCreate()
instanceOptions := &core1_0.InstanceCreateInfo{
APIVersion: common.APIVersion(common.CreateVersion(1, 1, 0)),
ApplicationName: appName,
ApplicationVersion: common.CreateVersion(0, 1, 0),
EngineName: engineName,
EngineVersion: common.CreateVersion(0, 2, 1),
}
err := help.getCreateInstanceExtension(instanceOptions, loader, win)
if err != nil {
return nil
}
err = help.getCreateInstanceLayer(instanceOptions, loader, win)
if err != nil {
return nil
}
handle, _, err := loader.CreateInstance(nil, *instanceOptions)
if err != nil {
panic(err)
}
return &FInstance{
ptr: handle,
loader: loader,
win: win,
}
}
func (e *FInstance) Ptr() core1_0.Instance {
return e.ptr
}
func (e *FInstance) Destroy() {
e.ptr.Destroy(nil)
e.ptr = nil
}
func (e *FInstance) EnumeratePhysicalDevices() []core1_0.PhysicalDevice {
r, _, err := e.ptr.EnumeratePhysicalDevices()
if err != nil {
panic(err)
}
return r
}
func (e *FInstance) WaitIdle() (common.VkResult, error) {
return e.device.WaitIdle()
}
func (e *FInstance) DrawFrame() error {
fences := []core1_0.Fence{e.inFlightFence[e.currentFrame]}
_, err := e.device.WaitForFences(true, common.NoTimeout, fences)
if err != nil {
return err
}
imageIndex, _, err := e.swapchain.AcquireNextImage(common.NoTimeout, e.imageAvailableSemaphore[e.currentFrame], nil)
if err != nil {
return err
}
if e.imagesInFlight[imageIndex] != nil {
_, err := e.device.WaitForFences(true, common.NoTimeout, []core1_0.Fence{e.imagesInFlight[imageIndex]})
if err != nil {
return err
}
}
e.imagesInFlight[imageIndex] = e.inFlightFence[e.currentFrame]
_, err = e.device.ResetFences(fences)
if err != nil {
return err
}
_, err = e.graphicsQueue.Submit(e.inFlightFence[e.currentFrame], []core1_0.SubmitInfo{
{
WaitSemaphores: []core1_0.Semaphore{e.imageAvailableSemaphore[e.currentFrame]},
WaitDstStageMask: []core1_0.PipelineStageFlags{core1_0.PipelineStageColorAttachmentOutput},
CommandBuffers: []core1_0.CommandBuffer{e.commandBuffers[imageIndex]},
SignalSemaphores: []core1_0.Semaphore{e.renderFinishedSemaphore[e.currentFrame]},
},
})
if err != nil {
return err
}
_, err = e.swapchainExtension.QueuePresent(e.presentQueue, khr_swapchain.PresentInfo{
WaitSemaphores: []core1_0.Semaphore{e.renderFinishedSemaphore[e.currentFrame]},
Swapchains: []khr_swapchain.Swapchain{e.swapchain},
ImageIndices: []int{imageIndex},
})
if err != nil {
return err
}
e.currentFrame = (e.currentFrame + 1) % MaxFramesInFlight
return nil
}