From ba03560df00355d16396b2297a66c9210b11450a Mon Sep 17 00:00:00 2001 From: xCollateral <103696619+xCollateral@users.noreply.github.com> Date: Wed, 18 Sep 2024 13:03:51 +0200 Subject: [PATCH] Implement flush commands method - Flush draw commands on screenshot recording if needed --- .../mixin/chunk/LevelRendererMixin.java | 2 +- .../mixin/util/ScreenshotRecorderM.java | 17 ++--- .../java/net/vulkanmod/vulkan/Renderer.java | 69 +++++++++++++++---- 3 files changed, 63 insertions(+), 25 deletions(-) diff --git a/src/main/java/net/vulkanmod/mixin/chunk/LevelRendererMixin.java b/src/main/java/net/vulkanmod/mixin/chunk/LevelRendererMixin.java index 850290af8..1b9c00f98 100644 --- a/src/main/java/net/vulkanmod/mixin/chunk/LevelRendererMixin.java +++ b/src/main/java/net/vulkanmod/mixin/chunk/LevelRendererMixin.java @@ -117,7 +117,7 @@ public String getSectionStatistics() { */ @Overwrite public boolean hasRenderedAllSections() { - return this.worldRenderer.graphNeedsUpdate(); + return !this.worldRenderer.graphNeedsUpdate() && this.worldRenderer.getTaskDispatcher().isIdle(); } /** diff --git a/src/main/java/net/vulkanmod/mixin/util/ScreenshotRecorderM.java b/src/main/java/net/vulkanmod/mixin/util/ScreenshotRecorderM.java index 2a2639fc5..58ae4ff90 100644 --- a/src/main/java/net/vulkanmod/mixin/util/ScreenshotRecorderM.java +++ b/src/main/java/net/vulkanmod/mixin/util/ScreenshotRecorderM.java @@ -4,6 +4,7 @@ import com.mojang.blaze3d.platform.NativeImage; import net.minecraft.client.Screenshot; import net.vulkanmod.gl.GlTexture; +import net.vulkanmod.vulkan.Renderer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -15,21 +16,17 @@ public class ScreenshotRecorderM { */ @Overwrite public static NativeImage takeScreenshot(RenderTarget target) { - int i = target.width; - int j = target.height; + int width = target.width; + int height = target.height; - NativeImage nativeimage = new NativeImage(i, j, false); + NativeImage nativeimage = new NativeImage(width, height, false); GlTexture.bindTexture(target.getColorTextureId()); - //TODO screenshot might be requested when cmds have not been submitted yet -// RenderPass renderPass = ((ExtendedRenderTarget)target).getRenderPass(); -// -// Renderer renderer = Renderer.getInstance(); -// boolean b = renderer.getBoundRenderPass() == renderPass; + // Need to submit and wait cmds if screenshot was requested + // before the end of the frame + Renderer.getInstance().flushCmds(); nativeimage.downloadTexture(0, true); - - //nativeimage.flipY(); return nativeimage; } } diff --git a/src/main/java/net/vulkanmod/vulkan/Renderer.java b/src/main/java/net/vulkanmod/vulkan/Renderer.java index f90a10afa..d06831374 100644 --- a/src/main/java/net/vulkanmod/vulkan/Renderer.java +++ b/src/main/java/net/vulkanmod/vulkan/Renderer.java @@ -245,26 +245,28 @@ public void beginFrame() { imageIndex = pImageIndex.get(0); - 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; + this.beginRenderPass(stack); + } - vkResult = vkBeginCommandBuffer(commandBuffer, beginInfo); - if (vkResult != VK_SUCCESS) { - throw new RuntimeException("Failed to begin recording command buffer: %s".formatted(VkResult.decode(vkResult))); - } - recordingCmds = true; + p.pop(); + } - mainPass.begin(commandBuffer, stack); + private void beginRenderPass(MemoryStack stack) { + VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.calloc(stack); + beginInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO); + beginInfo.flags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - vkCmdSetDepthBias(commandBuffer, 0.0F, 0.0F, 0.0F); + VkCommandBuffer commandBuffer = currentCmdBuffer; - vkCmdSetLineWidth(commandBuffer, 1.0F); + int vkResult = vkBeginCommandBuffer(commandBuffer, beginInfo); + if (vkResult != VK_SUCCESS) { + throw new RuntimeException("Failed to begin recording command buffer: %s".formatted(VkResult.decode(vkResult))); } - p.pop(); + recordingCmds = true; + mainPass.begin(commandBuffer, stack); + + resetDynamicState(commandBuffer); } public void endFrame() { @@ -333,6 +335,39 @@ private void submitFrame() { } } + /** + * Called in case draw results are needed before the of the frame + */ + public void flushCmds() { + if (!this.recordingCmds) + return; + + try (MemoryStack stack = stackPush()) { + int vkResult; + + this.endRenderPass(currentCmdBuffer); + vkEndCommandBuffer(currentCmdBuffer); + + VkSubmitInfo submitInfo = VkSubmitInfo.calloc(stack); + submitInfo.sType(VK_STRUCTURE_TYPE_SUBMIT_INFO); + + submitInfo.pCommandBuffers(stack.pointers(currentCmdBuffer)); + + vkResetFences(device, inFlightFences.get(currentFrame)); + + Synchronization.INSTANCE.waitFences(); + + if ((vkResult = vkQueueSubmit(DeviceManager.getGraphicsQueue().queue(), submitInfo, inFlightFences.get(currentFrame))) != VK_SUCCESS) { + vkResetFences(device, inFlightFences.get(currentFrame)); + throw new RuntimeException("Failed to submit draw command buffer: %s".formatted(VkResult.decode(vkResult))); + } + + vkWaitForFences(device, inFlightFences.get(currentFrame), true, VUtil.UINT64_MAX); + + this.beginRenderPass(stack); + } + } + public void endRenderPass() { endRenderPass(currentCmdBuffer); } @@ -540,6 +575,12 @@ public Pipeline getBoundPipeline() { return boundPipeline; } + private static void resetDynamicState(VkCommandBuffer commandBuffer) { + vkCmdSetDepthBias(commandBuffer, 0.0F, 0.0F, 0.0F); + + vkCmdSetLineWidth(commandBuffer, 1.0F); + } + public static void setDepthBias(float units, float factor) { VkCommandBuffer commandBuffer = INSTANCE.currentCmdBuffer;