gpu/internal/vulkan,internal/vk: allocate descriptor sets in batches

We know exactly the configuration and number of sets in each pool, so
we may as well allocate them al up front.

References: https://todo.sr.ht/~eliasnaur/gio/375
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2022-03-11 18:02:38 +01:00
parent e8aa881d40
commit 7785310e9d
2 changed files with 56 additions and 66 deletions
+45 -59
View File
@@ -107,8 +107,8 @@ type descPool struct {
layout vk.PipelineLayout
descLayout vk.DescriptorSetLayout
pool vk.DescriptorPool
sets []vk.DescriptorSet
size int
cap int
texBinds []int
imgBinds []int
bufBinds []int
@@ -224,7 +224,6 @@ func (b *Backend) resetPipes() {
continue
}
if p.desc.size > 0 {
vk.ResetDescriptorPool(b.dev, p.desc.pool)
p.desc.size = 0
}
}
@@ -686,74 +685,61 @@ func (p *descPool) release(d vk.Device) {
}
func (p *descPool) bindDescriptorSet(b *Backend, cmdBuf vk.CommandBuffer, bindPoint vk.PipelineBindPoint, texBinds [texUnits]*Texture, bufBinds [storageUnits]*Buffer) {
realloced := false
destroyPool := func() {
if p.size == len(p.sets) {
l := p.descLayout
if l == 0 {
panic("vulkan: descriptor set is dirty, but pipeline has empty layout")
}
newCap := len(p.sets) * 2
if pool := p.pool; pool != 0 {
b.deferFunc(func(d vk.Device) {
vk.DestroyDescriptorPool(d, pool)
})
}
p.pool = 0
p.cap = 0
}
for {
if p.size == p.cap {
if realloced {
panic("vulkan: vkAllocateDescriptorSet failed on a newly allocated descriptor pool")
}
newCap := p.cap * 2
destroyPool()
realloced = true
const initialPoolSize = 100
if newCap < initialPoolSize {
newCap = initialPoolSize
}
var poolSizes []vk.DescriptorPoolSize
if n := len(p.texBinds); n > 0 {
poolSizes = append(poolSizes, vk.BuildDescriptorPoolSize(vk.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, newCap*n))
}
if n := len(p.imgBinds); n > 0 {
poolSizes = append(poolSizes, vk.BuildDescriptorPoolSize(vk.DESCRIPTOR_TYPE_STORAGE_IMAGE, newCap*n))
}
if n := len(p.bufBinds); n > 0 {
poolSizes = append(poolSizes, vk.BuildDescriptorPoolSize(vk.DESCRIPTOR_TYPE_STORAGE_BUFFER, newCap*n))
}
pool, err := vk.CreateDescriptorPool(b.dev, newCap, poolSizes)
if err != nil {
panic(fmt.Errorf("vulkan: failed to allocate descriptor pool with %d descriptors", newCap))
}
p.pool = pool
p.cap = newCap
p.size = 0
const initialPoolSize = 100
if newCap < initialPoolSize {
newCap = initialPoolSize
}
l := p.descLayout
if l == 0 {
panic("vulkan: descriptor set is dirty, but pipeline has empty layout")
var poolSizes []vk.DescriptorPoolSize
if n := len(p.texBinds); n > 0 {
poolSizes = append(poolSizes, vk.BuildDescriptorPoolSize(vk.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, newCap*n))
}
descSet, err := vk.AllocateDescriptorSet(b.dev, p.pool, l)
if n := len(p.imgBinds); n > 0 {
poolSizes = append(poolSizes, vk.BuildDescriptorPoolSize(vk.DESCRIPTOR_TYPE_STORAGE_IMAGE, newCap*n))
}
if n := len(p.bufBinds); n > 0 {
poolSizes = append(poolSizes, vk.BuildDescriptorPoolSize(vk.DESCRIPTOR_TYPE_STORAGE_BUFFER, newCap*n))
}
pool, err := vk.CreateDescriptorPool(b.dev, newCap, poolSizes)
if err != nil {
destroyPool()
continue
panic(fmt.Errorf("vulkan: failed to allocate descriptor pool with %d descriptors: %v", newCap, err))
}
p.size++
for _, bind := range p.texBinds {
tex := texBinds[bind]
write := vk.BuildWriteDescriptorSetImage(descSet, bind, vk.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, tex.sampler, tex.view, vk.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
vk.UpdateDescriptorSet(b.dev, write)
p.pool = pool
sets, err := vk.AllocateDescriptorSets(b.dev, p.pool, l, newCap)
if err != nil {
panic(fmt.Errorf("vulkan: failed to allocate descriptor with %d sets: %v", newCap, err))
}
for _, bind := range p.imgBinds {
tex := texBinds[bind]
write := vk.BuildWriteDescriptorSetImage(descSet, bind, vk.DESCRIPTOR_TYPE_STORAGE_IMAGE, 0, tex.view, vk.IMAGE_LAYOUT_GENERAL)
vk.UpdateDescriptorSet(b.dev, write)
}
for _, bind := range p.bufBinds {
buf := bufBinds[bind]
write := vk.BuildWriteDescriptorSetBuffer(descSet, bind, vk.DESCRIPTOR_TYPE_STORAGE_BUFFER, buf.buf)
vk.UpdateDescriptorSet(b.dev, write)
}
vk.CmdBindDescriptorSets(cmdBuf, bindPoint, p.layout, 0, []vk.DescriptorSet{descSet})
break
p.sets = sets
p.size = 0
}
descSet := p.sets[p.size]
p.size++
for _, bind := range p.texBinds {
tex := texBinds[bind]
write := vk.BuildWriteDescriptorSetImage(descSet, bind, vk.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, tex.sampler, tex.view, vk.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
vk.UpdateDescriptorSet(b.dev, write)
}
for _, bind := range p.imgBinds {
tex := texBinds[bind]
write := vk.BuildWriteDescriptorSetImage(descSet, bind, vk.DESCRIPTOR_TYPE_STORAGE_IMAGE, 0, tex.view, vk.IMAGE_LAYOUT_GENERAL)
vk.UpdateDescriptorSet(b.dev, write)
}
for _, bind := range p.bufBinds {
buf := bufBinds[bind]
write := vk.BuildWriteDescriptorSetBuffer(descSet, bind, vk.DESCRIPTOR_TYPE_STORAGE_BUFFER, buf.buf)
vk.UpdateDescriptorSet(b.dev, write)
}
vk.CmdBindDescriptorSets(cmdBuf, bindPoint, p.layout, 0, []vk.DescriptorSet{descSet})
}
func (t *Texture) imageBarrier(cmdBuf vk.CommandBuffer, layout vk.ImageLayout, stage vk.PipelineStageFlags, access vk.AccessFlags) {
+11 -7
View File
@@ -1739,18 +1739,22 @@ func UpdateDescriptorSet(d Device, write WriteDescriptorSet) {
C.vkUpdateDescriptorSets(funcs.vkUpdateDescriptorSets, d, write, 0, nil)
}
func AllocateDescriptorSet(d Device, pool DescriptorPool, layout DescriptorSetLayout) (DescriptorSet, error) {
func AllocateDescriptorSets(d Device, pool DescriptorPool, layout DescriptorSetLayout, count int) ([]DescriptorSet, error) {
layouts := make([]DescriptorSetLayout, count)
for i := range layouts {
layouts[i] = layout
}
inf := C.VkDescriptorSetAllocateInfo{
sType: C.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
descriptorPool: pool,
descriptorSetCount: 1,
pSetLayouts: &layout,
descriptorSetCount: C.uint32_t(count),
pSetLayouts: &layouts[0],
}
var set C.VkDescriptorSet
if err := vkErr(C.vkAllocateDescriptorSets(funcs.vkAllocateDescriptorSets, d, inf, &set)); err != nil {
return nilDescriptorSet, fmt.Errorf("vulkan: vkAllocateDescriptorSets: %w", err)
sets := make([]DescriptorSet, count, count)
if err := vkErr(C.vkAllocateDescriptorSets(funcs.vkAllocateDescriptorSets, d, inf, &sets[0])); err != nil {
return nil, fmt.Errorf("vulkan: vkAllocateDescriptorSets: %w", err)
}
return set, nil
return sets, nil
}
func CreateComputePipeline(d Device, mod ShaderModule, layout PipelineLayout) (Pipeline, error) {