forked from joejulian/gio
app: [Vulkan] keep VkSurfaceKHR ownership to platforms
Before this change, it was unclear who owned the platform specific VkSurfaceKHR object, leading to a double-free in the error path for devices with no Vulkan support. This change moves the ownership to the platform specific code. Add vk.EnumeratePhysicalDevices while here (refactor was part of debugging of the double-free). Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+4
-22
@@ -17,7 +17,6 @@ import (
|
|||||||
type vkContext struct {
|
type vkContext struct {
|
||||||
physDev vk.PhysicalDevice
|
physDev vk.PhysicalDevice
|
||||||
inst vk.Instance
|
inst vk.Instance
|
||||||
surf vk.Surface
|
|
||||||
dev vk.Device
|
dev vk.Device
|
||||||
queueFam int
|
queueFam int
|
||||||
queue vk.Queue
|
queue vk.Queue
|
||||||
@@ -35,36 +34,30 @@ type vkContext struct {
|
|||||||
func newVulkanContext(inst vk.Instance, surf vk.Surface) (*vkContext, error) {
|
func newVulkanContext(inst vk.Instance, surf vk.Surface) (*vkContext, error) {
|
||||||
physDev, qFam, err := vk.ChoosePhysicalDevice(inst, surf)
|
physDev, qFam, err := vk.ChoosePhysicalDevice(inst, surf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
vk.DestroySurface(inst, surf)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dev, err := vk.CreateDeviceAndQueue(physDev, qFam, "VK_KHR_swapchain")
|
dev, err := vk.CreateDeviceAndQueue(physDev, qFam, "VK_KHR_swapchain")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
vk.DestroySurface(inst, surf)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
vk.DestroySurface(inst, surf)
|
|
||||||
vk.DestroyDevice(dev)
|
vk.DestroyDevice(dev)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
acquireSem, err := vk.CreateSemaphore(dev)
|
acquireSem, err := vk.CreateSemaphore(dev)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
vk.DestroySurface(inst, surf)
|
|
||||||
vk.DestroyDevice(dev)
|
vk.DestroyDevice(dev)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
presentSem, err := vk.CreateSemaphore(dev)
|
presentSem, err := vk.CreateSemaphore(dev)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
vk.DestroySemaphore(dev, acquireSem)
|
vk.DestroySemaphore(dev, acquireSem)
|
||||||
vk.DestroySurface(inst, surf)
|
|
||||||
vk.DestroyDevice(dev)
|
vk.DestroyDevice(dev)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
c := &vkContext{
|
c := &vkContext{
|
||||||
physDev: physDev,
|
physDev: physDev,
|
||||||
inst: inst,
|
inst: inst,
|
||||||
surf: surf,
|
|
||||||
dev: dev,
|
dev: dev,
|
||||||
queueFam: qFam,
|
queueFam: qFam,
|
||||||
queue: vk.GetDeviceQueue(dev, qFam, 0),
|
queue: vk.GetDeviceQueue(dev, qFam, 0),
|
||||||
@@ -120,7 +113,7 @@ func mapErr(err error) error {
|
|||||||
func (c *vkContext) release() {
|
func (c *vkContext) release() {
|
||||||
vk.DeviceWaitIdle(c.dev)
|
vk.DeviceWaitIdle(c.dev)
|
||||||
|
|
||||||
c.destroySurface()
|
c.destroySwapchain()
|
||||||
vk.DestroySemaphore(c.dev, c.acquireSem)
|
vk.DestroySemaphore(c.dev, c.acquireSem)
|
||||||
vk.DestroySemaphore(c.dev, c.presentSem)
|
vk.DestroySemaphore(c.dev, c.presentSem)
|
||||||
vk.DestroyDevice(c.dev)
|
vk.DestroyDevice(c.dev)
|
||||||
@@ -142,7 +135,7 @@ func (c *vkContext) destroyImageViews() {
|
|||||||
c.views = nil
|
c.views = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *vkContext) destroySurface() {
|
func (c *vkContext) destroySwapchain() {
|
||||||
vk.DeviceWaitIdle(c.dev)
|
vk.DeviceWaitIdle(c.dev)
|
||||||
|
|
||||||
c.destroyImageViews()
|
c.destroyImageViews()
|
||||||
@@ -150,24 +143,13 @@ func (c *vkContext) destroySurface() {
|
|||||||
vk.DestroySwapchain(c.dev, c.swchain)
|
vk.DestroySwapchain(c.dev, c.swchain)
|
||||||
c.swchain = 0
|
c.swchain = 0
|
||||||
}
|
}
|
||||||
if c.surf != 0 {
|
|
||||||
vk.DestroySurface(c.inst, c.surf)
|
|
||||||
c.surf = 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *vkContext) setSurface(surf vk.Surface) {
|
func (c *vkContext) refresh(surf vk.Surface, width, height int) error {
|
||||||
if c.surf != 0 {
|
|
||||||
panic("another surface is active")
|
|
||||||
}
|
|
||||||
c.surf = surf
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *vkContext) refresh(width, height int) error {
|
|
||||||
vk.DeviceWaitIdle(c.dev)
|
vk.DeviceWaitIdle(c.dev)
|
||||||
|
|
||||||
c.destroyImageViews()
|
c.destroyImageViews()
|
||||||
swchain, imgs, format, err := vk.CreateSwapchain(c.physDev, c.dev, c.surf, width, height, c.swchain)
|
swchain, imgs, format, err := vk.CreateSwapchain(c.physDev, c.dev, surf, width, height, c.swchain)
|
||||||
if c.swchain != 0 {
|
if c.swchain != 0 {
|
||||||
vk.DestroySwapchain(c.dev, c.swchain)
|
vk.DestroySwapchain(c.dev, c.swchain)
|
||||||
c.swchain = 0
|
c.swchain = 0
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
type wlVkContext struct {
|
type wlVkContext struct {
|
||||||
win *window
|
win *window
|
||||||
inst vk.Instance
|
inst vk.Instance
|
||||||
|
surf vk.Surface
|
||||||
ctx *vkContext
|
ctx *vkContext
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,6 +40,7 @@ func init() {
|
|||||||
c := &wlVkContext{
|
c := &wlVkContext{
|
||||||
win: w,
|
win: w,
|
||||||
inst: inst,
|
inst: inst,
|
||||||
|
surf: surf,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
}
|
}
|
||||||
return c, nil
|
return c, nil
|
||||||
@@ -55,6 +57,7 @@ func (c *wlVkContext) API() gpu.API {
|
|||||||
|
|
||||||
func (c *wlVkContext) Release() {
|
func (c *wlVkContext) Release() {
|
||||||
c.ctx.release()
|
c.ctx.release()
|
||||||
|
vk.DestroySurface(c.inst, c.surf)
|
||||||
vk.DestroyInstance(c.inst)
|
vk.DestroyInstance(c.inst)
|
||||||
*c = wlVkContext{}
|
*c = wlVkContext{}
|
||||||
}
|
}
|
||||||
@@ -71,11 +74,13 @@ func (c *wlVkContext) Unlock() {}
|
|||||||
|
|
||||||
func (c *wlVkContext) Refresh() error {
|
func (c *wlVkContext) Refresh() error {
|
||||||
win, w, h := c.win.nativeWindow()
|
win, w, h := c.win.nativeWindow()
|
||||||
c.ctx.destroySurface()
|
if c.surf != 0 {
|
||||||
|
c.ctx.destroySwapchain()
|
||||||
|
vk.DestroySurface(c.inst, c.surf)
|
||||||
|
}
|
||||||
surf, err := vk.CreateAndroidSurface(c.inst, unsafe.Pointer(win))
|
surf, err := vk.CreateAndroidSurface(c.inst, unsafe.Pointer(win))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.ctx.setSurface(surf)
|
return c.ctx.refresh(surf, w, h)
|
||||||
return c.ctx.refresh(w, h)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
type wlVkContext struct {
|
type wlVkContext struct {
|
||||||
win *window
|
win *window
|
||||||
inst vk.Instance
|
inst vk.Instance
|
||||||
|
surf vk.Surface
|
||||||
ctx *vkContext
|
ctx *vkContext
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ func init() {
|
|||||||
c := &wlVkContext{
|
c := &wlVkContext{
|
||||||
win: w,
|
win: w,
|
||||||
inst: inst,
|
inst: inst,
|
||||||
|
surf: surf,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
}
|
}
|
||||||
return c, nil
|
return c, nil
|
||||||
@@ -58,6 +60,7 @@ func (c *wlVkContext) API() gpu.API {
|
|||||||
|
|
||||||
func (c *wlVkContext) Release() {
|
func (c *wlVkContext) Release() {
|
||||||
c.ctx.release()
|
c.ctx.release()
|
||||||
|
vk.DestroySurface(c.inst, c.surf)
|
||||||
vk.DestroyInstance(c.inst)
|
vk.DestroyInstance(c.inst)
|
||||||
*c = wlVkContext{}
|
*c = wlVkContext{}
|
||||||
}
|
}
|
||||||
@@ -74,5 +77,5 @@ func (c *wlVkContext) Unlock() {}
|
|||||||
|
|
||||||
func (c *wlVkContext) Refresh() error {
|
func (c *wlVkContext) Refresh() error {
|
||||||
_, w, h := c.win.surface()
|
_, w, h := c.win.surface()
|
||||||
return c.ctx.refresh(w, h)
|
return c.ctx.refresh(c.surf, w, h)
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -17,6 +17,7 @@ import (
|
|||||||
type x11VkContext struct {
|
type x11VkContext struct {
|
||||||
win *x11Window
|
win *x11Window
|
||||||
inst vk.Instance
|
inst vk.Instance
|
||||||
|
surf vk.Surface
|
||||||
ctx *vkContext
|
ctx *vkContext
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ func init() {
|
|||||||
c := &x11VkContext{
|
c := &x11VkContext{
|
||||||
win: w,
|
win: w,
|
||||||
inst: inst,
|
inst: inst,
|
||||||
|
surf: surf,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
}
|
}
|
||||||
return c, nil
|
return c, nil
|
||||||
@@ -58,6 +60,7 @@ func (c *x11VkContext) API() gpu.API {
|
|||||||
|
|
||||||
func (c *x11VkContext) Release() {
|
func (c *x11VkContext) Release() {
|
||||||
c.ctx.release()
|
c.ctx.release()
|
||||||
|
vk.DestroySurface(c.inst, c.surf)
|
||||||
vk.DestroyInstance(c.inst)
|
vk.DestroyInstance(c.inst)
|
||||||
*c = x11VkContext{}
|
*c = x11VkContext{}
|
||||||
}
|
}
|
||||||
@@ -74,5 +77,5 @@ func (c *x11VkContext) Unlock() {}
|
|||||||
|
|
||||||
func (c *x11VkContext) Refresh() error {
|
func (c *x11VkContext) Refresh() error {
|
||||||
_, w, h := c.win.window()
|
_, w, h := c.win.window()
|
||||||
return c.ctx.refresh(w, h)
|
return c.ctx.refresh(c.surf, w, h)
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-6
@@ -816,12 +816,12 @@ func CreateInstance(exts ...string) (Instance, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
inf := C.VkInstanceCreateInfo{
|
inf := C.VkInstanceCreateInfo{
|
||||||
sType: C.VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
sType: C.VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||||
enabledExtensionCount: C.uint32_t(len(exts)),
|
|
||||||
}
|
}
|
||||||
if len(exts) > 0 {
|
if len(exts) > 0 {
|
||||||
cexts := mallocCStringArr(exts)
|
cexts := mallocCStringArr(exts)
|
||||||
defer freeCStringArr(cexts)
|
defer freeCStringArr(cexts)
|
||||||
|
inf.enabledExtensionCount = C.uint32_t(len(exts))
|
||||||
inf.ppEnabledExtensionNames = &cexts[0]
|
inf.ppEnabledExtensionNames = &cexts[0]
|
||||||
}
|
}
|
||||||
var inst Instance
|
var inst Instance
|
||||||
@@ -861,17 +861,25 @@ func GetPhysicalDeviceQueueFamilyProperties(pd PhysicalDevice) []QueueFamilyProp
|
|||||||
return queues
|
return queues
|
||||||
}
|
}
|
||||||
|
|
||||||
func ChoosePhysicalDevice(inst Instance, surf Surface) (PhysicalDevice, int, error) {
|
func EnumeratePhysicalDevices(inst Instance) ([]PhysicalDevice, error) {
|
||||||
var count C.uint32_t
|
var count C.uint32_t
|
||||||
if err := vkErr(C.vkEnumeratePhysicalDevices(funcs.vkEnumeratePhysicalDevices, inst, &count, nil)); err != nil {
|
if err := vkErr(C.vkEnumeratePhysicalDevices(funcs.vkEnumeratePhysicalDevices, inst, &count, nil)); err != nil {
|
||||||
return nil, 0, fmt.Errorf("vulkan: vkEnumeratePhysicalDevices: %w", err)
|
return nil, fmt.Errorf("vulkan: vkEnumeratePhysicalDevices: %w", err)
|
||||||
}
|
}
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return nil, 0, errors.New("vulkan: no devices available")
|
return nil, nil
|
||||||
}
|
}
|
||||||
devs := make([]C.VkPhysicalDevice, count)
|
devs := make([]C.VkPhysicalDevice, count)
|
||||||
if err := vkErr(C.vkEnumeratePhysicalDevices(funcs.vkEnumeratePhysicalDevices, inst, &count, &devs[0])); err != nil {
|
if err := vkErr(C.vkEnumeratePhysicalDevices(funcs.vkEnumeratePhysicalDevices, inst, &count, &devs[0])); err != nil {
|
||||||
return nil, 0, fmt.Errorf("vulkan: vkEnumeratePhysicalDevices: %w", err)
|
return nil, fmt.Errorf("vulkan: vkEnumeratePhysicalDevices: %w", err)
|
||||||
|
}
|
||||||
|
return devs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChoosePhysicalDevice(inst Instance, surf Surface) (PhysicalDevice, int, error) {
|
||||||
|
devs, err := EnumeratePhysicalDevices(inst)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
for _, pd := range devs {
|
for _, pd := range devs {
|
||||||
const caps = C.VK_QUEUE_GRAPHICS_BIT | C.VK_QUEUE_COMPUTE_BIT
|
const caps = C.VK_QUEUE_GRAPHICS_BIT | C.VK_QUEUE_COMPUTE_BIT
|
||||||
|
|||||||
Reference in New Issue
Block a user