From 8c44c0cdcabda1084887dc100dac805bca603622 Mon Sep 17 00:00:00 2001 From: xCollateral <> Date: Tue, 5 Sep 2023 11:20:05 +0200 Subject: [PATCH] Refactor and various changes including VkRenderPass comeback --- .../java/net/vulkanmod/config/Options.java | 7 +- .../vulkanmod/config/widget/OptionWidget.java | 3 +- .../config/widget/RangeOptionWidget.java | 3 +- .../java/net/vulkanmod/gl/GlFramebuffer.java | 9 +- src/main/java/net/vulkanmod/gl/GlTexture.java | 3 +- .../net/vulkanmod/mixin/ClientLevelM.java | 13 - .../java/net/vulkanmod/mixin/WindowMixin.java | 52 +- .../vulkanmod/mixin/chunk/FrustumMixin.java | 4 +- .../mixin/chunk/LevelRendererMixin.java | 149 +++- .../java/net/vulkanmod/mixin/gui/GuiM.java | 1 - .../mixin/render/BufferUploaderM.java | 15 +- .../mixin/render/GlStateManagerM.java | 10 +- .../mixin/render/MainTargetMixin.java | 3 - .../mixin/render/MinecraftMixin.java | 26 +- .../mixin/render/RenderSystemMixin.java | 10 +- .../mixin/render/RenderTargetMixin.java | 7 +- .../mixin/render/ShaderInstanceM.java | 3 - .../mixin/render/model/ModelPartCubeM.java | 1 - .../mixin/render/model/ModelPartM.java | 38 -- .../mixin/render/vertex/VertexBufferM.java | 2 +- .../vulkanmod/mixin/texture/MNativeImage.java | 7 +- .../mixin/texture/MTextureManager.java | 27 +- src/main/java/net/vulkanmod/render/VBO.java | 87 +-- .../render/chunk/AreaUploadManager.java | 22 +- .../vulkanmod/render/chunk/DrawBuffers.java | 37 +- .../vulkanmod/render/chunk/RenderSection.java | 21 +- .../vulkanmod/render/chunk/SectionGrid.java | 16 +- .../net/vulkanmod/render/chunk/VFrustum.java | 17 +- .../vulkanmod/render/chunk/WorldRenderer.java | 68 +- .../render/chunk/build/LiquidRenderer.java | 418 ++++++++++++ .../net/vulkanmod/render/util/MathUtil.java | 20 + .../render/vertex/TerrainBufferBuilder.java | 194 ++++-- .../java/net/vulkanmod/vulkan/Device.java | 326 +++++++++ .../java/net/vulkanmod/vulkan/DeviceInfo.java | 21 +- .../java/net/vulkanmod/vulkan/Drawer.java | 643 ++---------------- .../net/vulkanmod/vulkan/Framebuffer.java | 169 ----- .../java/net/vulkanmod/vulkan/Renderer.java | 617 +++++++++++++++++ .../net/vulkanmod/vulkan/VRenderSystem.java | 44 +- .../java/net/vulkanmod/vulkan/Vulkan.java | 402 +++-------- .../vulkan/framebuffer/Framebuffer.java | 255 +++++++ .../vulkan/framebuffer/RenderPass.java | 310 +++++++++ .../vulkan/{ => framebuffer}/SwapChain.java | 294 ++++---- .../vulkan/memory/IndirectBuffer.java | 2 +- .../vulkan/memory/MemoryManager.java | 59 +- .../vulkanmod/vulkan/memory/MemoryTypes.java | 15 +- .../vulkan/memory/UniformBuffers.java | 5 +- .../vulkan/passes/DefaultMainPass.java | 78 +++ .../net/vulkanmod/vulkan/passes/MainPass.java | 10 + .../net/vulkanmod/vulkan/shader/Pipeline.java | 121 ++-- .../vulkan/shader/PipelineState.java | 25 +- .../vulkan/shader/ShaderManager.java | 28 +- .../vulkan/shader/ShaderSPIRVUtils.java | 2 +- .../net/vulkanmod/vulkan/shader/Uniforms.java | 52 ++ .../vulkanmod/vulkan/shader/layout/Mat4f.java | 14 +- .../vulkanmod/vulkan/shader/layout/Vec1f.java | 16 +- .../vulkanmod/vulkan/shader/layout/Vec1i.java | 6 +- .../vulkanmod/vulkan/shader/layout/Vec2f.java | 8 +- .../vulkanmod/vulkan/shader/layout/Vec3f.java | 11 +- .../vulkanmod/vulkan/shader/layout/Vec4f.java | 8 +- .../vulkan/texture/VTextureSelector.java | 19 + .../vulkanmod/vulkan/texture/VulkanImage.java | 33 +- .../net/vulkanmod/vulkan/util/ColorUtil.java | 118 ++++ .../net/vulkanmod/vulkan/util/DrawUtil.java | 10 +- .../java/net/vulkanmod/vulkan/util/VUtil.java | 24 +- src/main/resources/vulkanmod.mixins.json | 2 - 65 files changed, 3314 insertions(+), 1726 deletions(-) delete mode 100644 src/main/java/net/vulkanmod/mixin/ClientLevelM.java create mode 100644 src/main/java/net/vulkanmod/render/chunk/build/LiquidRenderer.java create mode 100644 src/main/java/net/vulkanmod/render/util/MathUtil.java create mode 100644 src/main/java/net/vulkanmod/vulkan/Device.java delete mode 100644 src/main/java/net/vulkanmod/vulkan/Framebuffer.java create mode 100644 src/main/java/net/vulkanmod/vulkan/Renderer.java create mode 100644 src/main/java/net/vulkanmod/vulkan/framebuffer/Framebuffer.java create mode 100644 src/main/java/net/vulkanmod/vulkan/framebuffer/RenderPass.java rename src/main/java/net/vulkanmod/vulkan/{ => framebuffer}/SwapChain.java (53%) create mode 100644 src/main/java/net/vulkanmod/vulkan/passes/DefaultMainPass.java create mode 100644 src/main/java/net/vulkanmod/vulkan/passes/MainPass.java create mode 100644 src/main/java/net/vulkanmod/vulkan/shader/Uniforms.java create mode 100644 src/main/java/net/vulkanmod/vulkan/util/ColorUtil.java diff --git a/src/main/java/net/vulkanmod/config/Options.java b/src/main/java/net/vulkanmod/config/Options.java index ff4a428fd..b6e4312a1 100644 --- a/src/main/java/net/vulkanmod/config/Options.java +++ b/src/main/java/net/vulkanmod/config/Options.java @@ -7,6 +7,7 @@ import net.minecraft.network.chat.contents.TranslatableContents; import net.vulkanmod.Initializer; import net.vulkanmod.vulkan.Drawer; +import net.vulkanmod.vulkan.Renderer; public class Options { static net.minecraft.client.Options minecraftOptions = Minecraft.getInstance().options; @@ -169,12 +170,14 @@ public static Option[] getGraphicsOpts() { public static Option[] getOtherOpts() { return new Option[] { - new RangeOption("RenderFrameQueue", 2, + new RangeOption("Queue Frames", 2, 5, 1, value -> { config.frameQueueSize = value; + Renderer.scheduleSwapChainUpdate(); }, () -> config.frameQueueSize) - .setTooltip(Component.nullToEmpty("Restart is needed to take effect")), + .setTooltip(Component.nullToEmpty(""" + Sets the number of queue frames""")), new SwitchOption("Gui Optimizations", value -> config.guiOptimizations = value, () -> config.guiOptimizations) diff --git a/src/main/java/net/vulkanmod/config/widget/OptionWidget.java b/src/main/java/net/vulkanmod/config/widget/OptionWidget.java index 8fde0889f..40d4bda9c 100644 --- a/src/main/java/net/vulkanmod/config/widget/OptionWidget.java +++ b/src/main/java/net/vulkanmod/config/widget/OptionWidget.java @@ -20,6 +20,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvents; import net.minecraft.util.Mth; +import net.vulkanmod.vulkan.util.ColorUtil; import net.vulkanmod.vulkan.util.VUtil; import java.util.Objects; @@ -75,7 +76,7 @@ public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float RenderSystem.defaultBlendFunc(); RenderSystem.enableDepthTest(); - int color = this.controlHovered ? VUtil.packColor(0.0f, 0.0f, 0.0f, 0.45f) : VUtil.packColor(0.0f, 0.0f, 0.0f, 0.3f); + int color = this.controlHovered ? ColorUtil.packColorInt(0.0f, 0.0f, 0.0f, 0.45f) : ColorUtil.packColorInt(0.0f, 0.0f, 0.0f, 0.3f); if(this.hovered) guiGraphics.fill(this.x - 2, this.y - 2, this.x + this.width + 2, this.y + this.height + 2, 0x28000000); diff --git a/src/main/java/net/vulkanmod/config/widget/RangeOptionWidget.java b/src/main/java/net/vulkanmod/config/widget/RangeOptionWidget.java index 6578b1512..96c33700c 100644 --- a/src/main/java/net/vulkanmod/config/widget/RangeOptionWidget.java +++ b/src/main/java/net/vulkanmod/config/widget/RangeOptionWidget.java @@ -8,6 +8,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.util.Mth; import net.vulkanmod.config.RangeOption; +import net.vulkanmod.vulkan.util.ColorUtil; import net.vulkanmod.vulkan.util.VUtil; import org.lwjgl.glfw.GLFW; @@ -40,7 +41,7 @@ protected void renderBackground(GuiGraphics guiGraphics, Minecraft client, int m // this.drawTexture(matrices, this.controlX + (int)(this.value * (this.controlWidth - 8)), this.y, 0, 46 + i, 4, 20); // this.drawTexture(matrices, this.controlX + (int)(this.value * (this.controlWidth - 8)) + 4, this.y, 196, 46 + i, 4, 20); - int color = this.controlHovered ? VUtil.packColor(1.0f, 1.0f, 1.0f, 1.0f) : VUtil.packColor(1.0f, 1.0f, 1.0f, 0.8f); + int color = this.controlHovered ? ColorUtil.packColorInt(1.0f, 1.0f, 1.0f, 1.0f) : ColorUtil.packColorInt(1.0f, 1.0f, 1.0f, 0.8f); guiGraphics.fill(this.controlX + (int)(this.value * (this.controlWidth - 8)), this.y + 20, this.controlX + (int)(this.value * (this.controlWidth - 8)) + 8, this.y, color); } diff --git a/src/main/java/net/vulkanmod/gl/GlFramebuffer.java b/src/main/java/net/vulkanmod/gl/GlFramebuffer.java index 7b2a4153a..415799b21 100644 --- a/src/main/java/net/vulkanmod/gl/GlFramebuffer.java +++ b/src/main/java/net/vulkanmod/gl/GlFramebuffer.java @@ -1,15 +1,12 @@ package net.vulkanmod.gl; import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; -import net.vulkanmod.vulkan.Drawer; -import net.vulkanmod.vulkan.Framebuffer; -import net.vulkanmod.vulkan.texture.VTextureSelector; -import net.vulkanmod.vulkan.texture.VulkanImage; +import net.vulkanmod.vulkan.Renderer; +import net.vulkanmod.vulkan.framebuffer.Framebuffer; import org.apache.commons.lang3.Validate; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL30; import org.lwjgl.opengl.GL30C; -import org.lwjgl.system.NativeType; public class GlFramebuffer { @@ -117,7 +114,7 @@ public static int glCheckFramebufferStatus(int target) { } void beginRendering() { - Drawer.getInstance().beginRendering(this.framebuffer); + Renderer.getInstance().beginRendering(this.framebuffer); } void setAttachmentTexture(int attachment, int texture) { diff --git a/src/main/java/net/vulkanmod/gl/GlTexture.java b/src/main/java/net/vulkanmod/gl/GlTexture.java index 316b0bc4e..dbbb65a48 100644 --- a/src/main/java/net/vulkanmod/gl/GlTexture.java +++ b/src/main/java/net/vulkanmod/gl/GlTexture.java @@ -56,11 +56,12 @@ public static void texImage2D(int target, int level, int internalFormat, int wid boundTexture.uploadImage(pixels); } + public static void texSubImage2D(int target, int level, int xOffset, int yOffset, int width, int height, int format, int type, @Nullable ByteBuffer pixels) { if(width == 0 || height == 0) return; - VTextureSelector.uploadSubTexture(level, width, height, xOffset, yOffset, 0, 0, width, pixels); + VTextureSelector.uploadSubTexture(level, width, height, xOffset, yOffset,0, 0, width, pixels); } public static void setVulkanImage(int id, VulkanImage vulkanImage) { diff --git a/src/main/java/net/vulkanmod/mixin/ClientLevelM.java b/src/main/java/net/vulkanmod/mixin/ClientLevelM.java deleted file mode 100644 index 0f5dc8409..000000000 --- a/src/main/java/net/vulkanmod/mixin/ClientLevelM.java +++ /dev/null @@ -1,13 +0,0 @@ -package net.vulkanmod.mixin; - -import net.minecraft.client.multiplayer.ClientLevel; -import net.vulkanmod.render.chunk.WorldRenderer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(ClientLevel.class) -public class ClientLevelM { - -} diff --git a/src/main/java/net/vulkanmod/mixin/WindowMixin.java b/src/main/java/net/vulkanmod/mixin/WindowMixin.java index 839b525b0..296144834 100644 --- a/src/main/java/net/vulkanmod/mixin/WindowMixin.java +++ b/src/main/java/net/vulkanmod/mixin/WindowMixin.java @@ -2,11 +2,11 @@ import com.mojang.blaze3d.platform.*; import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.Minecraft; import net.vulkanmod.Initializer; import net.vulkanmod.config.Config; import net.vulkanmod.config.Options; import net.vulkanmod.config.VideoResolution; +import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.VRenderSystem; import net.vulkanmod.vulkan.Vulkan; import org.lwjgl.glfw.GLFW; @@ -45,6 +45,16 @@ public abstract class WindowMixin { @Shadow private int width; @Shadow private int height; + @Shadow @Final private WindowEventHandler eventHandler; + + @Shadow public abstract int getWidth(); + + @Shadow public abstract int getHeight(); + + @Shadow private int framebufferWidth; + + @Shadow private int framebufferHeight; + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwWindowHint(II)V")) private void redirect(int hint, int value) { } @@ -59,6 +69,8 @@ private GLCapabilities redirect2() { @Inject(method = "", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwCreateWindow(IILjava/lang/CharSequence;JJ)J")) private void vulkanHint(WindowEventHandler windowEventHandler, ScreenManager screenManager, DisplayData displayData, String string, String string2, CallbackInfo ci) { GLFW.glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); +// GLFW.glfwWindowHint(GLFW_AUTO_ICONIFY, GLFW_FALSE); +// GLFW.glfwWindowHint(GLFW_FOCUSED, GLFW_FALSE); } @Inject(method = "", at = @At(value = "RETURN")) @@ -192,4 +204,42 @@ else if(config.windowedFullscreen) { GLFW.glfwSetWindowMonitor(this.window, 0L, this.x, this.y, this.width, this.height, -1); } } + + /** + * @author + * @reason + */ + @Overwrite + private void onFramebufferResize(long window, int width, int height) { + if (window == this.window) { + int k = this.getWidth(); + int m = this.getHeight(); + if (width != 0 && height != 0) { + this.framebufferWidth = width; + this.framebufferHeight = height; + if (this.framebufferWidth != k || this.framebufferHeight != m) { + this.eventHandler.resizeDisplay(); + } + + } + + if(width > 0 && height > 0) + Renderer.scheduleSwapChainUpdate(); + } + } + + /** + * @author + * @reason + */ + @Overwrite + private void onResize(long window, int width, int height) { +// System.out.printf("onResize: %d %d%n", width, height); + this.width = width; + this.height = height; + + if(width > 0 && height > 0) + Renderer.scheduleSwapChainUpdate(); + } + } diff --git a/src/main/java/net/vulkanmod/mixin/chunk/FrustumMixin.java b/src/main/java/net/vulkanmod/mixin/chunk/FrustumMixin.java index 7b42f243c..998af7718 100644 --- a/src/main/java/net/vulkanmod/mixin/chunk/FrustumMixin.java +++ b/src/main/java/net/vulkanmod/mixin/chunk/FrustumMixin.java @@ -16,7 +16,7 @@ public class FrustumMixin implements FrustumMixed { @Shadow private double camX; @Shadow private double camY; @Shadow private double camZ; - private VFrustum vFrustum = new VFrustum(); + private final VFrustum vFrustum = new VFrustum(); @Inject(method = "calculateFrustum", at = @At("HEAD"), cancellable = true) private void calculateFrustum(Matrix4f modelView, Matrix4f projection, CallbackInfo ci) { @@ -27,7 +27,7 @@ private void calculateFrustum(Matrix4f modelView, Matrix4f projection, CallbackI @Inject(method = "prepare", at = @At("RETURN")) public void prepare(double d, double e, double f, CallbackInfo ci) { - this.vFrustum.prepare(this.camX, this.camY, this.camZ); + this.vFrustum.setCamOffset(this.camX, this.camY, this.camZ); } @Override diff --git a/src/main/java/net/vulkanmod/mixin/chunk/LevelRendererMixin.java b/src/main/java/net/vulkanmod/mixin/chunk/LevelRendererMixin.java index 9ec2c659a..ec9d9b917 100644 --- a/src/main/java/net/vulkanmod/mixin/chunk/LevelRendererMixin.java +++ b/src/main/java/net/vulkanmod/mixin/chunk/LevelRendererMixin.java @@ -2,6 +2,8 @@ import com.mojang.blaze3d.vertex.PoseStack; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; @@ -11,16 +13,16 @@ import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.core.BlockPos; import net.minecraft.server.level.BlockDestructionProgress; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.phys.Vec3; import net.vulkanmod.render.chunk.WorldRenderer; import net.vulkanmod.render.profiling.Profiler2; +import net.vulkanmod.vulkan.util.Pair; import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -42,8 +44,22 @@ public abstract class LevelRendererMixin { @Shadow @Final private Minecraft minecraft; @Shadow @Final private Set globalBlockEntities; @Shadow private boolean generateClouds; + @Shadow @Final private EntityRenderDispatcher entityRenderDispatcher; + + @Shadow protected abstract boolean shouldShowEntityOutlines(); + + @Shadow public abstract void needsUpdate(); + + @Shadow public abstract void renderLevel(PoseStack poseStack, float f, long l, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f); + private WorldRenderer worldRenderer; + @Unique + private static boolean ENTITIES_OPT = true; + + @Unique + private Object2ReferenceOpenHashMap, ObjectArrayList>> entitiesMap = new Object2ReferenceOpenHashMap<>(); + @Inject(method = "", at = @At("RETURN")) private void init(Minecraft minecraft, EntityRenderDispatcher entityRenderDispatcher, BlockEntityRenderDispatcher blockEntityRenderDispatcher, RenderBuffers renderBuffers, CallbackInfo ci) { this.worldRenderer = WorldRenderer.init(this.renderBuffers); @@ -72,6 +88,10 @@ private void renderBlockEntities(PoseStack poseStack, float f, long l, boolean b @Overwrite private void setupRender(Camera camera, Frustum frustum, boolean isCapturedFrustum, boolean spectator) { this.worldRenderer.setupRenderer(camera, frustum, isCapturedFrustum, spectator); + + ENTITIES_OPT = true; +// ENTITIES_OPT = false; + entitiesMap.clear(); } /** @@ -146,23 +166,10 @@ public String getChunkStatistics() { return this.worldRenderer.getChunkStatistics(); } - //Debug - @Inject(method = "renderLevel", at = @At("HEAD")) - private void pushProfiler(PoseStack poseStack, float f, long l, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, CallbackInfo ci) { -// Profiler2 profiler = Profiler2.getMainProfiler(); -// profiler.push("Render_level_1"); - } - - @Inject(method = "renderLevel", at = @At("TAIL")) - private void popProfiler(PoseStack poseStack, float f, long l, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, CallbackInfo ci) { -// Profiler2 profiler = Profiler2.getMainProfiler(); -// profiler.pop(); - } - @Inject(method = "renderClouds", at = @At("HEAD")) private void pushProfiler2(PoseStack poseStack, Matrix4f matrix4f, float f, double d, double e, double g, CallbackInfo ci) { Profiler2 profiler = Profiler2.getMainProfiler(); - profiler.push("Render_clouds"); + profiler.push("clouds"); } @Inject(method = "renderClouds", at = @At("TAIL")) @@ -186,4 +193,110 @@ private void popProfiler3(PoseStack poseStack, float f, long l, boolean bl, Came Profiler2 profiler = Profiler2.getMainProfiler(); profiler.pop(); } + + /** + * @author + * @reason + */ + @Overwrite + private void renderEntity(Entity entity, double d, double e, double f, float g, PoseStack poseStack, MultiBufferSource multiBufferSource) { + if(!ENTITIES_OPT) { + double h = Mth.lerp((double)g, entity.xOld, entity.getX()); + double i = Mth.lerp((double)g, entity.yOld, entity.getY()); + double j = Mth.lerp((double)g, entity.zOld, entity.getZ()); + float k = Mth.lerp(g, entity.yRotO, entity.getYRot()); + this.entityRenderDispatcher.render(entity, h - d, i - e, j - f, k, g, poseStack, multiBufferSource, this.entityRenderDispatcher.getPackedLightCoords(entity, g)); + return; + } + + var entityClass = entity.getClass(); + var list = this.entitiesMap.get(entityClass); + + if(list == null) { + list = new ObjectArrayList<>(); + this.entitiesMap.put(entityClass, list); + } + + list.add(new Pair<>(entity, multiBufferSource)); + + } + + @Inject(method = "renderLevel", at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;endLastBatch()V", + shift = At.Shift.AFTER, ordinal = 0) + ) + private void renderEntities(PoseStack poseStack, float partialTicks, long l, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, CallbackInfo ci) { + if(!ENTITIES_OPT) + return; + + Vec3 cameraPos = WorldRenderer.getCameraPos(); + + for(var list : this.entitiesMap.values()) { + for(var pair : list) { + Entity entity = pair.first; + MultiBufferSource multiBufferSource = pair.second; + + double h = Mth.lerp(partialTicks, entity.xOld, entity.getX()); + double i = Mth.lerp(partialTicks, entity.yOld, entity.getY()); + double j = Mth.lerp(partialTicks, entity.zOld, entity.getZ()); + float k = Mth.lerp(partialTicks, entity.yRotO, entity.getYRot()); + this.entityRenderDispatcher.render(entity, h - cameraPos.x, i - cameraPos.y, j - cameraPos.z, k, partialTicks, poseStack, multiBufferSource, this.entityRenderDispatcher.getPackedLightCoords(entity, partialTicks)); + } + } + } + +// @Redirect(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientLevel;entitiesForRendering()Ljava/lang/Iterable;")) +// private Iterable replaceIterator(ClientLevel instance) { +// +// return () -> new Iterator() { +// @Override +// public boolean hasNext() { +// return false; +// } +// +// @Override +// public Entity next() { +// return null; +// } +// }; +// } +// +// @Inject(method = "renderLevel", at = @At(value = "INVOKE", +// target = "Lnet/minecraft/client/multiplayer/ClientLevel;entitiesForRendering()Ljava/lang/Iterable;", +// shift = At.Shift.AFTER), +// locals = LocalCapture.CAPTURE_FAILHARD +// ) +// private void renderEntities(PoseStack poseStack, float f, long l, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, CallbackInfo ci) { +// for(Entity entity : this.level.entitiesForRendering()) { +// if (this.entityRenderDispatcher.shouldRender(entity, frustum, d0, d1, d2) || entity.hasIndirectPassenger(this.minecraft.player)) { +// BlockPos blockpos = entity.blockPosition(); +// if ((this.level.isOutsideBuildHeight(blockpos.getY()) || this.isChunkCompiled(blockpos)) && (entity != p_109604_.getEntity() || p_109604_.isDetached() || p_109604_.getEntity() instanceof LivingEntity && ((LivingEntity)p_109604_.getEntity()).isSleeping()) && (!(entity instanceof LocalPlayer) || p_109604_.getEntity() == entity)) { +// ++this.renderedEntities; +// if (entity.tickCount == 0) { +// entity.xOld = entity.getX(); +// entity.yOld = entity.getY(); +// entity.zOld = entity.getZ(); +// } +// +// MultiBufferSource multibuffersource; +// if (this.shouldShowEntityOutlines() && this.minecraft.shouldEntityAppearGlowing(entity)) { +// flag3 = true; +// OutlineBufferSource outlinebuffersource = this.renderBuffers.outlineBufferSource(); +// multibuffersource = outlinebuffersource; +// int i = entity.getTeamColor(); +// int j = 255; +// int k = i >> 16 & 255; +// int l = i >> 8 & 255; +// int i1 = i & 255; +// outlinebuffersource.setColor(k, l, i1, 255); +// } else { +// multibuffersource = bu; +// } +// +// this.renderEntity(entity, d0, d1, d2, p_109601_, p_109600_, multibuffersource); +// } +// } +// } +// } + } diff --git a/src/main/java/net/vulkanmod/mixin/gui/GuiM.java b/src/main/java/net/vulkanmod/mixin/gui/GuiM.java index 02ed9620d..11273f683 100644 --- a/src/main/java/net/vulkanmod/mixin/gui/GuiM.java +++ b/src/main/java/net/vulkanmod/mixin/gui/GuiM.java @@ -1,6 +1,5 @@ package net.vulkanmod.mixin.gui; -import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; diff --git a/src/main/java/net/vulkanmod/mixin/render/BufferUploaderM.java b/src/main/java/net/vulkanmod/mixin/render/BufferUploaderM.java index d94540527..c200305a0 100644 --- a/src/main/java/net/vulkanmod/mixin/render/BufferUploaderM.java +++ b/src/main/java/net/vulkanmod/mixin/render/BufferUploaderM.java @@ -3,7 +3,9 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.BufferUploader; -import net.vulkanmod.vulkan.Drawer; +import net.vulkanmod.interfaces.ShaderMixed; +import net.vulkanmod.vulkan.Renderer; +import net.vulkanmod.vulkan.shader.Pipeline; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -26,8 +28,15 @@ public static void drawWithShader(BufferBuilder.RenderedBuffer buffer) { BufferBuilder.DrawState parameters = buffer.drawState(); - Drawer drawer = Drawer.getInstance(); - drawer.draw(buffer.vertexBuffer(), parameters.mode(), parameters.format(), parameters.vertexCount()); + Renderer renderer = Renderer.getInstance(); + + if(parameters.vertexCount() <= 0) + return; + + Pipeline pipeline = ((ShaderMixed)(RenderSystem.getShader())).getPipeline(); + renderer.bindPipeline(pipeline); + renderer.uploadAndBindUBOs(pipeline); + Renderer.getDrawer().draw(buffer.vertexBuffer(), parameters.mode(), parameters.format(), parameters.vertexCount()); } } diff --git a/src/main/java/net/vulkanmod/mixin/render/GlStateManagerM.java b/src/main/java/net/vulkanmod/mixin/render/GlStateManagerM.java index 0701a0f6b..59a39e54f 100644 --- a/src/main/java/net/vulkanmod/mixin/render/GlStateManagerM.java +++ b/src/main/java/net/vulkanmod/mixin/render/GlStateManagerM.java @@ -4,11 +4,9 @@ import com.mojang.blaze3d.systems.RenderSystem; import net.vulkanmod.gl.GlFramebuffer; import net.vulkanmod.gl.GlTexture; -import net.vulkanmod.vulkan.Drawer; +import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.VRenderSystem; import org.jetbrains.annotations.Nullable; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL30; import org.lwjgl.system.MemoryUtil; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -69,7 +67,7 @@ public static void _blendFuncSeparate(int i, int j, int k, int l) { */ @Overwrite(remap = false) public static void _disableScissorTest() { - Drawer.resetScissor(); + Renderer.resetScissor(); } /** @@ -83,7 +81,7 @@ public static void _enableScissorTest() {} */ @Overwrite(remap = false) public static void _viewport(int x, int y, int width, int height) { - Drawer.setViewport(x, y, width, height); + Renderer.setViewport(x, y, width, height); } /** @@ -91,7 +89,7 @@ public static void _viewport(int x, int y, int width, int height) { */ @Overwrite(remap = false) public static void _scissorBox(int x, int y, int width, int height) { - Drawer.setScissor(x, y, width, height); + Renderer.setScissor(x, y, width, height); } //TODO diff --git a/src/main/java/net/vulkanmod/mixin/render/MainTargetMixin.java b/src/main/java/net/vulkanmod/mixin/render/MainTargetMixin.java index dfc5fa3a8..2806c2cda 100644 --- a/src/main/java/net/vulkanmod/mixin/render/MainTargetMixin.java +++ b/src/main/java/net/vulkanmod/mixin/render/MainTargetMixin.java @@ -2,9 +2,6 @@ import com.mojang.blaze3d.pipeline.MainTarget; import com.mojang.blaze3d.pipeline.RenderTarget; -import com.mojang.blaze3d.systems.RenderSystem; -import net.vulkanmod.vulkan.Drawer; -import net.vulkanmod.vulkan.util.DrawUtil; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; diff --git a/src/main/java/net/vulkanmod/mixin/render/MinecraftMixin.java b/src/main/java/net/vulkanmod/mixin/render/MinecraftMixin.java index 498e5da09..98f45490b 100644 --- a/src/main/java/net/vulkanmod/mixin/render/MinecraftMixin.java +++ b/src/main/java/net/vulkanmod/mixin/render/MinecraftMixin.java @@ -7,6 +7,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.font.FontManager; +import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.particle.ParticleEngine; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.LevelRenderer; @@ -19,8 +20,9 @@ import net.minecraft.server.packs.resources.ReloadableResourceManager; import net.vulkanmod.render.texture.SpriteUtil; import net.vulkanmod.render.profiling.Profiler2; -import net.vulkanmod.vulkan.Drawer; +import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.Vulkan; +import net.vulkanmod.vulkan.passes.DefaultMainPass; import org.slf4j.Logger; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -53,19 +55,18 @@ public class MinecraftMixin { @Shadow @Final private PaintingTextureManager paintingTextures; @Shadow public boolean noRender; - @Inject(method = "runTick", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;clear(IZ)V", shift = At.Shift.BEFORE)) - private void beginRender(boolean tick, CallbackInfo ci) { - Drawer drawer = Drawer.getInstance(); - drawer.initiateRenderPass(); + @Redirect(method = "runTick", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;clear(IZ)V")) + private void beginRender(int i, boolean bl) { + Renderer renderer = Renderer.getInstance(); + renderer.beginFrame(); } @Inject(method = "runTick", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/Window;updateDisplay()V", shift = At.Shift.BEFORE)) private void submitRender(boolean tick, CallbackInfo ci) { - Drawer drawer = Drawer.getInstance(); + Renderer renderer = Renderer.getInstance(); Profiler2 p = Profiler2.getMainProfiler(); p.push("submitRender"); - drawer.endRenderPass(); - drawer.submitDraw(); + renderer.endFrame(); p.pop(); } @@ -99,15 +100,12 @@ private Optional removeTimer() { locals = LocalCapture.CAPTURE_FAILHARD) private void redirectResourceTick(boolean bl, CallbackInfo ci, long l, Runnable runnable, int i, int j) { int n = Math.min(10, i) - 1; - if(j == n) - SpriteUtil.setDoUpload(true); - else - SpriteUtil.setDoUpload(false); + SpriteUtil.setDoUpload(j == n); } @Inject(method = "runTick", at = @At(value = "HEAD")) private void resetBuffers(boolean bl, CallbackInfo ci) { - Drawer.getInstance().resetBuffers(); + Renderer.getInstance().resetBuffers(); } /** @@ -150,7 +148,7 @@ private void skipEmergencySave(Minecraft instance) { @Inject(method = "resizeDisplay", at = @At("HEAD")) public void onResolutionChanged(CallbackInfo ci) { - Drawer.shouldRecreate = true; + Renderer.scheduleSwapChainUpdate(); } } diff --git a/src/main/java/net/vulkanmod/mixin/render/RenderSystemMixin.java b/src/main/java/net/vulkanmod/mixin/render/RenderSystemMixin.java index 90cb87794..cc496e4f4 100644 --- a/src/main/java/net/vulkanmod/mixin/render/RenderSystemMixin.java +++ b/src/main/java/net/vulkanmod/mixin/render/RenderSystemMixin.java @@ -10,7 +10,7 @@ import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.resources.ResourceLocation; import net.vulkanmod.interfaces.VAbstractTextureI; -import net.vulkanmod.vulkan.Drawer; +import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.VRenderSystem; import net.vulkanmod.vulkan.texture.VTextureSelector; import org.jetbrains.annotations.Nullable; @@ -159,7 +159,7 @@ public static void flipFrame(long window) { */ @Overwrite(remap = false) public static void viewport(int x, int y, int width, int height) { - Drawer.setViewport(x, y, width, height); + Renderer.setViewport(x, y, width, height); } /** @@ -167,7 +167,7 @@ public static void viewport(int x, int y, int width, int height) { */ @Overwrite(remap = false) public static void enableScissor(int x, int y, int width, int height) { - Drawer.setScissor(x, y, width, height); + Renderer.setScissor(x, y, width, height); } /** @@ -175,7 +175,7 @@ public static void enableScissor(int x, int y, int width, int height) { */ @Overwrite(remap = false) public static void disableScissor() { - Drawer.resetScissor(); + Renderer.resetScissor(); } /** @@ -414,14 +414,12 @@ public static void setProjectionMatrix(Matrix4f projectionMatrix, VertexSorting if (!isOnRenderThread()) { recordRenderCall(() -> { RenderSystemMixin.projectionMatrix = matrix4f; - RenderSystem.vertexSorting = vertexSorting; //Vulkan VRenderSystem.applyProjectionMatrix(matrix4f); VRenderSystem.calculateMVP(); }); } else { RenderSystemMixin.projectionMatrix = matrix4f; - RenderSystem.vertexSorting = vertexSorting; //Vulkan VRenderSystem.applyProjectionMatrix(matrix4f); VRenderSystem.calculateMVP(); diff --git a/src/main/java/net/vulkanmod/mixin/render/RenderTargetMixin.java b/src/main/java/net/vulkanmod/mixin/render/RenderTargetMixin.java index 8a9984fa5..1bae0fd9c 100644 --- a/src/main/java/net/vulkanmod/mixin/render/RenderTargetMixin.java +++ b/src/main/java/net/vulkanmod/mixin/render/RenderTargetMixin.java @@ -2,10 +2,9 @@ import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.systems.RenderSystem; -import net.vulkanmod.vulkan.Drawer; -import net.vulkanmod.vulkan.Framebuffer; +import net.vulkanmod.vulkan.Renderer; +import net.vulkanmod.vulkan.framebuffer.Framebuffer; import net.vulkanmod.vulkan.util.DrawUtil; -import org.lwjgl.system.MemoryStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; @@ -49,7 +48,7 @@ public void resize(int i, int j, boolean bl) { */ @Overwrite public void bindWrite(boolean updateViewport) { - Drawer.getInstance().beginRendering(framebuffer); + Renderer.getInstance().beginRendering(framebuffer); } /** diff --git a/src/main/java/net/vulkanmod/mixin/render/ShaderInstanceM.java b/src/main/java/net/vulkanmod/mixin/render/ShaderInstanceM.java index b051581c7..df6932229 100644 --- a/src/main/java/net/vulkanmod/mixin/render/ShaderInstanceM.java +++ b/src/main/java/net/vulkanmod/mixin/render/ShaderInstanceM.java @@ -86,9 +86,6 @@ private void bindAttr(int program, int index, CharSequence name) {} */ @Overwrite public void close() { - if(pipeline == null) - return; - pipeline.cleanUp(); } diff --git a/src/main/java/net/vulkanmod/mixin/render/model/ModelPartCubeM.java b/src/main/java/net/vulkanmod/mixin/render/model/ModelPartCubeM.java index 02ff04f87..92fe31ef4 100644 --- a/src/main/java/net/vulkanmod/mixin/render/model/ModelPartCubeM.java +++ b/src/main/java/net/vulkanmod/mixin/render/model/ModelPartCubeM.java @@ -16,7 +16,6 @@ public class ModelPartCubeM implements ModelPartCubeMixed { CubeModel cube; - //TODO @Inject(method = "", at = @At(value = "FIELD", target = "Lnet/minecraft/client/model/geom/ModelPart$Cube;polygons:[Lnet/minecraft/client/model/geom/ModelPart$Polygon;", ordinal = 0, shift = At.Shift.AFTER)) diff --git a/src/main/java/net/vulkanmod/mixin/render/model/ModelPartM.java b/src/main/java/net/vulkanmod/mixin/render/model/ModelPartM.java index 6edc4e3ce..e49be0220 100644 --- a/src/main/java/net/vulkanmod/mixin/render/model/ModelPartM.java +++ b/src/main/java/net/vulkanmod/mixin/render/model/ModelPartM.java @@ -10,13 +10,11 @@ import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Vector3f; -import org.joml.Vector4f; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -import java.util.Iterator; import java.util.List; @Mixin(ModelPart.class) @@ -73,41 +71,5 @@ protected void compile(PoseStack.Pose pose, VertexConsumer vertexConsumer, int i } } -// Iterator var9 = this.cubes.iterator(); -// -// while(var9.hasNext()) { -// ModelPart.Cube cube = (ModelPart.Cube)var9.next(); -//// cube.compile(pose, vertexConsumer, i, j, r, g, b, a); -// -// Matrix4f matrix4f = pose.pose(); -// Matrix3f matrix3f = pose.normal(); -// -// -// ModelPartCubeMixed cubeMixed = (ModelPartCubeMixed)(cube); -// CubeModel cubeModel = cubeMixed.getCubeModel(); -// -// ModelPart.Polygon[] var11 = cubeModel.getPolygons(); -// int var12 = var11.length; -// -// for(int var13 = 0; var13 < var12; ++var13) { -// ModelPart.Polygon polygon = var11[var13]; -// Vector3f vector3f = matrix3f.transform(new Vector3f(polygon.normal)); -// float l = vector3f.x(); -// float m = vector3f.y(); -// float n = vector3f.z(); -// ModelPart.Vertex[] var19 = polygon.vertices; -// int var20 = var19.length; -// -// for(int var21 = 0; var21 < var20; ++var21) { -// ModelPart.Vertex vertex = var19[var21]; -// float o = vertex.pos.x() / 16.0F; -// float p = vertex.pos.y() / 16.0F; -// float q = vertex.pos.z() / 16.0F; -// Vector4f vector4f = matrix4f.transform(new Vector4f(o, p, q, 1.0F)); -// vertexConsumer.vertex(vector4f.x(), vector4f.y(), vector4f.z(), r, g, b, a, vertex.u, vertex.v, j, i, l, m, n); -// } -// } -// } - } } diff --git a/src/main/java/net/vulkanmod/mixin/render/vertex/VertexBufferM.java b/src/main/java/net/vulkanmod/mixin/render/vertex/VertexBufferM.java index 3e02e15fd..dc5b140dd 100644 --- a/src/main/java/net/vulkanmod/mixin/render/vertex/VertexBufferM.java +++ b/src/main/java/net/vulkanmod/mixin/render/vertex/VertexBufferM.java @@ -57,7 +57,7 @@ public void upload(BufferBuilder.RenderedBuffer buffer) { */ @Overwrite public void drawWithShader(Matrix4f viewMatrix, Matrix4f projectionMatrix, ShaderInstance shader) { - vbo._drawWithShader(viewMatrix, projectionMatrix, shader); + vbo.drawWithShader(viewMatrix, projectionMatrix, shader); } /** diff --git a/src/main/java/net/vulkanmod/mixin/texture/MNativeImage.java b/src/main/java/net/vulkanmod/mixin/texture/MNativeImage.java index 55800c46e..ac76870bb 100644 --- a/src/main/java/net/vulkanmod/mixin/texture/MNativeImage.java +++ b/src/main/java/net/vulkanmod/mixin/texture/MNativeImage.java @@ -2,11 +2,10 @@ import com.mojang.blaze3d.platform.NativeImage; import com.mojang.blaze3d.systems.RenderSystem; -import net.vulkanmod.vulkan.Drawer; import net.vulkanmod.vulkan.Vulkan; import net.vulkanmod.vulkan.texture.VTextureSelector; import net.vulkanmod.vulkan.texture.VulkanImage; -import net.vulkanmod.vulkan.util.VUtil; +import net.vulkanmod.vulkan.util.ColorUtil; import org.lwjgl.system.MemoryUtil; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -77,7 +76,7 @@ private void _upload(int level, int xOffset, int yOffset, int unpackSkipPixels, public void downloadTexture(int level, boolean removeAlpha) { RenderSystem.assertOnRenderThread(); - VulkanImage.downloadTexture(this.width, this.height, 4, this.buffer, Vulkan.getSwapChainImages().get(Drawer.getCurrentFrame())); + VulkanImage.downloadTexture(this.width, this.height, 4, this.buffer, Vulkan.getSwapChain().getColorAttachment().getId()); if (removeAlpha && this.format.hasAlpha()) { for (int i = 0; i < this.height; ++i) { @@ -85,7 +84,7 @@ public void downloadTexture(int level, boolean removeAlpha) { int v = this.getPixelRGBA(j, i); if(Vulkan.getSwapChain().isBGRAformat) - v = VUtil.BGRAtoRGBA(v); + v = ColorUtil.BGRAtoRGBA(v); this.setPixelRGBA(j, i, v | 255 << this.format.alphaOffset()); } diff --git a/src/main/java/net/vulkanmod/mixin/texture/MTextureManager.java b/src/main/java/net/vulkanmod/mixin/texture/MTextureManager.java index a4ff4ca1b..c6747dcdb 100644 --- a/src/main/java/net/vulkanmod/mixin/texture/MTextureManager.java +++ b/src/main/java/net/vulkanmod/mixin/texture/MTextureManager.java @@ -5,9 +5,7 @@ import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.renderer.texture.Tickable; import net.minecraft.resources.ResourceLocation; -import net.vulkanmod.render.texture.SpriteUtil; -import net.vulkanmod.vulkan.Drawer; -import net.vulkanmod.vulkan.queue.GraphicsQueue; +import net.vulkanmod.vulkan.Renderer; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -29,19 +27,20 @@ public abstract class MTextureManager { */ @Overwrite public void tick() { - if(Drawer.skipRendering) + if(Renderer.skipRendering) return; - if(SpriteUtil.shouldUpload()) - GraphicsQueue.getInstance().startRecording(); - for (Tickable tickable : this.tickableTextures) { - tickable.tick(); - } - if(SpriteUtil.shouldUpload()) { - SpriteUtil.transitionLayouts(GraphicsQueue.getInstance().getCommandBuffer()); - GraphicsQueue.getInstance().endRecordingAndSubmit(); -// Synchronization.INSTANCE.waitFences(); - } + //Debug D +// if(SpriteUtil.shouldUpload()) +// GraphicsQueue.getInstance().startRecording(); +// for (Tickable tickable : this.tickableTextures) { +// tickable.tick(); +// } +// if(SpriteUtil.shouldUpload()) { +// SpriteUtil.transitionLayouts(GraphicsQueue.getInstance().getCommandBuffer()); +// GraphicsQueue.getInstance().endRecordingAndSubmit(); +//// Synchronization.INSTANCE.waitFences(); +// } } /** diff --git a/src/main/java/net/vulkanmod/render/VBO.java b/src/main/java/net/vulkanmod/render/VBO.java index 33c8000b3..8cf3415b3 100644 --- a/src/main/java/net/vulkanmod/render/VBO.java +++ b/src/main/java/net/vulkanmod/render/VBO.java @@ -7,30 +7,24 @@ import net.fabricmc.api.Environment; import net.minecraft.client.renderer.ShaderInstance; import net.vulkanmod.interfaces.ShaderMixed; -import net.vulkanmod.vulkan.Drawer; +import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.VRenderSystem; import net.vulkanmod.vulkan.memory.*; import net.vulkanmod.vulkan.shader.Pipeline; import org.joml.Matrix4f; import java.nio.ByteBuffer; -import java.util.concurrent.locks.ReentrantLock; @Environment(EnvType.CLIENT) public class VBO { private VertexBuffer vertexBuffer; -// private AsyncVertexBuffer vertexBuffer; private IndexBuffer indexBuffer; -// private VertexFormat.IndexType indexType; + private int indexCount; private int vertexCount; private VertexFormat.Mode mode; -// private boolean sequentialIndices; -// private VertexFormat vertexFormat; -// private int vertexOffset; private boolean autoIndexed = false; -// private boolean uploaded = false; public VBO() {} @@ -50,15 +44,14 @@ public void upload(BufferBuilder.RenderedBuffer buffer) { } private void configureVertexFormat(BufferBuilder.DrawState parameters, ByteBuffer data) { -// boolean bl = !parameters.format().equals(this.vertexFormat); if (!parameters.indexOnly()) { - if(vertexBuffer != null) this.vertexBuffer.freeBuffer(); + if(vertexBuffer != null) + this.vertexBuffer.freeBuffer(); + this.vertexBuffer = new VertexBuffer(data.remaining(), MemoryTypes.GPU_MEM); -// this.vertexBuffer = new AsyncVertexBuffer(data.remaining()); vertexBuffer.copyToVertexBuffer(parameters.format().getVertexSize(), parameters.vertexCount(), data); -// this.uploaded = false; } } @@ -66,22 +59,34 @@ private void configureIndexBuffer(BufferBuilder.DrawState parameters, ByteBuffer if (parameters.sequentialIndex()) { AutoIndexBuffer autoIndexBuffer; - if(this.mode != VertexFormat.Mode.TRIANGLE_FAN) { - autoIndexBuffer = Drawer.getInstance().getQuadsIndexBuffer(); - } else { - autoIndexBuffer = Drawer.getInstance().getTriangleFanIndexBuffer(); - this.indexCount = (vertexCount - 2) * 3; + switch (this.mode) { + case TRIANGLE_FAN -> { + autoIndexBuffer = Renderer.getDrawer().getTriangleFanIndexBuffer(); + this.indexCount = (vertexCount - 2) * 3; + } + case QUADS -> { + autoIndexBuffer = Renderer.getDrawer().getQuadsIndexBuffer(); + } + case TRIANGLES -> { + autoIndexBuffer = null; + } + default -> throw new IllegalStateException("Unexpected draw mode:" + this.mode); } - if(indexBuffer != null && !this.autoIndexed) indexBuffer.freeBuffer(); + if(indexBuffer != null && !this.autoIndexed) + indexBuffer.freeBuffer(); + + if(autoIndexBuffer != null) { + autoIndexBuffer.checkCapacity(vertexCount); + indexBuffer = autoIndexBuffer.getIndexBuffer(); + } - autoIndexBuffer.checkCapacity(vertexCount); - indexBuffer = autoIndexBuffer.getIndexBuffer(); this.autoIndexed = true; } else { - if(indexBuffer != null) this.indexBuffer.freeBuffer(); + if(indexBuffer != null) + this.indexBuffer.freeBuffer(); this.indexBuffer = new IndexBuffer(data.remaining(), MemoryTypes.GPU_MEM); // this.indexBuffer = new AsyncIndexBuffer(data.remaining()); indexBuffer.copyBuffer(data); @@ -89,19 +94,31 @@ private void configureIndexBuffer(BufferBuilder.DrawState parameters, ByteBuffer } - public void _drawWithShader(Matrix4f MV, Matrix4f P, ShaderInstance shader) { + public void drawWithShader(Matrix4f MV, Matrix4f P, ShaderInstance shader) { if (this.indexCount != 0) { RenderSystem.assertOnRenderThread(); RenderSystem.setShader(() -> shader); + drawWithShader(MV, P, ((ShaderMixed)shader).getPipeline()); + + } + } + + public void drawWithShader(Matrix4f MV, Matrix4f P, Pipeline pipeline) { + if (this.indexCount != 0) { + RenderSystem.assertOnRenderThread(); + VRenderSystem.applyMVP(MV, P); - Drawer drawer = Drawer.getInstance(); - Pipeline pipeline = ((ShaderMixed)(RenderSystem.getShader())).getPipeline(); - drawer.bindPipeline(pipeline); - drawer.uploadAndBindUBOs(pipeline); - drawer.drawIndexed(vertexBuffer, indexBuffer, indexCount); + Renderer renderer = Renderer.getInstance(); + renderer.bindPipeline(pipeline); + renderer.uploadAndBindUBOs(pipeline); + + if(indexBuffer != null) + Renderer.getDrawer().drawIndexed(vertexBuffer, indexBuffer, indexCount); + else + Renderer.getDrawer().draw(vertexBuffer, vertexCount); VRenderSystem.applyMVP(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix()); @@ -109,27 +126,13 @@ public void _drawWithShader(Matrix4f MV, Matrix4f P, ShaderInstance shader) { } public void drawChunkLayer() { -// if (this.indexCount != 0) { -// if(!this.uploaded) { -// this.checkUploadStatus(); -// if(!this.uploaded) return; -// } if (this.indexCount != 0) { RenderSystem.assertOnRenderThread(); - Drawer drawer = Drawer.getInstance(); - drawer.drawIndexed(vertexBuffer, indexBuffer, indexCount); + Renderer.getDrawer().drawIndexed(vertexBuffer, indexBuffer, indexCount); } } -// public void checkUploadStatus() { -// if(!(this.indexBuffer instanceof AsyncIndexBuffer asyncIndexBuffer)) -// this.uploaded = this.vertexBuffer.checkStatus(); -// else { -// this.uploaded = this.vertexBuffer.checkStatus() && asyncIndexBuffer.checkStatus(); -// } -// } - public void close() { if(vertexCount <= 0) return; vertexBuffer.freeBuffer(); diff --git a/src/main/java/net/vulkanmod/render/chunk/AreaUploadManager.java b/src/main/java/net/vulkanmod/render/chunk/AreaUploadManager.java index b004096fe..258bf735a 100644 --- a/src/main/java/net/vulkanmod/render/chunk/AreaUploadManager.java +++ b/src/main/java/net/vulkanmod/render/chunk/AreaUploadManager.java @@ -5,7 +5,6 @@ import net.vulkanmod.vulkan.memory.Buffer; import net.vulkanmod.vulkan.memory.StagingBuffer; import net.vulkanmod.vulkan.queue.CommandPool; -import net.vulkanmod.vulkan.queue.GraphicsQueue; import net.vulkanmod.vulkan.queue.TransferQueue; import org.apache.commons.lang3.Validate; @@ -16,21 +15,18 @@ public class AreaUploadManager { public static AreaUploadManager INSTANCE; - public static void createInstance(int frames) { - INSTANCE = new AreaUploadManager(frames); + public static void createInstance() { + INSTANCE = new AreaUploadManager(); } -// final Reference2LongOpenHashMap> map = new Reference2LongOpenHashMap<>(); - final ObjectArrayList[] recordedUploads; -// final ObjectArrayList[] recordedUploads; -// final ObjectArrayList[] recordedUploads; - final ObjectArrayList[] updatedParameters; - final ObjectArrayList[] frameOps; - final CommandPool.CommandBuffer[] commandBuffers; + ObjectArrayList[] recordedUploads; + ObjectArrayList[] updatedParameters; + ObjectArrayList[] frameOps; + CommandPool.CommandBuffer[] commandBuffers; int currentFrame; - public AreaUploadManager(int frames) { + public void createLists(int frames) { this.commandBuffers = new CommandPool.CommandBuffer[frames]; this.recordedUploads = new ObjectArrayList[frames]; this.updatedParameters = new ObjectArrayList[frames]; @@ -44,7 +40,7 @@ public AreaUploadManager(int frames) { } public synchronized void submitUploads() { - Validate.isTrue(currentFrame == Drawer.getCurrentFrame()); + Validate.isTrue(currentFrame == Renderer.getCurrentFrame()); if(this.recordedUploads[this.currentFrame].isEmpty()) return; @@ -53,7 +49,7 @@ public synchronized void submitUploads() { } public void uploadAsync(AreaBuffer.Segment uploadSegment, long bufferId, long dstOffset, long bufferSize, ByteBuffer src) { - Validate.isTrue(currentFrame == Drawer.getCurrentFrame()); + Validate.isTrue(currentFrame == Renderer.getCurrentFrame()); if(commandBuffers[currentFrame] == null) this.commandBuffers[currentFrame] = TransferQueue.getInstance().beginCommands(); diff --git a/src/main/java/net/vulkanmod/render/chunk/DrawBuffers.java b/src/main/java/net/vulkanmod/render/chunk/DrawBuffers.java index 270b9841c..481b74bfb 100644 --- a/src/main/java/net/vulkanmod/render/chunk/DrawBuffers.java +++ b/src/main/java/net/vulkanmod/render/chunk/DrawBuffers.java @@ -4,7 +4,7 @@ import net.vulkanmod.render.chunk.build.UploadBuffer; import net.vulkanmod.render.chunk.util.ResettableQueue; import net.vulkanmod.render.vertex.TerrainRenderType; -import net.vulkanmod.vulkan.Drawer; +import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.memory.IndirectBuffer; import net.vulkanmod.vulkan.shader.Pipeline; import net.vulkanmod.vulkan.shader.ShaderManager; @@ -15,8 +15,6 @@ import java.nio.ByteBuffer; import java.nio.LongBuffer; -import static org.lwjgl.system.JNI.callPJPV; -import static org.lwjgl.system.JNI.callPV; import static org.lwjgl.vulkan.VK10.*; public class DrawBuffers { @@ -30,7 +28,6 @@ public class DrawBuffers { public void allocateBuffers() { this.vertexBuffer = new AreaBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 3500000, VERTEX_SIZE); -// this.vertexBuffer = new AreaBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 10000000, VERTEX_SIZE); this.indexBuffer = new AreaBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, 1000000, INDEX_SIZE); this.allocated = true; @@ -64,7 +61,7 @@ public DrawParameters upload(UploadBuffer buffer, DrawParameters drawParameters) drawParameters.firstIndex = firstIndex; drawParameters.vertexOffset = vertexOffset; - Drawer.getInstance().getQuadsIndexBuffer().checkCapacity(buffer.indexCount * 2 / 3); + Renderer.getDrawer().getQuadsIndexBuffer().checkCapacity(buffer.indexCount * 2 / 3); buffer.release(); @@ -76,8 +73,6 @@ public int buildDrawBatchesIndirect(IndirectBuffer indirectBuffer, ChunkArea chu int drawCount = 0; - Pipeline pipeline = ShaderManager.getInstance().getTerrainShader(); - ResettableQueue queue = chunkArea.sectionQueue; MemoryStack stack = MemoryStack.stackPush(); @@ -90,8 +85,10 @@ public int buildDrawBatchesIndirect(IndirectBuffer indirectBuffer, ChunkArea chu terrainRenderType.setCutoutUniform(); boolean isTranslucent = terrainRenderType == TerrainRenderType.TRANSLUCENT; + Pipeline pipeline = ShaderManager.getInstance().getTerrainIndirectShader(renderType); + if(isTranslucent) { - vkCmdBindIndexBuffer(Drawer.getCommandBuffer(), this.indexBuffer.getId(), 0, VK_INDEX_TYPE_UINT16); + vkCmdBindIndexBuffer(Renderer.getCommandBuffer(), this.indexBuffer.getId(), 0, VK_INDEX_TYPE_UINT16); } var iterator = queue.iterator(isTranslucent); @@ -156,11 +153,11 @@ public int buildDrawBatchesIndirect(IndirectBuffer indirectBuffer, ChunkArea chu LongBuffer pVertexBuffer = stack.longs(vertexBuffer.getId()); LongBuffer pOffset = stack.longs(0); - vkCmdBindVertexBuffers(Drawer.getCommandBuffer(), 0, pVertexBuffer, pOffset); + vkCmdBindVertexBuffers(Renderer.getCommandBuffer(), 0, pVertexBuffer, pOffset); // pipeline.bindDescriptorSets(Drawer.getCommandBuffer(), WorldRenderer.getInstance().getUniformBuffers(), Drawer.getCurrentFrame()); - pipeline.bindDescriptorSets(Drawer.getCommandBuffer(), Drawer.getCurrentFrame()); - vkCmdDrawIndexedIndirect(Drawer.getCommandBuffer(), indirectBuffer.getId(), indirectBuffer.getOffset(), drawCount, stride); + pipeline.bindDescriptorSets(Renderer.getCommandBuffer(), Renderer.getCurrentFrame()); + vkCmdDrawIndexedIndirect(Renderer.getCommandBuffer(), indirectBuffer.getId(), indirectBuffer.getOffset(), drawCount, stride); // fakeIndirectCmd(Drawer.getCommandBuffer(), indirectBuffer, drawCount, uboBuffer); @@ -173,7 +170,7 @@ public int buildDrawBatchesIndirect(IndirectBuffer indirectBuffer, ChunkArea chu private static void fakeIndirectCmd(VkCommandBuffer commandBuffer, IndirectBuffer indirectBuffer, int drawCount, ByteBuffer offsetBuffer) { Pipeline pipeline = ShaderManager.shaderManager.terrainDirectShader; // Drawer.getInstance().bindPipeline(pipeline); - pipeline.bindDescriptorSets(Drawer.getCommandBuffer(), Drawer.getCurrentFrame()); + pipeline.bindDescriptorSets(Renderer.getCommandBuffer(), Renderer.getCurrentFrame()); // pipeline.bindDescriptorSets(Drawer.getCommandBuffer(), WorldRenderer.getInstance().getUniformBuffers(), Drawer.getCurrentFrame()); ByteBuffer buffer = indirectBuffer.getByteBuffer(); @@ -206,7 +203,7 @@ private static void fakeIndirectCmd(VkCommandBuffer commandBuffer, IndirectBuffe } } - public void buildDrawBatchesDirect(ChunkArea chunkArea, RenderType renderType, double camX, double camY, double camZ) { + public void buildDrawBatchesDirect(ResettableQueue queue, Pipeline pipeline, RenderType renderType, double camX, double camY, double camZ) { TerrainRenderType terrainRenderType = TerrainRenderType.get(renderType); terrainRenderType.setCutoutUniform(); boolean isTranslucent = terrainRenderType == TerrainRenderType.TRANSLUCENT; @@ -214,21 +211,22 @@ public void buildDrawBatchesDirect(ChunkArea chunkArea, RenderType renderType, d try(MemoryStack stack = MemoryStack.stackPush()) { LongBuffer pVertexBuffer = stack.longs(vertexBuffer.getId()); LongBuffer pOffset = stack.longs(0); - vkCmdBindVertexBuffers(Drawer.getCommandBuffer(), 0, pVertexBuffer, pOffset); + vkCmdBindVertexBuffers(Renderer.getCommandBuffer(), 0, pVertexBuffer, pOffset); } if(isTranslucent) { - vkCmdBindIndexBuffer(Drawer.getCommandBuffer(), this.indexBuffer.getId(), 0, VK_INDEX_TYPE_UINT16); + vkCmdBindIndexBuffer(Renderer.getCommandBuffer(), this.indexBuffer.getId(), 0, VK_INDEX_TYPE_UINT16); } - VkCommandBuffer commandBuffer = Drawer.getCommandBuffer(); + VkCommandBuffer commandBuffer = Renderer.getCommandBuffer(); - Pipeline pipeline = ShaderManager.shaderManager.terrainDirectShader; +// Pipeline pipeline = ShaderManager.shaderManager.terrainDirectShader; +// Pipeline pipeline = TestShaders.getShaderPipeline(renderType); // Drawer.getInstance().bindPipeline(pipeline); - pipeline.bindDescriptorSets(Drawer.getCommandBuffer(), Drawer.getCurrentFrame()); + pipeline.bindDescriptorSets(Renderer.getCommandBuffer(), Renderer.getCurrentFrame()); - ResettableQueue queue = chunkArea.sectionQueue; +// ResettableQueue queue = chunkArea.sectionQueue; int drawCount = 0; MemoryStack stack = MemoryStack.stackGet().push(); @@ -255,7 +253,6 @@ public void buildDrawBatchesDirect(ChunkArea chunkArea, RenderType renderType, d drawCount++; -// drawCount = drawParameters.indexCount == 0 ? drawCount : drawCount + 1; } if(drawCount > 0) { diff --git a/src/main/java/net/vulkanmod/render/chunk/RenderSection.java b/src/main/java/net/vulkanmod/render/chunk/RenderSection.java index a34b836a3..373fc17e0 100644 --- a/src/main/java/net/vulkanmod/render/chunk/RenderSection.java +++ b/src/main/java/net/vulkanmod/render/chunk/RenderSection.java @@ -26,6 +26,7 @@ public class RenderSection { private final RenderSection[] neighbours = new RenderSection[6]; public byte frustumIndex; private short lastFrame = -1; + private short lastFrame2 = -1; private final CompileStatus compileStatus = new CompileStatus(); @@ -45,9 +46,9 @@ public class RenderSection { //Graph-info public Direction mainDir; - byte directions; - byte step; - byte directionChanges; + public byte directions; + public byte step; + public byte directionChanges; byte sourceDirs; @@ -283,10 +284,22 @@ public void setCompiledSection(CompiledSection compiledSection) { public boolean setLastFrame(short i) { boolean res = i == this.lastFrame ; - if(!res) this.lastFrame = i; + if(!res) + this.lastFrame = i; return res; } + public boolean setLastFrame2(short i) { + boolean res = i == this.lastFrame2 ; + if(!res) + this.lastFrame2 = i; + return res; + } + + public short getLastFrame() { + return this.lastFrame; + } + static class CompileStatus { CompiledSection compiledSection = CompiledSection.UNCOMPILED; ChunkTask.BuildTask rebuildTask; diff --git a/src/main/java/net/vulkanmod/render/chunk/SectionGrid.java b/src/main/java/net/vulkanmod/render/chunk/SectionGrid.java index 56634ca93..d14b6f9d0 100644 --- a/src/main/java/net/vulkanmod/render/chunk/SectionGrid.java +++ b/src/main/java/net/vulkanmod/render/chunk/SectionGrid.java @@ -353,15 +353,19 @@ public void setDirty(int sectionX, int sectionY, int sectionZ, boolean p_110863_ } @Nullable - public RenderSection getRenderSectionAt(BlockPos blockPos) { - int i = blockPos.getX() >> 4; - int j = (blockPos.getY() - this.level.getMinBuildHeight()) >> 4; - int k = blockPos.getZ() >> 4; + public RenderSection getSectionAtBlockPos(BlockPos blockPos) { + return this.getSectionAtBlockPos(blockPos.getX(), blockPos.getY(), blockPos.getZ()); + } + + public RenderSection getSectionAtBlockPos(int x, int y, int z) { + int i = x >> 4; + int j = (y - this.level.getMinBuildHeight()) >> 4; + int k = z >> 4; - return this.getRenderSectionAt(i, j, k); + return this.getSectionAtSectionPos(i, j, k); } - public RenderSection getRenderSectionAt(int i, int j, int k) { + public RenderSection getSectionAtSectionPos(int i, int j, int k) { if (j >= 0 && j < this.gridHeight) { i = Math.floorMod(i, this.gridWidth); k = Math.floorMod(k, this.gridWidth); diff --git a/src/main/java/net/vulkanmod/render/chunk/VFrustum.java b/src/main/java/net/vulkanmod/render/chunk/VFrustum.java index b03066e96..9984e63ec 100644 --- a/src/main/java/net/vulkanmod/render/chunk/VFrustum.java +++ b/src/main/java/net/vulkanmod/render/chunk/VFrustum.java @@ -1,5 +1,6 @@ package net.vulkanmod.render.chunk; +import net.minecraft.world.phys.AABB; import org.joml.FrustumIntersection; import org.joml.Matrix4f; import org.joml.Vector4f; @@ -30,7 +31,7 @@ public VFrustum offsetToFullyIncludeCameraCube(int offset) { return this; } - public void prepare(double camX, double camY, double camZ) { + public void setCamOffset(double camX, double camY, double camZ) { this.camX = camX; this.camY = camY; this.camZ = camZ; @@ -56,4 +57,18 @@ public int cubeInFrustum(float x1, float y1, float z1, float x2, float y2, float private int intersectAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { return this.frustum.intersectAab(minX, minY, minZ, maxX, maxY, maxZ); } + + public boolean isVisible(AABB aABB) { + return this.cubeInFrustum(aABB.minX, aABB.minY, aABB.minZ, aABB.maxX, aABB.maxY, aABB.maxZ); + } + + private boolean cubeInFrustum(double d, double e, double f, double g, double h, double i) { + float j = (float)(d - this.camX); + float k = (float)(e - this.camY); + float l = (float)(f - this.camZ); + float m = (float)(g - this.camX); + float n = (float)(h - this.camY); + float o = (float)(i - this.camZ); + return this.frustum.testAab(j, k, l, m, n, o); + } } diff --git a/src/main/java/net/vulkanmod/render/chunk/WorldRenderer.java b/src/main/java/net/vulkanmod/render/chunk/WorldRenderer.java index 799811788..6826c52b0 100644 --- a/src/main/java/net/vulkanmod/render/chunk/WorldRenderer.java +++ b/src/main/java/net/vulkanmod/render/chunk/WorldRenderer.java @@ -3,7 +3,10 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.*; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.SheetedDecalTextureGenerator; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.blaze3d.vertex.VertexMultiConsumer; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.client.Camera; @@ -27,15 +30,16 @@ import net.vulkanmod.interfaces.FrustumMixed; import net.vulkanmod.render.chunk.build.ChunkTask; import net.vulkanmod.render.chunk.build.TaskDispatcher; -import net.vulkanmod.render.profiling.Profiler; -import net.vulkanmod.render.profiling.Profiler2; import net.vulkanmod.render.chunk.util.AreaSetQueue; import net.vulkanmod.render.chunk.util.ResettableQueue; import net.vulkanmod.render.chunk.util.Util; +import net.vulkanmod.render.profiling.Profiler; +import net.vulkanmod.render.profiling.Profiler2; import net.vulkanmod.render.vertex.TerrainRenderType; -import net.vulkanmod.vulkan.Drawer; +import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.VRenderSystem; import net.vulkanmod.vulkan.Vulkan; +import net.vulkanmod.vulkan.memory.Buffer; import net.vulkanmod.vulkan.memory.IndirectBuffer; import net.vulkanmod.vulkan.memory.MemoryTypes; import net.vulkanmod.vulkan.shader.Pipeline; @@ -84,7 +88,7 @@ public class WorldRenderer { IndirectBuffer[] indirectBuffers; // UniformBuffers uniformBuffers; - RenderRegionCache renderRegionCache; + public RenderRegionCache renderRegionCache; int nonEmptyChunks; private WorldRenderer(RenderBuffers renderBuffers) { @@ -92,10 +96,19 @@ private WorldRenderer(RenderBuffers renderBuffers) { this.renderBuffers = renderBuffers; this.taskDispatcher = new TaskDispatcher(); ChunkTask.setTaskDispatcher(this.taskDispatcher); + allocateIndirectBuffers(); + + Renderer.getInstance().addOnResizeCallback(() -> { + if(this.indirectBuffers.length != Vulkan.getSwapChain().getFramesNum()) + allocateIndirectBuffers(); + }); } private void allocateIndirectBuffers() { - this.indirectBuffers = new IndirectBuffer[Vulkan.getSwapChainImages().size()]; + if(this.indirectBuffers != null) + Arrays.stream(this.indirectBuffers).forEach(Buffer::freeBuffer); + + this.indirectBuffers = new IndirectBuffer[Vulkan.getSwapChain().getFramesNum()]; for(int i = 0; i < this.indirectBuffers.length; ++i) { this.indirectBuffers[i] = new IndirectBuffer(1000000, MemoryTypes.HOST_MEM); @@ -218,7 +231,7 @@ public void setupRenderer(Camera camera, Frustum frustum, boolean isCapturedFrus // p.round(); } - this.indirectBuffers[Drawer.getCurrentFrame()].reset(); + this.indirectBuffers[Renderer.getCurrentFrame()].reset(); // this.uniformBuffers.reset(); this.minecraft.getProfiler().pop(); @@ -229,7 +242,7 @@ private void initializeQueueForFullUpdate(Camera camera) { int i = 16; Vec3 vec3 = camera.getPosition(); BlockPos blockpos = camera.getBlockPosition(); - RenderSection renderSection = this.sectionGrid.getRenderSectionAt(blockpos); + RenderSection renderSection = this.sectionGrid.getSectionAtBlockPos(blockpos); if (renderSection == null) { boolean flag = blockpos.getY() > this.level.getMinBuildHeight(); @@ -242,7 +255,7 @@ private void initializeQueueForFullUpdate(Camera camera) { for(int i1 = -this.lastViewDistance; i1 <= this.lastViewDistance; ++i1) { for(int j1 = -this.lastViewDistance; j1 <= this.lastViewDistance; ++j1) { - RenderSection renderSection1 = this.sectionGrid.getRenderSectionAt(new BlockPos(k + SectionPos.sectionToBlockCoord(i1, 8), j, l + SectionPos.sectionToBlockCoord(j1, 8))); + RenderSection renderSection1 = this.sectionGrid.getSectionAtBlockPos(new BlockPos(k + SectionPos.sectionToBlockCoord(i1, 8), j, l + SectionPos.sectionToBlockCoord(j1, 8))); if (renderSection1 != null) { renderSection1.setGraphInfo(null, (byte) 0); list.add(renderSection1); @@ -374,7 +387,6 @@ private void addNode(RenderSection renderSection, RenderSection relativeChunk, D relativeChunk.directionChanges = (byte) d; } - else if (relativeChunk.getChunkArea().inFrustum(relativeChunk.frustumIndex) < 0 ) { if(relativeChunk.getChunkArea().inFrustum(relativeChunk.frustumIndex) == FrustumIntersection.INTERSECT) { @@ -453,7 +465,7 @@ public void compileChunks(Camera camera) { } public boolean isChunkCompiled(BlockPos blockPos) { - RenderSection renderSection = this.sectionGrid.getRenderSectionAt(blockPos); + RenderSection renderSection = this.sectionGrid.getSectionAtBlockPos(blockPos); return renderSection != null && renderSection.isCompiled(); } @@ -480,14 +492,6 @@ public void allChanged() { this.sectionGrid = new SectionGrid(this.level, this.minecraft.options.getEffectiveRenderDistance()); this.chunkAreaQueue = new AreaSetQueue(this.sectionGrid.chunkAreaManager.size); - if(this.indirectBuffers != null) { - for (IndirectBuffer buffer : this.indirectBuffers) { - buffer.freeBuffer(); - } - } - - this.allocateIndirectBuffers(); - Entity entity = this.minecraft.getCameraEntity(); if (entity != null) { this.sectionGrid.repositionCamera(entity.getX(), entity.getZ()); @@ -569,10 +573,10 @@ else if(layerName.equals("translucent")) VRenderSystem.applyMVP(poseStack.last().pose(), projection); - Drawer drawer = Drawer.getInstance(); - Pipeline pipeline = ShaderManager.getInstance().getTerrainShader(); - drawer.bindPipeline(pipeline); - drawer.bindAutoIndexBuffer(Drawer.getCommandBuffer(), 7); + Renderer renderer = Renderer.getInstance(); + Pipeline pipeline = ShaderManager.getInstance().getTerrainShader(renderType); + renderer.bindPipeline(pipeline); + Renderer.getDrawer().bindAutoIndexBuffer(Renderer.getCommandBuffer(), 7); p.push("draw batches"); @@ -589,15 +593,15 @@ else if(layerName.equals("translucent")) ChunkArea chunkArea = iterator.next(); if(indirectDraw) { - chunkArea.getDrawBuffers().buildDrawBatchesIndirect(indirectBuffers[Drawer.getCurrentFrame()], chunkArea, renderType, camX, camY, camZ); + chunkArea.getDrawBuffers().buildDrawBatchesIndirect(indirectBuffers[Renderer.getCurrentFrame()], chunkArea, renderType, camX, camY, camZ); } else { - chunkArea.getDrawBuffers().buildDrawBatchesDirect(chunkArea, renderType, camX, camY, camZ); + chunkArea.getDrawBuffers().buildDrawBatchesDirect(chunkArea.sectionQueue, pipeline, renderType, camX, camY, camZ); } } } if(layerName.equals("cutout") || layerName.equals("tripwire")) { - indirectBuffers[Drawer.getCurrentFrame()].submitUploads(); + indirectBuffers[Renderer.getCurrentFrame()].submitUploads(); // uniformBuffers.submitUploads(); } p.pop(); @@ -605,7 +609,7 @@ else if(layerName.equals("translucent")) //Need to reset push constant in case the pipeline will still be used for rendering if(!indirectDraw) { VRenderSystem.setChunkOffset(0, 0, 0); - drawer.pushConstants(pipeline); + renderer.pushConstants(pipeline); } this.minecraft.getProfiler().pop(); @@ -706,10 +710,20 @@ public void setSectionsLightReady(int x, int z) { // this.needsUpdate = true; } + public SectionGrid getSectionGrid() { + return this.sectionGrid; + } + public ChunkAreaManager getChunkAreaManager() { return this.sectionGrid.chunkAreaManager; } + public TaskDispatcher getTaskDispatcher() { return taskDispatcher; } + + public VFrustum getFrustum() { return this.frustum; } + + public short getLastFrame() { return lastFrame; } + public String getChunkStatistics() { int i = this.sectionGrid.chunks.length; // int j = this.sectionsInFrustum.size(); diff --git a/src/main/java/net/vulkanmod/render/chunk/build/LiquidRenderer.java b/src/main/java/net/vulkanmod/render/chunk/build/LiquidRenderer.java new file mode 100644 index 000000000..f68691121 --- /dev/null +++ b/src/main/java/net/vulkanmod/render/chunk/build/LiquidRenderer.java @@ -0,0 +1,418 @@ +package net.vulkanmod.render.chunk.build; + +import com.mojang.blaze3d.vertex.VertexConsumer; +import java.util.Iterator; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BiomeColors; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.ModelBakery; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.tags.FluidTags; +import net.minecraft.util.Mth; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.HalfTransparentBlock; +import net.minecraft.world.level.block.LeavesBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.vulkanmod.vulkan.util.VUtil; +import org.joml.Vector3f; + +@Environment(EnvType.CLIENT) +public class LiquidRenderer { + private static final float MAX_FLUID_HEIGHT = 0.8888889F; + private final TextureAtlasSprite[] lavaIcons = new TextureAtlasSprite[2]; + private final TextureAtlasSprite[] waterIcons = new TextureAtlasSprite[2]; + private TextureAtlasSprite waterOverlay; + + public void setupSprites() { + this.lavaIcons[0] = Minecraft.getInstance().getModelManager().getBlockModelShaper().getBlockModel(Blocks.LAVA.defaultBlockState()).getParticleIcon(); + this.lavaIcons[1] = ModelBakery.LAVA_FLOW.sprite(); + this.waterIcons[0] = Minecraft.getInstance().getModelManager().getBlockModelShaper().getBlockModel(Blocks.WATER.defaultBlockState()).getParticleIcon(); + this.waterIcons[1] = ModelBakery.WATER_FLOW.sprite(); + this.waterOverlay = ModelBakery.WATER_OVERLAY.sprite(); + } + + private static boolean isNeighborSameFluid(FluidState fluidState, FluidState fluidState2) { + return fluidState2.getType().isSame(fluidState.getType()); + } + + private static boolean isFaceOccludedByState(BlockGetter blockGetter, Direction direction, float f, BlockPos blockPos, BlockState blockState) { + if (blockState.canOcclude()) { + VoxelShape voxelShape = Shapes.box(0.0, 0.0, 0.0, 1.0, f, 1.0); + VoxelShape voxelShape2 = blockState.getOcclusionShape(blockGetter, blockPos); + return Shapes.blockOccudes(voxelShape, voxelShape2, direction); + } else { + return false; + } + } + + private static boolean isFaceOccludedByNeighbor(BlockGetter blockGetter, BlockPos blockPos, Direction direction, float f, BlockState blockState) { + return isFaceOccludedByState(blockGetter, direction, f, blockPos.relative(direction), blockState); + } + + private static boolean isFaceOccludedBySelf(BlockGetter blockGetter, BlockPos blockPos, BlockState blockState, Direction direction) { + return isFaceOccludedByState(blockGetter, direction.getOpposite(), 1.0F, blockPos, blockState); + } + + public static boolean shouldRenderFace(BlockAndTintGetter blockAndTintGetter, BlockPos blockPos, FluidState fluidState, BlockState blockState, Direction direction, FluidState fluidState2) { + return !isFaceOccludedBySelf(blockAndTintGetter, blockPos, blockState, direction) && !isNeighborSameFluid(fluidState, fluidState2); + } + + public void tessellate(BlockAndTintGetter blockAndTintGetter, BlockPos blockPos, VertexConsumer vertexConsumer, BlockState blockState, FluidState fluidState) { + boolean bl = fluidState.is(FluidTags.LAVA); + TextureAtlasSprite[] textureAtlasSprites = bl ? this.lavaIcons : this.waterIcons; + int i = bl ? 16777215 : BiomeColors.getAverageWaterColor(blockAndTintGetter, blockPos); + float f = (float)(i >> 16 & 255) / 255.0F; + float g = (float)(i >> 8 & 255) / 255.0F; + float h = (float)(i & 255) / 255.0F; + + BlockState blockState2 = blockAndTintGetter.getBlockState(blockPos.relative(Direction.DOWN)); + FluidState fluidState2 = blockState2.getFluidState(); + BlockState blockState3 = blockAndTintGetter.getBlockState(blockPos.relative(Direction.UP)); + FluidState fluidState3 = blockState3.getFluidState(); + BlockState blockState4 = blockAndTintGetter.getBlockState(blockPos.relative(Direction.NORTH)); + FluidState fluidState4 = blockState4.getFluidState(); + BlockState blockState5 = blockAndTintGetter.getBlockState(blockPos.relative(Direction.SOUTH)); + FluidState fluidState5 = blockState5.getFluidState(); + BlockState blockState6 = blockAndTintGetter.getBlockState(blockPos.relative(Direction.WEST)); + FluidState fluidState6 = blockState6.getFluidState(); + BlockState blockState7 = blockAndTintGetter.getBlockState(blockPos.relative(Direction.EAST)); + FluidState fluidState7 = blockState7.getFluidState(); + + boolean bl2 = !isNeighborSameFluid(fluidState, fluidState3); + boolean renderDownFace = shouldRenderFace(blockAndTintGetter, blockPos, fluidState, blockState, Direction.DOWN, fluidState2) && !isFaceOccludedByNeighbor(blockAndTintGetter, blockPos, Direction.DOWN, 0.8888889F, blockState2); + boolean bl4 = shouldRenderFace(blockAndTintGetter, blockPos, fluidState, blockState, Direction.NORTH, fluidState4); + boolean bl5 = shouldRenderFace(blockAndTintGetter, blockPos, fluidState, blockState, Direction.SOUTH, fluidState5); + boolean bl6 = shouldRenderFace(blockAndTintGetter, blockPos, fluidState, blockState, Direction.WEST, fluidState6); + boolean bl7 = shouldRenderFace(blockAndTintGetter, blockPos, fluidState, blockState, Direction.EAST, fluidState7); + + if (bl2 || renderDownFace || bl7 || bl6 || bl4 || bl5) + { + float j = blockAndTintGetter.getShade(Direction.DOWN, true); + float k = blockAndTintGetter.getShade(Direction.UP, true); + float l = blockAndTintGetter.getShade(Direction.NORTH, true); + float m = blockAndTintGetter.getShade(Direction.WEST, true); + Fluid fluid = fluidState.getType(); + float n = this.getHeight(blockAndTintGetter, fluid, blockPos, blockState, fluidState); + float o; + float p; + float q; + float r; + if (n >= 1.0F) { + o = 1.0F; + p = 1.0F; + q = 1.0F; + r = 1.0F; + } else { + float s = this.getHeight(blockAndTintGetter, fluid, blockPos.north(), blockState4, fluidState4); + float t = this.getHeight(blockAndTintGetter, fluid, blockPos.south(), blockState5, fluidState5); + float u = this.getHeight(blockAndTintGetter, fluid, blockPos.east(), blockState7, fluidState7); + float v = this.getHeight(blockAndTintGetter, fluid, blockPos.west(), blockState6, fluidState6); + o = this.calculateAverageHeight(blockAndTintGetter, fluid, n, s, u, blockPos.relative(Direction.NORTH).relative(Direction.EAST)); + p = this.calculateAverageHeight(blockAndTintGetter, fluid, n, s, v, blockPos.relative(Direction.NORTH).relative(Direction.WEST)); + q = this.calculateAverageHeight(blockAndTintGetter, fluid, n, t, u, blockPos.relative(Direction.SOUTH).relative(Direction.EAST)); + r = this.calculateAverageHeight(blockAndTintGetter, fluid, n, t, v, blockPos.relative(Direction.SOUTH).relative(Direction.WEST)); + } + + double x0 = (blockPos.getX() & 15); + double y0 = (blockPos.getY() & 15); + double z0 = (blockPos.getZ() & 15); + float x = 0.001F; + float y = renderDownFace ? 0.001F : 0.0F; + float z; + float ab; + float ad; + float af; + float aa; + float ac; + float ae; + float ag; + + if (bl2 && !isFaceOccludedByNeighbor(blockAndTintGetter, blockPos, Direction.UP, Math.min(Math.min(p, r), Math.min(q, o)), blockState3)) { + p -= 0.001F; + r -= 0.001F; + q -= 0.001F; + o -= 0.001F; + Vec3 vec3 = fluidState.getFlow(blockAndTintGetter, blockPos); + TextureAtlasSprite textureAtlasSprite; + float ah; + float ai; + float r1; + if (vec3.x == 0.0 && vec3.z == 0.0) { + textureAtlasSprite = textureAtlasSprites[0]; + z = textureAtlasSprite.getU(0.0); + aa = textureAtlasSprite.getV(0.0); + ab = z; + ac = textureAtlasSprite.getV(16.0); + ad = textureAtlasSprite.getU(16.0); + ae = ac; + af = ad; + ag = aa; + } else { + textureAtlasSprite = textureAtlasSprites[1]; + ah = (float)Mth.atan2(vec3.z, vec3.x) - 1.5707964F; + ai = Mth.sin(ah) * 0.25F; + float aj = Mth.cos(ah) * 0.25F; + r1 = 8.0F; + z = textureAtlasSprite.getU((8.0F + (-aj - ai) * 16.0F)); + aa = textureAtlasSprite.getV((8.0F + (-aj + ai) * 16.0F)); + ab = textureAtlasSprite.getU((8.0F + (-aj + ai) * 16.0F)); + ac = textureAtlasSprite.getV((8.0F + (aj + ai) * 16.0F)); + ad = textureAtlasSprite.getU((8.0F + (aj + ai) * 16.0F)); + ae = textureAtlasSprite.getV((8.0F + (aj - ai) * 16.0F)); + af = textureAtlasSprite.getU((8.0F + (aj - ai) * 16.0F)); + ag = textureAtlasSprite.getV((8.0F + (-aj - ai) * 16.0F)); + } + + float al = (z + ab + ad + af) / 4.0F; + ah = (aa + ac + ae + ag) / 4.0F; + ai = textureAtlasSprites[0].uvShrinkRatio(); + z = Mth.lerp(ai, z, al); + ab = Mth.lerp(ai, ab, al); + ad = Mth.lerp(ai, ad, al); + af = Mth.lerp(ai, af, al); + aa = Mth.lerp(ai, aa, ah); + ac = Mth.lerp(ai, ac, ah); + ae = Mth.lerp(ai, ae, ah); + ag = Mth.lerp(ai, ag, ah); + int am = this.getLightColor(blockAndTintGetter, blockPos); + r1 = k * f; + float g1 = k * g; + float b1 = k * h; + +// this.vertex(vertexConsumer, x0 + 0.0, y0 + (double)p, z0 + 0.0, r1, g1, b1, z, aa, am); +// this.vertex(vertexConsumer, x0 + 0.0, y0 + (double)r, z0 + 1.0, r1, g1, b1, ab, ac, am); +// this.vertex(vertexConsumer, x0 + 1.0, y0 + (double)q, z0 + 1.0, r1, g1, b1, ad, ae, am); +// this.vertex(vertexConsumer, x0 + 1.0, y0 + (double)o, z0 + 0.0, r1, g1, b1, af, ag, am); +// if (fluidState.shouldRenderBackwardUpFace(blockAndTintGetter, blockPos.above())) { +// this.vertex(vertexConsumer, x0 + 0.0, y0 + (double)p, z0 + 0.0, r1, g1, b1, z, aa, am); +// this.vertex(vertexConsumer, x0 + 1.0, y0 + (double)o, z0 + 0.0, r1, g1, b1, af, ag, am); +// this.vertex(vertexConsumer, x0 + 1.0, y0 + (double)q, z0 + 1.0, r1, g1, b1, ad, ae, am); +// this.vertex(vertexConsumer, x0 + 0.0, y0 + (double)r, z0 + 1.0, r1, g1, b1, ab, ac, am); +// } + + Vector3f normal = new Vector3f(0.0f, r - p, 1.0f).cross(1.0f, q - p, 1.0f); + normal.normalize(); + + this.vertex(vertexConsumer, x0 + 0.0, y0 + (double)p, z0 + 0.0, r1, g1, b1, z, aa, am, normal.x(), normal.y(), normal.z()); + this.vertex(vertexConsumer, x0 + 0.0, y0 + (double)r, z0 + 1.0, r1, g1, b1, ab, ac, am, normal.x(), normal.y(), normal.z()); + this.vertex(vertexConsumer, x0 + 1.0, y0 + (double)q, z0 + 1.0, r1, g1, b1, ad, ae, am, normal.x(), normal.y(), normal.z()); + this.vertex(vertexConsumer, x0 + 1.0, y0 + (double)o, z0 + 0.0, r1, g1, b1, af, ag, am, normal.x(), normal.y(), normal.z()); + if (fluidState.shouldRenderBackwardUpFace(blockAndTintGetter, blockPos.above())) { + this.vertex(vertexConsumer, x0 + 0.0, y0 + (double)p, z0 + 0.0, r1, g1, b1, z, aa, am, normal.x(), normal.y(), normal.z()); + this.vertex(vertexConsumer, x0 + 1.0, y0 + (double)o, z0 + 0.0, r1, g1, b1, af, ag, am, normal.x(), normal.y(), normal.z()); + this.vertex(vertexConsumer, x0 + 1.0, y0 + (double)q, z0 + 1.0, r1, g1, b1, ad, ae, am, normal.x(), normal.y(), normal.z()); + this.vertex(vertexConsumer, x0 + 0.0, y0 + (double)r, z0 + 1.0, r1, g1, b1, ab, ac, am, normal.x(), normal.y(), normal.z()); + } + } + + if (renderDownFace) { + z = textureAtlasSprites[0].getU0(); + ab = textureAtlasSprites[0].getU1(); + ad = textureAtlasSprites[0].getV0(); + af = textureAtlasSprites[0].getV1(); + int ap = this.getLightColor(blockAndTintGetter, blockPos.below()); + ac = j * f; + ae = j * g; + ag = j * h; + +// this.vertex(vertexConsumer, x0, y0 + (double)y, z0 + 1.0, ac, ae, ag, z, af, ap); +// this.vertex(vertexConsumer, x0, y0 + (double)y, z0, ac, ae, ag, z, ad, ap); +// this.vertex(vertexConsumer, x0 + 1.0, y0 + (double)y, z0, ac, ae, ag, ab, ad, ap); +// this.vertex(vertexConsumer, x0 + 1.0, y0 + (double)y, z0 + 1.0, ac, ae, ag, ab, af, ap); + + Vector3f normal = new Vector3f(0.0f, 0.0f, -1.0f).cross(1.0f, 0.0f, -1.0f); + normal.normalize(); + + this.vertex(vertexConsumer, x0, y0 + (double)y, z0 + 1.0, ac, ae, ag, z, af, ap, normal.x(), normal.y(), normal.z()); + this.vertex(vertexConsumer, x0, y0 + (double)y, z0, ac, ae, ag, z, ad, ap, normal.x(), normal.y(), normal.z()); + this.vertex(vertexConsumer, x0 + 1.0, y0 + (double)y, z0, ac, ae, ag, ab, ad, ap, normal.x(), normal.y(), normal.z()); + this.vertex(vertexConsumer, x0 + 1.0, y0 + (double)y, z0 + 1.0, ac, ae, ag, ab, af, ap,normal.x(), normal.y(), normal.z()); + } + + int aq = this.getLightColor(blockAndTintGetter, blockPos); + Iterator var76 = Direction.Plane.HORIZONTAL.iterator(); + + while(true) { + Direction direction; + double ar; + double at; + double as; + double au; + boolean bl8; + do { + do { + if (!var76.hasNext()) { + return; + } + + direction = var76.next(); + switch (direction) { + case NORTH -> { + af = p; + aa = o; + ar = x0; + as = x0 + 1.0; + at = z0 + 0.0010000000474974513; + au = z0 + 0.0010000000474974513; + bl8 = bl4; + } + case SOUTH -> { + af = q; + aa = r; + ar = x0 + 1.0; + as = x0; + at = z0 + 1.0 - 0.0010000000474974513; + au = z0 + 1.0 - 0.0010000000474974513; + bl8 = bl5; + } + case WEST -> { + af = r; + aa = p; + ar = x0 + 0.0010000000474974513; + as = x0 + 0.0010000000474974513; + at = z0 + 1.0; + au = z0; + bl8 = bl6; + } + default -> { + af = o; + aa = q; + ar = x0 + 1.0 - 0.0010000000474974513; + as = x0 + 1.0 - 0.0010000000474974513; + at = z0; + au = z0 + 1.0; + bl8 = bl7; + } + } + } while(!bl8); + } while(isFaceOccludedByNeighbor(blockAndTintGetter, blockPos, direction, Math.max(af, aa), blockAndTintGetter.getBlockState(blockPos.relative(direction)))); + + BlockPos blockPos2 = blockPos.relative(direction); + TextureAtlasSprite textureAtlasSprite2 = textureAtlasSprites[1]; + if (!bl) { + Block block = blockAndTintGetter.getBlockState(blockPos2).getBlock(); + if (block instanceof HalfTransparentBlock || block instanceof LeavesBlock) { + textureAtlasSprite2 = this.waterOverlay; + } + } + + float av = textureAtlasSprite2.getU(0.0); + float aw = textureAtlasSprite2.getU(8.0); + float ax = textureAtlasSprite2.getV((double)((1.0F - af) * 16.0F * 0.5F)); + float ay = textureAtlasSprite2.getV((double)((1.0F - aa) * 16.0F * 0.5F)); + float az = textureAtlasSprite2.getV(8.0); + float ba = direction.getAxis() == Direction.Axis.Z ? l : m; + float bb = k * ba * f; + float bc = k * ba * g; + float bd = k * ba * h; + +// this.vertex(vertexConsumer, ar, y0 + (double)af, at, bb, bc, bd, av, ax, aq); +// this.vertex(vertexConsumer, as, y0 + (double)aa, au, bb, bc, bd, aw, ay, aq); +// this.vertex(vertexConsumer, as, y0 + (double)y, au, bb, bc, bd, aw, az, aq); +// this.vertex(vertexConsumer, ar, y0 + (double)y, at, bb, bc, bd, av, az, aq); +// if (textureAtlasSprite2 != this.waterOverlay) { +// this.vertex(vertexConsumer, ar, y0 + (double)y, at, bb, bc, bd, av, az, aq); +// this.vertex(vertexConsumer, as, y0 + (double)y, au, bb, bc, bd, aw, az, aq); +// this.vertex(vertexConsumer, as, y0 + (double)aa, au, bb, bc, bd, aw, ay, aq); +// this.vertex(vertexConsumer, ar, y0 + (double)af, at, bb, bc, bd, av, ax, aq); +// } + + Vector3f normal = new Vector3f((float) (as - ar), (aa - af), (float) (au - at)).cross((float) (as - ar), (y - af), (float) (au - at)); + normal.normalize(); + + this.vertex(vertexConsumer, ar, y0 + (double)af, at, bb, bc, bd, av, ax, aq, normal.x(), normal.y(), normal.z()); + this.vertex(vertexConsumer, as, y0 + (double)aa, au, bb, bc, bd, aw, ay, aq, normal.x(), normal.y(), normal.z()); + this.vertex(vertexConsumer, as, y0 + (double)y, au, bb, bc, bd, aw, az, aq, normal.x(), normal.y(), normal.z()); + this.vertex(vertexConsumer, ar, y0 + (double)y, at, bb, bc, bd, av, az, aq, normal.x(), normal.y(), normal.z()); + if (textureAtlasSprite2 != this.waterOverlay) { + this.vertex(vertexConsumer, ar, y0 + (double)y, at, bb, bc, bd, av, az, aq); + this.vertex(vertexConsumer, as, y0 + (double)y, au, bb, bc, bd, aw, az, aq); + this.vertex(vertexConsumer, as, y0 + (double)aa, au, bb, bc, bd, aw, ay, aq); + this.vertex(vertexConsumer, ar, y0 + (double)af, at, bb, bc, bd, av, ax, aq); + } + } + } + } + + private float calculateAverageHeight(BlockAndTintGetter blockAndTintGetter, Fluid fluid, float f, float g, float h, BlockPos blockPos) { + if (!(h >= 1.0F) && !(g >= 1.0F)) { + float[] fs = new float[2]; + if (h > 0.0F || g > 0.0F) { + float i = this.getHeight(blockAndTintGetter, fluid, blockPos); + if (i >= 1.0F) { + return 1.0F; + } + + this.addWeightedHeight(fs, i); + } + + this.addWeightedHeight(fs, f); + this.addWeightedHeight(fs, h); + this.addWeightedHeight(fs, g); + return fs[0] / fs[1]; + } else { + return 1.0F; + } + } + + private void addWeightedHeight(float[] fs, float f) { + if (f >= 0.8F) { + fs[0] += f * 10.0F; + fs[1] += 10.0F; + } else if (f >= 0.0F) { + fs[0] += f; + fs[1]++; + } + + } + + private float getHeight(BlockAndTintGetter blockAndTintGetter, Fluid fluid, BlockPos blockPos) { + BlockState blockState = blockAndTintGetter.getBlockState(blockPos); + return this.getHeight(blockAndTintGetter, fluid, blockPos, blockState, blockState.getFluidState()); + } + + private float getHeight(BlockAndTintGetter blockAndTintGetter, Fluid fluid, BlockPos blockPos, BlockState blockState, FluidState fluidState) { + if (fluid.isSame(fluidState.getType())) { + BlockState blockState2 = blockAndTintGetter.getBlockState(blockPos.above()); + return fluid.isSame(blockState2.getFluidState().getType()) ? 1.0F : fluidState.getOwnHeight(); + } else { + return !blockState.isSolid() ? 0.0F : -1.0F; + } + } + + private void vertex(VertexConsumer vertexConsumer, double x, double y, double z, float r, float g, float b, float u, float v, int l) { +// vertexConsumer.vertex(x, y, z).color(r, g, b, 1.0F).uv(u, v).uv2(l).normal(0.0F, 1.0F, 0.0F).endVertex(); + vertexConsumer.vertex((float) x, (float) y, (float) z, r, g, b, 1.0f, u, v, 0, l, 0.0F, 1.0F, 0.0F); + } + + private void vertex(VertexConsumer vertexConsumer, double x, double y, double z, float r, float g, float b, float u, float v, int l, float normalX, float normalY, float normalZ) { +// vertexConsumer.vertex(x, y, z).color(r, g, b, 1.0F).uv(u, v).uv2(l).normal(0.0F, 1.0F, 0.0F).endVertex(); + vertexConsumer.vertex((float) x, (float) y, (float) z, r, g, b, 1.0f, u, v, 0, l, normalX, normalY, normalZ); + } + + private void putQuad() { + + } + + private int getLightColor(BlockAndTintGetter blockAndTintGetter, BlockPos blockPos) { + int i = LevelRenderer.getLightColor(blockAndTintGetter, blockPos); + int j = LevelRenderer.getLightColor(blockAndTintGetter, blockPos.above()); + int k = i & 255; + int l = j & 255; + int m = i >> 16 & 255; + int n = j >> 16 & 255; + return (Math.max(k, l)) | (Math.max(m, n)) << 16; + } +} diff --git a/src/main/java/net/vulkanmod/render/util/MathUtil.java b/src/main/java/net/vulkanmod/render/util/MathUtil.java new file mode 100644 index 000000000..99f26cbcb --- /dev/null +++ b/src/main/java/net/vulkanmod/render/util/MathUtil.java @@ -0,0 +1,20 @@ +package net.vulkanmod.render.util; + +public class MathUtil { + + public static float clamp(float min, float max, float x) { + return Math.min(Math.max(x, min), max); + } + + public static int clamp(int min, int max, int x) { + return Math.min(Math.max(x, min), max); + } + + public static float saturate(float x) { + return clamp(0.0f, 1.0f, x); + } + + public static float lerp(float v0, float v1, float t) { + return v0 + t * (v1 - v0); + } +} diff --git a/src/main/java/net/vulkanmod/render/vertex/TerrainBufferBuilder.java b/src/main/java/net/vulkanmod/render/vertex/TerrainBufferBuilder.java index fa11c1929..da40c704e 100644 --- a/src/main/java/net/vulkanmod/render/vertex/TerrainBufferBuilder.java +++ b/src/main/java/net/vulkanmod/render/vertex/TerrainBufferBuilder.java @@ -10,6 +10,7 @@ import net.minecraft.core.Vec3i; import net.minecraft.util.Mth; import net.vulkanmod.render.util.SortUtil; +import net.vulkanmod.vulkan.shader.ShaderManager; import org.apache.commons.lang3.mutable.MutableInt; import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; @@ -23,41 +24,45 @@ import java.util.function.IntConsumer; public class TerrainBufferBuilder implements VertexConsumer { - private static final float POS_CONV = 1900.0f; - private static final float UV_CONV = 65536.0f; - - private static final int GROWTH_SIZE = 2097152; - private static final Logger LOGGER = LogUtils.getLogger(); - - private ByteBuffer buffer; - private int renderedBufferCount; - private int renderedBufferPointer; - private int nextElementByte; - private int vertices; - @Nullable - private VertexFormatElement currentElement; - private int elementIndex; - private VertexFormat format; - private VertexFormat.Mode mode; - private boolean fastFormat; - private boolean fullFormat; - private boolean building; - @Nullable - private Vector3f[] sortingPoints; - private float sortX = Float.NaN; - private float sortY = Float.NaN; - private float sortZ = Float.NaN; - private boolean indexOnly; - - private long bufferPtr; + private static final float POS_CONV = 1900.0f; + private static final float UV_CONV = 65536.0f; + + private static final int GROWTH_SIZE = 2097152; + private static final Logger LOGGER = LogUtils.getLogger(); + + private ByteBuffer buffer; + private int renderedBufferCount; + private int renderedBufferPointer; + private int nextElementByte; + private int vertices; + @Nullable + private VertexFormatElement currentElement; + private int elementIndex; + private VertexFormat format; + private VertexFormat.Mode mode; + private boolean fastFormat; + private boolean fullFormat; + private boolean building; + @Nullable + private Vector3f[] sortingPoints; + private float sortX = Float.NaN; + private float sortY = Float.NaN; + private float sortZ = Float.NaN; + private boolean indexOnly; + + private long bufferPtr; // private long ptr; + VertexBuilder vertexBuilder; + public TerrainBufferBuilder(int i) { - this.buffer = MemoryTracker.create(i * 6); + this.buffer = MemoryTracker.create(i * 6); this.bufferPtr = MemoryUtil.memAddress0(this.buffer); - } - private void ensureVertexCapacity() { + this.vertexBuilder = ShaderManager.TERRAIN_VERTEX_FORMAT == CustomVertexFormat.COMPRESSED_TERRAIN ? new CompressedVertexBuilder() : new DefaultVertexBuilder(); + } + + private void ensureVertexCapacity() { this.ensureCapacity(this.format.getVertexSize()); } @@ -339,37 +344,50 @@ public void nextElement() { public void vertex(float x, float y, float z, float red, float green, float blue, float alpha, float u, float v, int overlay, int light, float normalX, float normalY, float normalZ) { // this.defaultVertex(x, y, z, red, green, blue, alpha, u, v, overlay, light, normalX, normalY, normalZ); - this.compressedVertex(x, y, z, red, green, blue, alpha, u, v, light); +// this.compressedVertex(x, y, z, red, green, blue, alpha, u, v, light); + this.vertexBuilder.vertex(x, y, z, red, green, blue, alpha, u, v, overlay, light, normalX, normalY, normalZ); } private void defaultVertex(float x, float y, float z, float red, float green, float blue, float alpha, float u, float v, int overlay, int light, float normalX, float normalY, float normalZ) { - this.putFloat(0, x); - this.putFloat(4, y); - this.putFloat(8, z); - this.putByte(12, (byte)((int)(red * 255.0F))); - this.putByte(13, (byte)((int)(green * 255.0F))); - this.putByte(14, (byte)((int)(blue * 255.0F))); - this.putByte(15, (byte)((int)(alpha * 255.0F))); - this.putFloat(16, u); - this.putFloat(20, v); - byte i; - i = 24; - - this.putShort(i, (short)(light & '\uffff')); - this.putShort(i + 2, (short)(light >> 16 & '\uffff')); - this.putByte(i + 4, BufferVertexConsumer.normalIntValue(normalX)); - this.putByte(i + 5, BufferVertexConsumer.normalIntValue(normalY)); - this.putByte(i + 6, BufferVertexConsumer.normalIntValue(normalZ)); - this.nextElementByte += i + 8; - this.endVertex(); + this.putFloat(0, x); + this.putFloat(4, y); + this.putFloat(8, z); + this.putByte(12, (byte)((int)(red * 255.0F))); + this.putByte(13, (byte)((int)(green * 255.0F))); + this.putByte(14, (byte)((int)(blue * 255.0F))); + this.putByte(15, (byte)((int)(alpha * 255.0F))); + this.putFloat(16, u); + this.putFloat(20, v); + byte i; + i = 24; + + this.putShort(i, (short)(light & '\uffff')); + this.putShort(i + 2, (short)(light >> 16 & '\uffff')); + this.putByte(i + 4, BufferVertexConsumer.normalIntValue(normalX)); + this.putByte(i + 5, BufferVertexConsumer.normalIntValue(normalY)); + this.putByte(i + 6, BufferVertexConsumer.normalIntValue(normalZ)); + this.nextElementByte += i + 8; + this.endVertex(); } private void compressedVertex(float x, float y, float z, float red, float green, float blue, float alpha, float u, float v, int light) { long ptr = this.bufferPtr + this.nextElementByte; - MemoryUtil.memPutShort(ptr + 0, (short) (x * POS_CONV)); - MemoryUtil.memPutShort(ptr + 2, (short) (y * POS_CONV)); - MemoryUtil.memPutShort(ptr + 4, (short) (z * POS_CONV)); + short sX = (short) (x * POS_CONV + 0.1f); + short sY = (short) (y * POS_CONV + 0.1f); + short sZ = (short) (z * POS_CONV + 0.1f); + + //Debug +// short x1 = (short) Math.round((x) * POS_CONV); +// float y1 = (short) Math.round((y) * POS_CONV); +// float z1 = (short) Math.round((z) * POS_CONV); +// +// if(x1 != sX || y1 != sY || z1 != sZ) +// System.nanoTime(); + + MemoryUtil.memPutShort(ptr + 0, sX); + MemoryUtil.memPutShort(ptr + 2, sY); + MemoryUtil.memPutShort(ptr + 4, sZ); int temp = VertexUtil.packColor(red, green, blue, alpha); MemoryUtil.memPutInt(ptr + 8, temp); @@ -589,4 +607,74 @@ public boolean sequentialIndex() { return this.sequentialIndex; } } + + interface VertexBuilder { + void vertex(float x, float y, float z, float red, float green, float blue, float alpha, float u, float v, int overlay, int light, float normalX, float normalY, float normalZ); + } + + class DefaultVertexBuilder implements VertexBuilder { + + public void vertex(float x, float y, float z, float red, float green, float blue, float alpha, float u, float v, int overlay, int light, float normalX, float normalY, float normalZ) { + putFloat(0, x); + putFloat(4, y); + putFloat(8, z); + putByte(12, (byte)((int)(red * 255.0F))); + putByte(13, (byte)((int)(green * 255.0F))); + putByte(14, (byte)((int)(blue * 255.0F))); + putByte(15, (byte)((int)(alpha * 255.0F))); + putFloat(16, u); + putFloat(20, v); + byte i; + i = 24; + + putShort(i, (short)(light & '\uffff')); + putShort(i + 2, (short)(light >> 16 & '\uffff')); + putByte(i + 4, BufferVertexConsumer.normalIntValue(normalX)); + putByte(i + 5, BufferVertexConsumer.normalIntValue(normalY)); + putByte(i + 6, BufferVertexConsumer.normalIntValue(normalZ)); + nextElementByte += i + 8; + endVertex(); + } + } + + class CompressedVertexBuilder implements VertexBuilder { + + public void vertex(float x, float y, float z, float red, float green, float blue, float alpha, float u, float v, int overlay, int light, float normalX, float normalY, float normalZ) { + long ptr = bufferPtr + nextElementByte; + + short sX = (short) (x * POS_CONV + 0.1f); + short sY = (short) (y * POS_CONV + 0.1f); + short sZ = (short) (z * POS_CONV + 0.1f); + + // short sX = (short) (x * 1.0001f * POS_CONV + 0.1f); + // short sY = (short) (y * 1.0001f * POS_CONV + 0.1f); + // short sZ = (short) (z * 1.0001f * POS_CONV + 0.1f); + // short sX = (short) (x * 0.99999999f * POS_CONV); + // short sY = (short) (y * 0.99999999f * POS_CONV); + // short sZ = (short) (z * 0.99999999f * POS_CONV); + + //Debug + // short x1 = (short) Math.round((x) * POS_CONV); + // float y1 = (short) Math.round((y) * POS_CONV); + // float z1 = (short) Math.round((z) * POS_CONV); + // + // if(x1 != sX || y1 != sY || z1 != sZ) + // System.nanoTime(); + + MemoryUtil.memPutShort(ptr + 0, sX); + MemoryUtil.memPutShort(ptr + 2, sY); + MemoryUtil.memPutShort(ptr + 4, sZ); + + int temp = VertexUtil.packColor(red, green, blue, alpha); + MemoryUtil.memPutInt(ptr + 8, temp); + + MemoryUtil.memPutShort(ptr + 12, (short) (u * UV_CONV)); + MemoryUtil.memPutShort(ptr + 14, (short) (v * UV_CONV)); + + MemoryUtil.memPutInt(ptr + 16, light); + + nextElementByte += 20; + endVertex(); + } + } } diff --git a/src/main/java/net/vulkanmod/vulkan/Device.java b/src/main/java/net/vulkanmod/vulkan/Device.java new file mode 100644 index 000000000..9ed864cf5 --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/Device.java @@ -0,0 +1,326 @@ +package net.vulkanmod.vulkan; + +import net.vulkanmod.Initializer; +import net.vulkanmod.vulkan.queue.Queue; +import org.lwjgl.PointerBuffer; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.vulkan.*; + +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.Set; + +import static java.util.stream.Collectors.toSet; +import static net.vulkanmod.vulkan.queue.Queue.findQueueFamilies; +import static net.vulkanmod.vulkan.util.VUtil.asPointerBuffer; +import static org.lwjgl.glfw.GLFWVulkan.glfwGetRequiredInstanceExtensions; +import static org.lwjgl.system.MemoryStack.stackGet; +import static org.lwjgl.system.MemoryStack.stackPush; +import static org.lwjgl.vulkan.EXTDebugUtils.VK_EXT_DEBUG_UTILS_EXTENSION_NAME; +import static org.lwjgl.vulkan.KHRSurface.*; +import static org.lwjgl.vulkan.VK10.*; +import static org.lwjgl.vulkan.VK12.VK_API_VERSION_1_2; + +public class Device { + + public static VkPhysicalDevice physicalDevice; + public static VkDevice device; + + public static DeviceInfo deviceInfo; + + public static VkPhysicalDeviceProperties deviceProperties; + public static VkPhysicalDeviceMemoryProperties memoryProperties; + + public static SurfaceProperties surfaceProperties; + + static VkQueue graphicsQueue; + static VkQueue presentQueue; + static VkQueue transferQueue; + + static void pickPhysicalDevice(VkInstance instance) { + + try(MemoryStack stack = stackPush()) { + + IntBuffer deviceCount = stack.ints(0); + + vkEnumeratePhysicalDevices(instance, deviceCount, null); + + if(deviceCount.get(0) == 0) { + throw new RuntimeException("Failed to find GPUs with Vulkan support"); + } + + PointerBuffer ppPhysicalDevices = stack.mallocPointer(deviceCount.get(0)); + + vkEnumeratePhysicalDevices(instance, deviceCount, ppPhysicalDevices); + + ArrayList integratedGPUs = new ArrayList<>(); + ArrayList otherDevices = new ArrayList<>(); + + VkPhysicalDevice currentDevice = null; + boolean flag = false; + + for(int i = 0; i < ppPhysicalDevices.capacity();i++) { + + currentDevice = new VkPhysicalDevice(ppPhysicalDevices.get(i), instance); + + VkPhysicalDeviceProperties deviceProperties = VkPhysicalDeviceProperties.calloc(stack); + vkGetPhysicalDeviceProperties(currentDevice, deviceProperties); + + if(isDeviceSuitable(currentDevice)) { + if(deviceProperties.deviceType() == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU){ + flag = true; + break; + } + else if(deviceProperties.deviceType() == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) integratedGPUs.add(currentDevice); + else otherDevices.add(currentDevice); + + } + } + + if(!flag) { + if(!integratedGPUs.isEmpty()) currentDevice = integratedGPUs.get(0); + else if(!otherDevices.isEmpty()) currentDevice = otherDevices.get(0); + else { + Initializer.LOGGER.error(DeviceInfo.debugString(ppPhysicalDevices, Vulkan.REQUIRED_EXTENSION, instance)); + throw new RuntimeException("Failed to find a suitable GPU"); + } + } + + physicalDevice = currentDevice; + + //Get device properties + deviceProperties = VkPhysicalDeviceProperties.malloc(); + vkGetPhysicalDeviceProperties(physicalDevice, deviceProperties); + + memoryProperties = VkPhysicalDeviceMemoryProperties.malloc(); + vkGetPhysicalDeviceMemoryProperties(physicalDevice, memoryProperties); + + surfaceProperties = querySurfaceProperties(physicalDevice, stack); + + deviceInfo = new DeviceInfo(physicalDevice, deviceProperties); + } + } + + static void createLogicalDevice() { + + try(MemoryStack stack = stackPush()) { + + net.vulkanmod.vulkan.queue.Queue.QueueFamilyIndices indices = findQueueFamilies(physicalDevice); + + int[] uniqueQueueFamilies = indices.unique(); + + VkDeviceQueueCreateInfo.Buffer queueCreateInfos = VkDeviceQueueCreateInfo.calloc(uniqueQueueFamilies.length, stack); + + for(int i = 0;i < uniqueQueueFamilies.length;i++) { + VkDeviceQueueCreateInfo queueCreateInfo = queueCreateInfos.get(i); + queueCreateInfo.sType(VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO); + queueCreateInfo.queueFamilyIndex(uniqueQueueFamilies[i]); + queueCreateInfo.pQueuePriorities(stack.floats(1.0f)); + } + + VkPhysicalDeviceFeatures2 deviceFeatures = VkPhysicalDeviceFeatures2.calloc(stack); + deviceFeatures.sType$Default(); + + //TODO indirect draw option disabled in case it is not supported + if(deviceInfo.availableFeatures.features().samplerAnisotropy()) + deviceFeatures.features().samplerAnisotropy(true); + if(deviceInfo.availableFeatures.features().logicOp()) + deviceFeatures.features().logicOp(true); + + VkPhysicalDeviceVulkan11Features deviceVulkan11Features = VkPhysicalDeviceVulkan11Features.calloc(stack); + deviceVulkan11Features.sType$Default(); + + if(deviceInfo.isDrawIndirectSupported()) { + deviceFeatures.features().multiDrawIndirect(true); + deviceVulkan11Features.shaderDrawParameters(true); + } + + VkDeviceCreateInfo createInfo = VkDeviceCreateInfo.calloc(stack); + + createInfo.sType(VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO); + createInfo.pQueueCreateInfos(queueCreateInfos); + // queueCreateInfoCount is automatically set + + createInfo.pEnabledFeatures(deviceFeatures.features()); + + VkPhysicalDeviceDynamicRenderingFeaturesKHR dynamicRenderingFeaturesKHR = VkPhysicalDeviceDynamicRenderingFeaturesKHR.calloc(stack); + dynamicRenderingFeaturesKHR.sType$Default(); + dynamicRenderingFeaturesKHR.dynamicRendering(true); + + createInfo.pNext(deviceVulkan11Features); + deviceVulkan11Features.pNext(dynamicRenderingFeaturesKHR.address()); + + //Vulkan 1.3 dynamic rendering +// VkPhysicalDeviceVulkan13Features deviceVulkan13Features = VkPhysicalDeviceVulkan13Features.calloc(stack); +// deviceVulkan13Features.sType$Default(); +// if(!deviceInfo.availableFeatures13.dynamicRendering()) +// throw new RuntimeException("Device does not support dynamic rendering feature."); +// +// deviceVulkan13Features.dynamicRendering(true); +// createInfo.pNext(deviceVulkan13Features); +// deviceVulkan13Features.pNext(deviceVulkan11Features.address()); + + createInfo.ppEnabledExtensionNames(asPointerBuffer(Vulkan.REQUIRED_EXTENSION)); + +// Configuration.DEBUG_FUNCTIONS.set(true); + + if(Vulkan.ENABLE_VALIDATION_LAYERS) { + createInfo.ppEnabledLayerNames(asPointerBuffer(Vulkan.VALIDATION_LAYERS)); + } + + PointerBuffer pDevice = stack.pointers(VK_NULL_HANDLE); + + if(vkCreateDevice(physicalDevice, createInfo, null, pDevice) != VK_SUCCESS) { + throw new RuntimeException("Failed to create logical device"); + } + + device = new VkDevice(pDevice.get(0), physicalDevice, createInfo, VK_API_VERSION_1_2); + + PointerBuffer pQueue = stack.pointers(VK_NULL_HANDLE); + + vkGetDeviceQueue(device, indices.graphicsFamily, 0, pQueue); + graphicsQueue = new VkQueue(pQueue.get(0), device); + + vkGetDeviceQueue(device, indices.presentFamily, 0, pQueue); + presentQueue = new VkQueue(pQueue.get(0), device); + + vkGetDeviceQueue(device, indices.transferFamily, 0, pQueue); + transferQueue = new VkQueue(pQueue.get(0), device); + + } + } + + private static PointerBuffer getRequiredExtensions() { + + PointerBuffer glfwExtensions = glfwGetRequiredInstanceExtensions(); + + if(Vulkan.ENABLE_VALIDATION_LAYERS) { + + MemoryStack stack = stackGet(); + + PointerBuffer extensions = stack.mallocPointer(glfwExtensions.capacity() + 1); + + extensions.put(glfwExtensions); + extensions.put(stack.UTF8(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)); + + // Rewind the buffer before returning it to reset its position back to 0 + return extensions.rewind(); + } + + return glfwExtensions; + } + + private static boolean isDeviceSuitable(VkPhysicalDevice device) { + + Queue.QueueFamilyIndices indices = findQueueFamilies(device); + + boolean extensionsSupported = checkDeviceExtensionSupport(device); + boolean swapChainAdequate = false; + + if(extensionsSupported) { + try(MemoryStack stack = stackPush()) { + SurfaceProperties surfaceProperties = querySurfaceProperties(device, stack); + swapChainAdequate = surfaceProperties.formats.hasRemaining() && surfaceProperties.presentModes.hasRemaining(); + } + } + + boolean anisotropicFilterSupported = false; + try(MemoryStack stack = stackPush()) { + VkPhysicalDeviceFeatures supportedFeatures = VkPhysicalDeviceFeatures.mallocStack(stack); + vkGetPhysicalDeviceFeatures(device, supportedFeatures); + anisotropicFilterSupported = supportedFeatures.samplerAnisotropy(); + } + + return indices.isSuitable() && extensionsSupported && swapChainAdequate; + } + + private static boolean checkDeviceExtensionSupport(VkPhysicalDevice device) { + + try(MemoryStack stack = stackPush()) { + + IntBuffer extensionCount = stack.ints(0); + + vkEnumerateDeviceExtensionProperties(device, (String)null, extensionCount, null); + + VkExtensionProperties.Buffer availableExtensions = VkExtensionProperties.mallocStack(extensionCount.get(0), stack); + + vkEnumerateDeviceExtensionProperties(device, (String)null, extensionCount, availableExtensions); + + Set extensions = availableExtensions.stream() + .map(VkExtensionProperties::extensionNameString) + .collect(toSet()); + + extensions.removeAll(Vulkan.REQUIRED_EXTENSION); + + return availableExtensions.stream() + .map(VkExtensionProperties::extensionNameString) + .collect(toSet()) + .containsAll(Vulkan.REQUIRED_EXTENSION); + } + } + + public static int findDepthFormat() { + return findSupportedFormat( + stackGet().ints(VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT), + VK_IMAGE_TILING_OPTIMAL, + VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); + } + + private static int findSupportedFormat(IntBuffer formatCandidates, int tiling, int features) { + + try(MemoryStack stack = stackPush()) { + + VkFormatProperties props = VkFormatProperties.calloc(stack); + + for(int i = 0; i < formatCandidates.capacity(); ++i) { + + int format = formatCandidates.get(i); + + vkGetPhysicalDeviceFormatProperties(physicalDevice, format, props); + + if(tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures() & features) == features) { + return format; + } else if(tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures() & features) == features) { + return format; + } + + } + } + + throw new RuntimeException("Failed to find supported format"); + } + + public static SurfaceProperties querySurfaceProperties(VkPhysicalDevice device, MemoryStack stack) { + + long surface = Vulkan.getSurface(); + SurfaceProperties details = new SurfaceProperties(); + + details.capabilities = VkSurfaceCapabilitiesKHR.malloc(stack); + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, details.capabilities); + + IntBuffer count = stack.ints(0); + + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, count, null); + + if(count.get(0) != 0) { + details.formats = VkSurfaceFormatKHR.malloc(count.get(0), stack); + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, count, details.formats); + } + + vkGetPhysicalDeviceSurfacePresentModesKHR(device,surface, count, null); + + if(count.get(0) != 0) { + details.presentModes = stack.mallocInt(count.get(0)); + vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, count, details.presentModes); + } + + return details; + } + + public static class SurfaceProperties { + public VkSurfaceCapabilitiesKHR capabilities; + public VkSurfaceFormatKHR.Buffer formats; + public IntBuffer presentModes; + } + +} diff --git a/src/main/java/net/vulkanmod/vulkan/DeviceInfo.java b/src/main/java/net/vulkanmod/vulkan/DeviceInfo.java index 4aa1eeca3..81d0a4490 100644 --- a/src/main/java/net/vulkanmod/vulkan/DeviceInfo.java +++ b/src/main/java/net/vulkanmod/vulkan/DeviceInfo.java @@ -1,5 +1,6 @@ package net.vulkanmod.vulkan; +import net.vulkanmod.vulkan.framebuffer.SwapChain; import org.lwjgl.PointerBuffer; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.*; @@ -14,16 +15,12 @@ import java.util.Set; import static java.util.stream.Collectors.toSet; -import static net.vulkanmod.vulkan.SwapChain.querySwapChainSupport; -import static org.lwjgl.system.MemoryStack.stackPush; -import static org.lwjgl.vulkan.VK10.vkEnumerateDeviceExtensionProperties; -import static org.lwjgl.vulkan.VK10.vkGetPhysicalDeviceProperties; -import static org.lwjgl.vulkan.VK11.vkGetPhysicalDeviceFeatures2; - import static org.lwjgl.glfw.GLFW.GLFW_PLATFORM_WIN32; import static org.lwjgl.glfw.GLFW.glfwGetPlatform; +import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; -import static org.lwjgl.vulkan.VK11.*; +import static org.lwjgl.vulkan.VK11.vkEnumerateInstanceVersion; +import static org.lwjgl.vulkan.VK11.vkGetPhysicalDeviceFeatures2; public class DeviceInfo { @@ -35,6 +32,7 @@ public class DeviceInfo { public final String deviceName; public final String driverVersion; public final String vkVersion; + public GraphicsCard graphicsCard; public final VkPhysicalDeviceFeatures2 availableFeatures; @@ -61,11 +59,9 @@ public DeviceInfo(VkPhysicalDevice device, VkPhysicalDeviceProperties properties this.device = device; this.vendorId = decodeVendor(properties.vendorID()); this.deviceName = properties.deviceNameString(); - this.driverVersion = decodeDvrVersion(Vulkan.deviceProperties.driverVersion(), Vulkan.deviceProperties.vendorID()); + this.driverVersion = decodeDvrVersion(Device.deviceProperties.driverVersion(), Device.deviceProperties.vendorID()); this.vkVersion = decDefVersion(getVkVer()); -// this.driverVersion = graphicsCard.getVersionInfo(); - this.availableFeatures = VkPhysicalDeviceFeatures2.calloc(); this.availableFeatures.sType$Default(); @@ -84,6 +80,7 @@ public DeviceInfo(VkPhysicalDevice device, VkPhysicalDeviceProperties properties if(this.availableFeatures.features().multiDrawIndirect() && this.availableFeatures11.shaderDrawParameters()) this.drawIndirectSupported = true; + } private static String decodeVendor(int i) { @@ -176,8 +173,8 @@ public static String debugString(PointerBuffer ppPhysicalDevices, Set re stringBuilder.append(String.format("Device %d: ", i)).append(info.deviceName).append("\n"); stringBuilder.append(info.unsupportedExtensions(requiredExtensions)).append("\n"); - SwapChain.SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device, stack); - boolean swapChainAdequate = swapChainSupport.formats.hasRemaining() && swapChainSupport.presentModes.hasRemaining() ; + Device.SurfaceProperties surfaceProperties = Device.querySurfaceProperties(device, stack); + boolean swapChainAdequate = surfaceProperties.formats.hasRemaining() && surfaceProperties.presentModes.hasRemaining() ; stringBuilder.append("Swapchain supported: ").append(swapChainAdequate ? "true" : "false").append("\n"); } diff --git a/src/main/java/net/vulkanmod/vulkan/Drawer.java b/src/main/java/net/vulkanmod/vulkan/Drawer.java index 2b9198460..cecef9534 100644 --- a/src/main/java/net/vulkanmod/vulkan/Drawer.java +++ b/src/main/java/net/vulkanmod/vulkan/Drawer.java @@ -1,120 +1,79 @@ package net.vulkanmod.vulkan; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.VertexFormat; -import net.minecraft.client.Minecraft; -import net.vulkanmod.interfaces.ShaderMixed; import net.vulkanmod.render.chunk.AreaUploadManager; -import net.vulkanmod.render.profiling.Profiler2; import net.vulkanmod.vulkan.memory.*; -import net.vulkanmod.vulkan.shader.Pipeline; -import net.vulkanmod.vulkan.shader.PipelineState; -import net.vulkanmod.vulkan.shader.ShaderManager; -import net.vulkanmod.vulkan.shader.layout.PushConstants; -import net.vulkanmod.vulkan.texture.VTextureSelector; import net.vulkanmod.vulkan.util.VUtil; -import org.lwjgl.PointerBuffer; -import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryUtil; -import org.lwjgl.vulkan.*; +import org.lwjgl.vulkan.VkCommandBuffer; import java.nio.ByteBuffer; -import java.nio.IntBuffer; import java.nio.LongBuffer; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static net.vulkanmod.vulkan.Vulkan.*; -import static org.lwjgl.glfw.GLFW.glfwGetFramebufferSize; -import static org.lwjgl.system.MemoryStack.stackGet; -import static org.lwjgl.system.MemoryStack.stackPush; -import static org.lwjgl.vulkan.EXTDebugUtils.*; -import static org.lwjgl.vulkan.KHRSwapchain.*; +import java.util.Arrays; + import static org.lwjgl.vulkan.VK10.*; +import static org.lwjgl.vulkan.VK10.vkCmdDraw; public class Drawer { - private static Drawer INSTANCE; - - public static void initDrawer() { INSTANCE = new Drawer(); } + private static final int INITIAL_VB_SIZE = 2000000; + private static final int INITIAL_UB_SIZE = 200000; - private static VkDevice device; - private static List commandBuffers; - - private final Set usedPipelines = new HashSet<>(); + private static final LongBuffer buffers = MemoryUtil.memAllocLong(1); + 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 int framesNum; private VertexBuffer[] vertexBuffers; private final AutoIndexBuffer quadsIndexBuffer; private final AutoIndexBuffer triangleFanIndexBuffer; private final AutoIndexBuffer triangleStripIndexBuffer; private UniformBuffers uniformBuffers; - private static int MAX_FRAMES_IN_FLIGHT; - private ArrayList imageAvailableSemaphores; - private ArrayList renderFinishedSemaphores; - private ArrayList inFlightFences; - - private Framebuffer boundFramebuffer; - - private static int currentFrame = 0; - private final int commandBuffersCount = getSwapChainImages().size(); - - public static PipelineState.BlendInfo blendInfo = PipelineState.defaultBlendInfo(); - public static PipelineState.BlendState currentBlendState; - public static PipelineState.DepthState currentDepthState = PipelineState.DEFAULT_DEPTH_STATE; - public static PipelineState.LogicOpState currentLogicOpState = PipelineState.DEFAULT_LOGICOP_STATE; - public static PipelineState.ColorMask currentColorMask = PipelineState.DEFAULT_COLORMASK; - - public static boolean shouldRecreate = false; - public static boolean skipRendering = false; - - private static final LongBuffer buffers = MemoryUtil.memAllocLong(1); - 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 int currentFrame; - - public Drawer() - { - this(2000000, 200000); - } - - public Drawer(int VBOSize, int UBOSize) { - device = Vulkan.getDevice(); - MAX_FRAMES_IN_FLIGHT = getSwapChainImages().size(); - vertexBuffers = new VertexBuffer[MAX_FRAMES_IN_FLIGHT]; - for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { - vertexBuffers[i] = new VertexBuffer(VBOSize, MemoryTypes.HOST_MEM); - } - - uniformBuffers = new UniformBuffers(UBOSize); + public Drawer() { + //Index buffers quadsIndexBuffer = new AutoIndexBuffer(100000, AutoIndexBuffer.DrawType.QUADS); triangleFanIndexBuffer = new AutoIndexBuffer(1000, AutoIndexBuffer.DrawType.TRIANGLE_FAN); triangleStripIndexBuffer = new AutoIndexBuffer(1000, AutoIndexBuffer.DrawType.TRIANGLE_STRIP); + } - createSyncObjects(); + public void setCurrentFrame(int currentFrame) { + this.currentFrame = currentFrame; + } - this.allocateCommandBuffers(); + public void createResources(int framesNum) { + this.framesNum = framesNum; - ShaderManager.initShaderManager(); - AreaUploadManager.createInstance(MAX_FRAMES_IN_FLIGHT); + if(vertexBuffers != null) { + Arrays.stream(this.vertexBuffers).iterator().forEachRemaining( + Buffer::freeBuffer + ); + } + this.vertexBuffers = new VertexBuffer[framesNum]; + for (int i = 0; i < framesNum; ++i) { + this.vertexBuffers[i] = new VertexBuffer(INITIAL_VB_SIZE, MemoryTypes.HOST_MEM); + } + + if(this.uniformBuffers != null) + this.uniformBuffers.free(); + this.uniformBuffers = new UniformBuffers(INITIAL_UB_SIZE); + } + + public void resetBuffers(int currentFrame) { + this.vertexBuffers[currentFrame].reset(); + this.uniformBuffers.reset(); } public void draw(ByteBuffer buffer, VertexFormat.Mode mode, VertexFormat vertexFormat, int vertexCount) { - if(!(vertexCount > 0)) return; - AutoIndexBuffer autoIndexBuffer; int indexCount; VertexBuffer vertexBuffer = this.vertexBuffers[currentFrame]; vertexBuffer.copyToVertexBuffer(vertexFormat.getVertexSize(), vertexCount, buffer); - Pipeline pipeline = ((ShaderMixed)(RenderSystem.getShader())).getPipeline(); - bindPipeline(pipeline); - uploadAndBindUBOs(pipeline); - switch (mode) { case QUADS, LINES -> { autoIndexBuffer = this.quadsIndexBuffer; @@ -140,357 +99,6 @@ public void draw(ByteBuffer buffer, VertexFormat.Mode mode, VertexFormat vertexF drawIndexed(vertexBuffer, autoIndexBuffer.getIndexBuffer(), indexCount); } - public void submitDraw() - { - if(skipRendering) return; - - drawFrame(); - } - - public void initiateRenderPass() { - - Profiler2 p = Profiler2.getMainProfiler(); - p.push("Frame_fence"); - try (MemoryStack stack = stackPush()) { - - IntBuffer width = stack.ints(0); - IntBuffer height = stack.ints(0); - - glfwGetFramebufferSize(window, width, height); - if (width.get(0) == 0 && height.get(0) == 0) { - skipRendering = true; - Minecraft.getInstance().noRender = true; - } else { - skipRendering = false; - Minecraft.getInstance().noRender = false; - } - } - - if(skipRendering) return; - - vkWaitForFences(device, inFlightFences.get(currentFrame), true, VUtil.UINT64_MAX); - - p.pop(); - p.start(); - p.push("Frame_ops"); - - AreaUploadManager.INSTANCE.updateFrame(currentFrame); - - MemoryManager.getInstance().initFrame(currentFrame); - -// this.vertexBuffers[currentFrame].reset(); -// this.uniformBuffers.reset(); -// Vulkan.getStagingBuffer(currentFrame).reset(); - - resetDescriptors(); - - vkResetCommandBuffer(commandBuffers.get(currentFrame), 0); - - p.pop(); - - try(MemoryStack stack = stackPush()) { - - VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.callocStack(stack); - beginInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO); - beginInfo.flags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - -// VkRect2D renderArea = VkRect2D.callocStack(stack); -// renderArea.offset(VkOffset2D.callocStack(stack).set(0, 0)); -// renderArea.extent(getSwapchainExtent()); -// -// VkClearValue.Buffer clearValues = VkClearValue.callocStack(2, stack); -// clearValues.get(0).color().float32(stack.floats(0.0f, 0.0f, 0.0f, 1.0f)); -// clearValues.get(1).depthStencil().set(1.0f, 0); - - VkCommandBuffer commandBuffer = commandBuffers.get(currentFrame); - - int err = vkBeginCommandBuffer(commandBuffer, beginInfo); - if (err != VK_SUCCESS) { - throw new RuntimeException("Failed to begin recording command buffer:" + err); - } - - //dyn-rendering - - getSwapChain().colorAttachmentLayout(stack, commandBuffer, currentFrame); - - Framebuffer framebuffer = Vulkan.getSwapChain(); - - framebuffer.beginRendering(commandBuffer, stack); - this.boundFramebuffer = framebuffer; - -// renderPassInfo.framebuffer(getSwapChainFramebuffers().get(currentFrame)); -// -// vkCmdBeginRenderPass(commandBuffer, renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport.Buffer pViewport = framebuffer.viewport(stack); - vkCmdSetViewport(commandBuffer, 0, pViewport); - - VkRect2D.Buffer pScissor = framebuffer.scissor(stack); - vkCmdSetScissor(commandBuffer, 0, pScissor); - - vkCmdSetDepthBias(commandBuffer, 0.0F, 0.0F, 0.0F); - } - } - - public void endRenderPass() { - if(skipRendering) return; - - VkCommandBuffer commandBuffer = commandBuffers.get(currentFrame); - -// vkCmdEndRenderPass(commandBuffer); -// vkCmdEndRendering(commandBuffer); - KHRDynamicRendering.vkCmdEndRenderingKHR(commandBuffer); - this.boundFramebuffer = null; - - try(MemoryStack stack = MemoryStack.stackPush()) { - getSwapChain().presentLayout(stack, commandBuffer, currentFrame); - } - - int result = vkEndCommandBuffer(commandBuffer); - if(result != VK_SUCCESS) { - throw new RuntimeException("Failed to record command buffer:" + result); - } - } - - public void beginRendering(Framebuffer framebuffer) { - if(skipRendering) return; - - if(this.boundFramebuffer != framebuffer) { - this.endRendering(); - - try (MemoryStack stack = stackPush()) { - framebuffer.beginRendering(commandBuffers.get(currentFrame), stack); - } - - this.boundFramebuffer = framebuffer; - } - } - - public void endRendering() { - if(skipRendering) return; - - VkCommandBuffer commandBuffer = commandBuffers.get(currentFrame); - -// vkCmdEndRenderPass(commandBuffer); -// vkCmdEndRendering(commandBuffer); - KHRDynamicRendering.vkCmdEndRenderingKHR(commandBuffer); - - this.boundFramebuffer = null; - } - - private void allocateCommandBuffers() { - commandBuffers = new ArrayList<>(commandBuffersCount); - - try(MemoryStack stack = stackPush()) { - - VkCommandBufferAllocateInfo allocInfo = VkCommandBufferAllocateInfo.callocStack(stack); - allocInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO); - allocInfo.commandPool(getCommandPool()); - allocInfo.level(VK_COMMAND_BUFFER_LEVEL_PRIMARY); - allocInfo.commandBufferCount(commandBuffersCount); - - PointerBuffer pCommandBuffers = stack.mallocPointer(commandBuffersCount); - - if (vkAllocateCommandBuffers(device, allocInfo, pCommandBuffers) != VK_SUCCESS) { - throw new RuntimeException("Failed to allocate command buffers"); - } - - for (int i = 0; i < commandBuffersCount; i++) { - commandBuffers.add(new VkCommandBuffer(pCommandBuffers.get(i), device)); - } - } - } - - public void resetBuffers() { - this.vertexBuffers[currentFrame].reset(); - this.uniformBuffers.reset(); - Vulkan.getStagingBuffer(currentFrame).reset(); - } - - private void resetDescriptors() { - for(Pipeline pipeline : usedPipelines) { - pipeline.resetDescriptorPool(currentFrame); - } - - usedPipelines.clear(); - } - - private void createSyncObjects() { - - final int frameNum = getSwapChainImages().size(); - - imageAvailableSemaphores = new ArrayList<>(frameNum); - renderFinishedSemaphores = new ArrayList<>(frameNum); - inFlightFences = new ArrayList<>(frameNum); - - try(MemoryStack stack = stackPush()) { - - VkSemaphoreCreateInfo semaphoreInfo = VkSemaphoreCreateInfo.callocStack(stack); - semaphoreInfo.sType(VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO); - - VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.callocStack(stack); - fenceInfo.sType(VK_STRUCTURE_TYPE_FENCE_CREATE_INFO); - fenceInfo.flags(VK_FENCE_CREATE_SIGNALED_BIT); - - LongBuffer pImageAvailableSemaphore = stack.mallocLong(1); - LongBuffer pRenderFinishedSemaphore = stack.mallocLong(1); - LongBuffer pFence = stack.mallocLong(1); - - for(int i = 0;i < frameNum;i++) { - - if(vkCreateSemaphore(device, semaphoreInfo, null, pImageAvailableSemaphore) != VK_SUCCESS - || vkCreateSemaphore(device, semaphoreInfo, null, pRenderFinishedSemaphore) != VK_SUCCESS - || vkCreateFence(device, fenceInfo, null, pFence) != VK_SUCCESS) { - - throw new RuntimeException("Failed to create synchronization objects for the frame " + i); - } - - imageAvailableSemaphores.add(pImageAvailableSemaphore.get(0)); - renderFinishedSemaphores.add(pRenderFinishedSemaphore.get(0)); - inFlightFences.add(pFence.get(0)); - - } - - } - } - - - public static Drawer getInstance() { return INSTANCE; } - - public static int getCurrentFrame() { return currentFrame; } - - private void drawFrame() { - - try(MemoryStack stack = stackPush()) { - - IntBuffer pImageIndex = stack.mallocInt(1); - - int vkResult = vkAcquireNextImageKHR(device, Vulkan.getSwapChain().getId(), VUtil.UINT64_MAX, - imageAvailableSemaphores.get(currentFrame), VK_NULL_HANDLE, pImageIndex); - - if(vkResult == VK_ERROR_OUT_OF_DATE_KHR || vkResult == VK_SUBOPTIMAL_KHR || shouldRecreate) { - shouldRecreate = false; - recreateSwapChain(); - return; - } else if(vkResult != VK_SUCCESS) { - throw new RuntimeException("Cannot get image: " + vkResult); - } - - final int imageIndex = pImageIndex.get(0); - - VkSubmitInfo submitInfo = VkSubmitInfo.callocStack(stack); - submitInfo.sType(VK_STRUCTURE_TYPE_SUBMIT_INFO); - - submitInfo.waitSemaphoreCount(1); - submitInfo.pWaitSemaphores(stackGet().longs(imageAvailableSemaphores.get(currentFrame))); - submitInfo.pWaitDstStageMask(stack.ints(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)); - - submitInfo.pSignalSemaphores(stackGet().longs(renderFinishedSemaphores.get(currentFrame))); - - submitInfo.pCommandBuffers(stack.pointers(commandBuffers.get(currentFrame))); - - vkResetFences(device, stackGet().longs(inFlightFences.get(currentFrame))); - - Synchronization.INSTANCE.waitFences(); - - if((vkResult = vkQueueSubmit(getGraphicsQueue(), submitInfo, inFlightFences.get(currentFrame))) != VK_SUCCESS) { - vkResetFences(device, stackGet().longs(inFlightFences.get(currentFrame))); - throw new RuntimeException("Failed to submit draw command buffer: " + vkResult); - } - - VkPresentInfoKHR presentInfo = VkPresentInfoKHR.callocStack(stack); - presentInfo.sType(VK_STRUCTURE_TYPE_PRESENT_INFO_KHR); - - presentInfo.pWaitSemaphores(stackGet().longs(renderFinishedSemaphores.get(currentFrame))); - - presentInfo.swapchainCount(1); - presentInfo.pSwapchains(stack.longs(Vulkan.getSwapChain().getId())); - - presentInfo.pImageIndices(pImageIndex); - - vkResult = vkQueuePresentKHR(getPresentQueue(), presentInfo); - - if(vkResult == VK_ERROR_OUT_OF_DATE_KHR || vkResult == VK_SUBOPTIMAL_KHR || shouldRecreate) { - shouldRecreate = false; - recreateSwapChain(); - return; - } else if(vkResult != VK_SUCCESS) { - throw new RuntimeException("Failed to present swap chain image"); - } - - currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; - } - } - - private void recreateSwapChain() { -// for(Long fence : inFlightFences) { -// vkWaitForFences(device, fence, true, VUtil.UINT64_MAX); -// } - - vkDeviceWaitIdle(device); - - for(int i = 0; i < getSwapChainImages().size(); ++i) { - vkDestroyFence(device, inFlightFences.get(i), null); - vkDestroySemaphore(device, imageAvailableSemaphores.get(i), null); - vkDestroySemaphore(device, renderFinishedSemaphores.get(i), null); - } - - commandBuffers.forEach(commandBuffer -> vkResetCommandBuffer(commandBuffer, 0)); - - Vulkan.recreateSwapChain(); - - createSyncObjects(); - - if(MAX_FRAMES_IN_FLIGHT != getSwapChainImages().size()) { - MAX_FRAMES_IN_FLIGHT = getSwapChainImages().size(); - - Vulkan.createStagingBuffers(); - -// Arrays.stream(this.vertexBuffers).iterator().forEachRemaining( -// Buffer::freeBuffer -// ); - this.vertexBuffers = new VertexBuffer[MAX_FRAMES_IN_FLIGHT]; - for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { - this.vertexBuffers[i] = new VertexBuffer(2000000, MemoryTypes.HOST_MEM); - } - -// this.uniformBuffers.free(); - this.uniformBuffers = new UniformBuffers(200000); - - AreaUploadManager.INSTANCE.waitAllUploads(); - AreaUploadManager.createInstance(MAX_FRAMES_IN_FLIGHT); - } - - currentFrame = 0; - } - - public void cleanUpResources() { - MemoryManager memoryManager = MemoryManager.getInstance(); - - Buffer buffer; - for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { - buffer = this.vertexBuffers[i]; - memoryManager.freeBuffer(buffer.getId(), buffer.getAllocation()); - - buffer = this.uniformBuffers.getUniformBuffer(i); - memoryManager.freeBuffer(buffer.getId(), buffer.getAllocation()); - - vkDestroyFence(device, inFlightFences.get(i), null); - vkDestroySemaphore(device, imageAvailableSemaphores.get(i), null); - vkDestroySemaphore(device, renderFinishedSemaphores.get(i), null); - } - - buffer = this.quadsIndexBuffer.getIndexBuffer(); - memoryManager.freeBuffer(buffer.getId(), buffer.getAllocation()); - buffer = this.triangleFanIndexBuffer.getIndexBuffer(); - memoryManager.freeBuffer(buffer.getId(), buffer.getAllocation()); - buffer = this.triangleStripIndexBuffer.getIndexBuffer(); - memoryManager.freeBuffer(buffer.getId(), buffer.getAllocation()); - - ShaderManager.getInstance().destroyPipelines(); - VTextureSelector.getWhiteTexture().free(); - } - public AutoIndexBuffer getQuadsIndexBuffer() { return quadsIndexBuffer; } @@ -501,15 +109,8 @@ public AutoIndexBuffer getTriangleFanIndexBuffer() { public UniformBuffers getUniformBuffers() { return this.uniformBuffers; } - public static VkCommandBuffer getCommandBuffer() { return commandBuffers.get(currentFrame); } - - public void uploadAndBindUBOs(Pipeline pipeline) { - VkCommandBuffer commandBuffer = commandBuffers.get(currentFrame); - pipeline.bindDescriptorSets(commandBuffer, currentFrame); - } - public void drawIndexed(VertexBuffer vertexBuffer, IndexBuffer indexBuffer, int indexCount) { - VkCommandBuffer commandBuffer = commandBuffers.get(currentFrame); + VkCommandBuffer commandBuffer = Renderer.getCommandBuffer(); VUtil.UNSAFE.putLong(pBuffers, vertexBuffer.getId()); VUtil.UNSAFE.putLong(pOffsets, vertexBuffer.getOffset()); @@ -520,7 +121,7 @@ public void drawIndexed(VertexBuffer vertexBuffer, IndexBuffer indexBuffer, int } public void draw(VertexBuffer vertexBuffer, int vertexCount) { - VkCommandBuffer commandBuffer = commandBuffers.get(currentFrame); + VkCommandBuffer commandBuffer = Renderer.getCommandBuffer(); VUtil.UNSAFE.putLong(pBuffers, vertexBuffer.getId()); VUtil.UNSAFE.putLong(pOffsets, vertexBuffer.getOffset()); @@ -529,18 +130,6 @@ public void draw(VertexBuffer vertexBuffer, int vertexCount) { vkCmdDraw(commandBuffer, vertexCount, 1, 0, 0); } - public void bindPipeline(Pipeline pipeline) { - VkCommandBuffer commandBuffer = commandBuffers.get(currentFrame); - - currentDepthState = VRenderSystem.getDepthState(); - currentColorMask = new PipelineState.ColorMask(VRenderSystem.getColorMask()); - currentBlendState = blendInfo.createBlendState(); - PipelineState currentState = new PipelineState(currentBlendState, currentDepthState, currentLogicOpState, currentColorMask); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getHandle(currentState)); - - usedPipelines.add(pipeline); - } - public void bindAutoIndexBuffer(VkCommandBuffer commandBuffer, int drawMode) { AutoIndexBuffer autoIndexBuffer; switch (drawMode) { @@ -554,149 +143,23 @@ public void bindAutoIndexBuffer(VkCommandBuffer commandBuffer, int drawMode) { vkCmdBindIndexBuffer(commandBuffer, indexBuffer.getId(), indexBuffer.getOffset(), VK_INDEX_TYPE_UINT16); } - public void pushConstants(Pipeline pipeline) { - VkCommandBuffer commandBuffer = commandBuffers.get(currentFrame); - - PushConstants pushConstants = pipeline.getPushConstants(); - - try (MemoryStack stack = stackPush()) { - ByteBuffer buffer = stack.malloc(pushConstants.getSize()); - long ptr = MemoryUtil.memAddress0(buffer); - pushConstants.update(ptr); - - nvkCmdPushConstants(commandBuffer, pipeline.getLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, pushConstants.getSize(), ptr); - } - - } - - public AutoIndexBuffer getQuadIndexBuffer() { - return this.quadsIndexBuffer; - } - - public static void setDepthBias(float units, float factor) { - VkCommandBuffer commandBuffer = commandBuffers.get(currentFrame); - - vkCmdSetDepthBias(commandBuffer, units, 0.0f, factor); - } - - public static void clearAttachments(int v) { - if(skipRendering) return; - - VkCommandBuffer commandBuffer = commandBuffers.get(currentFrame); - - try(MemoryStack stack = stackPush()) { - //ClearValues have to be different for each attachment to clear, it seems it works like a buffer: color and depth attributes override themselves - VkClearValue colorValue = VkClearValue.callocStack(stack); - colorValue.color().float32(VRenderSystem.clearColor); - - VkClearValue depthValue = VkClearValue.callocStack(stack); - depthValue.depthStencil().depth(VRenderSystem.clearDepth); - - int attachmentsCount; - VkClearAttachment.Buffer pAttachments; - if (v == 0x100) { - attachmentsCount = 1; - - pAttachments = VkClearAttachment.callocStack(attachmentsCount, stack); - - VkClearAttachment clearDepth = pAttachments.get(0); - clearDepth.aspectMask(VK_IMAGE_ASPECT_DEPTH_BIT); - clearDepth.clearValue(depthValue); - } else if (v == 0x4000) { - attachmentsCount = 1; - - pAttachments = VkClearAttachment.callocStack(attachmentsCount, stack); - - VkClearAttachment clearColor = pAttachments.get(0); - clearColor.aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); - clearColor.colorAttachment(0); - clearColor.clearValue(colorValue); - } else if (v == 0x4100) { - attachmentsCount = 2; - - pAttachments = VkClearAttachment.callocStack(attachmentsCount, stack); - - VkClearAttachment clearColor = pAttachments.get(0); - clearColor.aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); - clearColor.clearValue(colorValue); - - VkClearAttachment clearDepth = pAttachments.get(1); - clearDepth.aspectMask(VK_IMAGE_ASPECT_DEPTH_BIT); - clearDepth.clearValue(depthValue); - } else { - throw new RuntimeException("unexpected value"); - } - - //Rect to clear - VkRect2D renderArea = VkRect2D.callocStack(stack); - renderArea.offset(VkOffset2D.callocStack(stack).set(0, 0)); - renderArea.extent(getSwapchainExtent()); - - VkClearRect.Buffer pRect = VkClearRect.callocStack(1, stack); - pRect.get(0).rect(renderArea); - pRect.get(0).layerCount(1); - - vkCmdClearAttachments(commandBuffer, pAttachments, pRect); - } - } - - public static void setViewport(int x, int y, int width, int height) { - try(MemoryStack stack = stackPush()) { - VkViewport.Buffer viewport = VkViewport.callocStack(1, stack); - viewport.x(x); - viewport.y(height + y); - viewport.width(width); - viewport.height(-height); - viewport.minDepth(0.0f); - viewport.maxDepth(1.0f); - - vkCmdSetViewport(commandBuffers.get(currentFrame), 0, viewport); - } - } - - public static void setScissor(int x, int y, int width, int height) { - try(MemoryStack stack = stackPush()) { - int framebufferHeight = Drawer.getInstance().boundFramebuffer.height; - - VkRect2D.Buffer scissor = VkRect2D.malloc(1, stack); - scissor.offset(VkOffset2D.malloc(stack).set(x, framebufferHeight - (y + height))); - scissor.extent(VkExtent2D.malloc(stack).set(width, height)); - - vkCmdSetScissor(commandBuffers.get(currentFrame), 0, scissor); - } - } - - public static void resetScissor() { - try(MemoryStack stack = stackPush()) { - VkRect2D.Buffer scissor = Drawer.getInstance().boundFramebuffer.scissor(stack); - vkCmdSetScissor(commandBuffers.get(currentFrame), 0, scissor); - } - } + public void cleanUpResources() { + Buffer buffer; + for (int i = 0; i < framesNum; ++i) { + buffer = this.vertexBuffers[i]; + MemoryManager.freeBuffer(buffer.getId(), buffer.getAllocation()); - public static void pushDebugSection(String s) { - if(Vulkan.ENABLE_VALIDATION_LAYERS) { - VkCommandBuffer commandBuffer = commandBuffers.get(currentFrame); + buffer = this.uniformBuffers.getUniformBuffer(i); + MemoryManager.freeBuffer(buffer.getId(), buffer.getAllocation()); - try(MemoryStack stack = stackPush()) { - VkDebugUtilsLabelEXT markerInfo = VkDebugUtilsLabelEXT.callocStack(stack); - markerInfo.sType(VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT); - ByteBuffer string = stack.UTF8(s); - markerInfo.pLabelName(string); - vkCmdBeginDebugUtilsLabelEXT(commandBuffer, markerInfo); - } } - } - - public static void popDebugSection() { - if(Vulkan.ENABLE_VALIDATION_LAYERS) { - VkCommandBuffer commandBuffer = commandBuffers.get(currentFrame); - vkCmdEndDebugUtilsLabelEXT(commandBuffer); - } + buffer = this.quadsIndexBuffer.getIndexBuffer(); + MemoryManager.freeBuffer(buffer.getId(), buffer.getAllocation()); + buffer = this.triangleFanIndexBuffer.getIndexBuffer(); + MemoryManager.freeBuffer(buffer.getId(), buffer.getAllocation()); + buffer = this.triangleStripIndexBuffer.getIndexBuffer(); + MemoryManager.freeBuffer(buffer.getId(), buffer.getAllocation()); } - public static void popPushDebugSection(String s) { - popDebugSection(); - pushDebugSection(s); - } } diff --git a/src/main/java/net/vulkanmod/vulkan/Framebuffer.java b/src/main/java/net/vulkanmod/vulkan/Framebuffer.java deleted file mode 100644 index e3b836643..000000000 --- a/src/main/java/net/vulkanmod/vulkan/Framebuffer.java +++ /dev/null @@ -1,169 +0,0 @@ -package net.vulkanmod.vulkan; - -import net.vulkanmod.vulkan.texture.VTextureSelector; -import net.vulkanmod.vulkan.texture.VulkanImage; -import org.lwjgl.system.MemoryStack; -import org.lwjgl.vulkan.*; - -import java.util.ArrayList; - -import static net.vulkanmod.vulkan.Vulkan.getSwapchainExtent; -import static org.lwjgl.vulkan.VK10.*; -import static org.lwjgl.vulkan.VK13.vkCmdBeginRendering; - -public class Framebuffer { - public static final int DEFAULT_FORMAT = VK_FORMAT_R8G8B8A8_UNORM; - - public int format; - public int depthFormat; - public int width, height; - -// private List images; - private VulkanImage colorAttachment; - protected VulkanImage depthAttachment; - - public Framebuffer(int width, int height, int format) { - this(width, height, format, false); - } - - public Framebuffer(int width, int height, int format, boolean blur) { - this.format = format; - this.depthFormat = Vulkan.findDepthFormat(); - this.width = width; - this.height = height; - - this.colorAttachment = VulkanImage.createTextureImage(format, 1, width, height, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 0, blur, true); - - createDepthResources(blur); -// createFramebuffers(width, height); - } - - public Framebuffer(VulkanImage colorAttachment) { - this.width = colorAttachment.width; - this.height = colorAttachment.height; - - this.colorAttachment = colorAttachment; - - this.depthFormat = Vulkan.findDepthFormat(); - createDepthResources(false); - } - - protected Framebuffer() {} - -// private void createFramebuffers(int width, int height) { -// -// //List swapChainFramebuffers = new ArrayList(Vulkan.getSwapChainImages().size()); -// framebuffers = new ArrayList<>(imagesSize); -// -// try(MemoryStack stack = stackPush()) { -// -// LongBuffer attachments = stack.longs(VK_NULL_HANDLE, depthImageView); -// //attachments = stack.mallocLong(1); -// LongBuffer pFramebuffer = stack.mallocLong(1); -// -// // Lets allocate the create info struct once and just update the pAttachments field each iteration -// VkFramebufferCreateInfo framebufferInfo = VkFramebufferCreateInfo.callocStack(stack); -// framebufferInfo.sType(VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO); -// framebufferInfo.renderPass(Vulkan.getRenderPass()); -// framebufferInfo.width(width); -// framebufferInfo.height(height); -// framebufferInfo.layers(1); -// -// for(long imageView : imageViews) { -// -// attachments.put(0, imageView); -// -// framebufferInfo.pAttachments(attachments); -// -// if(vkCreateFramebuffer(Vulkan.getDevice(), framebufferInfo, null, pFramebuffer) != VK_SUCCESS) { -// throw new RuntimeException("Failed to create framebuffer"); -// } -// -// framebuffers.add(pFramebuffer.get(0)); -// } -// } -// } - - protected void createDepthResources(boolean blur) { - - this.depthAttachment = VulkanImage.createDepthImage(depthFormat, this.width, this.height, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - blur, false); - - VkCommandBuffer commandBuffer = Vulkan.beginImmediateCmd(); - this.depthAttachment.transitionImageLayout(MemoryStack.stackPush(), commandBuffer, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - Vulkan.endImmediateCmd(); - - } - - public void beginRendering(VkCommandBuffer commandBuffer, MemoryStack stack) { - this.colorAttachment.transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - this.depthAttachment.transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - - VkRect2D renderArea = VkRect2D.callocStack(stack); - renderArea.offset(VkOffset2D.callocStack(stack).set(0, 0)); - renderArea.extent(VkExtent2D.calloc(stack).set(this.width, this.height)); - - VkRenderingAttachmentInfo.Buffer colorAttachment = VkRenderingAttachmentInfo.calloc(1, stack); - colorAttachment.sType(KHRDynamicRendering.VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR); - colorAttachment.imageView(this.colorAttachment.getImageView()); - colorAttachment.imageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - colorAttachment.loadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE); - colorAttachment.storeOp(VK_ATTACHMENT_STORE_OP_STORE); -// colorAttachment.clearValue(clearValues.get(0)); - - VkRenderingAttachmentInfo depthAttachment = VkRenderingAttachmentInfo.calloc(stack); - depthAttachment.sType(KHRDynamicRendering.VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR); - depthAttachment.imageView(this.depthAttachment.getImageView()); - depthAttachment.imageLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - depthAttachment.loadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE); - depthAttachment.storeOp(VK_ATTACHMENT_STORE_OP_STORE); -// depthAttachment.clearValue(clearValues.get(1)); - - VkRenderingInfo renderingInfo = VkRenderingInfo.calloc(stack); - renderingInfo.sType(KHRDynamicRendering.VK_STRUCTURE_TYPE_RENDERING_INFO_KHR); - renderingInfo.renderArea(renderArea); - renderingInfo.layerCount(1); - renderingInfo.pColorAttachments(colorAttachment); - renderingInfo.pDepthAttachment(depthAttachment); - - vkCmdBeginRendering(commandBuffer, renderingInfo); - } - - public void bindAsTexture(VkCommandBuffer commandBuffer, MemoryStack stack) { - this.colorAttachment.transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - VTextureSelector.bindFramebufferTexture(this.colorAttachment); - } - - public VkViewport.Buffer viewport(MemoryStack stack) { - VkViewport.Buffer viewport = VkViewport.callocStack(1, stack); - viewport.x(0.0f); - viewport.y(this.height); - viewport.width(this.width); - viewport.height(-this.height); - viewport.minDepth(0.0f); - viewport.maxDepth(1.0f); - - return viewport; - } - - public VkRect2D.Buffer scissor(MemoryStack stack) { - VkRect2D.Buffer scissor = VkRect2D.callocStack(1, stack); - scissor.offset(VkOffset2D.callocStack(stack).set(0, 0)); - scissor.extent(VkExtent2D.malloc(stack).set(this.width, this.height)); - - return scissor; - } - - public void cleanUp() { - this.colorAttachment.free(); - this.depthAttachment.free(); - } - - public long getDepthImageView() { return depthAttachment.getImageView(); } - - public VulkanImage getDepthAttachment() { return depthAttachment; } - - public VulkanImage getColorAttachment() { return colorAttachment; } - -} diff --git a/src/main/java/net/vulkanmod/vulkan/Renderer.java b/src/main/java/net/vulkanmod/vulkan/Renderer.java new file mode 100644 index 000000000..6c832edfb --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/Renderer.java @@ -0,0 +1,617 @@ +package net.vulkanmod.vulkan; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import net.minecraft.client.Minecraft; +import net.vulkanmod.render.chunk.AreaUploadManager; +import net.vulkanmod.render.profiling.Profiler2; +import net.vulkanmod.vulkan.framebuffer.Framebuffer; +import net.vulkanmod.vulkan.framebuffer.RenderPass; +import net.vulkanmod.vulkan.memory.MemoryManager; +import net.vulkanmod.vulkan.passes.DefaultMainPass; +import net.vulkanmod.vulkan.passes.MainPass; +import net.vulkanmod.vulkan.shader.Pipeline; +import net.vulkanmod.vulkan.shader.PipelineState; +import net.vulkanmod.vulkan.shader.ShaderManager; +import net.vulkanmod.vulkan.shader.Uniforms; +import net.vulkanmod.vulkan.shader.layout.PushConstants; +import net.vulkanmod.vulkan.texture.VTextureSelector; +import net.vulkanmod.vulkan.util.VUtil; +import org.lwjgl.PointerBuffer; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.system.MemoryUtil; +import org.lwjgl.vulkan.*; + +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import java.nio.LongBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import static net.vulkanmod.vulkan.Vulkan.*; +import static org.lwjgl.system.MemoryStack.stackGet; +import static org.lwjgl.system.MemoryStack.stackPush; +import static org.lwjgl.vulkan.EXTDebugUtils.*; +import static org.lwjgl.vulkan.KHRSwapchain.*; +import static org.lwjgl.vulkan.VK10.*; + +public class Renderer { + private static Renderer INSTANCE; + + private static VkDevice device; + + private static boolean swapCahinUpdate = false; + public static boolean skipRendering = false; + + public static void initRenderer() { INSTANCE = new Renderer(); } + + public static Renderer getInstance() { return INSTANCE; } + + public static Drawer getDrawer() { return INSTANCE.drawer; } + + public static int getCurrentFrame() { return currentFrame; } + + private final Set usedPipelines = new ObjectOpenHashSet<>(); + + private final Drawer drawer; + + private int framesNum; + private List commandBuffers; + private ArrayList imageAvailableSemaphores; + private ArrayList renderFinishedSemaphores; + private ArrayList inFlightFences; + + private Framebuffer boundFramebuffer; + private RenderPass boundRenderPass; + + private static int currentFrame = 0; + private VkCommandBuffer currentCmdBuffer; + + MainPass mainPass = DefaultMainPass.PASS; + + private final List onResizeCallbacks = new ObjectArrayList<>(); + + public Renderer() { + device = Vulkan.getDevice(); + + Uniforms.setupDefaultUniforms(); + ShaderManager.init(); + AreaUploadManager.createInstance(); + + framesNum = getSwapChainImages().size(); + + drawer = new Drawer(); + drawer.createResources(framesNum); + + allocateCommandBuffers(); + createSyncObjects(); + + AreaUploadManager.INSTANCE.createLists(framesNum); + } + + private void allocateCommandBuffers() { + if(commandBuffers != null) { + commandBuffers.forEach(commandBuffer -> vkFreeCommandBuffers(device, Vulkan.getCommandPool(), commandBuffer)); + } + + commandBuffers = new ArrayList<>(framesNum); + + try(MemoryStack stack = stackPush()) { + + VkCommandBufferAllocateInfo allocInfo = VkCommandBufferAllocateInfo.calloc(stack); + allocInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO); + allocInfo.commandPool(getCommandPool()); + allocInfo.level(VK_COMMAND_BUFFER_LEVEL_PRIMARY); + allocInfo.commandBufferCount(framesNum); + + PointerBuffer pCommandBuffers = stack.mallocPointer(framesNum); + + if (vkAllocateCommandBuffers(device, allocInfo, pCommandBuffers) != VK_SUCCESS) { + throw new RuntimeException("Failed to allocate command buffers"); + } + + for (int i = 0; i < framesNum; i++) { + commandBuffers.add(new VkCommandBuffer(pCommandBuffers.get(i), device)); + } + } + } + + private void createSyncObjects() { + imageAvailableSemaphores = new ArrayList<>(framesNum); + renderFinishedSemaphores = new ArrayList<>(framesNum); + inFlightFences = new ArrayList<>(framesNum); + + try(MemoryStack stack = stackPush()) { + + VkSemaphoreCreateInfo semaphoreInfo = VkSemaphoreCreateInfo.calloc(stack); + semaphoreInfo.sType(VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO); + + VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.calloc(stack); + fenceInfo.sType(VK_STRUCTURE_TYPE_FENCE_CREATE_INFO); + fenceInfo.flags(VK_FENCE_CREATE_SIGNALED_BIT); + + LongBuffer pImageAvailableSemaphore = stack.mallocLong(1); + LongBuffer pRenderFinishedSemaphore = stack.mallocLong(1); + LongBuffer pFence = stack.mallocLong(1); + + for(int i = 0;i < framesNum; i++) { + + if(vkCreateSemaphore(device, semaphoreInfo, null, pImageAvailableSemaphore) != VK_SUCCESS + || vkCreateSemaphore(device, semaphoreInfo, null, pRenderFinishedSemaphore) != VK_SUCCESS + || vkCreateFence(device, fenceInfo, null, pFence) != VK_SUCCESS) { + + throw new RuntimeException("Failed to create synchronization objects for the frame " + i); + } + + imageAvailableSemaphores.add(pImageAvailableSemaphore.get(0)); + renderFinishedSemaphores.add(pRenderFinishedSemaphore.get(0)); + inFlightFences.add(pFence.get(0)); + + } + + } + } + + public void beginFrame() { + Profiler2 p = Profiler2.getMainProfiler(); + p.push("Frame_fence"); + + if(swapCahinUpdate) { + recreateSwapChain(); + swapCahinUpdate = false; + + if(getSwapChain().getWidth() == 0 && getSwapChain().getHeight() == 0) { + skipRendering = true; + Minecraft.getInstance().noRender = true; + } + else { + skipRendering = false; + Minecraft.getInstance().noRender = false; + } + } + + + if(skipRendering) + return; + + vkWaitForFences(device, inFlightFences.get(currentFrame), true, VUtil.UINT64_MAX); + + p.pop(); + p.start(); + p.push("Frame_ops"); + + AreaUploadManager.INSTANCE.updateFrame(currentFrame); + + MemoryManager.getInstance().initFrame(currentFrame); + drawer.setCurrentFrame(currentFrame); + + //Moved before texture updates +// this.vertexBuffers[currentFrame].reset(); +// this.uniformBuffers.reset(); +// Vulkan.getStagingBuffer(currentFrame).reset(); + + resetDescriptors(); + + currentCmdBuffer = commandBuffers.get(currentFrame); + vkResetCommandBuffer(currentCmdBuffer, 0); + + p.pop(); + + try(MemoryStack stack = stackPush()) { + + VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.calloc(stack); + beginInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO); + beginInfo.flags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); + + VkCommandBuffer commandBuffer = currentCmdBuffer; + + int err = vkBeginCommandBuffer(commandBuffer, beginInfo); + if (err != VK_SUCCESS) { + throw new RuntimeException("Failed to begin recording command buffer:" + err); + } + + mainPass.begin(commandBuffer, stack); + + vkCmdSetDepthBias(commandBuffer, 0.0F, 0.0F, 0.0F); + } + } + + public void endFrame() { + if(skipRendering) + return; + + mainPass.end(currentCmdBuffer); + + submitFrame(); + } + + public void endRenderPass() { + this.boundRenderPass.endRenderPass(currentCmdBuffer); + this.boundRenderPass = null; + } + + //TODO + public void beginRendering(Framebuffer framebuffer) { + if(skipRendering) + return; + + if(this.boundFramebuffer != framebuffer) { + this.endRendering(); + + try (MemoryStack stack = stackPush()) { + //TODO +// framebuffer.beginRenderPass(currentCmdBuffer, stack); + } + + this.boundFramebuffer = framebuffer; + } + } + + public void endRendering() { + if(skipRendering) + return; + + this.boundRenderPass.endRenderPass(currentCmdBuffer); + + this.boundFramebuffer = null; + this.boundRenderPass = null; + } + + public void setBoundFramebuffer(Framebuffer framebuffer) { + this.boundFramebuffer = framebuffer; + } + + public void resetBuffers() { + drawer.resetBuffers(currentFrame); + + Vulkan.getStagingBuffer(currentFrame).reset(); + } + + public void addUsedPipeline(Pipeline pipeline) { + usedPipelines.add(pipeline); + } + + public void removeUsedPipeline(Pipeline pipeline) { usedPipelines.remove(pipeline); } + + private void resetDescriptors() { + for(Pipeline pipeline : usedPipelines) { + pipeline.resetDescriptorPool(currentFrame); + } + + usedPipelines.clear(); + } + + private void submitFrame() { + if(swapCahinUpdate) + return; + + try(MemoryStack stack = stackPush()) { + + IntBuffer pImageIndex = stack.mallocInt(1); + + int vkResult = vkAcquireNextImageKHR(device, Vulkan.getSwapChain().getId(), VUtil.UINT64_MAX, + imageAvailableSemaphores.get(currentFrame), VK_NULL_HANDLE, pImageIndex); + + if(vkResult == VK_ERROR_OUT_OF_DATE_KHR || vkResult == VK_SUBOPTIMAL_KHR || swapCahinUpdate) { + swapCahinUpdate = true; +// shouldRecreate = false; +// waitForSwapChain(); +// recreateSwapChain(); +// shouldRecreate = true; + return; + } else if(vkResult != VK_SUCCESS) { + throw new RuntimeException("Cannot get image: " + vkResult); + } + + final int imageIndex = pImageIndex.get(0); + + VkSubmitInfo submitInfo = VkSubmitInfo.calloc(stack); + submitInfo.sType(VK_STRUCTURE_TYPE_SUBMIT_INFO); + + submitInfo.waitSemaphoreCount(1); + submitInfo.pWaitSemaphores(stackGet().longs(imageAvailableSemaphores.get(currentFrame))); + submitInfo.pWaitDstStageMask(stack.ints(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)); + + submitInfo.pSignalSemaphores(stackGet().longs(renderFinishedSemaphores.get(currentFrame))); + + submitInfo.pCommandBuffers(stack.pointers(currentCmdBuffer)); + + vkResetFences(device, stackGet().longs(inFlightFences.get(currentFrame))); + + Synchronization.INSTANCE.waitFences(); + + if((vkResult = vkQueueSubmit(getGraphicsQueue(), submitInfo, inFlightFences.get(currentFrame))) != VK_SUCCESS) { + vkResetFences(device, stackGet().longs(inFlightFences.get(currentFrame))); + throw new RuntimeException("Failed to submit draw command buffer: " + vkResult); + } + + VkPresentInfoKHR presentInfo = VkPresentInfoKHR.calloc(stack); + presentInfo.sType(VK_STRUCTURE_TYPE_PRESENT_INFO_KHR); + + presentInfo.pWaitSemaphores(stackGet().longs(renderFinishedSemaphores.get(currentFrame))); + + presentInfo.swapchainCount(1); + presentInfo.pSwapchains(stack.longs(Vulkan.getSwapChain().getId())); + + presentInfo.pImageIndices(pImageIndex); + + vkResult = vkQueuePresentKHR(getPresentQueue(), presentInfo); + + if(vkResult == VK_ERROR_OUT_OF_DATE_KHR || vkResult == VK_SUBOPTIMAL_KHR || swapCahinUpdate) { + swapCahinUpdate = true; +// shouldRecreate = false; +// recreateSwapChain(); + return; + } else if(vkResult != VK_SUCCESS) { + throw new RuntimeException("Failed to present swap chain image"); + } + + currentFrame = (currentFrame + 1) % framesNum; + } + } + + void waitForSwapChain() + { + vkResetFences(device, inFlightFences.get(currentFrame)); + +// constexpr VkPipelineStageFlags t=VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + try(MemoryStack stack = MemoryStack.stackPush()) { + //Empty Submit + VkSubmitInfo info = VkSubmitInfo.calloc(stack) + .sType$Default() + .pWaitSemaphores(stack.longs(imageAvailableSemaphores.get(currentFrame))) + .pWaitDstStageMask(stack.ints(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)); + + vkQueueSubmit(getGraphicsQueue(), info, inFlightFences.get(currentFrame)); + vkWaitForFences(device, inFlightFences.get(currentFrame), true, -1); + } + } + + private void recreateSwapChain() { +// for(Long fence : inFlightFences) { +// vkWaitForFences(device, fence, true, VUtil.UINT64_MAX); +// } + +// waitForSwapChain(); + Vulkan.waitIdle(); + +// for(int i = 0; i < getSwapChainImages().size(); ++i) { +// vkDestroyFence(device, inFlightFences.get(i), null); +// vkDestroySemaphore(device, imageAvailableSemaphores.get(i), null); +// vkDestroySemaphore(device, renderFinishedSemaphores.get(i), null); +// } + + commandBuffers.forEach(commandBuffer -> vkResetCommandBuffer(commandBuffer, 0)); + + Vulkan.recreateSwapChain(); + + int newFramesNum = getSwapChain().getFramesNum(); + + if(framesNum != newFramesNum) { + AreaUploadManager.INSTANCE.waitAllUploads(); + destroySyncObjects(); + + framesNum = newFramesNum; + createSyncObjects(); + allocateCommandBuffers(); + + Pipeline.recreateDescriptorSets(framesNum); + + drawer.createResources(framesNum); + AreaUploadManager.INSTANCE.createLists(framesNum); + } + + this.onResizeCallbacks.forEach(Runnable::run); + + currentFrame = 0; + } + + public void cleanUpResources() { + destroySyncObjects(); + + drawer.cleanUpResources(); + + ShaderManager.getInstance().destroyPipelines(); + VTextureSelector.getWhiteTexture().free(); + } + + private void destroySyncObjects() { + for (int i = 0; i < framesNum; ++i) { + vkDestroyFence(device, inFlightFences.get(i), null); + vkDestroySemaphore(device, imageAvailableSemaphores.get(i), null); + vkDestroySemaphore(device, renderFinishedSemaphores.get(i), null); + } + } + + public void setBoundRenderPass(RenderPass boundRenderPass) { + this.boundRenderPass = boundRenderPass; + } + + public RenderPass getBoundRenderPass() { + return boundRenderPass; + } + + public void setMainPass(MainPass mainPass) { this.mainPass = mainPass; } + + public void addOnResizeCallback(Runnable runnable) { + this.onResizeCallbacks.add(runnable); + } + + public void bindPipeline(Pipeline pipeline) { + VkCommandBuffer commandBuffer = currentCmdBuffer; + +// PipelineState currentState = new PipelineState(currentBlendState, currentDepthState, currentLogicOpState, currentColorMask, boundRenderPass); + PipelineState currentState = PipelineState.getCurrentPipelineState(boundRenderPass); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getHandle(currentState)); + + addUsedPipeline(pipeline); + } + + public void uploadAndBindUBOs(Pipeline pipeline) { + VkCommandBuffer commandBuffer = currentCmdBuffer; + pipeline.bindDescriptorSets(commandBuffer, currentFrame); + } + + public void pushConstants(Pipeline pipeline) { + VkCommandBuffer commandBuffer = currentCmdBuffer; + + PushConstants pushConstants = pipeline.getPushConstants(); + + try (MemoryStack stack = stackPush()) { + ByteBuffer buffer = stack.malloc(pushConstants.getSize()); + long ptr = MemoryUtil.memAddress0(buffer); + pushConstants.update(ptr); + + nvkCmdPushConstants(commandBuffer, pipeline.getLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, pushConstants.getSize(), ptr); + } + + } + + public static void setDepthBias(float units, float factor) { + VkCommandBuffer commandBuffer = INSTANCE.currentCmdBuffer; + + vkCmdSetDepthBias(commandBuffer, units, 0.0f, factor); + } + + public static void clearAttachments(int v) { + Framebuffer framebuffer = Renderer.getInstance().boundFramebuffer; + if(framebuffer == null) + return; + + clearAttachments(v, framebuffer.getWidth(), framebuffer.getHeight()); + } + + public static void clearAttachments(int v, int width, int height) { + if(skipRendering) + return; + + VkCommandBuffer commandBuffer = INSTANCE.currentCmdBuffer; + + try(MemoryStack stack = stackPush()) { + //ClearValues have to be different for each attachment to clear, it seems it works like a buffer: color and depth attributes override themselves + VkClearValue colorValue = VkClearValue.calloc(stack); + colorValue.color().float32(VRenderSystem.clearColor); + + VkClearValue depthValue = VkClearValue.calloc(stack); + depthValue.depthStencil().depth(VRenderSystem.clearDepth); + + int attachmentsCount; + VkClearAttachment.Buffer pAttachments; + if (v == 0x100) { + attachmentsCount = 1; + + pAttachments = VkClearAttachment.calloc(attachmentsCount, stack); + + VkClearAttachment clearDepth = pAttachments.get(0); + clearDepth.aspectMask(VK_IMAGE_ASPECT_DEPTH_BIT); + clearDepth.clearValue(depthValue); + } else if (v == 0x4000) { + attachmentsCount = 1; + + pAttachments = VkClearAttachment.calloc(attachmentsCount, stack); + + VkClearAttachment clearColor = pAttachments.get(0); + clearColor.aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); + clearColor.colorAttachment(0); + clearColor.clearValue(colorValue); + } else if (v == 0x4100) { + attachmentsCount = 2; + + pAttachments = VkClearAttachment.calloc(attachmentsCount, stack); + + VkClearAttachment clearColor = pAttachments.get(0); + clearColor.aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); + clearColor.clearValue(colorValue); + + VkClearAttachment clearDepth = pAttachments.get(1); + clearDepth.aspectMask(VK_IMAGE_ASPECT_DEPTH_BIT); + clearDepth.clearValue(depthValue); + } else { + throw new RuntimeException("unexpected value"); + } + + //Rect to clear + VkRect2D renderArea = VkRect2D.calloc(stack); + renderArea.offset(VkOffset2D.calloc(stack).set(0, 0)); + renderArea.extent(VkExtent2D.calloc(stack).set(width, height)); + + VkClearRect.Buffer pRect = VkClearRect.calloc(1, stack); + pRect.get(0).rect(renderArea); + pRect.get(0).layerCount(1); + + vkCmdClearAttachments(commandBuffer, pAttachments, pRect); + } + } + + public static void setViewport(int x, int y, int width, int height) { + try(MemoryStack stack = stackPush()) { + VkViewport.Buffer viewport = VkViewport.calloc(1, stack); + viewport.x(x); + viewport.y(height + y); + viewport.width(width); + viewport.height(-height); + viewport.minDepth(0.0f); + viewport.maxDepth(1.0f); + + VkRect2D.Buffer scissor = VkRect2D.malloc(1, stack); + scissor.offset(VkOffset2D.malloc(stack).set(0, 0)); + scissor.extent(VkExtent2D.malloc(stack).set(width, height)); + + vkCmdSetViewport(INSTANCE.currentCmdBuffer, 0, viewport); + vkCmdSetScissor(INSTANCE.currentCmdBuffer, 0, scissor); + } + } + + public static void setScissor(int x, int y, int width, int height) { + try(MemoryStack stack = stackPush()) { + int framebufferHeight = Renderer.getInstance().boundFramebuffer.getHeight(); + + VkRect2D.Buffer scissor = VkRect2D.malloc(1, stack); + scissor.offset(VkOffset2D.malloc(stack).set(x, framebufferHeight - (y + height))); + scissor.extent(VkExtent2D.malloc(stack).set(width, height)); + + vkCmdSetScissor(INSTANCE.currentCmdBuffer, 0, scissor); + } + } + + public static void resetScissor() { + try(MemoryStack stack = stackPush()) { + VkRect2D.Buffer scissor = Renderer.getInstance().boundFramebuffer.scissor(stack); + vkCmdSetScissor(INSTANCE.currentCmdBuffer, 0, scissor); + } + } + + public static void pushDebugSection(String s) { + if(Vulkan.ENABLE_VALIDATION_LAYERS) { + VkCommandBuffer commandBuffer = INSTANCE.currentCmdBuffer; + + try(MemoryStack stack = stackPush()) { + VkDebugUtilsLabelEXT markerInfo = VkDebugUtilsLabelEXT.calloc(stack); + markerInfo.sType(VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT); + ByteBuffer string = stack.UTF8(s); + markerInfo.pLabelName(string); + vkCmdBeginDebugUtilsLabelEXT(commandBuffer, markerInfo); + } + } + } + + public static void popDebugSection() { + if(Vulkan.ENABLE_VALIDATION_LAYERS) { + VkCommandBuffer commandBuffer = INSTANCE.currentCmdBuffer; + + vkCmdEndDebugUtilsLabelEXT(commandBuffer); + } + } + + public static void popPushDebugSection(String s) { + popDebugSection(); + pushDebugSection(s); + } + + public static int getFramesNum() { return INSTANCE.framesNum; } + + public static VkCommandBuffer getCommandBuffer() { return INSTANCE.currentCmdBuffer; } + + public static void scheduleSwapChainUpdate() { swapCahinUpdate = true; } +} diff --git a/src/main/java/net/vulkanmod/vulkan/VRenderSystem.java b/src/main/java/net/vulkanmod/vulkan/VRenderSystem.java index 27d722b19..d6e3a6c96 100644 --- a/src/main/java/net/vulkanmod/vulkan/VRenderSystem.java +++ b/src/main/java/net/vulkanmod/vulkan/VRenderSystem.java @@ -10,12 +10,11 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GameRenderer; import net.vulkanmod.vulkan.shader.PipelineState; +import net.vulkanmod.vulkan.util.ColorUtil; import net.vulkanmod.vulkan.util.MappedBuffer; import net.vulkanmod.vulkan.util.VUtil; import org.joml.Matrix4f; import org.lwjgl.system.MemoryUtil; -import oshi.SystemInfo; -import oshi.hardware.CentralProcessor; import java.nio.ByteBuffer; import java.nio.FloatBuffer; @@ -62,7 +61,7 @@ public static void initRenderer() public static ByteBuffer getChunkOffset() { return ChunkOffset.buffer; } public static int maxSupportedTextureSize() { - return Vulkan.deviceProperties.limits().maxImageDimension2D(); + return Device.deviceProperties.limits().maxImageDimension2D(); } public static void renderCrosshair(int p_69348_, boolean p_69349_, boolean p_69350_, boolean p_69351_) { @@ -166,17 +165,11 @@ public static void setChunkOffset(float f1, float f2, float f3) { } public static void setShaderColor(float f1, float f2, float f3, float f4) { - shaderColor.putFloat(0, f1); - shaderColor.putFloat(4, f2); - shaderColor.putFloat(8, f3); - shaderColor.putFloat(12, f4); + ColorUtil.setRGBA_Buffer(shaderColor, f1, f2, f3, f4); } public static void setShaderFogColor(float f1, float f2, float f3, float f4) { - shaderFogColor.putFloat(0, f1); - shaderFogColor.putFloat(4, f2); - shaderFogColor.putFloat(8, f3); - shaderFogColor.putFloat(12, f4); + ColorUtil.setRGBA_Buffer(shaderFogColor, f1, f2, f3, f4); } public static MappedBuffer getShaderColor() { @@ -188,26 +181,23 @@ public static MappedBuffer getShaderFogColor() { } public static void enableColorLogicOp() { - Drawer.currentLogicOpState = new PipelineState.LogicOpState(true, 0); + PipelineState.currentLogicOpState = new PipelineState.LogicOpState(true, 0); } public static void disableColorLogicOp() { - Drawer.currentLogicOpState = PipelineState.DEFAULT_LOGICOP_STATE; + PipelineState.currentLogicOpState = PipelineState.DEFAULT_LOGICOP_STATE; } public static void logicOp(GlStateManager.LogicOp p_69836_) { - Drawer.currentLogicOpState.setLogicOp(p_69836_); + PipelineState.currentLogicOpState.setLogicOp(p_69836_); } public static void clearColor(float f1, float f2, float f3, float f4) { - clearColor.put(0, f1); - clearColor.put(1, f2); - clearColor.put(2, f3); - clearColor.put(3, f4); + ColorUtil.setRGBA_Buffer(clearColor, f1, f2, f3, f4); } public static void clear(int v) { - Drawer.clearAttachments(v); + Renderer.clearAttachments(v); } public static void disableDepthTest() { @@ -248,11 +238,11 @@ public static void polygonOffset(float v, float v1) { } public static void enablePolygonOffset() { - Drawer.setDepthBias(depthBias[0], depthBias[1]); + Renderer.setDepthBias(depthBias[0], depthBias[1]); } public static void disablePolygonOffset() { - Drawer.setDepthBias(0.0F, 0.0F); + Renderer.setDepthBias(0.0F, 0.0F); } public static MappedBuffer getScreenSize() { @@ -276,26 +266,26 @@ public static void depthFunc(int p_69457_) { } public static void enableBlend() { - Drawer.blendInfo.enabled = true; + PipelineState.blendInfo.enabled = true; } public static void disableBlend() { - Drawer.blendInfo.enabled = false; + PipelineState.blendInfo.enabled = false; } public static void blendFunc(GlStateManager.SourceFactor sourceFactor, GlStateManager.DestFactor destFactor) { - Drawer.blendInfo.setBlendFunction(sourceFactor, destFactor); + PipelineState.blendInfo.setBlendFunction(sourceFactor, destFactor); } public static void blendFunc(int srcFactor, int dstFactor) { - Drawer.blendInfo.setBlendFunction(srcFactor, dstFactor); + PipelineState.blendInfo.setBlendFunction(srcFactor, dstFactor); } public static void blendFuncSeparate(GlStateManager.SourceFactor p_69417_, GlStateManager.DestFactor p_69418_, GlStateManager.SourceFactor p_69419_, GlStateManager.DestFactor p_69420_) { - Drawer.blendInfo.setBlendFuncSeparate(p_69417_, p_69418_, p_69419_, p_69420_); + PipelineState.blendInfo.setBlendFuncSeparate(p_69417_, p_69418_, p_69419_, p_69420_); } public static void blendFuncSeparate(int srcFactorRGB, int dstFactorRGB, int srcFactorAlpha, int dstFactorAlpha) { - Drawer.blendInfo.setBlendFuncSeparate(srcFactorRGB, dstFactorRGB, srcFactorAlpha, dstFactorAlpha); + PipelineState.blendInfo.setBlendFuncSeparate(srcFactorRGB, dstFactorRGB, srcFactorAlpha, dstFactorAlpha); } } diff --git a/src/main/java/net/vulkanmod/vulkan/Vulkan.java b/src/main/java/net/vulkanmod/vulkan/Vulkan.java index 745a85dec..52ed957d7 100644 --- a/src/main/java/net/vulkanmod/vulkan/Vulkan.java +++ b/src/main/java/net/vulkanmod/vulkan/Vulkan.java @@ -1,6 +1,6 @@ package net.vulkanmod.vulkan; -import net.vulkanmod.Initializer; +import net.vulkanmod.vulkan.framebuffer.SwapChain; import net.vulkanmod.vulkan.memory.Buffer; import net.vulkanmod.vulkan.memory.MemoryManager; import net.vulkanmod.vulkan.memory.MemoryTypes; @@ -9,6 +9,7 @@ import net.vulkanmod.vulkan.queue.Queue; import net.vulkanmod.vulkan.queue.TransferQueue; import net.vulkanmod.vulkan.shader.Pipeline; +import net.vulkanmod.vulkan.texture.VulkanImage; import net.vulkanmod.vulkan.util.VUtil; import org.lwjgl.PointerBuffer; import org.lwjgl.system.MemoryStack; @@ -18,12 +19,13 @@ import java.nio.IntBuffer; import java.nio.LongBuffer; -import java.util.*; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import java.util.stream.Stream; import static java.util.stream.Collectors.toSet; -import static net.vulkanmod.vulkan.SwapChain.querySwapChainSupport; -import static net.vulkanmod.vulkan.queue.Queue.findQueueFamilies; import static net.vulkanmod.vulkan.queue.Queue.getQueueFamilies; import static net.vulkanmod.vulkan.util.VUtil.asPointerBuffer; import static org.lwjgl.glfw.GLFWVulkan.glfwCreateWindowSurface; @@ -37,8 +39,6 @@ import static org.lwjgl.vulkan.KHRDynamicRendering.VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME; import static org.lwjgl.vulkan.KHRSwapchain.VK_KHR_SWAPCHAIN_EXTENSION_NAME; import static org.lwjgl.vulkan.VK10.*; -import static org.lwjgl.vulkan.VK11.VK_API_VERSION_1_1; -import static org.lwjgl.vulkan.VK11.vkEnumerateInstanceVersion; import static org.lwjgl.vulkan.VK12.VK_API_VERSION_1_2; public class Vulkan { @@ -46,8 +46,10 @@ public class Vulkan { public static final boolean ENABLE_VALIDATION_LAYERS = false; // public static final boolean ENABLE_VALIDATION_LAYERS = true; - public static final Set VALIDATION_LAYERS; +// public static final boolean DYNAMIC_RENDERING = true; + public static final boolean DYNAMIC_RENDERING = false; + public static final Set VALIDATION_LAYERS; static { if(ENABLE_VALIDATION_LAYERS) { VALIDATION_LAYERS = new HashSet<>(); @@ -60,11 +62,13 @@ public class Vulkan { } } - private static final Set DEVICE_EXTENSIONS = Stream.of( - VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME) + static final Set REQUIRED_EXTENSION = DYNAMIC_RENDERING ? Stream.of( + VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME) + .collect(toSet()) + : Stream.of( + VK_KHR_SWAPCHAIN_EXTENSION_NAME) .collect(toSet()); - private static int debugCallback(int messageSeverity, int messageType, long pCallbackData, long pUserData) { VkDebugUtilsMessengerCallbackDataEXT callbackData = VkDebugUtilsMessengerCallbackDataEXT.create(pCallbackData); @@ -106,7 +110,7 @@ private static void destroyDebugUtilsMessengerEXT(VkInstance instance, long debu } public static VkDevice getDevice() { - return device; + return Device.device; } public static long getAllocator() { @@ -119,18 +123,6 @@ public static long getAllocator() { private static long debugMessenger; private static long surface; - private static VkPhysicalDevice physicalDevice; - private static VkDevice device; - - private static DeviceInfo deviceInfo; - - public static VkPhysicalDeviceProperties deviceProperties; - public static VkPhysicalDeviceMemoryProperties memoryProperties; - - private static VkQueue graphicsQueue; - private static VkQueue presentQueue; - private static VkQueue transferQueue; - private static SwapChain swapChain; private static long commandPool; @@ -139,14 +131,17 @@ public static long getAllocator() { private static long allocator; + private static int FramesNum; private static StagingBuffer[] stagingBuffers; public static void initVulkan(long window) { createInstance(); setupDebugMessenger(); createSurface(window); - pickPhysicalDevice(); - createLogicalDevice(); + + Device.pickPhysicalDevice(instance); + Device.createLogicalDevice(); + createVma(); MemoryTypes.createMemoryTypes(); @@ -155,9 +150,10 @@ public static void initVulkan(long window) { allocateImmediateCmdBuffer(); createSwapChain(); + MemoryManager.createInstance(swapChain.getFramesNum()); createStagingBuffers(); - Drawer.initDrawer(); + Renderer.initRenderer(); } static void createStagingBuffers() { @@ -174,20 +170,29 @@ static void createStagingBuffers() { private static void createSwapChain() { swapChain = new SwapChain(); + + FramesNum = swapChain.getFramesNum(); } public static void recreateSwapChain() { - swapChain.recreateSwapChain(); + int newFramesNum = swapChain.recreateSwapChain(); + + if (FramesNum != newFramesNum) { + MemoryManager.createInstance(newFramesNum); + createStagingBuffers(); + } + + FramesNum = newFramesNum; } public static void waitIdle() { - vkDeviceWaitIdle(device); + vkDeviceWaitIdle(Device.device); } public static void cleanUp() { - vkDeviceWaitIdle(device); - vkDestroyCommandPool(device, commandPool, null); - vkDestroyFence(device, immediateFence, null); + vkDeviceWaitIdle(Device.device); + vkDestroyCommandPool(Device.device, commandPool, null); + vkDestroyFence(Device.device, immediateFence, null); GraphicsQueue.INSTANCE.cleanUp(); TransferQueue.INSTANCE.cleanUp(); @@ -195,7 +200,7 @@ public static void cleanUp() { Pipeline.destroyPipelineCache(); swapChain.cleanUp(); - Drawer.getInstance().cleanUpResources(); + Renderer.getInstance().cleanUpResources(); freeStagingBuffers(); try { @@ -206,7 +211,7 @@ public static void cleanUp() { vmaDestroyAllocator(allocator); - vkDestroyDevice(device, null); + vkDestroyDevice(Device.device, null); destroyDebugUtilsMessengerEXT(instance, debugMessenger, null); KHRSurface.vkDestroySurfaceKHR(instance, surface, null); vkDestroyInstance(instance, null); @@ -214,7 +219,7 @@ public static void cleanUp() { private static void freeStagingBuffers() { for(StagingBuffer buffer : stagingBuffers) { - MemoryManager.getInstance().freeBuffer(buffer.getId(), buffer.getAllocation()); + MemoryManager.freeBuffer(buffer.getId(), buffer.getAllocation()); } } @@ -228,7 +233,7 @@ private static void createInstance() { // Use calloc to initialize the structs with 0s. Otherwise, the program can crash due to random values - VkApplicationInfo appInfo = VkApplicationInfo.callocStack(stack); + VkApplicationInfo appInfo = VkApplicationInfo.calloc(stack); appInfo.sType(VK_STRUCTURE_TYPE_APPLICATION_INFO); appInfo.pApplicationName(stack.UTF8Safe("VulkanMod")); @@ -237,7 +242,7 @@ private static void createInstance() { appInfo.engineVersion(VK_MAKE_VERSION(1, 0, 0)); appInfo.apiVersion(VK_API_VERSION_1_2); - VkInstanceCreateInfo createInfo = VkInstanceCreateInfo.callocStack(stack); + VkInstanceCreateInfo createInfo = VkInstanceCreateInfo.calloc(stack); createInfo.sType(VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO); createInfo.pApplicationInfo(appInfo); @@ -248,7 +253,7 @@ private static void createInstance() { createInfo.ppEnabledLayerNames(asPointerBuffer(VALIDATION_LAYERS)); - VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo = VkDebugUtilsMessengerCreateInfoEXT.callocStack(stack); + VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo = VkDebugUtilsMessengerCreateInfoEXT.calloc(stack); populateDebugMessengerCreateInfo(debugCreateInfo); createInfo.pNext(debugCreateInfo.address()); } @@ -264,6 +269,26 @@ private static void createInstance() { } } + static boolean checkValidationLayerSupport() { + + try(MemoryStack stack = stackPush()) { + + IntBuffer layerCount = stack.ints(0); + + vkEnumerateInstanceLayerProperties(layerCount, null); + + VkLayerProperties.Buffer availableLayers = VkLayerProperties.malloc(layerCount.get(0), stack); + + vkEnumerateInstanceLayerProperties(layerCount, availableLayers); + + Set availableLayerNames = availableLayers.stream() + .map(VkLayerProperties::layerNameString) + .collect(toSet()); + + return availableLayerNames.containsAll(Vulkan.VALIDATION_LAYERS); + } + } + private static void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo) { debugCreateInfo.sType(VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT); // debugCreateInfo.messageSeverity(VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT); @@ -281,7 +306,7 @@ private static void setupDebugMessenger() { try(MemoryStack stack = stackPush()) { - VkDebugUtilsMessengerCreateInfoEXT createInfo = VkDebugUtilsMessengerCreateInfoEXT.callocStack(stack); + VkDebugUtilsMessengerCreateInfoEXT createInfo = VkDebugUtilsMessengerCreateInfoEXT.calloc(stack); populateDebugMessengerCreateInfo(createInfo); @@ -310,170 +335,17 @@ private static void createSurface(long handle) { } } - private static void pickPhysicalDevice() { - - try(MemoryStack stack = stackPush()) { - - IntBuffer deviceCount = stack.ints(0); - - vkEnumeratePhysicalDevices(instance, deviceCount, null); - - if(deviceCount.get(0) == 0) { - throw new RuntimeException("Failed to find GPUs with Vulkan support"); - } - - PointerBuffer ppPhysicalDevices = stack.mallocPointer(deviceCount.get(0)); - - vkEnumeratePhysicalDevices(instance, deviceCount, ppPhysicalDevices); - - ArrayList integratedGPUs = new ArrayList<>(); - ArrayList otherDevices = new ArrayList<>(); - - VkPhysicalDevice currentDevice = null; - boolean flag = false; - - for(int i = 0; i < ppPhysicalDevices.capacity();i++) { - - currentDevice = new VkPhysicalDevice(ppPhysicalDevices.get(i), instance); - - VkPhysicalDeviceProperties deviceProperties = VkPhysicalDeviceProperties.callocStack(stack); - vkGetPhysicalDeviceProperties(currentDevice, deviceProperties); - - if(isDeviceSuitable(currentDevice)) { - if(deviceProperties.deviceType() == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU){ - flag = true; - break; - } - else if(deviceProperties.deviceType() == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) integratedGPUs.add(currentDevice); - else otherDevices.add(currentDevice); - - } - } - - if(!flag) { - if(!integratedGPUs.isEmpty()) currentDevice = integratedGPUs.get(0); - else if(!otherDevices.isEmpty()) currentDevice = otherDevices.get(0); - else { - Initializer.LOGGER.error(DeviceInfo.debugString(ppPhysicalDevices, DEVICE_EXTENSIONS, instance)); - throw new RuntimeException("Failed to find a suitable GPU"); - } - } - - physicalDevice = currentDevice; - - //Get device properties - - deviceProperties = VkPhysicalDeviceProperties.malloc(); - vkGetPhysicalDeviceProperties(physicalDevice, deviceProperties); - - memoryProperties = VkPhysicalDeviceMemoryProperties.malloc(); - vkGetPhysicalDeviceMemoryProperties(physicalDevice, memoryProperties); - - deviceInfo = new DeviceInfo(physicalDevice, deviceProperties); - } - } - - private static void createLogicalDevice() { - - try(MemoryStack stack = stackPush()) { - - net.vulkanmod.vulkan.queue.Queue.QueueFamilyIndices indices = findQueueFamilies(physicalDevice); - - int[] uniqueQueueFamilies = indices.unique(); - - VkDeviceQueueCreateInfo.Buffer queueCreateInfos = VkDeviceQueueCreateInfo.callocStack(uniqueQueueFamilies.length, stack); - - for(int i = 0;i < uniqueQueueFamilies.length;i++) { - VkDeviceQueueCreateInfo queueCreateInfo = queueCreateInfos.get(i); - queueCreateInfo.sType(VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO); - queueCreateInfo.queueFamilyIndex(uniqueQueueFamilies[i]); - queueCreateInfo.pQueuePriorities(stack.floats(1.0f)); - } - - VkPhysicalDeviceFeatures2 deviceFeatures = VkPhysicalDeviceFeatures2.calloc(stack); - deviceFeatures.sType$Default(); - - if(deviceInfo.availableFeatures.features().samplerAnisotropy()) - deviceFeatures.features().samplerAnisotropy(true); - if(deviceInfo.availableFeatures.features().logicOp()) - deviceFeatures.features().logicOp(true); - - VkPhysicalDeviceVulkan11Features deviceVulkan11Features = VkPhysicalDeviceVulkan11Features.calloc(stack); - deviceVulkan11Features.sType$Default(); - - //TODO indirect draw option disabled in case it is not supported - if(deviceInfo.isDrawIndirectSupported()) { - deviceFeatures.features().multiDrawIndirect(true); - deviceVulkan11Features.shaderDrawParameters(true); - } - - VkDeviceCreateInfo createInfo = VkDeviceCreateInfo.callocStack(stack); - - createInfo.sType(VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO); - createInfo.pQueueCreateInfos(queueCreateInfos); - // queueCreateInfoCount is automatically set - - createInfo.pEnabledFeatures(deviceFeatures.features()); - - VkPhysicalDeviceDynamicRenderingFeaturesKHR dynamicRenderingFeaturesKHR = VkPhysicalDeviceDynamicRenderingFeaturesKHR.calloc(stack); - dynamicRenderingFeaturesKHR.sType$Default(); - dynamicRenderingFeaturesKHR.dynamicRendering(true); - - createInfo.pNext(deviceVulkan11Features); - deviceVulkan11Features.pNext(dynamicRenderingFeaturesKHR.address()); - - //Vulkan 1.3 dynamic rendering -// VkPhysicalDeviceVulkan13Features deviceVulkan13Features = VkPhysicalDeviceVulkan13Features.calloc(stack); -// deviceVulkan13Features.sType$Default(); -// if(!deviceInfo.availableFeatures13.dynamicRendering()) -// throw new RuntimeException("Device does not support dynamic rendering feature."); -// -// deviceVulkan13Features.dynamicRendering(true); -// createInfo.pNext(deviceVulkan13Features); -// deviceVulkan13Features.pNext(deviceVulkan11Features.address()); - - createInfo.ppEnabledExtensionNames(asPointerBuffer(DEVICE_EXTENSIONS)); - -// Configuration.DEBUG_FUNCTIONS.set(true); - - if(ENABLE_VALIDATION_LAYERS) { - createInfo.ppEnabledLayerNames(asPointerBuffer(VALIDATION_LAYERS)); - } - - PointerBuffer pDevice = stack.pointers(VK_NULL_HANDLE); - - if(vkCreateDevice(physicalDevice, createInfo, null, pDevice) != VK_SUCCESS) { - throw new RuntimeException("Failed to create logical device"); - } - - device = new VkDevice(pDevice.get(0), physicalDevice, createInfo, VK_API_VERSION_1_2); - - PointerBuffer pQueue = stack.pointers(VK_NULL_HANDLE); - - vkGetDeviceQueue(device, indices.graphicsFamily, 0, pQueue); - graphicsQueue = new VkQueue(pQueue.get(0), device); - - vkGetDeviceQueue(device, indices.presentFamily, 0, pQueue); - presentQueue = new VkQueue(pQueue.get(0), device); - - vkGetDeviceQueue(device, indices.transferFamily, 0, pQueue); - transferQueue = new VkQueue(pQueue.get(0), device); - - } - } - private static void createVma() { try(MemoryStack stack = stackPush()) { - VmaVulkanFunctions vulkanFunctions = VmaVulkanFunctions.callocStack(stack); - vulkanFunctions.set(instance, device); + VmaVulkanFunctions vulkanFunctions = VmaVulkanFunctions.calloc(stack); + vulkanFunctions.set(instance, Device.device); - VmaAllocatorCreateInfo allocatorCreateInfo = VmaAllocatorCreateInfo.callocStack(stack); - allocatorCreateInfo.physicalDevice(physicalDevice); - allocatorCreateInfo.device(device); + VmaAllocatorCreateInfo allocatorCreateInfo = VmaAllocatorCreateInfo.calloc(stack); + allocatorCreateInfo.physicalDevice(Device.physicalDevice); + allocatorCreateInfo.device(Device.device); allocatorCreateInfo.pVulkanFunctions(vulkanFunctions); allocatorCreateInfo.instance(instance); - allocatorCreateInfo.vulkanApiVersion(VK_API_VERSION_1_2); PointerBuffer pAllocator = stack.pointers(VK_NULL_HANDLE); @@ -491,14 +363,14 @@ private static void createCommandPool() { Queue.QueueFamilyIndices queueFamilyIndices = getQueueFamilies(); - VkCommandPoolCreateInfo poolInfo = VkCommandPoolCreateInfo.callocStack(stack); + VkCommandPoolCreateInfo poolInfo = VkCommandPoolCreateInfo.calloc(stack); poolInfo.sType(VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO); poolInfo.queueFamilyIndex(queueFamilyIndices.graphicsFamily); poolInfo.flags(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); LongBuffer pCommandPool = stack.mallocLong(1); - if (vkCreateCommandPool(device, poolInfo, null, pCommandPool) != VK_SUCCESS) { + if (vkCreateCommandPool(Device.device, poolInfo, null, pCommandPool) != VK_SUCCESS) { throw new RuntimeException("Failed to create command pool"); } @@ -506,57 +378,26 @@ private static void createCommandPool() { } } - private static int findSupportedFormat(IntBuffer formatCandidates, int tiling, int features) { - - try(MemoryStack stack = stackPush()) { - - VkFormatProperties props = VkFormatProperties.callocStack(stack); - - for(int i = 0; i < formatCandidates.capacity(); ++i) { - - int format = formatCandidates.get(i); - - vkGetPhysicalDeviceFormatProperties(physicalDevice, format, props); - - if(tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures() & features) == features) { - return format; - } else if(tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures() & features) == features) { - return format; - } - - } - } - - throw new RuntimeException("Failed to find supported format"); - } - - public static int findDepthFormat() { - return findSupportedFormat( - stackGet().ints(VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT), - VK_IMAGE_TILING_OPTIMAL, - VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); - } - private static void allocateImmediateCmdBuffer() { try(MemoryStack stack = stackPush()) { - VkCommandBufferAllocateInfo allocInfo = VkCommandBufferAllocateInfo.callocStack(stack); + VkCommandBufferAllocateInfo allocInfo = VkCommandBufferAllocateInfo.calloc(stack); allocInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO); allocInfo.level(VK_COMMAND_BUFFER_LEVEL_PRIMARY); allocInfo.commandPool(commandPool); allocInfo.commandBufferCount(1); PointerBuffer pCommandBuffer = stack.mallocPointer(1); - vkAllocateCommandBuffers(device, allocInfo, pCommandBuffer); - immediateCmdBuffer = new VkCommandBuffer(pCommandBuffer.get(0), device); + vkAllocateCommandBuffers(Device.device, allocInfo, pCommandBuffer); + immediateCmdBuffer = new VkCommandBuffer(pCommandBuffer.get(0), Device.device); - VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.callocStack(stack); + VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.calloc(stack); fenceInfo.sType(VK_STRUCTURE_TYPE_FENCE_CREATE_INFO); fenceInfo.flags(VK_FENCE_CREATE_SIGNALED_BIT); LongBuffer pFence = stack.mallocLong(1); - vkCreateFence(device, fenceInfo, null, pFence); - vkResetFences(device, pFence.get(0)); + vkCreateFence(Device.device, fenceInfo, null, pFence); + vkResetFences(Device.device, pFence.get(0)); immediateFence = pFence.get(0); } @@ -564,7 +405,7 @@ private static void allocateImmediateCmdBuffer() { public static VkCommandBuffer beginImmediateCmd() { try (MemoryStack stack = stackPush()) { - VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.callocStack(stack); + VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.calloc(stack); beginInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO); vkBeginCommandBuffer(immediateCmdBuffer, beginInfo); @@ -576,14 +417,14 @@ public static void endImmediateCmd() { try (MemoryStack stack = stackPush()) { vkEndCommandBuffer(immediateCmdBuffer); - VkSubmitInfo submitInfo = VkSubmitInfo.callocStack(stack); + VkSubmitInfo submitInfo = VkSubmitInfo.calloc(stack); submitInfo.sType(VK_STRUCTURE_TYPE_SUBMIT_INFO); submitInfo.pCommandBuffers(stack.pointers(immediateCmdBuffer)); - vkQueueSubmit(graphicsQueue, submitInfo, immediateFence); + vkQueueSubmit(Device.graphicsQueue, submitInfo, immediateFence); - vkWaitForFences(device, immediateFence, true, VUtil.UINT64_MAX); - vkResetFences(device, immediateFence); + vkWaitForFences(Device.device, immediateFence, true, VUtil.UINT64_MAX); + vkResetFences(Device.device, immediateFence); vkResetCommandBuffer(immediateCmdBuffer, 0); } @@ -609,89 +450,20 @@ private static PointerBuffer getRequiredExtensions() { return glfwExtensions; } - private static boolean isDeviceSuitable(VkPhysicalDevice device) { - - Queue.QueueFamilyIndices indices = findQueueFamilies(device); - - boolean extensionsSupported = checkDeviceExtensionSupport(device); - boolean swapChainAdequate = false; - - if(extensionsSupported) { - try(MemoryStack stack = stackPush()) { - SwapChain.SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device, stack); - swapChainAdequate = swapChainSupport.formats.hasRemaining() && swapChainSupport.presentModes.hasRemaining() ; - } - } - - boolean anisotropicFilterSuppoted = false; - try(MemoryStack stack = stackPush()) { - VkPhysicalDeviceFeatures supportedFeatures = VkPhysicalDeviceFeatures.mallocStack(stack); - vkGetPhysicalDeviceFeatures(device, supportedFeatures); - anisotropicFilterSuppoted = supportedFeatures.samplerAnisotropy(); - } - - return indices.isSuitable() && extensionsSupported && swapChainAdequate; - } - - private static boolean checkDeviceExtensionSupport(VkPhysicalDevice device) { - - try(MemoryStack stack = stackPush()) { - - IntBuffer extensionCount = stack.ints(0); - - vkEnumerateDeviceExtensionProperties(device, (String)null, extensionCount, null); - - VkExtensionProperties.Buffer availableExtensions = VkExtensionProperties.mallocStack(extensionCount.get(0), stack); - - vkEnumerateDeviceExtensionProperties(device, (String)null, extensionCount, availableExtensions); - - Set extensions = availableExtensions.stream() - .map(VkExtensionProperties::extensionNameString) - .collect(toSet()); - - extensions.removeAll(DEVICE_EXTENSIONS); - - return availableExtensions.stream() - .map(VkExtensionProperties::extensionNameString) - .collect(toSet()) - .containsAll(DEVICE_EXTENSIONS); - } - } - - private static boolean checkValidationLayerSupport() { - - try(MemoryStack stack = stackPush()) { - - IntBuffer layerCount = stack.ints(0); - - vkEnumerateInstanceLayerProperties(layerCount, null); - - VkLayerProperties.Buffer availableLayers = VkLayerProperties.mallocStack(layerCount.get(0), stack); - - vkEnumerateInstanceLayerProperties(layerCount, availableLayers); - - Set availableLayerNames = availableLayers.stream() - .map(VkLayerProperties::layerNameString) - .collect(toSet()); - - return availableLayerNames.containsAll(VALIDATION_LAYERS); - } - } - public static void setVsync(boolean b) { if(swapChain.isVsync() != b) { - Drawer.shouldRecreate = true; + Renderer.scheduleSwapChainUpdate(); swapChain.setVsync(b); } } public static long getSurface() { return surface; } - public static VkQueue getPresentQueue() { return presentQueue; } + public static VkQueue getPresentQueue() { return Device.presentQueue; } - public static VkQueue getGraphicsQueue() { return graphicsQueue; } + public static VkQueue getGraphicsQueue() { return Device.graphicsQueue; } - public static VkQueue getTransferQueue() { return transferQueue; } + public static VkQueue getTransferQueue() { return Device.transferQueue; } public static SwapChain getSwapChain() { return swapChain; } @@ -700,7 +472,7 @@ public static VkExtent2D getSwapchainExtent() return swapChain.getExtent(); } - public static List getSwapChainImages() { return swapChain.getImages(); } + public static List getSwapChainImages() { return swapChain.getImages(); } public static long getCommandPool() { @@ -709,6 +481,6 @@ public static long getCommandPool() public static StagingBuffer getStagingBuffer(int i) { return stagingBuffers[i]; } - public static DeviceInfo getDeviceInfo() { return deviceInfo; } + public static DeviceInfo getDeviceInfo() { return Device.deviceInfo; } } diff --git a/src/main/java/net/vulkanmod/vulkan/framebuffer/Framebuffer.java b/src/main/java/net/vulkanmod/vulkan/framebuffer/Framebuffer.java new file mode 100644 index 000000000..ed35460e6 --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/framebuffer/Framebuffer.java @@ -0,0 +1,255 @@ +package net.vulkanmod.vulkan.framebuffer; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.Reference2LongArrayMap; +import net.vulkanmod.vulkan.Renderer; +import net.vulkanmod.vulkan.Vulkan; +import net.vulkanmod.vulkan.texture.VTextureSelector; +import net.vulkanmod.vulkan.texture.VulkanImage; +import org.apache.commons.lang3.Validate; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.vulkan.*; + +import java.nio.LongBuffer; + +import static net.vulkanmod.vulkan.Vulkan.*; +import static org.lwjgl.vulkan.VK10.*; + +public class Framebuffer { + public static final int DEFAULT_FORMAT = VK_FORMAT_R8G8B8A8_UNORM; + +// private long id; + + protected int format; + protected int depthFormat; + protected int width, height; + protected boolean linearFiltering; + protected int attachmentCount; + + boolean hasColorAttachment; + boolean hasDepthAttachment; + + private VulkanImage colorAttachment; + protected VulkanImage depthAttachment; + + private final ObjectArrayList renderPasses = new ObjectArrayList<>(); + + private final Reference2LongArrayMap framebufferIds = new Reference2LongArrayMap<>(); + + //GL compatibility + public Framebuffer(VulkanImage colorAttachment) { + this.width = colorAttachment.width; + this.height = colorAttachment.height; + + this.colorAttachment = colorAttachment; + + this.depthFormat = SwapChain.getDefaultDepthFormat(); + this.depthAttachment = VulkanImage.createDepthImage(depthFormat, this.width, this.height, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + false, false); + } + + //SwapChain + protected Framebuffer() {} + + public Framebuffer(Builder builder) { + this.format = builder.format; + this.depthFormat = builder.depthFormat; + this.width = builder.width; + this.height = builder.height; + this.linearFiltering = builder.linearFiltering; + this.hasColorAttachment = builder.hasColorAttachment; + this.hasDepthAttachment = builder.hasDepthAttachment; + + this.createImages(); + } + + public void addRenderPass(RenderPass renderPass) { + this.renderPasses.add(renderPass); + } + + public void createImages() { + if(this.hasColorAttachment) { + this.colorAttachment = VulkanImage.createTextureImage(format, 1, width, height, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + 0, linearFiltering, true); + } + + if(this.hasDepthAttachment) { + this.depthAttachment = VulkanImage.createDepthImage(depthFormat, this.width, this.height, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + linearFiltering, true); + + this.attachmentCount++; + } + } + + public void resize(int newWidth, int newHeight) { + this.width = newWidth; + this.height = newHeight; + + this.cleanUp(); + + this.createImages(); + } + + private long createFramebuffer(RenderPass renderPass) { + + try(MemoryStack stack = MemoryStack.stackPush()) { + + LongBuffer attachments; + if(colorAttachment != null && depthAttachment != null) { + attachments = stack.longs(colorAttachment.getImageView(), depthAttachment.getImageView()); + } else if(colorAttachment != null) { + attachments = stack.longs(colorAttachment.getImageView()); + } else { + attachments = stack.longs(depthAttachment.getImageView()); + } + + LongBuffer pFramebuffer = stack.mallocLong(1); + + VkFramebufferCreateInfo framebufferInfo = VkFramebufferCreateInfo.callocStack(stack); + framebufferInfo.sType$Default(); + framebufferInfo.renderPass(renderPass.getId()); + framebufferInfo.width(this.width); + framebufferInfo.height(this.height); + framebufferInfo.layers(1); + framebufferInfo.pAttachments(attachments); + + if(VK10.vkCreateFramebuffer(Vulkan.getDevice(), framebufferInfo, null, pFramebuffer) != VK_SUCCESS) { + throw new RuntimeException("Failed to create framebuffer"); + } + + return pFramebuffer.get(0); + } + } + + public void beginRenderPass(VkCommandBuffer commandBuffer, RenderPass renderPass, MemoryStack stack) { + if(!DYNAMIC_RENDERING) { + long framebufferId = framebufferIds.computeIfAbsent(renderPass, renderPass1 -> createFramebuffer(renderPass)); + renderPass.beginRenderPass(commandBuffer, framebufferId, stack); + } + else + renderPass.beginDynamicRendering(commandBuffer, stack); + + Renderer.getInstance().setBoundRenderPass(renderPass); + Renderer.getInstance().setBoundFramebuffer(this); + } + + public static void endRenderPass(VkCommandBuffer commandBuffer) { + if(!DYNAMIC_RENDERING) + Renderer.getInstance().endRenderPass(); + else + KHRDynamicRendering.vkCmdEndRenderingKHR(commandBuffer); + + Renderer.getInstance().setBoundRenderPass(null); + } + + public void bindAsTexture(VkCommandBuffer commandBuffer, MemoryStack stack) { + this.colorAttachment.transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + VTextureSelector.bindFramebufferTexture(this.colorAttachment); + } + + public VkViewport.Buffer viewport(MemoryStack stack) { + VkViewport.Buffer viewport = VkViewport.callocStack(1, stack); + viewport.x(0.0f); + viewport.y(this.height); + viewport.width(this.width); + viewport.height(-this.height); + viewport.minDepth(0.0f); + viewport.maxDepth(1.0f); + + return viewport; + } + + public VkRect2D.Buffer scissor(MemoryStack stack) { + VkRect2D.Buffer scissor = VkRect2D.callocStack(1, stack); + scissor.offset(VkOffset2D.callocStack(stack).set(0, 0)); + scissor.extent(VkExtent2D.malloc(stack).set(this.width, this.height)); + + return scissor; + } + + public void cleanUp() { + if(this.colorAttachment != null) + this.colorAttachment.free(); + + if(this.depthAttachment != null) + this.depthAttachment.free(); + + final VkDevice device = Vulkan.getDevice(); + + framebufferIds.forEach((renderPass, id) -> { + vkDestroyFramebuffer(device, id, null); + }); + + framebufferIds.clear(); + + } + + public long getDepthImageView() { return depthAttachment.getImageView(); } + + public VulkanImage getDepthAttachment() { return depthAttachment; } + + public VulkanImage getColorAttachment() { return colorAttachment; } + + public int getWidth() { return this.width; } + + public int getHeight() { return this.height; } + + public int getFormat() { return this.format; } + + public int getDepthFormat() { return this.depthFormat; } + + public static class Builder { + final int width, height; + int format, depthFormat; + +// int colorAttachments; + boolean hasColorAttachment; + boolean hasDepthAttachment; + + boolean linearFiltering; + boolean depthLinearFiltering; + + public Builder(int width, int height, int colorAttachments, boolean hasDepthAttachment) { + Validate.isTrue(colorAttachments > 0 || hasDepthAttachment, "At least 1 attachment needed"); + + //TODO multi color attachments + Validate.isTrue(colorAttachments <= 1, "Not supported"); + + this.format = DEFAULT_FORMAT; + this.depthFormat = SwapChain.getDefaultDepthFormat(); + this.linearFiltering = true; + this.depthLinearFiltering = false; + + this.width = width; + this.height = height; + this.hasColorAttachment = colorAttachments == 1; + this.hasDepthAttachment = hasDepthAttachment; + } + + public Framebuffer build() { + return new Framebuffer(this); + } + + public Builder setFormat(int format) { + this.format = format; + + return this; + } + + public Builder setLinearFiltering(boolean b) { + this.linearFiltering = b; + + return this; + } + + public Builder setDepthLinearFiltering(boolean b) { + this.depthLinearFiltering = b; + + return this; + } + + } +} diff --git a/src/main/java/net/vulkanmod/vulkan/framebuffer/RenderPass.java b/src/main/java/net/vulkanmod/vulkan/framebuffer/RenderPass.java new file mode 100644 index 000000000..648ac7112 --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/framebuffer/RenderPass.java @@ -0,0 +1,310 @@ +package net.vulkanmod.vulkan.framebuffer; + +import net.vulkanmod.vulkan.Renderer; +import net.vulkanmod.vulkan.VRenderSystem; +import net.vulkanmod.vulkan.Vulkan; +import net.vulkanmod.vulkan.texture.VulkanImage; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.vulkan.*; + +import java.nio.LongBuffer; + +import static org.lwjgl.vulkan.VK10.*; + +public class RenderPass { + Framebuffer framebuffer; + long id; + + final int attachmentCount; + AttachmentInfo colorAttachmentInfo; + AttachmentInfo depthAttachmentInfo; + + int finalColorLayout; + int finalDepthLayout; + + public RenderPass(Framebuffer framebuffer, AttachmentInfo colorAttachmentInfo, AttachmentInfo depthAttachmentInfo) { + this.framebuffer = framebuffer; + this.colorAttachmentInfo = colorAttachmentInfo; + this.depthAttachmentInfo = depthAttachmentInfo; + + int count = 0; + if(colorAttachmentInfo != null) + count++; + if(depthAttachmentInfo != null) + count++; + + this.attachmentCount = count; + + if(!Vulkan.DYNAMIC_RENDERING) { + framebuffer.addRenderPass(this); + + createRenderPass(); + } + + } + + private void createRenderPass() { + + try(MemoryStack stack = MemoryStack.stackPush()) { + + VkAttachmentDescription.Buffer attachments = VkAttachmentDescription.calloc(attachmentCount, stack); + VkAttachmentReference.Buffer attachmentRefs = VkAttachmentReference.calloc(attachmentCount, stack); + + VkSubpassDescription.Buffer subpass = VkSubpassDescription.calloc(1, stack); + subpass.pipelineBindPoint(VK_PIPELINE_BIND_POINT_GRAPHICS); + + int i = 0; + + // Color attachment + if(colorAttachmentInfo != null) { + VkAttachmentDescription colorAttachment = attachments.get(i); + colorAttachment.format(colorAttachmentInfo.format); + colorAttachment.samples(VK_SAMPLE_COUNT_1_BIT); + colorAttachment.loadOp(colorAttachmentInfo.loadOp); + colorAttachment.storeOp(colorAttachmentInfo.storeOp); + colorAttachment.stencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE); + colorAttachment.stencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE); + + colorAttachment.initialLayout(colorAttachmentInfo.initialLayout); + colorAttachment.finalLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + VkAttachmentReference colorAttachmentRef = attachmentRefs.get(0); + colorAttachmentRef.attachment(0); + colorAttachmentRef.layout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + subpass.colorAttachmentCount(1); + subpass.pColorAttachments(VkAttachmentReference.calloc(1, stack).put(0, colorAttachmentRef)); + + ++i; + } + + + // Depth-Stencil attachment + if(depthAttachmentInfo != null) { + VkAttachmentDescription depthAttachment = attachments.get(i); + depthAttachment.format(depthAttachmentInfo.format); + depthAttachment.samples(VK_SAMPLE_COUNT_1_BIT); + depthAttachment.loadOp(depthAttachmentInfo.loadOp); + depthAttachment.storeOp(depthAttachmentInfo.storeOp); + depthAttachment.stencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE); + depthAttachment.stencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE); + depthAttachment.initialLayout(depthAttachmentInfo.initialLayout); + depthAttachment.finalLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + + VkAttachmentReference depthAttachmentRef = attachmentRefs.get(1); + depthAttachmentRef.attachment(1); + depthAttachmentRef.layout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + + subpass.pDepthStencilAttachment(depthAttachmentRef); + } + + VkRenderPassCreateInfo renderPassInfo = VkRenderPassCreateInfo.calloc(stack); + renderPassInfo.sType$Default(); + renderPassInfo.pAttachments(attachments); + renderPassInfo.pSubpasses(subpass); + + LongBuffer pRenderPass = stack.mallocLong(1); + + if(vkCreateRenderPass(Vulkan.getDevice(), renderPassInfo, null, pRenderPass) != VK_SUCCESS) { + throw new RuntimeException("Failed to create render pass"); + } + + id = pRenderPass.get(0); + + finalColorLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + finalDepthLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + } + } + + public void beginRenderPass(VkCommandBuffer commandBuffer, long framebufferId, MemoryStack stack) { + + if(colorAttachmentInfo != null && colorAttachmentInfo.initialLayout != VK_IMAGE_LAYOUT_UNDEFINED + && colorAttachmentInfo.initialLayout != framebuffer.getColorAttachment().getCurrentLayout()) +// throw new RuntimeException("current layout does not match expected initial layout"); + framebuffer.getColorAttachment().transitionImageLayout(stack, commandBuffer, colorAttachmentInfo.initialLayout); + if(depthAttachmentInfo != null && depthAttachmentInfo.initialLayout != VK_IMAGE_LAYOUT_UNDEFINED + && depthAttachmentInfo.initialLayout != framebuffer.getDepthAttachment().getCurrentLayout()) +// throw new RuntimeException("current layout does not match expected initial layout"); + framebuffer.getDepthAttachment().transitionImageLayout(stack, commandBuffer, depthAttachmentInfo.initialLayout); + + VkRenderPassBeginInfo renderPassInfo = VkRenderPassBeginInfo.callocStack(stack); + renderPassInfo.sType$Default(); + renderPassInfo.renderPass(this.id); + renderPassInfo.framebuffer(framebufferId); + + VkRect2D renderArea = VkRect2D.calloc(stack); + renderArea.offset(VkOffset2D.calloc(stack).set(0, 0)); + renderArea.extent(VkExtent2D.calloc(stack).set(framebuffer.getWidth(), framebuffer.getHeight())); + renderPassInfo.renderArea(renderArea); + + VkClearValue.Buffer clearValues; + clearValues = VkClearValue.calloc(2, stack); + clearValues.get(0).color().float32(VRenderSystem.clearColor); + clearValues.get(1).depthStencil().set(1.0f, 0); + + renderPassInfo.pClearValues(clearValues); + + vkCmdBeginRenderPass(commandBuffer, renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); + + Renderer.getInstance().setBoundRenderPass(this); + } + + public void endRenderPass(VkCommandBuffer commandBuffer) { + vkCmdEndRenderPass(commandBuffer); + + if(colorAttachmentInfo != null) + framebuffer.getColorAttachment().setCurrentLayout(finalColorLayout); + + if(depthAttachmentInfo != null) + framebuffer.getDepthAttachment().setCurrentLayout(finalDepthLayout); + + Renderer.getInstance().setBoundRenderPass(null); + } + + public void beginDynamicRendering(VkCommandBuffer commandBuffer, MemoryStack stack) { + VkRect2D renderArea = VkRect2D.calloc(stack); + renderArea.offset(VkOffset2D.calloc(stack).set(0, 0)); + renderArea.extent(VkExtent2D.calloc(stack).set(framebuffer.getWidth(), framebuffer.getHeight())); + + VkClearValue.Buffer clearValues; + clearValues = VkClearValue.calloc(2, stack); + clearValues.get(0).color().float32(stack.floats(0.0f, 0.0f, 0.0f, 1.0f)); + clearValues.get(1).depthStencil().set(1.0f, 0); + + VkRenderingInfo renderingInfo = VkRenderingInfo.calloc(stack); + renderingInfo.sType(KHRDynamicRendering.VK_STRUCTURE_TYPE_RENDERING_INFO_KHR); + renderingInfo.renderArea(renderArea); + renderingInfo.layerCount(1); + + // Color attachment + if(colorAttachmentInfo != null) { + VkRenderingAttachmentInfo.Buffer colorAttachment = VkRenderingAttachmentInfo.calloc(1, stack); + colorAttachment.sType(KHRDynamicRendering.VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR); + colorAttachment.imageView(framebuffer.getColorAttachment().getImageView()); + colorAttachment.imageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + colorAttachment.loadOp(colorAttachmentInfo.loadOp); + colorAttachment.storeOp(colorAttachmentInfo.storeOp); + colorAttachment.clearValue(clearValues.get(0)); + + renderingInfo.pColorAttachments(colorAttachment); + } + + //Depth attachment + if(depthAttachmentInfo != null) { + VkRenderingAttachmentInfo depthAttachment = VkRenderingAttachmentInfo.calloc(stack); + depthAttachment.sType(KHRDynamicRendering.VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR); + depthAttachment.imageView(framebuffer.getDepthAttachment().getImageView()); + depthAttachment.imageLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + depthAttachment.loadOp(depthAttachmentInfo.loadOp); + depthAttachment.storeOp(depthAttachmentInfo.storeOp); + depthAttachment.clearValue(clearValues.get(1)); + + renderingInfo.pDepthAttachment(depthAttachment); + } + + KHRDynamicRendering.vkCmdBeginRenderingKHR(commandBuffer, renderingInfo); + } + + public void endDynamicRendering(VkCommandBuffer commandBuffer) { + KHRDynamicRendering.vkCmdEndRenderingKHR(commandBuffer); + } + + public Framebuffer getFramebuffer() { + return framebuffer; + } + + public void cleanUp() { + //TODO + + if(!Vulkan.DYNAMIC_RENDERING) + vkDestroyRenderPass(Vulkan.getDevice(), this.id, null); + } + + public long getId() { + return id; + } + + public static class AttachmentInfo { + final Type type; + final int format; + VulkanImage attachment; + int initialLayout; + int loadOp; + int storeOp; + + public AttachmentInfo(Type type, int format) { + this.type = type; + this.format = format; + this.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + this.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + this.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + } + + public AttachmentInfo setOps(int loadOp, int storeOp) { + this.loadOp = loadOp; + this.storeOp = storeOp; + + return this; + } + + public AttachmentInfo setLoadOp(int loadOp) { + this.loadOp = loadOp; + + return this; + } + + public AttachmentInfo setInitialLayout(int initialLayout) { + this.initialLayout = initialLayout; + + return this; + } + + public enum Type { + COLOR, + DEPTH + } + } + + public static class Builder { + Framebuffer framebuffer; + AttachmentInfo colorAttachmentInfo; + AttachmentInfo depthAttachmentInfo; + + public Builder(Framebuffer framebuffer) { + this.framebuffer = framebuffer; + + if(framebuffer.hasColorAttachment) + colorAttachmentInfo = new AttachmentInfo(AttachmentInfo.Type.COLOR, framebuffer.format); + if(framebuffer.hasDepthAttachment) + depthAttachmentInfo = new AttachmentInfo(AttachmentInfo.Type.DEPTH, framebuffer.depthFormat); + } + + public RenderPass build() { + return new RenderPass(framebuffer, colorAttachmentInfo, depthAttachmentInfo); + } + + public Builder setLoadOp(int loadOp) { + if(colorAttachmentInfo != null) { + colorAttachmentInfo.setLoadOp(loadOp); + colorAttachmentInfo.setInitialLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + } + if(depthAttachmentInfo != null) { + depthAttachmentInfo.setLoadOp(loadOp); + depthAttachmentInfo.setInitialLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + } + + + return this; + } + + public AttachmentInfo getColorAttachmentInfo() { + return colorAttachmentInfo; + } + + public AttachmentInfo getDepthAttachmentInfo() { + return depthAttachmentInfo; + } + } +} diff --git a/src/main/java/net/vulkanmod/vulkan/SwapChain.java b/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java similarity index 53% rename from src/main/java/net/vulkanmod/vulkan/SwapChain.java rename to src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java index 31277eea8..32e80f80e 100644 --- a/src/main/java/net/vulkanmod/vulkan/SwapChain.java +++ b/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java @@ -1,8 +1,11 @@ -package net.vulkanmod.vulkan; +package net.vulkanmod.vulkan.framebuffer; -import net.minecraft.util.Mth; import net.vulkanmod.Initializer; -import net.vulkanmod.vulkan.memory.MemoryManager; +import net.vulkanmod.render.util.MathUtil; +import net.vulkanmod.vulkan.Device; +import net.vulkanmod.vulkan.Renderer; +import net.vulkanmod.vulkan.Synchronization; +import net.vulkanmod.vulkan.Vulkan; import net.vulkanmod.vulkan.queue.Queue; import net.vulkanmod.vulkan.texture.VulkanImage; import org.lwjgl.system.MemoryStack; @@ -11,10 +14,10 @@ import java.nio.IntBuffer; import java.nio.LongBuffer; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; -import static net.vulkanmod.vulkan.Vulkan.getSwapchainExtent; -import static net.vulkanmod.vulkan.Vulkan.window; +import static net.vulkanmod.vulkan.Vulkan.*; import static net.vulkanmod.vulkan.util.VUtil.UINT32_MAX; import static org.lwjgl.glfw.GLFW.glfwGetFramebufferSize; import static org.lwjgl.system.MemoryStack.stackGet; @@ -24,59 +27,81 @@ import static org.lwjgl.vulkan.VK10.*; public class SwapChain extends Framebuffer { + private static int DEFAULT_DEPTH_FORMAT = 0; + + public static int getDefaultDepthFormat() { + return DEFAULT_DEPTH_FORMAT; + } + + private RenderPass renderPass; + private long[] framebuffers; private long swapChain = VK_NULL_HANDLE; - private List swapChainImages; + private List swapChainImages; private VkExtent2D extent2D; - private List imageViews; public boolean isBGRAformat; private boolean vsync = false; - private final int framesNum; - private int[] currentLayout; public SwapChain() { - this.framesNum = Initializer.CONFIG.frameQueueSize; - createSwapChain(this.framesNum); + DEFAULT_DEPTH_FORMAT = Device.findDepthFormat(); - MemoryManager.createInstance(this.swapChainImages.size()); + this.attachmentCount = 2; + + this.depthFormat = DEFAULT_DEPTH_FORMAT; + createSwapChain(); - this.depthFormat = Vulkan.findDepthFormat(); - createDepthResources(false); } - public void recreateSwapChain() { + public int recreateSwapChain() { Synchronization.INSTANCE.waitFences(); - createSwapChain(this.framesNum); - - int framesNum = this.swapChainImages.size(); + if(this.depthAttachment != null) { + this.depthAttachment.free(); + this.depthAttachment = null; + } - if (MemoryManager.getFrames() != framesNum) { - MemoryManager.createInstance(framesNum); + if(!DYNAMIC_RENDERING && framebuffers != null) { +// this.renderPass.cleanUp(); + Arrays.stream(framebuffers).forEach(id -> vkDestroyFramebuffer(getDevice(), id, null)); + framebuffers = null; } - this.depthAttachment.free(); - createDepthResources(false); + createSwapChain(); + + return this.swapChainImages.size(); } - private void createSwapChain(int preferredImageCount) { + public void createSwapChain() { + int requestedFrames = Initializer.CONFIG.frameQueueSize; try(MemoryStack stack = stackPush()) { VkDevice device = Vulkan.getDevice(); - SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device.getPhysicalDevice(), stack); - - VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats); - int presentMode = chooseSwapPresentMode(swapChainSupport.presentModes); - VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities); + Device.SurfaceProperties surfaceProperties = Device.querySurfaceProperties(device.getPhysicalDevice(), stack); + + VkSurfaceFormatKHR surfaceFormat = getFormat(surfaceProperties.formats); + int presentMode = getPresentMode(surfaceProperties.presentModes); + VkExtent2D extent = getExtent(surfaceProperties.capabilities); + + if(extent.width() == 0 && extent.height() == 0) { + if(swapChain != VK_NULL_HANDLE) { + this.swapChainImages.forEach(image -> vkDestroyImageView(device, image.getImageView(), null)); + vkDestroySwapchainKHR(device, swapChain, null); + swapChain = VK_NULL_HANDLE; + } + + this.width = 0; + this.height = 0; + return; + } //Workaround for Mesa - IntBuffer imageCount = stack.ints(preferredImageCount); -// IntBuffer imageCount = stack.ints(Math.max(swapChainSupport.capabilities.minImageCount(), preferredImageCount)); + IntBuffer imageCount = stack.ints(requestedFrames); +// IntBuffer imageCount = stack.ints(Math.max(surfaceProperties.capabilities.minImageCount(), preferredImageCount)); - if(swapChainSupport.capabilities.maxImageCount() > 0 && imageCount.get(0) > swapChainSupport.capabilities.maxImageCount()) { - imageCount.put(0, swapChainSupport.capabilities.maxImageCount()); + if(surfaceProperties.capabilities.maxImageCount() > 0 && imageCount.get(0) > surfaceProperties.capabilities.maxImageCount()) { + imageCount.put(0, surfaceProperties.capabilities.maxImageCount()); } VkSwapchainCreateInfoKHR createInfo = VkSwapchainCreateInfoKHR.callocStack(stack); @@ -104,7 +129,7 @@ private void createSwapChain(int preferredImageCount) { createInfo.imageSharingMode(VK_SHARING_MODE_EXCLUSIVE); } - createInfo.preTransform(swapChainSupport.capabilities.currentTransform()); + createInfo.preTransform(surfaceProperties.capabilities.currentTransform()); createInfo.compositeAlpha(VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR); createInfo.presentMode(presentMode); createInfo.clipped(true); @@ -118,7 +143,7 @@ private void createSwapChain(int preferredImageCount) { } if(swapChain != VK_NULL_HANDLE) { - this.imageViews.forEach(imageView -> vkDestroyImageView(device, imageView, null)); + this.swapChainImages.forEach(iamge -> vkDestroyImageView(device, iamge.getImageView(), null)); vkDestroySwapchainKHR(device, swapChain, null); } @@ -132,53 +157,80 @@ private void createSwapChain(int preferredImageCount) { swapChainImages = new ArrayList<>(imageCount.get(0)); - for(int i = 0;i < pSwapchainImages.capacity();i++) { - swapChainImages.add(pSwapchainImages.get(i)); - } - - createImageViews(this.format); - this.width = extent2D.width(); this.height = extent2D.height(); + + for(int i = 0;i < pSwapchainImages.capacity(); i++) { + long imageId = pSwapchainImages.get(i); + long imageView = VulkanImage.createImageView(imageId, this.format, VK_IMAGE_ASPECT_COLOR_BIT, 1); + + swapChainImages.add(new VulkanImage(imageId, this.format, 1, this.width, this.height, 4, 0, imageView)); + } currentLayout = new int[this.swapChainImages.size()]; + + createDepthResources(); + + //RenderPass + if(this.renderPass == null) + createRenderPass(); + + if(!DYNAMIC_RENDERING) + createFramebuffers(); + } } - public void transitionImageLayout(MemoryStack stack, VkCommandBuffer commandBuffer, int newLayout, int frame) { - VulkanImage.transitionImageLayout(stack, commandBuffer, this.getImageId(frame), this.format, this.currentLayout[frame], newLayout, 1); - this.currentLayout[frame] = newLayout; + private void createRenderPass() { + this.hasColorAttachment = true; + this.hasDepthAttachment = true; + + this.renderPass = new RenderPass.Builder(this).build(); + } + + private void createFramebuffers() { + + try(MemoryStack stack = MemoryStack.stackPush()) { + + framebuffers = new long[swapChainImages.size()]; + + for(int i = 0; i < swapChainImages.size(); ++i) { + +// LongBuffer attachments = stack.longs(imageViews.get(i), depthAttachment.getImageView()); + LongBuffer attachments = stack.longs(this.swapChainImages.get(i).getImageView(), depthAttachment.getImageView()); + + //attachments = stack.mallocLong(1); + LongBuffer pFramebuffer = stack.mallocLong(1); + + VkFramebufferCreateInfo framebufferInfo = VkFramebufferCreateInfo.calloc(stack); + framebufferInfo.sType(VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO); + framebufferInfo.renderPass(this.renderPass.getId()); + framebufferInfo.width(this.width); + framebufferInfo.height(this.height); + framebufferInfo.layers(1); + framebufferInfo.pAttachments(attachments); + + if(vkCreateFramebuffer(Vulkan.getDevice(), framebufferInfo, null, pFramebuffer) != VK_SUCCESS) { + throw new RuntimeException("Failed to create framebuffer"); + } + + this.framebuffers[i] = pFramebuffer.get(0); + } + } } - public void beginRendering(VkCommandBuffer commandBuffer, MemoryStack stack) { - VkRect2D renderArea = VkRect2D.callocStack(stack); - renderArea.offset(VkOffset2D.callocStack(stack).set(0, 0)); - renderArea.extent(getSwapchainExtent()); - - VkRenderingAttachmentInfo.Buffer colorAttachment = VkRenderingAttachmentInfo.calloc(1, stack); - colorAttachment.sType(KHRDynamicRendering.VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR); - colorAttachment.imageView(this.getImageView(Drawer.getCurrentFrame())); - colorAttachment.imageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - colorAttachment.loadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE); - colorAttachment.storeOp(VK_ATTACHMENT_STORE_OP_STORE); -// colorAttachment.clearValue(clearValues.get(0)); - - VkRenderingAttachmentInfo depthAttachment = VkRenderingAttachmentInfo.calloc(stack); - depthAttachment.sType(KHRDynamicRendering.VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR); - depthAttachment.imageView(this.getDepthImageView()); - depthAttachment.imageLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - depthAttachment.loadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE); - depthAttachment.storeOp(VK_ATTACHMENT_STORE_OP_STORE); -// depthAttachment.clearValue(clearValues.get(1)); - - VkRenderingInfo renderingInfo = VkRenderingInfo.calloc(stack); - renderingInfo.sType(KHRDynamicRendering.VK_STRUCTURE_TYPE_RENDERING_INFO_KHR); - renderingInfo.renderArea(renderArea); - renderingInfo.layerCount(1); - renderingInfo.pColorAttachments(colorAttachment); - renderingInfo.pDepthAttachment(depthAttachment); - -// vkCmdBeginRendering(commandBuffer, renderingInfo); - KHRDynamicRendering.vkCmdBeginRenderingKHR(commandBuffer, renderingInfo); + public void beginRenderPass(VkCommandBuffer commandBuffer, MemoryStack stack) { + if(DYNAMIC_RENDERING) { +// this.colorAttachmentLayout(stack, commandBuffer, Drawer.getCurrentFrame()); +// beginDynamicRendering(commandBuffer, stack); + + this.renderPass.beginDynamicRendering(commandBuffer, stack); + } + else { + this.renderPass.beginRenderPass(commandBuffer, this.framebuffers[Renderer.getCurrentFrame()], stack); + } + + Renderer.getInstance().setBoundRenderPass(renderPass); + Renderer.getInstance().setBoundFramebuffer(this); } public void colorAttachmentLayout(MemoryStack stack, VkCommandBuffer commandBuffer, int frame) { @@ -188,7 +240,7 @@ public void colorAttachmentLayout(MemoryStack stack, VkCommandBuffer commandBuff barrier.oldLayout(this.currentLayout[frame]); // barrier.oldLayout(VK_IMAGE_LAYOUT_UNDEFINED); barrier.newLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - barrier.image(this.swapChainImages.get(frame)); + barrier.image(this.swapChainImages.get(frame).getId()); // barrier.srcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); barrier.subresourceRange().baseMipLevel(0); @@ -217,7 +269,7 @@ public void presentLayout(MemoryStack stack, VkCommandBuffer commandBuffer, int barrier.dstAccessMask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); barrier.oldLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); barrier.newLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); - barrier.image(this.swapChainImages.get(frame)); + barrier.image(this.swapChainImages.get(frame).getId()); barrier.subresourceRange().baseMipLevel(0); barrier.subresourceRange().levelCount(1); @@ -242,79 +294,49 @@ public void cleanUp() { VkDevice device = Vulkan.getDevice(); // framebuffers.forEach(framebuffer -> vkDestroyFramebuffer(device, framebuffer, null)); + + if(!DYNAMIC_RENDERING) { + Arrays.stream(framebuffers).forEach(id -> vkDestroyFramebuffer(device, id, null)); + } + vkDestroySwapchainKHR(device, this.swapChain, null); - imageViews.forEach(imageView -> vkDestroyImageView(device, imageView, null)); + swapChainImages.forEach(image -> vkDestroyImageView(device, image.getImageView(), null)); this.depthAttachment.free(); } - private void createImageViews(int format) { - imageViews = new ArrayList<>(swapChainImages.size()); - - for(long swapChainImage : swapChainImages) { - imageViews.add(VulkanImage.createImageView(swapChainImage, format, VK_IMAGE_ASPECT_COLOR_BIT, 1)); - } - + private void createDepthResources() { + this.depthAttachment = VulkanImage.createDepthImage(depthFormat, this.width, this.height, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + false, false); } public long getId() { return swapChain; } - public List getImages() { + public List getImages() { return swapChainImages; } public long getImageId(int i) { - return swapChainImages.get(i); + return swapChainImages.get(i).getId(); } public VkExtent2D getExtent() { return extent2D; } -// public List getFramebuffers() { -// return swapChainFramebuffers.getFramebuffers(); -// } - - public List getImageViews() { - return this.imageViews; + public VulkanImage getColorAttachment() { + return this.swapChainImages.get(Renderer.getCurrentFrame()); } - public long getImageView(int i) { return this.imageViews.get(i); } - - static SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device, MemoryStack stack) { - - long surface = Vulkan.getSurface(); - SwapChainSupportDetails details = new SwapChainSupportDetails(); - - details.capabilities = VkSurfaceCapabilitiesKHR.mallocStack(stack); - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, details.capabilities); + public long getImageView(int i) { return this.swapChainImages.get(i).getImageView(); } - IntBuffer count = stack.ints(0); - - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, count, null); - - if(count.get(0) != 0) { - details.formats = VkSurfaceFormatKHR.mallocStack(count.get(0), stack); - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, count, details.formats); - } - - vkGetPhysicalDeviceSurfacePresentModesKHR(device,surface, count, null); - - if(count.get(0) != 0) { - details.presentModes = stack.mallocInt(count.get(0)); - vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, count, details.presentModes); - } - - return details; - } - - private VkSurfaceFormatKHR chooseSwapSurfaceFormat(VkSurfaceFormatKHR.Buffer availableFormats) { + private VkSurfaceFormatKHR getFormat(VkSurfaceFormatKHR.Buffer availableFormats) { List list = availableFormats.stream().toList(); VkSurfaceFormatKHR format = list.get(0); - boolean flag = true; for (VkSurfaceFormatKHR availableFormat : list) { if (availableFormat.format() == VK_FORMAT_R8G8B8A8_UNORM && availableFormat.colorSpace() == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) @@ -322,19 +344,20 @@ private VkSurfaceFormatKHR chooseSwapSurfaceFormat(VkSurfaceFormatKHR.Buffer ava if (availableFormat.format() == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace() == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { format = availableFormat; - flag = false; } } - if(format.format() == VK_FORMAT_B8G8R8A8_UNORM) isBGRAformat = true; + if(format.format() == VK_FORMAT_B8G8R8A8_UNORM) + isBGRAformat = true; return format; } - private int chooseSwapPresentMode(IntBuffer availablePresentModes) { + private int getPresentMode(IntBuffer availablePresentModes) { int requestedMode = vsync ? VK_PRESENT_MODE_FIFO_KHR : VK_PRESENT_MODE_IMMEDIATE_KHR; //fifo mode is the only mode that has to be supported - if(requestedMode == VK_PRESENT_MODE_FIFO_KHR) return VK_PRESENT_MODE_FIFO_KHR; + if(requestedMode == VK_PRESENT_MODE_FIFO_KHR) + return VK_PRESENT_MODE_FIFO_KHR; for(int i = 0;i < availablePresentModes.capacity();i++) { if(availablePresentModes.get(i) == requestedMode) { @@ -347,12 +370,13 @@ private int chooseSwapPresentMode(IntBuffer availablePresentModes) { } - private static VkExtent2D chooseSwapExtent(VkSurfaceCapabilitiesKHR capabilities) { + private static VkExtent2D getExtent(VkSurfaceCapabilitiesKHR capabilities) { if(capabilities.currentExtent().width() != UINT32_MAX) { return capabilities.currentExtent(); } + //Fallback IntBuffer width = stackGet().ints(0); IntBuffer height = stackGet().ints(0); @@ -363,20 +387,12 @@ private static VkExtent2D chooseSwapExtent(VkSurfaceCapabilitiesKHR capabilities VkExtent2D minExtent = capabilities.minImageExtent(); VkExtent2D maxExtent = capabilities.maxImageExtent(); - actualExtent.width(Mth.clamp(minExtent.width(), maxExtent.width(), actualExtent.width())); - actualExtent.height(Mth.clamp(minExtent.height(), maxExtent.height(), actualExtent.height())); + actualExtent.width(MathUtil.clamp(minExtent.width(), maxExtent.width(), actualExtent.width())); + actualExtent.height(MathUtil.clamp(minExtent.height(), maxExtent.height(), actualExtent.height())); return actualExtent; } - static class SwapChainSupportDetails { - - VkSurfaceCapabilitiesKHR capabilities; - VkSurfaceFormatKHR.Buffer formats; - IntBuffer presentModes; - - } - public boolean isVsync() { return vsync; } @@ -384,4 +400,10 @@ public boolean isVsync() { public void setVsync(boolean vsync) { this.vsync = vsync; } + + public RenderPass getRenderPass() { + return renderPass; + } + + public int getFramesNum() { return this.swapChainImages.size(); } } diff --git a/src/main/java/net/vulkanmod/vulkan/memory/IndirectBuffer.java b/src/main/java/net/vulkanmod/vulkan/memory/IndirectBuffer.java index e6e4c27fb..aa795c916 100644 --- a/src/main/java/net/vulkanmod/vulkan/memory/IndirectBuffer.java +++ b/src/main/java/net/vulkanmod/vulkan/memory/IndirectBuffer.java @@ -30,7 +30,7 @@ public void recordCopyCmd(ByteBuffer byteBuffer) { if(commandBuffer == null) commandBuffer = TransferQueue.getInstance().beginCommands(); - StagingBuffer stagingBuffer = Vulkan.getStagingBuffer(Drawer.getCurrentFrame()); + StagingBuffer stagingBuffer = Vulkan.getStagingBuffer(Renderer.getCurrentFrame()); stagingBuffer.copyBuffer(size, byteBuffer); TransferQueue.uploadBufferCmd(commandBuffer, stagingBuffer.id, stagingBuffer.offset, this.getId(), this.getUsedBytes(), size); diff --git a/src/main/java/net/vulkanmod/vulkan/memory/MemoryManager.java b/src/main/java/net/vulkanmod/vulkan/memory/MemoryManager.java index 329f6aca1..89275a084 100644 --- a/src/main/java/net/vulkanmod/vulkan/memory/MemoryManager.java +++ b/src/main/java/net/vulkanmod/vulkan/memory/MemoryManager.java @@ -21,12 +21,20 @@ import static org.lwjgl.vulkan.VK10.*; public class MemoryManager { + private static final boolean DEBUG = false; + private static MemoryManager INSTANCE; - private final VkDevice device = Vulkan.getDevice(); + private static final Long2ReferenceOpenHashMap buffers = new Long2ReferenceOpenHashMap<>(); + private static final Long2ReferenceOpenHashMap images = new Long2ReferenceOpenHashMap<>(); + + private static final VkDevice device = Vulkan.getDevice(); private static final long allocator = Vulkan.getAllocator(); static int Frames; + private static long deviceMemory = 0; + private static long nativeMemory = 0; + private int currentFrame = 0; private ObjectArrayList[] freeableBuffers = new ObjectArrayList[Frames]; @@ -35,13 +43,7 @@ public class MemoryManager { private ObjectArrayList[] frameOps = new ObjectArrayList[Frames]; //debug - private ObjectArrayList[] stackTraces = new ObjectArrayList[Frames]; - - private static final Long2ReferenceOpenHashMap buffers = new Long2ReferenceOpenHashMap<>(); - private static final Long2ReferenceOpenHashMap images = new Long2ReferenceOpenHashMap<>(); - - private long deviceMemory = 0; - private long nativeMemory = 0; + private ObjectArrayList[] stackTraces; public static MemoryManager getInstance() { return INSTANCE; @@ -63,8 +65,13 @@ public static int getFrames() { freeableImages[i] = new ObjectArrayList<>(); frameOps[i] = new ObjectArrayList<>(); + } - stackTraces[i] = new ObjectArrayList<>(); + if(DEBUG) { + stackTraces = new ObjectArrayList[Frames]; + for(int i = 0; i < Frames; ++i) { + stackTraces[i] = new ObjectArrayList<>(); + } } } @@ -85,8 +92,8 @@ public void freeAllBuffers() { this.doFrameOps(frame); } - buffers.values().forEach(buffer -> freeBuffer(buffer.getId(), buffer.getAllocation())); - images.values().forEach(image -> image.doFree(this)); +// buffers.values().forEach(buffer -> freeBuffer(buffer.getId(), buffer.getAllocation())); +// images.values().forEach(image -> image.doFree(this)); } public void createBuffer(long size, int usage, int properties, LongBuffer pBuffer, PointerBuffer pBufferMemory) { @@ -130,11 +137,11 @@ public synchronized void createBuffer(Buffer buffer, int size, int usage, int pr nativeMemory += size; } - this.buffers.putIfAbsent(buffer.getId(), buffer); + buffers.putIfAbsent(buffer.getId(), buffer); } } - public void createImage(int width, int height, int mipLevels, int format, int tiling, int usage, int memProperties, + public static synchronized void createImage(int width, int height, int mipLevels, int format, int tiling, int usage, int memProperties, LongBuffer pTextureImage, PointerBuffer pTextureImageMemory) { try(MemoryStack stack = stackPush()) { @@ -164,8 +171,8 @@ public void createImage(int width, int height, int mipLevels, int format, int ti } } - public void addImage(VulkanImage image) { - this.images.putIfAbsent(image.getId(), image); + public static void addImage(VulkanImage image) { + images.putIfAbsent(image.getId(), image); } public void MapAndCopy(long allocation, long bufferSize, Consumer consumer){ @@ -188,13 +195,13 @@ public PointerBuffer Map(long allocation) { return data; } - public void freeBuffer(long buffer, long allocation) { + public static void freeBuffer(long buffer, long allocation) { vmaDestroyBuffer(allocator, buffer, allocation); - this.buffers.remove(buffer); + buffers.remove(buffer); } - private void freeBuffer(Buffer.BufferInfo bufferInfo) { + private static void freeBuffer(Buffer.BufferInfo bufferInfo) { vmaDestroyBuffer(allocator, bufferInfo.id(), bufferInfo.allocation()); if(bufferInfo.type() == MemoryType.Type.DEVICE_LOCAL) { @@ -203,13 +210,13 @@ private void freeBuffer(Buffer.BufferInfo bufferInfo) { nativeMemory -= bufferInfo.bufferSize(); } - this.buffers.remove(bufferInfo.id()); + buffers.remove(bufferInfo.id()); } - public void freeImage(long image, long allocation) { + public static void freeImage(long image, long allocation) { vmaDestroyImage(allocator, image, allocation); - this.images.remove(image); + images.remove(image); } public synchronized void addToFreeable(Buffer buffer) { @@ -219,8 +226,8 @@ public synchronized void addToFreeable(Buffer buffer) { freeableBuffers[currentFrame].add(bufferInfo); - //Debug - stackTraces[currentFrame].add(new Throwable().getStackTrace()); + if(DEBUG) + stackTraces[currentFrame].add(new Throwable().getStackTrace()); } public synchronized void addToFreeable(VulkanImage image) { @@ -250,8 +257,8 @@ private void freeBuffers(int frame) { bufferList.clear(); - //debug - stackTraces[frame].clear(); + if(DEBUG) + stackTraces[frame].clear(); this.freeImages(); } @@ -267,7 +274,7 @@ private void freeImages() { } private void checkBuffer(Buffer.BufferInfo bufferInfo) { - if(this.buffers.get(bufferInfo.id()) == null){ + if(buffers.get(bufferInfo.id()) == null){ throw new RuntimeException("trying to free not present buffer"); } diff --git a/src/main/java/net/vulkanmod/vulkan/memory/MemoryTypes.java b/src/main/java/net/vulkanmod/vulkan/memory/MemoryTypes.java index 428d2c2d1..ad1ba9939 100644 --- a/src/main/java/net/vulkanmod/vulkan/memory/MemoryTypes.java +++ b/src/main/java/net/vulkanmod/vulkan/memory/MemoryTypes.java @@ -1,6 +1,7 @@ package net.vulkanmod.vulkan.memory; -import net.vulkanmod.vulkan.Drawer; +import net.vulkanmod.vulkan.Device; +import net.vulkanmod.vulkan.Renderer; import net.vulkanmod.vulkan.queue.TransferQueue; import net.vulkanmod.vulkan.Vulkan; import net.vulkanmod.vulkan.util.VUtil; @@ -16,8 +17,8 @@ public class MemoryTypes { public static void createMemoryTypes() { - for(int i = 0; i < Vulkan.memoryProperties.memoryTypeCount(); ++i) { - VkMemoryType memoryType = Vulkan.memoryProperties.memoryTypes(i); + for(int i = 0; i < Device.memoryProperties.memoryTypeCount(); ++i) { + VkMemoryType memoryType = Device.memoryProperties.memoryTypes(i); //GPU only Memory if(memoryType.propertyFlags() == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) { @@ -39,8 +40,8 @@ public static void createMemoryTypes() { if(GPU_MEM != null) return; } - for(int i = 0; i < Vulkan.memoryProperties.memoryTypeCount(); ++i) { - VkMemoryType memoryType = Vulkan.memoryProperties.memoryTypes(i); + for(int i = 0; i < Device.memoryProperties.memoryTypeCount(); ++i) { + VkMemoryType memoryType = Device.memoryProperties.memoryTypes(i); //gpu-cpu shared memory if((memoryType.propertyFlags() & (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) != 0) { @@ -64,7 +65,7 @@ void createBuffer(Buffer buffer, int size) { @Override void copyToBuffer(Buffer buffer, long bufferSize, ByteBuffer byteBuffer) { - StagingBuffer stagingBuffer = Vulkan.getStagingBuffer(Drawer.getCurrentFrame()); + StagingBuffer stagingBuffer = Vulkan.getStagingBuffer(Renderer.getCurrentFrame()); stagingBuffer.copyBuffer((int) bufferSize, byteBuffer); TransferQueue.INSTANCE.copyBufferCmd(stagingBuffer.id, stagingBuffer.offset, buffer.getId(), buffer.getUsedBytes(), bufferSize); @@ -86,7 +87,7 @@ public long copyBuffer(Buffer src, Buffer dst) { @Override void uploadBuffer(Buffer buffer, ByteBuffer byteBuffer) { int bufferSize = byteBuffer.remaining(); - StagingBuffer stagingBuffer = Vulkan.getStagingBuffer(Drawer.getCurrentFrame()); + StagingBuffer stagingBuffer = Vulkan.getStagingBuffer(Renderer.getCurrentFrame()); stagingBuffer.copyBuffer(bufferSize, byteBuffer); TransferQueue.INSTANCE.copyBufferCmd(stagingBuffer.id, stagingBuffer.offset, buffer.getId(), 0, bufferSize); diff --git a/src/main/java/net/vulkanmod/vulkan/memory/UniformBuffers.java b/src/main/java/net/vulkanmod/vulkan/memory/UniformBuffers.java index d0fd218c8..e8ca97e6d 100644 --- a/src/main/java/net/vulkanmod/vulkan/memory/UniformBuffers.java +++ b/src/main/java/net/vulkanmod/vulkan/memory/UniformBuffers.java @@ -9,7 +9,6 @@ import java.util.ArrayList; import java.util.List; -import static net.vulkanmod.vulkan.Vulkan.deviceProperties; import static net.vulkanmod.vulkan.Vulkan.getSwapChainImages; import static net.vulkanmod.vulkan.util.VUtil.align; import static org.lwjgl.vulkan.VK10.VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; @@ -21,7 +20,7 @@ public class UniformBuffers { private List uniformBuffers; - private final static int minOffset = (int) deviceProperties.limits().minUniformBufferOffsetAlignment(); + private final static int minOffset = (int) Device.deviceProperties.limits().minUniformBufferOffsetAlignment(); private final int imagesSize = getSwapChainImages().size(); CommandPool.CommandBuffer commandBuffer; @@ -128,7 +127,7 @@ public void uploadUBO(ByteBuffer buffer, int offset) { int size = buffer.remaining(); - StagingBuffer stagingBuffer = Vulkan.getStagingBuffer(Drawer.getCurrentFrame()); + StagingBuffer stagingBuffer = Vulkan.getStagingBuffer(Renderer.getCurrentFrame()); stagingBuffer.copyBuffer(size, buffer); TransferQueue.uploadBufferCmd(commandBuffer, stagingBuffer.id, stagingBuffer.offset, this.id, offset, size); diff --git a/src/main/java/net/vulkanmod/vulkan/passes/DefaultMainPass.java b/src/main/java/net/vulkanmod/vulkan/passes/DefaultMainPass.java new file mode 100644 index 000000000..d7ecee56e --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/passes/DefaultMainPass.java @@ -0,0 +1,78 @@ +package net.vulkanmod.vulkan.passes; + +import net.vulkanmod.vulkan.Renderer; +import net.vulkanmod.vulkan.Vulkan; +import net.vulkanmod.vulkan.framebuffer.Framebuffer; +import net.vulkanmod.vulkan.framebuffer.SwapChain; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.vulkan.VkCommandBuffer; +import org.lwjgl.vulkan.VkRect2D; +import org.lwjgl.vulkan.VkViewport; + +import static org.lwjgl.vulkan.VK10.*; +import static org.lwjgl.vulkan.VK10.VK_SUCCESS; + +public class DefaultMainPass implements MainPass { + + public static DefaultMainPass PASS = new DefaultMainPass(); + + @Override + public void begin(VkCommandBuffer commandBuffer, MemoryStack stack) { + SwapChain swapChain = Vulkan.getSwapChain(); + swapChain.colorAttachmentLayout(stack, commandBuffer, Renderer.getCurrentFrame()); + + Framebuffer framebuffer = swapChain; + swapChain.beginRenderPass(commandBuffer, stack); + Renderer.clearAttachments(0x4100, swapChain.getWidth(), swapChain.getHeight()); +// Framebuffer framebuffer = this.hdrFinalFramebuffer; +// framebuffer.getColorAttachment().transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); +// +// framebuffer.beginRenderPass(commandBuffer, renderPass, stack); + +// this.boundFramebuffer = framebuffer; + Renderer.getInstance().setBoundFramebuffer(framebuffer); + + VkViewport.Buffer pViewport = framebuffer.viewport(stack); + vkCmdSetViewport(commandBuffer, 0, pViewport); + + VkRect2D.Buffer pScissor = framebuffer.scissor(stack); + vkCmdSetScissor(commandBuffer, 0, pScissor); + } + + @Override + public void end(VkCommandBuffer commandBuffer) { +// Framebuffer.endRenderPass(commandBuffer); +// +// try (MemoryStack stack = stackPush()) { +// this.hdrFinalFramebuffer.getColorAttachment() +// .transitionImageLayout(stack, commandBuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); +// +// SwapChain swapChain = Vulkan.getSwapChain(); +// +//// getSwapChain().colorAttachmentLayout(stack, commandBuffer, currentFrame); +// +//// swapChain.beginDynamicRendering(commandBuffer, stack); +// swapChain.beginRenderPass(commandBuffer, stack); +// +// clearAttachments(0x100, swapChain.width, swapChain.height); +// VRenderSystem.disableDepthTest(); +// } +// +//// VRenderSystem.disableDepthTest(); +// VRenderSystem.disableCull(); +// RenderSystem.disableBlend(); +// +// DrawUtil.drawFramebuffer(this.blitGammaShader, this.hdrFinalFramebuffer.getColorAttachment()); + + Framebuffer.endRenderPass(commandBuffer); + + try(MemoryStack stack = MemoryStack.stackPush()) { + Vulkan.getSwapChain().presentLayout(stack, commandBuffer, Renderer.getCurrentFrame()); + } + + int result = vkEndCommandBuffer(commandBuffer); + if(result != VK_SUCCESS) { + throw new RuntimeException("Failed to record command buffer:" + result); + } + } +} diff --git a/src/main/java/net/vulkanmod/vulkan/passes/MainPass.java b/src/main/java/net/vulkanmod/vulkan/passes/MainPass.java new file mode 100644 index 000000000..5399e1c73 --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/passes/MainPass.java @@ -0,0 +1,10 @@ +package net.vulkanmod.vulkan.passes; + +import org.lwjgl.system.MemoryStack; +import org.lwjgl.vulkan.VkCommandBuffer; + +public interface MainPass { + + void begin(VkCommandBuffer commandBuffer, MemoryStack stack); + void end(VkCommandBuffer commandBuffer); +} diff --git a/src/main/java/net/vulkanmod/vulkan/shader/Pipeline.java b/src/main/java/net/vulkanmod/vulkan/shader/Pipeline.java index 83eb475e8..91b55c44b 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/Pipeline.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/Pipeline.java @@ -8,11 +8,10 @@ import com.mojang.blaze3d.vertex.VertexFormatElement; import net.minecraft.util.GsonHelper; import net.vulkanmod.interfaces.VertexFormatMixed; -import net.vulkanmod.vulkan.Drawer; -import net.vulkanmod.vulkan.Framebuffer; +import net.vulkanmod.vulkan.*; +import net.vulkanmod.vulkan.framebuffer.RenderPass; import net.vulkanmod.vulkan.shader.ShaderSPIRVUtils.SPIRV; import net.vulkanmod.vulkan.shader.ShaderSPIRVUtils.ShaderKind; -import net.vulkanmod.vulkan.Vulkan; import net.vulkanmod.vulkan.memory.MemoryManager; import net.vulkanmod.vulkan.memory.UniformBuffers; import net.vulkanmod.vulkan.shader.layout.AlignedStruct; @@ -31,14 +30,10 @@ import java.nio.IntBuffer; import java.nio.LongBuffer; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import static net.vulkanmod.vulkan.shader.ShaderSPIRVUtils.compileShader; import static net.vulkanmod.vulkan.shader.ShaderSPIRVUtils.compileShaderFile; -import static net.vulkanmod.vulkan.Vulkan.getSwapChainImages; import static net.vulkanmod.vulkan.shader.PipelineState.*; import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; @@ -47,17 +42,21 @@ public class Pipeline { private static final VkDevice DEVICE = Vulkan.getDevice(); private static final long PIPELINE_CACHE = createPipelineCache(); - private static final int IMAGES_SIZE = getSwapChainImages().size(); + private static final List PIPELINES = new LinkedList<>(); + + public static void recreateDescriptorSets(int frames) { + PIPELINES.forEach(pipeline -> { + pipeline.destroyDescriptorSets(); + pipeline.createDescriptorSets(frames); + }); + } private long descriptorSetLayout; private long pipelineLayout; private final Map graphicsPipelines = new HashMap<>(); - private final DescriptorSets[] descriptorSets = new DescriptorSets[IMAGES_SIZE]; private final VertexFormat vertexFormat; - private int colorFormat; - private int depthFormat; - + private DescriptorSets[] descriptorSets; private final List UBOs; private final ManualUBO manualUBO; private final List samplers; @@ -66,26 +65,24 @@ public class Pipeline { private long vertShaderModule = 0; private long fragShaderModule = 0; - public Pipeline(VertexFormat vertexFormat, int colorFormat, int depthFormat, List UBOs, ManualUBO manualUBO, List samplers, PushConstants pushConstants, SPIRV vertSpirv, SPIRV fragSpirv) { + public Pipeline(VertexFormat vertexFormat, RenderPass renderPass, List UBOs, ManualUBO manualUBO, List samplers, PushConstants pushConstants, SPIRV vertSpirv, SPIRV fragSpirv) { this.UBOs = UBOs; this.manualUBO = manualUBO; this.samplers = samplers; this.pushConstants = pushConstants; this.vertexFormat = vertexFormat; - this.colorFormat = colorFormat; - this.depthFormat = depthFormat; - -// parseBindings(); createDescriptorSetLayout(); createPipelineLayout(); createShaderModules(vertSpirv, fragSpirv); - graphicsPipelines.computeIfAbsent(new PipelineState(DEFAULT_BLEND_STATE, DEFAULT_DEPTH_STATE, DEFAULT_LOGICOP_STATE, DEFAULT_COLORMASK), - this::createGraphicsPipeline); - createDescriptorSets(); - //allocateDescriptorSets(); + if(renderPass != null) + graphicsPipelines.computeIfAbsent(new PipelineState(DEFAULT_BLEND_STATE, DEFAULT_DEPTH_STATE, DEFAULT_LOGICOP_STATE, DEFAULT_COLORMASK, renderPass), + this::createGraphicsPipeline); + + createDescriptorSets(Vulkan.getSwapChainImages().size()); + PIPELINES.add(this); } private long createGraphicsPipeline(PipelineState state) { @@ -141,8 +138,10 @@ private long createGraphicsPipeline(PipelineState state) { rasterizer.polygonMode(VK_POLYGON_MODE_FILL); rasterizer.lineWidth(1.0f); - if(state.cullState) rasterizer.cullMode(VK_CULL_MODE_BACK_BIT); - else rasterizer.cullMode(VK_CULL_MODE_NONE); + if(state.cullState) + rasterizer.cullMode(VK_CULL_MODE_BACK_BIT); + else + rasterizer.cullMode(VK_CULL_MODE_NONE); rasterizer.frontFace(VK_FRONT_FACE_COUNTER_CLOCKWISE); rasterizer.depthBiasEnable(true); @@ -197,12 +196,6 @@ private long createGraphicsPipeline(PipelineState state) { dynamicStates.sType(VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO); dynamicStates.pDynamicStates(stack.ints(VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR)); - //dyn-rendering - VkPipelineRenderingCreateInfoKHR renderingInfo = VkPipelineRenderingCreateInfoKHR.calloc(stack); - renderingInfo.sType(KHRDynamicRendering.VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR); - renderingInfo.pColorAttachmentFormats(stack.ints(this.colorFormat)); - renderingInfo.depthAttachmentFormat(this.depthFormat); - VkGraphicsPipelineCreateInfo.Buffer pipelineInfo = VkGraphicsPipelineCreateInfo.callocStack(1, stack); pipelineInfo.sType(VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO); pipelineInfo.pStages(shaderStages); @@ -215,11 +208,21 @@ private long createGraphicsPipeline(PipelineState state) { pipelineInfo.pColorBlendState(colorBlending); pipelineInfo.pDynamicState(dynamicStates); pipelineInfo.layout(pipelineLayout); -// pipelineInfo.renderPass(Vulkan.getRenderPass()); -// pipelineInfo.subpass(0); pipelineInfo.basePipelineHandle(VK_NULL_HANDLE); pipelineInfo.basePipelineIndex(-1); - pipelineInfo.pNext(renderingInfo); + + if(!Vulkan.DYNAMIC_RENDERING) { + pipelineInfo.renderPass(state.renderPass.getId()); + pipelineInfo.subpass(0); + } + else { + //dyn-rendering + VkPipelineRenderingCreateInfoKHR renderingInfo = VkPipelineRenderingCreateInfoKHR.calloc(stack); + renderingInfo.sType(KHRDynamicRendering.VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR); + renderingInfo.pColorAttachmentFormats(stack.ints(state.renderPass.getFramebuffer().getFormat())); + renderingInfo.depthAttachmentFormat(state.renderPass.getFramebuffer().getDepthFormat()); + pipelineInfo.pNext(renderingInfo); + } LongBuffer pGraphicsPipeline = stack.mallocLong(1); @@ -300,8 +303,9 @@ private void createPipelineLayout() { } } - private void createDescriptorSets() { - for(int i = 0; i < IMAGES_SIZE; ++i) { + private void createDescriptorSets(int frames) { + descriptorSets = new DescriptorSets[frames]; + for(int i = 0; i < frames; ++i) { descriptorSets[i] = new DescriptorSets(i); } } @@ -315,9 +319,7 @@ public void cleanUp() { vkDestroyShaderModule(DEVICE, vertShaderModule, null); vkDestroyShaderModule(DEVICE, fragShaderModule, null); - for(DescriptorSets descriptorSets : this.descriptorSets) { - descriptorSets.cleanUp(); - } + destroyDescriptorSets(); graphicsPipelines.forEach((state, pipeline) -> { vkDestroyPipeline(DEVICE, pipeline, null); @@ -326,6 +328,17 @@ public void cleanUp() { vkDestroyDescriptorSetLayout(DEVICE, descriptorSetLayout, null); vkDestroyPipelineLayout(DEVICE, pipelineLayout, null); + + PIPELINES.remove(this); + Renderer.getInstance().removeUsedPipeline(this); + } + + private void destroyDescriptorSets() { + for(DescriptorSets descriptorSets : this.descriptorSets) { + descriptorSets.cleanUp(); + } + + this.descriptorSets = null; } public ManualUBO getManualUBO() { return this.manualUBO; } @@ -475,14 +488,13 @@ public static void destroyPipelineCache() { } public void resetDescriptorPool(int i) { - this.descriptorSets[i].resetIdx(); + if(this.descriptorSets != null) + this.descriptorSets[i].resetIdx(); } public long getHandle(PipelineState state) { - return graphicsPipelines.computeIfAbsent(state, state1 -> { - return createGraphicsPipeline(state1); - }); + return graphicsPipelines.computeIfAbsent(state, this::createGraphicsPipeline); } public PushConstants getPushConstants() { return this.pushConstants; } @@ -492,7 +504,7 @@ public long getHandle(PipelineState state) { public record Sampler(int binding, String type, String name) {} public void bindDescriptorSets(VkCommandBuffer commandBuffer, int frame) { - UniformBuffers uniformBuffers = Drawer.getInstance().getUniformBuffers(); + UniformBuffers uniformBuffers = Renderer.getDrawer().getUniformBuffers(); this.descriptorSets[frame].bindSets(commandBuffer, uniformBuffers); } @@ -593,7 +605,7 @@ private void updateDescriptorSet(MemoryStack stack, UniformBuffers uniformBuffer this.currentSet = this.sets.get(this.currentIdx); - VkWriteDescriptorSet.Buffer descriptorWrites = VkWriteDescriptorSet.callocStack(UBOs.size() + samplers.size(), stack); + VkWriteDescriptorSet.Buffer descriptorWrites = VkWriteDescriptorSet.calloc(UBOs.size() + samplers.size(), stack); VkDescriptorBufferInfo.Buffer[] bufferInfos = new VkDescriptorBufferInfo.Buffer[UBOs.size()]; //TODO maybe ubo update is not needed everytime @@ -717,6 +729,14 @@ private void cleanUp() { } public static class Builder { + + public static Pipeline create(VertexFormat format, String path) { + Pipeline.Builder pipelineBuilder = new Pipeline.Builder(format, path); + pipelineBuilder.parseBindingsJSON(); + pipelineBuilder.compileShaders(); + return pipelineBuilder.createPipeline(); + } + private final VertexFormat vertexFormat; private final String shaderPath; private List UBOs; @@ -728,7 +748,7 @@ public static class Builder { private SPIRV vertShaderSPIRV; private SPIRV fragShaderSPIRV; - private Framebuffer framebuffer; + private RenderPass renderPass; public Builder(VertexFormat vertexFormat, String path) { this.vertexFormat = vertexFormat; @@ -744,13 +764,10 @@ public Pipeline createPipeline() { && this.vertShaderSPIRV != null && this.fragShaderSPIRV != null, "Cannot create Pipeline: resources missing"); - if(this.framebuffer == null) - this.framebuffer = Vulkan.getSwapChain(); - if(this.manualUBO != null) this.UBOs.add(this.manualUBO); - return new Pipeline(this.vertexFormat, this.framebuffer.format, this.framebuffer.depthFormat, + return new Pipeline(this.vertexFormat, this.renderPass, this.UBOs, this.manualUBO, this.samplers, this.pushConstants, this.vertShaderSPIRV, this.fragShaderSPIRV); } @@ -777,7 +794,11 @@ public void parseBindingsJSON() { JsonObject jsonObject; - InputStream stream = Pipeline.class.getResourceAsStream("/assets/vulkanmod/shaders/" + this.shaderPath + ".json"); + String resourcePath = String.format("/assets/vulkanmod/shaders/%s.json", this.shaderPath); + InputStream stream = Pipeline.class.getResourceAsStream(resourcePath); + + if(stream == null) + throw new NullPointerException(String.format("Failed to load: %s", resourcePath)); jsonObject = GsonHelper.parse(new InputStreamReader(stream, StandardCharsets.UTF_8)); diff --git a/src/main/java/net/vulkanmod/vulkan/shader/PipelineState.java b/src/main/java/net/vulkanmod/vulkan/shader/PipelineState.java index 44efc838a..e3c858f5c 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/PipelineState.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/PipelineState.java @@ -1,6 +1,7 @@ package net.vulkanmod.vulkan.shader; import com.mojang.blaze3d.platform.GlStateManager; +import net.vulkanmod.vulkan.framebuffer.RenderPass; import net.vulkanmod.vulkan.VRenderSystem; import java.util.Objects; @@ -14,17 +15,33 @@ public class PipelineState { public static final LogicOpState DEFAULT_LOGICOP_STATE = new LogicOpState(false, 0); public static final ColorMask DEFAULT_COLORMASK = new ColorMask(true, true, true, true); + public static PipelineState.BlendInfo blendInfo = PipelineState.defaultBlendInfo(); + public static PipelineState.BlendState currentBlendState; + public static PipelineState.DepthState currentDepthState = PipelineState.DEFAULT_DEPTH_STATE; + public static PipelineState.LogicOpState currentLogicOpState = PipelineState.DEFAULT_LOGICOP_STATE; + public static PipelineState.ColorMask currentColorMask = PipelineState.DEFAULT_COLORMASK; + + public static PipelineState getCurrentPipelineState(RenderPass renderPass) { + currentBlendState = blendInfo.createBlendState(); + currentDepthState = VRenderSystem.getDepthState(); + currentColorMask = new PipelineState.ColorMask(VRenderSystem.getColorMask()); + + return new PipelineState(currentBlendState, currentDepthState, currentLogicOpState, currentColorMask, renderPass); + } + final BlendState blendState; final DepthState depthState; final ColorMask colorMask; final LogicOpState logicOpState; final boolean cullState; + final RenderPass renderPass; - public PipelineState(BlendState blendState, DepthState depthState, LogicOpState logicOpState, ColorMask colorMask) { + public PipelineState(BlendState blendState, DepthState depthState, LogicOpState logicOpState, ColorMask colorMask, RenderPass renderPass) { this.blendState = blendState; this.depthState = depthState; this.logicOpState = logicOpState; this.colorMask = colorMask; + this.renderPass = renderPass; this.cullState = VRenderSystem.cull; } @@ -33,12 +50,14 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PipelineState that = (PipelineState) o; - return blendState.equals(that.blendState) && depthState.equals(that.depthState) && logicOpState.equals(that.logicOpState) && (cullState == that.cullState) && colorMask.equals(that.colorMask); + return blendState.equals(that.blendState) && depthState.equals(that.depthState) + && this.renderPass == that.renderPass + && logicOpState.equals(that.logicOpState) && (cullState == that.cullState) && colorMask.equals(that.colorMask); } @Override public int hashCode() { - return Objects.hash(blendState, depthState, logicOpState, cullState); + return Objects.hash(blendState, depthState, logicOpState, cullState, renderPass); } public static BlendInfo defaultBlendInfo() { diff --git a/src/main/java/net/vulkanmod/vulkan/shader/ShaderManager.java b/src/main/java/net/vulkanmod/vulkan/shader/ShaderManager.java index bc5c27b26..89682f17a 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/ShaderManager.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/ShaderManager.java @@ -1,23 +1,27 @@ package net.vulkanmod.vulkan.shader; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.client.renderer.RenderType; import net.vulkanmod.Initializer; import net.vulkanmod.render.vertex.CustomVertexFormat; public class ShaderManager { - public static final VertexFormat TERRAIN_VERTEX_FORMAT = CustomVertexFormat.COMPRESSED_TERRAIN; -// public static final VertexFormat TERRAIN_VERTEX_FORMAT = DefaultVertexFormat.BLOCK; + public static VertexFormat TERRAIN_VERTEX_FORMAT; public static ShaderManager shaderManager; - public static void initShaderManager() { + public static void init() { + setTerrainVertexFormat(CustomVertexFormat.COMPRESSED_TERRAIN); shaderManager = new ShaderManager(); } + public static void setTerrainVertexFormat(VertexFormat format) { + TERRAIN_VERTEX_FORMAT = format; + } + public static ShaderManager getInstance() { return shaderManager; } - Pipeline terrainShader; + Pipeline terrainIndirectShader; public Pipeline terrainDirectShader; public ShaderManager() { @@ -25,7 +29,7 @@ public ShaderManager() { } private void createBasicPipelines() { - this.terrainShader = createPipeline("terrain"); + this.terrainIndirectShader = createPipeline("terrain"); this.terrainDirectShader = createPipeline("terrain_direct"); } @@ -33,15 +37,15 @@ private void createBasicPipelines() { private Pipeline createPipeline(String name) { String path = String.format("basic/%s/%s", name, name); - Pipeline.Builder pipelineBuilder = new Pipeline.Builder(TERRAIN_VERTEX_FORMAT, path); + Pipeline.Builder pipelineBuilder = new Pipeline.Builder(CustomVertexFormat.COMPRESSED_TERRAIN, path); pipelineBuilder.parseBindingsJSON(); pipelineBuilder.compileShaders(); return pipelineBuilder.createPipeline(); } - public Pipeline getTerrainShader() { + public Pipeline getTerrainShader(RenderType renderType) { if(Initializer.CONFIG.indirectDraw) { - return this.terrainShader; + return this.terrainIndirectShader; } else { return this.terrainDirectShader; @@ -49,8 +53,12 @@ public Pipeline getTerrainShader() { } + public Pipeline getTerrainIndirectShader(RenderType renderType) { + return terrainIndirectShader; + } + public void destroyPipelines() { - this.terrainShader.cleanUp(); + this.terrainIndirectShader.cleanUp(); this.terrainDirectShader.cleanUp(); } } diff --git a/src/main/java/net/vulkanmod/vulkan/shader/ShaderSPIRVUtils.java b/src/main/java/net/vulkanmod/vulkan/shader/ShaderSPIRVUtils.java index df0b02a86..b809fdab8 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/ShaderSPIRVUtils.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/ShaderSPIRVUtils.java @@ -49,7 +49,7 @@ public static SPIRV compileShader(String filename, String source, ShaderKind sha // shaderc_compile_options_set_optimization_level(options, shaderc_optimization_level_performance); -// shaderc_compile_options_set_generate_debug_info(options); + shaderc_compile_options_set_generate_debug_info(options); long result = shaderc_compile_into_spv(compiler, source, shaderKind.kind, filename, "main", options); diff --git a/src/main/java/net/vulkanmod/vulkan/shader/Uniforms.java b/src/main/java/net/vulkanmod/vulkan/shader/Uniforms.java new file mode 100644 index 000000000..28ef8517e --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/shader/Uniforms.java @@ -0,0 +1,52 @@ +package net.vulkanmod.vulkan.shader; + +import com.mojang.blaze3d.systems.RenderSystem; +import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap; +import net.vulkanmod.vulkan.VRenderSystem; +import net.vulkanmod.vulkan.util.MappedBuffer; + +import java.util.function.Supplier; + +public class Uniforms { + + public static Object2ReferenceOpenHashMap> vec1i_uniformMap = new Object2ReferenceOpenHashMap<>(); + + public static Object2ReferenceOpenHashMap> vec1f_uniformMap = new Object2ReferenceOpenHashMap<>(); + public static Object2ReferenceOpenHashMap> vec2f_uniformMap = new Object2ReferenceOpenHashMap<>(); + public static Object2ReferenceOpenHashMap> vec3f_uniformMap = new Object2ReferenceOpenHashMap<>(); + public static Object2ReferenceOpenHashMap> vec4f_uniformMap = new Object2ReferenceOpenHashMap<>(); + + public static Object2ReferenceOpenHashMap> mat4f_uniformMap = new Object2ReferenceOpenHashMap<>(); + + public static void setupDefaultUniforms() { + + //Mat4 + mat4f_uniformMap.put("ModelViewMat", VRenderSystem::getModelViewMatrix); + mat4f_uniformMap.put("ProjMat", VRenderSystem::getProjectionMatrix); + mat4f_uniformMap.put("MVP", VRenderSystem::getMVP); + mat4f_uniformMap.put("TextureMat", VRenderSystem::getTextureMatrix); + + //Vec1i + vec1i_uniformMap.put("EndPortalLayers", () -> 15); + + //Vec1 + vec1f_uniformMap.put("FogStart", RenderSystem::getShaderFogStart); + vec1f_uniformMap.put("FogEnd", RenderSystem::getShaderFogEnd); + vec1f_uniformMap.put("LineWidth", RenderSystem::getShaderLineWidth); + vec1f_uniformMap.put("GameTime", RenderSystem::getShaderGameTime); + vec1f_uniformMap.put("AlphaCutout", () -> VRenderSystem.alphaCutout); + + //Vec2 + vec2f_uniformMap.put("ScreenSize", VRenderSystem::getScreenSize); + + //Vec3 + vec3f_uniformMap.put("Light0_Direction", () -> VRenderSystem.lightDirection0); + vec3f_uniformMap.put("Light1_Direction", () -> VRenderSystem.lightDirection1); + vec3f_uniformMap.put("ChunkOffset", () -> VRenderSystem.ChunkOffset); + + //Vec4 + vec4f_uniformMap.put("ColorModulator", VRenderSystem::getShaderColor); + vec4f_uniformMap.put("FogColor", VRenderSystem::getShaderFogColor); + + } +} diff --git a/src/main/java/net/vulkanmod/vulkan/shader/layout/Mat4f.java b/src/main/java/net/vulkanmod/vulkan/shader/layout/Mat4f.java index 61d005d39..d564ecb57 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/layout/Mat4f.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/layout/Mat4f.java @@ -1,23 +1,19 @@ package net.vulkanmod.vulkan.shader.layout; -import net.vulkanmod.vulkan.VRenderSystem; +import net.vulkanmod.vulkan.shader.Uniforms; import net.vulkanmod.vulkan.util.MappedBuffer; +import org.apache.commons.lang3.Validate; import org.lwjgl.system.MemoryUtil; -import java.nio.ByteBuffer; - public class Mat4f extends Field { public Mat4f(FieldInfo info, long ptr) { super(info, ptr); } protected void setSupplier() { - switch (this.fieldInfo.name) { - case "ModelViewMat" -> this.values = VRenderSystem::getModelViewMatrix; - case "ProjMat" -> this.values = VRenderSystem::getProjectionMatrix; - case "MVP" -> this.values = VRenderSystem::getMVP; - case "TextureMat" -> this.values = VRenderSystem::getTextureMatrix; - } + this.values = Uniforms.mat4f_uniformMap.get(this.fieldInfo.name); + + Validate.notNull(this.values, "Field name not found: " + this.fieldInfo.name); } void update() { diff --git a/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec1f.java b/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec1f.java index 99fae630e..4835c0946 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec1f.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec1f.java @@ -1,8 +1,7 @@ package net.vulkanmod.vulkan.shader.layout; -import com.mojang.blaze3d.systems.RenderSystem; -import net.vulkanmod.vulkan.VRenderSystem; -import net.vulkanmod.vulkan.util.MappedBuffer; +import net.vulkanmod.vulkan.shader.Uniforms; +import org.apache.commons.lang3.Validate; import org.lwjgl.system.MemoryUtil; import java.util.function.Supplier; @@ -15,14 +14,9 @@ public Vec1f(FieldInfo fieldInfo, long ptr) { } void setSupplier() { - switch (this.fieldInfo.name) { - case "FogStart" -> this.floatSupplier = RenderSystem::getShaderFogStart; - case "FogEnd" -> this.floatSupplier = RenderSystem::getShaderFogEnd; - case "LineWidth" -> this.floatSupplier = RenderSystem::getShaderLineWidth; - case "GameTime" -> this.floatSupplier = RenderSystem::getShaderGameTime; - case "AlphaCutout" -> this.floatSupplier = () -> VRenderSystem.alphaCutout; -// default -> throw new IllegalArgumentException("Unexpected value: " + this.fieldInfo.name); - } + this.floatSupplier = Uniforms.vec1f_uniformMap.get(this.fieldInfo.name); + + Validate.notNull(this.floatSupplier, "Field name not found: " + this.fieldInfo.name); } void update() { diff --git a/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec1i.java b/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec1i.java index ce565d1cd..bfaab6b9c 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec1i.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec1i.java @@ -1,6 +1,8 @@ package net.vulkanmod.vulkan.shader.layout; +import net.vulkanmod.vulkan.shader.Uniforms; import net.vulkanmod.vulkan.util.MappedBuffer; +import org.apache.commons.lang3.Validate; import org.lwjgl.system.MemoryUtil; import java.util.function.Supplier; @@ -13,7 +15,9 @@ public Vec1i(FieldInfo fieldInfo, long ptr) { } void setSupplier() { - if (this.fieldInfo.name.equals("EndPortalLayers")) this.intSupplier = () -> 15; + this.intSupplier = Uniforms.vec1i_uniformMap.get(this.fieldInfo.name); + + Validate.notNull(this.intSupplier, "Field name not found: " + this.fieldInfo.name); } void update() { diff --git a/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec2f.java b/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec2f.java index 2379733c4..d858a5fc3 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec2f.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec2f.java @@ -1,8 +1,8 @@ package net.vulkanmod.vulkan.shader.layout; -import net.vulkanmod.vulkan.VRenderSystem; +import net.vulkanmod.vulkan.shader.Uniforms; import net.vulkanmod.vulkan.util.MappedBuffer; -import org.joml.Vector2f; +import org.apache.commons.lang3.Validate; import org.lwjgl.system.MemoryUtil; public class Vec2f extends Field { @@ -12,7 +12,9 @@ public Vec2f(FieldInfo fieldInfo, long ptr) { } void setSupplier() { - if (this.fieldInfo.name.equals("ScreenSize")) this.values = VRenderSystem::getScreenSize; + this.values = Uniforms.vec2f_uniformMap.get(this.fieldInfo.name); + + Validate.notNull(this.values, "Field name not found: " + this.fieldInfo.name); } void update() { diff --git a/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec3f.java b/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec3f.java index dcfc97956..6656354c4 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec3f.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec3f.java @@ -1,8 +1,9 @@ package net.vulkanmod.vulkan.shader.layout; -import net.vulkanmod.vulkan.VRenderSystem; +import net.vulkanmod.vulkan.shader.Uniforms; import net.vulkanmod.vulkan.util.MappedBuffer; import net.vulkanmod.vulkan.util.VUtil; +import org.apache.commons.lang3.Validate; public class Vec3f extends Field { @@ -11,11 +12,9 @@ public Vec3f(FieldInfo fieldInfo, long ptr) { } void setSupplier() { - switch (this.fieldInfo.name) { - case "Light0_Direction" -> this.values = () -> VRenderSystem.lightDirection0; - case "Light1_Direction" -> this.values = () -> VRenderSystem.lightDirection1; - case "ChunkOffset" -> this.values = () -> VRenderSystem.ChunkOffset; - } + this.values = Uniforms.vec3f_uniformMap.get(this.fieldInfo.name); + + Validate.notNull(this.values, "Field name not found: " + this.fieldInfo.name); } void update() { diff --git a/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec4f.java b/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec4f.java index 61dd1cd43..1bc12df0d 100644 --- a/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec4f.java +++ b/src/main/java/net/vulkanmod/vulkan/shader/layout/Vec4f.java @@ -1,8 +1,8 @@ package net.vulkanmod.vulkan.shader.layout; -import com.mojang.blaze3d.systems.RenderSystem; -import net.vulkanmod.vulkan.VRenderSystem; +import net.vulkanmod.vulkan.shader.Uniforms; import net.vulkanmod.vulkan.util.MappedBuffer; +import org.apache.commons.lang3.Validate; import org.lwjgl.system.MemoryUtil; public class Vec4f extends Field { @@ -12,9 +12,9 @@ public Vec4f(FieldInfo fieldInfo, long ptr) { } void setSupplier() { + this.values = Uniforms.vec4f_uniformMap.get(this.fieldInfo.name); - if (this.fieldInfo.name.equals("ColorModulator")) this.values = VRenderSystem::getShaderColor; - else if (this.fieldInfo.name.equals("FogColor")) this.values = VRenderSystem::getShaderFogColor; + Validate.notNull(this.values, "Field name not found: " + this.fieldInfo.name); } void update() { diff --git a/src/main/java/net/vulkanmod/vulkan/texture/VTextureSelector.java b/src/main/java/net/vulkanmod/vulkan/texture/VTextureSelector.java index 243cb12fd..2edd6d8f7 100644 --- a/src/main/java/net/vulkanmod/vulkan/texture/VTextureSelector.java +++ b/src/main/java/net/vulkanmod/vulkan/texture/VTextureSelector.java @@ -4,9 +4,12 @@ public abstract class VTextureSelector { private static VulkanImage boundTexture; + private static VulkanImage boundTexture2; + private static VulkanImage boundTexture3; private static VulkanImage lightTexture; private static VulkanImage overlayTexture; private static VulkanImage framebufferTexture; + private static VulkanImage framebufferTexture2; private static final VulkanImage whiteTexture = VulkanImage.createWhiteTexture(); @@ -24,10 +27,22 @@ public static void bindTexture(int i, VulkanImage texture) { } } + public static void bindTexture2(VulkanImage texture) { + boundTexture2 = texture; + } + + public static void bindTexture3(VulkanImage texture) { + boundTexture3 = texture; + } + public static void bindFramebufferTexture(VulkanImage texture) { framebufferTexture = texture; } + public static void bindFramebufferTexture2(VulkanImage texture) { + framebufferTexture2 = texture; + } + public static void uploadSubTexture(int mipLevel, int width, int height, int xOffset, int yOffset, int unpackSkipRows, int unpackSkipPixels, int unpackRowLength, ByteBuffer buffer) { VulkanImage texture; if(activeTexture == 0) texture = boundTexture; @@ -42,6 +57,10 @@ public static VulkanImage getTexture(String name) { case "Sampler0" -> getBoundTexture(); case "Sampler1" -> getOverlayTexture(); case "Sampler2" -> getLightTexture(); + case "Sampler3" -> boundTexture2; + case "Sampler4" -> boundTexture3; + case "Framebuffer0" -> framebufferTexture; + case "Framebuffer1" -> framebufferTexture2; default -> throw new RuntimeException("unknown sampler name: " + name); }; } diff --git a/src/main/java/net/vulkanmod/vulkan/texture/VulkanImage.java b/src/main/java/net/vulkanmod/vulkan/texture/VulkanImage.java index d0a1832da..9a8b34f04 100644 --- a/src/main/java/net/vulkanmod/vulkan/texture/VulkanImage.java +++ b/src/main/java/net/vulkanmod/vulkan/texture/VulkanImage.java @@ -22,7 +22,7 @@ import static org.lwjgl.vulkan.VK10.*; public class VulkanImage { - private static final int DefaultFormat = VK_FORMAT_R8G8B8A8_UNORM; + public static int DefaultFormat = VK_FORMAT_R8G8B8A8_UNORM; private static VkDevice device = Vulkan.getDevice(); @@ -39,14 +39,29 @@ public class VulkanImage { public final int height; public final int formatSize; + private int usage; + private int currentLayout; + public VulkanImage(long id, int format, int mipLevels, int width, int height, int formatSize, int usage, long imageView) { + this.id = id; + this.imageView = imageView; + + this.mipLevels = mipLevels; + this.width = width; + this.height = height; + this.formatSize = formatSize; + this.format = format; + this.usage = usage; + } + private VulkanImage(int format, int mipLevels, int width, int height, int usage, int formatSize) { this.mipLevels = mipLevels; this.width = width; this.height = height; this.formatSize = formatSize; this.format = format; + this.usage = usage; } public static VulkanImage createTextureImage(int format, int mipLevels, int width, int height, int usage, int formatSize, boolean blur, boolean clamp) { @@ -137,13 +152,13 @@ public void uploadSubTextureAsync(int mipLevel, int width, int height, int xOffs CommandPool.CommandBuffer commandBuffer = GraphicsQueue.getInstance().getCommandBuffer(); transferDstLayout(commandBuffer); - StagingBuffer stagingBuffer = Vulkan.getStagingBuffer(Drawer.getCurrentFrame()); - stagingBuffer.align(formatSize); + StagingBuffer stagingBuffer = Vulkan.getStagingBuffer(Renderer.getCurrentFrame()); + stagingBuffer.align(this.formatSize); stagingBuffer.copyBuffer((int)imageSize, buffer); copyBufferToImageCmd(commandBuffer, stagingBuffer.getId(), id, mipLevel, width, height, xOffset, yOffset, - (int) (stagingBuffer.getOffset() + (unpackRowLength * unpackSkipRows + unpackSkipPixels) * formatSize), unpackRowLength, height); + (int) (stagingBuffer.getOffset() + (unpackRowLength * unpackSkipRows + unpackSkipPixels) * this.formatSize), unpackRowLength, height); long fence = GraphicsQueue.getInstance().endIfNeeded(commandBuffer); if (fence != VK_NULL_HANDLE) @@ -485,6 +500,14 @@ public void doFree(MemoryManager memoryManager) { } } + public int getCurrentLayout() { + return currentLayout; + } + + public void setCurrentLayout(int currentLayout) { + this.currentLayout = currentLayout; + } + public long getId() { return id;} public long getAllocation() { return allocation;} public long getImageView() { return imageView; } @@ -553,7 +576,7 @@ private static int convertFormat(NativeImage.InternalGlFormat format) { private static int formatSize(int format) { return switch (format) { - case VK_FORMAT_R8G8B8A8_UNORM -> 4; + case VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_SRGB -> 4; case VK_FORMAT_R8_UNORM -> 1; default -> throw new IllegalArgumentException(String.format("Unxepcted format: %s", format)); }; diff --git a/src/main/java/net/vulkanmod/vulkan/util/ColorUtil.java b/src/main/java/net/vulkanmod/vulkan/util/ColorUtil.java new file mode 100644 index 000000000..09427ef9b --- /dev/null +++ b/src/main/java/net/vulkanmod/vulkan/util/ColorUtil.java @@ -0,0 +1,118 @@ +package net.vulkanmod.vulkan.util; + +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; + +public class ColorUtil { + + static ColorConsumer colorConsumer = new DefaultColorConsumer(); + + public static void useGammaCorrection(boolean b) { + colorConsumer = b ? new GammaColorConsumer() : new DefaultColorConsumer(); + } + + public static int packColorInt(float r, float g, float b, float a) { + int color = 0; + color += (int)(a * 255) << 24; + color += (int)(r * 255) << 16; + color += (int)(g * 255) << 8; + color += (int)(b * 255); + + return color; + } + + public static int BGRAtoRGBA(int v) { + byte r = (byte) (v >> 16); + byte g = (byte) (v >> 8); + byte b = (byte) (v); + byte a = (byte) (v >> 24); + + return r & 0xFF | (g << 8) & 0xFF00 | (b << 16) & 0xFF0000 | (a << 24) & 0xFF000000; + } + + public static float gamma(float f) { + return (float) Math.pow(f, 2.2); + } + + public static void setRGBA_Buffer(MappedBuffer buffer, float r, float g, float b, float a) { + colorConsumer.setRGBA_Buffer(buffer, r, g, b, a); + } + + public static void setRGBA_Buffer(FloatBuffer buffer, float r, float g, float b, float a) { + colorConsumer.setRGBA_Buffer(buffer, r, g, b, a); + } + + interface ColorConsumer { + + void setRGBA_Buffer(MappedBuffer buffer, float r, float g, float b, float a); + void setRGBA_Buffer(FloatBuffer buffer, float r, float g, float b, float a); + void setRGBA_Buffer(ByteBuffer buffer, float r, float g, float b, float a); + + default void putColor(MappedBuffer buffer, float r, float g, float b, float a) { + buffer.putFloat(0, r); + buffer.putFloat(4, g); + buffer.putFloat(8, b); + buffer.putFloat(12, a); + } + + default void putColor(FloatBuffer buffer, float r, float g, float b, float a) { + buffer.put(0, r); + buffer.put(1, g); + buffer.put(2, b); + buffer.put(3, a); + } + + default void putColor(ByteBuffer buffer, float r, float g, float b, float a) { + buffer.putFloat(0, r); + buffer.putFloat(4, g); + buffer.putFloat(8, b); + buffer.putFloat(12, a); + } + } + + public static class DefaultColorConsumer implements ColorConsumer { + + @Override + public void setRGBA_Buffer(MappedBuffer buffer, float r, float g, float b, float a) { + putColor(buffer, r, g, b, a); + } + + @Override + public void setRGBA_Buffer(FloatBuffer buffer, float r, float g, float b, float a) { + putColor(buffer, r, g, b, a); + } + + @Override + public void setRGBA_Buffer(ByteBuffer buffer, float r, float g, float b, float a) { + putColor(buffer, r, g, b, a); + } + } + + public static class GammaColorConsumer implements ColorConsumer { + + @Override + public void setRGBA_Buffer(MappedBuffer buffer, float r, float g, float b, float a) { + r = gamma(r); + g = gamma(g); + b = gamma(b); + putColor(buffer, r, g, b, a); + } + + @Override + public void setRGBA_Buffer(FloatBuffer buffer, float r, float g, float b, float a) { + r = gamma(r); + g = gamma(g); + b = gamma(b); + putColor(buffer, r, g, b, a); + } + + @Override + public void setRGBA_Buffer(ByteBuffer buffer, float r, float g, float b, float a) { + r = gamma(r); + g = gamma(g); + b = gamma(b); + putColor(buffer, r, g, b, a); + } + + } +} diff --git a/src/main/java/net/vulkanmod/vulkan/util/DrawUtil.java b/src/main/java/net/vulkanmod/vulkan/util/DrawUtil.java index 27e9bdde5..4093333b5 100644 --- a/src/main/java/net/vulkanmod/vulkan/util/DrawUtil.java +++ b/src/main/java/net/vulkanmod/vulkan/util/DrawUtil.java @@ -4,15 +4,15 @@ import com.mojang.blaze3d.vertex.*; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ShaderInstance; -import net.vulkanmod.vulkan.Drawer; -import net.vulkanmod.vulkan.Framebuffer; +import net.vulkanmod.vulkan.Renderer; +import net.vulkanmod.vulkan.framebuffer.Framebuffer; import org.joml.Matrix4f; import org.lwjgl.system.MemoryStack; public class DrawUtil { public static void drawFramebuffer(Framebuffer framebuffer) { - Drawer drawer = Drawer.getInstance(); + Renderer renderer = Renderer.getInstance(); Matrix4f matrix4f = new Matrix4f().setOrtho(0.0F, 1.0F, 1.0F, 0.0F, 0.0F, 1.0F); // matrix4f.setIdentity(); @@ -26,7 +26,7 @@ public static void drawFramebuffer(Framebuffer framebuffer) { // drawer.uploadAndBindUBOs(drawer.blitShader); try (MemoryStack stack = MemoryStack.stackPush()) { - framebuffer.bindAsTexture(Drawer.getCommandBuffer(), stack); + framebuffer.bindAsTexture(Renderer.getCommandBuffer(), stack); } ShaderInstance shaderInstance = Minecraft.getInstance().gameRenderer.blitShader; @@ -47,7 +47,7 @@ public static void drawFramebuffer(Framebuffer framebuffer) { bufferBuilder.vertex(0.0D, 1.0D, 0.0D).uv(0.0F, 0.0F).color(255, 255, 255, 255).endVertex(); // bufferBuilder.end(); // BufferUploader._endInternal(bufferBuilder); - BufferUploader.draw(bufferBuilder.end()); + BufferUploader.drawWithShader(bufferBuilder.end()); //Draw buffer // Pair pair = bufferBuilder.popNextBuffer(); diff --git a/src/main/java/net/vulkanmod/vulkan/util/VUtil.java b/src/main/java/net/vulkanmod/vulkan/util/VUtil.java index 35618e44b..e6c8d5ed0 100644 --- a/src/main/java/net/vulkanmod/vulkan/util/VUtil.java +++ b/src/main/java/net/vulkanmod/vulkan/util/VUtil.java @@ -114,27 +114,9 @@ public static void memcpy(ByteBuffer buffer, FloatBuffer floatBuffer, long offse floatBuffer.position(0); } - public static int align(int num, int align) { - int r = num % align; - return r == 0 ? num : num + align - r; + public static int align(int x, int align) { + int r = x % align; + return r == 0 ? x : x + align - r; } - public static int packColor(float r, float g, float b, float a) { - int color = 0; - color += (int)(a * 255) << 24; - color += (int)(r * 255) << 16; - color += (int)(g * 255) << 8; - color += (int)(b * 255); - - return color; - } - - public static int BGRAtoRGBA(int v) { - byte r = (byte) (v >> 16); - byte g = (byte) (v >> 8); - byte b = (byte) (v); - byte a = (byte) (v >> 24); - - return r & 0xFF | (g << 8) & 0xFF00 | (b << 16) & 0xFF0000 | (a << 24) & 0xFF000000; - } } diff --git a/src/main/resources/vulkanmod.mixins.json b/src/main/resources/vulkanmod.mixins.json index 5a1ccf16a..ad01a6d4f 100644 --- a/src/main/resources/vulkanmod.mixins.json +++ b/src/main/resources/vulkanmod.mixins.json @@ -18,7 +18,6 @@ "compatibility.UniformM", "debug.ChunkBorderRendererM", - "debug.DebugScreenOverlayM", "debug.GlDebugInfoM", "debug.KeyboardHandlerM", @@ -72,7 +71,6 @@ "vertex.VertexMultiConsumersM$MultipleM", "vertex.VertexMultiConsumersM$SheetDecalM", - "ClientLevelM", "WindowMixin" ], "injectors": {