zworld/engine/renderapi/image/image.go
2024-01-14 22:56:06 +08:00

210 lines
4.5 KiB
Go

package image
import (
"zworld/engine/renderapi/device"
"zworld/engine/renderapi/vkerror"
"zworld/plugins/math/vec3"
"github.com/vkngwrapper/core/v2/core1_0"
"github.com/vkngwrapper/core/v2/driver"
)
type T interface {
device.Resource[core1_0.Image]
Key() string
Memory() device.Memory
View(format core1_0.Format, mask core1_0.ImageAspectFlags) (View, error)
Width() int
Height() int
Format() core1_0.Format
Size() vec3.T
}
type image struct {
Args
ptr core1_0.Image
device device.T
memory device.Memory
}
type Args struct {
Type core1_0.ImageType
Key string
Width int
Height int
Depth int
Layers int
Levels int
Format core1_0.Format
Usage core1_0.ImageUsageFlags
Tiling core1_0.ImageTiling
Sharing core1_0.SharingMode
Layout core1_0.ImageLayout
Memory core1_0.MemoryPropertyFlags
}
func New2D(device device.T, key string, width, height int, format core1_0.Format, usage core1_0.ImageUsageFlags) (T, error) {
return New(device, Args{
Type: core1_0.ImageType2D,
Key: key,
Width: width,
Height: height,
Depth: 1,
Layers: 1,
Levels: 1,
Format: format,
Usage: usage,
Tiling: core1_0.ImageTilingOptimal,
Sharing: core1_0.SharingModeExclusive,
Layout: core1_0.ImageLayoutUndefined,
Memory: core1_0.MemoryPropertyDeviceLocal,
})
}
func New(device device.T, args Args) (T, error) {
if args.Depth < 1 {
args.Depth = 1
}
if args.Levels < 1 {
args.Levels = 1
}
if args.Layers < 1 {
args.Layers = 1
}
queueIdx := device.GetQueueFamilyIndex(core1_0.QueueGraphics)
info := core1_0.ImageCreateInfo{
ImageType: args.Type,
Format: args.Format,
Extent: core1_0.Extent3D{
Width: args.Width,
Height: args.Height,
Depth: args.Depth,
},
MipLevels: args.Levels,
ArrayLayers: args.Layers,
Samples: core1_0.Samples1,
Tiling: args.Tiling,
Usage: core1_0.ImageUsageFlags(args.Usage),
SharingMode: args.Sharing,
QueueFamilyIndices: []uint32{uint32(queueIdx)},
InitialLayout: args.Layout,
}
ptr, result, err := device.Ptr().CreateImage(nil, info)
if err != nil {
return nil, err
}
if result != core1_0.VKSuccess {
return nil, vkerror.FromResult(result)
}
// set image debug name
if args.Key != "" {
device.SetDebugObjectName(driver.VulkanHandle(ptr.Handle()), core1_0.ObjectTypeImage, args.Key)
}
memreq := ptr.MemoryRequirements()
mem := device.Allocate(args.Key, core1_0.MemoryRequirements{
Size: int(memreq.Size),
Alignment: int(memreq.Alignment),
MemoryTypeBits: memreq.MemoryTypeBits,
}, core1_0.MemoryPropertyFlags(args.Memory))
result, err = ptr.BindImageMemory(mem.Ptr(), 0)
if err != nil {
ptr.Destroy(nil)
mem.Destroy()
return nil, err
}
if result != core1_0.VKSuccess {
ptr.Destroy(nil)
mem.Destroy()
return nil, vkerror.FromResult(result)
}
return &image{
Args: args,
ptr: ptr,
device: device,
memory: mem,
}, nil
}
func Wrap(dev device.T, ptr core1_0.Image, args Args) T {
return &image{
ptr: ptr,
device: dev,
memory: nil,
Args: args,
}
}
func (i *image) Ptr() core1_0.Image {
return i.ptr
}
func (i *image) Memory() device.Memory {
return i.memory
}
func (i *image) Key() string { return i.Args.Key }
func (i *image) Width() int { return i.Args.Width }
func (i *image) Height() int { return i.Args.Height }
func (i *image) Format() core1_0.Format { return i.Args.Format }
func (i *image) Size() vec3.T {
return vec3.T{
X: float32(i.Args.Width),
Y: float32(i.Args.Height),
Z: float32(i.Args.Depth),
}
}
func (i *image) Destroy() {
if i.memory != nil {
i.memory.Destroy()
if i.ptr != nil {
i.ptr.Destroy(nil)
}
}
i.ptr = nil
i.memory = nil
i.device = nil
}
func (i *image) View(format core1_0.Format, mask core1_0.ImageAspectFlags) (View, error) {
info := core1_0.ImageViewCreateInfo{
Image: i.ptr,
ViewType: core1_0.ImageViewType2D,
Format: format,
SubresourceRange: core1_0.ImageSubresourceRange{
AspectMask: mask,
BaseMipLevel: 0,
LevelCount: 1,
BaseArrayLayer: 0,
LayerCount: 1,
},
}
ptr, result, err := i.device.Ptr().CreateImageView(nil, info)
if err != nil {
return nil, err
}
if result != core1_0.VKSuccess {
return nil, vkerror.FromResult(result)
}
if i.Args.Key != "" {
i.device.SetDebugObjectName(driver.VulkanHandle(ptr.Handle()), core1_0.ObjectTypeImageView, i.Args.Key)
}
return &imgview{
ptr: ptr,
device: i.device,
image: i,
format: format,
}, nil
}