From 815c6350cc1ba0375da7443386fb470605368cdb Mon Sep 17 00:00:00 2001 From: mcrcortex <18544518+MCRcortex@users.noreply.github.com> Date: Sun, 15 Oct 2023 19:37:15 +1000 Subject: [PATCH] Almost works --- build.gradle | 7 +- .../client/rendering/VkPipeline2.java | 148 +++++++++++++++++- .../client/rendering/VulkanPipeline.java | 21 ++- .../client/rendering/srp/SRPContext.java | 21 --- .../srp/api/VirtualResourceMapper.java | 4 + .../api/execution/DescriptorSetBuilder.java | 56 +++++++ .../srp/api/execution/ExecutionConstants.java | 17 ++ .../srp/api/execution/ExecutionContext.java | 35 ++--- .../execution/ExternalResourceTracker.java | 25 +++ .../srp/api/execution/ResourceMapping.java | 32 ++++ .../rendering/srp/api/layout/Layout.java | 25 ++- .../srp/api/layout/LayoutBinding.java | 34 +++- .../srp/api/pipeline/ComputePipeline.java | 8 +- .../rendering/srp/api/pipeline/Pipeline.java | 17 +- .../srp/api/pipeline/TracePipeline.java | 4 +- .../rendering/srp/graph/GraphExecutor.java | 16 ++ .../rendering/srp/graph/RenderGraph.java | 14 +- .../rendering/srp/graph/phase/Pass.java | 7 +- .../srp/graph/phase/pipeline/ComputePass.java | 21 ++- .../graph/phase/pipeline/PipelinePass.java | 101 ++++++++++-- .../srp/graph/phase/pipeline/TracePass.java | 21 ++- .../graph/resource/AccelerationResource.java | 4 - .../ExternalAccelerationResource.java | 20 +++ .../graph/resource/ExternalBoundLayout.java | 17 +- .../resource/ExternalBufferResource.java | 21 +++ .../graph/resource/ExternalImageResource.java | 18 ++- .../srp/graph/resource/ExternalResource.java | 4 +- .../srp/graph/resource/Resource.java | 7 + .../rendering/srp/lua/LuaContextHost.java | 69 ++++++-- .../rendering/srp/lua/LuaExternalObjects.java | 33 ++++ .../rendering/srp/lua/LuaFunctions.java | 121 ++++++++++---- .../rendering/srp/lua/LuaJavaLoader.java | 53 +++++++ .../vulkanite/client/rendering/srp/test2.java | 2 +- .../vulkanite/client/rendering/srp/test3.java | 8 +- .../lib/base/TrackedResourceObject.java | 6 + .../lib/descriptors/VDescriptorSet.java | 2 +- .../lib/pipeline/VComputePipeline.java | 18 ++- .../lib/pipeline/VRaytracePipeline.java | 4 +- .../cortex/vulkanite/lib/shader/VShader.java | 12 +- .../shader/reflection/ShaderReflection.java | 62 ++++++-- .../iris/MixinNewWorldRenderingPipeline.java | 29 +++- src/main/resources/fabric.mod.json | 2 +- 42 files changed, 967 insertions(+), 179 deletions(-) delete mode 100644 src/main/java/me/cortex/vulkanite/client/rendering/srp/SRPContext.java create mode 100644 src/main/java/me/cortex/vulkanite/client/rendering/srp/api/VirtualResourceMapper.java create mode 100644 src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/DescriptorSetBuilder.java create mode 100644 src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/ExecutionConstants.java create mode 100644 src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/ExternalResourceTracker.java create mode 100644 src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/ResourceMapping.java create mode 100644 src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/GraphExecutor.java delete mode 100644 src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/AccelerationResource.java create mode 100644 src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalAccelerationResource.java create mode 100644 src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalBufferResource.java create mode 100644 src/main/java/me/cortex/vulkanite/client/rendering/srp/lua/LuaExternalObjects.java create mode 100644 src/main/java/me/cortex/vulkanite/client/rendering/srp/lua/LuaJavaLoader.java diff --git a/build.gradle b/build.gradle index 3749086..53f1daa 100644 --- a/build.gradle +++ b/build.gradle @@ -47,8 +47,8 @@ dependencies { modRuntimeOnly 'net.java.dev.jna:jna:5.9.0' - implementation("com.github.FiguraMC.LuaJ:luaj-core:3.0.6-figura") - implementation("com.github.FiguraMC.LuaJ:luaj-jse:3.0.6-figura") + include(implementation("com.github.FiguraMC.LuaJ:luaj-core:3.0.6-figura")) + include(implementation("com.github.FiguraMC.LuaJ:luaj-jse:3.0.6-figura")) } processResources { @@ -186,4 +186,7 @@ dependencies { include(implementation("org.lwjgl:lwjgl-shaderc:$lwjglVersion")) include(runtimeOnly("org.lwjgl:lwjgl-shaderc:$lwjglVersion:$winNatives")) include(runtimeOnly("org.lwjgl:lwjgl-shaderc:$lwjglVersion:$linuxNatives")) + + include(runtimeOnly("org.lwjgl:lwjgl-spvc:$lwjglVersion:$winNatives")) + include(runtimeOnly("org.lwjgl:lwjgl-spvc:$lwjglVersion:$linuxNatives")) } \ No newline at end of file diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/VkPipeline2.java b/src/main/java/me/cortex/vulkanite/client/rendering/VkPipeline2.java index 83e87d9..8128ee7 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/VkPipeline2.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/VkPipeline2.java @@ -1,25 +1,167 @@ package me.cortex.vulkanite.client.rendering; import me.cortex.vulkanite.acceleration.AccelerationManager; +import me.cortex.vulkanite.client.Vulkanite; +import me.cortex.vulkanite.client.rendering.srp.graph.GraphExecutor; +import me.cortex.vulkanite.client.rendering.srp.lua.LuaContextHost; +import me.cortex.vulkanite.client.rendering.srp.lua.LuaExternalObjects; import me.cortex.vulkanite.compat.RaytracingShaderSet; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.cmd.VCmdBuff; import me.cortex.vulkanite.lib.cmd.VCommandPool; +import me.cortex.vulkanite.lib.memory.VBuffer; import me.cortex.vulkanite.lib.memory.VGImage; +import me.cortex.vulkanite.lib.other.sync.VGSemaphore; +import me.cortex.vulkanite.lib.other.sync.VSemaphore; +import me.cortex.vulkanite.mixin.iris.MixinCelestialUniforms; +import me.cortex.vulkanite.mixin.iris.MixinCommonUniforms; +import net.coderbot.iris.texture.pbr.PBRTextureManager; +import net.coderbot.iris.uniforms.CapturedRenderingState; +import net.coderbot.iris.uniforms.CelestialUniforms; +import net.coderbot.iris.uniforms.SystemTimeUniforms; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.Camera; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.lwjgl.system.MemoryUtil; + +import java.nio.ByteBuffer; + +import static org.lwjgl.opengl.EXTSemaphore.GL_LAYOUT_GENERAL_EXT; +import static org.lwjgl.opengl.GL11C.glFinish; +import static org.lwjgl.opengl.GL11C.glFlush; +import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; +import static org.lwjgl.vulkan.KHRRayTracingPipeline.VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR; +import static org.lwjgl.vulkan.VK10.*; +import static org.lwjgl.vulkan.VK10.VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; public class VkPipeline2 { private final VContext ctx; private final AccelerationManager accelerationManager; private final VCommandPool singleUsePool; + private final LuaContextHost pipeline; + private final EntityCapture capture = new EntityCapture(); - - public VkPipeline2(VContext ctx, AccelerationManager accelerationManager, RaytracingShaderSet[] passes, int[] ssboIds, VGImage[] customTextures) { + public VkPipeline2(VContext ctx, LuaContextHost pipeline, AccelerationManager accelerationManager) { this.ctx = ctx; this.accelerationManager = accelerationManager; this.singleUsePool = ctx.cmd.createSingleUsePool(); + pipeline.loadScript("srp.lua"); + pipeline.run(); + this.pipeline = pipeline; + } + + private void buildEntities() { + accelerationManager.setEntityData(capture.capture(CapturedRenderingState.INSTANCE.getTickDelta(), MinecraftClient.getInstance().world)); + } + + private Camera camera; + private MixinCelestialUniforms celestialUniforms; + + public void setup(Camera camera, MixinCelestialUniforms celestialUniforms) { + this.camera = camera; + this.celestialUniforms = celestialUniforms; + } + + private VBuffer createUBO() { + VBuffer 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); + long ptr = uboBuffer.map(); + MemoryUtil.memSet(ptr, 0, 1024); + { + ByteBuffer bb = MemoryUtil.memByteBuffer(ptr, 1024); + + Vector3f tmpv3 = new Vector3f(); + Matrix4f invProjMatrix = new Matrix4f(); + Matrix4f invViewMatrix = new Matrix4f(); + + CapturedRenderingState.INSTANCE.getGbufferProjection().invert(invProjMatrix); + new Matrix4f(CapturedRenderingState.INSTANCE.getGbufferModelView()).translate(camera.getPos().toVector3f().negate()).invert(invViewMatrix); + + invProjMatrix.transformProject(-1, -1, 0, 1, tmpv3).get(bb); + invProjMatrix.transformProject(+1, -1, 0, 1, tmpv3).get(4*Float.BYTES, bb); + invProjMatrix.transformProject(-1, +1, 0, 1, tmpv3).get(8*Float.BYTES, bb); + invProjMatrix.transformProject(+1, +1, 0, 1, tmpv3).get(12*Float.BYTES, bb); + invViewMatrix.get(Float.BYTES * 16, bb); + + celestialUniforms.invokeGetSunPosition().get(Float.BYTES * 32, bb); + celestialUniforms.invokeGetMoonPosition().get(Float.BYTES * 36, bb); + + bb.putInt(Float.BYTES * 40, SystemTimeUniforms.COUNTER.getAsInt()); + + int flags = MixinCommonUniforms.invokeIsEyeInWater() & 3; + bb.putInt(Float.BYTES * 41, flags); + bb.rewind(); + } + uboBuffer.unmap(); + uboBuffer.flush(); + return uboBuffer; } - private void buildGraph() { + public void execute() { + this.buildEntities(); + this.singleUsePool.doReleases(); + PBRTextureManager.notifyPBRTexturesChanged(); + + var outImgsGlIds = new int[0]; + var outImgsGlLayouts = new int[0]; + + var in = this.ctx.sync.createSharedBinarySemaphore(); + in.glSignal(new int[0], outImgsGlIds, outImgsGlLayouts); + glFlush(); + + var tlasLink = ctx.sync.createBinarySemaphore(); + var tlas = accelerationManager.buildTLAS(in, tlasLink); + + if (tlas == null) { + glFinish(); + tlasLink.free(); + in.free(); + return; + } + + if (LuaExternalObjects.TERRAIN_GEOMETRY_LAYOUT.getConcrete() != accelerationManager.getGeometrySet()) { + LuaExternalObjects.TERRAIN_GEOMETRY_LAYOUT.setConcrete(accelerationManager.getGeometrySet()); + } + + var ubo = this.createUBO(); + LuaExternalObjects.COMMON_UNIFORM_BUFFER.setConcrete(ubo); + LuaExternalObjects.WORLD_ACCELERATION_STRUCTURE.setConcrete(tlas); + + var cmd = this.singleUsePool.createCommandBuffer(); + cmd.begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); + var fence = this.ctx.sync.createFence(); + + + GraphExecutor.execute(this.pipeline.getGraph(), cmd, fence); + + + cmd.end(); + + var out = ctx.sync.createSharedBinarySemaphore(); + this.ctx.cmd.submit(0, new VCmdBuff[]{cmd}, new VSemaphore[]{tlasLink}, new int[]{VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR}, new VSemaphore[]{out}, fence); + + ctx.sync.addCallback(fence, ()->{ + in.free(); + cmd.enqueueFree(); + fence.free(); + tlasLink.free(); + ubo.free(); + Vulkanite.INSTANCE.addSyncedCallback(out::free); + }); + + out.glWait(new int[0], outImgsGlIds, outImgsGlLayouts); + glFlush(); + } + public void destory() { + vkDeviceWaitIdle(this.ctx.device); + this.pipeline.destory(); + this.ctx.sync.checkFences(); + this.singleUsePool.doReleases(); + this.singleUsePool.free(); } } 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 9b7dc99..62b60ac 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/VulkanPipeline.java @@ -24,7 +24,6 @@ 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.minecraft.client.MinecraftClient; import net.minecraft.client.render.Camera; @@ -172,27 +171,27 @@ public VulkanPipeline(VContext ctx, AccelerationManager accelerationManager, Ray supportsEntities = supportsEntitiesT; 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, 1), + new ShaderReflection.Binding("", 1, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0, false, 1), + new ShaderReflection.Binding("", 3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, false, 1), + new ShaderReflection.Binding("", 4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, false, 1), + new ShaderReflection.Binding("", 5, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, false, 1), + new ShaderReflection.Binding("", 6, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, maxIrisRenderTargets, false, 1), }); 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, 1) }); ArrayList customTexBindings = new ArrayList<>(); for (int i = 0; i < customTextureViews.length; i++) { - customTexBindings.add(new ShaderReflection.Binding("", i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, false)); + customTexBindings.add(new ShaderReflection.Binding("", i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, false, 2)); } var customTexSetExpected = new ShaderReflection.Set(customTexBindings); 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, true, 3)); } var ssboSetExpected = new ShaderReflection.Set(ssboBindings); @@ -394,7 +393,7 @@ public void renderPostShadows(List outImgs, Camera camera, ShaderStorag sets[record.ssboSet] = ssboSet.set; cmd.addTransientResource(ssboSet); } - pipeline.bindDSet(cmd, sets); + pipeline.bindDSets(cmd, sets); pipeline.trace(cmd, outImgs.get(0).width, outImgs.get(0).height, 1); // Barrier on the output images diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/SRPContext.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/SRPContext.java deleted file mode 100644 index b4e08f7..0000000 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/SRPContext.java +++ /dev/null @@ -1,21 +0,0 @@ -package me.cortex.vulkanite.client.rendering.srp; - -import me.cortex.vulkanite.client.rendering.srp.api.layout.Layout; -import me.cortex.vulkanite.client.rendering.srp.api.layout.LayoutBinding; -import me.cortex.vulkanite.client.rendering.srp.graph.resource.AccelerationResource; -import me.cortex.vulkanite.client.rendering.srp.graph.resource.ExternalBoundLayout; -import me.cortex.vulkanite.client.rendering.srp.graph.resource.ExternalImageResource; - -public class SRPContext { - public ExternalBoundLayout getExternalLayout(String identifier) { - return null;// new ExternalBoundLayout(new Layout(new LayoutBinding(1))).name(identifier); - } - - public AccelerationResource getAccelerationStructure(String identifier) { - return new AccelerationResource().name(identifier); - } - - public ExternalImageResource getExternalTexture(String identifier) { - return (ExternalImageResource) new ExternalImageResource().name(identifier); - } -} diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/VirtualResourceMapper.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/VirtualResourceMapper.java new file mode 100644 index 0000000..f5b2ffc --- /dev/null +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/VirtualResourceMapper.java @@ -0,0 +1,4 @@ +package me.cortex.vulkanite.client.rendering.srp.api; + +public interface VirtualResourceMapper { +} diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/DescriptorSetBuilder.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/DescriptorSetBuilder.java new file mode 100644 index 0000000..b645945 --- /dev/null +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/DescriptorSetBuilder.java @@ -0,0 +1,56 @@ +package me.cortex.vulkanite.client.rendering.srp.api.execution; + +import me.cortex.vulkanite.client.Vulkanite; +import me.cortex.vulkanite.client.rendering.srp.api.VirtualResourceMapper; +import me.cortex.vulkanite.client.rendering.srp.api.layout.Layout; +import me.cortex.vulkanite.client.rendering.srp.graph.resource.Resource; +import me.cortex.vulkanite.lib.cmd.VCmdBuff; +import me.cortex.vulkanite.lib.descriptors.DescriptorSetLayoutBuilder; +import me.cortex.vulkanite.lib.descriptors.VDescriptorSet; +import me.cortex.vulkanite.lib.descriptors.VDescriptorSetLayout; +import me.cortex.vulkanite.lib.descriptors.VTypedDescriptorPool; + +import java.util.List; + +import static org.lwjgl.vulkan.VK10.VK_SHADER_STAGE_ALL; +import static org.lwjgl.vulkan.VK12.VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT; + +//TODO: make into a cache thing so that it can reuse descriptor sets and VTypedDescriptorPool +public class DescriptorSetBuilder { + public static class BatchedUpdateDescriptorSet { + private final VTypedDescriptorPool pool; + public BatchedUpdateDescriptorSet(VTypedDescriptorPool pool) { + this.pool = pool; + } + + public long updateAndGetSet(VCmdBuff cmd) { + var set = pool.allocateSet(); + cmd.addTransientResource(set); + return set.set; + } + } + + public static BatchedUpdateDescriptorSet createDescriptorSet(VirtualResourceMapper mapper, Layout layout, List>> bindings) { + var layoutObj = createLayoutObject(layout); + var pool = new VTypedDescriptorPool(Vulkanite.INSTANCE.getCtx(), layoutObj, 0); + return new BatchedUpdateDescriptorSet(pool); + } + + private static VDescriptorSetLayout createLayoutObject(Layout layout) { + if (layout.hasUnsizedArrays()) { + throw new IllegalStateException("User defined layouts that are runtime sized are not supported"); + } + + var builder = new DescriptorSetLayoutBuilder(); + for (var binding : layout.getBindings()) { + if (binding.arraySize > 0) { + builder.binding(binding.index, binding.type, binding.arraySize, VK_SHADER_STAGE_ALL); + builder.setBindingFlags(binding.index, VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT); + } else { + builder.binding(binding.index, binding.type, VK_SHADER_STAGE_ALL); + } + } + + return builder.build(Vulkanite.INSTANCE.getCtx()); + } +} diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/ExecutionConstants.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/ExecutionConstants.java new file mode 100644 index 0000000..02e6c4d --- /dev/null +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/ExecutionConstants.java @@ -0,0 +1,17 @@ +package me.cortex.vulkanite.client.rendering.srp.api.execution; + +import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.cmd.VCmdBuff; +import me.cortex.vulkanite.lib.other.sync.VFence; +import net.coderbot.iris.uniforms.CommonUniforms; +import net.minecraft.client.MinecraftClient; +import org.joml.Vector2i; +import org.joml.Vector3i; + +public class ExecutionConstants { + public static ExecutionConstants INSTANCE = new ExecutionConstants(); + + public Vector2i getScreenSize() { + return new Vector2i(MinecraftClient.getInstance().getFramebuffer().textureWidth, MinecraftClient.getInstance().getFramebuffer().textureHeight); + } +} diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/ExecutionContext.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/ExecutionContext.java index 4b1a1a9..7878ba7 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/ExecutionContext.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/ExecutionContext.java @@ -1,32 +1,17 @@ package me.cortex.vulkanite.client.rendering.srp.api.execution; -import me.cortex.vulkanite.client.rendering.srp.graph.resource.AccelerationResource; -import me.cortex.vulkanite.client.rendering.srp.graph.resource.BufferResource; -import me.cortex.vulkanite.client.rendering.srp.graph.resource.ExternalImageResource; -import me.cortex.vulkanite.client.rendering.srp.graph.resource.ImageResource; -import me.cortex.vulkanite.lib.memory.VAccelerationStructure; -import me.cortex.vulkanite.lib.memory.VBuffer; -import me.cortex.vulkanite.lib.memory.VImage; +import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.cmd.VCmdBuff; +import me.cortex.vulkanite.lib.other.sync.VFence; -//Provides mappings from virtual resource definitions to concrete objects public class ExecutionContext { - public VAccelerationStructure getConcreteAcceleration(AccelerationResource resource) { - return null; - } - - public VImage getConcreteExternalImage(ExternalImageResource resource) { - return null; - } - - public VImage getConcreteImage(ImageResource resource) { - return null; - } - - public VBuffer getConcreteBuffer(BufferResource resource) { - return null; - } + public final VContext ctx; + public final VCmdBuff cmd; + public final VFence fence; - public VBuffer getConcreteExternalBuffer(BufferResource resource) { - return null; + public ExecutionContext(VContext ctx, VCmdBuff cmd, VFence fence) { + this.ctx = ctx; + this.cmd = cmd; + this.fence = fence; } } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/ExternalResourceTracker.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/ExternalResourceTracker.java new file mode 100644 index 0000000..3b92fcc --- /dev/null +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/ExternalResourceTracker.java @@ -0,0 +1,25 @@ +package me.cortex.vulkanite.client.rendering.srp.api.execution; + +import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; +import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; +import me.cortex.vulkanite.client.rendering.srp.graph.resource.ExternalResource; + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +public class ExternalResourceTracker { + private static final Reference2ObjectMap, Set>>> CALLBACKS = new Reference2ObjectOpenHashMap<>(); + + public static ,J> void registerCallback(ExternalResource resource, Consumer callback) { + CALLBACKS.computeIfAbsent(resource, a->new LinkedHashSet<>()).add((Consumer>) callback); + } + + public static ,J> void update(ExternalResource externalResource) { + CALLBACKS.getOrDefault(externalResource, Set.of()).forEach(callback->callback.accept(externalResource)); + } + + public static void resetAllCallbacks() { + CALLBACKS.clear(); + } +} diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/ResourceMapping.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/ResourceMapping.java new file mode 100644 index 0000000..35ac252 --- /dev/null +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/execution/ResourceMapping.java @@ -0,0 +1,32 @@ +package me.cortex.vulkanite.client.rendering.srp.api.execution; + +import me.cortex.vulkanite.client.rendering.srp.graph.resource.ExternalAccelerationResource; +import me.cortex.vulkanite.client.rendering.srp.graph.resource.BufferResource; +import me.cortex.vulkanite.client.rendering.srp.graph.resource.ExternalImageResource; +import me.cortex.vulkanite.client.rendering.srp.graph.resource.ImageResource; +import me.cortex.vulkanite.lib.memory.VAccelerationStructure; +import me.cortex.vulkanite.lib.memory.VBuffer; +import me.cortex.vulkanite.lib.memory.VImage; + +//Provides mappings from virtual resource definitions to concrete objects +public class ResourceMapping { + public VAccelerationStructure getConcreteAcceleration(ExternalAccelerationResource resource) { + return null; + } + + public VImage getConcreteExternalImage(ExternalImageResource resource) { + return null; + } + + public VImage getConcreteImage(ImageResource resource) { + return null; + } + + public VBuffer getConcreteBuffer(BufferResource resource) { + return null; + } + + public VBuffer getConcreteExternalBuffer(BufferResource resource) { + return null; + } +} diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/layout/Layout.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/layout/Layout.java index a1d1d0b..e3bc3ea 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/layout/Layout.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/layout/Layout.java @@ -2,18 +2,37 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; public class Layout { private final List bindings = new ArrayList<>(); - private final boolean runtimeSized; - public Layout(boolean runtimeSized, LayoutBinding... bindings) { - this.runtimeSized = runtimeSized; + private final int hash; + public Layout(LayoutBinding... bindings) { this.bindings.addAll(List.of(bindings)); + this.hash = Objects.hash(this.bindings); } public List getBindings() { return this.bindings; } + @Override + public boolean equals(Object object) { + if (this == object) + return true; + if (object == null || getClass() != object.getClass()) + return false; + Layout layout = (Layout) object; + return this.hash == layout.hash && Objects.equals(bindings, layout.bindings); + } + + @Override + public int hashCode() { + return hash; + } + + public boolean hasUnsizedArrays() { + return this.bindings.stream().anyMatch(a->a.arraySize==-1); + } } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/layout/LayoutBinding.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/layout/LayoutBinding.java index 1e0ef4f..3ab983f 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/layout/LayoutBinding.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/layout/LayoutBinding.java @@ -1,12 +1,15 @@ package me.cortex.vulkanite.client.rendering.srp.api.layout; +import java.util.Objects; + public class LayoutBinding { - private final String name; - private final int index; - private final int type; - private final int access; - private final int arraySize; + public final String name; + public final int index; + public final int type; + public final int access; + public final int arraySize; + private final int hash; public LayoutBinding(int index, int access, int type, int arraySize) { this(null, index, access, type, arraySize); } @@ -17,6 +20,8 @@ public LayoutBinding(String name, int index, int access, int type, int arraySize this.access = access; this.type = type; this.arraySize = arraySize; + + this.hash = Objects.hash(index, access, type, arraySize); } public boolean writes() { @@ -26,4 +31,23 @@ public boolean writes() { public boolean reads() { return (access&1)!=0; } + + @Override + public int hashCode() { + return this.hash; + } + + @Override + public boolean equals(Object object) { + if (this == object) + return true; + if (object == null || getClass() != object.getClass()) + return false; + LayoutBinding that = (LayoutBinding) object; + return hash == that.hash && index == that.index && type == that.type && access == that.access && arraySize == that.arraySize; + } + + public int type() { + return this.type; + } } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/pipeline/ComputePipeline.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/pipeline/ComputePipeline.java index 2f06a8f..e76f077 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/pipeline/ComputePipeline.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/pipeline/ComputePipeline.java @@ -6,8 +6,12 @@ import java.util.ArrayList; import java.util.List; -public class ComputePipeline extends Pipeline { +public class ComputePipeline extends Pipeline { public ComputePipeline(VComputePipeline pipeline, Layout... layouts) { - super(List.of(layouts)); + this(pipeline, List.of(layouts)); + } + + public ComputePipeline(VComputePipeline pipeline, List layouts) { + super(pipeline, layouts); } } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/pipeline/Pipeline.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/pipeline/Pipeline.java index bd0af3b..5ec9dd0 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/pipeline/Pipeline.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/pipeline/Pipeline.java @@ -4,14 +4,25 @@ import java.util.List; -public abstract class Pipeline > { +public abstract class Pipeline , J> { + protected final J concretePipeline; + protected final List layouts; - protected Pipeline(List layouts) { + protected Pipeline(J concretePipeline, List layouts) { + this.concretePipeline = concretePipeline; this.layouts = layouts; } public Layout getLayout(int index) { - return layouts.get(index); + return this.layouts.get(index); + } + + public J getConcretePipeline() { + return this.concretePipeline; + } + + public List getLayouts() { + return this.layouts; } } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/pipeline/TracePipeline.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/pipeline/TracePipeline.java index 00bef83..848573b 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/pipeline/TracePipeline.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/api/pipeline/TracePipeline.java @@ -7,12 +7,12 @@ import java.util.ArrayList; import java.util.List; -public class TracePipeline extends Pipeline { +public class TracePipeline extends Pipeline { public TracePipeline(VRaytracePipeline pipeline, Layout... layouts) { this(pipeline, List.of(layouts)); } public TracePipeline(VRaytracePipeline pipeline, List layouts) { - super(layouts); + super(pipeline, layouts); } } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/GraphExecutor.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/GraphExecutor.java new file mode 100644 index 0000000..6b9c75a --- /dev/null +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/GraphExecutor.java @@ -0,0 +1,16 @@ +package me.cortex.vulkanite.client.rendering.srp.graph; + +import me.cortex.vulkanite.client.Vulkanite; +import me.cortex.vulkanite.client.rendering.srp.api.execution.ExecutionContext; +import me.cortex.vulkanite.client.rendering.srp.graph.phase.Pass; +import me.cortex.vulkanite.lib.cmd.VCmdBuff; +import me.cortex.vulkanite.lib.other.sync.VFence; + +public class GraphExecutor { + public static void execute(RenderGraph graph, VCmdBuff cmdBuffer, VFence fence) { + var ectx = new ExecutionContext(Vulkanite.INSTANCE.getCtx(), cmdBuffer, fence); + for (Pass pass : graph.ordering) { + pass.execute(ectx); + } + } +} diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/RenderGraph.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/RenderGraph.java index 2f51c9e..a76de03 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/RenderGraph.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/RenderGraph.java @@ -2,18 +2,22 @@ import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; +import me.cortex.vulkanite.client.rendering.srp.api.VirtualResourceMapper; +import me.cortex.vulkanite.client.rendering.srp.api.execution.ExecutionContext; import me.cortex.vulkanite.client.rendering.srp.graph.phase.Pass; import me.cortex.vulkanite.client.rendering.srp.graph.resource.ExternalResource; import me.cortex.vulkanite.client.rendering.srp.graph.resource.Resource; import java.util.*; -public class RenderGraph { +public class RenderGraph implements VirtualResourceMapper { private final Reference2ObjectMap, Set>> dependents = new Reference2ObjectOpenHashMap<>(); private final List> outputs; private final Set> graphResources = new LinkedHashSet<>(); + final List> ordering = new ArrayList<>(); + public RenderGraph(Resource... outputs) { this(List.of(outputs)); } @@ -58,7 +62,7 @@ private void topologicalSort(List> sources) { if (lastRef == null) { //Resource is only ever read from // it MUST be an external reference - if (!(resource instanceof ExternalResource)) { + if (!(resource instanceof ExternalResource)) { throw new IllegalStateException("Tried reading from a resource thats never written to"); } continue; @@ -76,9 +80,11 @@ private void topologicalSort(List> sources) { for (var pass : ordering) { - pass.verify(); - System.err.println(pass.name()); + pass.verifyAndPrep(this); } + + this.ordering.clear(); + this.ordering.addAll(ordering); } private void topologicalSort0(Set> seen, Pass current, int depth, List> sort) { //TODO: want to actually find the range in which the phases can run diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/phase/Pass.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/phase/Pass.java index bd60cfb..c6c722e 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/phase/Pass.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/phase/Pass.java @@ -1,5 +1,7 @@ package me.cortex.vulkanite.client.rendering.srp.graph.phase; +import me.cortex.vulkanite.client.rendering.srp.api.VirtualResourceMapper; +import me.cortex.vulkanite.client.rendering.srp.api.execution.DescriptorSetBuilder; import me.cortex.vulkanite.client.rendering.srp.api.execution.ExecutionContext; import me.cortex.vulkanite.client.rendering.srp.graph.resource.Resource; @@ -37,9 +39,10 @@ public Collection> uses() { } //Verifies that everything is bound correctly and validly bound - public void verify(){}; + // also enable setup, such as creating layouts + public void verifyAndPrep(VirtualResourceMapper resourceMapper){} public void execute(ExecutionContext ctx) { - throw new IllegalStateException(); + throw new IllegalStateException("Execution not implemented"); } } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/phase/pipeline/ComputePass.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/phase/pipeline/ComputePass.java index bccbaaf..f0ef4fa 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/phase/pipeline/ComputePass.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/phase/pipeline/ComputePass.java @@ -1,9 +1,26 @@ package me.cortex.vulkanite.client.rendering.srp.graph.phase.pipeline; +import me.cortex.vulkanite.client.rendering.srp.api.execution.ExecutionContext; import me.cortex.vulkanite.client.rendering.srp.api.pipeline.ComputePipeline; +import me.cortex.vulkanite.lib.pipeline.VComputePipeline; +import org.joml.Vector3i; -public class ComputePass extends PipelinePass { - public ComputePass(ComputePipeline pipeline) { +import java.util.function.Supplier; + +public class ComputePass extends PipelinePass { + private final Supplier dispatchSizeSupplier; + + public ComputePass(ComputePipeline pipeline, Supplier dispatchSizeSupplier) { super(pipeline); + this.dispatchSizeSupplier = dispatchSizeSupplier; + } + + @Override + public void execute(ExecutionContext ctx) { + var pipe = this.pipeline.getConcretePipeline(); + var size = this.dispatchSizeSupplier.get(); + pipe.bind(ctx.cmd); + pipe.bindDSets(ctx.cmd, this.getDescriptorSets(ctx.cmd)); + pipe.dispatch(ctx.cmd, size.x, size.y, size.z); } } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/phase/pipeline/PipelinePass.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/phase/pipeline/PipelinePass.java index 71df143..26c75f8 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/phase/pipeline/PipelinePass.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/phase/pipeline/PipelinePass.java @@ -1,21 +1,27 @@ package me.cortex.vulkanite.client.rendering.srp.graph.phase.pipeline; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.function.Function; +import java.util.function.Supplier; +import me.cortex.vulkanite.client.rendering.srp.api.VirtualResourceMapper; +import me.cortex.vulkanite.client.rendering.srp.api.execution.DescriptorSetBuilder; import me.cortex.vulkanite.client.rendering.srp.api.layout.Layout; import me.cortex.vulkanite.client.rendering.srp.api.pipeline.Pipeline; import me.cortex.vulkanite.client.rendering.srp.graph.phase.Pass; -import me.cortex.vulkanite.client.rendering.srp.graph.resource.ExternalBoundLayout; -import me.cortex.vulkanite.client.rendering.srp.graph.resource.Resource; +import me.cortex.vulkanite.client.rendering.srp.graph.resource.*; +import me.cortex.vulkanite.lib.cmd.VCmdBuff; -public abstract class PipelinePass, J extends Pipeline> extends Pass { - protected final Pipeline pipeline; +import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; +import static org.lwjgl.vulkan.VK10.*; + +public abstract class PipelinePass, J extends Pipeline, P> extends Pass { + protected final Pipeline pipeline; protected final Map layoutBindings = new HashMap<>(); - public PipelinePass(Pipeline pipeline) { + private final List> descriptorSetProviders = new ArrayList<>(); + + public PipelinePass(Pipeline pipeline) { this.pipeline = pipeline; } @@ -23,18 +29,19 @@ public T bindLayout(Layout layout, Resource... bindings) { return (T) this.bindLayout(layout, Arrays.stream(bindings).map(List::of).toArray(List[]::new)); } - public T bindLayout(Layout layout, List>... bindings) { + public T bindLayout(Layout layout, List>... bindingArray) { + List>> bindings = List.of(bindingArray); if (this.layoutBindings.containsKey(layout)) { throw new IllegalStateException("Already bound layout"); } var bindingPoints = layout.getBindings(); - if (bindingPoints.size() != bindings.length) { + if (bindingPoints.size() != bindings.size()) { throw new IllegalStateException("Incorrect number of binding points"); } for (int i = 0; i < bindingPoints.size(); i++) { var bindingPoint = bindingPoints.get(i); - var bindingList = bindings[i]; + var bindingList = bindings.get(i); if (bindingPoint.reads()) { for (var binding : bindingList) { @@ -76,4 +83,74 @@ public T bindLayout(int index, List>... bindings) { public T bindLayout(Resource... bindings) { return this.bindLayout(0, bindings); } + + @Override + public void verifyAndPrep(VirtualResourceMapper resourceMapper) { + super.verifyAndPrep(resourceMapper); + this.validateLayoutBindings(resourceMapper); + } + + protected void validateLayoutBindings(VirtualResourceMapper resourceMapper) { + //Verify that the all the layout exist + if (!(this.layoutBindings.keySet().containsAll(this.pipeline.getLayouts()) && + new HashSet<>(this.pipeline.getLayouts()).containsAll(this.layoutBindings.keySet()))) { + throw new IllegalStateException("Pipeline doesnt have all the layouts bound"); + } + + for (var layout : this.pipeline.getLayouts()) { + var bindingObject = this.layoutBindings.get(layout); + if (bindingObject instanceof ExternalBoundLayout boundLayout) { + if (!boundLayout.layout().equals(layout)) { + throw new IllegalStateException("External bound layout does not match expected layout"); + } + this.descriptorSetProviders.add((cmd)->boundLayout.getConcrete()); + } else if (bindingObject instanceof List bindingList) { + var bindings = (List>>)bindingList; + if (bindings.size() != layout.getBindings().size()) { + throw new IllegalStateException("Binding length does not match"); + } + var bindingPoints = layout.getBindings(); + for (int i = 0; i < bindings.size(); i++) { + var binding = bindings.get(i); + var point = bindingPoints.get(i); + int pointType = switch (point.type()) { + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER -> 0; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER -> 0; + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER -> 1; + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE -> 1; + case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR -> 3; + + default -> throw new IllegalArgumentException("Unknown type: " + point.type()); + }; + int bindingType = -1; + var test = binding.get(0); + if (test instanceof BufferResource) { + bindingType = 0; + } else if (test instanceof ImageResource) { + bindingType = 1; + } else if (test instanceof ExternalAccelerationResource) { + bindingType = 3; + } else { + throw new IllegalStateException("Unknown binding type: " + test); + } + + if (pointType != bindingType) { + throw new IllegalStateException("Binding type and point type are not the same"); + } + } + var descriptorSet = DescriptorSetBuilder.createDescriptorSet(resourceMapper, layout, bindings); + this.descriptorSetProviders.add(descriptorSet::updateAndGetSet); + } else { + throw new IllegalStateException("Unknown binding method " + bindingObject); + } + } + } + + protected long[] getDescriptorSets(VCmdBuff cmd) { + var sets = new long[this.descriptorSetProviders.size()]; + for (int i = 0; i < sets.length; i++) { + sets[i] = this.descriptorSetProviders.get(i).apply(cmd); + } + return sets; + } } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/phase/pipeline/TracePass.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/phase/pipeline/TracePass.java index 907ad73..2ce91df 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/phase/pipeline/TracePass.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/phase/pipeline/TracePass.java @@ -1,10 +1,27 @@ package me.cortex.vulkanite.client.rendering.srp.graph.phase.pipeline; +import me.cortex.vulkanite.client.rendering.srp.api.execution.ExecutionContext; import me.cortex.vulkanite.client.rendering.srp.api.pipeline.TracePipeline; +import me.cortex.vulkanite.lib.pipeline.VRaytracePipeline; +import org.joml.Vector3i; -public class TracePass extends PipelinePass { - public TracePass(TracePipeline pipeline) { +import java.util.function.Supplier; + +public class TracePass extends PipelinePass { + private final Supplier dispatchSizeSupplier; + + public TracePass(TracePipeline pipeline, Supplier dispatchSizeSupplier) { super(pipeline); + this.dispatchSizeSupplier = dispatchSizeSupplier; + } + + @Override + public void execute(ExecutionContext ctx) { + var pipe = this.pipeline.getConcretePipeline(); + var size = this.dispatchSizeSupplier.get(); + pipe.bind(ctx.cmd); + pipe.bindDSets(ctx.cmd, this.getDescriptorSets(ctx.cmd)); + pipe.trace(ctx.cmd, size.x, size.y, size.z); } } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/AccelerationResource.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/AccelerationResource.java deleted file mode 100644 index 5700fcd..0000000 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/AccelerationResource.java +++ /dev/null @@ -1,4 +0,0 @@ -package me.cortex.vulkanite.client.rendering.srp.graph.resource; - -public class AccelerationResource extends Resource implements ExternalResource { -} diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalAccelerationResource.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalAccelerationResource.java new file mode 100644 index 0000000..6a3a0ac --- /dev/null +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalAccelerationResource.java @@ -0,0 +1,20 @@ +package me.cortex.vulkanite.client.rendering.srp.graph.resource; + +import me.cortex.vulkanite.client.rendering.srp.api.execution.ExternalResourceTracker; +import me.cortex.vulkanite.lib.memory.VAccelerationStructure; + +public class ExternalAccelerationResource extends Resource implements ExternalResource { + private VAccelerationStructure object; + + @Override + public ExternalAccelerationResource setConcrete(VAccelerationStructure concrete) { + this.object = concrete; + ExternalResourceTracker.update(this); + return this; + } + + @Override + public VAccelerationStructure getConcrete() { + return this.object; + } +} diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalBoundLayout.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalBoundLayout.java index 6caa476..69e7949 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalBoundLayout.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalBoundLayout.java @@ -1,9 +1,11 @@ package me.cortex.vulkanite.client.rendering.srp.graph.resource; +import me.cortex.vulkanite.client.rendering.srp.api.execution.ExternalResourceTracker; import me.cortex.vulkanite.client.rendering.srp.api.layout.Layout; +import me.cortex.vulkanite.lib.descriptors.VDescriptorSet; //This is special as its used to -public class ExternalBoundLayout extends Resource implements ExternalResource { +public class ExternalBoundLayout extends Resource implements ExternalResource { private final Layout layout; public ExternalBoundLayout(Layout layout) { @@ -13,4 +15,17 @@ public ExternalBoundLayout(Layout layout) { public Layout layout() { return this.layout; } + + private Long object = (long) -1; + @Override + public ExternalBoundLayout setConcrete(Long concrete) { + this.object = concrete; + ExternalResourceTracker.update(this); + return this; + } + + @Override + public Long getConcrete() { + return this.object; + } } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalBufferResource.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalBufferResource.java new file mode 100644 index 0000000..22a6d10 --- /dev/null +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalBufferResource.java @@ -0,0 +1,21 @@ +package me.cortex.vulkanite.client.rendering.srp.graph.resource; + +import me.cortex.vulkanite.client.rendering.srp.api.execution.ExternalResourceTracker; +import me.cortex.vulkanite.lib.memory.VAccelerationStructure; +import me.cortex.vulkanite.lib.memory.VBuffer; + +public class ExternalBufferResource extends BufferResource implements ExternalResource { + private VBuffer object; + + @Override + public ExternalBufferResource setConcrete(VBuffer concrete) { + this.object = concrete; + ExternalResourceTracker.update(this); + return this; + } + + @Override + public VBuffer getConcrete() { + return this.object; + } +} diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalImageResource.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalImageResource.java index 6362654..fe550be 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalImageResource.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalImageResource.java @@ -1,4 +1,20 @@ package me.cortex.vulkanite.client.rendering.srp.graph.resource; -public class ExternalImageResource extends ImageResource implements ExternalResource { +import me.cortex.vulkanite.client.rendering.srp.api.execution.ExternalResourceTracker; +import me.cortex.vulkanite.lib.memory.VImage; + +public class ExternalImageResource extends ImageResource implements ExternalResource { + private VImage object; + + @Override + public ExternalImageResource setConcrete(VImage concrete) { + this.object = concrete; + ExternalResourceTracker.update(this); + return this; + } + + @Override + public VImage getConcrete() { + return this.object; + } } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalResource.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalResource.java index d4eca90..34b7dd6 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalResource.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/ExternalResource.java @@ -1,4 +1,6 @@ package me.cortex.vulkanite.client.rendering.srp.graph.resource; -public interface ExternalResource > { +public interface ExternalResource , J> { + T setConcrete(J concrete); + J getConcrete(); } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/Resource.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/Resource.java index 90bad85..dfded26 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/Resource.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/graph/resource/Resource.java @@ -51,4 +51,11 @@ public Pass getLastWrite() { return this.writers.get(this.writers.size()-1); } + public T resetDependencies() { + this.writers.clear(); + this.readers.clear(); + this.dependencies.clear(); + return (T) this; + } + } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/lua/LuaContextHost.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/lua/LuaContextHost.java index 06cc2df..7daa90c 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/lua/LuaContextHost.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/lua/LuaContextHost.java @@ -1,22 +1,27 @@ package me.cortex.vulkanite.client.rendering.srp.lua; -import me.cortex.vulkanite.client.rendering.srp.graph.resource.AccelerationResource; -import me.cortex.vulkanite.client.rendering.srp.graph.resource.BufferResource; -import me.cortex.vulkanite.client.rendering.srp.graph.resource.ExternalImageResource; +import me.cortex.vulkanite.client.rendering.srp.api.execution.ExternalResourceTracker; +import me.cortex.vulkanite.client.rendering.srp.graph.RenderGraph; import org.luaj.vm2.*; import org.luaj.vm2.compiler.LuaC; -import org.luaj.vm2.luajc.JavaLoader; +import org.luaj.vm2.lib.Bit32Lib; +import org.luaj.vm2.lib.TableLib; +import org.luaj.vm2.lib.jse.JseMathLib; +import org.luaj.vm2.lib.jse.JseStringLib; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.util.Arrays; import java.util.function.Function; +import static me.cortex.vulkanite.client.rendering.srp.lua.LuaExternalObjects.*; import static org.lwjgl.vulkan.KHRRayTracingPipeline.*; public class LuaContextHost { private final LuaFunctions functions = new LuaFunctions(this); private final Function resourceLoader; - private final JavaLoader loader = new JavaLoader(); + private final LuaJavaLoader loader = new LuaJavaLoader(LuaContextHost.class.getClassLoader()); + private LuaFunction generationFunction; public LuaContextHost(Function resourceLoader) { this.resourceLoader = resourceLoader; } @@ -38,38 +43,74 @@ private LuaFunction compileBytecode(Prototype prototype, String classname, LuaVa return this.loader.load(prototype, classname, "script", globals); } - public LuaValue loadRunScript(String name) { - var func = compileBytecode(this.resourceLoader.apply(name), "me.cortex.vulkanite.client.srp.runtime.UserPipeline", createStandardLibrary()); - return func.call(); + private static int UNIQUEIFIER = 0; + public void loadScript(String name) { + this.generationFunction = compileBytecode(this.resourceLoader.apply(name), "me.cortex.vulkanite.client.srp.runtime.UserPipeline"+(UNIQUEIFIER++), createStandardLibrary()); + } + + public void run() { + //Need to reset the graph, else it pulls in things from previous invocations that are not valid + // TODO: to fix this properly, need to make LuaExternalObjects an actual object not public static final + LuaExternalObjects.resetExternalObjectGraph(); + ExternalResourceTracker.resetAllCallbacks(); + + this.generationFunction.call(); + } + + private void addLuaStdLib(LuaTable table) { + new Bit32Lib().call(LuaValue.valueOf("bit32"), table); + new JseMathLib().call(LuaValue.valueOf("math"), table); + new JseStringLib().call(LuaValue.valueOf("string"), table); + new TableLib().call(LuaValue.valueOf("table"), table); } private LuaValue createStandardLibrary() { var env = new LuaTable(); + addLuaStdLib(env); env.set("ctx", createContextTable()); env.set("SHADER_RAY_GEN", VK_SHADER_STAGE_RAYGEN_BIT_KHR); env.set("SHADER_RAY_MISS", VK_SHADER_STAGE_MISS_BIT_KHR); env.set("SHADER_RAY_CHIT", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR); env.set("SHADER_RAY_AHIT", VK_SHADER_STAGE_ANY_HIT_BIT_KHR); env.set("SHADER_RAY_INTER", VK_SHADER_STAGE_INTERSECTION_BIT_KHR); + env.set("Buffer", new LuaJFunction(this.functions::Buffer)); + env.set("Image", new LuaJFunction(this.functions::Image)); env.set("ShaderModule", new LuaJFunction(this.functions::ShaderModule)); env.set("RaytracePipeline", new LuaJFunction(this.functions::RaytracePipeline)); env.set("RaytracePass", new LuaJFunction(this.functions::RaytracePass)); + env.set("ComputePipeline", new LuaJFunction(this.functions::ComputePipeline)); + env.set("ComputePass", new LuaJFunction(this.functions::ComputePass)); env.set("setOutput", new LuaJFunction(this.functions::setOutput)); + env.set("loadResource", new LuaJFunction(this::loadResource)); return env; } + private LuaValue loadResource(LuaValue arg) { + var resource = resourceLoader.apply(arg.checkjstring()); + return resource==null?LuaValue.NIL:LuaString.valueUsing(resource); + } + private LuaValue createContextTable() { var ctx = new LuaTable(); - ctx.set("commonUniformBuffer", new LuaJObj<>(new BufferResource())); - ctx.set("accelerationStructure", new LuaJObj<>(new AccelerationResource())); - ctx.set("blockAtlas", new LuaJObj<>(new ExternalImageResource())); - ctx.set("blockAtlasNormal", new LuaJObj<>(new ExternalImageResource())); - ctx.set("blockAtlasSpecular", new LuaJObj<>(new ExternalImageResource())); - ctx.set("irisOutputTextures", LuaValue.listOf(new LuaValue[]{new LuaJObj<>(new ExternalImageResource()),new LuaJObj<>(new ExternalImageResource())})); + ctx.set("commonUniformBuffer", new LuaJObj<>(COMMON_UNIFORM_BUFFER)); + ctx.set("accelerationStructure", new LuaJObj<>(WORLD_ACCELERATION_STRUCTURE)); + ctx.set("blockAtlas", new LuaJObj<>(BLOCK_ATLAS)); + ctx.set("blockAtlasNormal", new LuaJObj<>(BLOCK_ATLAS_NORMAL)); + ctx.set("blockAtlasSpecular", new LuaJObj<>(BLOCK_ATLAS_SPECULAR)); + ctx.set("irisOutputTextures", LuaValue.listOf(Arrays.stream(IRIS_IMAGES).map(LuaJObj::new).toArray(LuaValue[]::new))); + ctx.set("terrainGeometrySet", new LuaJObj<>(TERRAIN_GEOMETRY_LAYOUT)); return ctx; } public byte[] getResource(String path) { return this.resourceLoader.apply(path); } + + public RenderGraph getGraph() { + return this.functions.graph; + } + + public void destory() { + this.functions.freeObjects(); + } } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/lua/LuaExternalObjects.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/lua/LuaExternalObjects.java new file mode 100644 index 0000000..f6c334a --- /dev/null +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/lua/LuaExternalObjects.java @@ -0,0 +1,33 @@ +package me.cortex.vulkanite.client.rendering.srp.lua; + +import me.cortex.vulkanite.client.rendering.srp.api.layout.Layout; +import me.cortex.vulkanite.client.rendering.srp.api.layout.LayoutBinding; +import me.cortex.vulkanite.client.rendering.srp.graph.resource.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.IntStream; + +import static org.lwjgl.vulkan.VK10.VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + +public class LuaExternalObjects { + private static final List> EXTERNAL_RESOURCES = new ArrayList<>(); + + public static final ExternalBufferResource COMMON_UNIFORM_BUFFER = (ExternalBufferResource) register(new ExternalBufferResource(), "Common uniform buffer"); + public static final ExternalAccelerationResource WORLD_ACCELERATION_STRUCTURE = register(new ExternalAccelerationResource(), "World acceleration structure"); + public static final ExternalImageResource BLOCK_ATLAS = (ExternalImageResource) register(new ExternalImageResource(), "Block atlas"); + public static final ExternalImageResource BLOCK_ATLAS_NORMAL = (ExternalImageResource) register(new ExternalImageResource(), "Block atlas normals"); + public static final ExternalImageResource BLOCK_ATLAS_SPECULAR = (ExternalImageResource) register(new ExternalImageResource(), "Block atlas specular"); + public static final ExternalImageResource[] IRIS_IMAGES = IntStream.range(0, 16).mapToObj(i->(ExternalImageResource)register(new ExternalImageResource(),"Iris colortex"+i)).toArray(ExternalImageResource[]::new); + public static final ExternalBoundLayout TERRAIN_GEOMETRY_LAYOUT = register(new ExternalBoundLayout(new Layout(new LayoutBinding(0, 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, -1))), "External terrain layout"); + + private static > T register(T resource, String name) { + EXTERNAL_RESOURCES.add(resource); + resource.name(name); + return resource; + } + + public static void resetExternalObjectGraph() { + EXTERNAL_RESOURCES.forEach(Resource::resetDependencies); + } +} diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/lua/LuaFunctions.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/lua/LuaFunctions.java index da3342d..3cfe720 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/lua/LuaFunctions.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/lua/LuaFunctions.java @@ -1,22 +1,32 @@ package me.cortex.vulkanite.client.rendering.srp.lua; import me.cortex.vulkanite.client.Vulkanite; +import me.cortex.vulkanite.client.rendering.srp.api.execution.ExecutionConstants; +import me.cortex.vulkanite.client.rendering.srp.api.execution.ExecutionContext; import me.cortex.vulkanite.client.rendering.srp.api.layout.Layout; import me.cortex.vulkanite.client.rendering.srp.api.layout.LayoutBinding; +import me.cortex.vulkanite.client.rendering.srp.api.pipeline.ComputePipeline; import me.cortex.vulkanite.client.rendering.srp.api.pipeline.TracePipeline; import me.cortex.vulkanite.client.rendering.srp.graph.RenderGraph; +import me.cortex.vulkanite.client.rendering.srp.graph.phase.pipeline.ComputePass; import me.cortex.vulkanite.client.rendering.srp.graph.phase.pipeline.TracePass; +import me.cortex.vulkanite.client.rendering.srp.graph.resource.BufferResource; import me.cortex.vulkanite.client.rendering.srp.graph.resource.ExternalBoundLayout; +import me.cortex.vulkanite.client.rendering.srp.graph.resource.ImageResource; import me.cortex.vulkanite.client.rendering.srp.graph.resource.Resource; import me.cortex.vulkanite.lib.base.TrackedResourceObject; import me.cortex.vulkanite.lib.base.VContext; +import me.cortex.vulkanite.lib.pipeline.ComputePipelineBuilder; import me.cortex.vulkanite.lib.pipeline.RaytracePipelineBuilder; import me.cortex.vulkanite.lib.shader.ShaderModule; import me.cortex.vulkanite.lib.shader.VShader; import me.cortex.vulkanite.lib.shader.reflection.ShaderReflection; +import org.joml.Vector3i; import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaValue; +import org.lwjgl.system.MemoryUtil; +import java.nio.ByteBuffer; import java.util.*; //TODO: create a set of vk resources that need to get freed @@ -25,20 +35,41 @@ public class LuaFunctions { private final VContext vctx = Vulkanite.INSTANCE.getCtx(); private final LuaContextHost ctx; + public RenderGraph graph; + public LuaFunctions(LuaContextHost ctx) { this.ctx = ctx; } + public LuaValue Buffer(LuaValue arg) { + return new LuaJObj<>(new BufferResource()); + } + + public LuaValue Image(LuaValue arg) { + return new LuaJObj<>(new ImageResource()); + } + public LuaValue ShaderModule(LuaValue arg) { int stages = arg.get("type").checkint(); + VShader shader = null; if (arg.get("file") != LuaValue.NIL) { - var source = ctx.getResource(arg.get("file").checkjstring()); - var shader = VShader.compileLoad(vctx, new String(source), stages); - this.allocatedObjects.add(shader); - return new LuaJObj<>(shader); + shader = VShader.compileLoad(vctx, new String(ctx.getResource(arg.get("file").checkjstring())), stages); + } else if (arg.get("src") != LuaValue.NIL) { + shader = VShader.compileLoad(vctx, arg.get("src").checkjstring(), stages); + } else if (arg.get("spirv") != LuaValue.NIL) { + var strObj = arg.get("spirv").checkstring(); + //TODO: fixme, verify that this cant cause an out of bounds memory write + var spirvBuffer = MemoryUtil.memAlloc(strObj.m_length); + spirvBuffer.put(0, strObj.m_bytes, strObj.m_offset, strObj.m_length); + spirvBuffer.rewind(); + shader = VShader.compileLoad(vctx, spirvBuffer, stages); + MemoryUtil.memFree(spirvBuffer); } else { throw new IllegalArgumentException("Unknown loading method for args: " + arg); } + + this.allocatedObjects.add(shader); + return new LuaJObj<>(shader); } public LuaValue RaytracePipeline(LuaValue arg) { @@ -76,21 +107,53 @@ public LuaValue RaytracePipeline(LuaValue arg) { return new LuaJObj<>(new TracePipeline(pipeline, pipeline.reflection.getSets().stream().map(LuaFunctions::buildLayout).toList())); } + public LuaValue ComputePipeline(LuaValue arg) { + var builder = new ComputePipelineBuilder(); + + var shader = ((LuaJObj)arg.get("shader")).get().named(); + builder.set(shader); + + var pipeline = builder.build(vctx); + this.allocatedObjects.add(pipeline); + return new LuaJObj<>(new ComputePipeline(pipeline, shader.shader().getReflection().getSets().stream().map(LuaFunctions::buildLayout).toList())); + } + private static Layout buildLayout(ShaderReflection.Set set) { List bindingList = new ArrayList<>(); for (var binding : set.bindings()) { - bindingList.add(new LayoutBinding(binding.name(), binding.binding(), 3, binding.descriptorType(), binding.runtimeSized()?-1:binding.arraySize())); + bindingList.add(new LayoutBinding(binding.name(), binding.binding(), binding.accessMsk(), binding.descriptorType(), binding.runtimeSized()?-1:binding.arraySize())); + } + return new Layout(bindingList.toArray(LayoutBinding[]::new)); + } + + private static List>> generateBindingList(LuaTable bindingArrayList) { + List>> bindings = new ArrayList<>(); + for (int index2 = 1; index2 < bindingArrayList.keyCount() + 1; index2++) { + var bindingObject = bindingArrayList.get(index2); + if (bindingObject instanceof LuaTable bindingList) { + List> bindingArray = new ArrayList<>(); + bindings.add(bindingArray); + for (int index3 = 1; index3 < bindingList.keyCount() + 1; index3++) { + var binding = ((LuaJObj>)bindingList.get(index3)).get(); + bindingArray.add(binding); + } + } else if (bindingObject instanceof LuaJObj bindingWrapper) { + var binding = ((LuaJObj>)bindingWrapper).get(); + bindings.add(List.of(binding)); + } else { + throw new IllegalArgumentException("Unknown binding object " + bindingObject + " for set: " + index2); + } } - return new Layout(false, bindingList.toArray(LayoutBinding[]::new)); + return bindings; } public LuaValue RaytracePass(LuaValue arg) { - var pass = new TracePass(((LuaJObj)arg.get("pipeline")).get()); + var pass = new TracePass(((LuaJObj)arg.get("pipeline")).get(), ()-> new Vector3i(ExecutionConstants.INSTANCE.getScreenSize(), 1)); var bindingTable = arg.get("bindings").checktable(); for (int index = 1; index < bindingTable.keyCount()+1; index++) { - var setBindingObject = bindingTable.get(index); - if (setBindingObject instanceof LuaJObj lobj) { + var bindingSetObject = bindingTable.get(index); + if (bindingSetObject instanceof LuaJObj lobj) { var obj = lobj.get(); if (obj instanceof ExternalBoundLayout ebl) { pass.bindLayout(index - 1, ebl); @@ -98,24 +161,28 @@ public LuaValue RaytracePass(LuaValue arg) { throw new IllegalArgumentException("Trying to bind unknown type " + obj + " to set: " + index); } } else { - List>> bindings = new ArrayList<>(); - var setBindingsList = setBindingObject.checktable(); - for (int index2 = 1; index2 < setBindingsList.keyCount() + 1; index2++) { - var bindingObject = setBindingsList.get(index2); - if (bindingObject instanceof LuaTable bindingList) { - List> bindingArray = new ArrayList<>(); - bindings.add(bindingArray); - for (int index3 = 1; index3 < bindingList.keyCount() + 1; index3++) { - var binding = ((LuaJObj>)bindingList.get(index3)).get(); - bindingArray.add(binding); - } - } else if (bindingObject instanceof LuaJObj bindingWrapper) { - var binding = ((LuaJObj>)bindingWrapper).get(); - bindings.add(List.of(binding)); - } else { - throw new IllegalArgumentException("Unknown binding object " + bindingObject + " for set: " + index2); - } + var bindings = generateBindingList(bindingSetObject.checktable()); + pass.bindLayout(index - 1, bindings.toArray(List[]::new)); + } + } + return new LuaJObj<>(pass); + } + + public LuaValue ComputePass(LuaValue arg) { + var pass = new ComputePass(((LuaJObj)arg.get("pipeline")).get(), ()-> new Vector3i(ExecutionConstants.INSTANCE.getScreenSize(), 1)); + + var bindingTable = arg.get("bindings").checktable(); + for (int index = 1; index < bindingTable.keyCount()+1; index++) { + var bindingSetObject = bindingTable.get(index); + if (bindingSetObject instanceof LuaJObj lobj) { + var obj = lobj.get(); + if (obj instanceof ExternalBoundLayout ebl) { + pass.bindLayout(index - 1, ebl); + } else { + throw new IllegalArgumentException("Trying to bind unknown type " + obj + " to set: " + index); } + } else { + var bindings = generateBindingList(bindingSetObject.checktable()); pass.bindLayout(index - 1, bindings.toArray(List[]::new)); } } @@ -124,7 +191,7 @@ public LuaValue RaytracePass(LuaValue arg) { public LuaValue setOutput(LuaValue arg) { var output = ((LuaJObj>)arg.get(1)).get(); - var graph = new RenderGraph(output); + this.graph = new RenderGraph(output); return LuaValue.NIL; } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/lua/LuaJavaLoader.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/lua/LuaJavaLoader.java new file mode 100644 index 0000000..626bb83 --- /dev/null +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/lua/LuaJavaLoader.java @@ -0,0 +1,53 @@ +package me.cortex.vulkanite.client.rendering.srp.lua; + +import org.luaj.vm2.LuaFunction; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Prototype; +import org.luaj.vm2.luajc.JavaGen; + +import java.util.HashMap; +import java.util.Map; + +public class LuaJavaLoader extends ClassLoader { + + private final Map unloaded = new HashMap<>(); + + public LuaJavaLoader(ClassLoader parent) { + super(parent); + } + + public LuaFunction load(Prototype p, String classname, String filename, LuaValue env) { + JavaGen jg = new JavaGen(p, classname, filename, false); + return load(jg, env); + } + + public LuaFunction load(JavaGen jg, LuaValue env) { + include(jg); + return load(jg.classname, env); + } + + public LuaFunction load(String classname, LuaValue env) { + try { + Class c = loadClass(classname); + LuaFunction v = (LuaFunction) c.newInstance(); + v.initupvalue1(env); + return v; + } catch (Exception e) { + throw new IllegalStateException("bad class gen: " + e); + } + } + + public void include(JavaGen jg) { + unloaded.put(jg.classname, jg.bytecode); + for (int i = 0, n = jg.inners != null? jg.inners.length: 0; i < n; i++) + include(jg.inners[i]); + } + + @Override + public Class findClass(String classname) throws ClassNotFoundException { + byte[] bytes = unloaded.get(classname); + if (bytes != null) + return defineClass(classname, bytes, 0, bytes.length); + return super.findClass(classname); + } +} diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/test2.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/test2.java index 8d23619..8bd6c08 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/test2.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/test2.java @@ -38,6 +38,6 @@ private static Layout buildLayout(ShaderReflection.Set set) { for (var binding : set.bindings()) { bindingList.add(new LayoutBinding(binding.name(), binding.binding(), 3, binding.descriptorType(), binding.runtimeSized()?-1:binding.arraySize())); } - return new Layout(false, bindingList.toArray(LayoutBinding[]::new)); + return new Layout(bindingList.toArray(LayoutBinding[]::new)); } } diff --git a/src/main/java/me/cortex/vulkanite/client/rendering/srp/test3.java b/src/main/java/me/cortex/vulkanite/client/rendering/srp/test3.java index 713823e..288de96 100644 --- a/src/main/java/me/cortex/vulkanite/client/rendering/srp/test3.java +++ b/src/main/java/me/cortex/vulkanite/client/rendering/srp/test3.java @@ -10,9 +10,8 @@ public class test3 { public static byte[] load(String path) { try { - return Files.readAllBytes(new File(path).toPath()); - } catch ( - IOException e) { + return Files.readAllBytes(new File("run/shaderpacks/testpack/shaders/"+path).toPath()); + } catch (IOException e) { throw new RuntimeException(e); } } @@ -21,7 +20,8 @@ public static void main(String[] args) throws InterruptedException { Vulkanite.INSTANCE.getCtx(); var host = new LuaContextHost(test3::load); - host.loadRunScript("test.lua"); + host.loadScript("srp.lua"); + host.run(); System.err.println("Done"); Thread.sleep(1000); Vulkanite.INSTANCE.destroy(); 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..cc017fa 100644 --- a/src/main/java/me/cortex/vulkanite/lib/base/TrackedResourceObject.java +++ b/src/main/java/me/cortex/vulkanite/lib/base/TrackedResourceObject.java @@ -16,6 +16,12 @@ protected void free0() { public abstract void free(); + public void assertNotFreed() { + if (isFreed()) { + throw new IllegalStateException("Object " + this + " should not be free, but is"); + } + } + public boolean isFreed() { return ref.freedRef[0]; } 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..92db864 100644 --- a/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSet.java +++ b/src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSet.java @@ -4,7 +4,7 @@ public class VDescriptorSet extends TrackedResourceObject { private final VTypedDescriptorPool pool; - public final long poolHandle; + final long poolHandle; public final long set; VDescriptorSet(VTypedDescriptorPool pool, long poolHandle, long set) { 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..fc4343e 100644 --- a/src/main/java/me/cortex/vulkanite/lib/pipeline/VComputePipeline.java +++ b/src/main/java/me/cortex/vulkanite/lib/pipeline/VComputePipeline.java @@ -2,7 +2,9 @@ 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.cmd.VCmdBuff; + +import static org.lwjgl.vulkan.VK10.*; public class VComputePipeline extends TrackedResourceObject { private final VContext context; @@ -25,6 +27,20 @@ public long pipeline() { @Override public void free() { + free0(); + vkDestroyPipeline(context.device, pipeline, null); + vkDestroyPipelineLayout(context.device, layout, null); + } + + public void bind(VCmdBuff cmd) { + vkCmdBindPipeline(cmd.buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline); + } + + public void dispatch(VCmdBuff cmd, int x, int y, int z) { + vkCmdDispatch(cmd.buffer, x, y, z); + } + public void bindDSets(VCmdBuff cmd, long... descs) { + vkCmdBindDescriptorSets(cmd.buffer, VK_PIPELINE_BIND_POINT_COMPUTE, layout, 0, descs, 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..1b80eab 100644 --- a/src/main/java/me/cortex/vulkanite/lib/pipeline/VRaytracePipeline.java +++ b/src/main/java/me/cortex/vulkanite/lib/pipeline/VRaytracePipeline.java @@ -47,6 +47,7 @@ public class VRaytracePipeline extends TrackedResourceObject { } public void bind(VCmdBuff cmd) { + assertNotFreed(); vkCmdBindPipeline(cmd.buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline); } @@ -54,13 +55,14 @@ 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) { + public void bindDSets(VCmdBuff cmd, long... descs) { vkCmdBindDescriptorSets(cmd.buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, layout, 0, descs, null); } public void free() { free0(); vkDestroyPipeline(context.device, pipeline, null); + vkDestroyPipelineLayout(context.device, layout, null); shader_binding_table.free(); gen.free(); miss.free(); 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..64305c9 100644 --- a/src/main/java/me/cortex/vulkanite/lib/shader/VShader.java +++ b/src/main/java/me/cortex/vulkanite/lib/shader/VShader.java @@ -39,21 +39,23 @@ public ShaderModule named(String name) { return new ShaderModule(this, name); } - public static VShader compileLoad(VContext ctx, String source, int stage) { + public static VShader compileLoad(VContext ctx, ByteBuffer spirv, int stage) { try (var stack = stackPush()) { - ByteBuffer code = ShaderCompiler.compileShader("shader", source, stage); - - ShaderReflection reflection = new ShaderReflection(code); + ShaderReflection reflection = new ShaderReflection(spirv); VkShaderModuleCreateInfo createInfo = VkShaderModuleCreateInfo.calloc(stack) .sType$Default() - .pCode(code); + .pCode(spirv); LongBuffer pShaderModule = stack.mallocLong(1); _CHECK_(vkCreateShaderModule(ctx.device, createInfo, null, pShaderModule)); return new VShader(ctx, pShaderModule.get(0), stage, reflection); } } + public static VShader compileLoad(VContext ctx, String source, int stage) { + return compileLoad(ctx,ShaderCompiler.compileShader("shader", source, stage), stage); + } + @Override public void free() { free0(); 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 0d33c97..bb75c93 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 @@ -12,11 +12,12 @@ import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.util.spvc.Spv.*; import static org.lwjgl.util.spvc.Spvc.*; +import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; import static org.lwjgl.vulkan.VK10.*; import static org.lwjgl.vulkan.VK12.*; public class ShaderReflection { - public record Binding(String name, int binding, int descriptorType, int arraySize, boolean runtimeSized) {} + public record Binding(String name, int binding, int descriptorType, int arraySize, boolean runtimeSized, int accessMsk) {} public record Set(ArrayList bindings) { public Set(ArrayList bindings) { // Sort by binding @@ -95,7 +96,7 @@ public ShaderReflection(ByteBuffer spirv) { long context = ptr.get(0); //Parse the spir-v - _CHECK_(spvc_context_parse_spirv(context, spirv.asIntBuffer(), spirv.remaining()>>2, ptr)); + _CHECK_(spvc_context_parse_spirv(context, spirv.asIntBuffer(), spirv.remaining() >> 2, ptr)); long ir = ptr.get(0); // Hand it off to a compiler instance and give it ownership of the IR. @@ -111,26 +112,54 @@ public ShaderReflection(ByteBuffer spirv) { int vkDescType = type.toVkDescriptorType(); _CHECK_(spvc_resources_get_resource_list_for_type(resources, type.id, ptr, ptr2)); + /* + for (int i = 0; i < 250; i++) { + //System.err.println(i); + System.err.println(spvc_compiler_get_name(compiler, i)); + System.err.println(spvc_compiler_get_member_decoration(compiler, i, 0, SpvDecorationNonWritable)); + System.err.println(spvc_compiler_get_member_decoration(compiler, i, 0, SpvDecorationNonReadable)); + }*/ var reflectedResources = SpvcReflectedResource.create(ptr.get(0), (int) ptr2.get(0)); for (var reflect : reflectedResources) { if (vkDescType != -1) { int binding = spvc_compiler_get_decoration(compiler, reflect.id(), SpvDecorationBinding); int set = spvc_compiler_get_decoration(compiler, reflect.id(), SpvDecorationDescriptorSet); - var spvcType = spvc_compiler_get_type_handle(compiler, reflect.type_id()); - //System.err.println("\n"); - //System.err.println(spvc_type_get_image_access_qualifier(spvcType)); - //System.err.println(spvc_compiler_get_name(compiler, reflect.id())); - //System.err.println(reflect.nameString()); - //System.err.println(spvc_compiler_has_decoration(compiler, reflect.id(), SpvDecorationRestrict)); - //System.err.println(spvc_compiler_has_decoration(compiler, reflect.id(), SpvDecorationNonReadable)); - //System.err.println(spvc_compiler_has_decoration(compiler, reflect.id(), SpvDecorationNonWritable)); - int arrayNDims = spvc_type_get_num_array_dimensions(spvcType); - int arraySize = 0; + var layoutType = spvc_compiler_get_type_handle(compiler, reflect.type_id()); String name = spvc_compiler_get_name(compiler, reflect.id()); + int baseLayoutTypeId = spvc_type_get_base_type_id(layoutType); + + int accessMsk = 0; + accessMsk |= spvc_compiler_has_member_decoration(compiler, baseLayoutTypeId, 0, SpvDecorationNonWritable)?0:2; + accessMsk |= spvc_compiler_has_member_decoration(compiler, baseLayoutTypeId, 0, SpvDecorationNonReadable)?0:1; + + if (accessMsk == 0) { + accessMsk = switch (vkDescType) { + case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR -> 1; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER -> 1; + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER -> 1; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER -> 3; + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE -> 3; + default -> throw new IllegalStateException("Unknown description type: " + vkDescType); + }; + } + + //System.err.println(spvc_compiler_get_name(compiler, baseLayoutTypeId) + ": " + name); + //System.err.println(spvc_compiler_get_member_decoration(compiler, baseLayoutTypeId, 0, SpvDecorationNonWritable)); + /* + int memberCount = spvc_type_get_num_member_types(layoutType); + for (int i = 0; i < memberCount; i++) { + var memberType = spvc_compiler_get_type_handle(compiler, spvc_type_get_member_type(layoutType, i)); + System.err.println(spvc_compiler_get_member_name(compiler, baseLayoutTypeId, i)); + System.err.println(spvc_type_get_num_array_dimensions(memberType)); + System.err.println(spvc_type_get_array_dimension(memberType, 0)); + }*/ + + int arrayNDims = spvc_type_get_num_array_dimensions(layoutType); + int arraySize = 0; if (arrayNDims > 0) { arraySize = 1; for (int i = 0; i < arrayNDims; i++) { - arraySize *= spvc_type_get_array_dimension(spvcType, i); + arraySize *= spvc_type_get_array_dimension(layoutType, i); } } boolean isRuntimeSized = false; @@ -138,7 +167,9 @@ public ShaderReflection(ByteBuffer spirv) { isRuntimeSized = true; arraySize = 1; } - var descriptor = new Binding(name, binding, vkDescType, arraySize, isRuntimeSized); + //NOTE:Only some types can actually be written to! stuff like uniforms etc cant be written to thus, dont need to + // make them writeable + var descriptor = new Binding(name, binding, vkDescType, arraySize, isRuntimeSized, accessMsk); while (sets.size() <= set) { sets.add(new Set(new ArrayList<>())); } @@ -192,6 +223,9 @@ public static ShaderReflection mergeStages(ShaderReflection ...stages) { if (!b.name.isEmpty() && !binding.name.isEmpty() && b.name.compareTo(binding.name) != 0) { System.err.println("Warning: Conflicting names for binding " + binding.binding + " : " + b.name + " and " + binding.name); } + if (b.accessMsk != binding.accessMsk) { + System.err.println("Warning: Conflicting access mask " + b.accessMsk + " and " + binding.accessMsk); + } alreadyExists = true; } } 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..6895c7a 100644 --- a/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java +++ b/src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java @@ -3,7 +3,9 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectMap.Entry; import me.cortex.vulkanite.client.Vulkanite; +import me.cortex.vulkanite.client.rendering.VkPipeline2; import me.cortex.vulkanite.client.rendering.VulkanPipeline; +import me.cortex.vulkanite.client.rendering.srp.lua.LuaContextHost; import me.cortex.vulkanite.compat.*; import me.cortex.vulkanite.lib.base.VContext; import me.cortex.vulkanite.lib.memory.VGImage; @@ -29,6 +31,9 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Comparator; import java.util.List; @@ -43,7 +48,7 @@ public class MixinNewWorldRenderingPipeline { @Shadow @Final private float sunPathRotation; @Unique private RaytracingShaderSet[] rtShaderPasses = null; @Unique private VContext ctx; - @Unique private VulkanPipeline pipeline; + @Unique private VkPipeline2 pipeline; @Unique private VGImage[] getCustomTextures() { @@ -64,6 +69,16 @@ private VGImage[] getCustomTextures() { @Inject(method = "", at = @At("TAIL")) private void injectRTShader(ProgramSet set, CallbackInfo ci) { ctx = Vulkanite.INSTANCE.getCtx(); + pipeline = new VkPipeline2(ctx, new LuaContextHost(path -> { + try { + return Files.readAllBytes(new File("shaderpacks/testpack/shaders/" + path).toPath()); + } catch ( + IOException e) { + throw new RuntimeException(e); + } + }), Vulkanite.INSTANCE.getAccelerationManager()); + + /* var passes = ((IGetRaytracingSource)set).getRaytracingSource(); if (passes != null) { rtShaderPasses = new RaytracingShaderSet[passes.length]; @@ -73,10 +88,12 @@ private void injectRTShader(ProgramSet set, CallbackInfo ci) { } // Still create this, later down the line we might add Vulkan compute pipelines or mesh shading, etc. pipeline = new VulkanPipeline(ctx, Vulkanite.INSTANCE.getAccelerationManager(), rtShaderPasses, set.getPackDirectives().getBufferObjects().keySet().toArray(new int[0]), getCustomTextures()); + */ } @Inject(method = "renderShadows", at = @At("TAIL")) private void renderShadows(LevelRendererAccessor par1, Camera par2, CallbackInfo ci) { + /* ShaderStorageBuffer[] buffers = new ShaderStorageBuffer[0]; if(shaderStorageBufferHolder != null) { @@ -87,10 +104,13 @@ private void renderShadows(LevelRendererAccessor par1, Camera par2, CallbackInfo for (int i = 0; i < renderTargets.getRenderTargetCount(); i++) { outImgs.add(((IRenderTargetVkGetter)renderTargets.getOrCreate(i)).getMain()); } + */ - MixinCelestialUniforms celestialUniforms = (MixinCelestialUniforms)(Object) new CelestialUniforms(this.sunPathRotation); + //MixinCelestialUniforms celestialUniforms = (MixinCelestialUniforms)(Object) new CelestialUniforms(this.sunPathRotation); - pipeline.renderPostShadows(outImgs, par2, buffers, celestialUniforms); + //pipeline.renderPostShadows(outImgs, par2, buffers, celestialUniforms); + pipeline.setup(par2, (MixinCelestialUniforms)(Object) new CelestialUniforms(this.sunPathRotation)); + pipeline.execute(); } @Inject(method = "destroyShaders", at = @At("TAIL")) @@ -101,8 +121,9 @@ private void destory(CallbackInfo ci) { pass.delete(); } } - pipeline.destory(); rtShaderPasses = null; + + pipeline.destory(); pipeline = null; } } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 4cf63f7..f764737 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", + "iris": "=1.6.10", "sodium": "=0.5.3" } }