153 lines
3.1 KiB
Go
153 lines
3.1 KiB
Go
|
|
package framebuffer
|
||
|
|
|
||
|
|
import (
|
||
|
|
"zworld/engine/renderapi/device"
|
||
|
|
"zworld/engine/renderapi/image"
|
||
|
|
"zworld/engine/renderapi/renderpass"
|
||
|
|
"zworld/engine/renderapi/renderpass/attachment"
|
||
|
|
"zworld/engine/renderapi/vkerror"
|
||
|
|
"zworld/engine/util"
|
||
|
|
|
||
|
|
"github.com/vkngwrapper/core/v2/core1_0"
|
||
|
|
"github.com/vkngwrapper/core/v2/driver"
|
||
|
|
)
|
||
|
|
|
||
|
|
type T interface {
|
||
|
|
device.Resource[core1_0.Framebuffer]
|
||
|
|
|
||
|
|
Attachment(attachment.Name) image.View
|
||
|
|
Size() (int, int)
|
||
|
|
}
|
||
|
|
|
||
|
|
type framebuf struct {
|
||
|
|
ptr core1_0.Framebuffer
|
||
|
|
device device.T
|
||
|
|
name string
|
||
|
|
attachments map[attachment.Name]image.View
|
||
|
|
views []image.View
|
||
|
|
images []image.T
|
||
|
|
width int
|
||
|
|
height int
|
||
|
|
}
|
||
|
|
|
||
|
|
func New(device device.T, name string, width, height int, pass renderpass.T) (T, error) {
|
||
|
|
attachments := pass.Attachments()
|
||
|
|
depth := pass.Depth()
|
||
|
|
|
||
|
|
images := make([]image.T, 0, len(attachments)+1)
|
||
|
|
views := make([]image.View, 0, len(attachments)+1)
|
||
|
|
attachs := make(map[attachment.Name]image.View)
|
||
|
|
|
||
|
|
cleanup := func() {
|
||
|
|
// clean up the mess we've made so far
|
||
|
|
for _, view := range views {
|
||
|
|
view.Destroy()
|
||
|
|
}
|
||
|
|
for _, image := range images {
|
||
|
|
image.Destroy()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
allocate := func(attach attachment.T, aspect core1_0.ImageAspectFlags) error {
|
||
|
|
img, ownership, err := attach.Image().Next(
|
||
|
|
device,
|
||
|
|
name,
|
||
|
|
width, height,
|
||
|
|
)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if ownership {
|
||
|
|
// the framebuffer is responsible for deallocating the image
|
||
|
|
images = append(images, img)
|
||
|
|
}
|
||
|
|
|
||
|
|
view, err := img.View(img.Format(), core1_0.ImageAspectFlags(aspect))
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
views = append(views, view)
|
||
|
|
|
||
|
|
attachs[attach.Name()] = view
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, attach := range attachments {
|
||
|
|
if err := allocate(attach, core1_0.ImageAspectColor); err != nil {
|
||
|
|
cleanup()
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if depth != nil {
|
||
|
|
if err := allocate(depth, core1_0.ImageAspectDepth); err != nil {
|
||
|
|
cleanup()
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
info := core1_0.FramebufferCreateInfo{
|
||
|
|
RenderPass: pass.Ptr(),
|
||
|
|
Attachments: util.Map(views, func(v image.View) core1_0.ImageView { return v.Ptr() }),
|
||
|
|
Width: width,
|
||
|
|
Height: height,
|
||
|
|
Layers: 1,
|
||
|
|
}
|
||
|
|
|
||
|
|
var ptr core1_0.Framebuffer
|
||
|
|
ptr, result, err := device.Ptr().CreateFramebuffer(nil, info)
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
if result != core1_0.VKSuccess {
|
||
|
|
cleanup()
|
||
|
|
return nil, vkerror.FromResult(result)
|
||
|
|
}
|
||
|
|
|
||
|
|
device.SetDebugObjectName(driver.VulkanHandle(ptr.Handle()), core1_0.ObjectTypeFramebuffer, name)
|
||
|
|
|
||
|
|
return &framebuf{
|
||
|
|
ptr: ptr,
|
||
|
|
device: device,
|
||
|
|
name: name,
|
||
|
|
width: width,
|
||
|
|
height: height,
|
||
|
|
images: images,
|
||
|
|
views: views,
|
||
|
|
attachments: attachs,
|
||
|
|
}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (b *framebuf) Ptr() core1_0.Framebuffer {
|
||
|
|
return b.ptr
|
||
|
|
}
|
||
|
|
|
||
|
|
func (b *framebuf) Size() (int, int) {
|
||
|
|
return b.width, b.height
|
||
|
|
}
|
||
|
|
|
||
|
|
func (b *framebuf) Attachment(name attachment.Name) image.View {
|
||
|
|
return b.attachments[name]
|
||
|
|
}
|
||
|
|
|
||
|
|
func (b *framebuf) Destroy() {
|
||
|
|
if b.ptr == nil {
|
||
|
|
panic("framebuffer already destroyed")
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, image := range b.images {
|
||
|
|
image.Destroy()
|
||
|
|
}
|
||
|
|
b.images = nil
|
||
|
|
|
||
|
|
for _, view := range b.views {
|
||
|
|
view.Destroy()
|
||
|
|
}
|
||
|
|
b.views = nil
|
||
|
|
|
||
|
|
b.attachments = nil
|
||
|
|
|
||
|
|
b.ptr.Destroy(nil)
|
||
|
|
b.ptr = nil
|
||
|
|
b.device = nil
|
||
|
|
}
|