From 132a8571ff3042deaf8070645ee58fd514e5c79c Mon Sep 17 00:00:00 2001 From: knokko Date: Sun, 11 Aug 2024 18:51:59 +0200 Subject: [PATCH] Refactor descriptor handling --- .../github/knokko/boiler/samples/HelloXR.java | 43 +++------- .../boiler/samples/TerrainPlayground.java | 41 +++------- .../boiler/descriptors/BoilerDescriptors.java | 16 +--- .../descriptors/DescriptorSetLayout.java | 81 +++++++++++++++++++ .../descriptors/FixedDescriptorBank.java | 49 ++--------- .../descriptors/GrowingDescriptorBank.java | 76 +++-------------- .../HomogeneousDescriptorPool.java | 35 ++++++++ .../boiler/compute/TestComputePipelines.java | 32 ++------ .../descriptors/TestDescriptorSetLayout.java | 56 +++++++++++++ .../descriptors/TestFixedDescriptorBank.java | 15 +--- .../TestGrowingDescriptorBank.java | 15 +--- .../boiler/descriptors/TestWriteImage.java | 31 ++----- 12 files changed, 239 insertions(+), 251 deletions(-) create mode 100644 src/main/java/com/github/knokko/boiler/descriptors/DescriptorSetLayout.java create mode 100644 src/main/java/com/github/knokko/boiler/descriptors/HomogeneousDescriptorPool.java create mode 100644 src/test/java/com/github/knokko/boiler/descriptors/TestDescriptorSetLayout.java diff --git a/samples/src/main/java/com/github/knokko/boiler/samples/HelloXR.java b/samples/src/main/java/com/github/knokko/boiler/samples/HelloXR.java index 111635e..8d43ee2 100644 --- a/samples/src/main/java/com/github/knokko/boiler/samples/HelloXR.java +++ b/samples/src/main/java/com/github/knokko/boiler/samples/HelloXR.java @@ -3,6 +3,8 @@ import com.github.knokko.boiler.builder.BoilerBuilder; import com.github.knokko.boiler.builder.xr.BoilerXrBuilder; import com.github.knokko.boiler.commands.CommandRecorder; +import com.github.knokko.boiler.descriptors.DescriptorSetLayout; +import com.github.knokko.boiler.descriptors.HomogeneousDescriptorPool; import com.github.knokko.boiler.images.VmaImage; import com.github.knokko.boiler.pipelines.GraphicsPipelineBuilder; import com.github.knokko.boiler.pipelines.ShaderInfo; @@ -37,6 +39,7 @@ public class HelloXR { @SuppressWarnings("resource") public static void main(String[] args) throws InterruptedException { + // TODO Shorten this sample using newer vk-boiler features var boiler = new BoilerBuilder( VK_API_VERSION_1_0, "HelloXR", 1 ) @@ -174,8 +177,8 @@ public static void main(String[] args) throws InterruptedException { 5 * 64, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, "MatrixBuffer" ); - long descriptorSetLayout; - long descriptorPool; + DescriptorSetLayout descriptorSetLayout; + HomogeneousDescriptorPool descriptorPool; long descriptorSet; long pipelineLayout; long graphicsPipeline; @@ -190,35 +193,11 @@ public static void main(String[] args) throws InterruptedException { matricesBinding.pImmutableSamplers(null); descriptorSetLayout = boiler.descriptors.createLayout(stack, layoutBindings, "MatricesLayout"); - - var poolSizes = VkDescriptorPoolSize.calloc(1, stack); - poolSizes.type(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - poolSizes.descriptorCount(1); - - var ciDescriptorPool = VkDescriptorPoolCreateInfo.calloc(stack); - ciDescriptorPool.sType$Default(); - ciDescriptorPool.flags(0); - ciDescriptorPool.maxSets(1); - ciDescriptorPool.pPoolSizes(poolSizes); - - var pDescriptorPool = stack.callocLong(1); - assertVkSuccess(vkCreateDescriptorPool( - boiler.vkDevice(), ciDescriptorPool, null, pDescriptorPool - ), "CreateDescriptorPool", "MatricesPool"); - descriptorPool = pDescriptorPool.get(0); - descriptorSet = boiler.descriptors.allocate( - stack, 1, descriptorPool, "MatricesSet", descriptorSetLayout - )[0]; + descriptorPool = descriptorSetLayout.createPool(1, 0, "MatricesPool"); + descriptorSet = descriptorPool.allocate(stack, 1)[0]; var descriptorWrites = VkWriteDescriptorSet.calloc(1, stack); - var matrixWrite = descriptorWrites.get(0); - matrixWrite.sType$Default(); - matrixWrite.dstSet(descriptorSet); - matrixWrite.dstBinding(0); - matrixWrite.dstArrayElement(0); - matrixWrite.descriptorCount(1); - matrixWrite.descriptorType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - matrixWrite.pBufferInfo(boiler.descriptors.bufferInfo(stack, matrixBuffer)); + boiler.descriptors.writeBuffer(stack, descriptorWrites, descriptorSet, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, matrixBuffer); vkUpdateDescriptorSets(boiler.vkDevice(), descriptorWrites, null); @@ -228,7 +207,7 @@ public static void main(String[] args) throws InterruptedException { pushConstants.size(8); pipelineLayout = boiler.pipelines.createLayout( - stack, pushConstants, "SimplePipelineLayout", descriptorSetLayout + stack, pushConstants, "SimplePipelineLayout", descriptorSetLayout.vkDescriptorSetLayout ); var vertexShader = boiler.pipelines.createShaderModule( stack, "com/github/knokko/boiler/samples/graphics/xr.vert.spv", "VertexShader" @@ -562,8 +541,8 @@ protected void submitAndWaitRender(MemoryStack stack) { vkDestroyCommandPool(boiler.vkDevice(), commandPool, null); vkDestroyPipeline(boiler.vkDevice(), graphicsPipeline, null); vkDestroyPipelineLayout(boiler.vkDevice(), pipelineLayout, null); - vkDestroyDescriptorPool(boiler.vkDevice(), descriptorPool, null); - vkDestroyDescriptorSetLayout(boiler.vkDevice(), descriptorSetLayout, null); + descriptorPool.destroy(); + descriptorSetLayout.destroy(); for (long imageView : swapchainImageViews) { vkDestroyImageView(boiler.vkDevice(), imageView, null); } diff --git a/samples/src/main/java/com/github/knokko/boiler/samples/TerrainPlayground.java b/samples/src/main/java/com/github/knokko/boiler/samples/TerrainPlayground.java index 15158ec..55e3594 100644 --- a/samples/src/main/java/com/github/knokko/boiler/samples/TerrainPlayground.java +++ b/samples/src/main/java/com/github/knokko/boiler/samples/TerrainPlayground.java @@ -5,6 +5,8 @@ import com.github.knokko.boiler.builder.instance.ValidationFeatures; import com.github.knokko.boiler.commands.CommandRecorder; import com.github.knokko.boiler.cull.FrustumCuller; +import com.github.knokko.boiler.descriptors.DescriptorSetLayout; +import com.github.knokko.boiler.descriptors.HomogeneousDescriptorPool; import com.github.knokko.boiler.images.VmaImage; import com.github.knokko.boiler.instance.BoilerInstance; import com.github.knokko.boiler.pipelines.GraphicsPipelineBuilder; @@ -138,7 +140,7 @@ private static long createRenderPass(MemoryStack stack, BoilerInstance boiler, i return renderPass; } - private static long createDescriptorSetLayout(MemoryStack stack, BoilerInstance boiler) { + private static DescriptorSetLayout createDescriptorSetLayout(MemoryStack stack, BoilerInstance boiler) { var bindings = VkDescriptorSetLayoutBinding.calloc(3, stack); var camera = bindings.get(0); camera.binding(0); @@ -361,10 +363,10 @@ public static void main(String[] args) throws InterruptedException { 64, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, "UniformBuffer" ); long renderPass; - long descriptorSetLayout; + DescriptorSetLayout descriptorSetLayout; long pipelineLayout; long groundPipeline; - long descriptorPool; + HomogeneousDescriptorPool descriptorPool; long descriptorSet; int depthFormat; long heightSampler; @@ -377,33 +379,12 @@ public static void main(String[] args) throws InterruptedException { renderPass = createRenderPass(stack, boiler, depthFormat); descriptorSetLayout = createDescriptorSetLayout(stack, boiler); - pipelineLayout = createGroundPipelineLayout(stack, boiler, descriptorSetLayout); + pipelineLayout = createGroundPipelineLayout(stack, boiler, descriptorSetLayout.vkDescriptorSetLayout); groundPipeline = createGroundPipeline(stack, boiler, pipelineLayout, renderPass); - var poolSizes = VkDescriptorPoolSize.calloc(3, stack); - var uniformPoolSize = poolSizes.get(0); - uniformPoolSize.type(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - uniformPoolSize.descriptorCount(1); - var heightMapPoolSize = poolSizes.get(1); - heightMapPoolSize.type(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); - heightMapPoolSize.descriptorCount(1); - var normalMapPoolSize = poolSizes.get(2); - normalMapPoolSize.type(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); - normalMapPoolSize.descriptorCount(2); - - var ciDescriptorPool = VkDescriptorPoolCreateInfo.calloc(stack); - ciDescriptorPool.sType$Default(); - ciDescriptorPool.maxSets(1); - ciDescriptorPool.pPoolSizes(poolSizes); - - var pDescriptorPool = stack.callocLong(1); - assertVkSuccess(vkCreateDescriptorPool( - boiler.vkDevice(), ciDescriptorPool, null, pDescriptorPool - ), "CreateDescriptorPool", "TerrainPlayground"); - descriptorPool = pDescriptorPool.get(0); - boiler.debug.name(stack, descriptorPool, VK_OBJECT_TYPE_DESCRIPTOR_POOL, "TerrainDescriptorPool"); - - descriptorSet = boiler.descriptors.allocate(stack, 1, descriptorPool, "TerrainDescriptor", descriptorSetLayout)[0]; + descriptorPool = descriptorSetLayout.createPool(1, 0, "TerrainDescriptorPool"); + + descriptorSet = descriptorPool.allocate(stack, 1)[0]; heightSampler = boiler.images.createSampler( stack, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, @@ -668,10 +649,10 @@ class CameraController { vkDestroySemaphore(boiler.vkDevice(), timeline, null); vkDestroyCommandPool(boiler.vkDevice(), commandPool, null); - vkDestroyDescriptorPool(boiler.vkDevice(), descriptorPool, null); + descriptorPool.destroy(); vkDestroyPipeline(boiler.vkDevice(), groundPipeline, null); vkDestroyPipelineLayout(boiler.vkDevice(), pipelineLayout, null); - vkDestroyDescriptorSetLayout(boiler.vkDevice(), descriptorSetLayout, null); + descriptorSetLayout.destroy(); vkDestroyRenderPass(boiler.vkDevice(), renderPass, null); vmaDestroyBuffer(boiler.vmaAllocator(), uniformBuffer.vkBuffer(), uniformBuffer.vmaAllocation()); vkDestroyImageView(boiler.vkDevice(), heightImage.vkImageView(), null); diff --git a/src/main/java/com/github/knokko/boiler/descriptors/BoilerDescriptors.java b/src/main/java/com/github/knokko/boiler/descriptors/BoilerDescriptors.java index 382e955..c4e8496 100644 --- a/src/main/java/com/github/knokko/boiler/descriptors/BoilerDescriptors.java +++ b/src/main/java/com/github/knokko/boiler/descriptors/BoilerDescriptors.java @@ -16,20 +16,8 @@ public BoilerDescriptors(BoilerInstance instance) { this.instance = instance; } - public long createLayout(MemoryStack stack, VkDescriptorSetLayoutBinding.Buffer bindings, String name) { - var ciLayout = VkDescriptorSetLayoutCreateInfo.calloc(stack); - ciLayout.sType$Default(); - ciLayout.flags(0); - ciLayout.pBindings(bindings); - - var pLayout = stack.callocLong(1); - assertVkSuccess(vkCreateDescriptorSetLayout( - instance.vkDevice(), ciLayout, null, pLayout - ), "CreateDescriptorSetLayout", name); - long layout = pLayout.get(0); - - instance.debug.name(stack, layout, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, name); - return layout; + public DescriptorSetLayout createLayout(MemoryStack stack, VkDescriptorSetLayoutBinding.Buffer bindings, String name) { + return new DescriptorSetLayout(stack, bindings, instance, name); } public long[] allocate(MemoryStack stack, int amount, long descriptorPool, String name, long... layouts) { diff --git a/src/main/java/com/github/knokko/boiler/descriptors/DescriptorSetLayout.java b/src/main/java/com/github/knokko/boiler/descriptors/DescriptorSetLayout.java new file mode 100644 index 0000000..5547f83 --- /dev/null +++ b/src/main/java/com/github/knokko/boiler/descriptors/DescriptorSetLayout.java @@ -0,0 +1,81 @@ +package com.github.knokko.boiler.descriptors; + +import com.github.knokko.boiler.instance.BoilerInstance; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.vulkan.VkDescriptorPoolCreateInfo; +import org.lwjgl.vulkan.VkDescriptorPoolSize; +import org.lwjgl.vulkan.VkDescriptorSetLayoutBinding; +import org.lwjgl.vulkan.VkDescriptorSetLayoutCreateInfo; + +import java.util.HashMap; +import java.util.Map; + +import static com.github.knokko.boiler.exceptions.VulkanFailureException.assertVkSuccess; +import static org.lwjgl.system.MemoryStack.stackPush; +import static org.lwjgl.vulkan.VK10.*; + +public class DescriptorSetLayout { + + final BoilerInstance instance; + public final long vkDescriptorSetLayout; + + final Map descriptorTypeCounts = new HashMap<>(); + + DescriptorSetLayout(MemoryStack stack, VkDescriptorSetLayoutBinding.Buffer bindings, BoilerInstance instance, String name) { + this.instance = instance; + + var ciLayout = VkDescriptorSetLayoutCreateInfo.calloc(stack); + ciLayout.sType$Default(); + ciLayout.flags(0); + ciLayout.pBindings(bindings); + + var pLayout = stack.callocLong(1); + assertVkSuccess(vkCreateDescriptorSetLayout( + instance.vkDevice(), ciLayout, null, pLayout + ), "CreateDescriptorSetLayout", name); + this.vkDescriptorSetLayout = pLayout.get(0); + + instance.debug.name(stack, this.vkDescriptorSetLayout, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, name); + + for (int index = bindings.position(); index < bindings.limit(); index++) { + descriptorTypeCounts.put(bindings.get(index).descriptorType(), 0); + } + for (int index = bindings.position(); index < bindings.limit(); index++) { + int type = bindings.get(index).descriptorType(); + descriptorTypeCounts.put(type, descriptorTypeCounts.get(type) + bindings.get(index).descriptorCount()); + } + } + + public HomogeneousDescriptorPool createPool(int maxSets, int flags, String name) { + try (var stack = stackPush()) { + + var poolSizes = VkDescriptorPoolSize.calloc(descriptorTypeCounts.size(), stack); + int poolSizeIndex = 0; + for (var entry : descriptorTypeCounts.entrySet()) { + var size = poolSizes.get(poolSizeIndex); + size.type(entry.getKey()); + size.descriptorCount(maxSets * entry.getValue()); + poolSizeIndex += 1; + } + + var ciPool = VkDescriptorPoolCreateInfo.calloc(stack); + ciPool.sType$Default(); + ciPool.flags(flags); + ciPool.maxSets(maxSets); + ciPool.pPoolSizes(poolSizes); + + var pPool = stack.callocLong(1); + assertVkSuccess(vkCreateDescriptorPool( + instance.vkDevice(), ciPool, null, pPool + ), "CreateDescriptorPool", name); + var pool = pPool.get(0); + + instance.debug.name(stack, pool, VK_OBJECT_TYPE_DESCRIPTOR_POOL, name); + return new HomogeneousDescriptorPool(this, pool, name); + } + } + + public void destroy() { + vkDestroyDescriptorSetLayout(instance.vkDevice(), vkDescriptorSetLayout, null); + } +} diff --git a/src/main/java/com/github/knokko/boiler/descriptors/FixedDescriptorBank.java b/src/main/java/com/github/knokko/boiler/descriptors/FixedDescriptorBank.java index 4616eed..478603e 100644 --- a/src/main/java/com/github/knokko/boiler/descriptors/FixedDescriptorBank.java +++ b/src/main/java/com/github/knokko/boiler/descriptors/FixedDescriptorBank.java @@ -1,14 +1,7 @@ package com.github.knokko.boiler.descriptors; -import com.github.knokko.boiler.instance.BoilerInstance; -import org.lwjgl.system.MemoryStack; -import org.lwjgl.vulkan.VkDescriptorPoolCreateInfo; -import org.lwjgl.vulkan.VkDescriptorSetAllocateInfo; - import java.util.concurrent.ConcurrentSkipListSet; -import java.util.function.BiConsumer; -import static com.github.knokko.boiler.exceptions.VulkanFailureException.assertVkSuccess; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; @@ -30,46 +23,18 @@ */ public class FixedDescriptorBank { - private final BoilerInstance instance; - private final long descriptorPool; + private final HomogeneousDescriptorPool pool; private final ConcurrentSkipListSet borrowedDescriptorSets; private final ConcurrentSkipListSet unusedDescriptorSets; - public FixedDescriptorBank( - BoilerInstance instance, long descriptorSetLayout, String context, - BiConsumer configureDescriptorPool - ) { - this.instance = instance; + public FixedDescriptorBank(DescriptorSetLayout layout, int capacity, int flags, String name) { try (var stack = stackPush()) { - var ciPool = VkDescriptorPoolCreateInfo.calloc(stack); - ciPool.sType$Default(); - configureDescriptorPool.accept(stack, ciPool); - int capacity = ciPool.maxSets(); - - var pPool = stack.callocLong(1); - assertVkSuccess(vkCreateDescriptorPool( - instance.vkDevice(), ciPool, null, pPool - ), "CreateDescriptorPool", "DescriptorBank" + context); - this.descriptorPool = pPool.get(0); - - var pSetLayouts = stack.callocLong(capacity); - for (int index = 0; index < capacity; index++) pSetLayouts.put(index, descriptorSetLayout); - - var aiSets = VkDescriptorSetAllocateInfo.calloc(stack); - aiSets.sType$Default(); - aiSets.descriptorPool(descriptorPool); - aiSets.pSetLayouts(pSetLayouts); - - var pSets = stack.callocLong(capacity); - assertVkSuccess(vkAllocateDescriptorSets( - instance.vkDevice(), aiSets, pSets - ), "AllocateDescriptorSets", "DescriptorBank" + context); + this.pool = layout.createPool(capacity, flags, name); + long[] descriptorSets = this.pool.allocate(stack, capacity); this.unusedDescriptorSets = new ConcurrentSkipListSet<>(); - for (int index = 0; index < capacity; index++) { - this.unusedDescriptorSets.add(pSets.get(index)); - } + for (long descriptorSet : descriptorSets) this.unusedDescriptorSets.add(descriptorSet); this.borrowedDescriptorSets = new ConcurrentSkipListSet<>(); } } @@ -82,7 +47,7 @@ public Long borrowDescriptorSet(String name) { if (result != null) { borrowedDescriptorSets.add(result); try (var stack = stackPush()) { - instance.debug.name(stack, result, VK_OBJECT_TYPE_DESCRIPTOR_SET, name); + pool.layout.instance.debug.name(stack, result, VK_OBJECT_TYPE_DESCRIPTOR_SET, name); } } return result; @@ -99,6 +64,6 @@ public void destroy(boolean checkEmpty) { if (checkEmpty && !borrowedDescriptorSets.isEmpty()) { throw new IllegalStateException("Not all descriptor sets have been returned"); } - vkDestroyDescriptorPool(instance.vkDevice(), descriptorPool, null); + pool.destroy(); } } diff --git a/src/main/java/com/github/knokko/boiler/descriptors/GrowingDescriptorBank.java b/src/main/java/com/github/knokko/boiler/descriptors/GrowingDescriptorBank.java index 722391b..64d4b00 100644 --- a/src/main/java/com/github/knokko/boiler/descriptors/GrowingDescriptorBank.java +++ b/src/main/java/com/github/knokko/boiler/descriptors/GrowingDescriptorBank.java @@ -1,17 +1,9 @@ package com.github.knokko.boiler.descriptors; -import com.github.knokko.boiler.instance.BoilerInstance; -import org.lwjgl.system.MemoryStack; -import org.lwjgl.vulkan.VkDescriptorPoolCreateInfo; -import org.lwjgl.vulkan.VkDescriptorSetAllocateInfo; - import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.concurrent.ConcurrentSkipListSet; -import java.util.function.BiConsumer; -import static com.github.knokko.boiler.exceptions.VulkanFailureException.assertVkSuccess; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; @@ -34,33 +26,17 @@ */ public class GrowingDescriptorBank { - private final BoilerInstance instance; - private final long descriptorSetLayout; - private final String name; - private final BiConsumer configureDescriptorPool; + private final DescriptorSetLayout layout; + private final int flags; - private final List descriptorPools = new ArrayList<>(); + private final List descriptorPools = new ArrayList<>(); private int nextCapacity = 2; - private final ConcurrentSkipListSet unusedDescriptorSets, borrowedDescriptorSets; - /** - * @param name Debugging purposes only - * @param configureDescriptorPool Populate the given VkDescriptorPoolCreateInfo. You should use this to - * set pPoolSizes for a descriptor pool that can hold exactly 1 - * descriptor set. (The descriptorCounts will automatically be multiplied - * with the capacity of the descriptor pool.) You should ignore maxSets and - * you can optionally set the flags. - */ - public GrowingDescriptorBank( - BoilerInstance instance, long descriptorSetLayout, String name, - BiConsumer configureDescriptorPool - ) { - this.instance = instance; - this.descriptorSetLayout = descriptorSetLayout; - this.name = name; - this.configureDescriptorPool = configureDescriptorPool; + public GrowingDescriptorBank(DescriptorSetLayout layout, int flags) { + this.layout = layout; + this.flags = flags; this.unusedDescriptorSets = new ConcurrentSkipListSet<>(); this.borrowedDescriptorSets = new ConcurrentSkipListSet<>(); } @@ -75,40 +51,14 @@ public long borrowDescriptorSet(String name) { if (maybeResult == null) { try (var stack = stackPush()) { - var ciPool = VkDescriptorPoolCreateInfo.calloc(stack); - ciPool.sType$Default(); - configureDescriptorPool.accept(stack, ciPool); - ciPool.maxSets(nextCapacity); - for (var poolSize : Objects.requireNonNull(ciPool.pPoolSizes())) { - poolSize.descriptorCount(nextCapacity * poolSize.descriptorCount()); - } - - var pPool = stack.callocLong(1); - assertVkSuccess(vkCreateDescriptorPool( - instance.vkDevice(), ciPool, null, pPool - ), "CreateDescriptorPool", "GrowingDescriptorBank-" + this.name + "-" + nextCapacity); - long newDescriptorPool = pPool.get(0); + var newDescriptorPool = layout.createPool(nextCapacity, flags, name + "-" + nextCapacity); descriptorPools.add(newDescriptorPool); - var pSetLayouts = stack.callocLong(nextCapacity); - for (int index = 0; index < nextCapacity; index++) { - pSetLayouts.put(index, descriptorSetLayout); - } - var aiSets = VkDescriptorSetAllocateInfo.calloc(stack); - aiSets.sType$Default(); - aiSets.descriptorPool(newDescriptorPool); - aiSets.pSetLayouts(pSetLayouts); - - var pSets = stack.callocLong(nextCapacity); - assertVkSuccess(vkAllocateDescriptorSets( - instance.vkDevice(), aiSets, pSets - ), "AllocateDescriptorSets", "GrowingDescriptorBank-" + this.name + "-" + nextCapacity); + var newSets = newDescriptorPool.allocate(stack, nextCapacity); + maybeResult = newSets[0]; + for (int index = 1; index < nextCapacity; index++) unusedDescriptorSets.add(newSets[index]); - maybeResult = pSets.get(0); - for (int index = 1; index < nextCapacity; index++) { - unusedDescriptorSets.add(pSets.get(index)); - } nextCapacity *= 2; } } @@ -116,7 +66,7 @@ public long borrowDescriptorSet(String name) { } borrowedDescriptorSets.add(maybeResult); try (var stack = stackPush()) { - instance.debug.name(stack, maybeResult, VK_OBJECT_TYPE_DESCRIPTOR_SET, name); + layout.instance.debug.name(stack, maybeResult, VK_OBJECT_TYPE_DESCRIPTOR_SET, name); } return maybeResult; } @@ -132,8 +82,8 @@ public void destroy(boolean checkBorrows) { if (checkBorrows && !borrowedDescriptorSets.isEmpty()) { throw new IllegalStateException("Not all borrowed descriptor sets have been returned"); } - for (long descriptorPool : descriptorPools) { - vkDestroyDescriptorPool(instance.vkDevice(), descriptorPool, null); + for (var descriptorPool : descriptorPools) { + descriptorPool.destroy(); } } } diff --git a/src/main/java/com/github/knokko/boiler/descriptors/HomogeneousDescriptorPool.java b/src/main/java/com/github/knokko/boiler/descriptors/HomogeneousDescriptorPool.java new file mode 100644 index 0000000..8f8f6c6 --- /dev/null +++ b/src/main/java/com/github/knokko/boiler/descriptors/HomogeneousDescriptorPool.java @@ -0,0 +1,35 @@ +package com.github.knokko.boiler.descriptors; + +import org.lwjgl.system.MemoryStack; + +import java.util.Arrays; + +import static org.lwjgl.vulkan.VK10.vkDestroyDescriptorPool; + +public class HomogeneousDescriptorPool { + + public final DescriptorSetLayout layout; + public final long vkDescriptorPool; + private final String name; + private long counter; + + HomogeneousDescriptorPool(DescriptorSetLayout layout, long vkDescriptorPool, String name) { + this.layout = layout; + this.vkDescriptorPool = vkDescriptorPool; + this.name = name; + } + + public long[] allocate(MemoryStack stack, int amount) { + long[] pLayouts = new long[amount]; + Arrays.fill(pLayouts, layout.vkDescriptorSetLayout); + long[] result = layout.instance.descriptors.allocate( + stack, amount, vkDescriptorPool, name + "-" + counter, pLayouts + ); + counter += 1; + return result; + } + + public void destroy() { + vkDestroyDescriptorPool(layout.instance.vkDevice(), vkDescriptorPool, null); + } +} diff --git a/src/test/java/com/github/knokko/boiler/compute/TestComputePipelines.java b/src/test/java/com/github/knokko/boiler/compute/TestComputePipelines.java index 7c0a098..4592938 100644 --- a/src/test/java/com/github/knokko/boiler/compute/TestComputePipelines.java +++ b/src/test/java/com/github/knokko/boiler/compute/TestComputePipelines.java @@ -19,10 +19,7 @@ public class TestComputePipelines { public void testSimpleComputeShader() { var boiler = new BoilerBuilder( VK_API_VERSION_1_2, "TestSimpleComputeShader", VK_MAKE_VERSION(0, 1, 0) - ) - .validation() - .forbidValidationErrors() - .build(); + ).validation().forbidValidationErrors().build(); try (var stack = stackPush()) { int valuesPerInvocation = 16; @@ -42,7 +39,7 @@ public void testSimpleComputeShader() { fillBufferLayoutBinding.descriptorCount(1); fillBufferLayoutBinding.stageFlags(VK_SHADER_STAGE_COMPUTE_BIT); - long descriptorSetLayout = boiler.descriptors.createLayout( + var descriptorSetLayout = boiler.descriptors.createLayout( stack, fillLayoutBindings, "FillBuffer-DescriptorSetLayout" ); @@ -53,28 +50,14 @@ public void testSimpleComputeShader() { sizePushConstant.size(8); long pipelineLayout = boiler.pipelines.createLayout( - stack, pushConstants, "FillBuffer-PipelineLayout", descriptorSetLayout + stack, pushConstants, "FillBuffer-PipelineLayout", descriptorSetLayout.vkDescriptorSetLayout ); long computePipeline = boiler.pipelines.createComputePipeline( stack, pipelineLayout, "shaders/fill.comp.spv", "FillBuffer" ); - var descriptorPoolSizes = VkDescriptorPoolSize.calloc(1, stack); - descriptorPoolSizes.type(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); - descriptorPoolSizes.descriptorCount(1); - - var ciDescriptorPool = VkDescriptorPoolCreateInfo.calloc(stack); - ciDescriptorPool.sType$Default(); - ciDescriptorPool.flags(0); - ciDescriptorPool.maxSets(1); - ciDescriptorPool.pPoolSizes(descriptorPoolSizes); - - var pDescriptorPool = stack.callocLong(1); - assertVkSuccess(vkCreateDescriptorPool( - boiler.vkDevice(), ciDescriptorPool, null, pDescriptorPool - ), "CreateDescriptorPool", "Filling"); - long descriptorPool = pDescriptorPool.get(0); - long descriptorSet = boiler.descriptors.allocate(stack, 1, descriptorPool, "Filling", descriptorSetLayout)[0]; + var descriptorPool = descriptorSetLayout.createPool(1, 0, "FillPool"); + long descriptorSet = descriptorPool.allocate(stack, 1)[0]; var descriptorWrites = VkWriteDescriptorSet.calloc(1, stack); boiler.descriptors.writeBuffer(stack, descriptorWrites, descriptorSet, 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, buffer); @@ -89,6 +72,7 @@ public void testSimpleComputeShader() { var commandBuffer = boiler.commands.createPrimaryBuffers( commandPool, 1, "Filling" )[0]; + boiler.commands.begin(commandBuffer, stack, "Filling"); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline); @@ -118,10 +102,10 @@ public void testSimpleComputeShader() { } vkDestroyFence(boiler.vkDevice(), fence, null); - vkDestroyDescriptorPool(boiler.vkDevice(), descriptorPool, null); + descriptorPool.destroy(); vkDestroyCommandPool(boiler.vkDevice(), commandPool, null); vkDestroyPipeline(boiler.vkDevice(), computePipeline, null); - vkDestroyDescriptorSetLayout(boiler.vkDevice(), descriptorSetLayout, null); + descriptorSetLayout.destroy(); vkDestroyPipelineLayout(boiler.vkDevice(), pipelineLayout, null); vmaDestroyBuffer(boiler.vmaAllocator(), buffer.vkBuffer(), buffer.vmaAllocation()); } diff --git a/src/test/java/com/github/knokko/boiler/descriptors/TestDescriptorSetLayout.java b/src/test/java/com/github/knokko/boiler/descriptors/TestDescriptorSetLayout.java new file mode 100644 index 0000000..a3128b3 --- /dev/null +++ b/src/test/java/com/github/knokko/boiler/descriptors/TestDescriptorSetLayout.java @@ -0,0 +1,56 @@ +package com.github.knokko.boiler.descriptors; + +import com.github.knokko.boiler.builder.BoilerBuilder; +import org.junit.jupiter.api.Test; +import org.lwjgl.vulkan.VkDescriptorSetLayoutBinding; + +import java.util.HashMap; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.lwjgl.system.MemoryStack.stackPush; +import static org.lwjgl.vulkan.VK10.*; +import static org.lwjgl.vulkan.VK13.VK_API_VERSION_1_3; + +public class TestDescriptorSetLayout { + + @Test + public void testDescriptorTypeCounts() { + var boiler = new BoilerBuilder( + VK_API_VERSION_1_3, "TestDescriptorSetLayout", 1 + ).validation().forbidValidationErrors().build(); + + try (var stack = stackPush()) { + var bindings = VkDescriptorSetLayoutBinding.calloc(3, stack); + var uniform1 = bindings.get(0); + uniform1.binding(0); + uniform1.descriptorType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + uniform1.descriptorCount(1); + uniform1.stageFlags(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + uniform1.pImmutableSamplers(null); + var sampler = bindings.get(1); + sampler.binding(1); + sampler.descriptorType(VK_DESCRIPTOR_TYPE_SAMPLER); + sampler.descriptorCount(5); + sampler.stageFlags(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + sampler.pImmutableSamplers(null); + var uniform2 = bindings.get(2); + uniform2.binding(2); + uniform2.descriptorType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + uniform2.descriptorCount(2); + uniform2.stageFlags(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + uniform2.pImmutableSamplers(null); + + var layout = boiler.descriptors.createLayout(stack, bindings, "DSLayout"); + + var expected = new HashMap(); + expected.put(VK_DESCRIPTOR_TYPE_SAMPLER, 5); + expected.put(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3); + + assertEquals(expected, layout.descriptorTypeCounts); + + layout.destroy(); + } + + boiler.destroyInitialObjects(); + } +} diff --git a/src/test/java/com/github/knokko/boiler/descriptors/TestFixedDescriptorBank.java b/src/test/java/com/github/knokko/boiler/descriptors/TestFixedDescriptorBank.java index 0684a94..a96b99b 100644 --- a/src/test/java/com/github/knokko/boiler/descriptors/TestFixedDescriptorBank.java +++ b/src/test/java/com/github/knokko/boiler/descriptors/TestFixedDescriptorBank.java @@ -2,7 +2,6 @@ import com.github.knokko.boiler.builder.BoilerBuilder; import org.junit.jupiter.api.Test; -import org.lwjgl.vulkan.VkDescriptorPoolSize; import org.lwjgl.vulkan.VkDescriptorSetLayoutBinding; import static org.junit.jupiter.api.Assertions.*; @@ -18,7 +17,7 @@ public void testFixedDescriptorBank() { .forbidValidationErrors() .build(); - long descriptorSetLayout; + DescriptorSetLayout descriptorSetLayout; try (var stack = stackPush()) { var bindings = VkDescriptorSetLayoutBinding.calloc(1, stack); bindings.binding(0); @@ -28,15 +27,8 @@ public void testFixedDescriptorBank() { descriptorSetLayout = boiler.descriptors.createLayout(stack, bindings, "Test"); } - var bank = new FixedDescriptorBank(boiler, descriptorSetLayout, "Test", (stack, ciPool) -> { - var poolSizes = VkDescriptorPoolSize.calloc(1, stack); - poolSizes.type(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - poolSizes.descriptorCount(2 * 5); - ciPool.flags(0); - ciPool.maxSets(2); - ciPool.pPoolSizes(poolSizes); - }); + var bank = new FixedDescriptorBank(descriptorSetLayout, 2, 0, "Test"); long descriptorSet1 = bank.borrowDescriptorSet("DS1"); long descriptorSet2 = bank.borrowDescriptorSet("DS2"); @@ -66,8 +58,7 @@ public void testFixedDescriptorBank() { assertTrue(descriptorSet21 == descriptorSet1 || descriptorSet21 == descriptorSet2); bank.destroy(false); - - vkDestroyDescriptorSetLayout(boiler.vkDevice(), descriptorSetLayout, null); + descriptorSetLayout.destroy(); boiler.destroyInitialObjects(); } } diff --git a/src/test/java/com/github/knokko/boiler/descriptors/TestGrowingDescriptorBank.java b/src/test/java/com/github/knokko/boiler/descriptors/TestGrowingDescriptorBank.java index e5966d6..ecc9431 100644 --- a/src/test/java/com/github/knokko/boiler/descriptors/TestGrowingDescriptorBank.java +++ b/src/test/java/com/github/knokko/boiler/descriptors/TestGrowingDescriptorBank.java @@ -2,7 +2,6 @@ import com.github.knokko.boiler.builder.BoilerBuilder; import org.junit.jupiter.api.Test; -import org.lwjgl.vulkan.VkDescriptorPoolSize; import org.lwjgl.vulkan.VkDescriptorSetLayoutBinding; import java.util.HashSet; @@ -21,7 +20,7 @@ public void testGrowingDescriptorBank() { .forbidValidationErrors() .build(); - long descriptorSetLayout; + DescriptorSetLayout layout; try (var stack = stackPush()) { var bindings = VkDescriptorSetLayoutBinding.calloc(1, stack); bindings.binding(0); @@ -29,16 +28,10 @@ public void testGrowingDescriptorBank() { bindings.descriptorCount(3); bindings.stageFlags(VK_SHADER_STAGE_VERTEX_BIT); - descriptorSetLayout = boiler.descriptors.createLayout(stack, bindings, "Test"); + layout = boiler.descriptors.createLayout(stack, bindings, "Test"); } - var bank = new GrowingDescriptorBank(boiler, descriptorSetLayout, "Test", (stack, ciPool) -> { - var poolSizes = VkDescriptorPoolSize.calloc(1, stack); - poolSizes.type(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); - poolSizes.descriptorCount(3); - - ciPool.pPoolSizes(poolSizes); - }); + var bank = new GrowingDescriptorBank(layout, 0); var initialSets = new long[15]; for (int index = 0; index < initialSets.length; index++) { @@ -65,7 +58,7 @@ public void testGrowingDescriptorBank() { } bank.destroy(false); - vkDestroyDescriptorSetLayout(boiler.vkDevice(), descriptorSetLayout, null); + layout.destroy(); boiler.destroyInitialObjects(); } diff --git a/src/test/java/com/github/knokko/boiler/descriptors/TestWriteImage.java b/src/test/java/com/github/knokko/boiler/descriptors/TestWriteImage.java index 7c308e1..ace5471 100644 --- a/src/test/java/com/github/knokko/boiler/descriptors/TestWriteImage.java +++ b/src/test/java/com/github/knokko/boiler/descriptors/TestWriteImage.java @@ -17,7 +17,6 @@ public class TestWriteImage { @Test - @SuppressWarnings("resource") public void testWriteImage() { var boiler = new BoilerBuilder( VK_API_VERSION_1_2, "TestWriteImage", 1 @@ -47,30 +46,16 @@ public void testWriteImage() { imageLayoutBinding.descriptorCount(1); imageLayoutBinding.stageFlags(VK_SHADER_STAGE_COMPUTE_BIT); - long descriptorSetLayout = boiler.descriptors.createLayout(stack, layoutBindings, "DSLayout"); - long pipelineLayout = boiler.pipelines.createLayout(stack, null, "PipelineLayout", descriptorSetLayout); + var descriptorSetLayout = boiler.descriptors.createLayout(stack, layoutBindings, "DSLayout"); + long pipelineLayout = boiler.pipelines.createLayout( + stack, null, "PipelineLayout", descriptorSetLayout.vkDescriptorSetLayout + ); long computePipeline = boiler.pipelines.createComputePipeline( stack, pipelineLayout, "shaders/sample.comp.spv", "SamplePipeline" ); - var descriptorPoolSizes = VkDescriptorPoolSize.calloc(2, stack); - descriptorPoolSizes.get(0).type(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); - descriptorPoolSizes.get(0).descriptorCount(1); - descriptorPoolSizes.get(1).type(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); - descriptorPoolSizes.get(1).descriptorCount(1); - - var ciDescriptorPool = VkDescriptorPoolCreateInfo.calloc(stack); - ciDescriptorPool.sType$Default(); - ciDescriptorPool.flags(0); - ciDescriptorPool.maxSets(1); - ciDescriptorPool.pPoolSizes(descriptorPoolSizes); - - var pDescriptorPool = stack.callocLong(1); - assertVkSuccess(vkCreateDescriptorPool( - boiler.vkDevice(), ciDescriptorPool, null, pDescriptorPool - ), "CreateDescriptorPool", "DescriptorPool"); - long descriptorPool = pDescriptorPool.get(0); - long descriptorSet = boiler.descriptors.allocate(stack, 1, descriptorPool, "DescriptorSet", descriptorSetLayout)[0]; + var descriptorPool = descriptorSetLayout.createPool(1, 0, "DescriptorPool"); + long descriptorSet = descriptorPool.allocate(stack, 1)[0]; var sampler = boiler.images.createSampler( stack, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, @@ -122,10 +107,10 @@ public void testWriteImage() { assertEquals(100, memGetInt(destBuffer.hostAddress())); vkDestroyFence(boiler.vkDevice(), fence, null); - vkDestroyDescriptorPool(boiler.vkDevice(), descriptorPool, null); + descriptorPool.destroy(); vkDestroyCommandPool(boiler.vkDevice(), commandPool, null); vkDestroyPipeline(boiler.vkDevice(), computePipeline, null); - vkDestroyDescriptorSetLayout(boiler.vkDevice(), descriptorSetLayout, null); + descriptorSetLayout.destroy(); vkDestroyPipelineLayout(boiler.vkDevice(), pipelineLayout, null); vkDestroySampler(boiler.vkDevice(), sampler, null); destBuffer.destroy(boiler.vmaAllocator());