From d27bd21ea005a5ae1c2ac41212db282b4a476c85 Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Mon, 9 Oct 2023 15:48:00 -0700 Subject: [PATCH 01/22] Add debug names to everything & fix some validation errors and small bugs --- .../acceleration/AccelerationBlasBuilder.java | 25 ++-- .../acceleration/AccelerationTLASManager.java | 3 + .../acceleration/SharedQuadVkIndexBuffer.java | 1 + .../java/me/cortex/vulkanite/client/Test.java | 59 ++++++++- .../me/cortex/vulkanite/client/Vulkanite.java | 21 ++- .../client/rendering/VulkanPipeline.java | 43 ++++--- .../lib/base/TrackedResourceObject.java | 2 + .../cortex/vulkanite/lib/base/VContext.java | 22 +++- .../lib/base/initalizer/VInitializer.java | 31 ++++- .../vulkanite/lib/cmd/CommandManager.java | 19 ++- .../me/cortex/vulkanite/lib/cmd/VCmdBuff.java | 120 ++++++++++-------- .../vulkanite/lib/cmd/VCommandPool.java | 7 +- .../vulkanite/lib/memory/MemoryManager.java | 4 + .../cortex/vulkanite/lib/memory/VBuffer.java | 6 + .../cortex/vulkanite/lib/memory/VImage.java | 9 ++ .../vulkanite/lib/memory/VmaAllocator.java | 1 + .../lib/pipeline/RaytracePipelineBuilder.java | 1 + .../vulkanite/mixin/iris/MixinGlTexture.java | 1 + .../iris/MixinNativeImageBackedTexture.java | 1 + .../mixin/iris/MixinPBRAtlasTexture.java | 1 + .../mixin/iris/MixinRenderTarget.java | 2 + .../minecraft/MixinSpriteAtlasTexture.java | 1 + 22 files changed, 287 insertions(+), 93 deletions(-) diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java index be979c7..5782bbb 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java @@ -50,7 +50,6 @@ public record BLASBatchResult(List results, VSemaphore semaphor private final Thread worker; private final int asyncQueue; private final Consumer resultConsumer; - private final VCommandPool sinlgeUsePool; private final VQueryPool queryPool; @@ -61,7 +60,6 @@ public record BLASBatchResult(List results, VSemaphore semaphor private final VComputePipeline gpuVertexDecodePipeline; public AccelerationBlasBuilder(VContext context, int asyncQueue, Consumer resultConsumer) { - this.sinlgeUsePool = context.cmd.createSingleUsePool(); this.queryPool = new VQueryPool(context.device, 10000, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR); this.context = context; this.asyncQueue = asyncQueue; @@ -159,7 +157,8 @@ private void run() { } } } - sinlgeUsePool.doReleases(); + var sinlgeUsePoolWorker = context.cmd.getSingleUsePool(); + sinlgeUsePoolWorker.doReleases(); if (jobs.size() > 100) { System.err.println("EXCESSIVE JOBS FOR SOME REASON AAAAAAAAAA"); //while (true); @@ -177,7 +176,7 @@ private void run() { var scratchBuffers = new VBuffer[jobs.size()]; var accelerationStructures = new VAccelerationStructure[jobs.size()]; - var uploadBuildCmd = sinlgeUsePool.createCommandBuffer(); + var uploadBuildCmd = sinlgeUsePoolWorker.createCommandBuffer(); uploadBuildCmd.begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); //Fill in the buildInfo and buildRanges @@ -206,6 +205,7 @@ private void run() { | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0); + buildBuffer.setDebugUtilsObjectName("BLAS geometry buffer"); buffersToFree.add(buildBuffer); var buildBufferAddr = buildBuffer.deviceAddress(); long buildBufferOffset = 0; @@ -290,6 +290,7 @@ private void run() { var scratch = context.memory.createBuffer(buildSizesInfo.buildScratchSize(), VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 256, 0); + scratch.setDebugUtilsObjectName("BLAS scratch buffer"); bi.scratchData(VkDeviceOrHostAddressKHR.calloc(stack).deviceAddress(scratch.deviceAddress())); bi.dstAccelerationStructure(structure.structure); @@ -341,7 +342,7 @@ private void run() { b.free(); } - sinlgeUsePool.releaseNow(uploadBuildCmd); + sinlgeUsePoolWorker.releaseNow(uploadBuildCmd); //We can destroy the fence here since we know its passed buildFence.free(); @@ -359,7 +360,7 @@ private void run() { //--------------------- { - var cmd = sinlgeUsePool.createCommandBuffer(); + var cmd = sinlgeUsePoolWorker.createCommandBuffer(); cmd.begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); //Dont need a memory barrier cause submit ensures cache flushing already @@ -394,7 +395,7 @@ private void run() { as.free(); } - sinlgeUsePool.releaseNow(cmd); + cmd.enqueueFree(); fence.free(); link.free(); }); @@ -423,15 +424,17 @@ private VBuffer uploadTerrainGeometry(BuiltSectionMeshParts meshParts, VCmdBuff var buff = context.memory.createBuffer(meshParts.getVertexData().getLength(), VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + buff.setDebugUtilsObjectName("Terrain geometry buffer"); cmd.encodeDataUpload(context.memory, MemoryUtil.memAddress(meshParts.getVertexData().getDirectBuffer()), buff, 0, meshParts.getVertexData().getLength()); return buff; } - //Enqueues jobs of section blas builds + // Enqueues jobs of section blas builds + // NOTE: This is on a different thread! public void enqueue(List batch) { - var cmd = sinlgeUsePool.createCommandBuffer(); + var cmd = context.cmd.getSingleUsePool().createCommandBuffer(); boolean hasJobs = false; List jobs = new ArrayList<>(batch.size()); @@ -466,7 +469,9 @@ public void enqueue(List batch) { if (hasJobs) { cmd.end(); - context.cmd.submitOnceAndWait(asyncQueue, cmd); + // TODO: Which queue should this be submitted to? + // Should we move all uploads to the worker? + context.cmd.submitOnceAndWait(0, cmd); } if (jobs.isEmpty()) { diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java index 030dbc5..cd2752b 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java @@ -45,6 +45,7 @@ public AccelerationTLASManager(VContext context, int queue) { this.context = context; this.queue = queue; this.singleUsePool = context.cmd.createSingleUsePool(); + this.singleUsePool.setDebugUtilsObjectName("TLAS singleUsePool"); this.buildDataManager.resizeBindlessSet(0, null); } @@ -170,6 +171,7 @@ public void buildTLAS(VSemaphore semIn, VSemaphore semOut, VSemaphore[] blocking VBuffer scratchBuffer = context.memory.createBuffer(buildSizesInfo.buildScratchSize(), VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 256, 0); + scratchBuffer.setDebugUtilsObjectName("TLAS Scratch Buffer"); buildInfo.dstAccelerationStructure(tlas.structure) .scratchData(VkDeviceOrHostAddressKHR.calloc(stack) @@ -259,6 +261,7 @@ public void setGeometryUpdateMemory(VCmdBuff cmd, VFence fence, VkAccelerationSt | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_HEAP_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 0, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); + data.setDebugUtilsObjectName("TLAS Instance Buffer"); long ptr = data.map(); MemoryUtil.memCopy(this.instances.address(0), ptr, size); data.unmap(); diff --git a/src/main/java/me/cortex/vulkanite/acceleration/SharedQuadVkIndexBuffer.java b/src/main/java/me/cortex/vulkanite/acceleration/SharedQuadVkIndexBuffer.java index 26051ca..056101c 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/SharedQuadVkIndexBuffer.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/SharedQuadVkIndexBuffer.java @@ -41,6 +41,7 @@ private static void makeNewIndexBuffer(VContext context, VCmdBuff uploaCmdBuff, | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_HEAP_DEVICE_LOCAL_BIT); + indexBuffer.setDebugUtilsObjectName("Geometry Index Buffer"); uploaCmdBuff.encodeDataUpload(context.memory, MemoryUtil.memAddress(buffer), indexBuffer, 0, buffer.remaining()); diff --git a/src/main/java/me/cortex/vulkanite/client/Test.java b/src/main/java/me/cortex/vulkanite/client/Test.java index af95e72..6841bcb 100644 --- a/src/main/java/me/cortex/vulkanite/client/Test.java +++ b/src/main/java/me/cortex/vulkanite/client/Test.java @@ -8,7 +8,10 @@ import org.lwjgl.glfw.GLFWErrorCallback; import org.lwjgl.glfw.GLFWVidMode; import org.lwjgl.opengl.GL; +import org.lwjgl.opengl.GL45; +import org.lwjgl.opengl.GL45C; import org.lwjgl.system.MemoryStack; +import org.lwjgl.system.MemoryUtil; import org.lwjgl.vulkan.VkPhysicalDeviceAccelerationStructureFeaturesKHR; import org.lwjgl.vulkan.VkPhysicalDeviceBufferDeviceAddressFeaturesKHR; import org.lwjgl.vulkan.VkPhysicalDeviceRayQueryFeaturesKHR; @@ -17,6 +20,7 @@ import java.io.File; import java.io.IOException; import java.nio.IntBuffer; +import java.nio.LongBuffer; import java.nio.file.Files; import java.util.List; @@ -102,6 +106,11 @@ public static void main(String[] args) throws IOException { .sType$Default() .rayTracingPipeline(true) .rayTracingPipelineTraceRaysIndirect(true) + ), List.of( + s-> {}, + s-> {}, + s-> {}, + s-> {} )); var context = init.createContext(); @@ -117,7 +126,7 @@ public static void main(String[] args) throws IOException { var pool = context.cmd.createSingleUsePool(); pool.createCommandBuffer(); - var mem = context.memory.createBuffer(1024, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 0, + var mem = context.memory.createBuffer(1024, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 0, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); mem.map(); mem.unmap(); @@ -126,6 +135,54 @@ public static void main(String[] args) throws IOException { // SharedQuadVkIndexBuffer.getIndexBuffer(context, uploadCmd, 10000); + var srcBeegThing = MemoryUtil.nmemCalloc(2L << 30L, 1); + MemoryUtil.memSet(srcBeegThing, 35, 2L << 30L); + + var fmlBuffer0 = context.memory.createBuffer(2L << 30L, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + context.cmd.executeWait(cmd -> { + cmd.encodeDataUpload(context.memory, srcBeegThing, fmlBuffer0, 0, 2L << 30L); + }); + + var fmlBuffer1 = context.memory.createBuffer(2L << 30L, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + context.cmd.executeWait(cmd -> { + cmd.encodeDataUpload(context.memory, srcBeegThing, fmlBuffer1, 0, 2L << 30L); + }); + + var fmlBuffer2 = context.memory.createBuffer(2L << 30L, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + context.cmd.executeWait(cmd -> { + cmd.encodeDataUpload(context.memory, srcBeegThing, fmlBuffer2, 0, 2L << 30L); + }); + + var fmlBuffer3 = context.memory.createBuffer(2L << 30L, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + context.cmd.executeWait(cmd -> { + cmd.encodeDataUpload(context.memory, srcBeegThing, fmlBuffer3, 0, 2L << 30L); + }); + + var fmlBuffer4 = context.memory.createBuffer(2L << 30L, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + context.cmd.executeWait(cmd -> { + cmd.encodeDataUpload(context.memory, srcBeegThing, fmlBuffer4, 0, 2L << 30L); + }); + + + int glBeegBuf = GL45.glCreateBuffers(); + GL45C.glNamedBufferData(glBeegBuf, 2L << 30L, GL45C.GL_STATIC_DRAW); + GL45C.glBindBufferBase(GL45C.GL_SHADER_STORAGE_BUFFER, 0, glBeegBuf); + + var beegData = LongBuffer.allocate(2 << 30); + beegData.array()[4] = 69; + GL45C.glNamedBufferSubData(glBeegBuf, 0, beegData); + + MemoryUtil.nmemFree(srcBeegThing); var layout = new DescriptorSetLayoutBuilder() .binding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_ALL)//camera data diff --git a/src/main/java/me/cortex/vulkanite/client/Vulkanite.java b/src/main/java/me/cortex/vulkanite/client/Vulkanite.java index 31f2fe2..0adc120 100644 --- a/src/main/java/me/cortex/vulkanite/client/Vulkanite.java +++ b/src/main/java/me/cortex/vulkanite/client/Vulkanite.java @@ -19,6 +19,7 @@ import static org.lwjgl.vulkan.EXTDebugUtils.VK_EXT_DEBUG_UTILS_EXTENSION_NAME; import static org.lwjgl.vulkan.EXTDescriptorIndexing.VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME; +import static org.lwjgl.vulkan.EXTMemoryBudget.VK_EXT_MEMORY_BUDGET_EXTENSION_NAME; import static org.lwjgl.vulkan.KHR16bitStorage.VK_KHR_16BIT_STORAGE_EXTENSION_NAME; import static org.lwjgl.vulkan.KHR8bitStorage.VK_KHR_8BIT_STORAGE_EXTENSION_NAME; import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME; @@ -41,6 +42,7 @@ import static org.lwjgl.vulkan.KHRRayTracingPipeline.VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME; import static org.lwjgl.vulkan.KHRShaderDrawParameters.VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME; import static org.lwjgl.vulkan.KHRSpirv14.VK_KHR_SPIRV_1_4_EXTENSION_NAME; +import static org.lwjgl.vulkan.VK10.vkDeviceWaitIdle; public class Vulkanite { public static final boolean IS_WINDOWS = Util.getOperatingSystem() == Util.OperatingSystem.WINDOWS; @@ -48,7 +50,7 @@ public class Vulkanite { public static boolean MEMORY_LEAK_TRACING = true; public static boolean IS_ENABLED = true; - public static final Vulkanite INSTANCE = new Vulkanite(); + public static Vulkanite INSTANCE = new Vulkanite(); private final VContext ctx; private final ArbitarySyncPointCallback fencedCallback = new ArbitarySyncPointCallback(); @@ -58,6 +60,8 @@ public class Vulkanite { public Vulkanite() { ctx = createVulkanContext(); + // Hack: so that AccelerationManager can access Vulkanite.INSTANCE + INSTANCE = this; //Fill in the shared index buffer with a large count so we (hopefully) dont have to worry about it anymore // SharedQuadVkIndexBuffer.getIndexBuffer(ctx, 30000); @@ -115,6 +119,7 @@ public void addSyncedCallback(Runnable callback) { } public void destroy() { + vkDeviceWaitIdle(ctx.device); for (var pool : descriptorPools.values()) { pool.free(); } @@ -149,6 +154,8 @@ private static VContext createVulkanContext() { VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, +// VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, + VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME )); if (IS_WINDOWS) { @@ -175,6 +182,18 @@ private static VContext createVulkanContext() { stack-> VkPhysicalDeviceVulkan12Features.calloc(stack) .sType$Default() + ), List.of( + features-> {}, + features -> {}, + features -> { + var vulkan11Features = (VkPhysicalDeviceVulkan11Features) features; + vulkan11Features.protectedMemory(false); + }, + features -> { + var vulkan12Features = (VkPhysicalDeviceVulkan12Features) features; + vulkan12Features.bufferDeviceAddressMultiDevice(false); +// vulkan12Features.bufferDeviceAddressCaptureReplay(false); + } )); return init.createContext(); diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java index 1d44e93..28ee012 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java @@ -55,6 +55,7 @@ import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; import static org.lwjgl.vulkan.KHRRayTracingPipeline.*; import static org.lwjgl.vulkan.VK10.*; +import static org.lwjgl.vulkan.VK12.VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; public class VulkanPipeline { private final VContext ctx; @@ -86,31 +87,32 @@ public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, Ray this.ctx = ctx; this.accelerationManager = accelerationManager; this.singleUsePool = ctx.cmd.createSingleUsePool(); + this.singleUsePool.setDebugUtilsObjectName("VulkanPipeline singleUsePool"); { this.customTextureViews = new SharedImageViewTracker[customTextures.length]; - for(int i = 0; i < customTextures.length; i++) { + for (int i = 0; i < customTextures.length; i++) { int index = i; - this.customTextureViews[i] = new SharedImageViewTracker(ctx, ()->customTextures[index]); + this.customTextureViews[i] = new SharedImageViewTracker(ctx, () -> customTextures[index]); } this.irisRenderTargetViews = new SharedImageViewTracker[maxIrisRenderTargets]; - for(int i = 0; i < maxIrisRenderTargets; i++) { + for (int i = 0; i < maxIrisRenderTargets; i++) { this.irisRenderTargetViews[i] = new SharedImageViewTracker(ctx, null); } - this.blockAtlasView = new SharedImageViewTracker(ctx, ()->{ + this.blockAtlasView = new SharedImageViewTracker(ctx, () -> { AbstractTexture blockAtlas = MinecraftClient.getInstance().getTextureManager().getTexture(new Identifier("minecraft", "textures/atlas/blocks.png")); - return ((IVGImage)blockAtlas).getVGImage(); + return ((IVGImage) blockAtlas).getVGImage(); }); - this.blockAtlasNormalView = new SharedImageViewTracker(ctx, ()->{ + this.blockAtlasNormalView = new SharedImageViewTracker(ctx, () -> { AbstractTexture blockAtlas = MinecraftClient.getInstance().getTextureManager().getTexture(new Identifier("minecraft", "textures/atlas/blocks.png")); PBRTextureHolder holder = PBRTextureManager.INSTANCE.getOrLoadHolder(blockAtlas.getGlId());//((TextureAtlasExtension)blockAtlas).getPBRHolder() - return ((IVGImage)holder.getNormalTexture()).getVGImage(); + return ((IVGImage) holder.getNormalTexture()).getVGImage(); }); - this.blockAtlasSpecularView = new SharedImageViewTracker(ctx, ()->{ + this.blockAtlasSpecularView = new SharedImageViewTracker(ctx, () -> { AbstractTexture blockAtlas = MinecraftClient.getInstance().getTextureManager().getTexture(new Identifier("minecraft", "textures/atlas/blocks.png")); PBRTextureHolder holder = PBRTextureManager.INSTANCE.getOrLoadHolder(blockAtlas.getGlId());//((TextureAtlasExtension)blockAtlas).getPBRHolder() - return ((IVGImage)holder.getSpecularTexture()).getVGImage(); + return ((IVGImage) holder.getSpecularTexture()).getVGImage(); }); this.placeholderSpecular = ctx.memory.createImage2D(4, 4, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); this.placeholderSpecularView = new VImageView(ctx, placeholderSpecular); @@ -121,7 +123,7 @@ public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, Ray var initZeros = stack.callocInt(4 * 4); var initNormals = stack.mallocFloat(4 * 4 * 4); for (int i = 0; i < 4 * 4; i++) { - initNormals.put(new float[] {0.5f, 0.5f, 1.0f, 1.0f}); + initNormals.put(new float[]{0.5f, 0.5f, 1.0f, 1.0f}); } initNormals.rewind(); @@ -141,7 +143,7 @@ public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, Ray } } - this.sampler = new VSampler(ctx, a->a.magFilter(VK_FILTER_NEAREST) + this.sampler = new VSampler(ctx, a -> a.magFilter(VK_FILTER_NEAREST) .minFilter(VK_FILTER_NEAREST) .mipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST) .addressModeU(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE) @@ -152,7 +154,7 @@ public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, Ray .borderColor(VK_BORDER_COLOR_INT_OPAQUE_BLACK) .maxAnisotropy(1.0f)); - this.ctexSampler = new VSampler(ctx, a->a.magFilter(VK_FILTER_LINEAR) + this.ctexSampler = new VSampler(ctx, a -> a.magFilter(VK_FILTER_LINEAR) .minFilter(VK_FILTER_LINEAR) .mipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST) .addressModeU(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE) @@ -169,16 +171,16 @@ public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, Ray try { var commonSetExpected = new ShaderReflection.Set(new ShaderReflection.Binding[]{ - new ShaderReflection.Binding("", 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, false), - new ShaderReflection.Binding("", 1, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0, false), - new ShaderReflection.Binding("", 3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, false), - new ShaderReflection.Binding("", 4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, false), - new ShaderReflection.Binding("", 5, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, false), - new ShaderReflection.Binding("", 6, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, maxIrisRenderTargets, false), + new ShaderReflection.Binding("", 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, false), + new ShaderReflection.Binding("", 1, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0, false), + new ShaderReflection.Binding("", 3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, false), + new ShaderReflection.Binding("", 4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, false), + new ShaderReflection.Binding("", 5, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, false), + new ShaderReflection.Binding("", 6, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, maxIrisRenderTargets, false), }); var geomSetExpected = new ShaderReflection.Set(new ShaderReflection.Binding[]{ - new ShaderReflection.Binding("", 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, true) + new ShaderReflection.Binding("", 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, true) }); ArrayList customTexBindings = new ArrayList<>(); @@ -189,7 +191,7 @@ public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, Ray ArrayList ssboBindings = new ArrayList<>(); for (int id : ssboIds) { - ssboBindings.add(new ShaderReflection.Binding("", id, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, true)); + ssboBindings.add(new ShaderReflection.Binding("", id, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, false)); } var ssboSetExpected = new ShaderReflection.Set(ssboBindings); @@ -263,6 +265,7 @@ public void renderPostShadows(List outImgs, Camera camera, ShaderStorag VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 0, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); + uboBuffer.setDebugUtilsObjectName("VulkanPipeline UBO"); long ptr = uboBuffer.map(); MemoryUtil.memSet(ptr, 0, 1024); { diff --git a/src/main/java/me/cortex/vulkanite/lib/base/TrackedResourceObject.java b/src/main/java/me/cortex/vulkanite/lib/base/TrackedResourceObject.java index 40f9921..25e6816 100644 --- a/src/main/java/me/cortex/vulkanite/lib/base/TrackedResourceObject.java +++ b/src/main/java/me/cortex/vulkanite/lib/base/TrackedResourceObject.java @@ -1,5 +1,7 @@ package me.cortex.vulkanite.lib.base; +import me.cortex.vulkanite.client.Vulkanite; + import java.lang.ref.Cleaner; public abstract class TrackedResourceObject { diff --git a/src/main/java/me/cortex/vulkanite/lib/base/VContext.java b/src/main/java/me/cortex/vulkanite/lib/base/VContext.java index 2dcdfd3..790d897 100644 --- a/src/main/java/me/cortex/vulkanite/lib/base/VContext.java +++ b/src/main/java/me/cortex/vulkanite/lib/base/VContext.java @@ -3,8 +3,14 @@ import me.cortex.vulkanite.lib.cmd.CommandManager; import me.cortex.vulkanite.lib.other.sync.SyncManager; import me.cortex.vulkanite.lib.memory.MemoryManager; +import org.lwjgl.vulkan.VkDebugUtilsObjectNameInfoEXT; import org.lwjgl.vulkan.VkDevice; +import static org.lwjgl.system.MemoryStack.stackPush; +import static org.lwjgl.system.MemoryUtil.memUTF8; +import static org.lwjgl.vulkan.EXTDebugUtils.vkSetDebugUtilsObjectNameEXT; +import static org.lwjgl.vulkan.VK10.VK_OBJECT_TYPE_UNKNOWN; + public class VContext { public final VkDevice device; @@ -13,11 +19,25 @@ public class VContext { public final SyncManager sync; public final CommandManager cmd; public final DeviceProperties properties; - public VContext(VkDevice device, int queueCount, boolean hasDeviceAddresses) { + public final boolean hasDebugUtils; + public VContext(VkDevice device, int queueCount, boolean hasDeviceAddresses, boolean hasDebugUtils) { this.device = device; memory = new MemoryManager(device, hasDeviceAddresses); sync = new SyncManager(device); cmd = new CommandManager(device, queueCount); properties = new DeviceProperties(device); + this.hasDebugUtils = hasDebugUtils; + } + + public void setDebugUtilsObjectName(long handle, int objectType, String name) { + if (hasDebugUtils) { + try (var stack = stackPush()) { + vkSetDebugUtilsObjectNameEXT(device, VkDebugUtilsObjectNameInfoEXT.calloc(stack) + .sType$Default() + .objectType(objectType) + .objectHandle(handle) + .pObjectName(memUTF8(name))); + } + } } } diff --git a/src/main/java/me/cortex/vulkanite/lib/base/initalizer/VInitializer.java b/src/main/java/me/cortex/vulkanite/lib/base/initalizer/VInitializer.java index 75a9e6a..715eb83 100644 --- a/src/main/java/me/cortex/vulkanite/lib/base/initalizer/VInitializer.java +++ b/src/main/java/me/cortex/vulkanite/lib/base/initalizer/VInitializer.java @@ -18,6 +18,7 @@ import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.system.MemoryUtil.memUTF8; +import static org.lwjgl.vulkan.EXTDebugUtils.*; import static org.lwjgl.vulkan.VK10.*; import static org.lwjgl.vulkan.VK11.*; @@ -26,6 +27,7 @@ public class VInitializer { private VkPhysicalDevice physicalDevice; private VkDevice device; private int queueCount; + private long debugMessenger = 0; public VInitializer(String appName, String engineName, int major, int minor, String[] extensions, String[] layers) { try (MemoryStack stack = stackPush()) { VkApplicationInfo appInfo = VkApplicationInfo.calloc(stack) @@ -44,6 +46,24 @@ public VInitializer(String appName, String engineName, int major, int minor, Str _CHECK_(vkCreateInstance(instanceCreateInfo, null, result)); instance = new VkInstance(result.get(0), instanceCreateInfo); + + if (Arrays.asList(extensions).contains(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) { + VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo = VkDebugUtilsMessengerCreateInfoEXT.calloc(stack) + .sType$Default() + .messageSeverity(VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) + .messageType(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) + .pfnUserCallback((messageSeverity, messageTypes, pCallbackData, pUserData) -> { + VkDebugUtilsMessengerCallbackDataEXT callbackData = VkDebugUtilsMessengerCallbackDataEXT.create(pCallbackData); + System.err.println("Validation layer: " + callbackData.pMessageString()); + Thread.dumpStack(); + return VK_FALSE; + }); + + var pDebugMessenger = stack.mallocLong(1); + _CHECK_(vkCreateDebugUtilsMessengerEXT(instance, debugCreateInfo, null, pDebugMessenger)); + debugMessenger = pDebugMessenger.get(0); + // Runtime.getRuntime().addShutdownHook(new Thread(() -> vkDestroyDebugUtilsMessengerEXT(instance, debugMessenger, null))); + } } } @@ -61,7 +81,7 @@ public void findPhysicalDevice() { } //TODO: add nice queue creation system - public void createDevice(List extensions, List layers, float[] queuePriorities, Consumer deviceFeatures, List> applicators) { + public void createDevice(List extensions, List layers, float[] queuePriorities, Consumer deviceFeatures, List> applicators, List> postApplicators) { var deviceExtensions = new HashSet<>(getDeviceExtensionStrings(physicalDevice)); for (var extension : extensions) { if (!deviceExtensions.contains(extension)) { @@ -93,10 +113,15 @@ public void createDevice(List extensions, List layers, float[] q long chain = createInfo.address(); var deviceProperties2 = VkPhysicalDeviceFeatures2.calloc(stack).sType$Default(); - for (var applicator : applicators) { + if (postApplicators.size() != applicators.size()) { + throw new IllegalStateException("Post applicators and applicators must be the same size"); + } + for (int i = 0; i < applicators.size(); i++) { + var applicator = applicators.get(i); Struct feature = applicator.apply(stack); deviceProperties2.pNext(feature.address()); vkGetPhysicalDeviceFeatures2(physicalDevice, deviceProperties2); + postApplicators.get(i).accept(feature); long next = feature.address(); MemoryUtil.memPutAddress(chain+8, next); chain = next; @@ -165,6 +190,6 @@ private VkExtensionProperties.Buffer getDeviceExtensions(MemoryStack stack, VkPh public VContext createContext() { //TODO:FIXME: DONT HARDCODE THE FACT IT HAS DEVICE ADDRESSES - return new VContext(device, queueCount, true); + return new VContext(device, queueCount, true, debugMessenger != 0); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java b/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java index 794cab0..7f991aa 100644 --- a/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java @@ -3,6 +3,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import io.netty.util.internal.shaded.org.jctools.queues.MessagePassingQueue.Consumer; +import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.lib.other.sync.VFence; import me.cortex.vulkanite.lib.other.sync.VSemaphore; import org.lwjgl.vulkan.VkCommandBufferBeginInfo; @@ -10,7 +11,9 @@ import org.lwjgl.vulkan.VkQueue; import org.lwjgl.vulkan.VkSubmitInfo; +import java.lang.management.ThreadInfo; import java.nio.LongBuffer; +import java.util.HashMap; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; @@ -20,7 +23,14 @@ public class CommandManager { private final VkDevice device; private final VkQueue[] queues; - private final VCommandPool singleUsePool; + private final ThreadLocal threadLocalPool = + new ThreadLocal() { + @Override protected VCommandPool initialValue() { + var pool = createSingleUsePool(); + pool.setDebugUtilsObjectName("Thread-local single use pool"); + return pool; + } + }; public CommandManager(VkDevice device, int queues) { this.device = device; @@ -33,7 +43,6 @@ public CommandManager(VkDevice device, int queues) { this.queues[i] = new VkQueue(pQ.get(0), device); } } - this.singleUsePool = createSingleUsePool(); } public VCommandPool createSingleUsePool() { @@ -44,6 +53,10 @@ public VCommandPool createPool(int flags) { return new VCommandPool(device, flags); } + public VCommandPool getSingleUsePool() { + return threadLocalPool.get(); + } + public void submit(int queueId, VkSubmitInfo submit) { try (var stack = stackPush()) { vkQueueSubmit(queues[queueId], submit, 0); @@ -64,7 +77,7 @@ public void submitOnceAndWait(int queueId, VCmdBuff cmdBuff) { } public void executeWait(Consumer cmdbuf) { - var cmd = singleUsePool.createCommandBuffer(); + var cmd = getSingleUsePool().createCommandBuffer(); cmd.begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); cmdbuf.accept(cmd); cmd.end(); diff --git a/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java b/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java index bf61272..61edea9 100644 --- a/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java +++ b/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java @@ -1,5 +1,6 @@ package me.cortex.vulkanite.lib.cmd; +import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.lib.base.TrackedResourceObject; import me.cortex.vulkanite.lib.memory.MemoryManager; import me.cortex.vulkanite.lib.memory.VBuffer; @@ -61,6 +62,7 @@ public void encodeDataUpload(MemoryManager manager, long src, VBuffer dest, long VBuffer staging = manager.createBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 0, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); + staging.setDebugUtilsObjectName("Data Upload Host Staging"); long ptr = staging.map(); MemoryUtil.memCopy(src, ptr, size); staging.unmap(); @@ -78,6 +80,7 @@ public void encodeImageUpload(MemoryManager manager, long src, VImage dest, long VBuffer staging = manager.createBuffer(srcSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 0, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); + staging.setDebugUtilsObjectName("Image Upload Host Staging"); long ptr = staging.map(); MemoryUtil.memCopy(src, ptr, srcSize); staging.unmap(); @@ -109,57 +112,31 @@ public void addTransientResource(TrackedResourceObject resource) { } public static int dstStageToAccess(int dstStage) { - switch (dstStage) { - case VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT: - return VK_ACCESS_MEMORY_READ_BIT; - case VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT: - return VK_ACCESS_INDIRECT_COMMAND_READ_BIT; - case VK_PIPELINE_STAGE_VERTEX_INPUT_BIT: - return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; - case VK_PIPELINE_STAGE_VERTEX_SHADER_BIT: - case VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT: - case VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT: - case VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT: - case VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT: - case VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT: - case VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR: - return VK_ACCESS_SHADER_READ_BIT; - case VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT: - return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; - case VK_PIPELINE_STAGE_TRANSFER_BIT: - return VK_ACCESS_TRANSFER_READ_BIT; - case VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR: - return VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_SHADER_READ_BIT; - default: - return VK_ACCESS_MEMORY_READ_BIT; - } + return switch (dstStage) { + case VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT -> VK_ACCESS_INDIRECT_COMMAND_READ_BIT; + case VK_PIPELINE_STAGE_VERTEX_INPUT_BIT -> VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + case VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR -> + VK_ACCESS_SHADER_READ_BIT; + case VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT -> VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + case VK_PIPELINE_STAGE_TRANSFER_BIT -> VK_ACCESS_TRANSFER_READ_BIT; + case VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR -> + VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_SHADER_READ_BIT; + default -> VK_ACCESS_MEMORY_READ_BIT; + }; } public static int srcStageToAccess(int srcStage) { - switch (srcStage) { - case VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT: - return VK_ACCESS_MEMORY_WRITE_BIT; - case VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT: - return VK_ACCESS_INDIRECT_COMMAND_READ_BIT; - case VK_PIPELINE_STAGE_VERTEX_INPUT_BIT: - return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; - case VK_PIPELINE_STAGE_VERTEX_SHADER_BIT: - case VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT: - case VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT: - case VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT: - case VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT: - case VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT: - case VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR: - return VK_ACCESS_SHADER_WRITE_BIT; - case VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT: - return VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - case VK_PIPELINE_STAGE_TRANSFER_BIT: - return VK_ACCESS_TRANSFER_WRITE_BIT; - case VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR: - return VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_SHADER_WRITE_BIT; - default: - return VK_ACCESS_MEMORY_WRITE_BIT; - } + return switch (srcStage) { + case VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT -> VK_ACCESS_INDIRECT_COMMAND_READ_BIT; + case VK_PIPELINE_STAGE_VERTEX_INPUT_BIT -> VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + case VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR -> + VK_ACCESS_SHADER_WRITE_BIT; + case VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT -> VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + case VK_PIPELINE_STAGE_TRANSFER_BIT -> VK_ACCESS_TRANSFER_WRITE_BIT; + case VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR -> + VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_SHADER_WRITE_BIT; + default -> VK_ACCESS_MEMORY_WRITE_BIT; + }; } public void encodeBufferBarrier(VBuffer buffer, long offset, long size) { @@ -177,17 +154,50 @@ public void encodeBufferBarrier(VBuffer buffer, long offset, long size, int srcS } } - public void encodeImageTransition(VImage image, int src, int dst, int aspectMask, int mipLevels) { - encodeImageTransition(image, src, dst, aspectMask, mipLevels, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + public int srcLayoutToStage(int srcLayout) { + return switch (srcLayout) { + case VK_IMAGE_LAYOUT_UNDEFINED -> VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL -> VK_PIPELINE_STAGE_TRANSFER_BIT; + case VK_IMAGE_LAYOUT_GENERAL -> VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL -> + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR; + default -> VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + }; + } + + public int layoutToAccess(int srcLayout) { + return switch (srcLayout) { + case VK_IMAGE_LAYOUT_UNDEFINED -> 0; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL -> VK_ACCESS_TRANSFER_READ_BIT; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL -> VK_ACCESS_TRANSFER_WRITE_BIT; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL -> VK_ACCESS_SHADER_READ_BIT; + default -> VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; + }; + } + + public int dstLayoutToStage(int dstLayout) { + return switch (dstLayout) { + case VK_IMAGE_LAYOUT_UNDEFINED -> VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL -> VK_PIPELINE_STAGE_TRANSFER_BIT; + case VK_IMAGE_LAYOUT_GENERAL -> VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL -> + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR; + default -> VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + }; } - public void encodeImageTransition(VImage image, int src, int dst, int aspectMask, int mipLevels, int srcStage, int dstStage) { + public void encodeImageTransition(VImage image, int src, int dst, int aspectMask, int mipLevels) { try (var stack = stackPush()) { var barrier = VkImageMemoryBarrier.calloc(1, stack); - barrier.get(0).sType$Default().srcAccessMask(srcStageToAccess(srcStage)) - .dstAccessMask(dstStageToAccess(dstStage)).oldLayout(src).newLayout(dst).image(image.image()) + barrier.get(0).sType$Default().oldLayout(src).newLayout(dst).image(image.image()) .subresourceRange().aspectMask(aspectMask).baseMipLevel(0).levelCount(mipLevels).baseArrayLayer(0) .layerCount(VK_REMAINING_ARRAY_LAYERS); + + int srcStage = srcLayoutToStage(src); + int dstStage = dstLayoutToStage(dst); + barrier.srcAccessMask(layoutToAccess(src)); + barrier.dstAccessMask(layoutToAccess(dst)); + vkCmdPipelineBarrier(this.buffer, srcStage, dstStage, 0, null, null, barrier); } @@ -209,4 +219,8 @@ void freeInternal() { transientResources.forEach(TrackedResourceObject::free); transientResources.clear(); } + + public void setDebugUtilsObjectName(String name) { + Vulkanite.INSTANCE.getCtx().setDebugUtilsObjectName(buffer.address(), VK_OBJECT_TYPE_COMMAND_BUFFER, name); + } } diff --git a/src/main/java/me/cortex/vulkanite/lib/cmd/VCommandPool.java b/src/main/java/me/cortex/vulkanite/lib/cmd/VCommandPool.java index 279a82a..9847c5b 100644 --- a/src/main/java/me/cortex/vulkanite/lib/cmd/VCommandPool.java +++ b/src/main/java/me/cortex/vulkanite/lib/cmd/VCommandPool.java @@ -1,5 +1,6 @@ package me.cortex.vulkanite.lib.cmd; +import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.lib.base.TrackedResourceObject; import org.lwjgl.PointerBuffer; import org.lwjgl.system.MemoryStack; @@ -17,7 +18,7 @@ public class VCommandPool extends TrackedResourceObject { final VkDevice device; - final long pool; + public final long pool; public VCommandPool(VkDevice device, int flags) { this(device, 0, flags); } @@ -82,4 +83,8 @@ public void free() { free0(); vkDestroyCommandPool(device, pool, null); } + + public void setDebugUtilsObjectName(String name) { + Vulkanite.INSTANCE.getCtx().setDebugUtilsObjectName(pool, VK_OBJECT_TYPE_COMMAND_POOL, name); + } } diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java b/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java index 9a00623..ae232af 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java @@ -302,4 +302,8 @@ public VAccelerationStructure createAcceleration(long size, int alignment, int u return new VAccelerationStructure(device, pAccelerationStructure.get(0), buffer); } } + + public void dumpStats() { + System.out.println("VMA JSON:\n" + allocator.dumpJson(false)); + } } diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/VBuffer.java b/src/main/java/me/cortex/vulkanite/lib/memory/VBuffer.java index 17753d0..a144d49 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/VBuffer.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/VBuffer.java @@ -1,7 +1,9 @@ package me.cortex.vulkanite.lib.memory; +import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.lib.base.TrackedResourceObject; +import static org.lwjgl.vulkan.VK10.VK_OBJECT_TYPE_BUFFER; import static org.lwjgl.vulkan.VK10.VK_WHOLE_SIZE; public class VBuffer extends TrackedResourceObject { @@ -46,4 +48,8 @@ public void flush(long offset, long size) { public long size() { return allocation.size(); } + + public void setDebugUtilsObjectName(String name) { + Vulkanite.INSTANCE.getCtx().setDebugUtilsObjectName(buffer(), VK_OBJECT_TYPE_BUFFER, name); + } } diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/VImage.java b/src/main/java/me/cortex/vulkanite/lib/memory/VImage.java index d8606c8..e83a7e7 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/VImage.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/VImage.java @@ -1,7 +1,12 @@ package me.cortex.vulkanite.lib.memory; +import me.cortex.vulkanite.client.Vulkanite; + import java.lang.ref.Cleaner; +import static org.lwjgl.vulkan.VK10.VK_OBJECT_TYPE_BUFFER; +import static org.lwjgl.vulkan.VK10.VK_OBJECT_TYPE_IMAGE; + public class VImage { protected VmaAllocator.ImageAllocation allocation; public final int width; @@ -40,4 +45,8 @@ public void free() { public long image() { return allocation.image; } + + public void setDebugUtilsObjectName(String name) { + Vulkanite.INSTANCE.getCtx().setDebugUtilsObjectName(image(), VK_OBJECT_TYPE_IMAGE, name); + } } diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/VmaAllocator.java b/src/main/java/me/cortex/vulkanite/lib/memory/VmaAllocator.java index 4c5a424..6a2ecd3 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/VmaAllocator.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/VmaAllocator.java @@ -101,6 +101,7 @@ public VmaAllocator(VkDevice device, boolean enableDeviceAddresses, long sharedB .set(device.getPhysicalDevice().getInstance(), device)) .vulkanApiVersion(VK_API_VERSION_1_2) .flags(enableDeviceAddresses ? VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT : 0); + allocatorCreateInfo.flags(allocatorCreateInfo.flags() | VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT); PointerBuffer pAllocator = stack.pointers(0); if (vmaCreateAllocator(allocatorCreateInfo, pAllocator) != VK_SUCCESS) { diff --git a/src/main/java/me/cortex/vulkanite/lib/pipeline/RaytracePipelineBuilder.java b/src/main/java/me/cortex/vulkanite/lib/pipeline/RaytracePipelineBuilder.java index 3d24240..3d34d91 100644 --- a/src/main/java/me/cortex/vulkanite/lib/pipeline/RaytracePipelineBuilder.java +++ b/src/main/java/me/cortex/vulkanite/lib/pipeline/RaytracePipelineBuilder.java @@ -189,6 +189,7 @@ public VRaytracePipeline build(VContext context, int maxDepth) { VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR, VK_MEMORY_HEAP_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 0, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); + sbtMap.setDebugUtilsObjectName("SBT"); long ptr = sbtMap.map(); // Groups in order of RayGen, Miss Groups, Hit Groups, and callable diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java index dbd6223..e21bb90 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java @@ -51,6 +51,7 @@ private int redirectTextureCreation(GlTexture instance, TextureType target, int VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ); + sharedImage.setDebugUtilsObjectName("GlTexture"); Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { cmdbuf.encodeImageTransition(sharedImage, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNativeImageBackedTexture.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNativeImageBackedTexture.java index 6c6e428..d0d6887 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNativeImageBackedTexture.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNativeImageBackedTexture.java @@ -51,6 +51,7 @@ private void redirectGen(int id, int width, int height) { GL_RGBA8, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + img.setDebugUtilsObjectName("NativeImageBackedTexture"); setVGImage(img); Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinPBRAtlasTexture.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinPBRAtlasTexture.java index d475561..1f69ef4 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinPBRAtlasTexture.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinPBRAtlasTexture.java @@ -37,6 +37,7 @@ private void redirect(int id, int maxLevel, int width, int height) { GL_RGBA8, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + img.setDebugUtilsObjectName("PBRAtlasTexture"); setVGImage(img); Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java index 7e9e579..59e9348 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java @@ -73,6 +73,8 @@ private void setupTextures(int width, int height, boolean allowsLinear) { vgMainTexture = ctx.memory.createSharedImage(width, height, 1, 1, vkfmt, glfmt, VK_IMAGE_USAGE_STORAGE_BIT , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); vgAltTexture = ctx.memory.createSharedImage(width, height, 1, 1, vkfmt, glfmt, VK_IMAGE_USAGE_STORAGE_BIT , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + vgMainTexture.setDebugUtilsObjectName("RenderTarget Main"); + vgAltTexture.setDebugUtilsObjectName("RenderTarget Alt"); Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { cmdbuf.encodeImageTransition(vgMainTexture, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); cmdbuf.encodeImageTransition(vgAltTexture, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); diff --git a/src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinSpriteAtlasTexture.java b/src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinSpriteAtlasTexture.java index 4be634a..6c8b8f5 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinSpriteAtlasTexture.java +++ b/src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinSpriteAtlasTexture.java @@ -36,6 +36,7 @@ private void redirect(int id, int maxLevel, int width, int height) { GL_RGBA8, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + img.setDebugUtilsObjectName("RenderTarget MainSpriteAtlasTexture"); setVGImage(img); Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { From ef5a5a1dcdb915fc29d4df2af6bbd3561fbfecac Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Sat, 9 Dec 2023 21:05:21 -0800 Subject: [PATCH 02/22] Less crashy in the BLAS builder --- .../acceleration/AccelerationBlasBuilder.java | 31 ++++++++++++------- .../descriptors/DescriptorUpdateBuilder.java | 28 ++++++++++++++--- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java index 5782bbb..1c51fe6 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java @@ -97,7 +97,7 @@ public AccelerationBlasBuilder(VContext context, int asyncQueue, Consumer 100) { - System.err.println("EXCESSIVE JOBS FOR SOME REASON AAAAAAAAAA"); - //while (true); - } + //Jobs are batched and built on the async vulkan queue then block synchronized with fence // which then results in compaction and dispatch to consumer @@ -181,6 +178,7 @@ private void run() { //Fill in the buildInfo and buildRanges int i = -1; + vkCmdBindPipeline(uploadBuildCmd.buffer, VK_PIPELINE_BIND_POINT_COMPUTE, gpuVertexDecodePipeline.pipeline()); for (var job : jobs) { i++; var brs = VkAccelerationStructureBuildRangeInfoKHR.calloc(job.geometries.size(), stack); @@ -200,7 +198,7 @@ private void run() { } var buildBuffer = context.memory.createBuffer(buildBufferSize, - VK_BUFFER_USAGE_TRANSFER_DST_BIT + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, @@ -210,6 +208,9 @@ private void run() { var buildBufferAddr = buildBuffer.deviceAddress(); long buildBufferOffset = 0; + uploadBuildCmd.encodeBufferBarrier(buildBuffer, 0, VK_WHOLE_SIZE, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + for (int geoIdx = 0; geoIdx < job.geometries.size(); geoIdx++) { var geometry = job.geometries.get(geoIdx); //TODO: Fill in geometryInfo, maxPrims and buildRangeInfo @@ -221,12 +222,20 @@ private void run() { // 1: inAddr // 2: outAddr var pushConstant = new long[3]; + var geometryInputBuffer = job.data.geometryBuffers().get(geoIdx); pushConstant[0] = geometry.quadCount * 4; - pushConstant[1] = job.data.geometryBuffers().get(geoIdx).deviceAddress(); + pushConstant[1] = geometryInputBuffer.deviceAddress(); pushConstant[2] = buildBufferAddr + buildBufferOffset; - vkCmdBindPipeline(uploadBuildCmd.buffer, VK_PIPELINE_BIND_POINT_COMPUTE, gpuVertexDecodePipeline.pipeline()); + if (pushConstant[1] == 0) { + throw new IllegalStateException("Geometry input buffer address is 0"); + } + if (pushConstant[2] == 0) { + throw new IllegalStateException("Build buffer address is 0"); + } vkCmdPushConstants(uploadBuildCmd.buffer, gpuVertexDecodePipeline.layout(), VK_SHADER_STAGE_ALL, 0, pushConstant); - vkCmdDispatch(uploadBuildCmd.buffer, Math.min((geometry.quadCount * 4 + 255) / 256, 128), 1, 1); + uploadBuildCmd.encodeBufferBarrier(geometryInputBuffer, 0, VK_WHOLE_SIZE, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + vkCmdDispatch(uploadBuildCmd.buffer, Math.min((geometry.quadCount * 4 + 255) / 256, 256), 1, 1); VkDeviceOrHostAddressConstKHR indexData = SharedQuadVkIndexBuffer.getIndexBuffer(context, uploadBuildCmd, diff --git a/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java b/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java index 9811c51..3ac5194 100644 --- a/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java +++ b/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java @@ -15,6 +15,7 @@ import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; import static org.lwjgl.vulkan.VK10.*; +import java.util.ArrayList; import java.util.List; public class DescriptorUpdateBuilder { @@ -22,6 +23,8 @@ public class DescriptorUpdateBuilder { private final MemoryStack stack; private final VkWriteDescriptorSet.Buffer updates; private final VImageView placeholderImageView; + private ArrayList bulkBufferInfos = new ArrayList<>(); + private ArrayList bulkImageInfos = new ArrayList<>(); private ShaderReflection.Set refSet = null; public DescriptorUpdateBuilder(VContext ctx, int maxUpdates) { @@ -30,7 +33,15 @@ public DescriptorUpdateBuilder(VContext ctx, int maxUpdates) { public DescriptorUpdateBuilder(VContext ctx, int maxUpdates, VImageView placeholderImageView) { this.ctx = ctx; - this.stack = MemoryStack.stackPush(); + // this.stack = MemoryStack.stackPush(); + int objSize = Integer.max( + Integer.max( + VkDescriptorBufferInfo.SIZEOF, + VkDescriptorImageInfo.SIZEOF), + VkWriteDescriptorSetAccelerationStructureKHR.SIZEOF); + objSize = ((objSize + 15) / 16) * 16; + this.stack = MemoryStack.create(1024 + maxUpdates * VkWriteDescriptorSet.SIZEOF + maxUpdates * objSize); + this.stack.push(); this.updates = VkWriteDescriptorSet.calloc(maxUpdates, stack); this.placeholderImageView = placeholderImageView; } @@ -81,7 +92,7 @@ public DescriptorUpdateBuilder buffer(int binding, int dstArrayElement, List Date: Mon, 12 Feb 2024 23:16:04 -0800 Subject: [PATCH 03/22] Move to GC tracked resources, WIP mostly working --- build.gradle | 4 +- gradle.properties | 6 +- .../acceleration/AccelerationBlasBuilder.java | 171 ++++------- .../acceleration/AccelerationManager.java | 35 +-- .../acceleration/AccelerationTLASManager.java | 216 ++++--------- .../acceleration/EntityBlasBuilder.java | 26 +- .../acceleration/JobPassThroughData.java | 3 +- .../acceleration/SharedQuadVkIndexBuffer.java | 15 +- .../java/me/cortex/vulkanite/client/Test.java | 33 +- .../me/cortex/vulkanite/client/Vulkanite.java | 31 +- .../rendering/SharedImageViewTracker.java | 37 +-- .../client/rendering/VulkanPipeline.java | 213 +++++-------- .../compat/IRenderTargetVkGetter.java | 5 +- .../me/cortex/vulkanite/compat/IVGBuffer.java | 5 +- .../me/cortex/vulkanite/compat/IVGImage.java | 5 +- .../vulkanite/compat/RaytracingShaderSet.java | 28 +- .../lib/base/TrackedResourceObject.java | 40 --- .../me/cortex/vulkanite/lib/base/VObject.java | 18 ++ .../me/cortex/vulkanite/lib/base/VRef.java | 44 +++ .../vulkanite/lib/cmd/CommandManager.java | 285 ++++++++++++++---- .../me/cortex/vulkanite/lib/cmd/VCmdBuff.java | 198 ++++++++---- .../vulkanite/lib/cmd/VCommandPool.java | 38 +-- .../DescriptorSetLayoutBuilder.java | 5 +- .../descriptors/DescriptorUpdateBuilder.java | 56 ++-- .../lib/descriptors/VDescriptorPool.java | 119 ++++---- .../lib/descriptors/VDescriptorSet.java | 17 +- .../lib/descriptors/VDescriptorSetLayout.java | 14 +- .../lib/descriptors/VTypedDescriptorPool.java | 87 ------ .../vulkanite/lib/memory/MemoryManager.java | 27 +- .../lib/memory/VAccelerationStructure.java | 23 +- .../cortex/vulkanite/lib/memory/VBuffer.java | 28 +- .../cortex/vulkanite/lib/memory/VGBuffer.java | 21 +- .../cortex/vulkanite/lib/memory/VGImage.java | 20 +- .../cortex/vulkanite/lib/memory/VImage.java | 12 +- .../vulkanite/lib/memory/VmaAllocator.java | 29 +- .../vulkanite/lib/other/VImageView.java | 28 +- .../vulkanite/lib/other/VQueryPool.java | 18 +- .../cortex/vulkanite/lib/other/VSampler.java | 14 +- .../vulkanite/lib/other/sync/SyncManager.java | 19 +- .../vulkanite/lib/other/sync/VFence.java | 15 +- .../vulkanite/lib/other/sync/VGSemaphore.java | 15 +- .../vulkanite/lib/other/sync/VSemaphore.java | 14 +- .../lib/pipeline/ComputePipelineBuilder.java | 11 +- .../lib/pipeline/RaytracePipelineBuilder.java | 18 +- .../lib/pipeline/VComputePipeline.java | 8 +- .../lib/pipeline/VRaytracePipeline.java | 41 +-- .../vulkanite/lib/shader/ShaderModule.java | 7 +- .../cortex/vulkanite/lib/shader/VShader.java | 16 +- .../shader/reflection/ShaderReflection.java | 13 +- .../vulkanite/mixin/iris/MixinGlTexture.java | 17 +- .../iris/MixinNativeImageBackedTexture.java | 8 +- .../iris/MixinNewWorldRenderingPipeline.java | 14 +- .../mixin/iris/MixinPBRAtlasTexture.java | 6 +- .../mixin/iris/MixinRenderTarget.java | 33 +- .../mixin/iris/MixinShaderStorageBuffer.java | 13 +- .../iris/MixinShaderStorageBufferHolder.java | 3 +- .../mixin/minecraft/MixinAbstractTexture.java | 12 +- .../mixin/minecraft/MixinResourceTexture.java | 4 +- .../minecraft/MixinSpriteAtlasTexture.java | 6 +- .../mixin/sodium/gl/MixinGLRenderDevice.java | 2 +- .../mixin/sodium/gl/MixinMutableBuffer.java | 11 +- src/main/resources/fabric.mod.json | 4 +- 62 files changed, 1118 insertions(+), 1166 deletions(-) delete mode 100644 src/main/java/me/cortex/vulkanite/lib/base/TrackedResourceObject.java create mode 100644 src/main/java/me/cortex/vulkanite/lib/base/VObject.java create mode 100644 src/main/java/me/cortex/vulkanite/lib/base/VRef.java delete mode 100644 src/main/java/me/cortex/vulkanite/lib/descriptors/VTypedDescriptorPool.java diff --git a/build.gradle b/build.gradle index 1a6d7e4..a73c356 100644 --- a/build.gradle +++ b/build.gradle @@ -38,8 +38,8 @@ dependencies { modImplementation("net.fabricmc.fabric-api:fabric-rendering-data-attachment-v1:0.3.38+73761d2e9a") modImplementation(fabricApi.module("fabric-resource-loader-v0", project.fabric_version)) - modImplementation "maven.modrinth:sodium:mc1.20.2-0.5.3" - modImplementation "maven.modrinth:iris:1.6.9+1.20.2" + modImplementation "maven.modrinth:sodium:mc1.20.2-0.5.5" + modImplementation "maven.modrinth:iris:1.6.14+1.20.2" modRuntimeOnly 'org.anarres:jcpp:1.4.14' modRuntimeOnly 'io.github.douira:glsl-transformer:2.0.0-pre13' diff --git a/gradle.properties b/gradle.properties index b0b4fc5..4e339e7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,11 +3,11 @@ org.gradle.jvmargs=-Xmx4G # Fabric Properties # check these on https://modmuss50.me/fabric.html minecraft_version=1.20.2 -yarn_mappings=1.20.2+build.1 -loader_version=0.14.21 +yarn_mappings=1.20.2+build.4 +loader_version=0.15.6 #Fabric api -fabric_version=0.88.5+1.20.2 +fabric_version=0.91.6+1.20.2 # Mod Properties mod_version=0.0.4-pre-alpha maven_group=me.cortex diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java index 1c51fe6..b39dd3b 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java @@ -7,6 +7,7 @@ import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.compat.IAccelerationBuildResult; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.cmd.VCmdBuff; import me.cortex.vulkanite.lib.cmd.VCommandPool; import me.cortex.vulkanite.lib.descriptors.DescriptorSetLayoutBuilder; @@ -45,22 +46,26 @@ public class AccelerationBlasBuilder { private final VContext context; private record BLASTriangleData(int quadCount, int geometryFlags) {} private record BLASBuildJob(List geometries, JobPassThroughData data) {} - public record BLASBuildResult(VAccelerationStructure structure, JobPassThroughData data) {} - public record BLASBatchResult(List results, VSemaphore semaphore) { } - private final Thread worker; + public record BLASBuildResult(VRef structure, JobPassThroughData data) {} + public record BLASBatchResult(List results, long execution) { } + private final int asyncQueue; private final Consumer resultConsumer; - private final VQueryPool queryPool; + private final VRef queryPool; //TODO: maybe move to an executor type system private final Semaphore awaitingJobBatchess = new Semaphore(0);//Note: this is done to avoid spin locking on the job consumer private final ConcurrentLinkedDeque> batchedJobs = new ConcurrentLinkedDeque<>(); - private final VComputePipeline gpuVertexDecodePipeline; + private final VRef gpuVertexDecodePipeline; + + public int getAsyncQueue() { + return asyncQueue; + } public AccelerationBlasBuilder(VContext context, int asyncQueue, Consumer resultConsumer) { - this.queryPool = new VQueryPool(context.device, 10000, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR); + this.queryPool = VQueryPool.create(context.device, 10000, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR); this.context = context; this.asyncQueue = asyncQueue; this.resultConsumer = resultConsumer; @@ -119,12 +124,10 @@ void main() { var decodePipeBuilder = new ComputePipelineBuilder(); decodePipeBuilder.addPushConstantRange(8 * 3, 0); - decodePipeBuilder.set(decodeShader.named()); + decodePipeBuilder.set(decodeShader.get().named()); gpuVertexDecodePipeline = decodePipeBuilder.build(context); - decodeShader.free(); - - worker = new Thread(this::run); + Thread worker = new Thread(this::run); worker.setName("Acceleration blas worker"); worker.start(); } @@ -157,8 +160,8 @@ private void run() { } } } + var sinlgeUsePoolWorker = context.cmd.getSingleUsePool(); - sinlgeUsePoolWorker.doReleases(); //Jobs are batched and built on the async vulkan queue then block synchronized with fence // which then results in compaction and dispatch to consumer @@ -169,16 +172,15 @@ private void run() { PointerBuffer buildRanges = stack.mallocPointer(jobs.size()); LongBuffer pAccelerationStructures = stack.mallocLong(jobs.size()); - List buffersToFree = new ArrayList<>(jobs.size() * 2); - var scratchBuffers = new VBuffer[jobs.size()]; - var accelerationStructures = new VAccelerationStructure[jobs.size()]; + var accelerationStructures = new ArrayList>(jobs.size()); - var uploadBuildCmd = sinlgeUsePoolWorker.createCommandBuffer(); - uploadBuildCmd.begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); + var uploadBuildCmdRef = sinlgeUsePoolWorker.createCommandBuffer(); + var uploadBuildCmd = uploadBuildCmdRef.get(); //Fill in the buildInfo and buildRanges int i = -1; - vkCmdBindPipeline(uploadBuildCmd.buffer, VK_PIPELINE_BIND_POINT_COMPUTE, gpuVertexDecodePipeline.pipeline()); + uploadBuildCmd.bindCompute(gpuVertexDecodePipeline); + for (var job : jobs) { i++; var brs = VkAccelerationStructureBuildRangeInfoKHR.calloc(job.geometries.size(), stack); @@ -190,7 +192,7 @@ private void run() { int vertexStride = 4 * 3; for (var geometry : job.geometries) { - buildBufferSize += geometry.quadCount * 4 * vertexStride; + buildBufferSize += geometry.quadCount * 4L * vertexStride; } if (buildBufferSize <= 0) { @@ -203,9 +205,8 @@ private void run() { | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0); - buildBuffer.setDebugUtilsObjectName("BLAS geometry buffer"); - buffersToFree.add(buildBuffer); - var buildBufferAddr = buildBuffer.deviceAddress(); + buildBuffer.get().setDebugUtilsObjectName("BLAS geometry buffer"); + var buildBufferAddr = buildBuffer.get().deviceAddress(); long buildBufferOffset = 0; uploadBuildCmd.encodeBufferBarrier(buildBuffer, 0, VK_WHOLE_SIZE, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, @@ -223,8 +224,8 @@ private void run() { // 2: outAddr var pushConstant = new long[3]; var geometryInputBuffer = job.data.geometryBuffers().get(geoIdx); - pushConstant[0] = geometry.quadCount * 4; - pushConstant[1] = geometryInputBuffer.deviceAddress(); + pushConstant[0] = geometry.quadCount * 4L; + pushConstant[1] = geometryInputBuffer.get().deviceAddress(); pushConstant[2] = buildBufferAddr + buildBufferOffset; if (pushConstant[1] == 0) { throw new IllegalStateException("Geometry input buffer address is 0"); @@ -232,10 +233,10 @@ private void run() { if (pushConstant[2] == 0) { throw new IllegalStateException("Build buffer address is 0"); } - vkCmdPushConstants(uploadBuildCmd.buffer, gpuVertexDecodePipeline.layout(), VK_SHADER_STAGE_ALL, 0, pushConstant); + uploadBuildCmd.pushConstants(0, pushConstant); uploadBuildCmd.encodeBufferBarrier(geometryInputBuffer, 0, VK_WHOLE_SIZE, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); - vkCmdDispatch(uploadBuildCmd.buffer, Math.min((geometry.quadCount * 4 + 255) / 256, 256), 1, 1); + uploadBuildCmd.dispatch(Math.min((geometry.quadCount * 4 + 255) / 256, 256), 1, 1); VkDeviceOrHostAddressConstKHR indexData = SharedQuadVkIndexBuffer.getIndexBuffer(context, uploadBuildCmd, @@ -265,7 +266,7 @@ private void run() { //maxPrims.put(2); //br.primitiveCount(2); - buildBufferOffset += geometry.quadCount * 4 * vertexStride; + buildBufferOffset += geometry.quadCount * 4L * vertexStride; } uploadBuildCmd.encodeBufferBarrier(buildBuffer, 0, VK_WHOLE_SIZE, VK_PIPELINE_STAGE_TRANSFER_BIT, @@ -299,141 +300,83 @@ private void run() { var scratch = context.memory.createBuffer(buildSizesInfo.buildScratchSize(), VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 256, 0); - scratch.setDebugUtilsObjectName("BLAS scratch buffer"); + scratch.get().setDebugUtilsObjectName("BLAS scratch buffer"); - bi.scratchData(VkDeviceOrHostAddressKHR.calloc(stack).deviceAddress(scratch.deviceAddress())); - bi.dstAccelerationStructure(structure.structure); + bi.scratchData(VkDeviceOrHostAddressKHR.calloc(stack).deviceAddress(scratch.get().deviceAddress())); + bi.dstAccelerationStructure(structure.get().structure); - pAccelerationStructures.put(structure.structure); + pAccelerationStructures.put(structure.get().structure); - accelerationStructures[i] = structure; - scratchBuffers[i] = scratch; + accelerationStructures.add(structure); + uploadBuildCmd.addBufferRef(scratch); } buildInfos.rewind(); buildRanges.rewind(); pAccelerationStructures.rewind(); - VSemaphore link = context.sync.createBinarySemaphore(); { - vkCmdBuildAccelerationStructuresKHR(uploadBuildCmd.buffer, buildInfos, buildRanges); + vkCmdBuildAccelerationStructuresKHR(uploadBuildCmd.buffer(), buildInfos, buildRanges); //TODO: should probably do memory barrier to read access uploadBuildCmd.encodeMemoryBarrier(); - queryPool.reset(uploadBuildCmd, 0, jobs.size()); + uploadBuildCmd.resetQueryPool(queryPool, 0, jobs.size()); vkCmdWriteAccelerationStructuresPropertiesKHR( - uploadBuildCmd.buffer, + uploadBuildCmd.buffer(), pAccelerationStructures, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, - queryPool.pool, + queryPool.get().pool, 0); - uploadBuildCmd.end(); - - VFence buildFence = context.sync.createFence(); - context.cmd.submit(asyncQueue, new VCmdBuff[]{uploadBuildCmd}, new VSemaphore[0], new int[0], - new VSemaphore[]{link}, - buildFence); - - //vkDeviceWaitIdle(context.device); - { - //We need to wait for the fence which signals that the build has finished and we can query the result - // TODO: find a cleaner way to wait on the query results (tho i think waiting on a fence is realistically the easiest thing to do) - vkWaitForFences(context.device, buildFence.address(), true, -1); - - //FIXME: this is extream jank, we can clean up after this point because we know the fence has passed, this is so ugly tho - - for (var sb : scratchBuffers) { - sb.free(); - } - for (var b : buffersToFree) { - b.free(); - } - - sinlgeUsePoolWorker.releaseNow(uploadBuildCmd); + long buildExecution = context.cmd.submit(asyncQueue, uploadBuildCmdRef); - //We can destroy the fence here since we know its passed - buildFence.free(); - } + // Waiting on a semaphore is realistically the easiest thing to do rn + context.cmd.hostWaitForExecution(asyncQueue, buildExecution); } - long[] compactedSizes = queryPool.getResultsLong(jobs.size()); - VSemaphore awaitSemaphore = context.sync.createBinarySemaphore(); - - VAccelerationStructure[] compactedAS = new VAccelerationStructure[jobs.size()]; + long[] compactedSizes = queryPool.get().getResultsLong(jobs.size()); List results = new ArrayList<>(); //vkDeviceWaitIdle(context.device); //--------------------- + long blasExecution = 0; { - var cmd = sinlgeUsePoolWorker.createCommandBuffer(); - cmd.begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - - //Dont need a memory barrier cause submit ensures cache flushing already + var cmdRef = sinlgeUsePoolWorker.createCommandBuffer(); + // Dont need a memory barrier cause submit ensures cache flushing already for (int idx = 0; idx < compactedSizes.length; idx++) { var as = context.memory.createAcceleration(compactedSizes[idx], 256, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR); - vkCmdCopyAccelerationStructureKHR(cmd.buffer, VkCopyAccelerationStructureInfoKHR.calloc(stack).sType$Default() - .src(accelerationStructures[idx].structure) - .dst(as.structure) + vkCmdCopyAccelerationStructureKHR(cmdRef.get().buffer(), VkCopyAccelerationStructureInfoKHR.calloc(stack).sType$Default() + .src(accelerationStructures.get(idx).get().structure) + .dst(as.get().structure) .mode(VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR)); - compactedAS[idx] = as; var job = jobs.get(idx); results.add(new BLASBuildResult(as, job.data)); } - vkCmdPipelineBarrier(cmd.buffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, null, null, null); - - VFence fence = context.sync.createFence(); - - cmd.end(); - context.cmd.submit(asyncQueue, new VCmdBuff[]{cmd}, - new VSemaphore[]{link}, - new int[]{VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR}, - new VSemaphore[]{awaitSemaphore}, - fence); - - context.sync.addCallback(fence, () -> { - for (var as : accelerationStructures) { - as.free(); - } - - cmd.enqueueFree(); - fence.free(); - link.free(); - }); + blasExecution = context.cmd.submit(asyncQueue, cmdRef); } - //Submit to callback, linking the build semaphore so that we dont stall the queue more than we need - resultConsumer.accept(new BLASBatchResult(results, awaitSemaphore)); + resultConsumer.accept(new BLASBatchResult(results, blasExecution)); - //TODO: FIXME, so there is an issue in that the query pool needs to be represented per thing - // since the cpu can run ahead of the gpu, need multiple query pools until we know the gpu is finished with it - // using a fence, OR FOR THREAD ONLY we can assume that we allow one batch per queue - //that is, at the end (here) we do a vkWaitForFences on the final fence, _then_ we can release all the temporary - // resources that we know weve used, TODO: I THINK I FIXED THIS BY PUTTING A FENCE SYNC between stage 1 and 2 - - //NOTE: THIS IS ACTUALLY WRONG, since we need to block on the query result in order to do the second part - // it doesnt matter about needing multiple query pools - - //vkDeviceWaitIdle(context.device); + context.cmd.hostWaitForExecution(asyncQueue, blasExecution); } } } - private VBuffer uploadTerrainGeometry(BuiltSectionMeshParts meshParts, VCmdBuff cmd) { + private VRef uploadTerrainGeometry(BuiltSectionMeshParts meshParts, VCmdBuff cmd) { var buff = context.memory.createBuffer(meshParts.getVertexData().getLength(), VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - buff.setDebugUtilsObjectName("Terrain geometry buffer"); + buff.get().setDebugUtilsObjectName("Terrain geometry buffer"); cmd.encodeDataUpload(context.memory, MemoryUtil.memAddress(meshParts.getVertexData().getDirectBuffer()), buff, 0, meshParts.getVertexData().getLength()); @@ -452,7 +395,7 @@ public void enqueue(List batch) { if (acbr == null) continue; List buildData = new ArrayList<>(); - List geometryBuffers = new ArrayList<>(); + List> geometryBuffers = new ArrayList<>(); for (var entry : acbr.entrySet()) { int flag = entry.getKey() == DefaultTerrainRenderPasses.SOLID ? VK_GEOMETRY_OPAQUE_BIT_KHR : 0; buildData.add(new BLASTriangleData(entry.getValue().quadCount(), flag)); @@ -464,10 +407,9 @@ public void enqueue(List batch) { if (!hasJobs) { hasJobs = true; - cmd.begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); } - geometryBuffers.add(uploadTerrainGeometry(geometry, cmd)); + geometryBuffers.add(uploadTerrainGeometry(geometry, cmd.get())); } if (buildData.size() > 0) { @@ -477,14 +419,13 @@ public void enqueue(List batch) { } if (hasJobs) { - cmd.end(); // TODO: Which queue should this be submitted to? // Should we move all uploads to the worker? - context.cmd.submitOnceAndWait(0, cmd); + context.cmd.submitOnceAndWait(1, cmd); } if (jobs.isEmpty()) { - return;//No jobs to do + return; // No jobs to do } batchedJobs.add(jobs); awaitingJobBatchess.release(); diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationManager.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationManager.java index 0d583cc..41d3b55 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationManager.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationManager.java @@ -1,6 +1,9 @@ package me.cortex.vulkanite.acceleration; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; +import me.cortex.vulkanite.lib.cmd.VCmdBuff; +import me.cortex.vulkanite.lib.descriptors.VDescriptorSet; import me.cortex.vulkanite.lib.descriptors.VDescriptorSetLayout; import me.cortex.vulkanite.lib.memory.VAccelerationStructure; import me.cortex.vulkanite.lib.memory.VBuffer; @@ -38,7 +41,7 @@ public void setEntityData(List> dat tlasManager.setEntityData(data); } - private final List syncs = new LinkedList<>(); + private final List blasExecutions = new LinkedList<>(); //This updates the tlas internal structure, DOES NOT INCLUDING BUILDING THE TLAS public void updateTick() { @@ -48,15 +51,16 @@ public void updateTick() { while (!blasResults.isEmpty()) { var batch = blasResults.poll(); results.addAll(batch.results()); - syncs.add(batch.semaphore()); + blasExecutions.add(batch.execution()); } tlasManager.updateSections(results); } } - public VAccelerationStructure buildTLAS(VSemaphore inLink, VSemaphore outLink) { - tlasManager.buildTLAS(inLink, outLink, syncs.toArray(new VSemaphore[0])); - syncs.clear(); + public VRef buildTLAS(int queueId, VCmdBuff cmd) { + blasExecutions.forEach(exec -> ctx.cmd.queueWaitForExeuction(queueId, blasBuilder.getAsyncQueue(), exec)); + blasExecutions.clear(); + tlasManager.buildTLAS(cmd); return tlasManager.getTlas(); } @@ -64,28 +68,11 @@ public void sectionRemove(RenderSection section) { tlasManager.removeSection(section); } - //Cleans up any loose things such as semaphores waiting to be synced etc - public void cleanup() { - //TODO: FIXME: I DONT THINK THIS IS CORRECT OR WORKS, IM STILL LEAKING VRAM MEMORY OUT THE WAZOO WHEN f3+a reloading - ctx.cmd.waitQueueIdle(0); - ctx.cmd.waitQueueIdle(1); - try { - Thread.sleep(250L); - } catch (InterruptedException e) { - e.printStackTrace(); - } - ctx.cmd.waitQueueIdle(0); - ctx.cmd.waitQueueIdle(1); - syncs.forEach(VSemaphore::free); - syncs.clear(); - tlasManager.cleanupTick(); - } - - public long getGeometrySet() { + public VRef getGeometrySet() { return tlasManager.getGeometrySet(); } - public VDescriptorSetLayout getGeometryLayout() { + public VRef getGeometryLayout() { return tlasManager.getGeometryLayout(); } } diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java index 068c0dd..395527a 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java @@ -5,12 +5,10 @@ import com.mojang.blaze3d.systems.RenderSystem; import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.cmd.VCmdBuff; import me.cortex.vulkanite.lib.cmd.VCommandPool; -import me.cortex.vulkanite.lib.descriptors.DescriptorSetLayoutBuilder; -import me.cortex.vulkanite.lib.descriptors.DescriptorUpdateBuilder; -import me.cortex.vulkanite.lib.descriptors.VDescriptorPool; -import me.cortex.vulkanite.lib.descriptors.VDescriptorSetLayout; +import me.cortex.vulkanite.lib.descriptors.*; import me.cortex.vulkanite.lib.memory.VAccelerationStructure; import me.cortex.vulkanite.lib.memory.VBuffer; import me.cortex.vulkanite.lib.other.sync.VFence; @@ -39,18 +37,13 @@ public class AccelerationTLASManager { private final TLASSectionManager buildDataManager = new TLASSectionManager(); private final VContext context; private final int queue; - private final VCommandPool singleUsePool; - private final List structuresToRelease = new ArrayList<>(); - - private VAccelerationStructure currentTLAS; + private VRef currentTLAS; public AccelerationTLASManager(VContext context, int queue) { this.context = context; this.queue = queue; - this.singleUsePool = context.cmd.createSingleUsePool(); - this.singleUsePool.setDebugUtilsObjectName("TLAS singleUsePool"); - this.buildDataManager.resizeBindlessSet(0, null); + this.buildDataManager.resizeBindlessSet(0); this.entityBlasBuilder = new EntityBlasBuilder(context); } @@ -78,25 +71,9 @@ public void removeSection(RenderSection section) { // TODO: cleanup, this is very messy // FIXME: in the case of no geometry create an empty tlas or something??? - public void buildTLAS(VSemaphore semIn, VSemaphore semOut, VSemaphore[] blocking) { + public void buildTLAS(VCmdBuff cmd) { RenderSystem.assertOnRenderThread(); - singleUsePool.doReleases(); - - if (buildDataManager.sectionCount() == 0) { - if (blocking.length != 0) { - // This case can happen when reloading or some other weird cases, only occurse - // when the world _becomes_ empty for some reason, so just clear all the - // semaphores - // TODO: move to a destroy method or something in AccelerationManager instead of - // here - for (var semaphore : blocking) { - semaphore.free(); - } - } - return; - } - // NOTE: renderLink is required to ensure that we are not overriding memory that // is actively being used for frames // should have a VK_PIPELINE_STAGE_TRANSFER_BIT blocking bit @@ -105,23 +82,12 @@ public void buildTLAS(VSemaphore semIn, VSemaphore semOut, VSemaphore[] blocking // each region is its own geometry input // this is done for performance reasons when updating (adding/removing) sections - - - VkAccelerationStructureGeometryKHR geometry = VkAccelerationStructureGeometryKHR.calloc(stack); int instances = 0; - var cmd = singleUsePool.createCommandBuffer(); - cmd.begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - VFence fence = context.sync.createFence(); - - Pair entityBuild; + Pair, VRef> entityBuild; if (entityData != null) { - entityBuild = entityBlasBuilder.buildBlas(entityData, cmd, fence); - context.sync.addCallback(fence, ()->{ - entityBuild.getLeft().free(); - entityBuild.getRight().free(); - }); + entityBuild = entityBlasBuilder.buildBlas(entityData, cmd); } else { entityBuild = null; } @@ -134,12 +100,7 @@ public void buildTLAS(VSemaphore semIn, VSemaphore semOut, VSemaphore[] blocking // the current build phase, and the gpu side needs to be updated accoringly and // synced correctly - vkCmdPipelineBarrier(cmd.buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, - VkMemoryBarrier.calloc(1, stack) - .sType$Default() - .srcAccessMask(0) - .dstAccessMask(VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT), - null, null); + cmd.encodeMemoryBarrier(); VkAccelerationStructureInstanceKHR extra = null; if (entityBuild != null) { @@ -147,21 +108,15 @@ public void buildTLAS(VSemaphore semIn, VSemaphore semOut, VSemaphore[] blocking extra.mask(~0) .instanceCustomIndex(0) .instanceShaderBindingTableRecordOffset(1) - .accelerationStructureReference(entityBuild.getLeft().deviceAddress); + .accelerationStructureReference(entityBuild.getLeft().get().deviceAddress); extra.transform().matrix(new Matrix4x3f().getTransposed(stack.mallocFloat(12))); buildDataManager.descUpdateJobs.add(new TLASSectionManager.DescUpdateJob(0,0, List.of(entityBuild.getRight()))); instances++; } - buildDataManager.setGeometryUpdateMemory(fence, geometry, extra); + buildDataManager.setGeometryUpdateMemory(geometry, extra); instances += buildDataManager.sectionCount(); - vkCmdPipelineBarrier(cmd.buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, - VkMemoryBarrier.calloc(1, stack) - .sType$Default() - .srcAccessMask(VK_ACCESS_TRANSFER_WRITE_BIT) - .dstAccessMask(VK_ACCESS_SHADER_READ_BIT), - null, null); + cmd.encodeMemoryBarrier(); } @@ -201,7 +156,7 @@ public void buildTLAS(VSemaphore semIn, VSemaphore semOut, VSemaphore[] blocking stack.ints(instanceCounts), buildSizesInfo); - VAccelerationStructure tlas = context.memory.createAcceleration(buildSizesInfo.accelerationStructureSize(), + var tlas = context.memory.createAcceleration(buildSizesInfo.accelerationStructureSize(), 256, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR, VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR); @@ -210,14 +165,14 @@ public void buildTLAS(VSemaphore semIn, VSemaphore semOut, VSemaphore[] blocking // about that and it should // get automatically freed since we using vma dont have to worry about // performance _too_ much i think - VBuffer scratchBuffer = context.memory.createBuffer(buildSizesInfo.buildScratchSize(), + var scratchBuffer = context.memory.createBuffer(buildSizesInfo.buildScratchSize(), VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 256, 0); - scratchBuffer.setDebugUtilsObjectName("TLAS Scratch Buffer"); + scratchBuffer.get().setDebugUtilsObjectName("TLAS Scratch Buffer"); - buildInfo.dstAccelerationStructure(tlas.structure) + buildInfo.dstAccelerationStructure(tlas.get().structure) .scratchData(VkDeviceOrHostAddressKHR.calloc(stack) - .deviceAddress(scratchBuffer.deviceAddress())); + .deviceAddress(scratchBuffer.get().deviceAddress())); var buildRanges = VkAccelerationStructureBuildRangeInfoKHR.calloc(instanceCounts.length, stack); for (int count : instanceCounts) { @@ -225,50 +180,19 @@ public void buildTLAS(VSemaphore semIn, VSemaphore semOut, VSemaphore[] blocking } buildRanges.rewind(); - vkCmdBuildAccelerationStructuresKHR(cmd.buffer, + vkCmdBuildAccelerationStructuresKHR(cmd.buffer(), buildInfo, stack.pointers(buildRanges)); + cmd.addBufferRef(scratchBuffer); - cmd.end(); - - int[] waitingStage = new int[blocking.length + 1]; - VSemaphore[] allBlocking = new VSemaphore[waitingStage.length]; - System.arraycopy(blocking, 0, allBlocking, 0, blocking.length); + cmd.encodeMemoryBarrier(); - allBlocking[waitingStage.length - 1] = semIn; - - Arrays.fill(waitingStage, - VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_TRANSFER_BIT); - context.cmd.submit(queue, new VCmdBuff[] { cmd }, allBlocking, waitingStage, new VSemaphore[] { semOut }, - fence); - - VAccelerationStructure oldTLAS = currentTLAS; currentTLAS = tlas; - - List capturedList = new ArrayList<>(structuresToRelease); - structuresToRelease.clear(); - context.sync.addCallback(fence, () -> { - scratchBuffer.free(); - if (oldTLAS != null) { - oldTLAS.free(); - } - fence.free(); - cmd.enqueueFree(); - - for (var as : capturedList) { - as.free(); - } - - // Release all the semaphores from the blas build system - for (var sem : blocking) { - sem.free(); - } - }); } } - public VAccelerationStructure getTlas() { - return currentTLAS; + public VRef getTlas() { + return currentTLAS.addRef(); } @@ -296,33 +220,36 @@ public TLASGeometryManager() { // TODO: make the instances buffer, gpu permenent then stream updates instead of // uploading per frame - public void setGeometryUpdateMemory(VFence fence, VkAccelerationStructureGeometryKHR struct, VkAccelerationStructureInstanceKHR addin) { + public VRef setGeometryUpdateMemory(VkAccelerationStructureGeometryKHR struct, VkAccelerationStructureInstanceKHR addin) { long size = (long) VkAccelerationStructureInstanceKHR.SIZEOF * count; - VBuffer data = context.memory.createBuffer(size + (addin==null?0:VkAccelerationStructureInstanceKHR.SIZEOF), + long newSize = size + (addin==null?0:VkAccelerationStructureInstanceKHR.SIZEOF); + if (newSize == 0) { + System.err.println("Instance buffer has a new size of 0, something is wrong."); + newSize = VkAccelerationStructureInstanceKHR.SIZEOF; + } + var data = context.memory.createBuffer(newSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_HEAP_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 0, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); - data.setDebugUtilsObjectName("TLAS Instance Buffer"); - long ptr = data.map(); + data.get().setDebugUtilsObjectName("TLAS Instance Buffer"); + long ptr = data.get().map(); if (addin != null) { MemoryUtil.memCopy(addin.address(), ptr, VkAccelerationStructureInstanceKHR.SIZEOF); ptr += VkAccelerationStructureInstanceKHR.SIZEOF; } MemoryUtil.memCopy(this.instances.address(0), ptr, size); - data.unmap(); - data.flush(); + data.get().unmap(); + data.get().flush(); struct.geometry() .instances() .data() - .deviceAddress(data.deviceAddress()); + .deviceAddress(data.get().deviceAddress()); - context.sync.addCallback(fence, () -> { - data.free(); - }); + return data; } public int sectionCount() { @@ -398,23 +325,23 @@ public TLASSectionManager() { } } - private VDescriptorSetLayout geometryBufferSetLayout; - private VDescriptorPool geometryBufferDescPool; - private long geometryBufferDescSet = 0; + private VRef geometryBufferSetLayout; + private VRef geometryBufferDescPool; + private VRef geometryBufferDescSet = null; private int setCapacity = 0; - private record DescUpdateJob(int binding, int dstArrayElement, List buffers) { + private record DescUpdateJob(int binding, int dstArrayElement, List> buffers) { } - private record ArenaDeallocJob(int index, int count, List geometryBuffers) { + private record ArenaDeallocJob(int index, int count, List> geometryBuffers) { } private final ConcurrentLinkedDeque descUpdateJobs = new ConcurrentLinkedDeque<>(); private final ConcurrentLinkedDeque arenaDeallocJobs = new ConcurrentLinkedDeque<>(); - private final Deque descPoolsToRelease = new ArrayDeque<>(); + private final Deque> descPoolsToRelease = new ArrayDeque<>(); - public void resizeBindlessSet(int newSize, VFence fence) { + public void resizeBindlessSet(int newSize) { if (geometryBufferSetLayout == null) { var layoutBuilder = new DescriptorSetLayoutBuilder( VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT); @@ -428,21 +355,19 @@ public void resizeBindlessSet(int newSize, VFence fence) { if (newSize > setCapacity) { int newCapacity = roundUpPow2(Math.max(newSize, 32)); - var newGeometryBufferDescPool = new VDescriptorPool(context, - VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, 1, newCapacity, geometryBufferSetLayout.types); - newGeometryBufferDescPool.allocateSets(geometryBufferSetLayout, new int[] { newCapacity }); - long newGeometryBufferDescSet = newGeometryBufferDescPool.get(0); + var newGeometryBufferDescPool = VDescriptorPool.create(context, geometryBufferSetLayout, VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, newCapacity); + var newGeometryBufferDescSet = newGeometryBufferDescPool.get().allocateSet(newCapacity); - System.out.println("New geometry desc set: " + Long.toHexString(newGeometryBufferDescSet) + System.out.println("New geometry desc set: " + Long.toHexString(newGeometryBufferDescSet.get().set) + " with capacity " + newCapacity); - if (geometryBufferDescSet != 0) { + if (geometryBufferDescSet != null) { try (var stack = stackPush()) { var setCopy = VkCopyDescriptorSet.calloc(1, stack); setCopy.get(0) .sType$Default() - .srcSet(geometryBufferDescSet) - .dstSet(newGeometryBufferDescSet) + .srcSet(geometryBufferDescSet.get().set) + .dstSet(newGeometryBufferDescSet.get().set) .descriptorCount(setCapacity); vkUpdateDescriptorSets(context.device, null, setCopy); } @@ -458,12 +383,12 @@ public void resizeBindlessSet(int newSize, VFence fence) { } @Override - public void setGeometryUpdateMemory(VFence fence, VkAccelerationStructureGeometryKHR struct, VkAccelerationStructureInstanceKHR addin) { - super.setGeometryUpdateMemory(fence, struct, addin); - resizeBindlessSet(arena.maxIndex, fence); + public VRef setGeometryUpdateMemory(VkAccelerationStructureGeometryKHR struct, VkAccelerationStructureInstanceKHR addin) { + var instanceBuf = super.setGeometryUpdateMemory(struct, addin); + resizeBindlessSet(arena.maxIndex); if (descUpdateJobs.isEmpty()) { - return; + return null; } var dub = new DescriptorUpdateBuilder(context, descUpdateJobs.size()); @@ -478,6 +403,8 @@ public void setGeometryUpdateMemory(VFence fence, VkAccelerationStructureGeometr Vulkanite.INSTANCE.addSyncedCallback(() -> { fenceTick(); }); + + return instanceBuf; } // TODO: mixinto RenderSection and add a reference to a holder for us, its much @@ -485,10 +412,10 @@ public void setGeometryUpdateMemory(VFence fence, VkAccelerationStructureGeometr private static final class Holder { final int id; int geometryIndex = -1; - List geometryBuffers; + List> geometryBuffers; final RenderSection section; - VAccelerationStructure structure; + VRef structure; private Holder(int id, RenderSection section) { this.id = id; @@ -502,19 +429,14 @@ public void fenceTick() { while (!arenaDeallocJobs.isEmpty()) { var job = arenaDeallocJobs.poll(); arena.free(job.index, job.count); - job.geometryBuffers.forEach(buffer -> buffer.free()); - } - while (!descPoolsToRelease.isEmpty()) { - descPoolsToRelease.poll().free(); + job.geometryBuffers.clear(); } + descPoolsToRelease.clear(); } public void update(AccelerationBlasBuilder.BLASBuildResult result) { var data = result.data(); var holder = tmp.computeIfAbsent(data.section().getPosition(), a -> new Holder(alloc(), data.section())); - if (holder.structure != null) { - structuresToRelease.add(holder.structure); - } holder.structure = result.structure(); if (holder.geometryIndex != -1) { @@ -530,7 +452,7 @@ public void update(AccelerationBlasBuilder.BLASBuildResult result) { var asi = VkAccelerationStructureInstanceKHR.calloc(stack) .mask(~0) .instanceCustomIndex(holder.geometryIndex) - .accelerationStructureReference(holder.structure.deviceAddress); + .accelerationStructureReference(holder.structure.get().deviceAddress); asi.transform() .matrix(new Matrix4x3f() .translate(holder.section.getOriginX(), holder.section.getOriginY(), @@ -545,8 +467,6 @@ public void remove(RenderSection section) { if (holder == null) return; - structuresToRelease.add(holder.structure); - free(holder.id); for (var job : descUpdateJobs) { @@ -598,25 +518,11 @@ public void free(int pos, int count) { } } - public long getGeometrySet() { + public VRef getGeometrySet() { return buildDataManager.geometryBufferDescSet; } - public VDescriptorSetLayout getGeometryLayout() { - return buildDataManager.geometryBufferSetLayout; - } - - // Called for cleaning up any remaining loose resources - void cleanupTick() { - singleUsePool.doReleases(); - structuresToRelease.forEach(VAccelerationStructure::free); - structuresToRelease.clear(); - if (currentTLAS != null) { - currentTLAS.free(); - currentTLAS = null; - } - if (buildDataManager.sectionCount() != 0) { - throw new IllegalStateException("Sections are not empty on cleanup"); - } + public VRef getGeometryLayout() { + return buildDataManager.geometryBufferSetLayout.addRef(); } } diff --git a/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java b/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java index be44244..1908a0f 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java @@ -2,11 +2,11 @@ import me.cortex.vulkanite.compat.IVGImage; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.cmd.VCmdBuff; import me.cortex.vulkanite.lib.memory.VAccelerationStructure; import me.cortex.vulkanite.lib.memory.VBuffer; import me.cortex.vulkanite.lib.other.VUtil; -import me.cortex.vulkanite.lib.other.sync.VFence; import net.coderbot.iris.vertices.IrisVertexFormats; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.BufferBuilder; @@ -35,7 +35,7 @@ public EntityBlasBuilder(VContext context) { } private record BuildInfo(VertexFormat format, int quadCount, long address) {} - Pair buildBlas(List> renders, VCmdBuff cmd, VFence fence) { + Pair, VRef> buildBlas(List> renders, VCmdBuff cmd) { long combined_size = 0; TextureManager textureManager = MinecraftClient.getInstance().getTextureManager(); for (var type : renders) { @@ -57,25 +57,25 @@ Pair buildBlas(List infos = new ArrayList<>(); for (var pair : renders) { offset = VUtil.alignUp(offset, 128); MemoryUtil.memCopy(MemoryUtil.memAddress(pair.getRight().getVertexBuffer()), ptr + offset, pair.getRight().getVertexBuffer().remaining()); - infos.add(new BuildInfo(pair.getRight().getParameters().format(), pair.getRight().getParameters().indexCount()/6, geometryBuffer.deviceAddress() + offset)); + infos.add(new BuildInfo(pair.getRight().getParameters().format(), pair.getRight().getParameters().indexCount()/6, geometryBuffer.get().deviceAddress() + offset)); offset += pair.getRight().getVertexBuffer().remaining(); } - geometryBuffer.unmap(); + geometryBuffer.get().unmap(); - VAccelerationStructure blas = null; + VRef blas = null; try (var stack = MemoryStack.stackPush()) { int[] primitiveCounts = new int[infos.size()]; var buildInfo = populateBuildStructs(ctx, stack, cmd, infos, primitiveCounts); - blas = executeBlasBuild(ctx, cmd, fence, stack, buildInfo, primitiveCounts); + blas = executeBlasBuild(ctx, cmd, stack, buildInfo, primitiveCounts); } @@ -115,7 +115,7 @@ private VkAccelerationStructureGeometryKHR.Buffer populateBuildStructs(VContext return geometryInfos; } - private static VAccelerationStructure executeBlasBuild(VContext ctx, VCmdBuff cmd, VFence cleanupFence, MemoryStack stack, VkAccelerationStructureGeometryKHR.Buffer geometryInfos, int[] prims) { + private static VRef executeBlasBuild(VContext ctx, VCmdBuff cmd, MemoryStack stack, VkAccelerationStructureGeometryKHR.Buffer geometryInfos, int[] prims) { var buildInfos = VkAccelerationStructureBuildGeometryInfoKHR.calloc(1, stack); var buildRanges = VkAccelerationStructureBuildRangeInfoKHR.calloc(prims.length, stack); for (int primCount : prims) { @@ -148,20 +148,20 @@ private static VAccelerationStructure executeBlasBuild(VContext ctx, VCmdBuff cm VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 256, 0); - bi.scratchData(VkDeviceOrHostAddressKHR.calloc(stack).deviceAddress(scratch.deviceAddress())); - bi.dstAccelerationStructure(structure.structure); + bi.scratchData(VkDeviceOrHostAddressKHR.calloc(stack).deviceAddress(scratch.get().deviceAddress())); + bi.dstAccelerationStructure(structure.get().structure); buildInfos.rewind(); buildRanges.rewind(); - vkCmdBuildAccelerationStructuresKHR(cmd.buffer, buildInfos, stack.pointers(buildRanges)); + vkCmdBuildAccelerationStructuresKHR(cmd.buffer(), buildInfos, stack.pointers(buildRanges)); - vkCmdPipelineBarrier(cmd.buffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, VkMemoryBarrier.calloc(1) + vkCmdPipelineBarrier(cmd.buffer(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, VkMemoryBarrier.calloc(1) .sType$Default() .srcAccessMask(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR) .dstAccessMask(VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR), null, null); - ctx.sync.addCallback(cleanupFence, scratch::free); + cmd.addBufferRef(scratch); return structure; } } diff --git a/src/main/java/me/cortex/vulkanite/acceleration/JobPassThroughData.java b/src/main/java/me/cortex/vulkanite/acceleration/JobPassThroughData.java index d54d4c2..0a7a080 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/JobPassThroughData.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/JobPassThroughData.java @@ -1,10 +1,11 @@ package me.cortex.vulkanite.acceleration; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VBuffer; import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; import java.util.List; -public record JobPassThroughData(RenderSection section, long time, List geometryBuffers) { +public record JobPassThroughData(RenderSection section, long time, List> geometryBuffers) { } diff --git a/src/main/java/me/cortex/vulkanite/acceleration/SharedQuadVkIndexBuffer.java b/src/main/java/me/cortex/vulkanite/acceleration/SharedQuadVkIndexBuffer.java index 056101c..ea7090e 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/SharedQuadVkIndexBuffer.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/SharedQuadVkIndexBuffer.java @@ -1,6 +1,7 @@ package me.cortex.vulkanite.acceleration; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.cmd.VCmdBuff; import me.cortex.vulkanite.lib.memory.VBuffer; import org.lwjgl.system.MemoryUtil; @@ -15,8 +16,7 @@ public class SharedQuadVkIndexBuffer { public static final int TYPE = VK_INDEX_TYPE_UINT32; - private static VBuffer indexBuffer = null; - private static VkDeviceOrHostAddressConstKHR indexBufferAddr = null; + private static VRef indexBuffer = null; private static int currentQuadCount = 0; public synchronized static VkDeviceOrHostAddressConstKHR getIndexBuffer(VContext context, VCmdBuff uploaCmdBuff, int quadCount) { @@ -24,16 +24,10 @@ public synchronized static VkDeviceOrHostAddressConstKHR getIndexBuffer(VContext makeNewIndexBuffer(context, uploaCmdBuff, quadCount); } - return indexBufferAddr; + return indexBuffer.get().deviceAddressConst(); } private static void makeNewIndexBuffer(VContext context, VCmdBuff uploaCmdBuff, int quadCount) { - if (indexBuffer != null) { - //TODO: need to enqueue the old indexBuffer for memory release - indexBufferAddr.free();//Note this is calloced (in global heap) so need to release it IS SEPERATE FROM indexBuffer - throw new IllegalStateException(); - } - ByteBuffer buffer = genQuadIdxs(quadCount); //TODO: dont harcode VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR and VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT indexBuffer = context.memory.createBuffer(buffer.remaining(), @@ -41,12 +35,11 @@ private static void makeNewIndexBuffer(VContext context, VCmdBuff uploaCmdBuff, | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_HEAP_DEVICE_LOCAL_BIT); - indexBuffer.setDebugUtilsObjectName("Geometry Index Buffer"); + indexBuffer.get().setDebugUtilsObjectName("Geometry Index Buffer"); uploaCmdBuff.encodeDataUpload(context.memory, MemoryUtil.memAddress(buffer), indexBuffer, 0, buffer.remaining()); - indexBufferAddr = VkDeviceOrHostAddressConstKHR.calloc().deviceAddress(indexBuffer.deviceAddress()); currentQuadCount = quadCount; } diff --git a/src/main/java/me/cortex/vulkanite/client/Test.java b/src/main/java/me/cortex/vulkanite/client/Test.java index 7f59bca..e0a9af4 100644 --- a/src/main/java/me/cortex/vulkanite/client/Test.java +++ b/src/main/java/me/cortex/vulkanite/client/Test.java @@ -116,21 +116,21 @@ public static void main(String[] args) throws IOException { var context = init.createContext(); context.memory.createSharedBuffer(1000, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - context.memory.createSharedBuffer(1000, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT).free(); - context.memory.createSharedBuffer(1000, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT).free(); - context.memory.createSharedBuffer(1000, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT).free(); - context.memory.createSharedImage(128,128, 1, VK_FORMAT_R8G8B8A8_UNORM, GL_RGBA8, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT).free(); - context.memory.createSharedImage(128,128, 1, VK_FORMAT_R8G8B8A8_UNORM, GL_RGBA8, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT).free(); - context.memory.createSharedImage(128,128, 1, VK_FORMAT_R8G8B8A8_UNORM, GL_RGBA8, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT).free(); - context.memory.createAcceleration(100*256,256, 0, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR).free(); + context.memory.createSharedBuffer(1000, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + context.memory.createSharedBuffer(1000, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + context.memory.createSharedBuffer(1000, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + context.memory.createSharedImage(128,128, 1, VK_FORMAT_R8G8B8A8_UNORM, GL_RGBA8, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + context.memory.createSharedImage(128,128, 1, VK_FORMAT_R8G8B8A8_UNORM, GL_RGBA8, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + context.memory.createSharedImage(128,128, 1, VK_FORMAT_R8G8B8A8_UNORM, GL_RGBA8, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + context.memory.createAcceleration(100*256,256, 0, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR); var pool = context.cmd.createSingleUsePool(); - pool.createCommandBuffer(); + pool.get().createCommandBuffer(); var mem = context.memory.createBuffer(1024, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 0, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); - mem.map(); - mem.unmap(); - mem.flush(); + mem.get().map(); + mem.get().unmap(); + mem.get().flush(); System.gc(); // SharedQuadVkIndexBuffer.getIndexBuffer(context, uploadCmd, 10000); @@ -197,13 +197,12 @@ public static void main(String[] args) throws IOException { var rchs = VShader.compileLoad(context, Files.readString(new File("run/raychit.glsl").toPath()), VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR); var pipeline = new RaytracePipelineBuilder() .addLayout(layout) - .setRayGen(rgs.named()) - .addMiss(rms.named()) - .addHit(rchs.named(), null, null) + .setRayGen(rgs.get().named()) + .addMiss(rms.get().named()) + .addHit(rchs.get().named(), null, null) .build(context, 1); - context.sync.createSharedBinarySemaphore() - .free(); + context.sync.createSharedBinarySemaphore(); var cl = new DescriptorSetLayoutBuilder() @@ -212,7 +211,7 @@ public static void main(String[] args) throws IOException { var compute = VShader.compileLoad(context, Files.readString(new File("run/compute.glsl").toPath()), VK_SHADER_STAGE_COMPUTE_BIT); var comppipe = new ComputePipelineBuilder() - .set(compute.named()) + .set(compute.get().named()) .addLayout(cl) .build(context); diff --git a/src/main/java/me/cortex/vulkanite/client/Vulkanite.java b/src/main/java/me/cortex/vulkanite/client/Vulkanite.java index 0adc120..1e6e6d3 100644 --- a/src/main/java/me/cortex/vulkanite/client/Vulkanite.java +++ b/src/main/java/me/cortex/vulkanite/client/Vulkanite.java @@ -1,13 +1,11 @@ package me.cortex.vulkanite.client; import me.cortex.vulkanite.acceleration.AccelerationManager; -import me.cortex.vulkanite.acceleration.SharedQuadVkIndexBuffer; -import me.cortex.vulkanite.client.rendering.VulkanPipeline; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.base.initalizer.VInitializer; import me.cortex.vulkanite.lib.descriptors.VDescriptorPool; import me.cortex.vulkanite.lib.descriptors.VDescriptorSetLayout; -import me.cortex.vulkanite.lib.descriptors.VTypedDescriptorPool; import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; import net.minecraft.util.Util; @@ -17,13 +15,8 @@ import java.util.HashMap; import java.util.List; -import static org.lwjgl.vulkan.EXTDebugUtils.VK_EXT_DEBUG_UTILS_EXTENSION_NAME; import static org.lwjgl.vulkan.EXTDescriptorIndexing.VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME; -import static org.lwjgl.vulkan.EXTMemoryBudget.VK_EXT_MEMORY_BUDGET_EXTENSION_NAME; -import static org.lwjgl.vulkan.KHR16bitStorage.VK_KHR_16BIT_STORAGE_EXTENSION_NAME; -import static org.lwjgl.vulkan.KHR8bitStorage.VK_KHR_8BIT_STORAGE_EXTENSION_NAME; import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME; -import static org.lwjgl.vulkan.KHRBufferDeviceAddress.VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME; import static org.lwjgl.vulkan.KHRDeferredHostOperations.VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME; import static org.lwjgl.vulkan.KHRExternalFenceCapabilities.VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME; import static org.lwjgl.vulkan.KHRExternalFenceFd.VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME; @@ -38,7 +31,6 @@ import static org.lwjgl.vulkan.KHRExternalSemaphoreWin32.VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME; import static org.lwjgl.vulkan.KHRGetMemoryRequirements2.VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME; import static org.lwjgl.vulkan.KHRGetPhysicalDeviceProperties2.VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME; -import static org.lwjgl.vulkan.KHRRayQuery.VK_KHR_RAY_QUERY_EXTENSION_NAME; import static org.lwjgl.vulkan.KHRRayTracingPipeline.VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME; import static org.lwjgl.vulkan.KHRShaderDrawParameters.VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME; import static org.lwjgl.vulkan.KHRSpirv14.VK_KHR_SPIRV_1_4_EXTENSION_NAME; @@ -56,7 +48,7 @@ public class Vulkanite { private final ArbitarySyncPointCallback fencedCallback = new ArbitarySyncPointCallback(); private final AccelerationManager accelerationManager; - private final HashMap descriptorPools = new HashMap<>(); + private final HashMap> descriptorPools = new HashMap<>(); public Vulkanite() { ctx = createVulkanContext(); @@ -79,21 +71,19 @@ public void upload(List results) { accelerationManager.chunkBuilds(results); } - public VTypedDescriptorPool getPoolByLayout(VDescriptorSetLayout layout) { + public VRef getPoolByLayout(VRef layout) { + var key = layout.get(); synchronized (descriptorPools) { - if (!descriptorPools.containsKey(layout)) { - descriptorPools.put(layout, new VTypedDescriptorPool(ctx, layout, 0)); + if (!descriptorPools.containsKey(key)) { + descriptorPools.put(key, VDescriptorPool.create(ctx, layout, 0)); } - return descriptorPools.get(layout); + return descriptorPools.get(key).addRef(); } } public void removePoolByLayout(VDescriptorSetLayout layout) { synchronized (descriptorPools) { - if (descriptorPools.containsKey(layout)) { - descriptorPools.get(layout).free(); - descriptorPools.remove(layout); - } + descriptorPools.remove(layout); } } @@ -120,10 +110,7 @@ public void addSyncedCallback(Runnable callback) { public void destroy() { vkDeviceWaitIdle(ctx.device); - for (var pool : descriptorPools.values()) { - pool.free(); - } - accelerationManager.cleanup(); + descriptorPools.clear(); } private static VContext createVulkanContext() { diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/SharedImageViewTracker.java b/src/main/java/me/cortex/vulkanite/client/rendering/SharedImageViewTracker.java index 9435642..07fb9df 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/SharedImageViewTracker.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/SharedImageViewTracker.java @@ -2,6 +2,8 @@ import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; +import me.cortex.vulkanite.lib.memory.VGImage; import me.cortex.vulkanite.lib.memory.VImage; import me.cortex.vulkanite.lib.other.VImageView; @@ -9,44 +11,35 @@ public class SharedImageViewTracker { private final VContext ctx; - private final Supplier supplier; - private VImageView view; - public SharedImageViewTracker(VContext ctx, Supplier imageSupplier) { + private final Supplier> supplier; + private VRef view; + public SharedImageViewTracker(VContext ctx, Supplier> imageSupplier) { this.supplier = imageSupplier; this.ctx = ctx; } //NOTE: getting the image doesnt invalidate/check for a different image - public VImage getImage() { + public VRef getImage() { if (view != null) { - return view.image; + return view.get().image.addRef(); } return null; } - public VImageView getView() { + public VRef getView() { return getView(this.supplier); } - public VImageView getView(Supplier imageSupplier) { - VImage image = imageSupplier.get(); - if (this.view == null || this.view.image != image) { + public VRef getView(Supplier> imageSupplier) { + VRef image = imageSupplier.get(); + if (view == null || view.get().isDerivedFrom(image.get())) { //TODO: move this to like a fence free that you pass in via an arg - if (view != null) { - Vulkanite.INSTANCE.addSyncedCallback(view::free); - view = null; - } if (image != null) { - this.view = new VImageView(ctx, image); + view = VImageView.create(ctx, new VRef<>(image.get())); + } else { + view = null; } } - return view; - } - - public void free() { - if (view != null) { - Vulkanite.INSTANCE.addSyncedCallback(view::free); - view = null; - } + return view == null ? null : view.addRef(); } } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java index 991c719..78c46de 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java @@ -6,9 +6,11 @@ import me.cortex.vulkanite.compat.IVGImage; import me.cortex.vulkanite.compat.RaytracingShaderSet; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.cmd.VCmdBuff; import me.cortex.vulkanite.lib.cmd.VCommandPool; import me.cortex.vulkanite.lib.descriptors.DescriptorUpdateBuilder; +import me.cortex.vulkanite.lib.descriptors.VDescriptorSet; import me.cortex.vulkanite.lib.memory.VBuffer; import me.cortex.vulkanite.lib.memory.VGImage; import me.cortex.vulkanite.lib.memory.VImage; @@ -51,13 +53,12 @@ public class VulkanPipeline { private final VContext ctx; private final AccelerationManager accelerationManager; - private final VCommandPool singleUsePool; - private record RtPipeline(VRaytracePipeline pipeline, int commonSet, int geomSet, int customTexSet, int ssboSet) {} + private record RtPipeline(VRef pipeline, int commonSet, int geomSet, int customTexSet, int ssboSet) {} private ArrayList raytracePipelines = new ArrayList<>(); - private final VSampler sampler; - private final VSampler ctexSampler; + private final VRef sampler; + private final VRef ctexSampler; private final SharedImageViewTracker[] irisRenderTargetViews; private final SharedImageViewTracker[] customTextureViews; @@ -65,10 +66,10 @@ private record RtPipeline(VRaytracePipeline pipeline, int commonSet, int geomSet private final SharedImageViewTracker blockAtlasNormalView; private final SharedImageViewTracker blockAtlasSpecularView; - private final VImage placeholderSpecular; - private final VImageView placeholderSpecularView; - private final VImage placeholderNormals; - private final VImageView placeholderNormalsView; + private final VRef placeholderSpecular; + private final VRef placeholderSpecularView; + private final VRef placeholderNormals; + private final VRef placeholderNormalsView; private int fidx; @@ -76,17 +77,15 @@ private record RtPipeline(VRaytracePipeline pipeline, int commonSet, int geomSet private final boolean supportsEntities; - public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, RaytracingShaderSet[] passes, int[] ssboIds, VGImage[] customTextures) { + public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, RaytracingShaderSet[] passes, int[] ssboIds, List> customTextures) { this.ctx = ctx; this.accelerationManager = accelerationManager; - this.singleUsePool = ctx.cmd.createSingleUsePool(); - this.singleUsePool.setDebugUtilsObjectName("VulkanPipeline singleUsePool"); { - this.customTextureViews = new SharedImageViewTracker[customTextures.length]; - for (int i = 0; i < customTextures.length; i++) { + this.customTextureViews = new SharedImageViewTracker[customTextures.size()]; + for (int i = 0; i < customTextures.size(); i++) { int index = i; - this.customTextureViews[i] = new SharedImageViewTracker(ctx, () -> customTextures[index]); + this.customTextureViews[i] = new SharedImageViewTracker(ctx, () -> new VRef<>(customTextures.get(index).get())); } this.irisRenderTargetViews = new SharedImageViewTracker[maxIrisRenderTargets]; @@ -108,9 +107,9 @@ public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, Ray return ((IVGImage) holder.getSpecularTexture()).getVGImage(); }); this.placeholderSpecular = ctx.memory.createImage2D(4, 4, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - this.placeholderSpecularView = new VImageView(ctx, placeholderSpecular); + this.placeholderSpecularView = VImageView.create(ctx, placeholderSpecular); this.placeholderNormals = ctx.memory.createImage2D(4, 4, 1, VK_FORMAT_R32G32B32A32_SFLOAT, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - this.placeholderNormalsView = new VImageView(ctx, placeholderNormals); + this.placeholderNormalsView = VImageView.create(ctx, placeholderNormals); try (var stack = stackPush()) { var initZeros = stack.callocInt(4 * 4); @@ -120,23 +119,18 @@ public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, Ray } initNormals.rewind(); - var cmd = singleUsePool.createCommandBuffer(); - cmd.begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - cmd.encodeImageTransition(placeholderSpecular, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT, 1); - cmd.encodeImageTransition(placeholderNormals, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT, 1); - cmd.encodeImageUpload(ctx.memory, MemoryUtil.memAddress(initZeros), placeholderSpecular, initZeros.capacity() * 4, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - cmd.encodeImageUpload(ctx.memory, MemoryUtil.memAddress(initNormals), placeholderNormals, initNormals.capacity() * 4, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - cmd.encodeImageTransition(placeholderSpecular, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT, 1); - cmd.encodeImageTransition(placeholderNormals, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT, 1); - cmd.end(); - - ctx.cmd.submit(0, VkSubmitInfo.calloc(stack).sType$Default().pCommandBuffers(stack.pointers(cmd))); - - Vulkanite.INSTANCE.addSyncedCallback(cmd::enqueueFree); + ctx.cmd.executeWait(cmd -> { + cmd.encodeImageTransition(placeholderSpecular, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT, 1); + cmd.encodeImageTransition(placeholderNormals, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT, 1); + cmd.encodeImageUpload(ctx.memory, MemoryUtil.memAddress(initZeros), placeholderSpecular, initZeros.capacity() * 4L, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + cmd.encodeImageUpload(ctx.memory, MemoryUtil.memAddress(initNormals), placeholderNormals, initNormals.capacity() * 4L, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + cmd.encodeImageTransition(placeholderSpecular, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT, 1); + cmd.encodeImageTransition(placeholderNormals, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT, 1); + }); } } - this.sampler = new VSampler(ctx, a -> a.magFilter(VK_FILTER_NEAREST) + this.sampler = VSampler.create(ctx, a -> a.magFilter(VK_FILTER_NEAREST) .minFilter(VK_FILTER_NEAREST) .mipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST) .addressModeU(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE) @@ -147,7 +141,7 @@ public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, Ray .borderColor(VK_BORDER_COLOR_INT_OPAQUE_BLACK) .maxAnisotropy(1.0f)); - this.ctexSampler = new VSampler(ctx, a -> a.magFilter(VK_FILTER_LINEAR) + this.ctexSampler = VSampler.create(ctx, a -> a.magFilter(VK_FILTER_LINEAR) .minFilter(VK_FILTER_LINEAR) .mipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST) .addressModeU(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE) @@ -208,8 +202,8 @@ public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, Ray int customTexSet = -1; int ssboSet = -1; - for (int setIdx = 0; setIdx < pipe.reflection.getNSets(); setIdx++) { - var set = pipe.reflection.getSet(setIdx); + for (int setIdx = 0; setIdx < pipe.get().reflection.getNSets(); setIdx++) { + var set = pipe.get().reflection.getSet(setIdx); if (set.validate(commonSetExpected)) { commonSet = setIdx; } else if (set.validate(geomSetExpected)) { @@ -243,39 +237,42 @@ private void buildEntities() { accelerationManager.setEntityData(supportsEntities?capture.capture(CapturedRenderingState.INSTANCE.getTickDelta(), MinecraftClient.getInstance().world):null); } - public void renderPostShadows(List outImgs, Camera camera, ShaderStorageBuffer[] ssbos, MixinCelestialUniforms celestialUniforms) { - buildEntities(); + public void renderPostShadows(List> vgOutImgs, Camera camera, ShaderStorageBuffer[] ssbos, MixinCelestialUniforms celestialUniforms) { + ctx.cmd.newFrame(); +// System.gc(); + + buildEntities(); - this.singleUsePool.doReleases(); PBRTextureManager.notifyPBRTexturesChanged(); var in = ctx.sync.createSharedBinarySemaphore(); - var outImgsGlIds = outImgs.stream().mapToInt(i -> i.glId).toArray(); - var outImgsGlLayouts = outImgs.stream().mapToInt(i -> GL_LAYOUT_GENERAL_EXT).toArray(); - in.glSignal(new int[0], outImgsGlIds, outImgsGlLayouts); + var outImgsGlIds = vgOutImgs.stream().mapToInt(i -> i.get().glId).toArray(); + var outImgsGlLayouts = vgOutImgs.stream().mapToInt(i -> GL_LAYOUT_GENERAL_EXT).toArray(); + in.get().glSignal(new int[0], outImgsGlIds, outImgsGlLayouts); glFlush(); - var tlasLink = ctx.sync.createBinarySemaphore(); + var cmdRef = ctx.cmd.getSingleUsePool().createCommandBuffer(); + var cmd = cmdRef.get(); - var tlas = accelerationManager.buildTLAS(in, tlasLink); + var tlas = accelerationManager.buildTLAS(0, cmd); if (tlas == null) { glFinish(); - tlasLink.free(); - in.free(); return; } + var outImgs = vgOutImgs.stream().map(i -> new VRef(i.get())).toList(); + var out = ctx.sync.createSharedBinarySemaphore(); - VBuffer uboBuffer; + VRef uboBuffer; { uboBuffer = ctx.memory.createBuffer(1024, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 0, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); - uboBuffer.setDebugUtilsObjectName("VulkanPipeline UBO"); - long ptr = uboBuffer.map(); + uboBuffer.get().setDebugUtilsObjectName("VulkanPipeline UBO"); + long ptr = uboBuffer.get().map(); MemoryUtil.memSet(ptr, 0, 1024); { ByteBuffer bb = MemoryUtil.memByteBuffer(ptr, 1024); @@ -302,8 +299,8 @@ public void renderPostShadows(List outImgs, Camera camera, ShaderStorag bb.putInt(Float.BYTES * 41, flags); bb.rewind(); } - uboBuffer.unmap(); - uboBuffer.flush(); + uboBuffer.get().unmap(); + uboBuffer.get().flush(); // Call getView() on shared image view trackers to ensure they are created blockAtlasView.getView(); @@ -313,10 +310,6 @@ public void renderPostShadows(List outImgs, Camera camera, ShaderStorag v.getView(); } - //TODO: dont use a single use pool for commands like this... - var cmd = singleUsePool.createCommandBuffer(); - cmd.begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - { // Put barriers on images & transition to the optimal layout // These layouts also need to match the descriptor sets @@ -337,14 +330,17 @@ public void renderPostShadows(List outImgs, Camera camera, ShaderStorag for (var record : raytracePipelines) { var pipeline = record.pipeline; - pipeline.bind(cmd); - var layouts = pipeline.reflection.getLayouts(); // Should be cached already - var sets = new long[layouts.size()]; + cmd.bindRT(pipeline); + var layouts = pipeline.get().reflection.getLayouts(); // Should be cached already + var sets = new ArrayList>(layouts.size()); + for (int i = 0; i < layouts.size(); i++) { + sets.add(null); // Well, LOL, can't use Arrays.toList because it's generic + } if (record.commonSet != -1) { - var commonSet = Vulkanite.INSTANCE.getPoolByLayout(layouts.get(record.commonSet)).allocateSet(); + var commonSet = Vulkanite.INSTANCE.getPoolByLayout(layouts.get(record.commonSet)).get().allocateSet(); - var updater = new DescriptorUpdateBuilder(ctx, pipeline.reflection.getSet(record.commonSet)) - .set(commonSet.set) + var updater = new DescriptorUpdateBuilder(ctx, pipeline.get().reflection.getSet(record.commonSet)) + .set(commonSet) .uniform(0, uboBuffer) .acceleration(1, tlas) .imageSampler(3, blockAtlasView.getView(), sampler) @@ -356,48 +352,45 @@ public void renderPostShadows(List outImgs, Camera camera, ShaderStorag blockAtlasSpecularView.getView() != null ? blockAtlasSpecularView.getView() : placeholderSpecularView, sampler); - List outImgViewList = new ArrayList<>(outImgs.size()); + List> outImgViewList = new ArrayList<>(outImgs.size()); for (int i = 0; i < outImgs.size(); i++) { int index = i; - outImgViewList.add(irisRenderTargetViews[i].getView(() -> outImgs.get(index))); + outImgViewList.add(irisRenderTargetViews[i].getView(() -> vgOutImgs.get(index))); } updater.imageStore(6, 0, outImgViewList); updater.apply(); - sets[record.commonSet] = commonSet.set; - cmd.addTransientResource(commonSet); + sets.set(record.commonSet, commonSet); } if (record.geomSet != -1) { - sets[record.geomSet] = accelerationManager.getGeometrySet(); + sets.set(record.geomSet, accelerationManager.getGeometrySet()); } if (record.customTexSet != -1) { - var ctexSet = Vulkanite.INSTANCE.getPoolByLayout(layouts.get(record.customTexSet)).allocateSet(); + var ctexSet = Vulkanite.INSTANCE.getPoolByLayout(layouts.get(record.customTexSet)).get().allocateSet(); - var updater = new DescriptorUpdateBuilder(ctx, pipeline.reflection.getSet(record.customTexSet)) - .set(ctexSet.set); + var updater = new DescriptorUpdateBuilder(ctx, pipeline.get().reflection.getSet(record.customTexSet)) + .set(ctexSet); for (int i = 0; i < customTextureViews.length; i++) { updater.imageSampler(i, customTextureViews[i].getView(), ctexSampler); } updater.apply(); - sets[record.customTexSet] = ctexSet.set; - cmd.addTransientResource(ctexSet); + sets.set(record.customTexSet, ctexSet); } if (record.ssboSet != -1) { - var ssboSet = Vulkanite.INSTANCE.getPoolByLayout(layouts.get(record.ssboSet)).allocateSet(); + var ssboSet = Vulkanite.INSTANCE.getPoolByLayout(layouts.get(record.ssboSet)).get().allocateSet(); - var updater = new DescriptorUpdateBuilder(ctx, pipeline.reflection.getSet(record.ssboSet)) - .set(ssboSet.set); + var updater = new DescriptorUpdateBuilder(ctx, pipeline.get().reflection.getSet(record.ssboSet)) + .set(ssboSet); for (ShaderStorageBuffer ssbo : ssbos) { - updater.buffer(ssbo.getIndex(), ((IVGBuffer) ssbo).getBuffer()); + updater.buffer(ssbo.getIndex(), new VRef<>(((IVGBuffer) ssbo).getBuffer().get())); } updater.apply(); - sets[record.ssboSet] = ssboSet.set; - cmd.addTransientResource(ssboSet); + sets.set(record.ssboSet, ssboSet); } - pipeline.bindDSet(cmd, sets); - pipeline.trace(cmd, outImgs.get(0).width, outImgs.get(0).height, 1); + cmd.bindDSet(sets); + cmd.traceRays(outImgs.get(0).get().width, outImgs.get(0).get().height, 1); // Barrier on the output images for (var img : outImgs) { @@ -419,27 +412,10 @@ public void renderPostShadows(List outImgs, Camera camera, ShaderStorag } } - cmd.end(); - var fence = ctx.sync.createFence(); - ctx.cmd.submit(0, new VCmdBuff[]{cmd}, new VSemaphore[]{tlasLink}, new int[]{VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR}, new VSemaphore[]{out}, fence); - - - var semCapture = previousSemaphore; - previousSemaphore = out; - ctx.sync.addCallback(fence, ()->{ - tlasLink.free(); - in.free(); - cmd.enqueueFree(); - fence.free(); - - uboBuffer.free(); - if (semCapture != null) { - semCapture.free(); - } - }); + ctx.cmd.submit(0, cmdRef, Arrays.asList(new VRef<>(in.get())), new int[]{VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT}, Arrays.asList(new VRef<>(out.get())), null); } - out.glWait(new int[0], outImgsGlIds, outImgsGlLayouts); + out.get().glWait(new int[0], outImgsGlIds, outImgsGlLayouts); glFlush(); fidx++; @@ -449,53 +425,6 @@ public void renderPostShadows(List outImgs, Camera camera, ShaderStorag public void destory() { vkDeviceWaitIdle(ctx.device); - - // Check pending fences first - // Then destroy the cmd pool (which destroys linked transient resources) - ctx.sync.checkFences(); - if (singleUsePool != null) { - singleUsePool.doReleases(); - singleUsePool.free(); - } - if (previousSemaphore != null) { - previousSemaphore.free(); - } - // Finally destroy the pipelines - // (Which destroys the descriptor set layouts & releases the VTypedDescriptorPool) - for (var pass : raytracePipelines) { - if (pass != null) { - pass.pipeline.free(); - } - } - - for (SharedImageViewTracker customTexView : customTextureViews) { - if (customTexView != null) - customTexView.free(); - } - - for (SharedImageViewTracker irisRenderTargetView : irisRenderTargetViews) { - if (irisRenderTargetView != null) - irisRenderTargetView.free(); - } - - if (blockAtlasView != null) - blockAtlasView.free(); - if (blockAtlasNormalView != null) - blockAtlasNormalView.free(); - if (blockAtlasSpecularView != null) - blockAtlasSpecularView.free(); - if (placeholderNormalsView != null) - placeholderNormalsView.free(); - if (placeholderNormals != null) - placeholderNormals.free(); - if (placeholderSpecularView != null) - placeholderSpecularView.free(); - if (placeholderSpecular != null) - placeholderSpecular.free(); - if (sampler != null) - sampler.free(); - if (ctexSampler != null) - ctexSampler.free(); } diff --git a/src/main/java/me/cortex/vulkanite/compat/IRenderTargetVkGetter.java b/src/main/java/me/cortex/vulkanite/compat/IRenderTargetVkGetter.java index 7fce060..9b779cb 100644 --- a/src/main/java/me/cortex/vulkanite/compat/IRenderTargetVkGetter.java +++ b/src/main/java/me/cortex/vulkanite/compat/IRenderTargetVkGetter.java @@ -1,8 +1,9 @@ package me.cortex.vulkanite.compat; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VGImage; public interface IRenderTargetVkGetter { - VGImage getMain(); - VGImage getAlt(); + VRef getMain(); + VRef getAlt(); } diff --git a/src/main/java/me/cortex/vulkanite/compat/IVGBuffer.java b/src/main/java/me/cortex/vulkanite/compat/IVGBuffer.java index a9c6293..cd7e490 100644 --- a/src/main/java/me/cortex/vulkanite/compat/IVGBuffer.java +++ b/src/main/java/me/cortex/vulkanite/compat/IVGBuffer.java @@ -1,8 +1,9 @@ package me.cortex.vulkanite.compat; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VGBuffer; public interface IVGBuffer { - VGBuffer getBuffer(); - void setBuffer(VGBuffer buffer); + VRef getBuffer(); + void setBuffer(VRef buffer); } diff --git a/src/main/java/me/cortex/vulkanite/compat/IVGImage.java b/src/main/java/me/cortex/vulkanite/compat/IVGImage.java index 00204ce..6487765 100644 --- a/src/main/java/me/cortex/vulkanite/compat/IVGImage.java +++ b/src/main/java/me/cortex/vulkanite/compat/IVGImage.java @@ -1,8 +1,9 @@ package me.cortex.vulkanite.compat; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VGImage; public interface IVGImage { - VGImage getVGImage(); - void setVGImage(VGImage image); + VRef getVGImage(); + void setVGImage(VRef image); } diff --git a/src/main/java/me/cortex/vulkanite/compat/RaytracingShaderSet.java b/src/main/java/me/cortex/vulkanite/compat/RaytracingShaderSet.java index e808b64..e6190b0 100644 --- a/src/main/java/me/cortex/vulkanite/compat/RaytracingShaderSet.java +++ b/src/main/java/me/cortex/vulkanite/compat/RaytracingShaderSet.java @@ -18,20 +18,14 @@ private record RayHit(ShaderModule close, ShaderModule any, ShaderModule interse private final ShaderModule[] raymiss; private final RayHit[] rayhits; - private final VShader[] allShader; - public RaytracingShaderSet(VContext ctx, RaytracingShaderSource source) { - List shaderList = new ArrayList<>(); - - VShader shader = VShader.compileLoad(ctx, source.raygen, VK_SHADER_STAGE_RAYGEN_BIT_KHR); - shaderList.add(shader); - this.raygen = shader.named(); + var shader = VShader.compileLoad(ctx, source.raygen, VK_SHADER_STAGE_RAYGEN_BIT_KHR); + this.raygen = shader.get().named(); this.raymiss = new ShaderModule[source.raymiss.length]; for (int i = 0; i < raymiss.length; i++) { shader = VShader.compileLoad(ctx, source.raymiss[i], VK_SHADER_STAGE_MISS_BIT_KHR); - shaderList.add(shader); - this.raymiss[i] = shader.named(); + this.raymiss[i] = shader.get().named(); } this.rayhits = new RayHit[source.rayhit.length]; @@ -41,27 +35,23 @@ public RaytracingShaderSet(VContext ctx, RaytracingShaderSource source) { ShaderModule close = null; if (hit.close() != null) { shader = VShader.compileLoad(ctx, hit.close(), VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR); - shaderList.add(shader); - close = shader.named(); + close = shader.get().named(); } ShaderModule any = null; if (hit.any() != null) { shader = VShader.compileLoad(ctx, hit.any(), VK_SHADER_STAGE_ANY_HIT_BIT_KHR); - shaderList.add(shader); - any = shader.named(); + any = shader.get().named(); } ShaderModule intersection = null; if (hit.intersection() != null) { shader = VShader.compileLoad(ctx, hit.intersection(), VK_SHADER_STAGE_INTERSECTION_BIT_KHR); - shaderList.add(shader); - intersection = shader.named(); + intersection = shader.get().named(); } this.rayhits[i] = new RayHit(close, any, intersection); } - this.allShader = shaderList.toArray(new VShader[0]); } public void apply(RaytracePipelineBuilder builder) { @@ -77,10 +67,4 @@ public void apply(RaytracePipelineBuilder builder) { public int getRayHitCount() { return rayhits.length; } - - public void delete() { - for (var shader : allShader) { - shader.free(); - } - } } diff --git a/src/main/java/me/cortex/vulkanite/lib/base/TrackedResourceObject.java b/src/main/java/me/cortex/vulkanite/lib/base/TrackedResourceObject.java deleted file mode 100644 index 25e6816..0000000 --- a/src/main/java/me/cortex/vulkanite/lib/base/TrackedResourceObject.java +++ /dev/null @@ -1,40 +0,0 @@ -package me.cortex.vulkanite.lib.base; - -import me.cortex.vulkanite.client.Vulkanite; - -import java.lang.ref.Cleaner; - -public abstract class TrackedResourceObject { - - private final Ref ref; - public TrackedResourceObject() { - this.ref = register(this); - } - - protected void free0() { - ref.freedRef[0] = true; - ref.cleanable.clean(); - } - - public abstract void free(); - - public boolean isFreed() { - return ref.freedRef[0]; - } - - private record Ref(Cleaner.Cleanable cleanable, boolean[] freedRef) {} - - private static final Cleaner cleaner = Cleaner.create(); - public static Ref register(Object obj) { - String clazz = obj.getClass().getName(); - Throwable trace = new Throwable(); - boolean[] freed = new boolean[1]; - var clean = cleaner.register(obj, ()->{ - if (!freed[0]) { - System.err.println("Object named: "+ clazz+" was not freed, location at: "); - trace.printStackTrace(); - } - }); - return new Ref(clean, freed); - } -} diff --git a/src/main/java/me/cortex/vulkanite/lib/base/VObject.java b/src/main/java/me/cortex/vulkanite/lib/base/VObject.java new file mode 100644 index 0000000..e4cf033 --- /dev/null +++ b/src/main/java/me/cortex/vulkanite/lib/base/VObject.java @@ -0,0 +1,18 @@ +package me.cortex.vulkanite.lib.base; + +import java.util.concurrent.atomic.AtomicLong; + +public abstract class VObject { + protected abstract void free(); + + private final AtomicLong refCount = new AtomicLong(0); + protected void incRef() { + refCount.incrementAndGet(); + } + + protected void decRef() { + if (refCount.decrementAndGet() == 0) { + free(); + } + } +} diff --git a/src/main/java/me/cortex/vulkanite/lib/base/VRef.java b/src/main/java/me/cortex/vulkanite/lib/base/VRef.java new file mode 100644 index 0000000..95b0e22 --- /dev/null +++ b/src/main/java/me/cortex/vulkanite/lib/base/VRef.java @@ -0,0 +1,44 @@ +package me.cortex.vulkanite.lib.base; + +import org.jetbrains.annotations.NotNull; + +import java.lang.ref.Cleaner; + +public class VRef { + private static final Cleaner cleaner = Cleaner.create(); + + private final T ref; + + static class State implements Runnable { + private final VObject ref; + + State(VObject ref) { + this.ref = ref; + } + + @Override + public void run() { + ref.decRef(); + } + } + + public VRef(T ref) { + ref.incRef(); + this.ref = ref; + cleaner.register(this, new State(ref)); + } + + public T get() { + return ref; + } + + @NotNull + public VRef addRef() { + return new VRef<>(ref); + } + + @NotNull + public VRef addRefGeneric() { + return new VRef<>(ref); + } +} diff --git a/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java b/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java index 7f991aa..f931478 100644 --- a/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java @@ -1,113 +1,264 @@ package me.cortex.vulkanite.lib.cmd; -import com.mojang.blaze3d.systems.RenderSystem; +import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import com.mojang.blaze3d.systems.RenderSystem; import io.netty.util.internal.shaded.org.jctools.queues.MessagePassingQueue.Consumer; -import me.cortex.vulkanite.client.Vulkanite; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.other.sync.VFence; import me.cortex.vulkanite.lib.other.sync.VSemaphore; -import org.lwjgl.vulkan.VkCommandBufferBeginInfo; -import org.lwjgl.vulkan.VkDevice; -import org.lwjgl.vulkan.VkQueue; -import org.lwjgl.vulkan.VkSubmitInfo; +import org.lwjgl.vulkan.*; -import java.lang.management.ThreadInfo; import java.nio.LongBuffer; -import java.util.HashMap; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; +import static org.lwjgl.vulkan.VK12.vkWaitSemaphores; //Manages multiple command queues and fence synchronizations public class CommandManager { private final VkDevice device; - private final VkQueue[] queues; - - private final ThreadLocal threadLocalPool = - new ThreadLocal() { - @Override protected VCommandPool initialValue() { - var pool = createSingleUsePool(); - pool.setDebugUtilsObjectName("Thread-local single use pool"); - return pool; - } - }; + private final Queue[] queues; + private final ThreadLocal> threadLocalPool = + new ThreadLocal<>() { + @Override + protected VRef initialValue() { + var pool = createSingleUsePool(); + pool.get().setDebugUtilsObjectName("Thread-local single use pool"); + return pool; + } + }; + + private static final int[] waitAll = {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT}; public CommandManager(VkDevice device, int queues) { this.device = device; - this.queues = new VkQueue[queues]; - try (var stack = stackPush()) { - var pQ = stack.pointers(0); - for (int i = 0; i < queues; i++) { - vkGetDeviceQueue(device, 0, i, pQ); - System.out.println("Queue "+i+" has address " + Long.toHexString(pQ.get(0))); - this.queues[i] = new VkQueue(pQ.get(0), device); - } + this.queues = new Queue[queues]; + for (int i = 0; i < queues; i++) { + this.queues[i] = new Queue(i, device); } } - public VCommandPool createSingleUsePool() { + public VRef createSingleUsePool() { return createPool(VK_COMMAND_POOL_CREATE_TRANSIENT_BIT); } - public VCommandPool createPool(int flags) { - return new VCommandPool(device, flags); + public VRef createPool(int flags) { + return new VRef<>(new VCommandPool(device, flags)); } public VCommandPool getSingleUsePool() { - return threadLocalPool.get(); + return threadLocalPool.get().get(); } - public void submit(int queueId, VkSubmitInfo submit) { - try (var stack = stackPush()) { - vkQueueSubmit(queues[queueId], submit, 0); - } + public void submitOnceAndWait(int queueId, final VRef cmdBuff) { + long exec = this.submit(queueId, cmdBuff); + this.hostWaitForExecution(queueId, exec); + } + + public void executeWait(Consumer cmdbuf) { + var cmd = getSingleUsePool().createCommandBuffer(); + cmdbuf.accept(cmd.get()); + submitOnceAndWait(0, cmd); + } + + /** + * Enqueues a wait for a timeline value on a queue + * @param waitQueueId The queue that will wait + * @param executionQueueId The queue whose timeline value will be waited for + * @param execution The timeline value to wait for + */ + public void queueWaitForExeuction(int waitQueueId, int executionQueueId, long execution) { + queues[waitQueueId].waitForExecution(executionQueueId, execution); } - public void submitOnceAndWait(int queueId, VCmdBuff cmdBuff) { + /** + * Wait on the host for a timeline value on a queue + * @param waitQueueId The queue whose timeline value will be waited for + * @param execution The timeline value to wait for + */ + public void hostWaitForExecution(int waitQueueId, long execution) { + var waitQueue = queues[waitQueueId]; + try (var stack = stackPush()) { - var submit = VkSubmitInfo.calloc(stack).sType$Default() - .pCommandBuffers(stack.pointers(cmdBuff)) - .pWaitSemaphores(stack.longs()) - .pWaitDstStageMask(stack.ints()) - .pSignalSemaphores(stack.longs()); - vkQueueSubmit(queues[queueId], submit, 0); - vkQueueWaitIdle(queues[queueId]); - cmdBuff.freeInternal(); + VkSemaphoreWaitInfo waitInfo = VkSemaphoreWaitInfo.calloc(stack) + .sType$Default() + .pSemaphores(stack.longs(waitQueue.timelineSema.get().address())) + .semaphoreCount(1) + .pValues(stack.longs(execution)); + + _CHECK_(vkWaitSemaphores(device, waitInfo, -1)); + } + + synchronized (queues[waitQueueId]) { + waitQueue.completedTimestamp = Long.max(waitQueue.completedTimestamp, execution); } + waitQueue.collect(); } - public void executeWait(Consumer cmdbuf) { - var cmd = getSingleUsePool().createCommandBuffer(); - cmd.begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - cmdbuf.accept(cmd); - cmd.end(); - submitOnceAndWait(0, cmd); + public long submit(int queueId, final VRef cmdBuff) { + return submit(queueId, cmdBuff, null, waitAll, null, null); } - //TODO: if its a single use command buffer, automatically add the required fences and stuff to free the command buffer once its done - public void submit(int queueId, VCmdBuff[] cmdBuffs, VSemaphore[] waits, int[] waitStages, VSemaphore[] triggers, VFence fence) { + public long submit(int queueId, final VRef cmdBuff, List> waits, int[] waitStages, List> triggers, VFence fence) { if (queueId == 0) { RenderSystem.assertOnRenderThread(); } + return queues[queueId].submit(cmdBuff, queues, waits, waitStages, triggers, fence); + } - try (var stack = stackPush()) { - LongBuffer waitSemaphores = stack.mallocLong(waits.length); - LongBuffer signalSemaphores = stack.mallocLong(triggers.length); - for (var wait : waits) {waitSemaphores.put(wait.address());} - for (var trigger : triggers) {signalSemaphores.put(trigger.address());} - waitSemaphores.rewind(); - signalSemaphores.rewind(); - var submit = VkSubmitInfo.calloc(stack).sType$Default() - .pCommandBuffers(stack.pointers(cmdBuffs)) - .pWaitSemaphores(waitSemaphores) - .waitSemaphoreCount(waits.length) - .pWaitDstStageMask(stack.ints(waitStages)) - .pSignalSemaphores(signalSemaphores); - vkQueueSubmit(queues[queueId], submit, fence==null?0:fence.address()); + public void waitQueueIdle(int queue) { + queues[queue].waitIdle(); + queues[queue].collect(); + } + + public synchronized void newFrame() { + for (var queue : queues) { + queue.newFrame(); } } - public void waitQueueIdle(int queue) { - vkQueueWaitIdle(queues[queue]); + private static class Queue { + public final VkQueue queue; + public final Multimap waitingFor = Multimaps.synchronizedMultimap(HashMultimap.create()); + public final ConcurrentHashMap> submitted = new ConcurrentHashMap<>(); + public AtomicLong timeline = new AtomicLong(1); + public long completedTimestamp = 0; + public final VRef timelineSema; + public final Deque frameTimestamps = new ArrayDeque<>(3); + + public Queue(int queueId, VkDevice device) { + try (var stack = stackPush()) { + var pQ = stack.pointers(0); + vkGetDeviceQueue(device, 0, queueId, pQ); + + this.queue = new VkQueue(pQ.get(0), device); + + var timelineCreateInfo = VkSemaphoreTypeCreateInfo.calloc(stack) + .sType$Default() + .semaphoreType(VK12.VK_SEMAPHORE_TYPE_TIMELINE) + .initialValue(0); + + var semaphoreCreateInfo = VkSemaphoreCreateInfo.calloc(stack) + .sType$Default() + .pNext(timelineCreateInfo.address()); + + var pSemaphore = stack.longs(0); + vkCreateSemaphore(device, semaphoreCreateInfo, null, pSemaphore); + this.timelineSema = VSemaphore.create(device, pSemaphore.get(0)); + } + } + + public void newFrame() { + if (frameTimestamps.size() >= 3) { + long oldest = frameTimestamps.removeFirst(); + completedTimestamp = Long.max(completedTimestamp, oldest); + } + frameTimestamps.addLast(completedTimestamp); + + collect(); + } + + public void collect() { + synchronized (this) { + for (var key : submitted.keySet()) { + if (key <= completedTimestamp) { + submitted.remove(key); + } + } + } + } + + public void waitIdle() { + _CHECK_(vkQueueWaitIdle(queue)); + + synchronized (this) { + waitingFor.clear(); + submitted.clear(); + completedTimestamp = timeline.get() - 1; + } + } + + public void waitForExecution(int execQueue, long execution) { + synchronized (this) { + waitingFor.put(execQueue, execution); + } + } + + public long submit(final VRef cmdBuff, Queue[] queues, List> waits, int[] waitStages, List> triggers, VFence fence) { + long t = timeline.getAndIncrement(); + + synchronized (this) { + try (var stack = stackPush()) { + Collection> timelineWaitingEntries; + timelineWaitingEntries = waitingFor.entries(); + + int waitCount = (waits == null ? 0 : waits.size()) + timelineWaitingEntries.size(); + int triggerCount = (triggers == null ? 0 : triggers.size()) + 1; + + LongBuffer waitSemaphores = stack.mallocLong(waitCount); + LongBuffer signalSemaphores = stack.mallocLong(triggerCount); + LongBuffer waitTimelineValues = stack.mallocLong(waitCount); + LongBuffer signalTimelineValues = stack.mallocLong(triggerCount); + // Traditional binary semaphores + if (waits != null) { + for (var wait : waits) { + waitSemaphores.put(wait.get().address()); + waitTimelineValues.put(0); + cmdBuff.get().addSemaphoreRef(wait); + } + } + if (triggers != null) { + for (var trigger : triggers) { + signalSemaphores.put(trigger.get().address()); + signalTimelineValues.put(0); + cmdBuff.get().addSemaphoreRef(trigger); + } + } + // Timeline semaphores + for (var entry : timelineWaitingEntries) { + var sema = queues[entry.getKey()].timelineSema; + waitSemaphores.put(sema.get().address()); + waitTimelineValues.put(entry.getValue()); + cmdBuff.get().addSemaphoreRef(sema); + } + signalSemaphores.put(timelineSema.get().address()); + signalTimelineValues.put(t); + cmdBuff.get().addSemaphoreRef(timelineSema); + + waitSemaphores.rewind(); + signalSemaphores.rewind(); + waitTimelineValues.rewind(); + signalTimelineValues.rewind(); + + var timelineSubmitInfo = VkTimelineSemaphoreSubmitInfo.calloc(stack) + .sType$Default() + .pWaitSemaphoreValues(waitTimelineValues) + .waitSemaphoreValueCount(waitCount) + .pSignalSemaphoreValues(signalTimelineValues) + .signalSemaphoreValueCount(triggerCount); + + var submit = VkSubmitInfo.calloc(stack).sType$Default() + .pCommandBuffers(stack.pointers(cmdBuff.get().seal())) + .pWaitSemaphores(waitSemaphores) + .waitSemaphoreCount(waitCount) + .pWaitDstStageMask(stack.ints(waitStages)) + .pSignalSemaphores(signalSemaphores) + .pNext(timelineSubmitInfo.address()); + _CHECK_(vkQueueSubmit(queue, submit, fence == null ? 0 : fence.address())); + } + + waitingFor.clear(); + submitted.put(t, cmdBuff.addRef()); + } + + return t; + } } } diff --git a/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java b/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java index 61edea9..2b6ed3a 100644 --- a/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java +++ b/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java @@ -1,100 +1,181 @@ package me.cortex.vulkanite.lib.cmd; import me.cortex.vulkanite.client.Vulkanite; -import me.cortex.vulkanite.lib.base.TrackedResourceObject; +import me.cortex.vulkanite.lib.base.VObject; +import me.cortex.vulkanite.lib.base.VRef; +import me.cortex.vulkanite.lib.descriptors.VDescriptorSet; import me.cortex.vulkanite.lib.memory.MemoryManager; import me.cortex.vulkanite.lib.memory.VBuffer; import me.cortex.vulkanite.lib.memory.VImage; +import me.cortex.vulkanite.lib.other.VQueryPool; +import me.cortex.vulkanite.lib.other.sync.VGSemaphore; +import me.cortex.vulkanite.lib.other.sync.VSemaphore; +import me.cortex.vulkanite.lib.pipeline.VComputePipeline; +import me.cortex.vulkanite.lib.pipeline.VRaytracePipeline; import org.lwjgl.system.Pointer; -import org.lwjgl.vulkan.VK; -import org.lwjgl.vulkan.VkBufferCopy; -import org.lwjgl.vulkan.VkBufferImageCopy; -import org.lwjgl.vulkan.VkBufferMemoryBarrier; -import org.lwjgl.vulkan.VkCommandBuffer; -import org.lwjgl.vulkan.VkCommandBufferBeginInfo; -import org.lwjgl.vulkan.VkDevice; -import org.lwjgl.vulkan.VkImageMemoryBarrier; -import org.lwjgl.vulkan.VkMemoryBarrier; +import org.lwjgl.vulkan.*; import org.lwjgl.system.MemoryUtil; import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; import static org.lwjgl.system.MemoryStack.stackPush; +import static org.lwjgl.vulkan.KHRRayTracingPipeline.*; +import static org.lwjgl.vulkan.KHRRayTracingPipeline.VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR; import static org.lwjgl.vulkan.VK10.*; -import static org.lwjgl.vulkan.KHRRayTracingPipeline.VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR; import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR; import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.LinkedList; +import java.util.*; //TODO: Track with TrackedResourceObject but need to be careful due to how the freeing works -public class VCmdBuff extends TrackedResourceObject implements Pointer { +public class VCmdBuff extends VObject { private final VCommandPool pool; - public final VkCommandBuffer buffer; + private VkCommandBuffer buffer; - private HashSet transientResources; + private final List> queryPoolRefs = new ArrayList<>(); + private final List> refs = new ArrayList<>(); - VCmdBuff(VCommandPool pool, VkCommandBuffer buff) { + public void addBufferRef(final VRef buffer) { + refs.add(buffer.addRefGeneric()); + } + public void addImageRef(final VRef image) { + refs.add(image.addRefGeneric()); + } + public void addSemaphoreRef(final VRef semaphore) { + refs.add(semaphore.addRefGeneric()); + } + public void addVGSemaphoreRef(final VRef semaphore) { + refs.add(semaphore.addRefGeneric()); + } + + protected VCmdBuff(VCommandPool pool, VkCommandBuffer buff, int flags) { this.pool = pool; this.buffer = buff; - this.transientResources = new HashSet<>(); + + try (var stack = stackPush()) { + vkBeginCommandBuffer(buffer, VkCommandBufferBeginInfo.calloc(stack).sType$Default().flags(flags)); + } } - //Enqueues the pool to be freed by the owning thread - public void enqueueFree() { - pool.free(this); + public final VkCommandBuffer buffer() { + return buffer; } - public void begin(int flags) { - try (var stack = stackPush()) { - vkBeginCommandBuffer(buffer, VkCommandBufferBeginInfo.calloc(stack).sType$Default().flags(flags)); + private VkCommandBuffer finalizedBuffer = null; + + public VkCommandBuffer seal() { + if (finalizedBuffer != null) { + return finalizedBuffer; + } + finalizedBuffer = buffer; + buffer = null; + vkEndCommandBuffer(finalizedBuffer); + return finalizedBuffer; + } + + private long currentPipelineLayout = -1; + private int currentShaderStageMask = 0; + private int currentPipelineBindPoint = -1; + + private VkStridedDeviceAddressRegionKHR gen, miss, hit, callable; + + public void bindCompute(final VRef pipeline) { + vkCmdBindPipeline(buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.get().pipeline()); + refs.add(new VRef<>(pipeline.get())); + currentPipelineLayout = pipeline.get().layout(); + currentShaderStageMask = VK_SHADER_STAGE_COMPUTE_BIT; + currentPipelineBindPoint = VK_PIPELINE_BIND_POINT_COMPUTE; + } + + public void bindRT(final VRef pipeline) { + vkCmdBindPipeline(buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.get().pipeline); + refs.add(new VRef<>(pipeline.get())); + currentPipelineLayout = pipeline.get().layout; + currentShaderStageMask = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR; + currentPipelineBindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR; + + gen = pipeline.get().gen; + miss = pipeline.get().miss; + hit = pipeline.get().hit; + callable = pipeline.get().callable; + } + + public void traceRays(int width, int height, int depth) { + vkCmdTraceRaysKHR(buffer, gen, miss, hit, callable, width, height, depth); + } + + public void bindDSet(VRef... sets) { + long[] vkSets = Arrays.stream(sets).mapToLong(s -> s.get().set).toArray(); + vkCmdBindDescriptorSets(buffer, currentPipelineBindPoint, currentPipelineLayout, 0, vkSets, null); + refs.addAll(Arrays.stream(sets).map(s -> new VRef(s.get())).toList()); + } + + public void bindDSet(List> sets) { + long[] vkSets = sets.stream().mapToLong(s -> s.get().set).toArray(); + vkCmdBindDescriptorSets(buffer, currentPipelineBindPoint, currentPipelineLayout, 0, vkSets, null); + refs.addAll(sets.stream().map(s -> new VRef(s.get())).toList()); + } + + public void pushConstants(int offset, int size, long dataPtr) { + nvkCmdPushConstants(buffer, currentPipelineLayout, VK_SHADER_STAGE_ALL, offset, size, dataPtr); + } + + public void pushConstants(int offset, long[] data) { + vkCmdPushConstants(buffer, currentPipelineLayout, VK_SHADER_STAGE_ALL, offset, data); + } + + public void dispatch(int x, int y, int z) { + if (currentShaderStageMask != VK_SHADER_STAGE_COMPUTE_BIT || currentPipelineLayout == -1) { + throw new IllegalStateException("No compute pipeline bound"); } + vkCmdDispatch(buffer, x, y, z); } - public void end() { - vkEndCommandBuffer(buffer); + public void resetQueryPool(final VRef queryPool, int first, int size) { + vkCmdResetQueryPool(buffer, queryPool.get().pool, first, size); + queryPoolRefs.add(queryPool.addRef()); } - public void encodeDataUpload(MemoryManager manager, long src, VBuffer dest, long destOffset, long size) { - VBuffer staging = manager.createBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + public void encodeDataUpload(MemoryManager manager, long src, final VRef dest, long destOffset, long size) { + VRef staging = manager.createBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 0, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); - staging.setDebugUtilsObjectName("Data Upload Host Staging"); - long ptr = staging.map(); + staging.get().setDebugUtilsObjectName("Data Upload Host Staging"); + long ptr = staging.get().map(); MemoryUtil.memCopy(src, ptr, size); - staging.unmap(); + staging.get().unmap(); try (var stack = stackPush()) { var copy = VkBufferCopy.calloc(1, stack); copy.get(0).srcOffset(0).dstOffset(destOffset).size(size); - vkCmdCopyBuffer(buffer, staging.buffer(), dest.buffer(), copy); + vkCmdCopyBuffer(buffer, staging.get().buffer(), dest.get().buffer(), copy); } - transientResources.add(staging); + addBufferRef(staging); + addBufferRef(dest); } - public void encodeImageUpload(MemoryManager manager, long src, VImage dest, long srcSize, int destLayout) { - VBuffer staging = manager.createBuffer(srcSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + public void encodeImageUpload(MemoryManager manager, long src, final VRef dest, long srcSize, int destLayout) { + VRef staging = manager.createBuffer(srcSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 0, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); - staging.setDebugUtilsObjectName("Image Upload Host Staging"); - long ptr = staging.map(); + staging.get().setDebugUtilsObjectName("Image Upload Host Staging"); + long ptr = staging.get().map(); MemoryUtil.memCopy(src, ptr, srcSize); - staging.unmap(); + staging.get().unmap(); try (var stack = stackPush()) { var copy = VkBufferImageCopy.calloc(1, stack); copy.get(0).bufferOffset(0).bufferImageHeight(0).bufferRowLength(0) .imageOffset(o -> o.set(0, 0, 0)) - .imageExtent(extent -> extent.set(dest.width, dest.height, dest.depth)) + .imageExtent(extent -> extent.set(dest.get().width, dest.get().height, dest.get().depth)) .imageSubresource(s -> s.aspectMask(VK_IMAGE_ASPECT_COLOR_BIT).baseArrayLayer(0).layerCount(1).mipLevel(0)); - vkCmdCopyBufferToImage(buffer, staging.buffer(), dest.image(), destLayout, copy); + vkCmdCopyBufferToImage(buffer, staging.get().buffer(), dest.get().image(), destLayout, copy); } - transientResources.add(staging); + addBufferRef(staging); + addImageRef(dest); } public void encodeMemoryBarrier() { @@ -107,10 +188,6 @@ public void encodeMemoryBarrier() { } } - public void addTransientResource(TrackedResourceObject resource) { - transientResources.add(resource); - } - public static int dstStageToAccess(int dstStage) { return switch (dstStage) { case VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT -> VK_ACCESS_INDIRECT_COMMAND_READ_BIT; @@ -139,19 +216,21 @@ public static int srcStageToAccess(int srcStage) { }; } - public void encodeBufferBarrier(VBuffer buffer, long offset, long size) { + public void encodeBufferBarrier(final VRef buffer, long offset, long size) { encodeBufferBarrier(buffer, offset, size, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); } - public void encodeBufferBarrier(VBuffer buffer, long offset, long size, int srcStage, int dstStage) { + public void encodeBufferBarrier(final VRef buffer, long offset, long size, int srcStage, int dstStage) { try (var stack = stackPush()) { var barrier = VkBufferMemoryBarrier.calloc(1, stack); barrier.get(0).sType$Default().srcAccessMask(srcStageToAccess(srcStage)) - .dstAccessMask(dstStageToAccess(dstStage)).buffer(buffer.buffer()) + .dstAccessMask(dstStageToAccess(dstStage)).buffer(buffer.get().buffer()) .offset(offset).size(size); vkCmdPipelineBarrier(this.buffer, srcStage, dstStage, 0, null, barrier, null); } + + addBufferRef(buffer); } public int srcLayoutToStage(int srcLayout) { @@ -186,10 +265,10 @@ public int dstLayoutToStage(int dstLayout) { }; } - public void encodeImageTransition(VImage image, int src, int dst, int aspectMask, int mipLevels) { + public void encodeImageTransition(VRef image, int src, int dst, int aspectMask, int mipLevels) { try (var stack = stackPush()) { var barrier = VkImageMemoryBarrier.calloc(1, stack); - barrier.get(0).sType$Default().oldLayout(src).newLayout(dst).image(image.image()) + barrier.get(0).sType$Default().oldLayout(src).newLayout(dst).image(image.get().image()) .subresourceRange().aspectMask(aspectMask).baseMipLevel(0).levelCount(mipLevels).baseArrayLayer(0) .layerCount(VK_REMAINING_ARRAY_LAYERS); @@ -201,23 +280,12 @@ public void encodeImageTransition(VImage image, int src, int dst, int aspectMask vkCmdPipelineBarrier(this.buffer, srcStage, dstStage, 0, null, null, barrier); } + addImageRef(image); } - @Override - public long address() { - return buffer.address(); - } - - @Override - public void free() { - throw new IllegalStateException(); - } - - void freeInternal() { - free0(); + protected void free() { vkFreeCommandBuffers(pool.device, pool.pool, buffer); - transientResources.forEach(TrackedResourceObject::free); - transientResources.clear(); + refs.clear(); } public void setDebugUtilsObjectName(String name) { diff --git a/src/main/java/me/cortex/vulkanite/lib/cmd/VCommandPool.java b/src/main/java/me/cortex/vulkanite/lib/cmd/VCommandPool.java index 9847c5b..974344a 100644 --- a/src/main/java/me/cortex/vulkanite/lib/cmd/VCommandPool.java +++ b/src/main/java/me/cortex/vulkanite/lib/cmd/VCommandPool.java @@ -1,7 +1,8 @@ package me.cortex.vulkanite.lib.cmd; import me.cortex.vulkanite.client.Vulkanite; -import me.cortex.vulkanite.lib.base.TrackedResourceObject; +import me.cortex.vulkanite.lib.base.VRef; +import me.cortex.vulkanite.lib.base.VObject; import org.lwjgl.PointerBuffer; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.VkCommandBuffer; @@ -10,13 +11,14 @@ import org.lwjgl.vulkan.VkDevice; import java.nio.LongBuffer; -import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.ArrayList; +import java.util.List; import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; -public class VCommandPool extends TrackedResourceObject { +public class VCommandPool extends VObject { final VkDevice device; public final long pool; public VCommandPool(VkDevice device, int flags) { @@ -36,15 +38,15 @@ public VCommandPool(VkDevice device, int family, int flags) { } } - public synchronized VCmdBuff createCommandBuffer() { - return createCommandBuffers(1)[0]; + public synchronized VRef createCommandBuffer() { + return createCommandBuffers(1).get(0); } - public synchronized VCmdBuff[] createCommandBuffers(int count) { - return createCommandBuffers(count, 0); + public synchronized List> createCommandBuffers(int count) { + return createCommandBuffers(count, 0, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); } - public synchronized VCmdBuff[] createCommandBuffers(int count, int level) { + public synchronized List> createCommandBuffers(int count, int level, int flags) { try (MemoryStack stack = MemoryStack.stackPush()){ PointerBuffer pCommandBuffer = stack.mallocPointer(count); _CHECK_(vkAllocateCommandBuffers(device, @@ -55,32 +57,16 @@ public synchronized VCmdBuff[] createCommandBuffers(int count, int level) { .level(level) .commandBufferCount(count), pCommandBuffer), "Failed to create command buffer"); - VCmdBuff[] buffers = new VCmdBuff[count]; + List> buffers = new ArrayList<>(); for (int i = 0; i < count; i++) { - buffers[i] = new VCmdBuff(this, new VkCommandBuffer(pCommandBuffer.get(i), device)); + buffers.add(new VRef<>(new VCmdBuff(this, new VkCommandBuffer(pCommandBuffer.get(i), device), flags))); } return buffers; } } - private final ConcurrentLinkedDeque toRelease = new ConcurrentLinkedDeque<>(); - void free(VCmdBuff cmdBuff) { - toRelease.add(cmdBuff); - } - - public void doReleases() { - while (!toRelease.isEmpty()) { - toRelease.poll().freeInternal(); - } - } - - public void releaseNow(VCmdBuff cmd) { - cmd.freeInternal(); - } - @Override public void free() { - free0(); vkDestroyCommandPool(device, pool, null); } diff --git a/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorSetLayoutBuilder.java b/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorSetLayoutBuilder.java index b2f4d6c..bffcb81 100644 --- a/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorSetLayoutBuilder.java +++ b/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorSetLayoutBuilder.java @@ -2,6 +2,7 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; import org.lwjgl.system.MemoryUtil; import org.lwjgl.vulkan.VkDescriptorSetLayoutBinding; import org.lwjgl.vulkan.VkDescriptorSetLayoutCreateInfo; @@ -45,7 +46,7 @@ public DescriptorSetLayoutBuilder(int flags){ this.flags = flags; } - public VDescriptorSetLayout build(VContext ctx) { + public VRef build(VContext ctx) { try (var stack = stackPush()) { var info = VkDescriptorSetLayoutCreateInfo.calloc(stack) .sType$Default() @@ -66,7 +67,7 @@ public VDescriptorSetLayout build(VContext ctx) { LongBuffer pBuffer = stack.mallocLong(1); _CHECK_(vkCreateDescriptorSetLayout(ctx.device, info, null, pBuffer)); - return new VDescriptorSetLayout(ctx, pBuffer.get(0), types.toIntArray()); + return VDescriptorSetLayout.create(ctx, pBuffer.get(0), types.toIntArray()); } } } diff --git a/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java b/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java index 3ac5194..f4e8f79 100644 --- a/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java +++ b/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java @@ -1,6 +1,7 @@ package me.cortex.vulkanite.lib.descriptors; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VAccelerationStructure; import me.cortex.vulkanite.lib.memory.VBuffer; import me.cortex.vulkanite.lib.other.VImageView; @@ -22,7 +23,7 @@ public class DescriptorUpdateBuilder { private final VContext ctx; private final MemoryStack stack; private final VkWriteDescriptorSet.Buffer updates; - private final VImageView placeholderImageView; + private final VRef placeholderImageView; private ArrayList bulkBufferInfos = new ArrayList<>(); private ArrayList bulkImageInfos = new ArrayList<>(); private ShaderReflection.Set refSet = null; @@ -31,7 +32,7 @@ public DescriptorUpdateBuilder(VContext ctx, int maxUpdates) { this(ctx, maxUpdates, null); } - public DescriptorUpdateBuilder(VContext ctx, int maxUpdates, VImageView placeholderImageView) { + public DescriptorUpdateBuilder(VContext ctx, int maxUpdates, final VRef placeholderImageView) { this.ctx = ctx; // this.stack = MemoryStack.stackPush(); int objSize = Integer.max( @@ -50,29 +51,32 @@ public DescriptorUpdateBuilder(VContext ctx, ShaderReflection.Set refSet) { this(ctx, refSet, null); } - public DescriptorUpdateBuilder(VContext ctx, ShaderReflection.Set refSet, VImageView placeholderImageView) { + public DescriptorUpdateBuilder(VContext ctx, ShaderReflection.Set refSet, final VRef placeholderImageView) { this(ctx, refSet.bindings().size(), placeholderImageView); this.refSet = refSet; } - private long viewOrPlaceholder(VImageView v) { + private long viewOrPlaceholder(VRef v) { if (v == null && placeholderImageView == null) return 0; - return v == null ? placeholderImageView.view : v.view; + return v == null ? placeholderImageView.get().view : v.get().view; } private long set; - public DescriptorUpdateBuilder set(long set) { - this.set = set; + private VRef setRef; + public DescriptorUpdateBuilder set(VRef set) { + this.set = set.get().set; + this.setRef = set.addRef(); return this; } - public DescriptorUpdateBuilder buffer(int binding, VBuffer buffer) { + public DescriptorUpdateBuilder buffer(int binding, final VRef buffer) { return buffer(binding, buffer, 0, VK_WHOLE_SIZE); } - public DescriptorUpdateBuilder buffer(int binding, VBuffer buffer, long offset, long range) { + public DescriptorUpdateBuilder buffer(int binding, final VRef buffer, long offset, long range) { if (refSet != null && refSet.getBindingAt(binding) == null) { return this; } + setRef.get().refs.put(binding, buffer.addRefGeneric()); updates.get() .sType$Default() .dstBinding(binding) @@ -81,21 +85,22 @@ public DescriptorUpdateBuilder buffer(int binding, VBuffer buffer, long offset, .descriptorCount(1) .pBufferInfo(VkDescriptorBufferInfo .calloc(1, stack) - .buffer(buffer.buffer()) + .buffer(buffer.get().buffer()) .offset(offset) .range(range)); return this; } - public DescriptorUpdateBuilder buffer(int binding, int dstArrayElement, List buffers) { + public DescriptorUpdateBuilder buffer(int binding, int dstArrayElement, final List> buffers) { if (refSet != null && refSet.getBindingAt(binding) == null) { return this; } var bufInfo = VkDescriptorBufferInfo.calloc(buffers.size()); for (int i = 0; i < buffers.size(); i++) { + setRef.get().refs.put(binding, buffers.get(i).addRefGeneric()); bufInfo.get(i) - .buffer(buffers.get(i).buffer()) + .buffer(buffers.get(i).get().buffer()) .offset(0) .range(VK_WHOLE_SIZE); } @@ -112,13 +117,14 @@ public DescriptorUpdateBuilder buffer(int binding, int dstArrayElement, List buffer) { return uniform(binding, buffer, 0, VK_WHOLE_SIZE); } - public DescriptorUpdateBuilder uniform(int binding, VBuffer buffer, long offset, long range) { + public DescriptorUpdateBuilder uniform(int binding, final VRef buffer, long offset, long range) { if (refSet != null && refSet.getBindingAt(binding) == null) { return this; } + setRef.get().refs.put(binding, buffer.addRefGeneric()); updates.get() .sType$Default() .dstBinding(binding) @@ -127,19 +133,20 @@ public DescriptorUpdateBuilder uniform(int binding, VBuffer buffer, long offset, .descriptorCount(1) .pBufferInfo(VkDescriptorBufferInfo .calloc(1, stack) - .buffer(buffer.buffer()) + .buffer(buffer.get().buffer()) .offset(offset) .range(range)); return this; } - public DescriptorUpdateBuilder acceleration(int binding, VAccelerationStructure... structures) { + public DescriptorUpdateBuilder acceleration(int binding, VRef... structures) { if (refSet != null && refSet.getBindingAt(binding) == null) { return this; } var buff = stack.mallocLong(structures.length); for (var structure : structures) { - buff.put(structure.structure); + setRef.get().refs.put(binding, structure.addRefGeneric()); + buff.put(structure.get().structure); } buff.rewind(); updates.get() @@ -154,12 +161,13 @@ public DescriptorUpdateBuilder acceleration(int binding, VAccelerationStructure. return this; } - public DescriptorUpdateBuilder imageStore(int binding, int dstArrayElement, List views) { + public DescriptorUpdateBuilder imageStore(int binding, int dstArrayElement, final List> views) { if (refSet != null && refSet.getBindingAt(binding) == null) { return this; } var imgInfo = VkDescriptorImageInfo.calloc(views.size()); for (int i = 0; i < views.size(); i++) { + setRef.get().refs.put(binding, views.get(i).addRefGeneric()); imgInfo.get(i) .imageLayout(VK_IMAGE_LAYOUT_GENERAL) .imageView(viewOrPlaceholder(views.get(i))); @@ -174,13 +182,14 @@ public DescriptorUpdateBuilder imageStore(int binding, int dstArrayElement, List bulkImageInfos.add(imgInfo); return this; } - public DescriptorUpdateBuilder imageStore(int binding, VImageView view) { + public DescriptorUpdateBuilder imageStore(int binding, final VRef view) { return imageStore(binding, VK_IMAGE_LAYOUT_GENERAL, view); } - public DescriptorUpdateBuilder imageStore(int binding, int layout, VImageView view) { + public DescriptorUpdateBuilder imageStore(int binding, int layout, final VRef view) { if (refSet != null && refSet.getBindingAt(binding) == null) { return this; } + setRef.get().refs.put(binding, view.addRefGeneric()); updates.get() .sType$Default() .dstBinding(binding) @@ -194,14 +203,15 @@ public DescriptorUpdateBuilder imageStore(int binding, int layout, VImageView vi return this; } - public DescriptorUpdateBuilder imageSampler(int binding, VImageView view, VSampler sampler) { + public DescriptorUpdateBuilder imageSampler(int binding, final VRef view, VRef sampler) { return imageSampler(binding, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, view, sampler); } - public DescriptorUpdateBuilder imageSampler(int binding, int layout, VImageView view, VSampler sampler) { + public DescriptorUpdateBuilder imageSampler(int binding, int layout, final VRef view, VRef sampler) { if (refSet != null && refSet.getBindingAt(binding) == null) { return this; } + setRef.get().refs.put(binding, view.addRefGeneric()); updates.get() .sType$Default() .dstBinding(binding) @@ -212,7 +222,7 @@ public DescriptorUpdateBuilder imageSampler(int binding, int layout, VImageView .calloc(1, stack) .imageLayout(layout) .imageView(viewOrPlaceholder(view)) - .sampler(sampler.sampler)); + .sampler(sampler.get().sampler)); return this; } diff --git a/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorPool.java b/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorPool.java index 9926f08..0f2b45c 100644 --- a/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorPool.java +++ b/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorPool.java @@ -1,102 +1,109 @@ package me.cortex.vulkanite.lib.descriptors; -import me.cortex.vulkanite.lib.base.TrackedResourceObject; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VObject; +import me.cortex.vulkanite.lib.base.VRef; import org.lwjgl.vulkan.VkDescriptorPoolCreateInfo; import org.lwjgl.vulkan.VkDescriptorPoolSize; import org.lwjgl.vulkan.VkDescriptorSetAllocateInfo; import org.lwjgl.vulkan.VkDescriptorSetVariableDescriptorCountAllocateInfo; import java.nio.LongBuffer; +import java.util.ArrayList; import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; -public class VDescriptorPool extends TrackedResourceObject { +public class VDescriptorPool extends VObject { private final VContext ctx; - private final long pool; + private final ArrayList pools = new ArrayList<>(); + private final ArrayList poolFreeSizes = new ArrayList<>(); + private final VRef layout; + private final int flags; - private final long[] sets; + private static final int nSetsPerPool = 16; + private final int countPerType; - public VDescriptorPool(VContext ctx, int flags, int numSets, int... types) { + private VDescriptorPool(VContext ctx, VRef layout, int flags, int countPerType) { this.ctx = ctx; - this.sets = new long[numSets]; + this.layout = layout.addRef(); + this.flags = flags; + this.countPerType = countPerType; + } - try (var stack = stackPush()) { - var sizes = VkDescriptorPoolSize.calloc(types.length, stack); - for (int i = 0; i < types.length; i++) { - sizes.get(i).type(types[i]).descriptorCount(numSets); - } - LongBuffer pPool = stack.mallocLong(1); - _CHECK_(vkCreateDescriptorPool(ctx.device, VkDescriptorPoolCreateInfo.calloc(stack) - .sType$Default() - .flags(flags) - .maxSets(numSets) - .pPoolSizes(sizes), null, pPool)); - pool = pPool.get(0); - } + public static VRef create(VContext ctx, VRef layout, int flags) { + return new VRef<>(new VDescriptorPool(ctx, layout, flags, 1)); } - public VDescriptorPool(VContext ctx, int flags, int numSets, int countPerType, int... types) { - this.ctx = ctx; - this.sets = new long[numSets]; + public static VRef create(VContext ctx, VRef layout, int flags, int countPerType) { + return new VRef<>(new VDescriptorPool(ctx, layout, flags, countPerType)); + } + private void createNewPool() { try (var stack = stackPush()) { - var sizes = VkDescriptorPoolSize.calloc(types.length, stack); - for (int i = 0; i < types.length; i++) { - sizes.get(i).type(types[i]).descriptorCount(numSets * countPerType); + var sizes = VkDescriptorPoolSize.calloc(layout.get().types.length, stack); + for (int i = 0; i < layout.get().types.length; i++) { + sizes.get(i).type(layout.get().types[i]).descriptorCount(nSetsPerPool * countPerType); } LongBuffer pPool = stack.mallocLong(1); _CHECK_(vkCreateDescriptorPool(ctx.device, VkDescriptorPoolCreateInfo.calloc(stack) .sType$Default() - .flags(flags) - .maxSets(numSets) + .flags(flags | VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT) + .maxSets(nSetsPerPool) .pPoolSizes(sizes), null, pPool)); - pool = pPool.get(0); + pools.add(pPool.get(0)); + poolFreeSizes.add(nSetsPerPool); } } - public void allocateSets(VDescriptorSetLayout layout, int... variableSizes) { + public VRef allocateSet(int variableSize) { + if (poolFreeSizes.isEmpty() || poolFreeSizes.get(pools.size() - 1) == 0) { + createNewPool(); + } + long pool = pools.get(pools.size() - 1); + long set; + poolFreeSizes.set(pools.size() - 1, poolFreeSizes.get(pools.size() - 1) - 1); try (var stack = stackPush()) { - var layouts = stack.mallocLong(sets.length); - for (int i = 0; i < sets.length; i++) { - layouts.put(layout.layout); - } - layouts.rewind(); - LongBuffer pDescriptorSets = stack.mallocLong(sets.length); + var pSet = stack.mallocLong(1); var allocInfo = VkDescriptorSetAllocateInfo.calloc(stack) - .sType$Default() - .descriptorPool(pool) - .pSetLayouts(layouts); - if (variableSizes != null) { - var descriptorCounts = stack.mallocInt(variableSizes.length); - for (int i = 0; i < variableSizes.length; i++) { - descriptorCounts.put(variableSizes[i]); - } - descriptorCounts.rewind(); - var variableCountInfo = VkDescriptorSetVariableDescriptorCountAllocateInfo.calloc(stack) .sType$Default() - .pDescriptorCounts(descriptorCounts); + .descriptorPool(pool) + .pSetLayouts(stack.longs(layout.get().layout)); + if (variableSize >= 0) { + var variableCountInfo = VkDescriptorSetVariableDescriptorCountAllocateInfo.calloc(stack) + .sType$Default() + .pDescriptorCounts(stack.ints(variableSize)); allocInfo.pNext(variableCountInfo.address()); } - _CHECK_(vkAllocateDescriptorSets(ctx.device, allocInfo, pDescriptorSets), - "Failed to allocate descriptor set"); - pDescriptorSets.get(sets); + _CHECK_(vkAllocateDescriptorSets(ctx.device, allocInfo, pSet)); + set = pSet.get(0); } + return new VRef<>(new VDescriptorSet(this, pool, set)); } - public void allocateSets(VDescriptorSetLayout layout) { - allocateSets(layout, null); + public VRef allocateSet() { + return allocateSet(-1); } - public long get(int idx) { - return sets[idx]; + public void freeSet(VDescriptorSet set) { + int index = pools.indexOf(set.poolHandle); + try (var stack = stackPush()) { + var pDescriptorSets = stack.mallocLong(1).put(0, set.set); + _CHECK_(vkFreeDescriptorSets(ctx.device, set.poolHandle, pDescriptorSets)); + } + poolFreeSizes.set(index, poolFreeSizes.get(index) + 1); + if (poolFreeSizes.get(index) == nSetsPerPool) { + vkDestroyDescriptorPool(ctx.device, set.poolHandle, null); + pools.remove(index); + poolFreeSizes.remove(index); + } } @Override - public void free() { - free0(); - vkDestroyDescriptorPool(ctx.device, pool, null); + protected void free() { + for (long pool : pools) { + vkDestroyDescriptorPool(ctx.device, pool, null); + } } } diff --git a/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSet.java b/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSet.java index 825afc7..de26443 100644 --- a/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSet.java +++ b/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSet.java @@ -1,21 +1,26 @@ package me.cortex.vulkanite.lib.descriptors; -import me.cortex.vulkanite.lib.base.TrackedResourceObject; +import me.cortex.vulkanite.lib.base.VObject; +import me.cortex.vulkanite.lib.base.VRef; -public class VDescriptorSet extends TrackedResourceObject { - private final VTypedDescriptorPool pool; +import java.util.HashMap; +import java.util.Map; + +public class VDescriptorSet extends VObject { + private final VDescriptorPool pool; public final long poolHandle; public final long set; - VDescriptorSet(VTypedDescriptorPool pool, long poolHandle, long set) { + public Map> refs = new HashMap<>(); + + protected VDescriptorSet(VDescriptorPool pool, long poolHandle, long set) { this.pool = pool; this.poolHandle = poolHandle; this.set = set; } @Override - public void free() { - free0(); + protected void free() { pool.freeSet(this); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSetLayout.java b/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSetLayout.java index 5ff63cd..55d21d0 100644 --- a/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSetLayout.java +++ b/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSetLayout.java @@ -1,8 +1,9 @@ package me.cortex.vulkanite.lib.descriptors; import me.cortex.vulkanite.client.Vulkanite; -import me.cortex.vulkanite.lib.base.TrackedResourceObject; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VObject; +import me.cortex.vulkanite.lib.base.VRef; import org.lwjgl.system.Pointer; import org.lwjgl.vulkan.VkDescriptorPoolCreateInfo; import org.lwjgl.vulkan.VkDescriptorPoolSize; @@ -15,26 +16,29 @@ import static org.lwjgl.vulkan.VK10.vkCreateDescriptorPool; import static org.lwjgl.vulkan.VK10.vkDestroyDescriptorSetLayout; -public final class VDescriptorSetLayout extends TrackedResourceObject implements Pointer { +public final class VDescriptorSetLayout extends VObject implements Pointer { private final VContext ctx; public final long layout; public final int[] types; - public VDescriptorSetLayout(VContext ctx, long layout, int[] types) { + private VDescriptorSetLayout(VContext ctx, long layout, int[] types) { this.ctx = ctx; this.layout = layout; this.types = types; } + public static VRef create(VContext ctx, long layout, int[] types) { + return new VRef<>(new VDescriptorSetLayout(ctx, layout, types)); + } + @Override public long address() { return layout; } @Override - public void free() { + protected void free() { Vulkanite.INSTANCE.removePoolByLayout(this); - free0(); vkDestroyDescriptorSetLayout(ctx.device, layout, null); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/descriptors/VTypedDescriptorPool.java b/src/main/java/me/cortex/vulkanite/lib/descriptors/VTypedDescriptorPool.java deleted file mode 100644 index c7113b4..0000000 --- a/src/main/java/me/cortex/vulkanite/lib/descriptors/VTypedDescriptorPool.java +++ /dev/null @@ -1,87 +0,0 @@ -package me.cortex.vulkanite.lib.descriptors; - -import me.cortex.vulkanite.lib.base.TrackedResourceObject; -import me.cortex.vulkanite.lib.base.VContext; -import org.lwjgl.vulkan.VkDescriptorPoolCreateInfo; -import org.lwjgl.vulkan.VkDescriptorPoolSize; -import org.lwjgl.vulkan.VkDescriptorSetAllocateInfo; - -import java.nio.LongBuffer; -import java.util.ArrayList; - -import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; -import static org.lwjgl.system.MemoryStack.stackPush; -import static org.lwjgl.vulkan.VK10.*; - -public class VTypedDescriptorPool extends TrackedResourceObject { - private final VContext ctx; - private final ArrayList pools = new ArrayList<>(); - private final ArrayList poolFreeSizes = new ArrayList<>(); - private final VDescriptorSetLayout layout; - private final int flags; - - private static final int nSetsPerPool = 16; - - public VTypedDescriptorPool(VContext ctx, VDescriptorSetLayout layout, int flags) { - this.ctx = ctx; - this.layout = layout; - this.flags = flags; - } - - private void createNewPool() { - try (var stack = stackPush()) { - var sizes = VkDescriptorPoolSize.calloc(layout.types.length, stack); - for (int i = 0; i < layout.types.length; i++) { - sizes.get(i).type(layout.types[i]).descriptorCount(nSetsPerPool); - } - LongBuffer pPool = stack.mallocLong(1); - _CHECK_(vkCreateDescriptorPool(ctx.device, VkDescriptorPoolCreateInfo.calloc(stack) - .sType$Default() - .flags(flags | VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT) - .maxSets(nSetsPerPool) - .pPoolSizes(sizes), null, pPool)); - pools.add(pPool.get(0)); - poolFreeSizes.add(nSetsPerPool); - } - } - - public VDescriptorSet allocateSet() { - if (poolFreeSizes.isEmpty() || poolFreeSizes.get(pools.size() - 1) == 0) { - createNewPool(); - } - long pool = pools.get(pools.size() - 1); - long set; - poolFreeSizes.set(pools.size() - 1, poolFreeSizes.get(pools.size() - 1) - 1); - try (var stack = stackPush()) { - var pSet = stack.mallocLong(1); - _CHECK_(vkAllocateDescriptorSets(ctx.device, VkDescriptorSetAllocateInfo.calloc(stack) - .sType$Default() - .descriptorPool(pool) - .pSetLayouts(stack.mallocLong(1).put(0, layout.layout)), pSet)); - set = pSet.get(0); - } - return new VDescriptorSet(this, pool, set); - } - - public void freeSet(VDescriptorSet set) { - int index = pools.indexOf(set.poolHandle); - try (var stack = stackPush()) { - var pDescriptorSets = stack.mallocLong(1).put(0, set.set); - _CHECK_(vkFreeDescriptorSets(ctx.device, set.poolHandle, pDescriptorSets)); - } - poolFreeSizes.set(index, poolFreeSizes.get(index) + 1); - if (poolFreeSizes.get(index) == nSetsPerPool) { - vkDestroyDescriptorPool(ctx.device, set.poolHandle, null); - pools.remove(index); - poolFreeSizes.remove(index); - } - } - - @Override - public void free() { - free0(); - for (long pool : pools) { - vkDestroyDescriptorPool(ctx.device, pool, null); - } - } -} diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java b/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java index 54be14d..ddc3764 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java @@ -6,6 +6,7 @@ import com.sun.jna.platform.win32.WinNT; import me.cortex.vulkanite.client.Vulkanite; +import me.cortex.vulkanite.lib.base.VRef; import org.lwjgl.PointerBuffer; import org.lwjgl.util.vma.VmaAllocationCreateInfo; import org.lwjgl.vulkan.*; @@ -154,7 +155,7 @@ public static void release(long memory) { } }; - public VGBuffer createSharedBuffer(long size, int usage, int properties) { + public VRef createSharedBuffer(long size, int usage, int properties) { try (var stack = stackPush()) { var bufferCreateInfo = VkBufferCreateInfo .calloc(stack) @@ -175,14 +176,14 @@ public VGBuffer createSharedBuffer(long size, int usage, int properties) { int glId = glCreateBuffers(); glNamedBufferStorageMemEXT(glId, size, memoryObject, alloc.ai.offset()); _CHECK_GL_ERROR_(); - return new VGBuffer(alloc, glId); + return VGBuffer.create(alloc, glId); } } - public VGImage createSharedImage(int width, int height, int mipLevels, int vkFormat, int glFormat, int usage, int properties) { + public VRef createSharedImage(int width, int height, int mipLevels, int vkFormat, int glFormat, int usage, int properties) { return createSharedImage(2, width, height, 1, mipLevels, vkFormat, glFormat, usage, properties); } - public VGImage createSharedImage(int dimensions, int width, int height, int depth, int mipLevels, int vkFormat, int glFormat, int usage, int properties) { + public VRef createSharedImage(int dimensions, int width, int height, int depth, int mipLevels, int vkFormat, int glFormat, int usage, int properties) { int vkImageType = VK_IMAGE_TYPE_2D; int glImageType = GL_TEXTURE_2D; @@ -247,15 +248,15 @@ public VGImage createSharedImage(int dimensions, int width, int height, int dept } _CHECK_GL_ERROR_(); - return new VGImage(alloc, width, height, depth, mipLevels, vkFormat, glFormat, glId); + return VGImage.create(alloc, width, height, depth, mipLevels, vkFormat, glFormat, glId); } } - public VBuffer createBuffer(long size, int usage, int properties) { + public VRef createBuffer(long size, int usage, int properties) { return createBuffer(size, usage, properties, 0L, 0); } - public VBuffer createBuffer(long size, int usage, int properties, long alignment, int vmaFlags) { + public VRef createBuffer(long size, int usage, int properties, long alignment, int vmaFlags) { try (var stack = stackPush()) { var alloc = allocator.alloc(0, VkBufferCreateInfo .calloc(stack) @@ -266,11 +267,11 @@ public VBuffer createBuffer(long size, int usage, int properties, long alignment .usage(VMA_MEMORY_USAGE_AUTO) .requiredFlags(properties), alignment); - return new VBuffer(alloc); + return VBuffer.create(alloc); } } - public VImage createImage2D(int width, int height, int mipLevels, int vkFormat, int usage, int properties) { + public VRef createImage2D(int width, int height, int mipLevels, int vkFormat, int usage, int properties) { try (var stack = stackPush()) { var alloc = allocator.alloc(0, VkImageCreateInfo .calloc(stack) @@ -287,11 +288,11 @@ public VImage createImage2D(int width, int height, int mipLevels, int vkFormat, VmaAllocationCreateInfo.calloc(stack) .usage(VMA_MEMORY_USAGE_AUTO) .requiredFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)); - return new VImage(alloc, width, height, 1, mipLevels, vkFormat); + return VImage.create(alloc, width, height, 1, mipLevels, vkFormat); } } - public VAccelerationStructure createAcceleration(long size, int alignment, int usage, int type) { + public VRef createAcceleration(long size, int alignment, int usage, int type) { var buffer = createBuffer(size, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | usage, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, alignment, 0); try (var stack = stackPush()) { LongBuffer pAccelerationStructure = stack.mallocLong(1); @@ -300,9 +301,9 @@ public VAccelerationStructure createAcceleration(long size, int alignment, int u .sType$Default() .type(type) .size(size) - .buffer(buffer.buffer()), null, pAccelerationStructure), + .buffer(buffer.get().buffer()), null, pAccelerationStructure), "Failed to create acceleration acceleration structure"); - return new VAccelerationStructure(device, pAccelerationStructure.get(0), buffer); + return VAccelerationStructure.create(device, pAccelerationStructure.get(0), buffer); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/VAccelerationStructure.java b/src/main/java/me/cortex/vulkanite/lib/memory/VAccelerationStructure.java index 1b71a36..170aa40 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/VAccelerationStructure.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/VAccelerationStructure.java @@ -1,25 +1,24 @@ package me.cortex.vulkanite.lib.memory; -import me.cortex.vulkanite.lib.base.TrackedResourceObject; +import me.cortex.vulkanite.lib.base.VObject; +import me.cortex.vulkanite.lib.base.VRef; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.VkAccelerationStructureDeviceAddressInfoKHR; import org.lwjgl.vulkan.VkDevice; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; import static org.lwjgl.vulkan.KHRAccelerationStructure.*; -public class VAccelerationStructure extends TrackedResourceObject { +public class VAccelerationStructure extends VObject { public final long structure; - public final VBuffer buffer; + @SuppressWarnings("FieldCanBeLocal") + private final VRef buffer; + public final long deviceAddress; private final VkDevice device; - VAccelerationStructure(VkDevice device, long structure, VBuffer buffer) { + protected VAccelerationStructure(VkDevice device, long structure, final VRef buffer) { this.device = device; - this.buffer = buffer; + this.buffer = buffer.addRef(); this.structure = structure; try (MemoryStack stack = MemoryStack.stackPush()){ deviceAddress = vkGetAccelerationStructureDeviceAddressKHR(device, @@ -30,9 +29,11 @@ public class VAccelerationStructure extends TrackedResourceObject { } } + public static VRef create(VkDevice device, long structure, VRef buffer) { + return new VRef<>(new VAccelerationStructure(device, structure, buffer)); + } + public void free() { - free0(); vkDestroyAccelerationStructureKHR(device, structure, null); - buffer.free(); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/VBuffer.java b/src/main/java/me/cortex/vulkanite/lib/memory/VBuffer.java index a144d49..a113a22 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/VBuffer.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/VBuffer.java @@ -1,24 +1,36 @@ package me.cortex.vulkanite.lib.memory; import me.cortex.vulkanite.client.Vulkanite; -import me.cortex.vulkanite.lib.base.TrackedResourceObject; +import me.cortex.vulkanite.lib.base.VObject; +import me.cortex.vulkanite.lib.base.VRef; +import org.lwjgl.vulkan.VkDeviceOrHostAddressConstKHR; import static org.lwjgl.vulkan.VK10.VK_OBJECT_TYPE_BUFFER; import static org.lwjgl.vulkan.VK10.VK_WHOLE_SIZE; -public class VBuffer extends TrackedResourceObject { +public class VBuffer extends VObject { private VmaAllocator.BufferAllocation allocation; + private final VkDeviceOrHostAddressConstKHR deviceAddressConst; - VBuffer(VmaAllocator.BufferAllocation allocation) { + public static VRef create(VmaAllocator.BufferAllocation allocation) { + return new VRef<>(new VBuffer(allocation)); + } + + protected VBuffer(VmaAllocator.BufferAllocation allocation) { this.allocation = allocation; + if (allocation.deviceAddress != -1) { + this.deviceAddressConst = VkDeviceOrHostAddressConstKHR.calloc() + .deviceAddress(allocation.deviceAddress); + } else { + this.deviceAddressConst = null; + } } public long buffer() { return allocation.buffer; } - public void free() { - free0(); + protected void free() { allocation.free(); allocation = null; } @@ -29,6 +41,12 @@ public long deviceAddress() { return allocation.deviceAddress; } + public VkDeviceOrHostAddressConstKHR deviceAddressConst() { + if (allocation.deviceAddress == -1) + throw new IllegalStateException(); + return deviceAddressConst; + } + public long map() { return allocation.map(); } diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/VGBuffer.java b/src/main/java/me/cortex/vulkanite/lib/memory/VGBuffer.java index d69a098..5c9ba87 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/VGBuffer.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/VGBuffer.java @@ -1,22 +1,33 @@ package me.cortex.vulkanite.lib.memory; +import me.cortex.vulkanite.client.Vulkanite; +import me.cortex.vulkanite.lib.base.VRef; + import static me.cortex.vulkanite.lib.other.VUtil._CHECK_GL_ERROR_; +import static org.lwjgl.opengl.GL11C.glDeleteTextures; import static org.lwjgl.opengl.GL15C.glDeleteBuffers; public class VGBuffer extends VBuffer { public final int glId; private final long vkMemory; - VGBuffer(VmaAllocator.BufferAllocation allocation, int glId) { + protected VGBuffer(VmaAllocator.BufferAllocation allocation, int glId) { super(allocation); this.glId = glId; this.vkMemory = allocation.ai.deviceMemory(); } + public static VRef create(VmaAllocator.BufferAllocation allocation, int glId) { + return new VRef<>(new VGBuffer(allocation, glId)); + } + @Override - public void free() { - glDeleteBuffers(glId); - _CHECK_GL_ERROR_(); - MemoryManager.ExternalMemoryTracker.release(this.vkMemory); + protected void free() { + int glId = this.glId; + Vulkanite.INSTANCE.addSyncedCallback(() -> { + glDeleteBuffers(glId); + _CHECK_GL_ERROR_(); + MemoryManager.ExternalMemoryTracker.release(this.vkMemory); + }); super.free(); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/VGImage.java b/src/main/java/me/cortex/vulkanite/lib/memory/VGImage.java index 7fd9e11..58a1769 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/VGImage.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/VGImage.java @@ -1,5 +1,8 @@ package me.cortex.vulkanite.lib.memory; +import me.cortex.vulkanite.client.Vulkanite; +import me.cortex.vulkanite.lib.base.VRef; + import static me.cortex.vulkanite.lib.other.VUtil._CHECK_GL_ERROR_; import static org.lwjgl.opengl.GL11C.glDeleteTextures; @@ -8,17 +11,24 @@ public class VGImage extends VImage { public final int glFormat; private final long vkMemory; - VGImage(VmaAllocator.ImageAllocation allocation, int width, int height, int depth, int mipLayers, int format, int glFormat, int glId) { + protected VGImage(VmaAllocator.ImageAllocation allocation, int width, int height, int depth, int mipLayers, int format, int glFormat, int glId) { super(allocation, width, height, depth, mipLayers, format); this.glId = glId; this.glFormat = glFormat; this.vkMemory = allocation.ai.deviceMemory(); } - public void free() { - glDeleteTextures(glId); - _CHECK_GL_ERROR_(); - MemoryManager.ExternalMemoryTracker.release(this.vkMemory); + public static VRef create(VmaAllocator.ImageAllocation allocation, int width, int height, int depth, int mipLayers, int format, int glFormat, int glId) { + return new VRef<>(new VGImage(allocation, width, height, depth, mipLayers, format, glFormat, glId)); + } + + protected void free() { + int glId = this.glId; + Vulkanite.INSTANCE.addSyncedCallback(() -> { + glDeleteTextures(glId); + _CHECK_GL_ERROR_(); + MemoryManager.ExternalMemoryTracker.release(this.vkMemory); + }); super.free(); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/VImage.java b/src/main/java/me/cortex/vulkanite/lib/memory/VImage.java index e83a7e7..09aa04b 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/VImage.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/VImage.java @@ -1,13 +1,15 @@ package me.cortex.vulkanite.lib.memory; import me.cortex.vulkanite.client.Vulkanite; +import me.cortex.vulkanite.lib.base.VObject; +import me.cortex.vulkanite.lib.base.VRef; import java.lang.ref.Cleaner; import static org.lwjgl.vulkan.VK10.VK_OBJECT_TYPE_BUFFER; import static org.lwjgl.vulkan.VK10.VK_OBJECT_TYPE_IMAGE; -public class VImage { +public class VImage extends VObject { protected VmaAllocator.ImageAllocation allocation; public final int width; public final int height; @@ -17,7 +19,7 @@ public class VImage { public final int dimensions; - VImage(VmaAllocator.ImageAllocation allocation, int width, int height, int depth, int mipLayers, int format) { + protected VImage(VmaAllocator.ImageAllocation allocation, int width, int height, int depth, int mipLayers, int format) { this.allocation = allocation; this.width = width; this.height = height; @@ -37,7 +39,11 @@ else if(height != 1 && depth == 1) { this.dimensions = dimensions; } - public void free() { + public static VRef create(VmaAllocator.ImageAllocation allocation, int width, int height, int depth, int mipLayers, int format) { + return new VRef<>(new VImage(allocation, width, height, depth, mipLayers, format)); + } + + protected void free() { allocation.free(); allocation = null; } diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/VmaAllocator.java b/src/main/java/me/cortex/vulkanite/lib/memory/VmaAllocator.java index 6a2ecd3..907d9a6 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/VmaAllocator.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/VmaAllocator.java @@ -1,7 +1,6 @@ package me.cortex.vulkanite.lib.memory; -import me.cortex.vulkanite.lib.base.TrackedResourceObject; - +import me.cortex.vulkanite.lib.base.VObject; import org.lwjgl.PointerBuffer; import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryUtil; @@ -211,6 +210,9 @@ BufferAllocation alloc(long pool, VkBufferCreateInfo bufferCreateInfo, BufferAllocation alloc(long pool, VkBufferCreateInfo bufferCreateInfo, VmaAllocationCreateInfo allocationCreateInfo, long alignment) { + if (bufferCreateInfo.size() == 0) { + throw new RuntimeException("Buffer size must be greater than 0"); + } try (var stack = stackPush()) { LongBuffer pb = stack.mallocLong(1); PointerBuffer pa = stack.mallocPointer(1); @@ -273,7 +275,7 @@ ImageAllocation alloc(long pool, VkImageCreateInfo imageCreateInfo, VmaAllocatio } } - public abstract static class Allocation extends TrackedResourceObject { + public abstract static class Allocation extends VObject { public final VmaAllocationInfo ai; public final long allocation; @@ -283,8 +285,7 @@ public Allocation(long allocation, VmaAllocationInfo info) { this.allocation = allocation; } - public void free() { - free0(); + protected void free() { // vmaFreeMemory(allocator, allocation); ai.free(); } @@ -298,7 +299,7 @@ public class BufferAllocation extends Allocation { public long buffer = 0; public final long deviceAddress; - public BufferAllocation(long buffer, long allocation, VmaAllocationInfo info, boolean hasDeviceAddress) { + protected BufferAllocation(long buffer, long allocation, VmaAllocationInfo info, boolean hasDeviceAddress) { super(allocation, info); this.buffer = buffer; if (hasDeviceAddresses && hasDeviceAddress) { @@ -314,7 +315,7 @@ public BufferAllocation(long buffer, long allocation, VmaAllocationInfo info, bo } @Override - public void free() { + protected void free() { // vkFreeMemory(); vmaDestroyBuffer(allocator, buffer, allocation); super.free(); @@ -356,17 +357,16 @@ public void flush(long offset, long size) { public class SharedBufferAllocation extends BufferAllocation { private final boolean dedicated; - public SharedBufferAllocation(long buffer, long allocation, VmaAllocationInfo info, boolean hasDeviceAddress, + protected SharedBufferAllocation(long buffer, long allocation, VmaAllocationInfo info, boolean hasDeviceAddress, boolean dedicated) { super(buffer, allocation, info, hasDeviceAddress); this.dedicated = dedicated; } @Override - public void free() { + protected void free() { vkDestroyBuffer(device, buffer, null); vmaFreeMemory(allocator, allocation); - free0(); ai.free(); } @@ -378,13 +378,13 @@ boolean isDedicated() { public class ImageAllocation extends Allocation { public final long image; - public ImageAllocation(long image, long allocation, VmaAllocationInfo info) { + protected ImageAllocation(long image, long allocation, VmaAllocationInfo info) { super(allocation, info); this.image = image; } @Override - public void free() { + protected void free() { // vkFreeMemory(); vmaDestroyImage(allocator, image, allocation); super.free(); @@ -394,17 +394,16 @@ public void free() { public class SharedImageAllocation extends ImageAllocation { private final boolean dedicated; - public SharedImageAllocation(long image, long allocation, VmaAllocationInfo info, boolean dedicated) { + protected SharedImageAllocation(long image, long allocation, VmaAllocationInfo info, boolean dedicated) { super(image, allocation, info); this.dedicated = dedicated; } @Override - public void free() { + protected void free() { // vkFreeMemory(); vkDestroyImage(device, image, null); vmaFreeMemory(allocator, allocation); - free0(); ai.free(); } diff --git a/src/main/java/me/cortex/vulkanite/lib/other/VImageView.java b/src/main/java/me/cortex/vulkanite/lib/other/VImageView.java index 665a4cb..18ff1f0 100644 --- a/src/main/java/me/cortex/vulkanite/lib/other/VImageView.java +++ b/src/main/java/me/cortex/vulkanite/lib/other/VImageView.java @@ -1,7 +1,8 @@ package me.cortex.vulkanite.lib.other; -import me.cortex.vulkanite.lib.base.TrackedResourceObject; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VObject; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VImage; import org.lwjgl.vulkan.VkImageViewCreateInfo; @@ -11,15 +12,15 @@ import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; -public class VImageView extends TrackedResourceObject { +public class VImageView extends VObject { private final VContext ctx; - public final VImage image; + public final VRef image; public final long view; - public VImageView(VContext ctx, VImage image) { + protected VImageView(VContext ctx, final VRef image) { this.ctx = ctx; - this.image = image; + this.image = image.addRef(); - int imageViewType = switch (image.dimensions) { + int imageViewType = switch (image.get().dimensions) { case 1 -> VK_IMAGE_VIEW_TYPE_1D; case 2 -> VK_IMAGE_VIEW_TYPE_2D; case 3 -> VK_IMAGE_VIEW_TYPE_3D; @@ -31,8 +32,8 @@ public VImageView(VContext ctx, VImage image) { var vci = VkImageViewCreateInfo.calloc(stack) .sType$Default() .viewType(imageViewType) - .format(image.format) - .image(image.image()); + .format(image.get().format) + .image(image.get().image()); vci.subresourceRange() .aspectMask(VK_IMAGE_ASPECT_COLOR_BIT) .layerCount(1) @@ -42,8 +43,15 @@ public VImageView(VContext ctx, VImage image) { } } - public void free() { - free0(); + public boolean isDerivedFrom(VImage image) { + return this.image.get().image() == image.image(); + } + + static public VRef create(VContext ctx, final VRef image) { + return new VRef<>(new VImageView(ctx, image)); + } + + protected void free() { vkDestroyImageView(ctx.device, view, null); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/other/VQueryPool.java b/src/main/java/me/cortex/vulkanite/lib/other/VQueryPool.java index 040b2bd..1f21484 100644 --- a/src/main/java/me/cortex/vulkanite/lib/other/VQueryPool.java +++ b/src/main/java/me/cortex/vulkanite/lib/other/VQueryPool.java @@ -1,6 +1,7 @@ package me.cortex.vulkanite.lib.other; -import me.cortex.vulkanite.lib.base.TrackedResourceObject; +import me.cortex.vulkanite.lib.base.VObject; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.cmd.VCmdBuff; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.VkCommandBuffer; @@ -13,10 +14,10 @@ import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; -public class VQueryPool extends TrackedResourceObject { +public class VQueryPool extends VObject { public final long pool; private final VkDevice device; - public VQueryPool(VkDevice device, int count, int type) { + private VQueryPool(VkDevice device, int count, int type) { this.device = device; try (MemoryStack stack = stackPush()) { LongBuffer pQueryPool = stack.mallocLong(1); @@ -31,12 +32,8 @@ public VQueryPool(VkDevice device, int count, int type) { } } - public void reset(VCmdBuff cmd, int first, int size) { - reset(cmd.buffer, first, size); - } - - public void reset(VkCommandBuffer cmd, int first, int size) { - vkCmdResetQueryPool(cmd, pool, first, size); + public static VRef create(VkDevice device, int count, int type) { + return new VRef<>(new VQueryPool(device, count, type)); } public long[] getResultsLong(int count) { @@ -53,8 +50,7 @@ public long[] getResultsLong(int start, int count, int flags) { } } - public void free() { - free0(); + protected void free() { vkDestroyQueryPool(device, pool, null); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/other/VSampler.java b/src/main/java/me/cortex/vulkanite/lib/other/VSampler.java index 076b700..20cfff9 100644 --- a/src/main/java/me/cortex/vulkanite/lib/other/VSampler.java +++ b/src/main/java/me/cortex/vulkanite/lib/other/VSampler.java @@ -1,7 +1,8 @@ package me.cortex.vulkanite.lib.other; -import me.cortex.vulkanite.lib.base.TrackedResourceObject; +import me.cortex.vulkanite.lib.base.VObject; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.VkSamplerCreateInfo; @@ -12,11 +13,11 @@ import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; -public class VSampler extends TrackedResourceObject { +public final class VSampler extends VObject { private final VContext ctx; public final long sampler; - public VSampler(VContext context, Consumer setup) { + private VSampler(VContext context, Consumer setup) { this.ctx = context; try (MemoryStack stack = stackPush()) { LongBuffer pSampler = stack.mallocLong(1); @@ -30,9 +31,12 @@ public VSampler(VContext context, Consumer setup) { } } + public static VRef create(VContext context, Consumer setup) { + return new VRef<>(new VSampler(context, setup)); + } + @Override - public void free() { - free0(); + protected void free() { vkDestroySampler(ctx.device, sampler, null); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java b/src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java index 8ce7816..7c84429 100644 --- a/src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java @@ -1,6 +1,7 @@ package me.cortex.vulkanite.lib.other.sync; import me.cortex.vulkanite.client.Vulkanite; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.HandleDescriptorManger; import org.lwjgl.PointerBuffer; import org.lwjgl.vulkan.*; @@ -40,15 +41,15 @@ public SyncManager(VkDevice device) { this.device = device; } - public VFence createFence() { + public VRef createFence() { try (var stack = stackPush()) { LongBuffer res = stack.callocLong(1); _CHECK_(vkCreateFence(device, VkFenceCreateInfo.calloc(stack).sType$Default(), null, res)); - return new VFence(device, res.get(0)); + return VFence.create(device, res.get(0)); } } - private VGSemaphore createSharedBinarySemaphoreWin32() { + private VRef createSharedBinarySemaphoreWin32() { try (var stack = stackPush()) { LongBuffer res = stack.callocLong(1); _CHECK_(vkCreateSemaphore(device, @@ -80,11 +81,11 @@ private VGSemaphore createSharedBinarySemaphoreWin32() { if (glGetError() != GL_NO_ERROR) throw new IllegalStateException(); - return new VGSemaphore(device, semaphore, glSemaphore, pb.get(0)); + return VGSemaphore.create(device, semaphore, glSemaphore, pb.get(0)); } } - private VGSemaphore createSharedBinarySemaphoreFd() { + private VRef createSharedBinarySemaphoreFd() { try (var stack = stackPush()) { LongBuffer res = stack.callocLong(1); _CHECK_(vkCreateSemaphore(device, @@ -116,19 +117,19 @@ private VGSemaphore createSharedBinarySemaphoreFd() { if (glGetError() != GL_NO_ERROR) throw new IllegalStateException(); - return new VGSemaphore(device, semaphore, glSemaphore, fd.get(0)); + return VGSemaphore.create(device, semaphore, glSemaphore, fd.get(0)); } } - public VGSemaphore createSharedBinarySemaphore() { + public VRef createSharedBinarySemaphore() { return Vulkanite.IS_WINDOWS?createSharedBinarySemaphoreWin32():createSharedBinarySemaphoreFd(); } - public VSemaphore createBinarySemaphore() { + public VRef createBinarySemaphore() { try (var stack = stackPush()) { LongBuffer res = stack.callocLong(1); _CHECK_(vkCreateSemaphore(device, VkSemaphoreCreateInfo.calloc(stack).sType$Default(), null, res)); - return new VSemaphore(device, res.get(0)); + return VSemaphore.create(device, res.get(0)); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/other/sync/VFence.java b/src/main/java/me/cortex/vulkanite/lib/other/sync/VFence.java index 518f8f7..2081e83 100644 --- a/src/main/java/me/cortex/vulkanite/lib/other/sync/VFence.java +++ b/src/main/java/me/cortex/vulkanite/lib/other/sync/VFence.java @@ -1,6 +1,7 @@ package me.cortex.vulkanite.lib.other.sync; -import me.cortex.vulkanite.lib.base.TrackedResourceObject; +import me.cortex.vulkanite.lib.base.VObject; +import me.cortex.vulkanite.lib.base.VRef; import org.lwjgl.system.Pointer; import org.lwjgl.vulkan.VkDevice; @@ -8,22 +9,26 @@ import static org.lwjgl.vulkan.VK10.vkDestroyFence; -public final class VFence extends TrackedResourceObject implements Pointer { +public final class VFence extends VObject implements Pointer { private final VkDevice device; private final long fence; - public VFence(VkDevice device, long fence) { + private VFence(VkDevice device, long fence) { this.device = device; this.fence = fence; } + static VRef create(VkDevice device, long fence) { + return new VRef<>(new VFence(device, fence)); + } + @Override public long address() { return fence; } - public void free() { - free0(); + @Override + protected void free() { vkDestroyFence(device, fence, null); } diff --git a/src/main/java/me/cortex/vulkanite/lib/other/sync/VGSemaphore.java b/src/main/java/me/cortex/vulkanite/lib/other/sync/VGSemaphore.java index 421398a..c89f3de 100644 --- a/src/main/java/me/cortex/vulkanite/lib/other/sync/VGSemaphore.java +++ b/src/main/java/me/cortex/vulkanite/lib/other/sync/VGSemaphore.java @@ -1,5 +1,7 @@ package me.cortex.vulkanite.lib.other.sync; +import me.cortex.vulkanite.client.Vulkanite; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.HandleDescriptorManger; import me.cortex.vulkanite.lib.memory.MemoryManager; import org.lwjgl.vulkan.VkDevice; @@ -10,16 +12,23 @@ public class VGSemaphore extends VSemaphore { public final int glSemaphore; private final long handleDescriptor; - public VGSemaphore(VkDevice device, long semaphore, int glSemaphore, long handleDescriptor) { + protected VGSemaphore(VkDevice device, long semaphore, int glSemaphore, long handleDescriptor) { super(device, semaphore); this.glSemaphore = glSemaphore; this.handleDescriptor = handleDescriptor; } + public static VRef create(VkDevice device, long semaphore, int glSemaphore, long handleDescriptor) { + return new VRef<>(new VGSemaphore(device, semaphore, glSemaphore, handleDescriptor)); + } + @Override - public void free() { + protected void free() { HandleDescriptorManger.close(handleDescriptor); - glDeleteSemaphoresEXT(glSemaphore); + int glSemaphore = this.glSemaphore; + Vulkanite.INSTANCE.addSyncedCallback(() -> { + glDeleteSemaphoresEXT(glSemaphore); + }); super.free(); } diff --git a/src/main/java/me/cortex/vulkanite/lib/other/sync/VSemaphore.java b/src/main/java/me/cortex/vulkanite/lib/other/sync/VSemaphore.java index 7dd7b3b..653b106 100644 --- a/src/main/java/me/cortex/vulkanite/lib/other/sync/VSemaphore.java +++ b/src/main/java/me/cortex/vulkanite/lib/other/sync/VSemaphore.java @@ -1,6 +1,7 @@ package me.cortex.vulkanite.lib.other.sync; -import me.cortex.vulkanite.lib.base.TrackedResourceObject; +import me.cortex.vulkanite.lib.base.VObject; +import me.cortex.vulkanite.lib.base.VRef; import org.lwjgl.system.Pointer; import org.lwjgl.vulkan.VkDevice; @@ -8,22 +9,25 @@ import static org.lwjgl.vulkan.VK10.vkDestroySemaphore; -public class VSemaphore extends TrackedResourceObject implements Pointer { +public class VSemaphore extends VObject implements Pointer { private final VkDevice device; private final long semaphore; - public VSemaphore(VkDevice device, long semaphore) { + protected VSemaphore(VkDevice device, long semaphore) { this.device = device; this.semaphore = semaphore; } + public static VRef create(VkDevice device, long semaphore) { + return new VRef<>(new VSemaphore(device, semaphore)); + } + @Override public long address() { return semaphore; } - public void free() { - free0(); + protected void free() { vkDestroySemaphore(device, semaphore, null); } diff --git a/src/main/java/me/cortex/vulkanite/lib/pipeline/ComputePipelineBuilder.java b/src/main/java/me/cortex/vulkanite/lib/pipeline/ComputePipelineBuilder.java index 97cb410..5c12461 100644 --- a/src/main/java/me/cortex/vulkanite/lib/pipeline/ComputePipelineBuilder.java +++ b/src/main/java/me/cortex/vulkanite/lib/pipeline/ComputePipelineBuilder.java @@ -1,6 +1,7 @@ package me.cortex.vulkanite.lib.pipeline; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.descriptors.VDescriptorSetLayout; import me.cortex.vulkanite.lib.shader.ShaderModule; import org.lwjgl.vulkan.*; @@ -19,8 +20,8 @@ public ComputePipelineBuilder() { } - Set layouts = new LinkedHashSet<>(); - public ComputePipelineBuilder addLayout(VDescriptorSetLayout layout) { + Set> layouts = new LinkedHashSet<>(); + public ComputePipelineBuilder addLayout(VRef layout) { layouts.add(layout); return this; } @@ -38,14 +39,14 @@ public void addPushConstantRange(int size, int offset) { pushConstants.add(new PushConstant(size, offset)); } - public VComputePipeline build(VContext context) { + public VRef build(VContext context) { try (var stack = stackPush()) { VkPipelineLayoutCreateInfo layoutCreateInfo = VkPipelineLayoutCreateInfo.calloc(stack) .sType$Default(); { //TODO: cleanup and add push constants - layoutCreateInfo.pSetLayouts(stack.longs(layouts.stream().mapToLong(a->a.layout).toArray())); + layoutCreateInfo.pSetLayouts(stack.longs(layouts.stream().mapToLong(a->a.get().layout).toArray())); } if (pushConstants.size() > 0) { @@ -71,7 +72,7 @@ public VComputePipeline build(VContext context) { .layout(pLayout.get(0)) .stage(shaderStage), null, pPipeline)); - return new VComputePipeline(context, pLayout.get(0), pPipeline.get(0)); + return new VRef<>(new VComputePipeline(context, pLayout.get(0), pPipeline.get(0))); } } } diff --git a/src/main/java/me/cortex/vulkanite/lib/pipeline/RaytracePipelineBuilder.java b/src/main/java/me/cortex/vulkanite/lib/pipeline/RaytracePipelineBuilder.java index 3d34d91..b7e88d1 100644 --- a/src/main/java/me/cortex/vulkanite/lib/pipeline/RaytracePipelineBuilder.java +++ b/src/main/java/me/cortex/vulkanite/lib/pipeline/RaytracePipelineBuilder.java @@ -1,6 +1,7 @@ package me.cortex.vulkanite.lib.pipeline; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.descriptors.VDescriptorSetLayout; import me.cortex.vulkanite.lib.memory.VBuffer; import me.cortex.vulkanite.lib.shader.ShaderModule; @@ -58,20 +59,20 @@ public RaytracePipelineBuilder addCallable(ShaderModule callable) { return this; } - ArrayList layouts = new ArrayList<>(); - public RaytracePipelineBuilder addLayout(VDescriptorSetLayout layout) { + List> layouts = new ArrayList<>(); + public RaytracePipelineBuilder addLayout(VRef layout) { layouts.add(layout); return this; } //TODO: generate stb - public VRaytracePipeline build(VContext context, int maxDepth) { + public VRef build(VContext context, int maxDepth) { shaders.add(gen); ArrayList reflections = new ArrayList<>(); ShaderReflection reflection = null; for (var shader : shaders) { - reflections.add(shader.shader().getReflection()); + reflections.add(shader.shader().get().getReflection()); } try { reflection = ShaderReflection.mergeStages(reflections.toArray(ShaderReflection[]::new)); @@ -136,7 +137,7 @@ public VRaytracePipeline build(VContext context, int maxDepth) { { //TODO: cleanup and add push constants - layoutCreateInfo.pSetLayouts(stack.longs(layouts.stream().mapToLong(a->a.layout).toArray())); + layoutCreateInfo.pSetLayouts(stack.longs(layouts.stream().mapToLong(a->a.get().layout).toArray())); } LongBuffer pLayout = stack.mallocLong(1); @@ -183,12 +184,13 @@ public VRaytracePipeline build(VContext context, int maxDepth) { long aHandles = MemoryUtil.memAddress(handles); //TODO/FIXME: add alignment to gpu buffer - VBuffer sbtMap = context.memory.createBuffer(sbtSize, + VRef sbtMapRef = context.memory.createBuffer(sbtSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR, VK_MEMORY_HEAP_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 0, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); + VBuffer sbtMap = sbtMapRef.get(); sbtMap.setDebugUtilsObjectName("SBT"); long ptr = sbtMap.map(); @@ -215,14 +217,14 @@ public VRaytracePipeline build(VContext context, int maxDepth) { sbtMap.unmap(); sbtMap.flush(); - return new VRaytracePipeline(context, pPipeline.get(0), pLayout.get(0), sbtMap, + return new VRef<>(new VRaytracePipeline(context, pPipeline.get(0), pLayout.get(0), sbtMapRef, VkStridedDeviceAddressRegionKHR.calloc().set(sbtMap.deviceAddress() + rgenBase, handleSizeAligned, handleSizeAligned), VkStridedDeviceAddressRegionKHR.calloc().set(sbtMap.deviceAddress() + missGroupBase, handleSizeAligned, handleSizeAligned * missGroupCount), VkStridedDeviceAddressRegionKHR.calloc().set(sbtMap.deviceAddress() + hitGroupsBase, handleSizeAligned, handleSizeAligned * hitGroupsCount), VkStridedDeviceAddressRegionKHR.calloc().set(sbtMap.deviceAddress() + callGroupBase, handleSizeAligned, handleSizeAligned * callGroupCount), shaders, reflection - ); + )); } } } diff --git a/src/main/java/me/cortex/vulkanite/lib/pipeline/VComputePipeline.java b/src/main/java/me/cortex/vulkanite/lib/pipeline/VComputePipeline.java index 32c2e34..0439b6e 100644 --- a/src/main/java/me/cortex/vulkanite/lib/pipeline/VComputePipeline.java +++ b/src/main/java/me/cortex/vulkanite/lib/pipeline/VComputePipeline.java @@ -1,10 +1,10 @@ package me.cortex.vulkanite.lib.pipeline; -import me.cortex.vulkanite.lib.base.TrackedResourceObject; import me.cortex.vulkanite.lib.base.VContext; -import me.cortex.vulkanite.lib.other.sync.VFence; +import me.cortex.vulkanite.lib.base.VObject; +import static org.lwjgl.vulkan.VK10.vkDestroyPipeline; -public class VComputePipeline extends TrackedResourceObject { +public class VComputePipeline extends VObject { private final VContext context; private final long pipeline; private final long layout; @@ -25,6 +25,6 @@ public long pipeline() { @Override public void free() { - + vkDestroyPipeline(context.device, pipeline, null); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/pipeline/VRaytracePipeline.java b/src/main/java/me/cortex/vulkanite/lib/pipeline/VRaytracePipeline.java index d1da4a8..fec99d8 100644 --- a/src/main/java/me/cortex/vulkanite/lib/pipeline/VRaytracePipeline.java +++ b/src/main/java/me/cortex/vulkanite/lib/pipeline/VRaytracePipeline.java @@ -1,7 +1,8 @@ package me.cortex.vulkanite.lib.pipeline; -import me.cortex.vulkanite.lib.base.TrackedResourceObject; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VObject; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.cmd.VCmdBuff; import me.cortex.vulkanite.lib.memory.VBuffer; import me.cortex.vulkanite.lib.shader.ShaderModule; @@ -14,30 +15,30 @@ import static org.lwjgl.vulkan.KHRRayTracingPipeline.vkCmdTraceRaysKHR; import static org.lwjgl.vulkan.VK10.*; -public class VRaytracePipeline extends TrackedResourceObject { +public class VRaytracePipeline extends VObject { private final VContext context; - private final long pipeline; - private final long layout; - private final VBuffer shader_binding_table; - private final VkStridedDeviceAddressRegionKHR gen; - private final VkStridedDeviceAddressRegionKHR miss; - private final VkStridedDeviceAddressRegionKHR hit; - private final VkStridedDeviceAddressRegionKHR callable; + public final long pipeline; + public final long layout; + @SuppressWarnings("FieldCanBeLocal") + private final VRef shader_binding_table; + public final VkStridedDeviceAddressRegionKHR gen; + public final VkStridedDeviceAddressRegionKHR miss; + public final VkStridedDeviceAddressRegionKHR hit; + public final VkStridedDeviceAddressRegionKHR callable; private final Set shadersUsed; public final ShaderReflection reflection; - VRaytracePipeline(VContext context, long pipeline, long layout, VBuffer sbtMap, + VRaytracePipeline(VContext context, long pipeline, long layout, final VRef sbtMap, VkStridedDeviceAddressRegionKHR raygen, VkStridedDeviceAddressRegionKHR miss, VkStridedDeviceAddressRegionKHR hit, VkStridedDeviceAddressRegionKHR callable, Set shadersUsed, ShaderReflection reflection) { - this.context = context; this.pipeline = pipeline; this.layout = layout; - this.shader_binding_table = sbtMap; + this.shader_binding_table = sbtMap.addRef(); this.gen = raygen; this.miss = miss; this.hit = hit; @@ -46,22 +47,8 @@ public class VRaytracePipeline extends TrackedResourceObject { this.reflection = reflection; } - public void bind(VCmdBuff cmd) { - vkCmdBindPipeline(cmd.buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline); - } - - public void trace(VCmdBuff cmd, int width, int height, int depth) { - vkCmdTraceRaysKHR(cmd.buffer, gen, miss, hit, callable, width, height, depth); - } - - public void bindDSet(VCmdBuff cmd, long... descs) { - vkCmdBindDescriptorSets(cmd.buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, layout, 0, descs, null); - } - - public void free() { - free0(); + protected void free() { vkDestroyPipeline(context.device, pipeline, null); - shader_binding_table.free(); gen.free(); miss.free(); hit.free(); diff --git a/src/main/java/me/cortex/vulkanite/lib/shader/ShaderModule.java b/src/main/java/me/cortex/vulkanite/lib/shader/ShaderModule.java index 7b70788..f72ed53 100644 --- a/src/main/java/me/cortex/vulkanite/lib/shader/ShaderModule.java +++ b/src/main/java/me/cortex/vulkanite/lib/shader/ShaderModule.java @@ -1,14 +1,15 @@ package me.cortex.vulkanite.lib.shader; +import me.cortex.vulkanite.lib.base.VRef; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.VkPipelineShaderStageCreateInfo; public record ShaderModule( - VShader shader, String name) { + VRef shader, String name) { public void setupStruct(MemoryStack stack, VkPipelineShaderStageCreateInfo struct) { struct.sType$Default() - .stage(shader.stage) - .module(shader.module) + .stage(shader.get().stage) + .module(shader.get().module) .pName(stack.UTF8(name)); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/shader/VShader.java b/src/main/java/me/cortex/vulkanite/lib/shader/VShader.java index 47ed7ca..546259e 100644 --- a/src/main/java/me/cortex/vulkanite/lib/shader/VShader.java +++ b/src/main/java/me/cortex/vulkanite/lib/shader/VShader.java @@ -1,7 +1,8 @@ package me.cortex.vulkanite.lib.shader; -import me.cortex.vulkanite.lib.base.TrackedResourceObject; +import me.cortex.vulkanite.lib.base.VObject; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.shader.reflection.ShaderReflection; import org.lwjgl.vulkan.VkShaderModuleCreateInfo; @@ -14,7 +15,7 @@ import static org.lwjgl.vulkan.KHRRayTracingPipeline.*; import static org.lwjgl.vulkan.VK10.*; -public class VShader extends TrackedResourceObject { +public class VShader extends VObject { private final VContext ctx; public final long module; public final int stage; @@ -24,7 +25,7 @@ public ShaderReflection getReflection() { return reflection; } - public VShader(VContext ctx, long module, int stage, ShaderReflection reflection) { + private VShader(VContext ctx, long module, int stage, ShaderReflection reflection) { this.ctx = ctx; this.module = module; this.stage = stage; @@ -36,10 +37,10 @@ public ShaderModule named() { } public ShaderModule named(String name) { - return new ShaderModule(this, name); + return new ShaderModule(new VRef<>(this), name); } - public static VShader compileLoad(VContext ctx, String source, int stage) { + public static VRef compileLoad(VContext ctx, String source, int stage) { try (var stack = stackPush()) { ByteBuffer code = ShaderCompiler.compileShader("shader", source, stage); @@ -50,13 +51,12 @@ public static VShader compileLoad(VContext ctx, String source, int stage) { .pCode(code); LongBuffer pShaderModule = stack.mallocLong(1); _CHECK_(vkCreateShaderModule(ctx.device, createInfo, null, pShaderModule)); - return new VShader(ctx, pShaderModule.get(0), stage, reflection); + return new VRef<>(new VShader(ctx, pShaderModule.get(0), stage, reflection)); } } @Override - public void free() { - free0(); + protected void free() { vkDestroyShaderModule(ctx.device, module, null); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/shader/reflection/ShaderReflection.java b/src/main/java/me/cortex/vulkanite/lib/shader/reflection/ShaderReflection.java index 20612ae..e24a45f 100644 --- a/src/main/java/me/cortex/vulkanite/lib/shader/reflection/ShaderReflection.java +++ b/src/main/java/me/cortex/vulkanite/lib/shader/reflection/ShaderReflection.java @@ -1,6 +1,7 @@ package me.cortex.vulkanite.lib.shader.reflection; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.descriptors.DescriptorSetLayoutBuilder; import me.cortex.vulkanite.lib.descriptors.VDescriptorSetLayout; import org.lwjgl.util.spvc.SpvcReflectedResource; @@ -195,13 +196,13 @@ public static ShaderReflection mergeStages(ShaderReflection ...stages) { return out; } - public List buildSetLayouts(VContext context) { + public List> buildSetLayouts(VContext context) { // TODO: Pick a better number, somehow return buildSetLayouts(context, 65536); } - private List layouts = new ArrayList<>(); - public List buildSetLayouts(VContext context, int runtimeSizedArrayMaxSize) { + private List> layouts = new ArrayList<>(); + public List> buildSetLayouts(VContext context, int runtimeSizedArrayMaxSize) { freeLayouts(); layouts = new ArrayList<>(); for (var set : sets) { @@ -231,14 +232,12 @@ public List buildSetLayouts(VContext context, int runtimeS return layouts; } - public final List getLayouts() { + public final List> getLayouts() { return layouts; } public void freeLayouts() { - for (var l : layouts) { - l.free(); - } + layouts.clear(); } private static void _CHECK_(int status) { diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java index ad41384..1a6645d 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java @@ -3,6 +3,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.compat.IVGImage; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VGImage; import me.cortex.vulkanite.lib.other.FormatConverter; import net.coderbot.iris.gl.IrisRenderSystem; @@ -22,7 +23,7 @@ @Mixin(value = GlTexture.class, remap = false) public abstract class MixinGlTexture extends MixinGlResource implements IVGImage { - @Unique private VGImage sharedImage; + @Unique private VRef sharedImage; @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_genTexture()I")) private static int redirectGen() { @@ -52,15 +53,15 @@ private int redirectTextureCreation(GlTexture instance, TextureType target, int VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ); - sharedImage.setDebugUtilsObjectName("GlTexture"); + sharedImage.get().setDebugUtilsObjectName("GlTexture"); Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { - cmdbuf.encodeImageTransition(sharedImage, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); + cmdbuf.encodeImageTransition(new VRef<>(sharedImage.get()), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); }); - this.setGlId(sharedImage.glId); + this.setGlId(sharedImage.get().glId); - return sharedImage.glId; + return sharedImage.get().glId; } @Redirect(method="", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/gl/texture/TextureType;apply(IIIIIIILjava/nio/ByteBuffer;)V")) @@ -86,10 +87,10 @@ private void redirectUpload(TextureType instance, int glId, int width, int heigh @Overwrite protected void destroyInternal(){ glFinish(); - sharedImage.free(); + sharedImage = null; } - public VGImage getVGImage() { - return sharedImage; + public VRef getVGImage() { + return sharedImage == null ? null : sharedImage.addRef(); } } diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNativeImageBackedTexture.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNativeImageBackedTexture.java index bee4b8c..5aa9c01 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNativeImageBackedTexture.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNativeImageBackedTexture.java @@ -5,6 +5,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.compat.IVGImage; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.mixin.minecraft.MixinAbstractTexture; import net.coderbot.iris.gl.IrisRenderSystem; import net.coderbot.iris.rendertarget.NativeImageBackedCustomTexture; @@ -38,7 +39,6 @@ private void redirectGen(int id, int width, int height) { } if (getVGImage() != null) { System.err.println("Vulkan image already allocated, releasing"); - Vulkanite.INSTANCE.addSyncedCallback(getVGImage()::free); setVGImage(null); } @@ -50,13 +50,13 @@ private void redirectGen(int id, int width, int height) { GL_RGBA8, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - img.setDebugUtilsObjectName("NativeImageBackedTexture"); + img.get().setDebugUtilsObjectName("NativeImageBackedTexture"); setVGImage(img); Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { - cmdbuf.encodeImageTransition(img, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); + cmdbuf.encodeImageTransition(new VRef<>(img.get()), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); }); - GlStateManager._bindTexture(img.glId); + GlStateManager._bindTexture(img.get().glId); } } diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java index a711fe2..d603be2 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java @@ -6,6 +6,7 @@ import me.cortex.vulkanite.client.rendering.VulkanPipeline; import me.cortex.vulkanite.compat.*; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VGImage; import net.coderbot.iris.gl.buffer.ShaderStorageBuffer; import net.coderbot.iris.gl.texture.TextureAccess; @@ -46,7 +47,7 @@ public class MixinNewWorldRenderingPipeline { @Unique private VulkanPipeline pipeline; @Unique - private VGImage[] getCustomTextures() { + private List> getCustomTextures() { Object2ObjectMap texturesBinary = customTextureManager.getIrisCustomTextures(); Object2ObjectMap texturesPNGs = customTextureManager.getCustomTextureIdMap(TextureStage.GBUFFERS_AND_SHADOW); @@ -58,7 +59,7 @@ private VGImage[] getCustomTextures() { return entryList.stream() .map(entry -> ((IVGImage) entry.getValue()).getVGImage()) - .toArray(VGImage[]::new); + .toList(); } @Inject(method = "", at = @At("TAIL")) @@ -83,7 +84,7 @@ private void renderShadows(LevelRendererAccessor par1, Camera par2, CallbackInfo buffers = ((ShaderStorageBufferHolderAccessor)shaderStorageBufferHolder).getBuffers(); } - List outImgs = new ArrayList<>(); + List> outImgs = new ArrayList<>(); for (int i = 0; i < renderTargets.getRenderTargetCount(); i++) { outImgs.add(((IRenderTargetVkGetter)renderTargets.getOrCreate(i)).getMain()); } @@ -95,12 +96,9 @@ private void renderShadows(LevelRendererAccessor par1, Camera par2, CallbackInfo @Inject(method = "destroyShaders", at = @At("TAIL")) private void destory(CallbackInfo ci) { + if (ctx == null) return; + ctx.cmd.waitQueueIdle(0); - if (rtShaderPasses != null) { - for (var pass : rtShaderPasses) { - pass.delete(); - } - } pipeline.destory(); rtShaderPasses = null; pipeline = null; diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinPBRAtlasTexture.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinPBRAtlasTexture.java index e775cbb..709c0b9 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinPBRAtlasTexture.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinPBRAtlasTexture.java @@ -3,6 +3,7 @@ import com.mojang.blaze3d.platform.GlStateManager; import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.compat.IVGImage; +import me.cortex.vulkanite.lib.base.VRef; import net.coderbot.iris.texture.pbr.PBRAtlasTexture; import net.minecraft.client.texture.AbstractTexture; import net.minecraft.client.texture.SpriteAtlasTexture; @@ -20,7 +21,6 @@ public abstract class MixinPBRAtlasTexture extends AbstractTexture implements IV private void redirect(int id, int maxLevel, int width, int height) { if (getVGImage() != null) { System.err.println("Vulkan image already allocated, releasing"); - Vulkanite.INSTANCE.addSyncedCallback(getVGImage()::free); setVGImage(null); } @@ -36,11 +36,11 @@ private void redirect(int id, int maxLevel, int width, int height) { GL_RGBA8, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - img.setDebugUtilsObjectName("PBRAtlasTexture"); + img.get().setDebugUtilsObjectName("PBRAtlasTexture"); setVGImage(img); Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { - cmdbuf.encodeImageTransition(img, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); + cmdbuf.encodeImageTransition(new VRef<>(img.get()), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); }); diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java index ed1c4ec..2149b01 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java @@ -2,6 +2,7 @@ import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.compat.IRenderTargetVkGetter; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VGImage; import me.cortex.vulkanite.lib.other.FormatConverter; import net.coderbot.iris.gl.texture.InternalTextureFormat; @@ -24,8 +25,8 @@ public abstract class MixinRenderTarget implements IRenderTargetVkGetter { @Shadow protected abstract void setupTexture(int i, int i1, int i2, boolean b); - @Unique private VGImage vgMainTexture; - @Unique private VGImage vgAltTexture; + @Unique private VRef vgMainTexture; + @Unique private VRef vgAltTexture; @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_genTextures([I)V")) private void redirectGen(int[] textures) { @@ -45,21 +46,17 @@ private void redirectResize(RenderTarget instance, int t, int w, int h) {} @Overwrite public int getMainTexture() { - return vgMainTexture.glId; + return vgMainTexture.get().glId; } @Overwrite public int getAltTexture() { - return vgAltTexture.glId; + return vgAltTexture.get().glId; } @Overwrite public void resize(int width, int height) { glFinish(); - //TODO: block the gpu fully before deleting and resizing the textures - vgMainTexture.free(); - vgAltTexture.free(); - setupTextures(width, height, !internalFormat.getPixelFormat().isInteger()); } @@ -73,11 +70,11 @@ private void setupTextures(int width, int height, boolean allowsLinear) { vgMainTexture = ctx.memory.createSharedImage(width, height, 1, vkfmt, glfmt, VK_IMAGE_USAGE_STORAGE_BIT , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); vgAltTexture = ctx.memory.createSharedImage(width, height, 1, vkfmt, glfmt, VK_IMAGE_USAGE_STORAGE_BIT , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - vgMainTexture.setDebugUtilsObjectName("RenderTarget Main"); - vgAltTexture.setDebugUtilsObjectName("RenderTarget Alt"); + vgMainTexture.get().setDebugUtilsObjectName("RenderTarget Main"); + vgAltTexture.get().setDebugUtilsObjectName("RenderTarget Alt"); Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { - cmdbuf.encodeImageTransition(vgMainTexture, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); - cmdbuf.encodeImageTransition(vgAltTexture, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); + cmdbuf.encodeImageTransition(new VRef<>(vgMainTexture.get()), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); + cmdbuf.encodeImageTransition(new VRef<>(vgAltTexture.get()), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); }); setupTexture(getMainTexture(), width, height, allowsLinear); @@ -88,15 +85,15 @@ private void setupTextures(int width, int height, boolean allowsLinear) { private void redirectResize(int[] textures) { glFinish(); //TODO: block the gpu fully before deleting and resizing the textures - vgMainTexture.free(); - vgAltTexture.free(); + vgMainTexture = null; + vgAltTexture = null; } - public VGImage getMain() { - return vgMainTexture; + public VRef getMain() { + return vgMainTexture.addRef(); } - public VGImage getAlt() { - return vgAltTexture; + public VRef getAlt() { + return vgAltTexture.addRef(); } } diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBuffer.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBuffer.java index 2c308ce..5d15cae 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBuffer.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBuffer.java @@ -2,6 +2,7 @@ import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.compat.IVGBuffer; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VGBuffer; import net.coderbot.iris.gl.IrisRenderSystem; import net.coderbot.iris.gl.buffer.ShaderStorageBuffer; @@ -18,27 +19,27 @@ public class MixinShaderStorageBuffer implements IVGBuffer { @Shadow protected int id; @Unique - private VGBuffer vkBuffer; + private VRef vkBuffer; - public VGBuffer getBuffer() { - return vkBuffer; + public VRef getBuffer() { + return vkBuffer == null ? null : vkBuffer.addRef(); } - public void setBuffer(VGBuffer buffer) { + public void setBuffer(VRef buffer) { if (vkBuffer != null && buffer != null) { throw new IllegalStateException("Override buffer not null"); } this.vkBuffer = buffer; if (buffer != null) { glDeleteBuffers(id); - id = vkBuffer.glId; + id = vkBuffer.get().glId; } } @Redirect(method = "destroy", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/gl/IrisRenderSystem;deleteBuffers(I)V")) private void redirectDelete(int id) { if (vkBuffer != null) { - Vulkanite.INSTANCE.addSyncedCallback(vkBuffer::free); + vkBuffer = null; } else { IrisRenderSystem.deleteBuffers(id); } diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBufferHolder.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBufferHolder.java index 65e8ee4..b436e25 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBufferHolder.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBufferHolder.java @@ -3,6 +3,7 @@ import com.mojang.blaze3d.platform.GlStateManager; import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.compat.IVGBuffer; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VGBuffer; import net.coderbot.iris.gl.IrisRenderSystem; import net.coderbot.iris.gl.buffer.ShaderStorageBuffer; @@ -27,7 +28,7 @@ private boolean alwaysReturnTrue(ShaderStorageInfo instance) { return true; } - private static VGBuffer alloc(int size) { + private static VRef alloc(int size) { return Vulkanite.INSTANCE.getCtx().memory.createSharedBuffer(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); } diff --git a/src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinAbstractTexture.java b/src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinAbstractTexture.java index 35c04e2..0d4f5d8 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinAbstractTexture.java +++ b/src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinAbstractTexture.java @@ -2,6 +2,7 @@ import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.compat.IVGImage; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VGImage; import net.minecraft.client.texture.AbstractTexture; import org.spongepowered.asm.mixin.Mixin; @@ -15,16 +16,16 @@ @Mixin(AbstractTexture.class) public class MixinAbstractTexture implements IVGImage { @Shadow protected int glId; - @Unique private VGImage vgImage; + @Unique private VRef vgImage; @Override - public void setVGImage(VGImage image) { + public void setVGImage(VRef image) { this.vgImage = image; } @Override - public VGImage getVGImage() { - return vgImage; + public VRef getVGImage() { + return vgImage == null ? null : vgImage; } @Inject(method = "getGlId", at = @At("HEAD"), cancellable = true) @@ -33,7 +34,7 @@ private void redirectGetId(CallbackInfoReturnable cir) { if (glId != -1) { throw new IllegalStateException("glId != -1 while VGImage is set"); } - cir.setReturnValue(vgImage.glId); + cir.setReturnValue(vgImage.get().glId); cir.cancel(); } } @@ -41,7 +42,6 @@ private void redirectGetId(CallbackInfoReturnable cir) { @Inject(method = "clearGlId", at = @At("HEAD"), cancellable = true) private void redirectClear(CallbackInfo ci) { if (vgImage != null) { - Vulkanite.INSTANCE.addSyncedCallback(vgImage::free); vgImage = null; glId = -1; ci.cancel(); diff --git a/src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinResourceTexture.java b/src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinResourceTexture.java index 2c8fc53..87a0f02 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinResourceTexture.java +++ b/src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinResourceTexture.java @@ -5,6 +5,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.compat.IVGImage; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VGImage; import net.minecraft.client.texture.AbstractTexture; import net.minecraft.client.texture.ResourceTexture; @@ -31,7 +32,6 @@ private void redirect(int id, int maxLevel, int width, int height) { RenderSystem.assertOnRenderThreadOrInit(); if (getVGImage() != null) { System.err.println("Vulkan image already allocated, releasing"); - Vulkanite.INSTANCE.addSyncedCallback(getVGImage()::free); setVGImage(null); } @@ -50,7 +50,7 @@ private void redirect(int id, int maxLevel, int width, int height) { setVGImage(img); Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { - cmdbuf.encodeImageTransition(img, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); + cmdbuf.encodeImageTransition(new VRef<>(img.get()), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); }); GlStateManager._bindTexture(getGlId()); diff --git a/src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinSpriteAtlasTexture.java b/src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinSpriteAtlasTexture.java index a82cbd2..dd79b18 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinSpriteAtlasTexture.java +++ b/src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinSpriteAtlasTexture.java @@ -3,6 +3,7 @@ import com.mojang.blaze3d.platform.GlStateManager; import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.compat.IVGImage; +import me.cortex.vulkanite.lib.base.VRef; import net.minecraft.client.texture.AbstractTexture; import net.minecraft.client.texture.SpriteAtlasTexture; import org.spongepowered.asm.mixin.Mixin; @@ -19,7 +20,6 @@ public abstract class MixinSpriteAtlasTexture extends AbstractTexture implements private void redirect(int id, int maxLevel, int width, int height) { if (getVGImage() != null) { System.err.println("Vulkan image already allocated, releasing"); - Vulkanite.INSTANCE.addSyncedCallback(getVGImage()::free); setVGImage(null); } @@ -35,11 +35,11 @@ private void redirect(int id, int maxLevel, int width, int height) { GL_RGBA8, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - img.setDebugUtilsObjectName("RenderTarget MainSpriteAtlasTexture"); + img.get().setDebugUtilsObjectName("RenderTarget MainSpriteAtlasTexture"); setVGImage(img); Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { - cmdbuf.encodeImageTransition(img, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); + cmdbuf.encodeImageTransition(new VRef<>(img.get()), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); }); diff --git a/src/main/java/me/cortex/vulkanite/mixin/sodium/gl/MixinGLRenderDevice.java b/src/main/java/me/cortex/vulkanite/mixin/sodium/gl/MixinGLRenderDevice.java index 4627158..aa154c4 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/sodium/gl/MixinGLRenderDevice.java +++ b/src/main/java/me/cortex/vulkanite/mixin/sodium/gl/MixinGLRenderDevice.java @@ -13,7 +13,7 @@ public class MixinGLRenderDevice { @Inject(method = "deleteBuffer", at = @At("HEAD"), cancellable = true) private void redirectDelete(GlBuffer buffer, CallbackInfo ci) { if (buffer instanceof IVGBuffer vkBuffer && vkBuffer.getBuffer() != null) { - Vulkanite.INSTANCE.addSyncedCallback(vkBuffer.getBuffer()::free); + vkBuffer.setBuffer(null); ci.cancel(); } } diff --git a/src/main/java/me/cortex/vulkanite/mixin/sodium/gl/MixinMutableBuffer.java b/src/main/java/me/cortex/vulkanite/mixin/sodium/gl/MixinMutableBuffer.java index 6ac8517..e3ffe75 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/sodium/gl/MixinMutableBuffer.java +++ b/src/main/java/me/cortex/vulkanite/mixin/sodium/gl/MixinMutableBuffer.java @@ -1,6 +1,7 @@ package me.cortex.vulkanite.mixin.sodium.gl; import me.cortex.vulkanite.compat.IVGBuffer; +import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VGBuffer; import me.jellysquid.mods.sodium.client.gl.buffer.GlBuffer; import me.jellysquid.mods.sodium.client.gl.buffer.GlMutableBuffer; @@ -11,20 +12,20 @@ @Mixin(value = GlMutableBuffer.class, remap = false) public class MixinMutableBuffer extends GlBuffer implements IVGBuffer { - @Unique private VGBuffer vkBuffer; + @Unique private VRef vkBuffer; - public VGBuffer getBuffer() { - return vkBuffer; + public VRef getBuffer() { + return vkBuffer == null ? null : vkBuffer.addRef(); } - public void setBuffer(VGBuffer buffer) { + public void setBuffer(VRef buffer) { if (vkBuffer != null && buffer != null) { throw new IllegalStateException("Override buffer not null"); } this.vkBuffer = buffer; if (buffer != null) { glDeleteBuffers(handle()); - setHandle(vkBuffer.glId); + setHandle(vkBuffer.get().glId); } } } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 4cf63f7..2cc756a 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -15,7 +15,7 @@ ], "depends": { "fabricloader": ">=0.14.21", - "iris": "=1.6.9", - "sodium": "=0.5.3" + "iris": "=1.6.14", + "sodium": "=0.5.5" } } From 7795ab1638cfff14262f940d65054c853b08b956 Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Mon, 12 Feb 2024 23:27:46 -0800 Subject: [PATCH 04/22] WIP, trying to figure out what's tanking perf & fixing host memory usage --- .../acceleration/EntityBlasBuilder.java | 1 + .../client/rendering/VulkanPipeline.java | 4 +--- .../vulkanite/lib/cmd/CommandManager.java | 17 ++++++++++------- .../me/cortex/vulkanite/lib/cmd/VCmdBuff.java | 4 ++++ 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java b/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java index 1908a0f..8df8ad9 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java @@ -161,6 +161,7 @@ private static VRef executeBlasBuild(VContext ctx, VCmdB .srcAccessMask(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR) .dstAccessMask(VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR), null, null); + cmd.addAccelerationStructureRef(structure); cmd.addBufferRef(scratch); return structure; } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java index 78c46de..4511904 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java @@ -240,8 +240,6 @@ private void buildEntities() { public void renderPostShadows(List> vgOutImgs, Camera camera, ShaderStorageBuffer[] ssbos, MixinCelestialUniforms celestialUniforms) { ctx.cmd.newFrame(); -// System.gc(); - buildEntities(); PBRTextureManager.notifyPBRTexturesChanged(); @@ -412,7 +410,7 @@ public void renderPostShadows(List> vgOutImgs, Camera camera, Shad } } - ctx.cmd.submit(0, cmdRef, Arrays.asList(new VRef<>(in.get())), new int[]{VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT}, Arrays.asList(new VRef<>(out.get())), null); + ctx.cmd.submit(0, cmdRef, Arrays.asList(new VRef<>(in.get())), Arrays.asList(new VRef<>(out.get())), null); } out.get().glWait(new int[0], outImgsGlIds, outImgsGlLayouts); diff --git a/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java b/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java index f931478..66958ac 100644 --- a/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java @@ -12,6 +12,7 @@ import me.cortex.vulkanite.lib.other.sync.VSemaphore; import org.lwjgl.vulkan.*; +import java.nio.IntBuffer; import java.nio.LongBuffer; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -35,8 +36,6 @@ protected VRef initialValue() { } }; - private static final int[] waitAll = {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT}; - public CommandManager(VkDevice device, int queues) { this.device = device; this.queues = new Queue[queues]; @@ -103,14 +102,14 @@ public void hostWaitForExecution(int waitQueueId, long execution) { } public long submit(int queueId, final VRef cmdBuff) { - return submit(queueId, cmdBuff, null, waitAll, null, null); + return submit(queueId, cmdBuff, null, null, null); } - public long submit(int queueId, final VRef cmdBuff, List> waits, int[] waitStages, List> triggers, VFence fence) { + public long submit(int queueId, final VRef cmdBuff, List> waits, List> triggers, VFence fence) { if (queueId == 0) { RenderSystem.assertOnRenderThread(); } - return queues[queueId].submit(cmdBuff, queues, waits, waitStages, triggers, fence); + return queues[queueId].submit(cmdBuff, queues, waits, triggers, fence); } public void waitQueueIdle(int queue) { @@ -191,7 +190,7 @@ public void waitForExecution(int execQueue, long execution) { } } - public long submit(final VRef cmdBuff, Queue[] queues, List> waits, int[] waitStages, List> triggers, VFence fence) { + public long submit(final VRef cmdBuff, Queue[] queues, List> waits, List> triggers, VFence fence) { long t = timeline.getAndIncrement(); synchronized (this) { @@ -206,11 +205,13 @@ public long submit(final VRef cmdBuff, Queue[] queues, List cmdBuff, Queue[] queues, List cmdBuff, Queue[] queues, List cmdBuff, Queue[] queues, List semaphore) { public void addVGSemaphoreRef(final VRef semaphore) { refs.add(semaphore.addRefGeneric()); } + public void addAccelerationStructureRef(final VRef accelerationStructure) { + refs.add(accelerationStructure.addRefGeneric()); + } protected VCmdBuff(VCommandPool pool, VkCommandBuffer buff, int flags) { this.pool = pool; From c9637b4eac974399e262db5a7af520e988f5d727 Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Mon, 12 Feb 2024 23:33:23 -0800 Subject: [PATCH 05/22] Code cleanups --- .../acceleration/EntityBlasBuilder.java | 4 ++-- .../client/rendering/VulkanPipeline.java | 7 +----- .../vulkanite/lib/cmd/CommandManager.java | 24 +++++++++---------- .../me/cortex/vulkanite/lib/cmd/VCmdBuff.java | 5 ++-- 4 files changed, 16 insertions(+), 24 deletions(-) diff --git a/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java b/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java index 8df8ad9..42c682b 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java @@ -70,7 +70,7 @@ Pair, VRef> buildBlas(List blas = null; + VRef blas; try (var stack = MemoryStack.stackPush()) { int[] primitiveCounts = new int[infos.size()]; var buildInfo = populateBuildStructs(ctx, stack, cmd, infos, primitiveCounts); @@ -156,7 +156,7 @@ private static VRef executeBlasBuild(VContext ctx, VCmdB vkCmdBuildAccelerationStructuresKHR(cmd.buffer(), buildInfos, stack.pointers(buildRanges)); - vkCmdPipelineBarrier(cmd.buffer(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, VkMemoryBarrier.calloc(1) + vkCmdPipelineBarrier(cmd.buffer(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, VkMemoryBarrier.calloc(1, stack) .sType$Default() .srcAccessMask(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR) .dstAccessMask(VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR), null, null); diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java index 4511904..e6e2c0e 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java @@ -55,7 +55,7 @@ public class VulkanPipeline { private final AccelerationManager accelerationManager; private record RtPipeline(VRef pipeline, int commonSet, int geomSet, int customTexSet, int ssboSet) {} - private ArrayList raytracePipelines = new ArrayList<>(); + private final ArrayList raytracePipelines = new ArrayList<>(); private final VRef sampler; private final VRef ctexSampler; @@ -71,8 +71,6 @@ private record RtPipeline(VRef pipeline, int commonSet, int g private final VRef placeholderNormals; private final VRef placeholderNormalsView; - private int fidx; - private final int maxIrisRenderTargets = 16; private final boolean supportsEntities; @@ -229,9 +227,6 @@ public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, Ray } } - private VSemaphore previousSemaphore; - - private final EntityCapture capture = new EntityCapture(); private void buildEntities() { accelerationManager.setEntityData(supportsEntities?capture.capture(CapturedRenderingState.INSTANCE.getTickDelta(), MinecraftClient.getInstance().world):null); diff --git a/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java b/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java index 66958ac..9cabdf9 100644 --- a/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java @@ -1,7 +1,5 @@ package me.cortex.vulkanite.lib.cmd; -import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; - import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; @@ -18,6 +16,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; +import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; import static org.lwjgl.vulkan.VK12.vkWaitSemaphores; @@ -27,14 +26,11 @@ public class CommandManager { private final VkDevice device; private final Queue[] queues; private final ThreadLocal> threadLocalPool = - new ThreadLocal<>() { - @Override - protected VRef initialValue() { - var pool = createSingleUsePool(); - pool.get().setDebugUtilsObjectName("Thread-local single use pool"); - return pool; - } - }; + ThreadLocal.withInitial(() -> { + var pool = createSingleUsePool(); + pool.get().setDebugUtilsObjectName("Thread-local single use pool"); + return pool; + }); public CommandManager(VkDevice device, int queues) { this.device = device; @@ -69,6 +65,7 @@ public void executeWait(Consumer cmdbuf) { /** * Enqueues a wait for a timeline value on a queue + * * @param waitQueueId The queue that will wait * @param executionQueueId The queue whose timeline value will be waited for * @param execution The timeline value to wait for @@ -79,6 +76,7 @@ public void queueWaitForExeuction(int waitQueueId, int executionQueueId, long ex /** * Wait on the host for a timeline value on a queue + * * @param waitQueueId The queue whose timeline value will be waited for * @param execution The timeline value to wait for */ @@ -125,12 +123,12 @@ public synchronized void newFrame() { private static class Queue { public final VkQueue queue; - public final Multimap waitingFor = Multimaps.synchronizedMultimap(HashMultimap.create()); + public final Multimap waitingFor = Multimaps.synchronizedMultimap(HashMultimap.create()); public final ConcurrentHashMap> submitted = new ConcurrentHashMap<>(); - public AtomicLong timeline = new AtomicLong(1); - public long completedTimestamp = 0; public final VRef timelineSema; public final Deque frameTimestamps = new ArrayDeque<>(3); + public AtomicLong timeline = new AtomicLong(1); + public long completedTimestamp = 0; public Queue(int queueId, VkDevice device) { try (var stack = stackPush()) { diff --git a/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java b/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java index e855cc2..5e395a0 100644 --- a/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java +++ b/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java @@ -14,7 +14,6 @@ import me.cortex.vulkanite.lib.other.sync.VSemaphore; import me.cortex.vulkanite.lib.pipeline.VComputePipeline; import me.cortex.vulkanite.lib.pipeline.VRaytracePipeline; -import org.lwjgl.system.Pointer; import org.lwjgl.vulkan.*; import org.lwjgl.system.MemoryUtil; @@ -34,7 +33,7 @@ public class VCmdBuff extends VObject { private final VCommandPool pool; private VkCommandBuffer buffer; - private final List> queryPoolRefs = new ArrayList<>(); + @SuppressWarnings("FieldCanBeLocal") private final List> refs = new ArrayList<>(); public void addBufferRef(final VRef buffer) { @@ -138,7 +137,7 @@ public void dispatch(int x, int y, int z) { public void resetQueryPool(final VRef queryPool, int first, int size) { vkCmdResetQueryPool(buffer, queryPool.get().pool, first, size); - queryPoolRefs.add(queryPool.addRef()); + refs.add(queryPool.addRefGeneric()); } public void encodeDataUpload(MemoryManager manager, long src, final VRef dest, long destOffset, long size) { From 65d6abccbf2e0d57236269e91b6fcb2865f14896 Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Mon, 12 Feb 2024 23:33:23 -0800 Subject: [PATCH 06/22] Code cleanups --- .../acceleration/EntityBlasBuilder.java | 4 ++-- .../client/rendering/VulkanPipeline.java | 11 +-------- .../vulkanite/lib/cmd/CommandManager.java | 24 +++++++++---------- .../me/cortex/vulkanite/lib/cmd/VCmdBuff.java | 5 ++-- 4 files changed, 16 insertions(+), 28 deletions(-) diff --git a/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java b/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java index 8df8ad9..42c682b 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java @@ -70,7 +70,7 @@ Pair, VRef> buildBlas(List blas = null; + VRef blas; try (var stack = MemoryStack.stackPush()) { int[] primitiveCounts = new int[infos.size()]; var buildInfo = populateBuildStructs(ctx, stack, cmd, infos, primitiveCounts); @@ -156,7 +156,7 @@ private static VRef executeBlasBuild(VContext ctx, VCmdB vkCmdBuildAccelerationStructuresKHR(cmd.buffer(), buildInfos, stack.pointers(buildRanges)); - vkCmdPipelineBarrier(cmd.buffer(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, VkMemoryBarrier.calloc(1) + vkCmdPipelineBarrier(cmd.buffer(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, VkMemoryBarrier.calloc(1, stack) .sType$Default() .srcAccessMask(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR) .dstAccessMask(VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR), null, null); diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java index 4511904..098f17a 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java @@ -55,7 +55,7 @@ public class VulkanPipeline { private final AccelerationManager accelerationManager; private record RtPipeline(VRef pipeline, int commonSet, int geomSet, int customTexSet, int ssboSet) {} - private ArrayList raytracePipelines = new ArrayList<>(); + private final ArrayList raytracePipelines = new ArrayList<>(); private final VRef sampler; private final VRef ctexSampler; @@ -71,8 +71,6 @@ private record RtPipeline(VRef pipeline, int commonSet, int g private final VRef placeholderNormals; private final VRef placeholderNormalsView; - private int fidx; - private final int maxIrisRenderTargets = 16; private final boolean supportsEntities; @@ -229,9 +227,6 @@ public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, Ray } } - private VSemaphore previousSemaphore; - - private final EntityCapture capture = new EntityCapture(); private void buildEntities() { accelerationManager.setEntityData(supportsEntities?capture.capture(CapturedRenderingState.INSTANCE.getTickDelta(), MinecraftClient.getInstance().world):null); @@ -415,10 +410,6 @@ public void renderPostShadows(List> vgOutImgs, Camera camera, Shad out.get().glWait(new int[0], outImgsGlIds, outImgsGlLayouts); glFlush(); - - fidx++; - fidx %= 10; - } public void destory() { diff --git a/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java b/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java index 66958ac..9cabdf9 100644 --- a/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java @@ -1,7 +1,5 @@ package me.cortex.vulkanite.lib.cmd; -import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; - import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; @@ -18,6 +16,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; +import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; import static org.lwjgl.vulkan.VK12.vkWaitSemaphores; @@ -27,14 +26,11 @@ public class CommandManager { private final VkDevice device; private final Queue[] queues; private final ThreadLocal> threadLocalPool = - new ThreadLocal<>() { - @Override - protected VRef initialValue() { - var pool = createSingleUsePool(); - pool.get().setDebugUtilsObjectName("Thread-local single use pool"); - return pool; - } - }; + ThreadLocal.withInitial(() -> { + var pool = createSingleUsePool(); + pool.get().setDebugUtilsObjectName("Thread-local single use pool"); + return pool; + }); public CommandManager(VkDevice device, int queues) { this.device = device; @@ -69,6 +65,7 @@ public void executeWait(Consumer cmdbuf) { /** * Enqueues a wait for a timeline value on a queue + * * @param waitQueueId The queue that will wait * @param executionQueueId The queue whose timeline value will be waited for * @param execution The timeline value to wait for @@ -79,6 +76,7 @@ public void queueWaitForExeuction(int waitQueueId, int executionQueueId, long ex /** * Wait on the host for a timeline value on a queue + * * @param waitQueueId The queue whose timeline value will be waited for * @param execution The timeline value to wait for */ @@ -125,12 +123,12 @@ public synchronized void newFrame() { private static class Queue { public final VkQueue queue; - public final Multimap waitingFor = Multimaps.synchronizedMultimap(HashMultimap.create()); + public final Multimap waitingFor = Multimaps.synchronizedMultimap(HashMultimap.create()); public final ConcurrentHashMap> submitted = new ConcurrentHashMap<>(); - public AtomicLong timeline = new AtomicLong(1); - public long completedTimestamp = 0; public final VRef timelineSema; public final Deque frameTimestamps = new ArrayDeque<>(3); + public AtomicLong timeline = new AtomicLong(1); + public long completedTimestamp = 0; public Queue(int queueId, VkDevice device) { try (var stack = stackPush()) { diff --git a/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java b/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java index e855cc2..5e395a0 100644 --- a/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java +++ b/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java @@ -14,7 +14,6 @@ import me.cortex.vulkanite.lib.other.sync.VSemaphore; import me.cortex.vulkanite.lib.pipeline.VComputePipeline; import me.cortex.vulkanite.lib.pipeline.VRaytracePipeline; -import org.lwjgl.system.Pointer; import org.lwjgl.vulkan.*; import org.lwjgl.system.MemoryUtil; @@ -34,7 +33,7 @@ public class VCmdBuff extends VObject { private final VCommandPool pool; private VkCommandBuffer buffer; - private final List> queryPoolRefs = new ArrayList<>(); + @SuppressWarnings("FieldCanBeLocal") private final List> refs = new ArrayList<>(); public void addBufferRef(final VRef buffer) { @@ -138,7 +137,7 @@ public void dispatch(int x, int y, int z) { public void resetQueryPool(final VRef queryPool, int first, int size) { vkCmdResetQueryPool(buffer, queryPool.get().pool, first, size); - queryPoolRefs.add(queryPool.addRef()); + refs.add(queryPool.addRefGeneric()); } public void encodeDataUpload(MemoryManager manager, long src, final VRef dest, long destOffset, long size) { From d9d1b133ff4c243f84c218ca5e01c98eaae9773b Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Wed, 14 Feb 2024 19:12:32 -0800 Subject: [PATCH 07/22] A lot more working and wastes a lot less VRAM --- .../acceleration/AccelerationBlasBuilder.java | 94 ++++++++++--------- .../acceleration/AccelerationTLASManager.java | 17 ++-- .../acceleration/EntityBlasBuilder.java | 6 +- .../acceleration/SharedQuadVkIndexBuffer.java | 4 +- .../rendering/SharedImageViewTracker.java | 2 +- .../client/rendering/VulkanPipeline.java | 45 ++++++--- .../me/cortex/vulkanite/lib/base/VObject.java | 9 +- .../me/cortex/vulkanite/lib/base/VRef.java | 17 +++- .../cortex/vulkanite/lib/base/VRegistry.java | 83 ++++++++++++++++ .../vulkanite/lib/cmd/CommandManager.java | 37 ++++++-- .../me/cortex/vulkanite/lib/cmd/VCmdBuff.java | 11 ++- .../vulkanite/lib/cmd/VCommandPool.java | 2 +- .../lib/descriptors/VDescriptorPool.java | 19 ++-- .../lib/descriptors/VDescriptorSet.java | 6 +- .../vulkanite/lib/memory/MemoryManager.java | 19 +++- .../lib/memory/PoolLinearAllocator.java | 68 ++++++++++++++ .../lib/memory/VAccelerationStructure.java | 1 + .../cortex/vulkanite/lib/memory/VBuffer.java | 16 +++- .../cortex/vulkanite/lib/memory/VGBuffer.java | 8 +- .../me/cortex/vulkanite/lib/other/VUtil.java | 3 + 20 files changed, 365 insertions(+), 102 deletions(-) create mode 100644 src/main/java/me/cortex/vulkanite/lib/base/VRegistry.java create mode 100644 src/main/java/me/cortex/vulkanite/lib/memory/PoolLinearAllocator.java diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java index b39dd3b..c3eedec 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java @@ -12,6 +12,7 @@ import me.cortex.vulkanite.lib.cmd.VCommandPool; import me.cortex.vulkanite.lib.descriptors.DescriptorSetLayoutBuilder; import me.cortex.vulkanite.lib.descriptors.VDescriptorSetLayout; +import me.cortex.vulkanite.lib.memory.PoolLinearAllocator; import me.cortex.vulkanite.lib.memory.VAccelerationStructure; import me.cortex.vulkanite.lib.memory.VBuffer; import me.cortex.vulkanite.lib.other.VQueryPool; @@ -136,7 +137,16 @@ void main() { private void run() { MemoryStack bigStack = MemoryStack.create(20_000_000); + var buildBufferAllocator = new PoolLinearAllocator(context, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT + | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR + | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, 0x200_0000L, 16); + var scratchAllocator = new PoolLinearAllocator(context, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + 0x200_0000L, 256); + var initialASBufferAllocator = new PoolLinearAllocator(context, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR, + 0x200_0000L, 256); + List jobs = new ArrayList<>(); + Deque priorExecutions = new ArrayDeque<>(3); while (true) { { jobs.clear(); @@ -188,29 +198,7 @@ private void run() { var maxPrims = stack.callocInt(job.geometries.size()); buildRanges.put(brs); - long buildBufferSize = 0; - - int vertexStride = 4 * 3; - for (var geometry : job.geometries) { - buildBufferSize += geometry.quadCount * 4L * vertexStride; - } - - if (buildBufferSize <= 0) { - throw new IllegalStateException("Build buffer size <= 0"); - } - - var buildBuffer = context.memory.createBuffer(buildBufferSize, - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT - | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR - | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - 0, 0); - buildBuffer.get().setDebugUtilsObjectName("BLAS geometry buffer"); - var buildBufferAddr = buildBuffer.get().deviceAddress(); - long buildBufferOffset = 0; - - uploadBuildCmd.encodeBufferBarrier(buildBuffer, 0, VK_WHOLE_SIZE, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + long vertexStride = 4 * 3; for (int geoIdx = 0; geoIdx < job.geometries.size(); geoIdx++) { var geometry = job.geometries.get(geoIdx); @@ -218,6 +206,12 @@ private void run() { var geometryInfo = geometryInfos.get().sType$Default(); var br = brs.get(); + long buildBufferSize = geometry.quadCount * 4L * vertexStride; + var buildBuffer = buildBufferAllocator.allocate(buildBufferSize); + + uploadBuildCmd.encodeBufferBarrier(buildBuffer.buffer(), buildBuffer.offset(), buildBuffer.size(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + // We know the geometry data has been uploaded // 0: n_vertices // 1: inAddr @@ -226,7 +220,7 @@ private void run() { var geometryInputBuffer = job.data.geometryBuffers().get(geoIdx); pushConstant[0] = geometry.quadCount * 4L; pushConstant[1] = geometryInputBuffer.get().deviceAddress(); - pushConstant[2] = buildBufferAddr + buildBufferOffset; + pushConstant[2] = buildBuffer.deviceAddress(); if (pushConstant[1] == 0) { throw new IllegalStateException("Geometry input buffer address is 0"); } @@ -238,13 +232,19 @@ private void run() { VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); uploadBuildCmd.dispatch(Math.min((geometry.quadCount * 4 + 255) / 256, 256), 1, 1); - VkDeviceOrHostAddressConstKHR indexData = SharedQuadVkIndexBuffer.getIndexBuffer(context, + uploadBuildCmd.encodeBufferBarrier(buildBuffer.buffer(), buildBuffer.offset(), buildBuffer.size(), VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR); + + var indexBuffer = SharedQuadVkIndexBuffer.getIndexBuffer(context, uploadBuildCmd, Integer.max(geometry.quadCount, 30000)); + VkDeviceOrHostAddressConstKHR indexData = indexBuffer.get().deviceAddressConst(); int indexType = SharedQuadVkIndexBuffer.TYPE; + uploadBuildCmd.addBufferRef(indexBuffer); + VkDeviceOrHostAddressConstKHR vertexData = VkDeviceOrHostAddressConstKHR.calloc(stack) - .deviceAddress(buildBufferAddr + buildBufferOffset); + .deviceAddress(buildBuffer.deviceAddress()); int vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; geometryInfo.geometry(VkAccelerationStructureGeometryDataKHR.calloc(stack) @@ -265,12 +265,8 @@ private void run() { br.primitiveCount(geometry.quadCount * 2); //maxPrims.put(2); //br.primitiveCount(2); - - buildBufferOffset += geometry.quadCount * 4L * vertexStride; } - uploadBuildCmd.encodeBufferBarrier(buildBuffer, 0, VK_WHOLE_SIZE, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR); geometryInfos.rewind(); maxPrims.rewind(); @@ -294,21 +290,17 @@ private void run() { buildSizesInfo); - var structure = context.memory.createAcceleration(buildSizesInfo.accelerationStructureSize(), 256, - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR); + var backingBuffer = initialASBufferAllocator.allocate(buildSizesInfo.accelerationStructureSize()); + var structure = context.memory.createAcceleration(backingBuffer.buffer(), backingBuffer.offset(), backingBuffer.size(), VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR); - var scratch = context.memory.createBuffer(buildSizesInfo.buildScratchSize(), - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 256, 0); - scratch.get().setDebugUtilsObjectName("BLAS scratch buffer"); - - bi.scratchData(VkDeviceOrHostAddressKHR.calloc(stack).deviceAddress(scratch.get().deviceAddress())); + var scratch = scratchAllocator.allocate(buildSizesInfo.buildScratchSize()); + uploadBuildCmd.addBufferRef(scratch.buffer()); + bi.scratchData(VkDeviceOrHostAddressKHR.calloc(stack).deviceAddress(scratch.deviceAddress())); bi.dstAccelerationStructure(structure.get().structure); pAccelerationStructures.put(structure.get().structure); accelerationStructures.add(structure); - uploadBuildCmd.addBufferRef(scratch); } buildInfos.rewind(); @@ -333,6 +325,7 @@ private void run() { // Waiting on a semaphore is realistically the easiest thing to do rn context.cmd.hostWaitForExecution(asyncQueue, buildExecution); + uploadBuildCmdRef.close(); } long[] compactedSizes = queryPool.get().getResultsLong(jobs.size()); @@ -348,24 +341,36 @@ private void run() { // Dont need a memory barrier cause submit ensures cache flushing already for (int idx = 0; idx < compactedSizes.length; idx++) { - var as = context.memory.createAcceleration(compactedSizes[idx], 256, + var compact_as = context.memory.createAcceleration(compactedSizes[idx], 256, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR); + var fat_as = accelerationStructures.get(idx); vkCmdCopyAccelerationStructureKHR(cmdRef.get().buffer(), VkCopyAccelerationStructureInfoKHR.calloc(stack).sType$Default() - .src(accelerationStructures.get(idx).get().structure) - .dst(as.get().structure) + .src(fat_as.get().structure) + .dst(compact_as.get().structure) .mode(VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR)); + cmdRef.get().addAccelerationStructureRef(fat_as); + cmdRef.get().addAccelerationStructureRef(compact_as); + fat_as.close(); + var job = jobs.get(idx); - results.add(new BLASBuildResult(as, job.data)); + results.add(new BLASBuildResult(compact_as, job.data)); } blasExecution = context.cmd.submit(asyncQueue, cmdRef); + cmdRef.close(); } + accelerationStructures.forEach(VRef::close); + resultConsumer.accept(new BLASBatchResult(results, blasExecution)); - context.cmd.hostWaitForExecution(asyncQueue, blasExecution); + priorExecutions.add(blasExecution); + if (priorExecutions.size() > 3) { + long prior = priorExecutions.poll(); + context.cmd.hostWaitForExecution(asyncQueue, prior); + } } } } @@ -423,6 +428,7 @@ public void enqueue(List batch) { // Should we move all uploads to the worker? context.cmd.submitOnceAndWait(1, cmd); } + cmd.close(); if (jobs.isEmpty()) { return; // No jobs to do diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java index 395527a..13bb48f 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java @@ -184,9 +184,13 @@ public void buildTLAS(VCmdBuff cmd) { buildInfo, stack.pointers(buildRanges)); cmd.addBufferRef(scratchBuffer); + scratchBuffer.close(); cmd.encodeMemoryBarrier(); + if (currentTLAS != null) { + currentTLAS.close(); + } currentTLAS = tlas; } } @@ -326,7 +330,6 @@ public TLASSectionManager() { } private VRef geometryBufferSetLayout; - private VRef geometryBufferDescPool; private VRef geometryBufferDescSet = null; private int setCapacity = 0; @@ -339,7 +342,6 @@ private record ArenaDeallocJob(int index, int count, List> geometr private final ConcurrentLinkedDeque descUpdateJobs = new ConcurrentLinkedDeque<>(); private final ConcurrentLinkedDeque arenaDeallocJobs = new ConcurrentLinkedDeque<>(); - private final Deque> descPoolsToRelease = new ArrayDeque<>(); public void resizeBindlessSet(int newSize) { if (geometryBufferSetLayout == null) { @@ -355,8 +357,8 @@ public void resizeBindlessSet(int newSize) { if (newSize > setCapacity) { int newCapacity = roundUpPow2(Math.max(newSize, 32)); - var newGeometryBufferDescPool = VDescriptorPool.create(context, geometryBufferSetLayout, VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, newCapacity); - var newGeometryBufferDescSet = newGeometryBufferDescPool.get().allocateSet(newCapacity); + var geometryBufferDescPool = VDescriptorPool.create(context, geometryBufferSetLayout, VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, newCapacity); + var newGeometryBufferDescSet = geometryBufferDescPool.get().allocateSet(newCapacity); System.out.println("New geometry desc set: " + Long.toHexString(newGeometryBufferDescSet.get().set) + " with capacity " + newCapacity); @@ -371,11 +373,8 @@ public void resizeBindlessSet(int newSize) { .descriptorCount(setCapacity); vkUpdateDescriptorSets(context.device, null, setCopy); } - - descPoolsToRelease.add(geometryBufferDescPool); } - geometryBufferDescPool = newGeometryBufferDescPool; geometryBufferDescSet = newGeometryBufferDescSet; setCapacity = newCapacity; } @@ -429,9 +428,9 @@ public void fenceTick() { while (!arenaDeallocJobs.isEmpty()) { var job = arenaDeallocJobs.poll(); arena.free(job.index, job.count); + job.geometryBuffers.forEach(VRef::close); job.geometryBuffers.clear(); } - descPoolsToRelease.clear(); } public void update(AccelerationBlasBuilder.BLASBuildResult result) { @@ -519,7 +518,7 @@ public void free(int pos, int count) { } public VRef getGeometrySet() { - return buildDataManager.geometryBufferDescSet; + return buildDataManager.geometryBufferDescSet.addRef(); } public VRef getGeometryLayout() { diff --git a/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java b/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java index 42c682b..25d838d 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java @@ -65,6 +65,7 @@ Pair, VRef> buildBlas(List indexBuffer = null; private static int currentQuadCount = 0; - public synchronized static VkDeviceOrHostAddressConstKHR getIndexBuffer(VContext context, VCmdBuff uploaCmdBuff, int quadCount) { + public synchronized static VRef getIndexBuffer(VContext context, VCmdBuff uploaCmdBuff, int quadCount) { if (currentQuadCount < quadCount) { makeNewIndexBuffer(context, uploaCmdBuff, quadCount); } - return indexBuffer.get().deviceAddressConst(); + return indexBuffer.addRef(); } private static void makeNewIndexBuffer(VContext context, VCmdBuff uploaCmdBuff, int quadCount) { diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/SharedImageViewTracker.java b/src/main/java/me/cortex/vulkanite/client/rendering/SharedImageViewTracker.java index 07fb9df..6e39a6a 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/SharedImageViewTracker.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/SharedImageViewTracker.java @@ -32,7 +32,7 @@ public VRef getView() { public VRef getView(Supplier> imageSupplier) { VRef image = imageSupplier.get(); - if (view == null || view.get().isDerivedFrom(image.get())) { + if (view == null || (!view.get().isDerivedFrom(image.get()))) { //TODO: move this to like a fence free that you pass in via an arg if (image != null) { view = VImageView.create(ctx, new VRef<>(image.get())); diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java index 098f17a..0b027ed 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java @@ -7,10 +7,12 @@ import me.cortex.vulkanite.compat.RaytracingShaderSet; import me.cortex.vulkanite.lib.base.VContext; import me.cortex.vulkanite.lib.base.VRef; +import me.cortex.vulkanite.lib.base.VRegistry; import me.cortex.vulkanite.lib.cmd.VCmdBuff; import me.cortex.vulkanite.lib.cmd.VCommandPool; import me.cortex.vulkanite.lib.descriptors.DescriptorUpdateBuilder; import me.cortex.vulkanite.lib.descriptors.VDescriptorSet; +import me.cortex.vulkanite.lib.memory.PoolLinearAllocator; import me.cortex.vulkanite.lib.memory.VBuffer; import me.cortex.vulkanite.lib.memory.VGImage; import me.cortex.vulkanite.lib.memory.VImage; @@ -75,6 +77,8 @@ private record RtPipeline(VRef pipeline, int commonSet, int g private final boolean supportsEntities; + private final PoolLinearAllocator uboAllocator; + public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, RaytracingShaderSet[] passes, int[] ssboIds, List> customTextures) { this.ctx = ctx; this.accelerationManager = accelerationManager; @@ -150,6 +154,10 @@ public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, Ray .borderColor(VK_BORDER_COLOR_INT_OPAQUE_BLACK) .maxAnisotropy(1.0f)); + this.uboAllocator = new PoolLinearAllocator(ctx, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + 32 * 1024, + 0, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); + if (passes == null) { supportsEntities = false; return; @@ -235,6 +243,8 @@ private void buildEntities() { public void renderPostShadows(List> vgOutImgs, Camera camera, ShaderStorageBuffer[] ssbos, MixinCelestialUniforms celestialUniforms) { ctx.cmd.newFrame(); + System.out.println(VRegistry.INSTANCE.dumpStats()); + buildEntities(); PBRTextureManager.notifyPBRTexturesChanged(); @@ -243,7 +253,7 @@ public void renderPostShadows(List> vgOutImgs, Camera camera, Shad var outImgsGlIds = vgOutImgs.stream().mapToInt(i -> i.get().glId).toArray(); var outImgsGlLayouts = vgOutImgs.stream().mapToInt(i -> GL_LAYOUT_GENERAL_EXT).toArray(); in.get().glSignal(new int[0], outImgsGlIds, outImgsGlLayouts); - glFlush(); + // glFlush(); var cmdRef = ctx.cmd.getSingleUsePool().createCommandBuffer(); var cmd = cmdRef.get(); @@ -258,14 +268,13 @@ public void renderPostShadows(List> vgOutImgs, Camera camera, Shad var outImgs = vgOutImgs.stream().map(i -> new VRef(i.get())).toList(); var out = ctx.sync.createSharedBinarySemaphore(); - VRef uboBuffer; + + var vref_in = new VRef(in.get()); + var vref_out = new VRef(out.get()); + + var uboBuffer = uboAllocator.allocate(1024); { - uboBuffer = ctx.memory.createBuffer(1024, - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - 0, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); - uboBuffer.get().setDebugUtilsObjectName("VulkanPipeline UBO"); - long ptr = uboBuffer.get().map(); + long ptr = uboBuffer.buffer().get().map(); MemoryUtil.memSet(ptr, 0, 1024); { ByteBuffer bb = MemoryUtil.memByteBuffer(ptr, 1024); @@ -292,8 +301,8 @@ public void renderPostShadows(List> vgOutImgs, Camera camera, Shad bb.putInt(Float.BYTES * 41, flags); bb.rewind(); } - uboBuffer.get().unmap(); - uboBuffer.get().flush(); + uboBuffer.buffer().get().unmap(); + uboBuffer.buffer().get().flush(); // Call getView() on shared image view trackers to ensure they are created blockAtlasView.getView(); @@ -334,7 +343,7 @@ public void renderPostShadows(List> vgOutImgs, Camera camera, Shad var updater = new DescriptorUpdateBuilder(ctx, pipeline.get().reflection.getSet(record.commonSet)) .set(commonSet) - .uniform(0, uboBuffer) + .uniform(0, uboBuffer.buffer(), uboBuffer.offset(), uboBuffer.size()) .acceleration(1, tlas) .imageSampler(3, blockAtlasView.getView(), sampler) .imageSampler(4, @@ -384,6 +393,7 @@ public void renderPostShadows(List> vgOutImgs, Camera camera, Shad } cmd.bindDSet(sets); cmd.traceRays(outImgs.get(0).get().width, outImgs.get(0).get().height, 1); + sets.forEach(VRef::close); // Barrier on the output images for (var img : outImgs) { @@ -405,15 +415,24 @@ public void renderPostShadows(List> vgOutImgs, Camera camera, Shad } } - ctx.cmd.submit(0, cmdRef, Arrays.asList(new VRef<>(in.get())), Arrays.asList(new VRef<>(out.get())), null); + ctx.cmd.submit(0, cmdRef, Arrays.asList(vref_in), Arrays.asList(vref_out), null); } + cmdRef.close(); + tlas.close(); + out.get().glWait(new int[0], outImgsGlIds, outImgsGlLayouts); - glFlush(); + // glFlush(); + vref_in.close(); + vref_out.close(); + in.close(); + out.close(); } public void destory() { vkDeviceWaitIdle(ctx.device); + ctx.cmd.newFrame(); + System.gc(); } diff --git a/src/main/java/me/cortex/vulkanite/lib/base/VObject.java b/src/main/java/me/cortex/vulkanite/lib/base/VObject.java index e4cf033..7c6cfc1 100644 --- a/src/main/java/me/cortex/vulkanite/lib/base/VObject.java +++ b/src/main/java/me/cortex/vulkanite/lib/base/VObject.java @@ -5,14 +5,19 @@ public abstract class VObject { protected abstract void free(); - private final AtomicLong refCount = new AtomicLong(0); + protected final AtomicLong refCount = new AtomicLong(0); protected void incRef() { - refCount.incrementAndGet(); + if (refCount.incrementAndGet() == 1) { + // First reference, put into registry + // So that the object is kept alive until we finish running `free()` + VRegistry.INSTANCE.register(this); + } } protected void decRef() { if (refCount.decrementAndGet() == 0) { free(); + VRegistry.INSTANCE.unregister(this); } } } diff --git a/src/main/java/me/cortex/vulkanite/lib/base/VRef.java b/src/main/java/me/cortex/vulkanite/lib/base/VRef.java index 95b0e22..9426c6b 100644 --- a/src/main/java/me/cortex/vulkanite/lib/base/VRef.java +++ b/src/main/java/me/cortex/vulkanite/lib/base/VRef.java @@ -22,12 +22,27 @@ public void run() { } } + private final Cleaner.Cleanable cleanable; + public VRef(T ref) { + if (ref == null) { + throw new NullPointerException("VRef to null object"); + } ref.incRef(); this.ref = ref; - cleaner.register(this, new State(ref)); + cleanable = cleaner.register(this, new State(ref)); } + /** + * (Optional) Decrement the reference count and release the object if the reference count reaches 0. + * This method can be called multiple times, but the object will only be released once. + * If this method is not called, the object will be released when the VRef is garbage collected. + */ + public void close() { + cleanable.clean(); + } + + @NotNull public T get() { return ref; } diff --git a/src/main/java/me/cortex/vulkanite/lib/base/VRegistry.java b/src/main/java/me/cortex/vulkanite/lib/base/VRegistry.java new file mode 100644 index 0000000..b312444 --- /dev/null +++ b/src/main/java/me/cortex/vulkanite/lib/base/VRegistry.java @@ -0,0 +1,83 @@ +package me.cortex.vulkanite.lib.base; + +import com.google.common.collect.ConcurrentHashMultiset; +import me.cortex.vulkanite.lib.memory.VBuffer; + +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR; +import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR; +import static org.lwjgl.vulkan.KHRRayTracingPipeline.VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR; +import static org.lwjgl.vulkan.VK10.*; +import static org.lwjgl.vulkan.VK12.VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + +public class VRegistry { + public static final VRegistry INSTANCE = new VRegistry(); + + private final ConcurrentHashMultiset objects = ConcurrentHashMultiset.create(); + + private VRegistry() { + } + + public void register(VObject object) { + objects.add(object); + } + + public void unregister(VObject object) { + objects.remove(object); + } + + private static final HashMap usageNames = new HashMap<>() {{ + put(VK_BUFFER_USAGE_TRANSFER_DST_BIT, "TRANSFER_DST"); + put(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, "TRANSFER_SRC"); + put(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, "UNIFORM_BUFFER"); + put(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, "STORAGE_BUFFER"); + put(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, "INDEX_BUFFER"); + put(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, "VERTEX_BUFFER"); + put(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, "SHADER_DEVICE_ADDRESS"); + put(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, "ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY"); + put(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR, "ACCELERATION_STRUCTURE_STORAGE"); + put(VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR, "SHADER_BINDING_TABLE"); + }}; + + public String dumpStats() { + final StringBuilder sb = new StringBuilder(); + + sb.append("VRegistry: ").append(objects.size()).append(" objects\n"); + sb.append("Objects:\n"); + + Map typeCount = new TreeMap<>(); + for (VObject object : objects) { + var key = object.getClass().getTypeName(); + typeCount.put(key, typeCount.getOrDefault(key, 0) + 1); + } + + for (String type : typeCount.keySet()) { + sb.append(" ").append(type).append(": ").append(typeCount.get(type)).append("\n"); + } + + Map bufferUsage = new TreeMap<>(); + for (VObject object : objects) { + if (object instanceof VBuffer buffer) { + var usage = buffer.usage(); + bufferUsage.put(usage, bufferUsage.getOrDefault(usage, 0) + 1); + } + } + + sb.append("Buffer Count Per Usage:\n"); + for (int usage : bufferUsage.keySet()) { + sb.append(" ").append(usage).append(": ").append(bufferUsage.get(usage)).append("\n"); + sb.append(" ("); + usageNames.forEach((key, value) -> { + if ((usage & key) != 0) { + sb.append(value).append(", "); + } + }); + sb.append(")\n"); + } + + return sb.toString(); + } +} diff --git a/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java b/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java index 9cabdf9..39c4e86 100644 --- a/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java @@ -19,6 +19,7 @@ import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; +import static org.lwjgl.vulkan.VK12.vkGetSemaphoreCounterValue; import static org.lwjgl.vulkan.VK12.vkWaitSemaphores; //Manages multiple command queues and fence synchronizations @@ -55,6 +56,7 @@ public VCommandPool getSingleUsePool() { public void submitOnceAndWait(int queueId, final VRef cmdBuff) { long exec = this.submit(queueId, cmdBuff); this.hostWaitForExecution(queueId, exec); + cmdBuff.close(); } public void executeWait(Consumer cmdbuf) { @@ -99,6 +101,10 @@ public void hostWaitForExecution(int waitQueueId, long execution) { waitQueue.collect(); } + public long getQueueCurrentExecution(int queueId) { + return queues[queueId].getCurrentExecution(); + } + public long submit(int queueId, final VRef cmdBuff) { return submit(queueId, cmdBuff, null, null, null); } @@ -115,7 +121,7 @@ public void waitQueueIdle(int queue) { queues[queue].collect(); } - public synchronized void newFrame() { + public void newFrame() { for (var queue : queues) { queue.newFrame(); } @@ -126,7 +132,7 @@ private static class Queue { public final Multimap waitingFor = Multimaps.synchronizedMultimap(HashMultimap.create()); public final ConcurrentHashMap> submitted = new ConcurrentHashMap<>(); public final VRef timelineSema; - public final Deque frameTimestamps = new ArrayDeque<>(3); +// public final Deque frameTimestamps = new ArrayDeque<>(3); public AtomicLong timeline = new AtomicLong(1); public long completedTimestamp = 0; @@ -153,17 +159,25 @@ public Queue(int queueId, VkDevice device) { } public void newFrame() { - if (frameTimestamps.size() >= 3) { - long oldest = frameTimestamps.removeFirst(); - completedTimestamp = Long.max(completedTimestamp, oldest); - } - frameTimestamps.addLast(completedTimestamp); +// if (frameTimestamps.size() >= 3) { +// long oldest = frameTimestamps.removeFirst(); +// completedTimestamp = Long.max(completedTimestamp, oldest); +// } +// frameTimestamps.addLast(completedTimestamp); + completedTimestamp = Long.max(completedTimestamp, getCurrentExecution()); collect(); } public void collect() { synchronized (this) { + for (var entry : submitted.entrySet()) { + if (entry.getKey() <= completedTimestamp) { + // We know it's gone, we can early-close it + // So that we don't need to wait for GC + entry.getValue().close(); + } + } for (var key : submitted.keySet()) { if (key <= completedTimestamp) { submitted.remove(key); @@ -177,6 +191,7 @@ public void waitIdle() { synchronized (this) { waitingFor.clear(); + submitted.forEach((k, v) -> v.close()); submitted.clear(); completedTimestamp = timeline.get() - 1; } @@ -261,5 +276,13 @@ public long submit(final VRef cmdBuff, Queue[] queues, List pool; private VkCommandBuffer buffer; @SuppressWarnings("FieldCanBeLocal") @@ -52,7 +52,7 @@ public void addAccelerationStructureRef(final VRef accel refs.add(accelerationStructure.addRefGeneric()); } - protected VCmdBuff(VCommandPool pool, VkCommandBuffer buff, int flags) { + protected VCmdBuff(VRef pool, VkCommandBuffer buff, int flags) { this.pool = pool; this.buffer = buff; @@ -157,6 +157,8 @@ public void encodeDataUpload(MemoryManager manager, long src, final VRef dest, long srcSize, int destLayout) { @@ -179,6 +181,8 @@ public void encodeImageUpload(MemoryManager manager, long src, final VRef image, int src, int dst, int aspe } protected void free() { - vkFreeCommandBuffers(pool.device, pool.pool, buffer); + vkFreeCommandBuffers(pool.get().device, pool.get().pool, buffer == null ? finalizedBuffer : buffer); + refs.forEach(VRef::close); refs.clear(); } diff --git a/src/main/java/me/cortex/vulkanite/lib/cmd/VCommandPool.java b/src/main/java/me/cortex/vulkanite/lib/cmd/VCommandPool.java index 974344a..088f90a 100644 --- a/src/main/java/me/cortex/vulkanite/lib/cmd/VCommandPool.java +++ b/src/main/java/me/cortex/vulkanite/lib/cmd/VCommandPool.java @@ -59,7 +59,7 @@ public synchronized List> createCommandBuffers(int count, int lev "Failed to create command buffer"); List> buffers = new ArrayList<>(); for (int i = 0; i < count; i++) { - buffers.add(new VRef<>(new VCmdBuff(this, new VkCommandBuffer(pCommandBuffer.get(i), device), flags))); + buffers.add(new VRef<>(new VCmdBuff(new VRef<>(this), new VkCommandBuffer(pCommandBuffer.get(i), device), flags))); } return buffers; } diff --git a/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorPool.java b/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorPool.java index 0f2b45c..c2181c1 100644 --- a/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorPool.java +++ b/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorPool.java @@ -14,6 +14,7 @@ import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; +import static org.lwjgl.vulkan.VK11.VK_ERROR_OUT_OF_POOL_MEMORY; public class VDescriptorPool extends VObject { private final VContext ctx; @@ -22,22 +23,23 @@ public class VDescriptorPool extends VObject { private final VRef layout; private final int flags; - private static final int nSetsPerPool = 16; + private final int nSetsPerPool; private final int countPerType; - private VDescriptorPool(VContext ctx, VRef layout, int flags, int countPerType) { + private VDescriptorPool(VContext ctx, VRef layout, int flags, int nSetsPerPool, int countPerType) { this.ctx = ctx; this.layout = layout.addRef(); this.flags = flags; this.countPerType = countPerType; + this.nSetsPerPool = nSetsPerPool; } public static VRef create(VContext ctx, VRef layout, int flags) { - return new VRef<>(new VDescriptorPool(ctx, layout, flags, 1)); + return new VRef<>(new VDescriptorPool(ctx, layout, flags, 16, 1)); } public static VRef create(VContext ctx, VRef layout, int flags, int countPerType) { - return new VRef<>(new VDescriptorPool(ctx, layout, flags, countPerType)); + return new VRef<>(new VDescriptorPool(ctx, layout, flags, 1, countPerType)); } private void createNewPool() { @@ -76,10 +78,15 @@ public VRef allocateSet(int variableSize) { .pDescriptorCounts(stack.ints(variableSize)); allocInfo.pNext(variableCountInfo.address()); } - _CHECK_(vkAllocateDescriptorSets(ctx.device, allocInfo, pSet)); + int result = vkAllocateDescriptorSets(ctx.device, allocInfo, pSet); + if (result == VK_ERROR_OUT_OF_POOL_MEMORY) { + createNewPool(); + return allocateSet(variableSize); + } + _CHECK_(result); set = pSet.get(0); } - return new VRef<>(new VDescriptorSet(this, pool, set)); + return new VRef<>(new VDescriptorSet(new VRef<>(this), pool, set)); } public VRef allocateSet() { diff --git a/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSet.java b/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSet.java index de26443..986579d 100644 --- a/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSet.java +++ b/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSet.java @@ -7,13 +7,13 @@ import java.util.Map; public class VDescriptorSet extends VObject { - private final VDescriptorPool pool; + private final VRef pool; public final long poolHandle; public final long set; public Map> refs = new HashMap<>(); - protected VDescriptorSet(VDescriptorPool pool, long poolHandle, long set) { + protected VDescriptorSet(VRef pool, long poolHandle, long set) { this.pool = pool; this.poolHandle = poolHandle; this.set = set; @@ -21,6 +21,6 @@ protected VDescriptorSet(VDescriptorPool pool, long poolHandle, long set) { @Override protected void free() { - pool.freeSet(this); + pool.get().freeSet(this); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java b/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java index ddc3764..3f81d40 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java @@ -176,7 +176,7 @@ public VRef createSharedBuffer(long size, int usage, int properties) { int glId = glCreateBuffers(); glNamedBufferStorageMemEXT(glId, size, memoryObject, alloc.ai.offset()); _CHECK_GL_ERROR_(); - return VGBuffer.create(alloc, glId); + return VGBuffer.create(alloc, usage, glId); } } @@ -267,7 +267,7 @@ public VRef createBuffer(long size, int usage, int properties, long ali .usage(VMA_MEMORY_USAGE_AUTO) .requiredFlags(properties), alignment); - return VBuffer.create(alloc); + return VBuffer.create(alloc, usage); } } @@ -307,6 +307,21 @@ public VRef createAcceleration(long size, int alignment, } } + public VRef createAcceleration(VRef buffer, long offset, long size, int type) { + try (var stack = stackPush()) { + LongBuffer pAccelerationStructure = stack.mallocLong(1); + _CHECK_(vkCreateAccelerationStructureKHR(device, VkAccelerationStructureCreateInfoKHR + .calloc(stack) + .sType$Default() + .type(type) + .size(size) + .buffer(buffer.get().buffer()) + .offset(offset), null, pAccelerationStructure), + "Failed to create acceleration acceleration structure"); + return VAccelerationStructure.create(device, pAccelerationStructure.get(0), buffer); + } + } + public void dumpStats() { System.out.println("VMA JSON:\n" + allocator.dumpJson(false)); } diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/PoolLinearAllocator.java b/src/main/java/me/cortex/vulkanite/lib/memory/PoolLinearAllocator.java new file mode 100644 index 0000000..171db37 --- /dev/null +++ b/src/main/java/me/cortex/vulkanite/lib/memory/PoolLinearAllocator.java @@ -0,0 +1,68 @@ +package me.cortex.vulkanite.lib.memory; + +import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VRef; + +import java.util.Stack; + +import static org.lwjgl.vulkan.VK10.VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + +public class PoolLinearAllocator { + private final int usage; + private final int properties; + private final int vmaFlags; + private final long poolSize; + private final long alignment; + + private VRef buffer; + private long currentOffset; + + private final VContext ctx; + + public record BufferRegion(VRef buffer, long offset, long size, long deviceAddress) { } + + public PoolLinearAllocator(VContext ctx, int usage, long poolSize, long alignment) { + this(ctx, usage, poolSize, alignment, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0); + } + + public PoolLinearAllocator(VContext ctx, int usage, long poolSize, long alignment, int properties, int vmaFlags) { + this.ctx = ctx; + this.usage = usage; + this.poolSize = poolSize; + this.alignment = alignment; + this.properties = properties; + this.vmaFlags = vmaFlags; + + this.currentOffset = 0; + + newBuffer(poolSize); + } + + private void newBuffer(long size) { + var newBuffer = ctx.memory.createBuffer(size, usage, properties, alignment, 0); + if (buffer != null) { + buffer.close(); + } + buffer = newBuffer; + currentOffset = 0; + } + + public BufferRegion allocate(long size) { + if (currentOffset + size > poolSize) { + newBuffer(Long.max(poolSize, size)); + } + + long deviceAddress = buffer.get().hasDeviceAddress() ? buffer.get().deviceAddress() + currentOffset : 0; + BufferRegion region = new BufferRegion(buffer, currentOffset, size, deviceAddress); + currentOffset = (currentOffset + size + alignment - 1) & ~(alignment - 1); + + return region; + } + + public void reset() { + if (buffer != null) { + buffer.close(); + } + currentOffset = 0; + } +} diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/VAccelerationStructure.java b/src/main/java/me/cortex/vulkanite/lib/memory/VAccelerationStructure.java index 170aa40..fae00c9 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/VAccelerationStructure.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/VAccelerationStructure.java @@ -35,5 +35,6 @@ public static VRef create(VkDevice device, long structur public void free() { vkDestroyAccelerationStructureKHR(device, structure, null); + buffer.close(); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/VBuffer.java b/src/main/java/me/cortex/vulkanite/lib/memory/VBuffer.java index a113a22..851c913 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/VBuffer.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/VBuffer.java @@ -11,12 +11,13 @@ public class VBuffer extends VObject { private VmaAllocator.BufferAllocation allocation; private final VkDeviceOrHostAddressConstKHR deviceAddressConst; + private final int usage; - public static VRef create(VmaAllocator.BufferAllocation allocation) { - return new VRef<>(new VBuffer(allocation)); + public static VRef create(VmaAllocator.BufferAllocation allocation, int usage) { + return new VRef<>(new VBuffer(allocation, usage)); } - protected VBuffer(VmaAllocator.BufferAllocation allocation) { + protected VBuffer(VmaAllocator.BufferAllocation allocation, int usage) { this.allocation = allocation; if (allocation.deviceAddress != -1) { this.deviceAddressConst = VkDeviceOrHostAddressConstKHR.calloc() @@ -24,17 +25,26 @@ protected VBuffer(VmaAllocator.BufferAllocation allocation) { } else { this.deviceAddressConst = null; } + this.usage = usage; } public long buffer() { return allocation.buffer; } + public int usage() { + return usage; + } + protected void free() { allocation.free(); allocation = null; } + public boolean hasDeviceAddress() { + return allocation.deviceAddress != -1; + } + public long deviceAddress() { if (allocation.deviceAddress == -1) throw new IllegalStateException(); diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/VGBuffer.java b/src/main/java/me/cortex/vulkanite/lib/memory/VGBuffer.java index 5c9ba87..c6abd60 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/VGBuffer.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/VGBuffer.java @@ -10,14 +10,14 @@ public class VGBuffer extends VBuffer { public final int glId; private final long vkMemory; - protected VGBuffer(VmaAllocator.BufferAllocation allocation, int glId) { - super(allocation); + protected VGBuffer(VmaAllocator.BufferAllocation allocation, int usage, int glId) { + super(allocation, usage); this.glId = glId; this.vkMemory = allocation.ai.deviceMemory(); } - public static VRef create(VmaAllocator.BufferAllocation allocation, int glId) { - return new VRef<>(new VGBuffer(allocation, glId)); + public static VRef create(VmaAllocator.BufferAllocation allocation, int usage, int glId) { + return new VRef<>(new VGBuffer(allocation, usage, glId)); } @Override diff --git a/src/main/java/me/cortex/vulkanite/lib/other/VUtil.java b/src/main/java/me/cortex/vulkanite/lib/other/VUtil.java index 14654f7..c2e4773 100644 --- a/src/main/java/me/cortex/vulkanite/lib/other/VUtil.java +++ b/src/main/java/me/cortex/vulkanite/lib/other/VUtil.java @@ -13,6 +13,7 @@ import static org.lwjgl.vulkan.KHRSwapchain.VK_ERROR_OUT_OF_DATE_KHR; import static org.lwjgl.vulkan.KHRSwapchain.VK_SUBOPTIMAL_KHR; import static org.lwjgl.vulkan.VK10.*; +import static org.lwjgl.vulkan.VK11.VK_ERROR_OUT_OF_POOL_MEMORY; public class VUtil { public static String translateVulkanResult(int result) { @@ -38,6 +39,8 @@ public static String translateVulkanResult(int result) { return "A host memory allocation has failed."; case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "A device memory allocation has failed."; + case VK_ERROR_OUT_OF_POOL_MEMORY: + return "A descriptor pool memory allocation has failed."; case VK_ERROR_INITIALIZATION_FAILED: return "Initialization of an object could not be completed for implementation-specific reasons."; case VK_ERROR_DEVICE_LOST: From 2e9885632a003699436d474b4b8230746baf7192 Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Tue, 21 May 2024 19:02:51 -0700 Subject: [PATCH 08/22] Solving the concurrent object heap issue (and destruction from other threads issue) --- .../acceleration/AccelerationBlasBuilder.java | 3 ++ .../acceleration/AccelerationManager.java | 3 +- .../acceleration/AccelerationTLASManager.java | 14 ++---- .../client/rendering/VulkanPipeline.java | 1 + .../me/cortex/vulkanite/lib/base/VObject.java | 3 +- .../cortex/vulkanite/lib/base/VRegistry.java | 48 ++++++++++++++++--- .../descriptors/DescriptorUpdateBuilder.java | 14 +++--- .../lib/descriptors/VDescriptorSet.java | 10 +++- .../vulkanite/lib/memory/MemoryManager.java | 4 +- 9 files changed, 70 insertions(+), 30 deletions(-) diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java index c3eedec..5a1c611 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java @@ -8,6 +8,7 @@ import me.cortex.vulkanite.compat.IAccelerationBuildResult; import me.cortex.vulkanite.lib.base.VContext; import me.cortex.vulkanite.lib.base.VRef; +import me.cortex.vulkanite.lib.base.VRegistry; import me.cortex.vulkanite.lib.cmd.VCmdBuff; import me.cortex.vulkanite.lib.cmd.VCommandPool; import me.cortex.vulkanite.lib.descriptors.DescriptorSetLayoutBuilder; @@ -171,6 +172,8 @@ private void run() { } } + VRegistry.INSTANCE.threadLocalCollect(); + var sinlgeUsePoolWorker = context.cmd.getSingleUsePool(); //Jobs are batched and built on the async vulkan queue then block synchronized with fence diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationManager.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationManager.java index 41d3b55..c156a51 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationManager.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationManager.java @@ -60,8 +60,7 @@ public void updateTick() { public VRef buildTLAS(int queueId, VCmdBuff cmd) { blasExecutions.forEach(exec -> ctx.cmd.queueWaitForExeuction(queueId, blasBuilder.getAsyncQueue(), exec)); blasExecutions.clear(); - tlasManager.buildTLAS(cmd); - return tlasManager.getTlas(); + return tlasManager.buildTLAS(cmd); } public void sectionRemove(RenderSection section) { diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java index 13bb48f..5aa69b3 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java @@ -38,8 +38,6 @@ public class AccelerationTLASManager { private final VContext context; private final int queue; - private VRef currentTLAS; - public AccelerationTLASManager(VContext context, int queue) { this.context = context; this.queue = queue; @@ -71,7 +69,7 @@ public void removeSection(RenderSection section) { // TODO: cleanup, this is very messy // FIXME: in the case of no geometry create an empty tlas or something??? - public void buildTLAS(VCmdBuff cmd) { + public VRef buildTLAS(VCmdBuff cmd) { RenderSystem.assertOnRenderThread(); // NOTE: renderLink is required to ensure that we are not overriding memory that @@ -188,17 +186,10 @@ public void buildTLAS(VCmdBuff cmd) { cmd.encodeMemoryBarrier(); - if (currentTLAS != null) { - currentTLAS.close(); - } - currentTLAS = tlas; + return tlas; } } - public VRef getTlas() { - return currentTLAS.addRef(); - } - // Manages entries in the VkAccelerationStructureInstanceKHR buffer, ment to // reuse as much as possible and be very efficient @@ -373,6 +364,7 @@ public void resizeBindlessSet(int newSize) { .descriptorCount(setCapacity); vkUpdateDescriptorSets(context.device, null, setCopy); } + geometryBufferDescSet.close(); } geometryBufferDescSet = newGeometryBufferDescSet; diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java index 0b027ed..00a5493 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java @@ -243,6 +243,7 @@ private void buildEntities() { public void renderPostShadows(List> vgOutImgs, Camera camera, ShaderStorageBuffer[] ssbos, MixinCelestialUniforms celestialUniforms) { ctx.cmd.newFrame(); + VRegistry.INSTANCE.threadLocalCollect(); System.out.println(VRegistry.INSTANCE.dumpStats()); buildEntities(); diff --git a/src/main/java/me/cortex/vulkanite/lib/base/VObject.java b/src/main/java/me/cortex/vulkanite/lib/base/VObject.java index 7c6cfc1..2b9be93 100644 --- a/src/main/java/me/cortex/vulkanite/lib/base/VObject.java +++ b/src/main/java/me/cortex/vulkanite/lib/base/VObject.java @@ -16,8 +16,9 @@ protected void incRef() { protected void decRef() { if (refCount.decrementAndGet() == 0) { - free(); VRegistry.INSTANCE.unregister(this); } } + + public Object heap = null; } diff --git a/src/main/java/me/cortex/vulkanite/lib/base/VRegistry.java b/src/main/java/me/cortex/vulkanite/lib/base/VRegistry.java index b312444..cb623b1 100644 --- a/src/main/java/me/cortex/vulkanite/lib/base/VRegistry.java +++ b/src/main/java/me/cortex/vulkanite/lib/base/VRegistry.java @@ -1,11 +1,10 @@ package me.cortex.vulkanite.lib.base; import com.google.common.collect.ConcurrentHashMultiset; +import java.util.concurrent.ConcurrentLinkedDeque; import me.cortex.vulkanite.lib.memory.VBuffer; -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; +import java.util.*; import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR; import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR; @@ -16,17 +15,44 @@ public class VRegistry { public static final VRegistry INSTANCE = new VRegistry(); - private final ConcurrentHashMultiset objects = ConcurrentHashMultiset.create(); + private static class ObjectHeap { + protected final long threadId = Thread.currentThread().getId(); + protected final String threadName = Thread.currentThread().getName(); + + protected final HashSet objects = new HashSet<>(); + protected final ConcurrentLinkedDeque toFree = new ConcurrentLinkedDeque<>(); + + protected void collect() { + if (Thread.currentThread().getId() != threadId) { + throw new IllegalStateException("Object heap collect called from wrong thread"); + } + VObject object; + while ((object = toFree.poll()) != null) { + objects.remove(object); + object.free(); + } + } + } + + private final ConcurrentHashMultiset objectHeaps = ConcurrentHashMultiset.create(); + + private final ThreadLocal heap = ThreadLocal.withInitial(()->{ + var heap = new ObjectHeap(); + objectHeaps.add(heap); + return heap; + }); private VRegistry() { } public void register(VObject object) { - objects.add(object); + heap.get().objects.add(object); + object.heap = heap.get(); } public void unregister(VObject object) { - objects.remove(object); + ObjectHeap heap = (ObjectHeap) object.heap; + heap.toFree.add(object); } private static final HashMap usageNames = new HashMap<>() {{ @@ -45,7 +71,11 @@ public void unregister(VObject object) { public String dumpStats() { final StringBuilder sb = new StringBuilder(); - sb.append("VRegistry: ").append(objects.size()).append(" objects\n"); + ObjectHeap heap = this.heap.get(); + var objects = heap.objects; + + sb.append("\nVRegistry (Thread=").append(heap.threadId).append(" ").append(heap.threadName).append("): "); + sb.append(objects.size()).append(" objects\n"); sb.append("Objects:\n"); Map typeCount = new TreeMap<>(); @@ -80,4 +110,8 @@ public String dumpStats() { return sb.toString(); } + + public void threadLocalCollect() { + heap.get().collect(); + } } diff --git a/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java b/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java index f4e8f79..4c27f76 100644 --- a/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java +++ b/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java @@ -76,7 +76,7 @@ public DescriptorUpdateBuilder buffer(int binding, final VRef buffer, l if (refSet != null && refSet.getBindingAt(binding) == null) { return this; } - setRef.get().refs.put(binding, buffer.addRefGeneric()); + setRef.get().addRef(binding, buffer.addRefGeneric()); updates.get() .sType$Default() .dstBinding(binding) @@ -98,7 +98,7 @@ public DescriptorUpdateBuilder buffer(int binding, int dstArrayElement, final Li } var bufInfo = VkDescriptorBufferInfo.calloc(buffers.size()); for (int i = 0; i < buffers.size(); i++) { - setRef.get().refs.put(binding, buffers.get(i).addRefGeneric()); + setRef.get().addRef(binding, buffers.get(i).addRefGeneric()); bufInfo.get(i) .buffer(buffers.get(i).get().buffer()) .offset(0) @@ -124,7 +124,7 @@ public DescriptorUpdateBuilder uniform(int binding, final VRef buffer, if (refSet != null && refSet.getBindingAt(binding) == null) { return this; } - setRef.get().refs.put(binding, buffer.addRefGeneric()); + setRef.get().addRef(binding, buffer.addRefGeneric()); updates.get() .sType$Default() .dstBinding(binding) @@ -145,7 +145,7 @@ public DescriptorUpdateBuilder acceleration(int binding, VRef> refs = new HashMap<>(); + private Map> refs = new HashMap<>(); + + public void addRef(int binding, VRef ref) { + var old = refs.put(binding, ref); + if (old != null) { + old.close(); + } + } protected VDescriptorSet(VRef pool, long poolHandle, long set) { this.pool = pool; @@ -22,5 +29,6 @@ protected VDescriptorSet(VRef pool, long poolHandle, long set) @Override protected void free() { pool.get().freeSet(this); + refs.values().forEach(VRef::close); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java b/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java index 3f81d40..746ba1f 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java @@ -303,7 +303,9 @@ public VRef createAcceleration(long size, int alignment, .size(size) .buffer(buffer.get().buffer()), null, pAccelerationStructure), "Failed to create acceleration acceleration structure"); - return VAccelerationStructure.create(device, pAccelerationStructure.get(0), buffer); + var ret = VAccelerationStructure.create(device, pAccelerationStructure.get(0), buffer); + buffer.close(); + return ret; } } From 36dd2f7240c957f87c7c60f2a77c6157944ddf96 Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Tue, 21 May 2024 19:36:16 -0700 Subject: [PATCH 09/22] Compaction is the name of the game, WIP --- .../acceleration/AccelerationBlasBuilder.java | 58 ++++++++++++------- .../acceleration/AccelerationTLASManager.java | 44 +++++++------- .../acceleration/JobPassThroughData.java | 2 +- .../descriptors/DescriptorUpdateBuilder.java | 24 ++++++++ 4 files changed, 84 insertions(+), 44 deletions(-) diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java index 5a1c611..34c9886 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java @@ -220,9 +220,10 @@ private void run() { // 1: inAddr // 2: outAddr var pushConstant = new long[3]; - var geometryInputBuffer = job.data.geometryBuffers().get(geoIdx); + var geometryInputBuffer = job.data.geometryBuffer(); + var geometryInputBufferOffset = job.data.bufferOffsets().get(geoIdx); pushConstant[0] = geometry.quadCount * 4L; - pushConstant[1] = geometryInputBuffer.get().deviceAddress(); + pushConstant[1] = geometryInputBuffer.get().deviceAddress() + geometryInputBufferOffset; pushConstant[2] = buildBuffer.deviceAddress(); if (pushConstant[1] == 0) { throw new IllegalStateException("Geometry input buffer address is 0"); @@ -380,15 +381,8 @@ private void run() { - private VRef uploadTerrainGeometry(BuiltSectionMeshParts meshParts, VCmdBuff cmd) { - var buff = context.memory.createBuffer(meshParts.getVertexData().getLength(), - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - buff.get().setDebugUtilsObjectName("Terrain geometry buffer"); - - cmd.encodeDataUpload(context.memory, MemoryUtil.memAddress(meshParts.getVertexData().getDirectBuffer()), buff, 0, meshParts.getVertexData().getLength()); - - return buff; + private void uploadTerrainGeometry(BuiltSectionMeshParts meshParts, VRef buffer, long destOffset, VCmdBuff cmd) { + cmd.encodeDataUpload(context.memory, MemoryUtil.memAddress(meshParts.getVertexData().getDirectBuffer()), buffer, destOffset, meshParts.getVertexData().getLength()); } // Enqueues jobs of section blas builds @@ -402,27 +396,49 @@ public void enqueue(List batch) { var acbr = ((IAccelerationBuildResult) cbr).getAccelerationGeometryData(); if (acbr == null) continue; - List buildData = new ArrayList<>(); - List> geometryBuffers = new ArrayList<>(); - for (var entry : acbr.entrySet()) { - int flag = entry.getKey() == DefaultTerrainRenderPasses.SOLID ? VK_GEOMETRY_OPAQUE_BIT_KHR : 0; - buildData.add(new BLASTriangleData(entry.getValue().quadCount(), flag)); + List geometries = new ArrayList<>(); + + long totalSize = 0; + for (var entry : acbr.entrySet()) { var geometry = cbr.getMesh(entry.getKey()); - if (geometry.getVertexData().getLength() == 0) { + var dataSize = geometry.getVertexData().getLength(); + if (dataSize == 0) { throw new IllegalStateException(); } - if (!hasJobs) { hasJobs = true; } + totalSize += dataSize; + geometries.add(geometry); + } + + var geomBuffer = context.memory.createBuffer(totalSize, + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + geomBuffer.get().setDebugUtilsObjectName("Terrain geometry buffer"); + + List buildData = new ArrayList<>(); + List bufferOffsets = new ArrayList<>(); + int i = 0; + long destOffset = 0; + for (var entry : acbr.entrySet()) { + int flag = entry.getKey() == DefaultTerrainRenderPasses.SOLID ? VK_GEOMETRY_OPAQUE_BIT_KHR : 0; + buildData.add(new BLASTriangleData(entry.getValue().quadCount(), flag)); + + var meshParts = geometries.get(i); + long dataSize = meshParts.getVertexData().getLength(); + + cmd.get().encodeDataUpload(context.memory, MemoryUtil.memAddress(meshParts.getVertexData().getDirectBuffer()), geomBuffer, destOffset, dataSize); + bufferOffsets.add(destOffset); - geometryBuffers.add(uploadTerrainGeometry(geometry, cmd.get())); + destOffset += dataSize; + i++; } - if (buildData.size() > 0) { + if (!buildData.isEmpty()) { jobs.add(new BLASBuildJob(buildData, - new JobPassThroughData(cbr.render, cbr.buildTime, geometryBuffers))); + new JobPassThroughData(cbr.render, cbr.buildTime, geomBuffer, bufferOffsets))); } } diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java index 5aa69b3..bd8cd5b 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java @@ -108,7 +108,7 @@ public VRef buildTLAS(VCmdBuff cmd) { .instanceShaderBindingTableRecordOffset(1) .accelerationStructureReference(entityBuild.getLeft().get().deviceAddress); extra.transform().matrix(new Matrix4x3f().getTransposed(stack.mallocFloat(12))); - buildDataManager.descUpdateJobs.add(new TLASSectionManager.DescUpdateJob(0,0, List.of(entityBuild.getRight()))); + buildDataManager.descUpdateJobs.add(new TLASSectionManager.DescUpdateJob(0,0, entityBuild.getRight(), List.of(0L))); instances++; } buildDataManager.setGeometryUpdateMemory(geometry, extra); @@ -325,10 +325,10 @@ public TLASSectionManager() { private int setCapacity = 0; - private record DescUpdateJob(int binding, int dstArrayElement, List> buffers) { + private record DescUpdateJob(int binding, int dstArrayElement, VRef geometryBuffer, List geometryBufferOffsets) { } - private record ArenaDeallocJob(int index, int count, List> geometryBuffers) { + private record ArenaDeallocJob(int index, int count, VRef geometryBuffer) { } private final ConcurrentLinkedDeque descUpdateJobs = new ConcurrentLinkedDeque<>(); @@ -386,14 +386,13 @@ public VRef setGeometryUpdateMemory(VkAccelerationStructureGeometryKHR dub.set(geometryBufferDescSet); while (!descUpdateJobs.isEmpty()) { var job = descUpdateJobs.poll(); - dub.buffer(job.binding, job.dstArrayElement, job.buffers); + dub.buffer(job.binding, job.dstArrayElement, job.geometryBuffer, job.geometryBufferOffsets); } dub.apply(); - // Queue up the arena dealloc jobs to be done after the fence is done - Vulkanite.INSTANCE.addSyncedCallback(() -> { - fenceTick(); - }); + // Since we have residency tracking through the descriptor set, + // we can free the buffers immediately + collect(); return instanceBuf; } @@ -403,7 +402,8 @@ public VRef setGeometryUpdateMemory(VkAccelerationStructureGeometryKHR private static final class Holder { final int id; int geometryIndex = -1; - List> geometryBuffers; + VRef geometryBuffer; + List geometryBufferOffsets; final RenderSection section; VRef structure; @@ -416,12 +416,11 @@ private Holder(int id, RenderSection section) { Map tmp = new HashMap<>(); - public void fenceTick() { - while (!arenaDeallocJobs.isEmpty()) { - var job = arenaDeallocJobs.poll(); + public void collect() { + ArenaDeallocJob job; + while ((job = arenaDeallocJobs.poll()) != null) { arena.free(job.index, job.count); - job.geometryBuffers.forEach(VRef::close); - job.geometryBuffers.clear(); + job.geometryBuffer.close(); } } @@ -431,13 +430,14 @@ public void update(AccelerationBlasBuilder.BLASBuildResult result) { holder.structure = result.structure(); if (holder.geometryIndex != -1) { - arenaDeallocJobs.add(new ArenaDeallocJob(holder.geometryIndex, holder.geometryBuffers.size(), - holder.geometryBuffers)); + arenaDeallocJobs.add(new ArenaDeallocJob(holder.geometryIndex, holder.geometryBufferOffsets.size(), + holder.geometryBuffer)); } - holder.geometryBuffers = data.geometryBuffers(); - holder.geometryIndex = arena.allocate(holder.geometryBuffers.size()); + holder.geometryBuffer = data.geometryBuffer(); + holder.geometryBufferOffsets = data.bufferOffsets(); + holder.geometryIndex = arena.allocate(holder.geometryBufferOffsets.size()); - descUpdateJobs.add(new DescUpdateJob(0, holder.geometryIndex, holder.geometryBuffers)); + descUpdateJobs.add(new DescUpdateJob(0, holder.geometryIndex, holder.geometryBuffer, holder.geometryBufferOffsets)); try (var stack = stackPush()) { var asi = VkAccelerationStructureInstanceKHR.calloc(stack) @@ -461,14 +461,14 @@ public void remove(RenderSection section) { free(holder.id); for (var job : descUpdateJobs) { - if (job.buffers == holder.geometryBuffers) { + if (job.geometryBuffer == holder.geometryBuffer) { descUpdateJobs.remove(job); } } if (holder.geometryIndex != -1) { - arenaDeallocJobs.add(new ArenaDeallocJob(holder.geometryIndex, holder.geometryBuffers.size(), - holder.geometryBuffers)); + arenaDeallocJobs.add(new ArenaDeallocJob(holder.geometryIndex, holder.geometryBufferOffsets.size(), + holder.geometryBuffer)); } } } diff --git a/src/main/java/me/cortex/vulkanite/acceleration/JobPassThroughData.java b/src/main/java/me/cortex/vulkanite/acceleration/JobPassThroughData.java index 0a7a080..1d91950 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/JobPassThroughData.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/JobPassThroughData.java @@ -6,6 +6,6 @@ import java.util.List; -public record JobPassThroughData(RenderSection section, long time, List> geometryBuffers) { +public record JobPassThroughData(RenderSection section, long time, VRef geometryBuffer, List bufferOffsets) { } diff --git a/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java b/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java index 4c27f76..b957ec9 100644 --- a/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java +++ b/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java @@ -116,6 +116,30 @@ public DescriptorUpdateBuilder buffer(int binding, int dstArrayElement, final Li return this; } + public DescriptorUpdateBuilder buffer(int binding, int dstArrayElement, final VRef buffer, List offsets) { + if (refSet != null && refSet.getBindingAt(binding) == null) { + return this; + } + var bufInfo = VkDescriptorBufferInfo.calloc(offsets.size()); + for (int i = 0; i < offsets.size(); i++) { + setRef.get().addRef(binding, buffer.addRefGeneric()); + bufInfo.get(i) + .buffer(buffer.get().buffer()) + .offset(offsets.get(i)) + .range(VK_WHOLE_SIZE); + } + updates.get() + .sType$Default() + .dstBinding(binding) + .dstSet(set) + .dstArrayElement(dstArrayElement) + .descriptorType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) + .descriptorCount(offsets.size()) + .pBufferInfo(bufInfo); + bulkBufferInfos.add(bufInfo); + return this; + } + public DescriptorUpdateBuilder uniform(int binding, final VRef buffer) { return uniform(binding, buffer, 0, VK_WHOLE_SIZE); From 0a379b0046e37cca6475ca4c2a592dcc6380fa13 Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Wed, 22 May 2024 17:16:40 -0700 Subject: [PATCH 10/22] Fixing a missing close in descriptor update builder --- .../acceleration/AccelerationBlasBuilder.java | 7 +- .../acceleration/AccelerationManager.java | 2 +- .../acceleration/AccelerationTLASManager.java | 110 +++++-------- .../client/rendering/VulkanPipeline.java | 7 +- .../vulkanite/lib/cmd/CommandManager.java | 94 +++++++---- .../descriptors/DescriptorUpdateBuilder.java | 1 + .../lib/descriptors/VDescriptorSet.java | 23 ++- .../lib/memory/AccelerationStructurePool.java | 152 ++++++++++++++++++ .../lib/memory/VAccelerationStructure.java | 1 - .../iris/MixinNewWorldRenderingPipeline.java | 3 + 10 files changed, 296 insertions(+), 104 deletions(-) create mode 100644 src/main/java/me/cortex/vulkanite/lib/memory/AccelerationStructurePool.java diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java index 34c9886..d16a18f 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java @@ -13,6 +13,7 @@ import me.cortex.vulkanite.lib.cmd.VCommandPool; import me.cortex.vulkanite.lib.descriptors.DescriptorSetLayoutBuilder; import me.cortex.vulkanite.lib.descriptors.VDescriptorSetLayout; +import me.cortex.vulkanite.lib.memory.AccelerationStructurePool; import me.cortex.vulkanite.lib.memory.PoolLinearAllocator; import me.cortex.vulkanite.lib.memory.VAccelerationStructure; import me.cortex.vulkanite.lib.memory.VBuffer; @@ -66,11 +67,14 @@ public int getAsyncQueue() { return asyncQueue; } + private final AccelerationStructurePool accelerationStructurePool; + public AccelerationBlasBuilder(VContext context, int asyncQueue, Consumer resultConsumer) { this.queryPool = VQueryPool.create(context.device, 10000, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR); this.context = context; this.asyncQueue = asyncQueue; this.resultConsumer = resultConsumer; + this.accelerationStructurePool = new AccelerationStructurePool(context); var decodeShader = VShader.compileLoad(context, """ #version 460 @@ -345,8 +349,7 @@ private void run() { // Dont need a memory barrier cause submit ensures cache flushing already for (int idx = 0; idx < compactedSizes.length; idx++) { - var compact_as = context.memory.createAcceleration(compactedSizes[idx], 256, - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR); + var compact_as = accelerationStructurePool.createAcceleration(compactedSizes[idx], VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR); var fat_as = accelerationStructures.get(idx); vkCmdCopyAccelerationStructureKHR(cmdRef.get().buffer(), VkCopyAccelerationStructureInfoKHR.calloc(stack).sType$Default() diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationManager.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationManager.java index c156a51..cbb8e3e 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationManager.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationManager.java @@ -58,7 +58,7 @@ public void updateTick() { } public VRef buildTLAS(int queueId, VCmdBuff cmd) { - blasExecutions.forEach(exec -> ctx.cmd.queueWaitForExeuction(queueId, blasBuilder.getAsyncQueue(), exec)); + ctx.cmd.queueWaitForExecutions(queueId, blasBuilder.getAsyncQueue(), blasExecutions); blasExecutions.clear(); return tlasManager.buildTLAS(cmd); } diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java index bd8cd5b..2cf6496 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java @@ -81,7 +81,7 @@ public VRef buildTLAS(VCmdBuff cmd) { // this is done for performance reasons when updating (adding/removing) sections VkAccelerationStructureGeometryKHR geometry = VkAccelerationStructureGeometryKHR.calloc(stack); - int instances = 0; + int instances = buildDataManager.sectionCount(); Pair, VRef> entityBuild; if (entityData != null) { @@ -90,46 +90,33 @@ public VRef buildTLAS(VCmdBuff cmd) { entityBuild = null; } - { - // TODO: need to sync with respect to updates from gpu memory updates from - // TLASBuildDataManager - // OR SOMETHING CAUSE WITH MULTIPLE FRAMES GOING AT ONCE the gpu state of - // TLASBuildDataManager needs to be synced with - // the current build phase, and the gpu side needs to be updated accoringly and - // synced correctly - - cmd.encodeMemoryBarrier(); - - VkAccelerationStructureInstanceKHR extra = null; - if (entityBuild != null) { - extra = VkAccelerationStructureInstanceKHR.calloc(stack); - extra.mask(~0) - .instanceCustomIndex(0) - .instanceShaderBindingTableRecordOffset(1) - .accelerationStructureReference(entityBuild.getLeft().get().deviceAddress); - extra.transform().matrix(new Matrix4x3f().getTransposed(stack.mallocFloat(12))); - buildDataManager.descUpdateJobs.add(new TLASSectionManager.DescUpdateJob(0,0, entityBuild.getRight(), List.of(0L))); - instances++; - } - buildDataManager.setGeometryUpdateMemory(geometry, extra); - instances += buildDataManager.sectionCount(); - - cmd.encodeMemoryBarrier(); + VkAccelerationStructureInstanceKHR extra = null; + if (entityBuild != null) { + extra = VkAccelerationStructureInstanceKHR.calloc(stack); + extra.mask(~0) + .instanceCustomIndex(0) + .instanceShaderBindingTableRecordOffset(1) + .accelerationStructureReference(entityBuild.getLeft().get().deviceAddress); + extra.transform().matrix(new Matrix4x3f().getTransposed(stack.mallocFloat(12))); + buildDataManager.descUpdateJobs.add(new TLASSectionManager.DescUpdateJob(0, 0, entityBuild.getRight(), List.of(0L))); + instances++; } + var instanceBuffer = buildDataManager.getInstanceBuffer(extra); + geometry.sType$Default() + .geometryType(VK_GEOMETRY_TYPE_INSTANCES_KHR) + .flags(0); - int[] instanceCounts = new int[]{instances}; - { - geometry.sType$Default() - .geometryType(VK_GEOMETRY_TYPE_INSTANCES_KHR) - .flags(0); - - geometry.geometry() - .instances() - .sType$Default() - .arrayOfPointers(false); - } + geometry.geometry() + .instances() + .sType$Default() + .arrayOfPointers(false); + + geometry.geometry() + .instances() + .data() + .deviceAddress(instanceBuffer.get().deviceAddress()); // TLAS always rebuild & PREFER_FAST_TRACE according to Nvidia @@ -145,12 +132,13 @@ public VRef buildTLAS(VCmdBuff cmd) { .calloc(stack) .sType$Default(); + int[] instanceCounts = new int[]{instances}; vkGetAccelerationStructureBuildSizesKHR( context.device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, buildInfo.get(0), // The reason its a buffer is cause of pain and that - // vkCmdBuildAccelerationStructuresKHR requires a buffer of - // VkAccelerationStructureBuildGeometryInfoKHR + // vkCmdBuildAccelerationStructuresKHR requires a buffer of + // VkAccelerationStructureBuildGeometryInfoKHR stack.ints(instanceCounts), buildSizesInfo); @@ -178,10 +166,14 @@ public VRef buildTLAS(VCmdBuff cmd) { } buildRanges.rewind(); + cmd.encodeMemoryBarrier(); + vkCmdBuildAccelerationStructuresKHR(cmd.buffer(), buildInfo, stack.pointers(buildRanges)); + cmd.addBufferRef(instanceBuffer); cmd.addBufferRef(scratchBuffer); + instanceBuffer.close(); scratchBuffer.close(); cmd.encodeMemoryBarrier(); @@ -215,7 +207,7 @@ public TLASGeometryManager() { // TODO: make the instances buffer, gpu permenent then stream updates instead of // uploading per frame - public VRef setGeometryUpdateMemory(VkAccelerationStructureGeometryKHR struct, VkAccelerationStructureInstanceKHR addin) { + public VRef getInstanceBuffer(VkAccelerationStructureInstanceKHR addin) { long size = (long) VkAccelerationStructureInstanceKHR.SIZEOF * count; long newSize = size + (addin==null?0:VkAccelerationStructureInstanceKHR.SIZEOF); if (newSize == 0) { @@ -239,11 +231,6 @@ public VRef setGeometryUpdateMemory(VkAccelerationStructureGeometryKHR data.get().unmap(); data.get().flush(); - struct.geometry() - .instances() - .data() - .deviceAddress(data.get().deviceAddress()); - return data; } @@ -355,15 +342,7 @@ public void resizeBindlessSet(int newSize) { + " with capacity " + newCapacity); if (geometryBufferDescSet != null) { - try (var stack = stackPush()) { - var setCopy = VkCopyDescriptorSet.calloc(1, stack); - setCopy.get(0) - .sType$Default() - .srcSet(geometryBufferDescSet.get().set) - .dstSet(newGeometryBufferDescSet.get().set) - .descriptorCount(setCapacity); - vkUpdateDescriptorSets(context.device, null, setCopy); - } + newGeometryBufferDescSet.get().copyFrom(context, geometryBufferDescSet, setCapacity); geometryBufferDescSet.close(); } @@ -374,27 +353,24 @@ public void resizeBindlessSet(int newSize) { } @Override - public VRef setGeometryUpdateMemory(VkAccelerationStructureGeometryKHR struct, VkAccelerationStructureInstanceKHR addin) { - var instanceBuf = super.setGeometryUpdateMemory(struct, addin); + public VRef getInstanceBuffer(VkAccelerationStructureInstanceKHR addin) { resizeBindlessSet(arena.maxIndex); - if (descUpdateJobs.isEmpty()) { - return null; - } - - var dub = new DescriptorUpdateBuilder(context, descUpdateJobs.size()); - dub.set(geometryBufferDescSet); - while (!descUpdateJobs.isEmpty()) { - var job = descUpdateJobs.poll(); - dub.buffer(job.binding, job.dstArrayElement, job.geometryBuffer, job.geometryBufferOffsets); + if (!descUpdateJobs.isEmpty()) { + var dub = new DescriptorUpdateBuilder(context, descUpdateJobs.size()); + dub.set(geometryBufferDescSet); + while (!descUpdateJobs.isEmpty()) { + var job = descUpdateJobs.poll(); + dub.buffer(job.binding, job.dstArrayElement, job.geometryBuffer, job.geometryBufferOffsets); + } + dub.apply(); } - dub.apply(); // Since we have residency tracking through the descriptor set, // we can free the buffers immediately collect(); - return instanceBuf; + return super.getInstanceBuffer(addin); } // TODO: mixinto RenderSection and add a reference to a holder for us, its much diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java index 00a5493..18fe887 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java @@ -243,9 +243,6 @@ private void buildEntities() { public void renderPostShadows(List> vgOutImgs, Camera camera, ShaderStorageBuffer[] ssbos, MixinCelestialUniforms celestialUniforms) { ctx.cmd.newFrame(); - VRegistry.INSTANCE.threadLocalCollect(); - System.out.println(VRegistry.INSTANCE.dumpStats()); - buildEntities(); PBRTextureManager.notifyPBRTexturesChanged(); @@ -262,6 +259,7 @@ public void renderPostShadows(List> vgOutImgs, Camera camera, Shad var tlas = accelerationManager.buildTLAS(0, cmd); if (tlas == null) { + VRegistry.INSTANCE.threadLocalCollect(); glFinish(); return; } @@ -428,6 +426,9 @@ public void renderPostShadows(List> vgOutImgs, Camera camera, Shad vref_out.close(); in.close(); out.close(); + + VRegistry.INSTANCE.threadLocalCollect(); + System.out.println(VRegistry.INSTANCE.dumpStats()); } public void destory() { diff --git a/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java b/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java index 39c4e86..3ddd648 100644 --- a/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java @@ -5,6 +5,9 @@ import com.google.common.collect.Multimaps; import com.mojang.blaze3d.systems.RenderSystem; import io.netty.util.internal.shaded.org.jctools.queues.MessagePassingQueue.Consumer; +import it.unimi.dsi.fastutil.ints.Int2LongArrayMap; +import it.unimi.dsi.fastutil.ints.Int2LongMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.other.sync.VFence; import me.cortex.vulkanite.lib.other.sync.VSemaphore; @@ -15,6 +18,7 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.ReentrantLock; import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; import static org.lwjgl.system.MemoryStack.stackPush; @@ -76,6 +80,17 @@ public void queueWaitForExeuction(int waitQueueId, int executionQueueId, long ex queues[waitQueueId].waitForExecution(executionQueueId, execution); } + /** + * Enqueues a wait for a timeline value on a queue + * + * @param waitQueueId The queue that will wait + * @param executionQueueId The queue whose timeline value will be waited for + * @param executions The timeline values to wait for + */ + public void queueWaitForExecutions(int waitQueueId, int executionQueueId, List executions) { + queues[waitQueueId].waitForExecutions(executionQueueId, executions); + } + /** * Wait on the host for a timeline value on a queue * @@ -95,9 +110,7 @@ public void hostWaitForExecution(int waitQueueId, long execution) { _CHECK_(vkWaitSemaphores(device, waitInfo, -1)); } - synchronized (queues[waitQueueId]) { - waitQueue.completedTimestamp = Long.max(waitQueue.completedTimestamp, execution); - } + waitQueue.updateCompletedTimestamp(execution); waitQueue.collect(); } @@ -129,12 +142,12 @@ public void newFrame() { private static class Queue { public final VkQueue queue; - public final Multimap waitingFor = Multimaps.synchronizedMultimap(HashMultimap.create()); - public final ConcurrentHashMap> submitted = new ConcurrentHashMap<>(); + private final Int2LongArrayMap waitingFor = new Int2LongArrayMap(); + private final Long2ObjectOpenHashMap> submitted = new Long2ObjectOpenHashMap<>(); public final VRef timelineSema; // public final Deque frameTimestamps = new ArrayDeque<>(3); public AtomicLong timeline = new AtomicLong(1); - public long completedTimestamp = 0; + public AtomicLong completedTimestamp = new AtomicLong(0); public Queue(int queueId, VkDevice device) { try (var stack = stackPush()) { @@ -158,27 +171,36 @@ public Queue(int queueId, VkDevice device) { } } + public void updateCompletedTimestamp(long newTimestamp) { + // completedTimestamp.atomicMax(newTimestamp); + long current; + do { + current = completedTimestamp.get(); + } while (current < newTimestamp && !completedTimestamp.compareAndSet(current, newTimestamp)); + } + public void newFrame() { // if (frameTimestamps.size() >= 3) { // long oldest = frameTimestamps.removeFirst(); // completedTimestamp = Long.max(completedTimestamp, oldest); // } // frameTimestamps.addLast(completedTimestamp); - completedTimestamp = Long.max(completedTimestamp, getCurrentExecution()); + updateCompletedTimestamp(getCurrentExecution()); collect(); } public void collect() { - synchronized (this) { - for (var entry : submitted.entrySet()) { - if (entry.getKey() <= completedTimestamp) { - // We know it's gone, we can early-close it - // So that we don't need to wait for GC - entry.getValue().close(); + synchronized (submitted) { + long completedTimestamp = this.completedTimestamp.get(); + + submitted.forEach((time, cmdRef) -> { + if (time <= completedTimestamp) { + cmdRef.close(); } - } - for (var key : submitted.keySet()) { + }); + + for (long key : submitted.keySet()) { if (key <= completedTimestamp) { submitted.remove(key); } @@ -187,29 +209,39 @@ public void collect() { } public void waitIdle() { - _CHECK_(vkQueueWaitIdle(queue)); - - synchronized (this) { + synchronized (waitingFor) { + vkQueueWaitIdle(queue); waitingFor.clear(); - submitted.forEach((k, v) -> v.close()); - submitted.clear(); - completedTimestamp = timeline.get() - 1; } + + updateCompletedTimestamp(getCurrentExecution()); + collect(); } public void waitForExecution(int execQueue, long execution) { - synchronized (this) { - waitingFor.put(execQueue, execution); + synchronized (waitingFor) { + waitingFor.put(execQueue, Long.max(waitingFor.getOrDefault(execQueue, 0), execution)); + } + } + + public void waitForExecutions(int execQueue, List executions) { + synchronized (waitingFor) { + long execMax = executions.stream().mapToLong(Long::longValue).max().orElse(waitingFor.getOrDefault(execQueue, 0)); + waitingFor.put(execQueue, execMax); } } public long submit(final VRef cmdBuff, Queue[] queues, List> waits, List> triggers, VFence fence) { long t = timeline.getAndIncrement(); - synchronized (this) { + synchronized (waitingFor) { + // We need to hold the lock until we have submitted cmdbuf into the queue + // Otherwise it might be possible that another thread will submit a cmdbuf without waiting for anything + // Queue submits has strong API ordering + var timelineWaitingEntries = waitingFor.int2LongEntrySet(); + waitingFor.clear(); + try (var stack = stackPush()) { - Collection> timelineWaitingEntries; - timelineWaitingEntries = waitingFor.entries(); int waitCount = (waits == null ? 0 : waits.size()) + timelineWaitingEntries.size(); int triggerCount = (triggers == null ? 0 : triggers.size()) + 1; @@ -237,9 +269,12 @@ public long submit(final VRef cmdBuff, Queue[] queues, List cmdBuff, Queue[] queues, List pool; public final long poolHandle; public final long set; - private Map> refs = new HashMap<>(); + private final Map> refs = new HashMap<>(); public void addRef(int binding, VRef ref) { var old = refs.put(binding, ref); @@ -31,4 +36,20 @@ protected void free() { pool.get().freeSet(this); refs.values().forEach(VRef::close); } + + public void copyFrom(VContext ctx, VRef other, int setCapacity) { + for (var entry : other.get().refs.entrySet()) { + refs.put(entry.getKey(), entry.getValue().addRef()); + } + + try (var stack = stackPush()) { + var setCopy = VkCopyDescriptorSet.calloc(1, stack); + setCopy.get(0) + .sType$Default() + .srcSet(other.get().set) + .dstSet(set) + .descriptorCount(setCapacity); + vkUpdateDescriptorSets(ctx.device, null, setCopy); + } + } } diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/AccelerationStructurePool.java b/src/main/java/me/cortex/vulkanite/lib/memory/AccelerationStructurePool.java new file mode 100644 index 0000000..ea6364c --- /dev/null +++ b/src/main/java/me/cortex/vulkanite/lib/memory/AccelerationStructurePool.java @@ -0,0 +1,152 @@ +package me.cortex.vulkanite.lib.memory; + +import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VObject; +import me.cortex.vulkanite.lib.base.VRef; +import org.lwjgl.vulkan.VkAccelerationStructureCreateInfoKHR; +import org.lwjgl.vulkan.VkDevice; + +import java.nio.LongBuffer; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.List; + +import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; +import static org.lwjgl.system.MemoryStack.stackPush; +import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR; +import static org.lwjgl.vulkan.KHRAccelerationStructure.vkCreateAccelerationStructureKHR; +import static org.lwjgl.vulkan.KHRBufferDeviceAddress.VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR; +import static org.lwjgl.vulkan.VK10.*; + +public class AccelerationStructurePool { + private static final int PAGE_SIZE = 1024; + private static final int BLOCK_NUM_PAGES = 128 * 1024; + private static final int BUFFER_USAGE = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR; + + public static class Block { + private final VRef buffer; + + private final BitSet vacant; + public int maxIndex = 0; + + private Block(MemoryManager memoryManager) { + buffer = memoryManager.createBuffer( + PAGE_SIZE * BLOCK_NUM_PAGES, + BUFFER_USAGE, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + PAGE_SIZE, + 0); + vacant = new BitSet(BLOCK_NUM_PAGES); + vacant.set(0, BLOCK_NUM_PAGES); + } + + private int allocate_n_pages(int count) { + int pos = vacant.nextSetBit(0); + outer: while (pos != -1) { + for (int offset = 1; offset < count; offset++) { + if (!vacant.get(offset + pos)) { + pos = vacant.nextSetBit(offset + pos + 1); + continue outer; + } + } + break; + } + if (pos == -1) { + throw new IllegalStateException(); + } + vacant.clear(pos, pos + count); + maxIndex = Math.max(maxIndex, pos + count); + return pos; + } + + public void free_n_pages(int pos, int count) { + vacant.set(pos, pos + count); + + maxIndex = vacant.previousClearBit(maxIndex) + 1; + } + + public long allocate(long size) { + int count = (int) Math.ceil((double) size / PAGE_SIZE); + try { + long pos = allocate_n_pages(count); + return pos * PAGE_SIZE; + } catch (IllegalStateException e) { + return -1; + } + } + + public void free(long offset, long size) { + int count = (int) Math.ceil((double) size / PAGE_SIZE); + free_n_pages((int) (offset / PAGE_SIZE), count); + } + } + + public static class AccelerationStructurePooled extends VAccelerationStructure { + private final Block block; + private final long offset; + private final long size; + + public AccelerationStructurePooled(VkDevice device, long structure, Block block, long offset, long size) { + super(device, structure, block.buffer.addRef()); + this.block = block; + this.offset = offset; + this.size = size; + } + + @Override + public void free() { + super.free(); + block.free(offset, size); + } + } + + private final List blocks = new ArrayList<>(); + + private final VContext ctx; + + public AccelerationStructurePool(VContext ctx) { + this.ctx = ctx; + blocks.add(new Block(ctx.memory)); + } + + public VRef createAcceleration(long size, int type) { + if (size > PAGE_SIZE * BLOCK_NUM_PAGES) { + return ctx.memory.createAcceleration(size, 256, BUFFER_USAGE, type); + } + + Block block = null; + long offset = -1; + + for (Block b : blocks) { + offset = b.allocate(size); + if (offset != -1) { + block = b; + break; + } + } + + if (offset == -1) { + block = new Block(ctx.memory); + blocks.add(block); + offset = block.allocate(size); + } + + AccelerationStructurePooled structure; + + try (var stack = stackPush()) { + LongBuffer pAccelerationStructure = stack.mallocLong(1); + _CHECK_(vkCreateAccelerationStructureKHR(ctx.device, VkAccelerationStructureCreateInfoKHR + .calloc(stack) + .sType$Default() + .type(type) + .size(size) + .buffer(block.buffer.get().buffer()) + .offset(offset), null, pAccelerationStructure), + "Failed to create acceleration acceleration structure"); + structure = new AccelerationStructurePooled(ctx.device, pAccelerationStructure.get(0), block, offset, size); + } + + return new VRef<>(structure); + } + +} diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/VAccelerationStructure.java b/src/main/java/me/cortex/vulkanite/lib/memory/VAccelerationStructure.java index fae00c9..824b8b0 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/VAccelerationStructure.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/VAccelerationStructure.java @@ -10,7 +10,6 @@ public class VAccelerationStructure extends VObject { public final long structure; - @SuppressWarnings("FieldCanBeLocal") private final VRef buffer; public final long deviceAddress; diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java index d603be2..93618bb 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java @@ -102,5 +102,8 @@ private void destory(CallbackInfo ci) { pipeline.destory(); rtShaderPasses = null; pipeline = null; + + // Force a GC, collect all dangling resources + System.gc(); } } From f4db9e1766dc9cd9651c36333a51d58da0bea479 Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Wed, 22 May 2024 17:40:13 -0700 Subject: [PATCH 11/22] Back to WIN32 handles (instead of KMT), this should make it work with Zink, i think --- .../lib/memory/HandleDescriptorManger.java | 38 ------------------- .../vulkanite/lib/memory/MemoryManager.java | 16 ++++---- .../vulkanite/lib/other/sync/SyncManager.java | 4 -- .../vulkanite/lib/other/sync/VGSemaphore.java | 25 ++++++++---- 4 files changed, 26 insertions(+), 57 deletions(-) delete mode 100644 src/main/java/me/cortex/vulkanite/lib/memory/HandleDescriptorManger.java diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/HandleDescriptorManger.java b/src/main/java/me/cortex/vulkanite/lib/memory/HandleDescriptorManger.java deleted file mode 100644 index d50ab0b..0000000 --- a/src/main/java/me/cortex/vulkanite/lib/memory/HandleDescriptorManger.java +++ /dev/null @@ -1,38 +0,0 @@ -package me.cortex.vulkanite.lib.memory; - -import com.sun.jna.Pointer; -import com.sun.jna.platform.linux.LibC; -import com.sun.jna.platform.win32.Kernel32; -import com.sun.jna.platform.win32.WinNT; -import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -import me.cortex.vulkanite.client.Vulkanite; - -public class HandleDescriptorManger { - private static final Long2IntOpenHashMap USED_HANDLE_DESCRIPTORS = new Long2IntOpenHashMap(); - public static void add(long handleDescriptor) { - synchronized (USED_HANDLE_DESCRIPTORS) { - USED_HANDLE_DESCRIPTORS.addTo(handleDescriptor, 1); - } - } - - public static void close(long handleDescriptor) { - synchronized (USED_HANDLE_DESCRIPTORS) { - int val = USED_HANDLE_DESCRIPTORS.addTo(handleDescriptor, -1); - if (val <= 0) { - throw new IllegalStateException(); - } - if (val == 1) { - USED_HANDLE_DESCRIPTORS.remove(handleDescriptor); - if (Vulkanite.IS_WINDOWS) { - if (!Kernel32.INSTANCE.CloseHandle(new WinNT.HANDLE(new Pointer(handleDescriptor)))) { - throw new IllegalStateException(); - } - } else { - if (LibC.INSTANCE.close((int) handleDescriptor) != 0) { - throw new IllegalStateException(); - } - } - } - } - } -} diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java b/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java index 746ba1f..6577876 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java @@ -40,7 +40,7 @@ import static org.lwjgl.vulkan.VK11.VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; public class MemoryManager { - private static final int EXTERNAL_MEMORY_HANDLE_TYPE = Vulkanite.IS_WINDOWS?VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; + private static final int EXTERNAL_MEMORY_HANDLE_TYPE = Vulkanite.IS_WINDOWS?VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; private final VkDevice device; private final VmaAllocator allocator; private final boolean hasDeviceAddresses; @@ -74,7 +74,7 @@ public static int acquire(VmaAllocator.Allocation allocation, VkDevice device, b _CHECK_(vkGetMemoryWin32HandleKHR(device, VkMemoryGetWin32HandleInfoKHR.calloc(stack) .sType$Default() .memory(vkMemory) - .handleType(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT), pb)); + .handleType(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT), pb)); nativeHandle = pb.get(0); } else { IntBuffer pb = stack.callocInt(1); @@ -103,7 +103,7 @@ public static int acquire(VmaAllocator.Allocation allocation, VkDevice device, b if (Vulkanite.IS_WINDOWS) { glImportMemoryWin32HandleEXT(newMemoryObject, memorySize, - GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT, nativeHandle); + GL_HANDLE_TYPE_OPAQUE_WIN32_EXT, nativeHandle); _CHECK_GL_ERROR_(); } else { glImportMemoryFdEXT(newMemoryObject, memorySize, @@ -135,11 +135,11 @@ public static void release(long memory) { glDeleteMemoryObjectsEXT(tracked.desc.glMemoryObj); _CHECK_GL_ERROR_(); if (Vulkanite.IS_WINDOWS) { - // if (!Kernel32.INSTANCE.CloseHandle(new WinNT.HANDLE(new Pointer(tracked.desc.handle)))) { - // int error = Kernel32.INSTANCE.GetLastError(); - // System.err.println("STATE MIGHT BE BROKEN! Failed to close handle: " + error); - // throw new IllegalStateException(); - // } + if (!Kernel32.INSTANCE.CloseHandle(new WinNT.HANDLE(new Pointer(tracked.desc.handle)))) { + int error = Kernel32.INSTANCE.GetLastError(); + System.err.println("STATE MIGHT BE BROKEN! Failed to close handle: " + error); + throw new IllegalStateException(); + } } else { int code = 0; if ((code = LibC.INSTANCE.close((int) tracked.desc.handle)) != 0) { diff --git a/src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java b/src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java index 7c84429..346f0b5 100644 --- a/src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java @@ -2,7 +2,6 @@ import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.lib.base.VRef; -import me.cortex.vulkanite.lib.memory.HandleDescriptorManger; import org.lwjgl.PointerBuffer; import org.lwjgl.vulkan.*; @@ -15,7 +14,6 @@ import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; import static org.lwjgl.opengl.EXTMemoryObjectFD.GL_HANDLE_TYPE_OPAQUE_FD_EXT; -import static org.lwjgl.opengl.EXTMemoryObjectFD.glImportMemoryFdEXT; import static org.lwjgl.opengl.EXTSemaphore.glGenSemaphoresEXT; import static org.lwjgl.opengl.EXTSemaphore.glIsSemaphoreEXT; import static org.lwjgl.opengl.EXTSemaphoreFD.glImportSemaphoreFdEXT; @@ -72,7 +70,6 @@ private VRef createSharedBinarySemaphoreWin32() { if (pb.get(0)== 0) { throw new IllegalStateException(); } - HandleDescriptorManger.add(pb.get(0)); int glSemaphore = glGenSemaphoresEXT(); glImportSemaphoreWin32HandleEXT(glSemaphore, GL_HANDLE_TYPE_OPAQUE_WIN32_EXT, pb.get(0)); @@ -108,7 +105,6 @@ private VRef createSharedBinarySemaphoreFd() { if (fd.get(0)== 0) { throw new IllegalStateException(); } - HandleDescriptorManger.add(fd.get(0)); int glSemaphore = glGenSemaphoresEXT(); glImportSemaphoreFdEXT(glSemaphore, GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd.get(0)); diff --git a/src/main/java/me/cortex/vulkanite/lib/other/sync/VGSemaphore.java b/src/main/java/me/cortex/vulkanite/lib/other/sync/VGSemaphore.java index c89f3de..af73acd 100644 --- a/src/main/java/me/cortex/vulkanite/lib/other/sync/VGSemaphore.java +++ b/src/main/java/me/cortex/vulkanite/lib/other/sync/VGSemaphore.java @@ -1,9 +1,11 @@ package me.cortex.vulkanite.lib.other.sync; +import com.sun.jna.Pointer; +import com.sun.jna.platform.linux.LibC; +import com.sun.jna.platform.win32.Kernel32; +import com.sun.jna.platform.win32.WinNT; import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.lib.base.VRef; -import me.cortex.vulkanite.lib.memory.HandleDescriptorManger; -import me.cortex.vulkanite.lib.memory.MemoryManager; import org.lwjgl.vulkan.VkDevice; import static org.lwjgl.opengl.EXTSemaphore.*; @@ -24,11 +26,20 @@ public static VRef create(VkDevice device, long semaphore, int glSe @Override protected void free() { - HandleDescriptorManger.close(handleDescriptor); - int glSemaphore = this.glSemaphore; - Vulkanite.INSTANCE.addSyncedCallback(() -> { - glDeleteSemaphoresEXT(glSemaphore); - }); + glDeleteSemaphoresEXT(this.glSemaphore); + if (Vulkanite.IS_WINDOWS) { + if (!Kernel32.INSTANCE.CloseHandle(new WinNT.HANDLE(new Pointer(handleDescriptor)))) { + int error = Kernel32.INSTANCE.GetLastError(); + System.err.println("STATE MIGHT BE BROKEN! Failed to close handle: " + error); + throw new IllegalStateException(); + } + } else { + int code = 0; + if ((code = LibC.INSTANCE.close((int) handleDescriptor)) != 0) { + System.err.println("STATE MIGHT BE BROKEN! Failed to close FD: " + code); + throw new IllegalStateException(); + } + } super.free(); } From e30dfd39b8b1dc668f4d5c0d63ed98a9d19d8b52 Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Fri, 24 May 2024 22:21:09 -0700 Subject: [PATCH 12/22] try to fix zink --- .../me/cortex/vulkanite/client/Vulkanite.java | 16 ++- .../client/rendering/VulkanPipeline.java | 2 +- .../vulkanite/lib/cmd/CommandManager.java | 21 ++- .../vulkanite/lib/memory/MemoryManager.java | 17 ++- .../vulkanite/lib/memory/VmaAllocator.java | 126 +++++++++++++----- .../vulkanite/lib/other/sync/SyncManager.java | 7 +- 6 files changed, 133 insertions(+), 56 deletions(-) diff --git a/src/main/java/me/cortex/vulkanite/client/Vulkanite.java b/src/main/java/me/cortex/vulkanite/client/Vulkanite.java index 1e6e6d3..a2d2460 100644 --- a/src/main/java/me/cortex/vulkanite/client/Vulkanite.java +++ b/src/main/java/me/cortex/vulkanite/client/Vulkanite.java @@ -9,6 +9,7 @@ import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; import net.minecraft.util.Util; +import org.lwjgl.opengl.GL20; import org.lwjgl.vulkan.*; import java.util.ArrayList; @@ -39,11 +40,10 @@ public class Vulkanite { public static final boolean IS_WINDOWS = Util.getOperatingSystem() == Util.OperatingSystem.WINDOWS; - public static boolean MEMORY_LEAK_TRACING = true; - public static boolean IS_ENABLED = true; public static Vulkanite INSTANCE = new Vulkanite(); + public final boolean IS_ZINK; private final VContext ctx; private final ArbitarySyncPointCallback fencedCallback = new ArbitarySyncPointCallback(); @@ -55,6 +55,18 @@ public Vulkanite() { // Hack: so that AccelerationManager can access Vulkanite.INSTANCE INSTANCE = this; + // Check GL_VENDOR to determine if Zink is being used + final var gl_vendor = GL20.glGetString(GL20.GL_VENDOR); + final var gl_renderer = GL20.glGetString(GL20.GL_RENDERER); + if (gl_vendor == null || gl_renderer == null) { + IS_ZINK = false; + } else { + IS_ZINK = gl_vendor.contains("Mesa") && gl_renderer.contains("zink"); + if (IS_ZINK) { + System.out.println("Zink GL detected"); + } + } + //Fill in the shared index buffer with a large count so we (hopefully) dont have to worry about it anymore // SharedQuadVkIndexBuffer.getIndexBuffer(ctx, 30000); diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java index 18fe887..5424a35 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java @@ -428,7 +428,7 @@ public void renderPostShadows(List> vgOutImgs, Camera camera, Shad out.close(); VRegistry.INSTANCE.threadLocalCollect(); - System.out.println(VRegistry.INSTANCE.dumpStats()); + // System.out.println(VRegistry.INSTANCE.dumpStats()); } public void destory() { diff --git a/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java b/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java index 3ddd648..724c7d2 100644 --- a/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java @@ -8,6 +8,7 @@ import it.unimi.dsi.fastutil.ints.Int2LongArrayMap; import it.unimi.dsi.fastutil.ints.Int2LongMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectSortedMap; import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.other.sync.VFence; import me.cortex.vulkanite.lib.other.sync.VSemaphore; @@ -141,9 +142,11 @@ public void newFrame() { } private static class Queue { + private record Submission(long t, VRef ref) {} + public final VkQueue queue; private final Int2LongArrayMap waitingFor = new Int2LongArrayMap(); - private final Long2ObjectOpenHashMap> submitted = new Long2ObjectOpenHashMap<>(); + private final List submitted = new ArrayList<>(); public final VRef timelineSema; // public final Deque frameTimestamps = new ArrayDeque<>(3); public AtomicLong timeline = new AtomicLong(1); @@ -194,17 +197,13 @@ public void collect() { synchronized (submitted) { long completedTimestamp = this.completedTimestamp.get(); - submitted.forEach((time, cmdRef) -> { - if (time <= completedTimestamp) { - cmdRef.close(); + submitted.removeIf((rec) -> { + if (rec.t <= completedTimestamp) { + rec.ref.close(); + return true; } + return false; }); - - for (long key : submitted.keySet()) { - if (key <= completedTimestamp) { - submitted.remove(key); - } - } } } @@ -307,7 +306,7 @@ public long submit(final VRef cmdBuff, Queue[] queues, List createSharedImage(int dimensions, int width, int height, in var createInfo = VkImageCreateInfo .calloc(stack) .sType$Default() - .usage(usage) .pNext(VkExternalMemoryImageCreateInfo.calloc(stack) .sType$Default() .handleTypes(EXTERNAL_MEMORY_HANDLE_TYPE)) + .usage(usage) .format(vkFormat) .imageType(vkImageType) .mipLevels(mipLevels) .arrayLayers(1) .tiling(VK_IMAGE_TILING_OPTIMAL) .initialLayout(VK_IMAGE_LAYOUT_UNDEFINED) - .usage(usage) .samples(VK_SAMPLE_COUNT_1_BIT); createInfo.extent().width(width).height(height).depth(depth); @@ -222,6 +226,7 @@ public VRef createSharedImage(int dimensions, int width, int height, in int memoryObject = ExternalMemoryTracker.acquire(alloc, device, alloc.isDedicated()); int glId = glCreateTextures(glImageType); + glTextureParameteri(glId, GL_TEXTURE_TILING_EXT, GL_OPTIMAL_TILING_EXT); switch(glImageType) { case GL_TEXTURE_1D: diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/VmaAllocator.java b/src/main/java/me/cortex/vulkanite/lib/memory/VmaAllocator.java index 907d9a6..2dca0ea 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/VmaAllocator.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/VmaAllocator.java @@ -1,5 +1,6 @@ package me.cortex.vulkanite.lib.memory; +import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.lib.base.VObject; import org.lwjgl.PointerBuffer; import org.lwjgl.system.MemoryStack; @@ -27,12 +28,13 @@ public class VmaAllocator { private final long sharedBlockSize; - private final VkExportMemoryAllocateInfo exportMemoryAllocateInfo; - private record ImageFormatQuery(int format, int imageType, int tiling, int usage, int flags) {} private record ImageFormatQueryResult(boolean supported, ImageFormatQuery updatedParams) {} private HashMap formatSupportCache = new HashMap<>(); + private final VkExportMemoryAllocateInfo exportMemoryAllocateInfo; + private final VkExportMemoryAllocateInfo exportDedicatedMemoryAllocateInfo; + boolean testModifyFormatSupport(VkDevice device, VkImageCreateInfo imageCreateInfo) { var query = new ImageFormatQuery(imageCreateInfo.format(), imageCreateInfo.imageType(), imageCreateInfo.tiling(), imageCreateInfo.usage(), imageCreateInfo.flags()); @@ -109,7 +111,44 @@ public VmaAllocator(VkDevice device, boolean enableDeviceAddresses, long sharedB allocator = pAllocator.get(0); - int sharedPoolMemoryTypeIndex; + { + // Create the pool for dedicated allocation + var imageCreateInfo = VkImageCreateInfo.calloc(stack) + .sType$Default() + .imageType(VK_IMAGE_TYPE_2D) + .format(VK_FORMAT_R8G8B8A8_UNORM) + .extent(e -> e.set(512, 512, 1)) + .mipLevels(1) + .arrayLayers(1) + .samples(VK_SAMPLE_COUNT_1_BIT) + .tiling(VK_IMAGE_TILING_OPTIMAL) + .usage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT) + .sharingMode(VK_SHARING_MODE_EXCLUSIVE) + .initialLayout(VK_IMAGE_LAYOUT_UNDEFINED); + var allocationCreateInfo = VmaAllocationCreateInfo.calloc(stack).usage(VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE) + .requiredFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + IntBuffer pMemoryTypeIndex = stack.callocInt(1); + if (vmaFindMemoryTypeIndexForImageInfo(allocator, imageCreateInfo, allocationCreateInfo, + pMemoryTypeIndex) != VK_SUCCESS) { + throw new RuntimeException("Failed to find memory type index for shared pool"); + } + int sharedDedicatedPoolMemoryTypeIndex = pMemoryTypeIndex.get(0); + + exportDedicatedMemoryAllocateInfo = VkExportMemoryAllocateInfo.calloc() + .sType$Default() + .pNext(0) + .handleTypes(sharedHandleType); + + VmaPoolCreateInfo pci = VmaPoolCreateInfo.calloc(stack) + .memoryTypeIndex(sharedDedicatedPoolMemoryTypeIndex) + .pMemoryAllocateNext(exportDedicatedMemoryAllocateInfo.address()); + PointerBuffer pb = stack.callocPointer(1); + if (vmaCreatePool(allocator, pci, pb) != VK_SUCCESS) { + throw new RuntimeException("Failed to create sharedDedicatedPool"); + } + sharedDedicatedPool = pb.get(0); + } { var bufferCreateInfo = VkBufferCreateInfo.calloc(stack) @@ -125,30 +164,24 @@ public VmaAllocator(VkDevice device, boolean enableDeviceAddresses, long sharedB pMemoryTypeIndex) != VK_SUCCESS) { throw new RuntimeException("Failed to find memory type index for shared pool"); } - sharedPoolMemoryTypeIndex = pMemoryTypeIndex.get(0); - } - // This object is leaked, yes... - // But we should only have one allocator anyways - exportMemoryAllocateInfo = VkExportMemoryAllocateInfo.calloc() - .sType$Default() - .pNext(0) - .handleTypes(sharedHandleType); + int sharedPoolMemoryTypeIndex = pMemoryTypeIndex.get(0); - VmaPoolCreateInfo pci = VmaPoolCreateInfo.calloc(stack) - .memoryTypeIndex(sharedPoolMemoryTypeIndex) - .pMemoryAllocateNext(exportMemoryAllocateInfo.address()); - PointerBuffer pb = stack.callocPointer(1); - if (vmaCreatePool(allocator, pci, pb) != VK_SUCCESS) { - throw new RuntimeException("Failed to create sharedDedicatedPool"); - } - sharedDedicatedPool = pb.get(0); - - pci.blockSize(sharedBlockSize); - if (vmaCreatePool(allocator, pci, pb) != VK_SUCCESS) { - throw new RuntimeException("Failed to create sharedPool"); + exportMemoryAllocateInfo = VkExportMemoryAllocateInfo.calloc() + .sType$Default() + .pNext(0) + .handleTypes(sharedHandleType); + + VmaPoolCreateInfo pci = VmaPoolCreateInfo.calloc(stack) + .memoryTypeIndex(sharedPoolMemoryTypeIndex) + .blockSize(sharedBlockSize) + .pMemoryAllocateNext(exportMemoryAllocateInfo.address()); + PointerBuffer pb = stack.callocPointer(1); + if (vmaCreatePool(allocator, pci, pb) != VK_SUCCESS) { + throw new RuntimeException("Failed to create sharedPool"); + } + sharedPool = pb.get(0); } - sharedPool = pb.get(0); } } @@ -235,25 +268,54 @@ SharedImageAllocation allocShared(VkImageCreateInfo imageCreateInfo, VmaAllocati testModifyFormatSupport(device, imageCreateInfo); try (var stack = stackPush()) { LongBuffer pb = stack.callocLong(1); - _CHECK_(vkCreateImage(device, imageCreateInfo, null, pb), "Failed to create VkBuffer"); + _CHECK_(vkCreateImage(device, imageCreateInfo, null, pb), "Failed to create VkImage"); long image = pb.get(0); var memReq = VkMemoryRequirements.calloc(stack); vkGetImageMemoryRequirements(device, image, memReq); - allocationCreateInfo.flags(VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) - .pool(sharedDedicatedPool) - .memoryTypeBits(memReq.memoryTypeBits()); + boolean dedicated = memReq.size() > sharedBlockSize; + if (Vulkanite.INSTANCE.IS_ZINK) { + dedicated = false; + } + + if (!dedicated) { + var dedicatedMemReq = VkMemoryDedicatedRequirements.calloc(stack) + .sType$Default() + .pNext(0); + var memReq2 = VkMemoryRequirements2.calloc(stack) + .sType$Default() + .pNext(dedicatedMemReq.address()); + vkGetImageMemoryRequirements2(device, VkImageMemoryRequirementsInfo2 + .calloc(stack) + .sType$Default() + .image(image), memReq2); + if (Vulkanite.INSTANCE.IS_ZINK) { + if (dedicatedMemReq.requiresDedicatedAllocation()) { + throw new RuntimeException("Zink does not support importing dedicated memory, however the Vulkan implementation demands it"); + } + } else { + dedicated = dedicatedMemReq.prefersDedicatedAllocation() || dedicatedMemReq.requiresDedicatedAllocation(); + } + } + + if (dedicated) { + allocationCreateInfo.flags(VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT); + allocationCreateInfo.pool(sharedDedicatedPool); + } else { + allocationCreateInfo.pool(sharedPool); + } + + allocationCreateInfo.memoryTypeBits(memReq.memoryTypeBits()); VmaAllocationInfo vai = VmaAllocationInfo.calloc(); PointerBuffer pAllocation = stack.mallocPointer(1); - _CHECK_( - vmaAllocateMemoryForImage(allocator, image, allocationCreateInfo, pAllocation, vai), - "Failed to allocate memory for image"); + _CHECK_(vmaAllocateMemory(allocator, memReq, allocationCreateInfo, pAllocation, vai), "Failed to allocate memory for image"); + long allocation = pAllocation.get(0); _CHECK_(vmaBindImageMemory(allocator, allocation, image), "failed to bind image memory"); - return new SharedImageAllocation(image, allocation, vai, true); + return new SharedImageAllocation(image, allocation, vai, dedicated); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java b/src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java index 346f0b5..a098c3f 100644 --- a/src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java @@ -13,6 +13,7 @@ import java.util.Map; import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; +import static me.cortex.vulkanite.lib.other.VUtil._CHECK_GL_ERROR_; import static org.lwjgl.opengl.EXTMemoryObjectFD.GL_HANDLE_TYPE_OPAQUE_FD_EXT; import static org.lwjgl.opengl.EXTSemaphore.glGenSemaphoresEXT; import static org.lwjgl.opengl.EXTSemaphore.glIsSemaphoreEXT; @@ -73,10 +74,9 @@ private VRef createSharedBinarySemaphoreWin32() { int glSemaphore = glGenSemaphoresEXT(); glImportSemaphoreWin32HandleEXT(glSemaphore, GL_HANDLE_TYPE_OPAQUE_WIN32_EXT, pb.get(0)); + _CHECK_GL_ERROR_(); if (!glIsSemaphoreEXT(glSemaphore)) throw new IllegalStateException(); - if (glGetError() != GL_NO_ERROR) - throw new IllegalStateException(); return VGSemaphore.create(device, semaphore, glSemaphore, pb.get(0)); } @@ -108,10 +108,9 @@ private VRef createSharedBinarySemaphoreFd() { int glSemaphore = glGenSemaphoresEXT(); glImportSemaphoreFdEXT(glSemaphore, GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd.get(0)); + _CHECK_GL_ERROR_(); if (!glIsSemaphoreEXT(glSemaphore)) throw new IllegalStateException(); - if (glGetError() != GL_NO_ERROR) - throw new IllegalStateException(); return VGSemaphore.create(device, semaphore, glSemaphore, fd.get(0)); } From b02b2ed4fa9830645600f43c5a3601e8d9e6513c Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Fri, 24 May 2024 23:53:02 -0700 Subject: [PATCH 13/22] Fix linux fd --- .../vulkanite/lib/other/sync/SyncManager.java | 13 ++++++++----- .../vulkanite/lib/other/sync/VGSemaphore.java | 8 +++++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java b/src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java index a098c3f..9d7faa3 100644 --- a/src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java @@ -94,25 +94,28 @@ private VRef createSharedBinarySemaphoreFd() { null, res)); long semaphore = res.get(0); - IntBuffer fd = stack.callocInt(1); + IntBuffer fdPtr = stack.callocInt(1); _CHECK_(vkGetSemaphoreFdKHR(device, VkSemaphoreGetFdInfoKHR.calloc(stack) .sType$Default() .semaphore(semaphore) .handleType(EXTERNAL_SEMAPHORE_TYPE), - fd)); + fdPtr)); - if (fd.get(0)== 0) { + int fd = fdPtr.get(0); + + if (fd == 0) { throw new IllegalStateException(); } int glSemaphore = glGenSemaphoresEXT(); - glImportSemaphoreFdEXT(glSemaphore, GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd.get(0)); + glImportSemaphoreFdEXT(glSemaphore, GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd); _CHECK_GL_ERROR_(); if (!glIsSemaphoreEXT(glSemaphore)) throw new IllegalStateException(); - return VGSemaphore.create(device, semaphore, glSemaphore, fd.get(0)); + fd = -1; + return VGSemaphore.create(device, semaphore, glSemaphore, fd); } } diff --git a/src/main/java/me/cortex/vulkanite/lib/other/sync/VGSemaphore.java b/src/main/java/me/cortex/vulkanite/lib/other/sync/VGSemaphore.java index af73acd..324690b 100644 --- a/src/main/java/me/cortex/vulkanite/lib/other/sync/VGSemaphore.java +++ b/src/main/java/me/cortex/vulkanite/lib/other/sync/VGSemaphore.java @@ -35,9 +35,11 @@ protected void free() { } } else { int code = 0; - if ((code = LibC.INSTANCE.close((int) handleDescriptor)) != 0) { - System.err.println("STATE MIGHT BE BROKEN! Failed to close FD: " + code); - throw new IllegalStateException(); + if (handleDescriptor != -1) { + if ((code = LibC.INSTANCE.close((int) handleDescriptor)) != 0) { + System.err.println("STATE MIGHT BE BROKEN! Failed to close FD: " + code); + throw new IllegalStateException(); + } } } super.free(); From aa14e740f43c91e31841d4aad293f7ffca80ec93 Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Sat, 25 May 2024 02:15:45 -0700 Subject: [PATCH 14/22] ... accidentaly broke dedicated image alloc, fixed it now --- .../vulkanite/acceleration/AccelerationBlasBuilder.java | 5 ----- .../java/me/cortex/vulkanite/lib/memory/MemoryManager.java | 2 +- .../java/me/cortex/vulkanite/lib/memory/VmaAllocator.java | 2 +- .../java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java | 2 ++ .../vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java | 2 ++ .../me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java | 2 +- 6 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java index d16a18f..13540af 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationBlasBuilder.java @@ -383,11 +383,6 @@ private void run() { } - - private void uploadTerrainGeometry(BuiltSectionMeshParts meshParts, VRef buffer, long destOffset, VCmdBuff cmd) { - cmd.encodeDataUpload(context.memory, MemoryUtil.memAddress(meshParts.getVertexData().getDirectBuffer()), buffer, destOffset, meshParts.getVertexData().getLength()); - } - // Enqueues jobs of section blas builds // NOTE: This is on a different thread! public void enqueue(List batch) { diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java b/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java index 276118c..a7d189d 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java @@ -112,7 +112,7 @@ public static int acquire(VmaAllocator.Allocation allocation, VkDevice device, b nativeHandle = -1; } - System.out.println("Imported memory object: " + newMemoryObject + " with handle: " + nativeHandle + " and size: " + memorySize); + System.out.println("Imported memory object: " + newMemoryObject + " with handle: " + nativeHandle + " and size: " + ((double)memorySize / 1024 / 1024) + "MB"); if (newMemoryObject == 0) throw new IllegalStateException(); diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/VmaAllocator.java b/src/main/java/me/cortex/vulkanite/lib/memory/VmaAllocator.java index 2dca0ea..311180e 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/VmaAllocator.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/VmaAllocator.java @@ -310,7 +310,7 @@ SharedImageAllocation allocShared(VkImageCreateInfo imageCreateInfo, VmaAllocati VmaAllocationInfo vai = VmaAllocationInfo.calloc(); PointerBuffer pAllocation = stack.mallocPointer(1); - _CHECK_(vmaAllocateMemory(allocator, memReq, allocationCreateInfo, pAllocation, vai), "Failed to allocate memory for image"); + _CHECK_(vmaAllocateMemoryForImage(allocator, image, allocationCreateInfo, pAllocation, vai), "Failed to allocate memory for image"); long allocation = pAllocation.get(0); _CHECK_(vmaBindImageMemory(allocator, allocation, image), "failed to bind image memory"); diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java index 1a6645d..77cb79f 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java @@ -18,6 +18,7 @@ import java.nio.ByteBuffer; +import static me.cortex.vulkanite.lib.other.VUtil._CHECK_GL_ERROR_; import static org.lwjgl.opengl.GL11C.*; import static org.lwjgl.vulkan.VK10.*; @@ -82,6 +83,7 @@ private void redirectUpload(TextureType instance, int glId, int width, int heigh GL30.glTexSubImage3D(target, 0, 0, 0, 0, width, height, depth, format, pixelType, data); break; } + _CHECK_GL_ERROR_(); } @Overwrite diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java index 93618bb..fc22aa7 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java @@ -34,6 +34,8 @@ import java.util.Comparator; import java.util.List; +import static org.lwjgl.opengl.GL11.glFinish; + @Mixin(value = NewWorldRenderingPipeline.class, remap = false) public class MixinNewWorldRenderingPipeline { diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java index 2149b01..6418abd 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java @@ -83,7 +83,7 @@ private void setupTextures(int width, int height, boolean allowsLinear) { @Redirect(method = "destroy", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_deleteTextures([I)V")) private void redirectResize(int[] textures) { - glFinish(); +// glFinish(); //TODO: block the gpu fully before deleting and resizing the textures vgMainTexture = null; vgAltTexture = null; From 71e26556aa96fd66c6aa62fa37e4841a30628cf3 Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Sun, 2 Jun 2024 16:25:56 -0700 Subject: [PATCH 15/22] Entities mate! --- .../acceleration/AccelerationTLASManager.java | 559 +++++++++++------- .../acceleration/EntityBlasBuilder.java | 147 +++-- .../acceleration/GeometryRayFlags.java | 14 + .../client/rendering/EntityCapture.java | 21 +- .../client/rendering/VulkanPipeline.java | 24 +- .../me/cortex/vulkanite/lib/base/VObject.java | 8 +- .../me/cortex/vulkanite/lib/base/VRef.java | 60 +- .../me/cortex/vulkanite/lib/cmd/VCmdBuff.java | 18 + .../descriptors/DescriptorUpdateBuilder.java | 18 +- .../lib/descriptors/VDescriptorSet.java | 26 +- .../vulkanite/lib/memory/MemoryManager.java | 13 +- .../me/cortex/vulkanite/lib/other/VUtil.java | 9 + .../vulkanite/mixin/iris/MixinGlTexture.java | 1 - .../iris/MixinNewWorldRenderingPipeline.java | 19 +- 14 files changed, 589 insertions(+), 348 deletions(-) create mode 100644 src/main/java/me/cortex/vulkanite/acceleration/GeometryRayFlags.java diff --git a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java index 2cf6496..6a49e1a 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/AccelerationTLASManager.java @@ -3,16 +3,16 @@ //TLAS manager, ingests blas build requests and manages builds and syncs the tlas import com.mojang.blaze3d.systems.RenderSystem; -import me.cortex.vulkanite.client.Vulkanite; +import it.unimi.dsi.fastutil.ints.IntArrayFIFOQueue; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.base.VObject; import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.cmd.VCmdBuff; -import me.cortex.vulkanite.lib.cmd.VCommandPool; import me.cortex.vulkanite.lib.descriptors.*; import me.cortex.vulkanite.lib.memory.VAccelerationStructure; import me.cortex.vulkanite.lib.memory.VBuffer; -import me.cortex.vulkanite.lib.other.sync.VFence; -import me.cortex.vulkanite.lib.other.sync.VSemaphore; import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.RenderLayer; @@ -37,6 +37,7 @@ public class AccelerationTLASManager { private final TLASSectionManager buildDataManager = new TLASSectionManager(); private final VContext context; private final int queue; + private List> entityData; public AccelerationTLASManager(VContext context, int queue) { this.context = context; @@ -45,6 +46,17 @@ public AccelerationTLASManager(VContext context, int queue) { this.entityBlasBuilder = new EntityBlasBuilder(context); } + private static int roundUpPow2(int v) { + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + return v; + } + // Returns a sync semaphore to chain in the next command submit public void updateSections(List results) { for (var result : results) { @@ -56,13 +68,10 @@ public void updateSections(List results } } - - private List> entityData; public void setEntityData(List> data) { this.entityData = data; } - public void removeSection(RenderSection section) { buildDataManager.remove(section); } @@ -81,28 +90,35 @@ public VRef buildTLAS(VCmdBuff cmd) { // this is done for performance reasons when updating (adding/removing) sections VkAccelerationStructureGeometryKHR geometry = VkAccelerationStructureGeometryKHR.calloc(stack); - int instances = buildDataManager.sectionCount(); - Pair, VRef> entityBuild; if (entityData != null) { - entityBuild = entityBlasBuilder.buildBlas(entityData, cmd); - } else { - entityBuild = null; - } + var entityBuild = entityBlasBuilder.buildBlas(entityData, cmd); - VkAccelerationStructureInstanceKHR extra = null; - if (entityBuild != null) { - extra = VkAccelerationStructureInstanceKHR.calloc(stack); - extra.mask(~0) - .instanceCustomIndex(0) - .instanceShaderBindingTableRecordOffset(1) - .accelerationStructureReference(entityBuild.getLeft().get().deviceAddress); - extra.transform().matrix(new Matrix4x3f().getTransposed(stack.mallocFloat(12))); - buildDataManager.descUpdateJobs.add(new TLASSectionManager.DescUpdateJob(0, 0, entityBuild.getRight(), List.of(0L))); - instances++; + for (var entityBatch : entityBuild) { + if (entityBatch.offsets().isEmpty()) { + continue; + } + + var entityASI = VkAccelerationStructureInstanceKHR.calloc(stack) + .mask(~0) + .instanceShaderBindingTableRecordOffset(1); + entityASI.transform().matrix(new Matrix4x3f().getTransposed(stack.mallocFloat(12))); + + buildDataManager.addEphemeralInstance(cmd, entityASI, entityBatch.structure(), entityBatch.geometry(), entityBatch.offsets()); + entityBatch.geometry().close(); + entityBatch.structure().close(); + } } - var instanceBuffer = buildDataManager.getInstanceBuffer(extra); + // getInstanceBuffer also builds / updates the geometry desc set + var rets = buildDataManager.getInstanceBuffer(); + var instanceBuffer = rets.getLeft(); + int numInstances = rets.getRight(); + + for (var holderRef : buildDataManager.activeSections.values()) { + // Let the cmdbuf manage the lifetime of the holder & desc set entry + cmd.moveRefGeneric(holderRef.addRefGeneric()); + } geometry.sType$Default() .geometryType(VK_GEOMETRY_TYPE_INSTANCES_KHR) @@ -118,7 +134,6 @@ public VRef buildTLAS(VCmdBuff cmd) { .data() .deviceAddress(instanceBuffer.get().deviceAddress()); - // TLAS always rebuild & PREFER_FAST_TRACE according to Nvidia var buildInfo = VkAccelerationStructureBuildGeometryInfoKHR.calloc(1, stack) .sType$Default() @@ -132,7 +147,7 @@ public VRef buildTLAS(VCmdBuff cmd) { .calloc(stack) .sType$Default(); - int[] instanceCounts = new int[]{instances}; + int[] instanceCounts = new int[]{numInstances}; vkGetAccelerationStructureBuildSizesKHR( context.device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, @@ -182,6 +197,50 @@ public VRef buildTLAS(VCmdBuff cmd) { } } + public VRef getGeometrySet() { + return buildDataManager.geometryBufferDescSet.addRef(); + } + + public VRef getGeometryLayout() { + return buildDataManager.geometryBufferSetLayout.addRef(); + } + + private static final class TlasPointerArena { + private final BitSet vacant; + public int maxIndex = 0; + + private TlasPointerArena(int size) { + size *= 3; + vacant = new BitSet(size); + vacant.set(0, size); + } + + public int allocate(int count) { + int pos = vacant.nextSetBit(0); + outer: + while (pos != -1) { + for (int offset = 1; offset < count; offset++) { + if (!vacant.get(offset + pos)) { + pos = vacant.nextSetBit(offset + pos + 1); + continue outer; + } + } + break; + } + if (pos == -1) { + throw new IllegalStateException(); + } + vacant.clear(pos, pos + count); + maxIndex = Math.max(maxIndex, pos + count); + return pos; + } + + public void free(int pos, int count) { + vacant.set(pos, pos + count); + + maxIndex = vacant.previousClearBit(maxIndex) + 1; + } + } // Manages entries in the VkAccelerationStructureInstanceKHR buffer, ment to // reuse as much as possible and be very efficient @@ -195,132 +254,150 @@ private class TLASGeometryManager { // Needs a gpu buffer for the instance data, this can be reused // private VkAccelerationStructureInstanceKHR.Buffer buffer; - private VkAccelerationStructureInstanceKHR.Buffer instances = VkAccelerationStructureInstanceKHR.calloc(30000); - private int[] instance2pointer = new int[30000]; - private int[] pointer2instance = new int[30000]; - private BitSet free = new BitSet(30000);// The reason this is needed is to give non used instance ids - private int count; + private final IntArrayFIFOQueue freeIds = new IntArrayFIFOQueue(); + private int maxInstances = 0; + private VkAccelerationStructureInstanceKHR.Buffer instances = null; + private int count = 0; + // This maps each location in the instance buffer to an id + private int[] loc2id = new int[maxInstances]; + // This maps each id to a location in the instance buffer + private int[] id2loc = new int[maxInstances]; public TLASGeometryManager() { - free.set(0, instance2pointer.length); + resize(32768); } - // TODO: make the instances buffer, gpu permenent then stream updates instead of - // uploading per frame - public VRef getInstanceBuffer(VkAccelerationStructureInstanceKHR addin) { - long size = (long) VkAccelerationStructureInstanceKHR.SIZEOF * count; - long newSize = size + (addin==null?0:VkAccelerationStructureInstanceKHR.SIZEOF); - if (newSize == 0) { - System.err.println("Instance buffer has a new size of 0, something is wrong."); - newSize = VkAccelerationStructureInstanceKHR.SIZEOF; - } - var data = context.memory.createBuffer(newSize, - VK_BUFFER_USAGE_TRANSFER_DST_BIT - | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR - | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, - VK_MEMORY_HEAP_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - 0, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); - data.get().setDebugUtilsObjectName("TLAS Instance Buffer"); - long ptr = data.get().map(); - if (addin != null) { - MemoryUtil.memCopy(addin.address(), ptr, VkAccelerationStructureInstanceKHR.SIZEOF); - ptr += VkAccelerationStructureInstanceKHR.SIZEOF; - } - MemoryUtil.memCopy(this.instances.address(0), ptr, size); + public void resize(int newSize) { + if (newSize > maxInstances) { + newSize = roundUpPow2(newSize); + + // Resize the instance buffer + VkAccelerationStructureInstanceKHR.Buffer newBuffer = VkAccelerationStructureInstanceKHR + .calloc(newSize); + if (instances != null) { + newBuffer.put(instances); + newBuffer.rewind(); + instances.free(); + } + instances = newBuffer; - data.get().unmap(); - data.get().flush(); + // Add new ids to the free list + for (int i = maxInstances; i < newSize; i++) { + freeIds.enqueue(i); + } - return data; - } + // Resize the id mapping arrays + int[] newLoc2Id = new int[newSize]; + int[] newId2Loc = new int[newSize]; + System.arraycopy(loc2id, 0, newLoc2Id, 0, count); + System.arraycopy(id2loc, 0, newId2Loc, 0, count); + loc2id = newLoc2Id; + id2loc = newId2Loc; - public int sectionCount() { - return count; + maxInstances = newSize; + } } - protected int alloc() { - int id = free.nextSetBit(0); + protected int alloc(VkAccelerationStructureInstanceKHR instance) { + // Increment the count + count++; + resize(count); - free.clear(id); + // Get a free id + int id = freeIds.dequeueInt(); - // Update the map - instance2pointer[id] = count; - pointer2instance[count] = id; + // The instances buffer is dense + // Allocation always append to the end + loc2id[count - 1] = id; + id2loc[id] = count - 1; - // Increment the count - count++; + // Copy the instance to the buffer + MemoryUtil.memCopy(instance.address(), instances.address(count - 1), VkAccelerationStructureInstanceKHR.SIZEOF); return id; } protected void free(int id) { - free.set(id); + if (id < 0) { + throw new IllegalArgumentException("Invalid id"); + } + + freeIds.enqueue(id); + + int loc = id2loc[id]; + id2loc[id] = -1; + loc2id[loc] = -1; count--; - if (instance2pointer[id] == count) { - // We are at the end of the pointer list, so just decrement and be done - instance2pointer[id] = -1; - pointer2instance[count] = -1; - } else { - // TODO: CHECK THIS IS CORRECT - - // We need to remove the pointer, and fill it in with the last element in the - // pointer array, updating the mapping of the moved - int ptrId = instance2pointer[id]; - instance2pointer[id] = -1; - - // I feel like this should be pointer2instance = pointer2instance - pointer2instance[ptrId] = pointer2instance[count]; - - // move over the ending data to the missing hole point - MemoryUtil.memCopy(instances.address(count), instances.address(ptrId), + if (loc != count) { + // Move the last element to the hole + int lastId = loc2id[count]; + loc2id[count] = -1; + loc2id[loc] = lastId; + id2loc[lastId] = loc; + MemoryUtil.memCopy(instances.address(count), instances.address(loc), VkAccelerationStructureInstanceKHR.SIZEOF); - - instance2pointer[pointer2instance[count]] = ptrId; } } - protected void update(int id, VkAccelerationStructureInstanceKHR data) { - MemoryUtil.memCopy(data.address(), instances.address(instance2pointer[id]), - VkAccelerationStructureInstanceKHR.SIZEOF); + private final List ephemeralInstances = new ArrayList<>(); + + public void addEphemeralInstance(VkAccelerationStructureInstanceKHR asi) { + var newASI = VkAccelerationStructureInstanceKHR.calloc(); + newASI.set(asi); + ephemeralInstances.add(newASI); } - } - private static int roundUpPow2(int v) { - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; - return v; - } + public Pair, Integer> getInstanceBuffer() { + int count = this.count + ephemeralInstances.size(); - private final class TLASSectionManager extends TLASGeometryManager { - private final TlasPointerArena arena = new TlasPointerArena(30000); + long size = VkAccelerationStructureInstanceKHR.SIZEOF * (long) count; + if (size == 0) { + size = VkAccelerationStructureInstanceKHR.SIZEOF; + } + var data = context.memory.createBuffer(size, + VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR + | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + VK_MEMORY_HEAP_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + 0, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); + data.get().setDebugUtilsObjectName("TLAS Instance Buffer"); - public TLASSectionManager() { - //Allocate index 0 to entity blas - if (arena.allocate(1) != 0) { - throw new IllegalStateException(); + long persistentSize = VkAccelerationStructureInstanceKHR.SIZEOF * (long) this.count; + long ptr = data.get().map(); + if (persistentSize > 0) { + MemoryUtil.memCopy(this.instances.address(0), ptr, persistentSize); + } + + ptr = ptr + persistentSize; + for (var asi : ephemeralInstances) { + MemoryUtil.memCopy(asi.address(), ptr, VkAccelerationStructureInstanceKHR.SIZEOF); + ptr += VkAccelerationStructureInstanceKHR.SIZEOF; + asi.free(); } + ephemeralInstances.clear(); + + data.get().unmap(); + data.get().flush(); + + return new Pair<>(data, count); } + } + private final class TLASSectionManager extends TLASGeometryManager { + private final TlasPointerArena arena = new TlasPointerArena(30000); + private final ConcurrentLinkedDeque sectionUpdates = new ConcurrentLinkedDeque<>(); + private final ConcurrentLinkedDeque sectionRemovals = new ConcurrentLinkedDeque<>(); + private final Map> activeSections = new HashMap<>(); + private final ArrayList descriptorUpdateJobs = new ArrayList<>(); private VRef geometryBufferSetLayout; private VRef geometryBufferDescSet = null; - private int setCapacity = 0; - private record DescUpdateJob(int binding, int dstArrayElement, VRef geometryBuffer, List geometryBufferOffsets) { - } - - private record ArenaDeallocJob(int index, int count, VRef geometryBuffer) { + public TLASSectionManager() { + super(); } - private final ConcurrentLinkedDeque descUpdateJobs = new ConcurrentLinkedDeque<>(); - private final ConcurrentLinkedDeque arenaDeallocJobs = new ConcurrentLinkedDeque<>(); - public void resizeBindlessSet(int newSize) { if (geometryBufferSetLayout == null) { var layoutBuilder = new DescriptorSetLayoutBuilder( @@ -353,143 +430,179 @@ public void resizeBindlessSet(int newSize) { } @Override - public VRef getInstanceBuffer(VkAccelerationStructureInstanceKHR addin) { - resizeBindlessSet(arena.maxIndex); + public Pair, Integer> getInstanceBuffer() { + HashSet removals = new HashSet<>(); + { + RenderSection section; + while ((section = sectionRemovals.poll()) != null) { + removals.add(section); + } + } - if (!descUpdateJobs.isEmpty()) { - var dub = new DescriptorUpdateBuilder(context, descUpdateJobs.size()); - dub.set(geometryBufferDescSet); - while (!descUpdateJobs.isEmpty()) { - var job = descUpdateJobs.poll(); - dub.buffer(job.binding, job.dstArrayElement, job.geometryBuffer, job.geometryBufferOffsets); + // Filter updates to only the latest + HashMap updates = new HashMap<>(); + { + AccelerationBlasBuilder.BLASBuildResult result; + while ((result = sectionUpdates.poll()) != null) { + var data = result.data(); + var section = data.section(); + if (removals.contains(section)) { + // Already removed, close the buffers and continue + result.structure().close(); + data.geometryBuffer().close(); + } else { + // We process the updates sequentially + // Older updates are overwritten + var key = section.getPosition(); + if (updates.containsKey(key)) { + var prev = updates.get(key); + prev.structure().close(); + prev.data().geometryBuffer().close(); + } + updates.put(key, result); + } } - dub.apply(); } - // Since we have residency tracking through the descriptor set, - // we can free the buffers immediately - collect(); + // Process removals + for (var section : removals) { + var prev = activeSections.remove(section.getPosition()); + if (prev != null) { + free(prev.get().id); + prev.close(); + } + } - return super.getInstanceBuffer(addin); - } + int newGeoms = 0; + for (var entry : updates.entrySet()) { + newGeoms += entry.getValue().data().bufferOffsets().size(); + } + resizeBindlessSet(Integer.max(arena.maxIndex + newGeoms, 1024)); - // TODO: mixinto RenderSection and add a reference to a holder for us, its much - // faster than a hashmap - private static final class Holder { - final int id; - int geometryIndex = -1; - VRef geometryBuffer; - List geometryBufferOffsets; + // Process updates + if (!updates.isEmpty() || !descriptorUpdateJobs.isEmpty()) { + var dub = new DescriptorUpdateBuilder(context, updates.size() + descriptorUpdateJobs.size()); + dub.set(geometryBufferDescSet); - final RenderSection section; - VRef structure; + for (var entry : updates.entrySet()) { + var result = entry.getValue(); + var data = result.data(); + var section = data.section(); + var posKey = section.getPosition(); - private Holder(int id, RenderSection section) { - this.id = id; - this.section = section; + var prevHolder = activeSections.remove(posKey); + if (prevHolder != null) { + free(prevHolder.get().id); + prevHolder.close(); + } + + int numGeometriesInInstance = data.bufferOffsets().size(); + int geometryIndex = arena.allocate(numGeometriesInInstance); + + // Add the geometry buffer to the descriptor set (the set retains another reference) + dub.buffer(0, geometryIndex, data.geometryBuffer(), data.bufferOffsets()); + data.geometryBuffer().close(); + + int id; + try (var stack = stackPush()) { + var asi = VkAccelerationStructureInstanceKHR.calloc(stack) + .mask(~0) + .instanceCustomIndex(geometryIndex) + .accelerationStructureReference(result.structure().get().deviceAddress); + asi.transform() + .matrix(new Matrix4x3f() + .translate(section.getOriginX(), section.getOriginY(), + section.getOriginZ()) + .getTransposed(stack.mallocFloat(12))); + + id = alloc(asi); + } + + // Ownership of result.structure() is transferred to the holder + var holder = Holder.create(id, geometryIndex, numGeometriesInInstance, result.structure(), this); + activeSections.put(section.getPosition(), holder); + } + + for (var job : descriptorUpdateJobs) { + dub.buffer(0, job.element, job.geometryBuffer, job.bufferOffsets); + job.geometryBuffer.close(); + } + descriptorUpdateJobs.clear(); + + dub.apply(); } - } - Map tmp = new HashMap<>(); + return super.getInstanceBuffer(); + } - public void collect() { - ArenaDeallocJob job; - while ((job = arenaDeallocJobs.poll()) != null) { - arena.free(job.index, job.count); - job.geometryBuffer.close(); + private void arenaFree(int index, int count) { + arena.free(index, count); + for (int i = 0; i < count; i++) { + geometryBufferDescSet.get().removeRef(index + i); } } public void update(AccelerationBlasBuilder.BLASBuildResult result) { - var data = result.data(); - var holder = tmp.computeIfAbsent(data.section().getPosition(), a -> new Holder(alloc(), data.section())); - holder.structure = result.structure(); - - if (holder.geometryIndex != -1) { - arenaDeallocJobs.add(new ArenaDeallocJob(holder.geometryIndex, holder.geometryBufferOffsets.size(), - holder.geometryBuffer)); - } - holder.geometryBuffer = data.geometryBuffer(); - holder.geometryBufferOffsets = data.bufferOffsets(); - holder.geometryIndex = arena.allocate(holder.geometryBufferOffsets.size()); - - descUpdateJobs.add(new DescUpdateJob(0, holder.geometryIndex, holder.geometryBuffer, holder.geometryBufferOffsets)); - - try (var stack = stackPush()) { - var asi = VkAccelerationStructureInstanceKHR.calloc(stack) - .mask(~0) - .instanceCustomIndex(holder.geometryIndex) - .accelerationStructureReference(holder.structure.get().deviceAddress); - asi.transform() - .matrix(new Matrix4x3f() - .translate(holder.section.getOriginX(), holder.section.getOriginY(), - holder.section.getOriginZ()) - .getTransposed(stack.mallocFloat(12))); - update(holder.id, asi); - } + sectionUpdates.add(result); } public void remove(RenderSection section) { - var holder = tmp.remove(section.getPosition()); - if (holder == null) + sectionRemovals.add(section); + } + + public void addEphemeralInstance(VCmdBuff cmd, VkAccelerationStructureInstanceKHR asi, final VRef structure, final VRef geometryBuffer, List bufferOffsets) { + if (bufferOffsets.isEmpty()) { return; + } - free(holder.id); + int numGeometries = bufferOffsets.size(); + int geometryIndex = arena.allocate(bufferOffsets.size()); - for (var job : descUpdateJobs) { - if (job.geometryBuffer == holder.geometryBuffer) { - descUpdateJobs.remove(job); - } - } + asi.accelerationStructureReference(structure.get().deviceAddress); + asi.instanceCustomIndex(geometryIndex); - if (holder.geometryIndex != -1) { - arenaDeallocJobs.add(new ArenaDeallocJob(holder.geometryIndex, holder.geometryBufferOffsets.size(), - holder.geometryBuffer)); - } - } - } + addEphemeralInstance(asi); - private static final class TlasPointerArena { - private final BitSet vacant; - public int maxIndex = 0; + var holder = Holder.create(-1, geometryIndex, numGeometries, structure.addRef(), this); + cmd.moveRefGeneric(holder.addRefGeneric()); + holder.close(); - private TlasPointerArena(int size) { - size *= 3; - vacant = new BitSet(size); - vacant.set(0, size); + descriptorUpdateJobs.add(new DescriptorUpdateJob(geometryIndex, geometryBuffer.addRef(), bufferOffsets)); } - public int allocate(int count) { - int pos = vacant.nextSetBit(0); - outer: while (pos != -1) { - for (int offset = 1; offset < count; offset++) { - if (!vacant.get(offset + pos)) { - pos = vacant.nextSetBit(offset + pos + 1); - continue outer; - } - } - break; - } - if (pos == -1) { - throw new IllegalStateException(); - } - vacant.clear(pos, pos + count); - maxIndex = Math.max(maxIndex, pos + count); - return pos; + public record DescriptorUpdateJob(int element, VRef geometryBuffer, List bufferOffsets) { } - public void free(int pos, int count) { - vacant.set(pos, pos + count); + // TODO: mixinto RenderSection and add a reference to a holder for us, its much + // faster than a hashmap + private static final class Holder extends VObject { + // A holder holds (duh) a section and its associated data + // The data might currently be in use by the gpu - maxIndex = vacant.previousClearBit(maxIndex) + 1; - } - } + final int id; + final TLASSectionManager manager; + final int geometryIndex; + final int numGeometries; + final VRef structure; - public VRef getGeometrySet() { - return buildDataManager.geometryBufferDescSet.addRef(); - } + private Holder(int id, int geometryIndex, int numGeometries, VRef structure, TLASSectionManager manager) { + this.id = id; + this.geometryIndex = geometryIndex; + this.numGeometries = numGeometries; + this.structure = structure; + this.manager = manager; + } - public VRef getGeometryLayout() { - return buildDataManager.geometryBufferSetLayout.addRef(); + public static VRef create(int id, int geometryIndex, int numGeometries, VRef structure, TLASSectionManager manager) { + return new VRef<>(new Holder(id, geometryIndex, numGeometries, structure, manager)); + } + + @Override + protected void free() { + structure.close(); + // This removes it from the geometry buffer & descriptor set + manager.arenaFree(geometryIndex, numGeometries); + } + } } } diff --git a/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java b/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java index 25d838d..e2b1cb4 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java @@ -22,29 +22,81 @@ import java.util.ArrayList; import java.util.List; -import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; +import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT; import static org.lwjgl.vulkan.KHRAccelerationStructure.*; -import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; import static org.lwjgl.vulkan.KHRBufferDeviceAddress.VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR; import static org.lwjgl.vulkan.VK10.*; public class EntityBlasBuilder { private final VContext ctx; + public EntityBlasBuilder(VContext context) { this.ctx = context; } - private record BuildInfo(VertexFormat format, int quadCount, long address) {} - Pair, VRef> buildBlas(List> renders, VCmdBuff cmd) { + private static VRef executeBlasBuild(VContext ctx, VCmdBuff cmd, MemoryStack stack, VkAccelerationStructureGeometryKHR.Buffer geometryInfos, int[] prims) { + var buildInfos = VkAccelerationStructureBuildGeometryInfoKHR.calloc(1, stack); + var buildRanges = VkAccelerationStructureBuildRangeInfoKHR.calloc(prims.length, stack); + for (int primCount : prims) { + buildRanges.get().primitiveCount(primCount); + } + + var bi = buildInfos.get() + .sType$Default() + .type(VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR) + .flags(VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR) + .pGeometries(geometryInfos) + .geometryCount(geometryInfos.remaining()); + + VkAccelerationStructureBuildSizesInfoKHR buildSizesInfo = VkAccelerationStructureBuildSizesInfoKHR + .calloc(stack) + .sType$Default(); + + vkGetAccelerationStructureBuildSizesKHR( + ctx.device, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, + bi, + prims, + buildSizesInfo); + + + var structure = ctx.memory.createAcceleration(buildSizesInfo.accelerationStructureSize(), 256, + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR); + + var scratch = ctx.memory.createBuffer(buildSizesInfo.buildScratchSize(), + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 256, 0); + + bi.scratchData(VkDeviceOrHostAddressKHR.calloc(stack).deviceAddress(scratch.get().deviceAddress())); + bi.dstAccelerationStructure(structure.get().structure); + + buildInfos.rewind(); + buildRanges.rewind(); + + vkCmdBuildAccelerationStructuresKHR(cmd.buffer(), buildInfos, stack.pointers(buildRanges)); + + vkCmdPipelineBarrier(cmd.buffer(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, VkMemoryBarrier.calloc(1, stack) + .sType$Default() + .srcAccessMask(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR) + .dstAccessMask(VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR), null, null); + + cmd.addAccelerationStructureRef(structure); + cmd.addBufferRef(scratch); + scratch.close(); + + return structure; + } + + List buildBlas(List> renders, VCmdBuff cmd) { long combined_size = 0; TextureManager textureManager = MinecraftClient.getInstance().getTextureManager(); for (var type : renders) { - if (((RenderLayer.MultiPhase)type.getLeft()).phases.texture instanceof RenderPhase.Textures) { + if (((RenderLayer.MultiPhase) type.getLeft()).phases.texture instanceof RenderPhase.Textures) { throw new IllegalStateException("Multi texture not supported"); } - var textureId = ((RenderLayer.MultiPhase)type.getLeft()).phases.texture.getId().get(); + var textureId = ((RenderLayer.MultiPhase) type.getLeft()).phases.texture.getId().get(); var texture = textureManager.getTexture(textureId); - var vkImage = ((IVGImage)texture).getVGImage(); + var vkImage = ((IVGImage) texture).getVGImage(); if (vkImage == null) { throw new IllegalStateException("Vulkan texture not created for render layer " + type.getLeft()); } @@ -56,20 +108,34 @@ Pair, VRef> buildBlas(List infos = new ArrayList<>(); + List offsets = new ArrayList<>(); for (var pair : renders) { offset = VUtil.alignUp(offset, 128); MemoryUtil.memCopy(MemoryUtil.memAddress(pair.getRight().getVertexBuffer()), ptr + offset, pair.getRight().getVertexBuffer().remaining()); - infos.add(new BuildInfo(pair.getRight().getParameters().format(), pair.getRight().getParameters().indexCount()/6, geometryBuffer.get().deviceAddress() + offset)); - - cmd.addBufferRef(geometryBuffer); + infos.add(new BuildInfo(pair.getRight().getParameters().format(), pair.getRight().getParameters().indexCount() / 6, geometryBuffer.get().deviceAddress() + offset)); + offsets.add(offset); offset += pair.getRight().getVertexBuffer().remaining(); } - geometryBuffer.get().unmap(); + cmd.addBufferRef(geometryBufferStaging); + geometryBufferStaging.get().unmap(); + + cmd.encodeBufferCopy(geometryBufferStaging, 0, geometryBuffer, 0, combined_size); + cmd.encodeBufferBarrier(geometryBuffer, 0, combined_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR); + geometryBufferStaging.close(); VRef blas; try (var stack = MemoryStack.stackPush()) { @@ -79,8 +145,7 @@ Pair, VRef> buildBlas(List(blas, geometryBuffer); + return List.of(new BLASResult(blas, geometryBuffer, offsets)); } private VkAccelerationStructureGeometryKHR.Buffer populateBuildStructs(VContext ctx, MemoryStack stack, VCmdBuff cmdBuff, List geometries, int[] primitiveCounts) { @@ -111,6 +176,7 @@ private VkAccelerationStructureGeometryKHR.Buffer populateBuildStructs(VContext .geometryType(VK_GEOMETRY_TYPE_TRIANGLES_KHR) // .flags(geometry.geometryFlags) ; + primitiveCounts[i++] = (geometry.quadCount * 2); cmdBuff.addBufferRef(indexBuffer); @@ -119,54 +185,9 @@ private VkAccelerationStructureGeometryKHR.Buffer populateBuildStructs(VContext return geometryInfos; } - private static VRef executeBlasBuild(VContext ctx, VCmdBuff cmd, MemoryStack stack, VkAccelerationStructureGeometryKHR.Buffer geometryInfos, int[] prims) { - var buildInfos = VkAccelerationStructureBuildGeometryInfoKHR.calloc(1, stack); - var buildRanges = VkAccelerationStructureBuildRangeInfoKHR.calloc(prims.length, stack); - for (int primCount : prims) { - buildRanges.get().primitiveCount(primCount); - } - - var bi = buildInfos.get() - .sType$Default() - .type(VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR) - .flags(VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR) - .pGeometries(geometryInfos) - .geometryCount(geometryInfos.remaining()); - - VkAccelerationStructureBuildSizesInfoKHR buildSizesInfo = VkAccelerationStructureBuildSizesInfoKHR - .calloc(stack) - .sType$Default(); - - vkGetAccelerationStructureBuildSizesKHR( - ctx.device, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, - bi, - prims, - buildSizesInfo); - - - var structure = ctx.memory.createAcceleration(buildSizesInfo.accelerationStructureSize(), 256, - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR); - - var scratch = ctx.memory.createBuffer(buildSizesInfo.buildScratchSize(), - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 256, 0); - - bi.scratchData(VkDeviceOrHostAddressKHR.calloc(stack).deviceAddress(scratch.get().deviceAddress())); - bi.dstAccelerationStructure(structure.get().structure); - - buildInfos.rewind(); - buildRanges.rewind(); - - vkCmdBuildAccelerationStructuresKHR(cmd.buffer(), buildInfos, stack.pointers(buildRanges)); - - vkCmdPipelineBarrier(cmd.buffer(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, VkMemoryBarrier.calloc(1, stack) - .sType$Default() - .srcAccessMask(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR) - .dstAccessMask(VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR), null, null); + public record BLASResult(VRef structure, VRef geometry, List offsets) { + } - cmd.addAccelerationStructureRef(structure); - cmd.addBufferRef(scratch); - return structure; + private record BuildInfo(VertexFormat format, int quadCount, long address) { } } diff --git a/src/main/java/me/cortex/vulkanite/acceleration/GeometryRayFlags.java b/src/main/java/me/cortex/vulkanite/acceleration/GeometryRayFlags.java new file mode 100644 index 0000000..343d1a7 --- /dev/null +++ b/src/main/java/me/cortex/vulkanite/acceleration/GeometryRayFlags.java @@ -0,0 +1,14 @@ +package me.cortex.vulkanite.acceleration; + +public enum GeometryRayFlags { + OPAQUE(1), + TRANSPARENT(1 << 1), + ENTITY(1 << 2), + PLAYER(1 << 7), + ; + final int flag; + + GeometryRayFlags(int i) { + flag = i; + } +} diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/EntityCapture.java b/src/main/java/me/cortex/vulkanite/client/rendering/EntityCapture.java index 1f7f672..c932711 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/EntityCapture.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/EntityCapture.java @@ -15,16 +15,15 @@ import net.minecraft.client.texture.TextureManager; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.world.ClientWorld; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.entity.Entity; import net.minecraft.util.Pair; import net.minecraft.world.World; import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryUtil; import org.lwjgl.vulkan.*; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; import static org.lwjgl.vulkan.KHRAccelerationStructure.*; @@ -86,10 +85,22 @@ public List> end() { if (builtBuffer.getParameters().format().equals(IrisVertexFormats.TERRAIN)) { return; } + + // TODO: Support anything other than ENTITY + if (!builtBuffer.getParameters().format().equals(IrisVertexFormats.ENTITY)) { + return; + } + //Dont support no texture things - if (((RenderLayer.MultiPhase)layer).phases.texture.getId().isEmpty()) { + if (!(layer instanceof RenderLayer.MultiPhase)) { return; } + + var texture = ((RenderLayer.MultiPhase)layer).phases.texture; + if ((texture == null) || (texture.getId().isEmpty())) { + return; + } + buffers.add(new Pair<>(layer, builtBuffer)); } }); diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java index 5424a35..c544a51 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java @@ -18,6 +18,7 @@ import me.cortex.vulkanite.lib.memory.VImage; import me.cortex.vulkanite.lib.other.VImageView; import me.cortex.vulkanite.lib.other.VSampler; +import me.cortex.vulkanite.lib.other.VUtil; import me.cortex.vulkanite.lib.other.sync.VSemaphore; import me.cortex.vulkanite.lib.pipeline.RaytracePipelineBuilder; import me.cortex.vulkanite.lib.pipeline.VRaytracePipeline; @@ -236,14 +237,28 @@ public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, Ray } private final EntityCapture capture = new EntityCapture(); - private void buildEntities() { + private void captureEntities() { accelerationManager.setEntityData(supportsEntities?capture.capture(CapturedRenderingState.INSTANCE.getTickDelta(), MinecraftClient.getInstance().world):null); } public void renderPostShadows(List> vgOutImgs, Camera camera, ShaderStorageBuffer[] ssbos, MixinCelestialUniforms celestialUniforms) { + var prof = MinecraftClient.getInstance().getProfiler(); + + for (int i = 0; i < 15; i++) { + if (VUtil._REPORT_GL_ERROR_()) { + break; + } else if (i == 14) { + System.err.println("Found OpenGL errors generated outside Vulkanite that can't be cleared"); + VUtil._CHECK_GL_ERROR_(); + } + } + ctx.cmd.newFrame(); + VRegistry.INSTANCE.threadLocalCollect(); - buildEntities(); + prof.push("vulkanite_capture_entities"); + captureEntities(); + prof.pop(); PBRTextureManager.notifyPBRTexturesChanged(); @@ -256,7 +271,9 @@ public void renderPostShadows(List> vgOutImgs, Camera camera, Shad var cmdRef = ctx.cmd.getSingleUsePool().createCommandBuffer(); var cmd = cmdRef.get(); + prof.push("vulkanite_build_tlas"); var tlas = accelerationManager.buildTLAS(0, cmd); + prof.pop(); if (tlas == null) { VRegistry.INSTANCE.threadLocalCollect(); @@ -273,6 +290,7 @@ public void renderPostShadows(List> vgOutImgs, Camera camera, Shad var uboBuffer = uboAllocator.allocate(1024); { + prof.push("vulkanite_encode_rt_passes"); long ptr = uboBuffer.buffer().get().map(); MemoryUtil.memSet(ptr, 0, 1024); { @@ -414,6 +432,7 @@ public void renderPostShadows(List> vgOutImgs, Camera camera, Shad } } + prof.pop(); ctx.cmd.submit(0, cmdRef, Arrays.asList(vref_in), Arrays.asList(vref_out), null); } @@ -427,7 +446,6 @@ public void renderPostShadows(List> vgOutImgs, Camera camera, Shad in.close(); out.close(); - VRegistry.INSTANCE.threadLocalCollect(); // System.out.println(VRegistry.INSTANCE.dumpStats()); } diff --git a/src/main/java/me/cortex/vulkanite/lib/base/VObject.java b/src/main/java/me/cortex/vulkanite/lib/base/VObject.java index 2b9be93..832e933 100644 --- a/src/main/java/me/cortex/vulkanite/lib/base/VObject.java +++ b/src/main/java/me/cortex/vulkanite/lib/base/VObject.java @@ -1,11 +1,13 @@ package me.cortex.vulkanite.lib.base; -import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicInteger; public abstract class VObject { + protected final AtomicInteger refCount = new AtomicInteger(0); + protected Object heap = null; + protected abstract void free(); - protected final AtomicLong refCount = new AtomicLong(0); protected void incRef() { if (refCount.incrementAndGet() == 1) { // First reference, put into registry @@ -19,6 +21,4 @@ protected void decRef() { VRegistry.INSTANCE.unregister(this); } } - - public Object heap = null; } diff --git a/src/main/java/me/cortex/vulkanite/lib/base/VRef.java b/src/main/java/me/cortex/vulkanite/lib/base/VRef.java index 9426c6b..74a8b59 100644 --- a/src/main/java/me/cortex/vulkanite/lib/base/VRef.java +++ b/src/main/java/me/cortex/vulkanite/lib/base/VRef.java @@ -2,26 +2,13 @@ import org.jetbrains.annotations.NotNull; +import java.io.Closeable; import java.lang.ref.Cleaner; +import java.lang.ref.WeakReference; -public class VRef { +public class VRef implements Closeable { private static final Cleaner cleaner = Cleaner.create(); - - private final T ref; - - static class State implements Runnable { - private final VObject ref; - - State(VObject ref) { - this.ref = ref; - } - - @Override - public void run() { - ref.decRef(); - } - } - + private final State state; private final Cleaner.Cleanable cleanable; public VRef(T ref) { @@ -29,8 +16,9 @@ public VRef(T ref) { throw new NullPointerException("VRef to null object"); } ref.incRef(); - this.ref = ref; - cleanable = cleaner.register(this, new State(ref)); + + state = new State<>(ref); + cleanable = cleaner.register(this, state); } /** @@ -38,22 +26,44 @@ public VRef(T ref) { * This method can be called multiple times, but the object will only be released once. * If this method is not called, the object will be released when the VRef is garbage collected. */ + @Override public void close() { cleanable.clean(); } @NotNull - public T get() { - return ref; + public VRef addRef() { + return new VRef<>(state.get()); } @NotNull - public VRef addRef() { - return new VRef<>(ref); + public VRef addRefGeneric() { + return new VRef<>(state.get()); } @NotNull - public VRef addRefGeneric() { - return new VRef<>(ref); + public T get() { + return state.get(); + } + + static class State extends WeakReference implements Runnable { + State(T ref) { + super(ref); + } + + @NotNull + @Override + public T get() { + T ref = super.get(); + if (ref == null) { + throw new NullPointerException("Referenced object has been garbage collected while VRef was still active"); + } + return ref; + } + + @Override + public void run() { + get().decRef(); + } } } diff --git a/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java b/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java index 0a69135..c5b7ecf 100644 --- a/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java +++ b/src/main/java/me/cortex/vulkanite/lib/cmd/VCmdBuff.java @@ -39,6 +39,13 @@ public class VCmdBuff extends VObject { public void addBufferRef(final VRef buffer) { refs.add(buffer.addRefGeneric()); } + + // This is a generic method that can be used to add any type of VObject to the refs list + // ref should be produced by addRefGeneric() method of the object + public void moveRefGeneric(final VRef ref) { + refs.add(ref); + } + public void addImageRef(final VRef image) { refs.add(image.addRefGeneric()); } @@ -140,6 +147,17 @@ public void resetQueryPool(final VRef queryPool, int first, int size refs.add(queryPool.addRefGeneric()); } + public void encodeBufferCopy(final VRef src, long srcOffset, final VRef dest, long destOffset, long size) { + try (var stack = stackPush()) { + var copy = VkBufferCopy.calloc(1, stack); + copy.get(0).srcOffset(srcOffset).dstOffset(destOffset).size(size); + vkCmdCopyBuffer(buffer, src.get().buffer(), dest.get().buffer(), copy); + } + + addBufferRef(src); + addBufferRef(dest); + } + public void encodeDataUpload(MemoryManager manager, long src, final VRef dest, long destOffset, long size) { VRef staging = manager.createBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 0, diff --git a/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java b/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java index 5b3d610..4303fa3 100644 --- a/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java +++ b/src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java @@ -13,12 +13,12 @@ import org.lwjgl.vulkan.VkWriteDescriptorSet; import org.lwjgl.vulkan.VkWriteDescriptorSetAccelerationStructureKHR; -import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; -import static org.lwjgl.vulkan.VK10.*; - import java.util.ArrayList; import java.util.List; +import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; +import static org.lwjgl.vulkan.VK10.*; + public class DescriptorUpdateBuilder { private final VContext ctx; private final MemoryStack stack; @@ -27,6 +27,8 @@ public class DescriptorUpdateBuilder { private ArrayList bulkBufferInfos = new ArrayList<>(); private ArrayList bulkImageInfos = new ArrayList<>(); private ShaderReflection.Set refSet = null; + private long set; + private VRef setRef; public DescriptorUpdateBuilder(VContext ctx, int maxUpdates) { this(ctx, maxUpdates, null); @@ -61,8 +63,6 @@ private long viewOrPlaceholder(VRef v) { return v == null ? placeholderImageView.get().view : v.get().view; } - private long set; - private VRef setRef; public DescriptorUpdateBuilder set(VRef set) { this.set = set.get().set; this.setRef = set.addRef(); @@ -72,6 +72,7 @@ public DescriptorUpdateBuilder set(VRef set) { public DescriptorUpdateBuilder buffer(int binding, final VRef buffer) { return buffer(binding, buffer, 0, VK_WHOLE_SIZE); } + public DescriptorUpdateBuilder buffer(int binding, final VRef buffer, long offset, long range) { if (refSet != null && refSet.getBindingAt(binding) == null) { return this; @@ -98,7 +99,7 @@ public DescriptorUpdateBuilder buffer(int binding, int dstArrayElement, final Li } var bufInfo = VkDescriptorBufferInfo.calloc(buffers.size()); for (int i = 0; i < buffers.size(); i++) { - setRef.get().addRef(binding, buffers.get(i).addRefGeneric()); + setRef.get().addRef(binding + dstArrayElement + i, buffers.get(i).addRefGeneric()); bufInfo.get(i) .buffer(buffers.get(i).get().buffer()) .offset(0) @@ -122,7 +123,7 @@ public DescriptorUpdateBuilder buffer(int binding, int dstArrayElement, final VR } var bufInfo = VkDescriptorBufferInfo.calloc(offsets.size()); for (int i = 0; i < offsets.size(); i++) { - setRef.get().addRef(binding, buffer.addRefGeneric()); + setRef.get().addRef(binding + dstArrayElement + i, buffer.addRefGeneric()); bufInfo.get(i) .buffer(buffer.get().buffer()) .offset(offsets.get(i)) @@ -144,6 +145,7 @@ public DescriptorUpdateBuilder buffer(int binding, int dstArrayElement, final VR public DescriptorUpdateBuilder uniform(int binding, final VRef buffer) { return uniform(binding, buffer, 0, VK_WHOLE_SIZE); } + public DescriptorUpdateBuilder uniform(int binding, final VRef buffer, long offset, long range) { if (refSet != null && refSet.getBindingAt(binding) == null) { return this; @@ -206,9 +208,11 @@ public DescriptorUpdateBuilder imageStore(int binding, int dstArrayElement, fina bulkImageInfos.add(imgInfo); return this; } + public DescriptorUpdateBuilder imageStore(int binding, final VRef view) { return imageStore(binding, VK_IMAGE_LAYOUT_GENERAL, view); } + public DescriptorUpdateBuilder imageStore(int binding, int layout, final VRef view) { if (refSet != null && refSet.getBindingAt(binding) == null) { return this; diff --git a/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSet.java b/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSet.java index 7f640ea..4a2ee9e 100644 --- a/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSet.java +++ b/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSet.java @@ -1,22 +1,25 @@ package me.cortex.vulkanite.lib.descriptors; +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import me.cortex.vulkanite.lib.base.VContext; import me.cortex.vulkanite.lib.base.VObject; import me.cortex.vulkanite.lib.base.VRef; import org.lwjgl.vulkan.VkCopyDescriptorSet; -import java.util.HashMap; -import java.util.Map; - import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.vkUpdateDescriptorSets; public class VDescriptorSet extends VObject { - private final VRef pool; public final long poolHandle; public final long set; + private final VRef pool; + private final Int2ObjectArrayMap> refs = new Int2ObjectArrayMap<>(); - private final Map> refs = new HashMap<>(); + protected VDescriptorSet(VRef pool, long poolHandle, long set) { + this.pool = pool; + this.poolHandle = poolHandle; + this.set = set; + } public void addRef(int binding, VRef ref) { var old = refs.put(binding, ref); @@ -25,10 +28,11 @@ public void addRef(int binding, VRef ref) { } } - protected VDescriptorSet(VRef pool, long poolHandle, long set) { - this.pool = pool; - this.poolHandle = poolHandle; - this.set = set; + public void removeRef(int binding) { + var old = refs.remove(binding); + if (old != null) { + old.close(); + } } @Override @@ -38,8 +42,8 @@ protected void free() { } public void copyFrom(VContext ctx, VRef other, int setCapacity) { - for (var entry : other.get().refs.entrySet()) { - refs.put(entry.getKey(), entry.getValue().addRef()); + for (var entry : other.get().refs.int2ObjectEntrySet()) { + refs.put(entry.getIntKey(), entry.getValue().addRef()); } try (var stack = stackPush()) { diff --git a/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java b/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java index a7d189d..f89ee3a 100644 --- a/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java +++ b/src/main/java/me/cortex/vulkanite/lib/memory/MemoryManager.java @@ -18,6 +18,7 @@ import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; import static me.cortex.vulkanite.lib.other.VUtil._CHECK_GL_ERROR_; +import static me.cortex.vulkanite.lib.other.VUtil._REPORT_GL_ERROR_; import static org.lwjgl.opengl.ARBDirectStateAccess.*; import static org.lwjgl.opengl.EXTMemoryObject.*; import static org.lwjgl.opengl.EXTMemoryObjectFD.GL_HANDLE_TYPE_OPAQUE_FD_EXT; @@ -173,7 +174,7 @@ public VRef createSharedBuffer(long size, int usage, int properties) { var allocationCreateInfo = VmaAllocationCreateInfo.calloc(stack) .requiredFlags(properties); - + var alloc = allocator.allocShared(bufferCreateInfo, allocationCreateInfo); int memoryObject = ExternalMemoryTracker.acquire(alloc, device, alloc.isDedicated()); @@ -189,6 +190,7 @@ public VRef createSharedImage(int width, int height, int mipLevels, int return createSharedImage(2, width, height, 1, mipLevels, vkFormat, glFormat, usage, properties); } public VRef createSharedImage(int dimensions, int width, int height, int depth, int mipLevels, int vkFormat, int glFormat, int usage, int properties) { + _REPORT_GL_ERROR_(); int vkImageType = VK_IMAGE_TYPE_2D; int glImageType = GL_TEXTURE_2D; @@ -201,6 +203,14 @@ public VRef createSharedImage(int dimensions, int width, int height, in glImageType = GL_TEXTURE_3D; } + System.out.println( + "Creating shared image with dimensions: " + width + "," + height + "," + depth + + " vkImageType: " + vkImageType + + " glImageType: " + glImageType + + " mipLevels: " + mipLevels + + " vkFormat: " + vkFormat + + " glFormat: " + glFormat); + try (var stack = stackPush()) { var createInfo = VkImageCreateInfo .calloc(stack) @@ -227,6 +237,7 @@ public VRef createSharedImage(int dimensions, int width, int height, in int glId = glCreateTextures(glImageType); glTextureParameteri(glId, GL_TEXTURE_TILING_EXT, GL_OPTIMAL_TILING_EXT); + _CHECK_GL_ERROR_(); switch(glImageType) { case GL_TEXTURE_1D: diff --git a/src/main/java/me/cortex/vulkanite/lib/other/VUtil.java b/src/main/java/me/cortex/vulkanite/lib/other/VUtil.java index c2e4773..a9fb816 100644 --- a/src/main/java/me/cortex/vulkanite/lib/other/VUtil.java +++ b/src/main/java/me/cortex/vulkanite/lib/other/VUtil.java @@ -101,6 +101,15 @@ public static void _CHECK_GL_ERROR_() { } } + public static boolean _REPORT_GL_ERROR_() { + int e = glGetError(); + if (e != GL_NO_ERROR) { + System.err.println("Gl error: " + e); + return false; + } + return true; + } + public static int alignUp(int size, int alignment) { return (size + alignment - 1) & -alignment; diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java index 77cb79f..5b43d0c 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java @@ -88,7 +88,6 @@ private void redirectUpload(TextureType instance, int glId, int width, int heigh @Overwrite protected void destroyInternal(){ - glFinish(); sharedImage = null; } diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java index fc22aa7..370e96a 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java @@ -11,7 +11,6 @@ import net.coderbot.iris.gl.buffer.ShaderStorageBuffer; import net.coderbot.iris.gl.texture.TextureAccess; import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder; -import net.coderbot.iris.gl.uniform.DynamicUniformHolder; import net.coderbot.iris.mixin.LevelRendererAccessor; import net.coderbot.iris.pipeline.CustomTextureManager; import net.coderbot.iris.pipeline.newshader.NewWorldRenderingPipeline; @@ -19,9 +18,8 @@ import net.coderbot.iris.shaderpack.ProgramSet; import net.coderbot.iris.shaderpack.texture.TextureStage; import net.coderbot.iris.uniforms.CelestialUniforms; -import net.coderbot.iris.uniforms.custom.CustomUniforms; import net.minecraft.client.render.Camera; -import org.jetbrains.annotations.Nullable; +import net.minecraft.client.MinecraftClient; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -29,13 +27,12 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.ArrayList; import java.util.Comparator; import java.util.List; -import static org.lwjgl.opengl.GL11.glFinish; - @Mixin(value = NewWorldRenderingPipeline.class, remap = false) public class MixinNewWorldRenderingPipeline { @@ -80,6 +77,9 @@ private void injectRTShader(ProgramSet set, CallbackInfo ci) { @Inject(method = "renderShadows", at = @At("TAIL")) private void renderShadows(LevelRendererAccessor par1, Camera par2, CallbackInfo ci) { + var prof = MinecraftClient.getInstance().getProfiler(); + prof.push("vulkanite_render_shadows"); + ShaderStorageBuffer[] buffers = new ShaderStorageBuffer[0]; if(shaderStorageBufferHolder != null) { @@ -94,6 +94,15 @@ private void renderShadows(LevelRendererAccessor par1, Camera par2, CallbackInfo MixinCelestialUniforms celestialUniforms = (MixinCelestialUniforms)(Object) new CelestialUniforms(this.sunPathRotation); pipeline.renderPostShadows(outImgs, par2, buffers, celestialUniforms); + + prof.pop(); + } + + @Inject(method = "shouldDisableVanillaEntityShadows", at = @At("HEAD"), cancellable = true) + private void shouldDisableVanillaEntityShadows(CallbackInfoReturnable ci) { + if (pipeline != null) { + ci.setReturnValue(true); + } } @Inject(method = "destroyShaders", at = @At("TAIL")) From ea2b9cfa217ebbb6ea48d3af94b4ad1553f2ad9e Mon Sep 17 00:00:00 2001 From: IMS212 Date: Sun, 2 Jun 2024 16:44:18 -0700 Subject: [PATCH 16/22] Iris 1.7 + 1.20.6 --- README.md | 1 + build.gradle | 30 +++++++++---------- gradle.properties | 8 ++--- gradle/wrapper/gradle-wrapper.properties | 2 +- .../acceleration/EntityBlasBuilder.java | 2 +- .../client/rendering/EntityCapture.java | 4 +-- .../client/rendering/VulkanPipeline.java | 16 +++++----- .../compat/RaytracingShaderSource.java | 3 -- .../vulkanite/lib/other/FormatConverter.java | 2 +- .../mixin/iris/MixinCelestialUniforms.java | 2 +- .../mixin/iris/MixinCommonUniforms.java | 2 +- .../vulkanite/mixin/iris/MixinGlResource.java | 7 ++--- .../vulkanite/mixin/iris/MixinGlTexture.java | 14 ++++----- ...e.java => MixinIrisRenderingPipeline.java} | 24 +++++++-------- .../iris/MixinNativeImageBackedTexture.java | 4 +-- .../mixin/iris/MixinPBRAtlasTexture.java | 2 +- .../iris/MixinPackRenderTargetDirectives.java | 2 +- .../vulkanite/mixin/iris/MixinProgramSet.java | 9 +++--- .../mixin/iris/MixinRenderTarget.java | 12 ++++---- .../iris/MixinShaderPackSourceNames.java | 2 +- .../mixin/iris/MixinShaderStorageBuffer.java | 6 ++-- .../iris/MixinShaderStorageBufferHolder.java | 12 ++++---- .../mixin/iris/MixinStandardMacros.java | 6 ++-- .../ShaderStorageBufferHolderAccessor.java | 4 +-- src/main/resources/fabric.mod.json | 4 +-- src/main/resources/vulkanite.mixins.json | 2 +- 26 files changed, 89 insertions(+), 93 deletions(-) rename src/main/java/me/cortex/vulkanite/mixin/iris/{MixinNewWorldRenderingPipeline.java => MixinIrisRenderingPipeline.java} (86%) diff --git a/README.md b/README.md index 19b7410..becb35f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +ol # Work in progress Minecraft mod that adds hardware raytracing support to minecraft using opengl vulkan interop diff --git a/build.gradle b/build.gradle index a73c356..8828762 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.2-SNAPSHOT' + id 'fabric-loom' version '1.6-SNAPSHOT' id 'maven-publish' } @@ -38,8 +38,8 @@ dependencies { modImplementation("net.fabricmc.fabric-api:fabric-rendering-data-attachment-v1:0.3.38+73761d2e9a") modImplementation(fabricApi.module("fabric-resource-loader-v0", project.fabric_version)) - modImplementation "maven.modrinth:sodium:mc1.20.2-0.5.5" - modImplementation "maven.modrinth:iris:1.6.14+1.20.2" + modImplementation "maven.modrinth:sodium:mc1.20.6-0.5.8" + modImplementation "maven.modrinth:iris:1.7.0+1.20.6" modRuntimeOnly 'org.anarres:jcpp:1.4.14' modRuntimeOnly 'io.github.douira:glsl-transformer:2.0.0-pre13' @@ -106,7 +106,7 @@ publishing { import org.gradle.internal.os.OperatingSystem -project.ext.lwjglVersion = "3.3.1" +project.ext.lwjglVersion = "3.3.3" switch (OperatingSystem.current()) { case OperatingSystem.LINUX: @@ -134,23 +134,23 @@ dependencies { include(implementation("org.lwjgl:lwjgl-shaderc")) include(implementation("org.lwjgl:lwjgl-spvc")) - include(runtimeOnly("org.lwjgl:lwjgl-meshoptimizer:$lwjglVersion:$lwjglNatives")) - include(runtimeOnly("org.lwjgl:lwjgl-vma:$lwjglVersion:$lwjglNatives")) - include(runtimeOnly("org.lwjgl:lwjgl-shaderc:$lwjglVersion:$lwjglNatives")) - include(runtimeOnly("org.lwjgl:lwjgl-spvc:$lwjglVersion:$lwjglNatives")) + include(runtimeOnly("org.lwjgl:lwjgl-meshoptimizer:$lwjglVersion:natives-linux")) + include(runtimeOnly("org.lwjgl:lwjgl-vma:$lwjglVersion:natives-linux")) + include(runtimeOnly("org.lwjgl:lwjgl-shaderc:$lwjglVersion:natives-linux")) + include(runtimeOnly("org.lwjgl:lwjgl-spvc:$lwjglVersion:natives-linux")) - include(implementation("org.lwjgl:lwjgl-meshoptimizer:$lwjglVersion:$lwjglNatives")) - include(implementation("org.lwjgl:lwjgl-vma:$lwjglVersion:$lwjglNatives")) - include(implementation("org.lwjgl:lwjgl-shaderc:$lwjglVersion:$lwjglNatives")) - include(implementation("org.lwjgl:lwjgl-spvc:$lwjglVersion:$lwjglNatives")) + include(implementation("org.lwjgl:lwjgl-meshoptimizer:$lwjglVersion:natives-linux")) + include(implementation("org.lwjgl:lwjgl-vma:$lwjglVersion:natives-linux")) + include(implementation("org.lwjgl:lwjgl-shaderc:$lwjglVersion:natives-linux")) + include(implementation("org.lwjgl:lwjgl-spvc:$lwjglVersion:natives-linux")) implementation "org.lwjgl:lwjgl" implementation "org.lwjgl:lwjgl-glfw" implementation "org.lwjgl:lwjgl-opengl" - runtimeOnly "org.lwjgl:lwjgl::$lwjglNatives" - runtimeOnly "org.lwjgl:lwjgl-glfw::$lwjglNatives" - runtimeOnly "org.lwjgl:lwjgl-opengl::$lwjglNatives" + runtimeOnly "org.lwjgl:lwjgl::natives-linux" + runtimeOnly "org.lwjgl:lwjgl-glfw::natives-linux" + runtimeOnly "org.lwjgl:lwjgl-opengl::natives-linux" } diff --git a/gradle.properties b/gradle.properties index 4e339e7..72a8854 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,12 +2,12 @@ org.gradle.jvmargs=-Xmx4G # Fabric Properties # check these on https://modmuss50.me/fabric.html -minecraft_version=1.20.2 -yarn_mappings=1.20.2+build.4 -loader_version=0.15.6 +minecraft_version=1.20.6 +yarn_mappings=1.20.6+build.3 +loader_version=0.15.11 #Fabric api -fabric_version=0.91.6+1.20.2 +fabric_version=0.99.4+1.20.6 # Mod Properties mod_version=0.0.4-pre-alpha maven_group=me.cortex diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0c85a1f..20db9ad 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java b/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java index e2b1cb4..a89f3fd 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java @@ -7,7 +7,7 @@ import me.cortex.vulkanite.lib.memory.VAccelerationStructure; import me.cortex.vulkanite.lib.memory.VBuffer; import me.cortex.vulkanite.lib.other.VUtil; -import net.coderbot.iris.vertices.IrisVertexFormats; +import net.irisshaders.iris.vertices.IrisVertexFormats; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.RenderLayer; diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/EntityCapture.java b/src/main/java/me/cortex/vulkanite/client/rendering/EntityCapture.java index c932711..c11a882 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/EntityCapture.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/EntityCapture.java @@ -8,8 +8,8 @@ import me.cortex.vulkanite.lib.memory.VBuffer; import me.cortex.vulkanite.lib.other.VUtil; import me.cortex.vulkanite.lib.other.sync.VFence; -import net.coderbot.iris.mixin.LevelRendererAccessor; -import net.coderbot.iris.vertices.IrisVertexFormats; +import net.irisshaders.iris.mixin.LevelRendererAccessor; +import net.irisshaders.iris.vertices.IrisVertexFormats; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.*; import net.minecraft.client.texture.TextureManager; diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java index c544a51..f8cc1f2 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java @@ -25,12 +25,12 @@ import me.cortex.vulkanite.lib.shader.reflection.ShaderReflection; import me.cortex.vulkanite.mixin.iris.MixinCelestialUniforms; import me.cortex.vulkanite.mixin.iris.MixinCommonUniforms; -import net.coderbot.iris.gl.buffer.ShaderStorageBuffer; -import net.coderbot.iris.texture.pbr.PBRTextureHolder; -import net.coderbot.iris.texture.pbr.PBRTextureManager; -import net.coderbot.iris.uniforms.CapturedRenderingState; -import net.coderbot.iris.uniforms.CommonUniforms; -import net.coderbot.iris.uniforms.SystemTimeUniforms; +import net.irisshaders.iris.gl.buffer.ShaderStorageBuffer; +import net.irisshaders.iris.texture.pbr.PBRTextureHolder; +import net.irisshaders.iris.texture.pbr.PBRTextureManager; +import net.irisshaders.iris.uniforms.CapturedRenderingState; +import net.irisshaders.iris.uniforms.CommonUniforms; +import net.irisshaders.iris.uniforms.SystemTimeUniforms; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.Camera; import net.minecraft.client.texture.AbstractTexture; @@ -102,12 +102,12 @@ public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, Ray this.blockAtlasNormalView = new SharedImageViewTracker(ctx, () -> { AbstractTexture blockAtlas = MinecraftClient.getInstance().getTextureManager().getTexture(new Identifier("minecraft", "textures/atlas/blocks.png")); PBRTextureHolder holder = PBRTextureManager.INSTANCE.getOrLoadHolder(blockAtlas.getGlId());//((TextureAtlasExtension)blockAtlas).getPBRHolder() - return ((IVGImage) holder.getNormalTexture()).getVGImage(); + return ((IVGImage) holder.normalTexture()).getVGImage(); }); this.blockAtlasSpecularView = new SharedImageViewTracker(ctx, () -> { AbstractTexture blockAtlas = MinecraftClient.getInstance().getTextureManager().getTexture(new Identifier("minecraft", "textures/atlas/blocks.png")); PBRTextureHolder holder = PBRTextureManager.INSTANCE.getOrLoadHolder(blockAtlas.getGlId());//((TextureAtlasExtension)blockAtlas).getPBRHolder() - return ((IVGImage) holder.getSpecularTexture()).getVGImage(); + return ((IVGImage) holder.specularTexture()).getVGImage(); }); this.placeholderSpecular = ctx.memory.createImage2D(4, 4, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); this.placeholderSpecularView = VImageView.create(ctx, placeholderSpecular); diff --git a/src/main/java/me/cortex/vulkanite/compat/RaytracingShaderSource.java b/src/main/java/me/cortex/vulkanite/compat/RaytracingShaderSource.java index 1c50628..833c6d5 100644 --- a/src/main/java/me/cortex/vulkanite/compat/RaytracingShaderSource.java +++ b/src/main/java/me/cortex/vulkanite/compat/RaytracingShaderSource.java @@ -1,8 +1,5 @@ package me.cortex.vulkanite.compat; -import net.coderbot.iris.shaderpack.ProgramDirectives; -import net.coderbot.iris.shaderpack.ProgramSet; - public class RaytracingShaderSource { public record RayHitSource(String close, String any, String intersection) {} public final String name; diff --git a/src/main/java/me/cortex/vulkanite/lib/other/FormatConverter.java b/src/main/java/me/cortex/vulkanite/lib/other/FormatConverter.java index ee0e778..fedd1de 100644 --- a/src/main/java/me/cortex/vulkanite/lib/other/FormatConverter.java +++ b/src/main/java/me/cortex/vulkanite/lib/other/FormatConverter.java @@ -1,6 +1,6 @@ package me.cortex.vulkanite.lib.other; -import net.coderbot.iris.gl.texture.InternalTextureFormat; +import net.irisshaders.iris.gl.texture.InternalTextureFormat; import static org.lwjgl.opengl.GL11C.GL_RGB8; import static org.lwjgl.opengl.GL11C.GL_RGBA16; diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinCelestialUniforms.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinCelestialUniforms.java index 660ab9e..f810a3f 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinCelestialUniforms.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinCelestialUniforms.java @@ -1,6 +1,6 @@ package me.cortex.vulkanite.mixin.iris; -import net.coderbot.iris.uniforms.CelestialUniforms; +import net.irisshaders.iris.uniforms.CelestialUniforms; import org.joml.Vector4f; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinCommonUniforms.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinCommonUniforms.java index 4d07ce4..b7a4069 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinCommonUniforms.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinCommonUniforms.java @@ -1,6 +1,6 @@ package me.cortex.vulkanite.mixin.iris; -import net.coderbot.iris.uniforms.CommonUniforms; +import net.irisshaders.iris.uniforms.CommonUniforms; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlResource.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlResource.java index 87e4d0f..b6cb42c 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlResource.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlResource.java @@ -3,10 +3,9 @@ import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.compat.IRenderTargetVkGetter; import me.cortex.vulkanite.lib.memory.VGImage; -import net.coderbot.iris.gl.GlResource; -import net.coderbot.iris.gl.texture.InternalTextureFormat; -import net.coderbot.iris.gl.texture.PixelFormat; -import net.coderbot.iris.rendertarget.RenderTarget; +import net.irisshaders.iris.gl.GlResource; +import net.irisshaders.iris.gl.texture.InternalTextureFormat; +import net.irisshaders.iris.gl.texture.PixelFormat; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java index 5b43d0c..90eb669 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java @@ -6,11 +6,11 @@ import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VGImage; import me.cortex.vulkanite.lib.other.FormatConverter; -import net.coderbot.iris.gl.IrisRenderSystem; -import net.coderbot.iris.gl.texture.GlTexture; -import net.coderbot.iris.gl.texture.InternalTextureFormat; -import net.coderbot.iris.gl.texture.TextureType; -import net.coderbot.iris.shaderpack.texture.TextureFilteringData; +import net.irisshaders.iris.gl.IrisRenderSystem; +import net.irisshaders.iris.gl.texture.GlTexture; +import net.irisshaders.iris.gl.texture.InternalTextureFormat; +import net.irisshaders.iris.gl.texture.TextureType; +import net.irisshaders.iris.shaderpack.texture.TextureFilteringData; import org.lwjgl.opengl.GL30; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; @@ -31,7 +31,7 @@ private static int redirectGen() { return -1; } - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/gl/texture/GlTexture;getGlId()I", ordinal = 0)) + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/irisshaders/iris/gl/texture/GlTexture;getGlId()I", ordinal = 0)) private int redirectTextureCreation(GlTexture instance, TextureType target, int sizeX, int sizeY, int sizeZ, int internalFormat, int format, int pixelType, byte[] pixels, TextureFilteringData filteringData) { // Before getting the texture id, create the texture that wasn't created earlier @@ -65,7 +65,7 @@ private int redirectTextureCreation(GlTexture instance, TextureType target, int return sharedImage.get().glId; } - @Redirect(method="", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/gl/texture/TextureType;apply(IIIIIIILjava/nio/ByteBuffer;)V")) + @Redirect(method="", at = @At(value = "INVOKE", target = "Lnet/irisshaders/iris/gl/texture/TextureType;apply(IIIIIIILjava/nio/ByteBuffer;)V")) private void redirectUpload(TextureType instance, int glId, int width, int height, int depth, int internalFormat, int format, int pixelType, ByteBuffer data) { int target = instance.getGlType(); diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinIrisRenderingPipeline.java similarity index 86% rename from src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java rename to src/main/java/me/cortex/vulkanite/mixin/iris/MixinIrisRenderingPipeline.java index 370e96a..adf5a72 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinIrisRenderingPipeline.java @@ -8,16 +8,16 @@ import me.cortex.vulkanite.lib.base.VContext; import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VGImage; -import net.coderbot.iris.gl.buffer.ShaderStorageBuffer; -import net.coderbot.iris.gl.texture.TextureAccess; -import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder; -import net.coderbot.iris.mixin.LevelRendererAccessor; -import net.coderbot.iris.pipeline.CustomTextureManager; -import net.coderbot.iris.pipeline.newshader.NewWorldRenderingPipeline; -import net.coderbot.iris.rendertarget.RenderTargets; -import net.coderbot.iris.shaderpack.ProgramSet; -import net.coderbot.iris.shaderpack.texture.TextureStage; -import net.coderbot.iris.uniforms.CelestialUniforms; +import net.irisshaders.iris.gl.buffer.ShaderStorageBuffer; +import net.irisshaders.iris.gl.texture.TextureAccess; +import net.irisshaders.iris.gl.buffer.ShaderStorageBufferHolder; +import net.irisshaders.iris.mixin.LevelRendererAccessor; +import net.irisshaders.iris.pipeline.CustomTextureManager; +import net.irisshaders.iris.pipeline.IrisRenderingPipeline; +import net.irisshaders.iris.shaderpack.programs.ProgramSet; +import net.irisshaders.iris.shaderpack.texture.TextureStage; +import net.irisshaders.iris.targets.RenderTargets; +import net.irisshaders.iris.uniforms.CelestialUniforms; import net.minecraft.client.render.Camera; import net.minecraft.client.MinecraftClient; import org.spongepowered.asm.mixin.Final; @@ -33,8 +33,8 @@ import java.util.Comparator; import java.util.List; -@Mixin(value = NewWorldRenderingPipeline.class, remap = false) -public class MixinNewWorldRenderingPipeline { +@Mixin(value = IrisRenderingPipeline.class, remap = false) +public class MixinIrisRenderingPipeline { @Shadow @Final private RenderTargets renderTargets; @Shadow @Final private CustomTextureManager customTextureManager; diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNativeImageBackedTexture.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNativeImageBackedTexture.java index 5aa9c01..941d698 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNativeImageBackedTexture.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNativeImageBackedTexture.java @@ -7,8 +7,8 @@ import me.cortex.vulkanite.compat.IVGImage; import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.mixin.minecraft.MixinAbstractTexture; -import net.coderbot.iris.gl.IrisRenderSystem; -import net.coderbot.iris.rendertarget.NativeImageBackedCustomTexture; +import net.irisshaders.iris.gl.IrisRenderSystem; +import net.irisshaders.iris.targets.backed.NativeImageBackedCustomTexture; import net.minecraft.client.texture.AbstractTexture; import net.minecraft.client.texture.NativeImage; import net.minecraft.client.texture.NativeImageBackedTexture; diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinPBRAtlasTexture.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinPBRAtlasTexture.java index 709c0b9..579538b 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinPBRAtlasTexture.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinPBRAtlasTexture.java @@ -4,7 +4,7 @@ import me.cortex.vulkanite.client.Vulkanite; import me.cortex.vulkanite.compat.IVGImage; import me.cortex.vulkanite.lib.base.VRef; -import net.coderbot.iris.texture.pbr.PBRAtlasTexture; +import net.irisshaders.iris.texture.pbr.PBRAtlasTexture; import net.minecraft.client.texture.AbstractTexture; import net.minecraft.client.texture.SpriteAtlasTexture; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinPackRenderTargetDirectives.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinPackRenderTargetDirectives.java index 81608b4..e5c70f8 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinPackRenderTargetDirectives.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinPackRenderTargetDirectives.java @@ -1,7 +1,7 @@ package me.cortex.vulkanite.mixin.iris; import com.google.common.collect.ImmutableSet; -import net.coderbot.iris.shaderpack.PackRenderTargetDirectives; +import net.irisshaders.iris.shaderpack.properties.PackRenderTargetDirectives; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinProgramSet.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinProgramSet.java index f301105..618032d 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinProgramSet.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinProgramSet.java @@ -2,11 +2,10 @@ import me.cortex.vulkanite.compat.IGetRaytracingSource; import me.cortex.vulkanite.compat.RaytracingShaderSource; -import net.coderbot.iris.shaderpack.ProgramSet; -import net.coderbot.iris.shaderpack.ProgramSource; -import net.coderbot.iris.shaderpack.ShaderPack; -import net.coderbot.iris.shaderpack.ShaderProperties; -import net.coderbot.iris.shaderpack.include.AbsolutePackPath; +import net.irisshaders.iris.shaderpack.ShaderPack; +import net.irisshaders.iris.shaderpack.include.AbsolutePackPath; +import net.irisshaders.iris.shaderpack.programs.ProgramSet; +import net.irisshaders.iris.shaderpack.properties.ShaderProperties; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java index 6418abd..5377830 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java @@ -5,9 +5,9 @@ import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VGImage; import me.cortex.vulkanite.lib.other.FormatConverter; -import net.coderbot.iris.gl.texture.InternalTextureFormat; -import net.coderbot.iris.gl.texture.PixelFormat; -import net.coderbot.iris.rendertarget.RenderTarget; +import net.irisshaders.iris.gl.texture.InternalTextureFormat; +import net.irisshaders.iris.gl.texture.PixelFormat; +import net.irisshaders.iris.targets.RenderTarget; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -33,15 +33,15 @@ private void redirectGen(int[] textures) { } - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/rendertarget/RenderTarget;setupTexture(IIIZ)V", ordinal = 0)) + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/irisshaders/iris/targets/RenderTarget;setupTexture(IIIZ)V", ordinal = 0)) private void redirectMain(RenderTarget instance, int id, int width, int height, boolean allowsLinear) { setupTextures(width, height, allowsLinear); } - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/rendertarget/RenderTarget;setupTexture(IIIZ)V", ordinal = 1)) + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/irisshaders/iris/targets/RenderTarget;setupTexture(IIIZ)V", ordinal = 1)) private void redirectAlt(RenderTarget instance, int id, int width, int height, boolean allowsLinear) {} - @Redirect(method = "setupTexture", at = @At(value = "INVOKE",target = "Lnet/coderbot/iris/rendertarget/RenderTarget;resizeTexture(III)V")) + @Redirect(method = "setupTexture", at = @At(value = "INVOKE",target = "Lnet/irisshaders/iris/targets/RenderTarget;resizeTexture(III)V")) private void redirectResize(RenderTarget instance, int t, int w, int h) {} @Overwrite diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderPackSourceNames.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderPackSourceNames.java index 14b6d02..f75a4df 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderPackSourceNames.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderPackSourceNames.java @@ -1,7 +1,7 @@ package me.cortex.vulkanite.mixin.iris; import com.google.common.collect.ImmutableList; -import net.coderbot.iris.shaderpack.include.ShaderPackSourceNames; +import net.irisshaders.iris.shaderpack.include.ShaderPackSourceNames; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBuffer.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBuffer.java index 5d15cae..2ba5ba1 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBuffer.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBuffer.java @@ -4,8 +4,8 @@ import me.cortex.vulkanite.compat.IVGBuffer; import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VGBuffer; -import net.coderbot.iris.gl.IrisRenderSystem; -import net.coderbot.iris.gl.buffer.ShaderStorageBuffer; +import net.irisshaders.iris.gl.IrisRenderSystem; +import net.irisshaders.iris.gl.buffer.ShaderStorageBuffer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -36,7 +36,7 @@ public void setBuffer(VRef buffer) { } } - @Redirect(method = "destroy", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/gl/IrisRenderSystem;deleteBuffers(I)V")) + @Redirect(method = "destroy", at = @At(value = "INVOKE", target = "Lnet/irisshaders/iris/gl/IrisRenderSystem;deleteBuffers(I)V")) private void redirectDelete(int id) { if (vkBuffer != null) { vkBuffer = null; diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBufferHolder.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBufferHolder.java index b436e25..d569e84 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBufferHolder.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBufferHolder.java @@ -5,10 +5,10 @@ import me.cortex.vulkanite.compat.IVGBuffer; import me.cortex.vulkanite.lib.base.VRef; import me.cortex.vulkanite.lib.memory.VGBuffer; -import net.coderbot.iris.gl.IrisRenderSystem; -import net.coderbot.iris.gl.buffer.ShaderStorageBuffer; -import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder; -import net.coderbot.iris.gl.buffer.ShaderStorageInfo; +import net.irisshaders.iris.gl.IrisRenderSystem; +import net.irisshaders.iris.gl.buffer.ShaderStorageBuffer; +import net.irisshaders.iris.gl.buffer.ShaderStorageBufferHolder; +import net.irisshaders.iris.gl.buffer.ShaderStorageInfo; import org.lwjgl.opengl.GL43C; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -22,7 +22,7 @@ public class MixinShaderStorageBufferHolder { @Unique private ShaderStorageInfo storageInfo; - @Redirect(method = "lambda$new$0", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/gl/buffer/ShaderStorageInfo;relative()Z")) + @Redirect(method = "lambda$new$0", at = @At(value = "INVOKE", target = "Lnet/irisshaders/iris/gl/buffer/ShaderStorageInfo;relative()Z")) private boolean alwaysReturnTrue(ShaderStorageInfo instance) { this.storageInfo = instance; return true; @@ -32,7 +32,7 @@ private static VRef alloc(int size) { return Vulkanite.INSTANCE.getCtx().memory.createSharedBuffer(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); } - @Redirect(method = "lambda$new$0", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/gl/buffer/ShaderStorageBuffer;resizeIfRelative(II)V")) + @Redirect(method = "lambda$new$0", at = @At(value = "INVOKE", target = "Lnet/irisshaders/iris/gl/buffer/ShaderStorageBuffer;resizeIfRelative(II)V")) private void redirectSizeAllocation(ShaderStorageBuffer instance, int width, int height) { if (storageInfo.relative()) { instance.resizeIfRelative(width, height); diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinStandardMacros.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinStandardMacros.java index 4b51cd1..a22d2fa 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinStandardMacros.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinStandardMacros.java @@ -1,7 +1,7 @@ package me.cortex.vulkanite.mixin.iris; -import net.coderbot.iris.gl.shader.StandardMacros; -import net.coderbot.iris.shaderpack.StringPair; +import net.irisshaders.iris.gl.shader.StandardMacros; +import net.irisshaders.iris.helpers.StringPair; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -12,7 +12,7 @@ @Mixin(value = StandardMacros.class, remap = false) public class MixinStandardMacros { - @Inject(method = "createStandardEnvironmentDefines", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/gl/shader/StandardMacros;define(Ljava/util/List;Ljava/lang/String;)V", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD) + @Inject(method = "createStandardEnvironmentDefines", at = @At(value = "INVOKE", target = "Lnet/irisshaders/iris/gl/shader/StandardMacros;define(Ljava/util/List;Ljava/lang/String;)V", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD) private static void injectVulkaniteDefine(CallbackInfoReturnable> cir, ArrayList defines) { defines.add(new StringPair("VULKANITE", " ")); } diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/ShaderStorageBufferHolderAccessor.java b/src/main/java/me/cortex/vulkanite/mixin/iris/ShaderStorageBufferHolderAccessor.java index 5d78387..ccba5a1 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/ShaderStorageBufferHolderAccessor.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/ShaderStorageBufferHolderAccessor.java @@ -1,7 +1,7 @@ package me.cortex.vulkanite.mixin.iris; -import net.coderbot.iris.gl.buffer.ShaderStorageBuffer; -import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder; +import net.irisshaders.iris.gl.buffer.ShaderStorageBuffer; +import net.irisshaders.iris.gl.buffer.ShaderStorageBufferHolder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 2cc756a..84ccda1 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -15,7 +15,7 @@ ], "depends": { "fabricloader": ">=0.14.21", - "iris": "=1.6.14", - "sodium": "=0.5.5" + "iris": "=1.7.0", + "sodium": "=0.5.8" } } diff --git a/src/main/resources/vulkanite.mixins.json b/src/main/resources/vulkanite.mixins.json index 7934e92..36288e0 100644 --- a/src/main/resources/vulkanite.mixins.json +++ b/src/main/resources/vulkanite.mixins.json @@ -9,7 +9,7 @@ "iris.MixinGlResource", "iris.MixinGlTexture", "iris.MixinNativeImageBackedTexture", - "iris.MixinNewWorldRenderingPipeline", + "iris.MixinIrisRenderingPipeline", "iris.MixinPackRenderTargetDirectives", "iris.MixinPBRAtlasTexture", "iris.MixinProgramSet", From 6d86524298f5e9aecf4d762ef9cd419062dec097 Mon Sep 17 00:00:00 2001 From: Bob Cao Date: Sun, 2 Jun 2024 16:46:34 -0700 Subject: [PATCH 17/22] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index becb35f..9d1a36c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -ol # Work in progress Minecraft mod that adds hardware raytracing support to minecraft using opengl vulkan interop -Enables extra passes that shader devs can use with raytracing passes \ No newline at end of file +Enables extra passes that shader devs can use with raytracing passes From 158a578ae2b5cbaf9aafae2d8d0f2d5efafc6f77 Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Sun, 2 Jun 2024 16:56:25 -0700 Subject: [PATCH 18/22] smol fix for the natives --- build.gradle | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index 8828762..1aa15fc 100644 --- a/build.gradle +++ b/build.gradle @@ -112,8 +112,8 @@ switch (OperatingSystem.current()) { case OperatingSystem.LINUX: def osArch = System.getProperty("os.arch") project.ext.lwjglNatives = osArch.startsWith("arm") || osArch.startsWith("aarch64") - ? "natives-linux-${osArch.contains("64") || osArch.startsWith("armv8") ? "arm64" : "arm32"}" - : "natives-linux" + ? "$lwjglNatives-${osArch.contains("64") || osArch.startsWith("armv8") ? "arm64" : "arm32"}" + : "$lwjglNatives" break case OperatingSystem.WINDOWS: project.ext.lwjglNatives = "natives-windows" @@ -134,30 +134,30 @@ dependencies { include(implementation("org.lwjgl:lwjgl-shaderc")) include(implementation("org.lwjgl:lwjgl-spvc")) - include(runtimeOnly("org.lwjgl:lwjgl-meshoptimizer:$lwjglVersion:natives-linux")) - include(runtimeOnly("org.lwjgl:lwjgl-vma:$lwjglVersion:natives-linux")) - include(runtimeOnly("org.lwjgl:lwjgl-shaderc:$lwjglVersion:natives-linux")) - include(runtimeOnly("org.lwjgl:lwjgl-spvc:$lwjglVersion:natives-linux")) + include(runtimeOnly("org.lwjgl:lwjgl-meshoptimizer:$lwjglVersion:$lwjglNatives")) + include(runtimeOnly("org.lwjgl:lwjgl-vma:$lwjglVersion:$lwjglNatives")) + include(runtimeOnly("org.lwjgl:lwjgl-shaderc:$lwjglVersion:$lwjglNatives")) + include(runtimeOnly("org.lwjgl:lwjgl-spvc:$lwjglVersion:$lwjglNatives")) - include(implementation("org.lwjgl:lwjgl-meshoptimizer:$lwjglVersion:natives-linux")) - include(implementation("org.lwjgl:lwjgl-vma:$lwjglVersion:natives-linux")) - include(implementation("org.lwjgl:lwjgl-shaderc:$lwjglVersion:natives-linux")) - include(implementation("org.lwjgl:lwjgl-spvc:$lwjglVersion:natives-linux")) + include(implementation("org.lwjgl:lwjgl-meshoptimizer:$lwjglVersion:$lwjglNatives")) + include(implementation("org.lwjgl:lwjgl-vma:$lwjglVersion:$lwjglNatives")) + include(implementation("org.lwjgl:lwjgl-shaderc:$lwjglVersion:$lwjglNatives")) + include(implementation("org.lwjgl:lwjgl-spvc:$lwjglVersion:$lwjglNatives")) implementation "org.lwjgl:lwjgl" implementation "org.lwjgl:lwjgl-glfw" implementation "org.lwjgl:lwjgl-opengl" - runtimeOnly "org.lwjgl:lwjgl::natives-linux" - runtimeOnly "org.lwjgl:lwjgl-glfw::natives-linux" - runtimeOnly "org.lwjgl:lwjgl-opengl::natives-linux" + runtimeOnly "org.lwjgl:lwjgl::$lwjglNatives" + runtimeOnly "org.lwjgl:lwjgl-glfw::$lwjglNatives" + runtimeOnly "org.lwjgl:lwjgl-opengl::$lwjglNatives" } project.ext.lwjglVersion = "3.3.1" project.ext.jomlVersion = "1.10.4" project.ext.winNatives = "natives-windows" -project.ext.linuxNatives = "natives-linux" +project.ext.linuxNatives = "$lwjglNatives" dependencies { include(implementation("org.lwjgl:lwjgl:$lwjglVersion")) From 71c301e97f79a2bd813243c79744342792e23cb4 Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Mon, 3 Jun 2024 13:05:34 -0700 Subject: [PATCH 19/22] more fix for the natives and ignore texture setup in entity capture for now --- build.gradle | 1 - .../acceleration/EntityBlasBuilder.java | 18 ++++++++-------- .../client/rendering/EntityCapture.java | 21 ++++++++++++------- .../iris/MixinShaderStorageBufferHolder.java | 2 +- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/build.gradle b/build.gradle index 1aa15fc..db06c5d 100644 --- a/build.gradle +++ b/build.gradle @@ -123,7 +123,6 @@ switch (OperatingSystem.current()) { repositories { mavenCentral() } -project.ext.lwjglNatives = "natives-windows" dependencies { implementation platform("org.lwjgl:lwjgl-bom:$lwjglVersion") diff --git a/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java b/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java index a89f3fd..0a6edd4 100644 --- a/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java +++ b/src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java @@ -91,15 +91,15 @@ List buildBlas(List> re long combined_size = 0; TextureManager textureManager = MinecraftClient.getInstance().getTextureManager(); for (var type : renders) { - if (((RenderLayer.MultiPhase) type.getLeft()).phases.texture instanceof RenderPhase.Textures) { - throw new IllegalStateException("Multi texture not supported"); - } - var textureId = ((RenderLayer.MultiPhase) type.getLeft()).phases.texture.getId().get(); - var texture = textureManager.getTexture(textureId); - var vkImage = ((IVGImage) texture).getVGImage(); - if (vkImage == null) { - throw new IllegalStateException("Vulkan texture not created for render layer " + type.getLeft()); - } +// if (((RenderLayer.MultiPhase) type.getLeft()).phases.texture instanceof RenderPhase.Textures) { +// throw new IllegalStateException("Multi texture not supported"); +// } +// var textureId = ((RenderLayer.MultiPhase) type.getLeft()).phases.texture.getId().get(); +// var texture = textureManager.getTexture(textureId); +// var vkImage = ((IVGImage) texture).getVGImage(); +// if (vkImage == null) { +// throw new IllegalStateException("Vulkan texture not created for render layer " + type.getLeft()); +// } if (!type.getRight().getParameters().format().equals(IrisVertexFormats.ENTITY)) { throw new IllegalStateException("Unknown vertex format used"); } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/EntityCapture.java b/src/main/java/me/cortex/vulkanite/client/rendering/EntityCapture.java index c11a882..56ab91b 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/EntityCapture.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/EntityCapture.java @@ -8,6 +8,7 @@ import me.cortex.vulkanite.lib.memory.VBuffer; import me.cortex.vulkanite.lib.other.VUtil; import me.cortex.vulkanite.lib.other.sync.VFence; +import net.irisshaders.iris.layer.OuterWrappedRenderType; import net.irisshaders.iris.mixin.LevelRendererAccessor; import net.irisshaders.iris.vertices.IrisVertexFormats; import net.minecraft.client.MinecraftClient; @@ -83,23 +84,27 @@ public List> end() { //TODO: Doesnt support terrian vertex format yet, requires a second blas so that the instance offset can be the same // as terrain instance offset if (builtBuffer.getParameters().format().equals(IrisVertexFormats.TERRAIN)) { + System.out.println("Skipping block entities (TERRAIN format)"); return; } // TODO: Support anything other than ENTITY if (!builtBuffer.getParameters().format().equals(IrisVertexFormats.ENTITY)) { + System.out.println("Skipping non-Entity format: " + builtBuffer.getParameters().format().toString()); return; } //Dont support no texture things - if (!(layer instanceof RenderLayer.MultiPhase)) { - return; - } - - var texture = ((RenderLayer.MultiPhase)layer).phases.texture; - if ((texture == null) || (texture.getId().isEmpty())) { - return; - } +// if (!(layer instanceof OuterWrappedRenderType)) { +// System.out.println("Skipping render layer that's not a MultiPhase, is " + layer.getClass().getName() + " instead"); +// return; +// } +// +// var texture = ((RenderLayer.MultiPhase)layer).phases.texture; +// if ((texture == null) || (texture.getId().isEmpty())) { +// System.out.println("Skipping render layer with no texture"); +// return; +// } buffers.add(new Pair<>(layer, builtBuffer)); } diff --git a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBufferHolder.java b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBufferHolder.java index d569e84..f0027fd 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBufferHolder.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBufferHolder.java @@ -37,7 +37,7 @@ private void redirectSizeAllocation(ShaderStorageBuffer instance, int width, int if (storageInfo.relative()) { instance.resizeIfRelative(width, height); } else { - ((IVGBuffer)instance).setBuffer(alloc(storageInfo.size())); + ((IVGBuffer)instance).setBuffer(alloc((int)storageInfo.size())); GlStateManager._glBindBuffer(GL43C.GL_SHADER_STORAGE_BUFFER, instance.getId()); IrisRenderSystem.clearBufferSubData(GL43C.GL_SHADER_STORAGE_BUFFER, GL43C.GL_R8, 0, storageInfo.size(), GL43C.GL_RED, GL43C.GL_BYTE, new int[] {0}); IrisRenderSystem.bindBufferBase(GL43C.GL_SHADER_STORAGE_BUFFER, instance.getIndex(), instance.getId()); From 1d0bfa2d8f68d13ed74ca159909c3fac208aa0d3 Mon Sep 17 00:00:00 2001 From: xirreal Date: Fri, 7 Jun 2024 22:10:45 +0200 Subject: [PATCH 20/22] Fix LWJGL dependencies being duplicated --- build.gradle | 38 ++++---------------------------------- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/build.gradle b/build.gradle index 1aa15fc..dba9246 100644 --- a/build.gradle +++ b/build.gradle @@ -107,6 +107,7 @@ publishing { import org.gradle.internal.os.OperatingSystem project.ext.lwjglVersion = "3.3.3" +project.ext.jomlVersion = "1.10.4" switch (OperatingSystem.current()) { case OperatingSystem.LINUX: @@ -123,14 +124,14 @@ switch (OperatingSystem.current()) { repositories { mavenCentral() } -project.ext.lwjglNatives = "natives-windows" dependencies { + include(implementation("org.joml:joml:${jomlVersion}")) + implementation platform("org.lwjgl:lwjgl-bom:$lwjglVersion") include(implementation("org.lwjgl:lwjgl-meshoptimizer")) include(implementation("org.lwjgl:lwjgl-vma")) - include(implementation("org.lwjgl:lwjgl-vulkan")) include(implementation("org.lwjgl:lwjgl-shaderc")) include(implementation("org.lwjgl:lwjgl-spvc")) @@ -139,47 +140,16 @@ dependencies { include(runtimeOnly("org.lwjgl:lwjgl-shaderc:$lwjglVersion:$lwjglNatives")) include(runtimeOnly("org.lwjgl:lwjgl-spvc:$lwjglVersion:$lwjglNatives")) + include(implementation("org.lwjgl:lwjgl-vulkan:$lwjglVersion")) include(implementation("org.lwjgl:lwjgl-meshoptimizer:$lwjglVersion:$lwjglNatives")) include(implementation("org.lwjgl:lwjgl-vma:$lwjglVersion:$lwjglNatives")) include(implementation("org.lwjgl:lwjgl-shaderc:$lwjglVersion:$lwjglNatives")) include(implementation("org.lwjgl:lwjgl-spvc:$lwjglVersion:$lwjglNatives")) - implementation "org.lwjgl:lwjgl" implementation "org.lwjgl:lwjgl-glfw" implementation "org.lwjgl:lwjgl-opengl" runtimeOnly "org.lwjgl:lwjgl::$lwjglNatives" runtimeOnly "org.lwjgl:lwjgl-glfw::$lwjglNatives" runtimeOnly "org.lwjgl:lwjgl-opengl::$lwjglNatives" -} - - -project.ext.lwjglVersion = "3.3.1" -project.ext.jomlVersion = "1.10.4" -project.ext.winNatives = "natives-windows" -project.ext.linuxNatives = "$lwjglNatives" - -dependencies { - include(implementation("org.lwjgl:lwjgl:$lwjglVersion")) - include(implementation("org.lwjgl:lwjgl-vulkan:$lwjglVersion")) - include(implementation("org.lwjgl:lwjgl-vma:$lwjglVersion")) - include(implementation("org.joml:joml:${jomlVersion}")) - include(runtimeOnly("org.lwjgl:lwjgl-vma:$lwjglVersion:$winNatives")) - include(runtimeOnly("org.lwjgl:lwjgl-vma:$lwjglVersion:$linuxNatives")) - - include(implementation("org.lwjgl:lwjgl-glfw:$lwjglVersion")) - include(runtimeOnly("org.lwjgl:lwjgl-glfw:$lwjglVersion:$winNatives")) - include(runtimeOnly("org.lwjgl:lwjgl-glfw:$lwjglVersion:$linuxNatives")) - include(implementation("org.lwjgl:lwjgl-stb:$lwjglVersion")) - include(runtimeOnly("org.lwjgl:lwjgl-stb:$lwjglVersion:$winNatives")) - include(runtimeOnly("org.lwjgl:lwjgl-stb:$lwjglVersion:$linuxNatives")) - include(implementation("org.lwjgl:lwjgl-openal:$lwjglVersion")) - include(runtimeOnly("org.lwjgl:lwjgl-openal:$lwjglVersion:$winNatives")) - include(runtimeOnly("org.lwjgl:lwjgl-openal:$lwjglVersion:$linuxNatives")) - include(runtimeOnly("org.lwjgl:lwjgl:$lwjglVersion:$winNatives")) - include(runtimeOnly("org.lwjgl:lwjgl:$lwjglVersion:$linuxNatives")) - - include(implementation("org.lwjgl:lwjgl-shaderc:$lwjglVersion")) - include(runtimeOnly("org.lwjgl:lwjgl-shaderc:$lwjglVersion:$winNatives")) - include(runtimeOnly("org.lwjgl:lwjgl-shaderc:$lwjglVersion:$linuxNatives")) } \ No newline at end of file From e0df0e27a69b6bf981059403ff2e98b3d6401238 Mon Sep 17 00:00:00 2001 From: Bob Cao Date: Fri, 7 Jun 2024 17:29:58 -0700 Subject: [PATCH 21/22] Update build.gradle --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index dba9246..bd98c4b 100644 --- a/build.gradle +++ b/build.gradle @@ -113,8 +113,8 @@ switch (OperatingSystem.current()) { case OperatingSystem.LINUX: def osArch = System.getProperty("os.arch") project.ext.lwjglNatives = osArch.startsWith("arm") || osArch.startsWith("aarch64") - ? "$lwjglNatives-${osArch.contains("64") || osArch.startsWith("armv8") ? "arm64" : "arm32"}" - : "$lwjglNatives" + ? "natives-linux-${osArch.contains("64") || osArch.startsWith("armv8") ? "arm64" : "arm32"}" + : "natives-linux" break case OperatingSystem.WINDOWS: project.ext.lwjglNatives = "natives-windows" @@ -152,4 +152,4 @@ dependencies { runtimeOnly "org.lwjgl:lwjgl::$lwjglNatives" runtimeOnly "org.lwjgl:lwjgl-glfw::$lwjglNatives" runtimeOnly "org.lwjgl:lwjgl-opengl::$lwjglNatives" -} \ No newline at end of file +} From 23841741fe4ad15ba7e788dba6698fa5d6831322 Mon Sep 17 00:00:00 2001 From: Cheng Cao Date: Fri, 7 Jun 2024 17:25:42 -0700 Subject: [PATCH 22/22] close before setting it loose to GC --- .../me/cortex/vulkanite/mixin/sodium/gl/MixinGLRenderDevice.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/me/cortex/vulkanite/mixin/sodium/gl/MixinGLRenderDevice.java b/src/main/java/me/cortex/vulkanite/mixin/sodium/gl/MixinGLRenderDevice.java index aa154c4..aab20dc 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/sodium/gl/MixinGLRenderDevice.java +++ b/src/main/java/me/cortex/vulkanite/mixin/sodium/gl/MixinGLRenderDevice.java @@ -13,6 +13,7 @@ public class MixinGLRenderDevice { @Inject(method = "deleteBuffer", at = @At("HEAD"), cancellable = true) private void redirectDelete(GlBuffer buffer, CallbackInfo ci) { if (buffer instanceof IVGBuffer vkBuffer && vkBuffer.getBuffer() != null) { + vkBuffer.getBuffer().close(); vkBuffer.setBuffer(null); ci.cancel(); }