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

116 lines
2.5 KiB
Go

package descriptor
import (
"log"
"zworld/engine/renderapi/device"
"github.com/vkngwrapper/core/v2/common"
"github.com/vkngwrapper/core/v2/core1_0"
"github.com/vkngwrapper/core/v2/driver"
"github.com/vkngwrapper/extensions/v2/ext_descriptor_indexing"
)
type Pool interface {
device.Resource[core1_0.DescriptorPool]
Allocate(layouts SetLayout) Set
Recreate()
}
type pool struct {
ptr core1_0.DescriptorPool
device device.T
sizes []core1_0.DescriptorPoolSize
maxSets int
allocatedSets int
allocatedCounts map[core1_0.DescriptorType]int
}
func NewPool(device device.T, sets int, sizes []core1_0.DescriptorPoolSize) Pool {
p := &pool{
device: device,
ptr: nil,
sizes: sizes,
maxSets: sets,
allocatedCounts: make(map[core1_0.DescriptorType]int),
}
p.Recreate()
return p
}
func (p *pool) Ptr() core1_0.DescriptorPool {
return p.ptr
}
func (p *pool) Recreate() {
p.Destroy()
info := core1_0.DescriptorPoolCreateInfo{
Flags: ext_descriptor_indexing.DescriptorPoolCreateUpdateAfterBind,
PoolSizes: p.sizes,
MaxSets: p.maxSets,
}
ptr, result, err := p.device.Ptr().CreateDescriptorPool(nil, info)
if err != nil {
panic(err)
}
if result != core1_0.VKSuccess {
panic("failed to create descriptor pooll")
}
p.ptr = ptr
}
func (p *pool) Destroy() {
if p.ptr == nil {
return
}
p.ptr.Destroy(nil)
p.ptr = nil
}
func (p *pool) Allocate(layout SetLayout) Set {
info := core1_0.DescriptorSetAllocateInfo{
DescriptorPool: p.ptr,
SetLayouts: []core1_0.DescriptorSetLayout{layout.Ptr()},
}
if layout.VariableCount() > 0 {
variableInfo := ext_descriptor_indexing.DescriptorSetVariableDescriptorCountAllocateInfo{
DescriptorCounts: []int{layout.VariableCount()},
}
info.NextOptions = common.NextOptions{Next: variableInfo}
}
ptr, r, err := p.device.Ptr().AllocateDescriptorSets(info)
if err != nil {
log.Println("allocated sets:", p.allocatedSets, "/", p.maxSets)
log.Println("allocated counts:", p.allocatedCounts)
panic(err)
}
if r != core1_0.VKSuccess {
if r == core1_0.VKErrorOutOfDeviceMemory {
panic("failed to allocate descriptor set: out of pool memory")
}
panic("failed to allocate descriptor set")
}
p.device.SetDebugObjectName(
driver.VulkanHandle(ptr[0].Handle()),
core1_0.ObjectTypeDescriptorSet,
layout.Name())
p.allocatedSets++
for kind, count := range layout.Counts() {
current, _ := p.allocatedCounts[kind]
p.allocatedCounts[kind] = current + count
}
return &set{
device: p.device,
ptr: ptr[0],
layout: layout,
}
}