From 246946722045d24965d5c712272ed1927a848e57 Mon Sep 17 00:00:00 2001 From: thr3343 <125277899+thr3343@users.noreply.github.com> Date: Sun, 12 Nov 2023 21:28:01 +0000 Subject: [PATCH] Enable VK12 VMA Features + Misc. Shader/Optimisation tweaks --- .../net/vulkanmod/render/chunk/ChunkArea.java | 4 +- .../vulkanmod/render/chunk/DrawBuffers.java | 98 +++++++----------- .../vulkanmod/render/chunk/WorldRenderer.java | 4 +- .../render/chunk/util/StaticQueue.java | 99 +++++++++++++++++++ .../java/net/vulkanmod/vulkan/Drawer.java | 3 +- .../java/net/vulkanmod/vulkan/Vulkan.java | 5 +- .../vulkan/memory/AutoIndexBuffer.java | 4 +- .../vulkanmod/shaders/include/light.glsl | 18 ++-- 8 files changed, 153 insertions(+), 82 deletions(-) create mode 100644 src/main/java/net/vulkanmod/render/chunk/util/StaticQueue.java diff --git a/src/main/java/net/vulkanmod/render/chunk/ChunkArea.java b/src/main/java/net/vulkanmod/render/chunk/ChunkArea.java index 39a35fbdfa..228dfab7b0 100644 --- a/src/main/java/net/vulkanmod/render/chunk/ChunkArea.java +++ b/src/main/java/net/vulkanmod/render/chunk/ChunkArea.java @@ -2,6 +2,7 @@ import net.minecraft.core.BlockPos; import net.vulkanmod.render.chunk.util.ResettableQueue; +import net.vulkanmod.render.chunk.util.StaticQueue; import org.joml.FrustumIntersection; import org.joml.Vector3i; @@ -15,7 +16,8 @@ public class ChunkArea { DrawBuffers drawBuffers; - final ResettableQueue sectionQueue = new ResettableQueue<>(); + //Help JIT optimisations by hardcoding the queue size to the max possible ChunkArea limit + final StaticQueue sectionQueue = new StaticQueue<>(512); public ChunkArea(int i, Vector3i origin) { this.index = i; diff --git a/src/main/java/net/vulkanmod/render/chunk/DrawBuffers.java b/src/main/java/net/vulkanmod/render/chunk/DrawBuffers.java index 580697713a..55eee3196e 100644 --- a/src/main/java/net/vulkanmod/render/chunk/DrawBuffers.java +++ b/src/main/java/net/vulkanmod/render/chunk/DrawBuffers.java @@ -3,6 +3,7 @@ import net.minecraft.client.renderer.RenderType; import net.vulkanmod.render.chunk.build.UploadBuffer; import net.vulkanmod.render.chunk.util.ResettableQueue; +import net.vulkanmod.render.chunk.util.StaticQueue; import net.vulkanmod.render.vertex.TerrainRenderType; import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.memory.IndirectBuffer; @@ -60,7 +61,7 @@ public DrawParameters upload(UploadBuffer buffer, DrawParameters drawParameters) drawParameters.firstIndex = firstIndex; drawParameters.vertexOffset = vertexOffset; - Renderer.getDrawer().getQuadsIndexBuffer().checkCapacity(buffer.indexCount * 2 / 3); + buffer.release(); @@ -72,7 +73,7 @@ public int buildDrawBatchesIndirect(IndirectBuffer indirectBuffer, ChunkArea chu int drawCount = 0; - ResettableQueue queue = chunkArea.sectionQueue; + StaticQueue queue = chunkArea.sectionQueue; MemoryStack stack = MemoryStack.stackPush(); ByteBuffer byteBuffer = stack.calloc(20 * queue.size()); @@ -86,8 +87,9 @@ public int buildDrawBatchesIndirect(IndirectBuffer indirectBuffer, ChunkArea chu Pipeline pipeline = TerrainShaderManager.getTerrainIndirectShader(renderType); + VkCommandBuffer commandBuffer = Renderer.getCommandBuffer(); if(isTranslucent) { - vkCmdBindIndexBuffer(Renderer.getCommandBuffer(), this.indexBuffer.getId(), 0, VK_INDEX_TYPE_UINT16); + vkCmdBindIndexBuffer(commandBuffer, this.indexBuffer.getId(), 0, VK_INDEX_TYPE_UINT16); } var iterator = queue.iterator(isTranslucent); @@ -110,10 +112,6 @@ public int buildDrawBatchesIndirect(IndirectBuffer indirectBuffer, ChunkArea chu // } - if(drawParameters.indexCount == 0) { - continue; - } - //TODO if(!drawParameters.ready && drawParameters.vertexBufferSegment.getOffset() != -1) { if(!drawParameters.vertexBufferSegment.isReady()) @@ -152,11 +150,11 @@ public int buildDrawBatchesIndirect(IndirectBuffer indirectBuffer, ChunkArea chu LongBuffer pVertexBuffer = stack.longs(vertexBuffer.getId()); LongBuffer pOffset = stack.longs(0); - vkCmdBindVertexBuffers(Renderer.getCommandBuffer(), 0, pVertexBuffer, pOffset); + vkCmdBindVertexBuffers(commandBuffer, 0, pVertexBuffer, pOffset); // pipeline.bindDescriptorSets(Drawer.getCommandBuffer(), WorldRenderer.getInstance().getUniformBuffers(), Drawer.getCurrentFrame()); - pipeline.bindDescriptorSets(Renderer.getCommandBuffer(), Renderer.getCurrentFrame()); - vkCmdDrawIndexedIndirect(Renderer.getCommandBuffer(), indirectBuffer.getId(), indirectBuffer.getOffset(), drawCount, stride); + pipeline.bindDescriptorSets(commandBuffer, Renderer.getCurrentFrame()); + vkCmdDrawIndexedIndirect(commandBuffer, indirectBuffer.getId(), indirectBuffer.getOffset(), drawCount, stride); // fakeIndirectCmd(Drawer.getCommandBuffer(), indirectBuffer, drawCount, uboBuffer); @@ -202,82 +200,54 @@ private static void fakeIndirectCmd(VkCommandBuffer commandBuffer, IndirectBuffe } } - public void buildDrawBatchesDirect(ResettableQueue queue, Pipeline pipeline, RenderType renderType, double camX, double camY, double camZ) { + public void buildDrawBatchesDirect(StaticQueue queue, Pipeline pipeline, RenderType renderType, double camX, double camY, double camZ) { TerrainRenderType terrainRenderType = TerrainRenderType.get(renderType); terrainRenderType.setCutoutUniform(); boolean isTranslucent = terrainRenderType == TerrainRenderType.TRANSLUCENT; - try(MemoryStack stack = MemoryStack.stackPush()) { - LongBuffer pVertexBuffer = stack.longs(vertexBuffer.getId()); - LongBuffer pOffset = stack.longs(0); - vkCmdBindVertexBuffers(Renderer.getCommandBuffer(), 0, pVertexBuffer, pOffset); - - } - - if(isTranslucent) { - vkCmdBindIndexBuffer(Renderer.getCommandBuffer(), this.indexBuffer.getId(), 0, VK_INDEX_TYPE_UINT16); - } - VkCommandBuffer commandBuffer = Renderer.getCommandBuffer(); + try(MemoryStack stack = MemoryStack.stackPush()) { + long pVertexBuffer = stack.npointer(vertexBuffer.getId()); + long pOffset = stack.npointer(0); + nvkCmdBindVertexBuffers(commandBuffer, 0, 1, (pVertexBuffer), (pOffset)); -// Pipeline pipeline = ShaderManager.shaderManager.terrainDirectShader; -// Pipeline pipeline = TestShaders.getShaderPipeline(renderType); -// Drawer.getInstance().bindPipeline(pipeline); - pipeline.bindDescriptorSets(Renderer.getCommandBuffer(), Renderer.getCurrentFrame()); -// ResettableQueue queue = chunkArea.sectionQueue; - int drawCount = 0; - MemoryStack stack = MemoryStack.stackGet().push(); - ByteBuffer byteBuffer = stack.malloc(24 * queue.size()); - long bufferPtr = MemoryUtil.memAddress0(byteBuffer); + if(isTranslucent) { + vkCmdBindIndexBuffer(commandBuffer, this.indexBuffer.getId(), 0, VK_INDEX_TYPE_UINT16); + } - var iterator = queue.iterator(isTranslucent); - while (iterator.hasNext()) { - RenderSection section = iterator.next(); - DrawParameters drawParameters = section.getDrawParameters(terrainRenderType); - if(drawParameters.indexCount == 0) { - continue; - } - long ptr = bufferPtr + (drawCount * 24L); - MemoryUtil.memPutInt(ptr, drawParameters.indexCount); - MemoryUtil.memPutInt(ptr + 4, drawParameters.firstIndex); - MemoryUtil.memPutInt(ptr + 8, drawParameters.vertexOffset); + // Pipeline pipeline = ShaderManager.shaderManager.terrainDirectShader; + // Pipeline pipeline = TestShaders.getShaderPipeline(renderType); + // Drawer.getInstance().bindPipeline(pipeline); + pipeline.bindDescriptorSets(commandBuffer, Renderer.getCurrentFrame()); - MemoryUtil.memPutFloat(ptr + 12, (float)((double) section.xOffset - camX)); - MemoryUtil.memPutFloat(ptr + 16, (float)((double) section.yOffset - camY)); - MemoryUtil.memPutFloat(ptr + 20, (float)((double) section.zOffset - camZ)); + // ResettableQueue queue = chunkArea.sectionQueue; - drawCount++; - } + final long ptr = stack.nmalloc(16); + final long layout = pipeline.getLayout(); + final float camX1 = (float) camX; + final float camY1 = (float) camY; + final float camZ1 = (float) camZ; - if(drawCount > 0) { - long offset; - int indexCount; - int firstIndex; - int vertexOffset; - for(int i = 0; i < drawCount; ++i) { + for (var iterator = queue.iterator(isTranslucent); iterator.hasNext(); ) { + RenderSection section = iterator.next(); + DrawParameters drawParameters = section.getDrawParameters(terrainRenderType); - offset = i * 24 + bufferPtr; - indexCount = MemoryUtil.memGetInt(offset + 0); - firstIndex = MemoryUtil.memGetInt(offset + 4); - vertexOffset = MemoryUtil.memGetInt(offset + 8); + MemoryUtil.memPutFloat(ptr + 0, section.xOffset - camX1); + MemoryUtil.memPutFloat(ptr + 4, section.yOffset - camY1); + MemoryUtil.memPutFloat(ptr + 8, section.zOffset - camZ1); -// if(indexCount == 0) { -// continue; -// } + nvkCmdPushConstants(commandBuffer, layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 12, ptr); - nvkCmdPushConstants(commandBuffer, pipeline.getLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, 12, offset + 12); + vkCmdDrawIndexed(commandBuffer, drawParameters.indexCount, 1, drawParameters.firstIndex, drawParameters.vertexOffset, 0); - vkCmdDrawIndexed(commandBuffer, indexCount, 1, firstIndex, vertexOffset, 0); } } - - stack.pop(); } public void releaseBuffers() { diff --git a/src/main/java/net/vulkanmod/render/chunk/WorldRenderer.java b/src/main/java/net/vulkanmod/render/chunk/WorldRenderer.java index 993ffcd3ca..3432a52b9f 100644 --- a/src/main/java/net/vulkanmod/render/chunk/WorldRenderer.java +++ b/src/main/java/net/vulkanmod/render/chunk/WorldRenderer.java @@ -314,9 +314,9 @@ private void updateRenderChunks() { while(this.chunkQueue.hasNext()) { RenderSection renderSection = this.chunkQueue.poll(); - renderSection.getChunkArea().sectionQueue.add(renderSection); if(!renderSection.isCompletelyEmpty()) { + renderSection.getChunkArea().sectionQueue.add(renderSection); this.chunkAreaQueue.add(renderSection.getChunkArea()); this.nonEmptyChunks++; } @@ -355,9 +355,9 @@ private void updateRenderChunksSpectator() { while(this.chunkQueue.hasNext()) { RenderSection renderSection = this.chunkQueue.poll(); - renderSection.getChunkArea().sectionQueue.add(renderSection); if(!renderSection.isCompletelyEmpty()) { + renderSection.getChunkArea().sectionQueue.add(renderSection); this.chunkAreaQueue.add(renderSection.getChunkArea()); this.nonEmptyChunks++; } diff --git a/src/main/java/net/vulkanmod/render/chunk/util/StaticQueue.java b/src/main/java/net/vulkanmod/render/chunk/util/StaticQueue.java new file mode 100644 index 0000000000..b355b87fe7 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/util/StaticQueue.java @@ -0,0 +1,99 @@ +package net.vulkanmod.render.chunk.util; + +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; +import java.util.function.Consumer; + +public class StaticQueue implements Iterable { + final T[] queue; + int position = 0; + int limit = 0; + final int capacity; + + public StaticQueue() { + this(1024); + } + + @SuppressWarnings("unchecked") + public StaticQueue(int initialCapacity) { + this.capacity = initialCapacity; + + this.queue = (T[])(new Object[capacity]); + } + + public boolean hasNext() { + return this.position < this.limit; + } + + public T poll() { + T t = this.queue[position]; + this.position++; + + return t; + } + + public void add(T t) { + if(t == null) + return; + + if(limit == capacity) throw new RuntimeException("Exceeded size: "+this.capacity); + this.queue[limit] = t; + + this.limit++; + } + + public int size() { + return limit; + } + + public void clear() { + this.position = 0; + this.limit = 0; + } + + public Iterator iterator(boolean reverseOrder) { + return reverseOrder ? new Iterator<>() { + int pos = StaticQueue.this.limit - 1; + final int limit = -1; + + @Override + public boolean hasNext() { + return pos > limit; + } + + @Override + public T next() { + return queue[pos--]; + } + } + : new Iterator<>() { + int pos = 0; + final int limit = StaticQueue.this.limit; + + @Override + public boolean hasNext() { + return pos < limit; + } + + @Override + public T next() { + return queue[pos++]; + } + }; + } + + @NotNull + @Override + public Iterator iterator() { + return iterator(false); + } + + @Override + public void forEach(Consumer action) { + for(int i = 0; i < this.limit; ++i) { + action.accept(this.queue[i]); + } + + } +} diff --git a/src/main/java/net/vulkanmod/vulkan/Drawer.java b/src/main/java/net/vulkanmod/vulkan/Drawer.java index cecef95343..b5aa806f12 100644 --- a/src/main/java/net/vulkanmod/vulkan/Drawer.java +++ b/src/main/java/net/vulkanmod/vulkan/Drawer.java @@ -22,6 +22,7 @@ public class Drawer { private static final LongBuffer offsets = MemoryUtil.memAllocLong(1); private static final long pBuffers = MemoryUtil.memAddress0(buffers); private static final long pOffsets = MemoryUtil.memAddress0(offsets); + private static final int UINT16_INDEX_MAX = 98304; private int framesNum; private VertexBuffer[] vertexBuffers; @@ -34,7 +35,7 @@ public class Drawer { public Drawer() { //Index buffers - quadsIndexBuffer = new AutoIndexBuffer(100000, AutoIndexBuffer.DrawType.QUADS); + quadsIndexBuffer = new AutoIndexBuffer(UINT16_INDEX_MAX, AutoIndexBuffer.DrawType.QUADS); triangleFanIndexBuffer = new AutoIndexBuffer(1000, AutoIndexBuffer.DrawType.TRIANGLE_FAN); triangleStripIndexBuffer = new AutoIndexBuffer(1000, AutoIndexBuffer.DrawType.TRIANGLE_STRIP); } diff --git a/src/main/java/net/vulkanmod/vulkan/Vulkan.java b/src/main/java/net/vulkanmod/vulkan/Vulkan.java index 24fe0733b7..609d66adbe 100644 --- a/src/main/java/net/vulkanmod/vulkan/Vulkan.java +++ b/src/main/java/net/vulkanmod/vulkan/Vulkan.java @@ -236,9 +236,9 @@ private static void createInstance() { appInfo.sType(VK_STRUCTURE_TYPE_APPLICATION_INFO); appInfo.pApplicationName(stack.UTF8Safe("VulkanMod")); - appInfo.applicationVersion(VK_MAKE_VERSION(1, 0, 0)); + appInfo.applicationVersion(VK_API_VERSION_1_2); appInfo.pEngineName(stack.UTF8Safe("No Engine")); - appInfo.engineVersion(VK_MAKE_VERSION(1, 0, 0)); + appInfo.engineVersion(VK_API_VERSION_1_2); appInfo.apiVersion(VK_API_VERSION_1_2); VkInstanceCreateInfo createInfo = VkInstanceCreateInfo.calloc(stack); @@ -345,6 +345,7 @@ private static void createVma() { allocatorCreateInfo.device(Device.device); allocatorCreateInfo.pVulkanFunctions(vulkanFunctions); allocatorCreateInfo.instance(instance); + allocatorCreateInfo.vulkanApiVersion(VK_API_VERSION_1_2); PointerBuffer pAllocator = stack.pointers(VK_NULL_HANDLE); diff --git a/src/main/java/net/vulkanmod/vulkan/memory/AutoIndexBuffer.java b/src/main/java/net/vulkanmod/vulkan/memory/AutoIndexBuffer.java index 48619fb1ba..523a4ba38c 100644 --- a/src/main/java/net/vulkanmod/vulkan/memory/AutoIndexBuffer.java +++ b/src/main/java/net/vulkanmod/vulkan/memory/AutoIndexBuffer.java @@ -5,6 +5,8 @@ import java.nio.ByteBuffer; import java.nio.ShortBuffer; +import static net.vulkanmod.vulkan.memory.AutoIndexBuffer.DrawType.QUADS; + public class AutoIndexBuffer { int vertexCount; DrawType drawType; @@ -44,7 +46,7 @@ private void createIndexBuffer(int vertexCount) { } public void checkCapacity(int vertexCount) { - if(vertexCount > this.vertexCount) { + if(this.drawType!=QUADS && vertexCount > this.vertexCount) { int newVertexCount = this.vertexCount * 2; System.out.println("Reallocating AutoIndexBuffer from " + this.vertexCount + " to " + newVertexCount); diff --git a/src/main/resources/assets/vulkanmod/shaders/include/light.glsl b/src/main/resources/assets/vulkanmod/shaders/include/light.glsl index 5876db9589..b5a0decd98 100644 --- a/src/main/resources/assets/vulkanmod/shaders/include/light.glsl +++ b/src/main/resources/assets/vulkanmod/shaders/include/light.glsl @@ -1,29 +1,25 @@ //light.glsl -#define MINECRAFT_LIGHT_POWER (0.6) -#define MINECRAFT_AMBIENT_LIGHT (0.4) +//#pragma once +const float MINECRAFT_LIGHT_POWER = (0.6); +const float MINECRAFT_AMBIENT_LIGHT = (0.4); vec4 minecraft_mix_light(vec3 lightDir0, vec3 lightDir1, vec3 normal, vec4 color) { lightDir0 = normalize(lightDir0); lightDir1 = normalize(lightDir1); float light0 = max(0.0, dot(lightDir0, normal)); float light1 = max(0.0, dot(lightDir1, normal)); - float lightAccum = min(1.0, (light0 + light1) * MINECRAFT_LIGHT_POWER + MINECRAFT_AMBIENT_LIGHT); + float lightAccum = min(1.0, fma((light0 + light1), MINECRAFT_LIGHT_POWER, MINECRAFT_AMBIENT_LIGHT)); return vec4(color.rgb * lightAccum, color.a); } vec4 minecraft_sample_lightmap(sampler2D lightMap, ivec2 uv) { - return texture(lightMap, clamp(uv / 256.0, vec2(0.5 / 16.0), vec2(15.5 / 16.0))); + return texelFetch(lightMap, bitfieldExtract(uv, 4, 8), 0); //return texture(lightMap, clamp(uv / 256.0, vec2(0.5 / 16.0), vec2(15.5 / 16.0))); } vec4 sample_lightmap(sampler2D lightMap, ivec2 uv) { - return texelFetch(lightMap, (uv & 255) >> 4, 0); + return texelFetch(lightMap, bitfieldExtract(uv, 4, 8), 0); } vec4 linear_fog(vec4 inColor, float vertexDistance, float fogStart, float fogEnd, vec4 fogColor) { - if (vertexDistance <= fogStart) { - return inColor; - } - - float fogValue = vertexDistance < fogEnd ? smoothstep(fogStart, fogEnd, vertexDistance) : 1.0; - return vec4(mix(inColor.rgb, fogColor.rgb, fogValue * fogColor.a), inColor.a); + return (vertexDistance <= fogStart) ? inColor : mix(inColor, fogColor, min(smoothstep(fogStart, fogEnd, vertexDistance), 1.0) * fogColor.a); } \ No newline at end of file