Skip to content

Commit 280d03a

Browse files
committed
Use dedicated Vulkan fence for GPU waits
1 parent 2980232 commit 280d03a

File tree

1 file changed

+70
-11
lines changed

1 file changed

+70
-11
lines changed

src/main/java/net/vulkanmod/render/engine/VkCommandEncoder.java

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
import net.vulkanmod.vulkan.shader.descriptor.UBO;
3434
import net.vulkanmod.vulkan.texture.ImageUtil;
3535
import net.vulkanmod.vulkan.texture.VTextureSelector;
36+
import net.vulkanmod.vulkan.util.VUtil;
37+
import net.vulkanmod.vulkan.util.VkResult;
3638
import org.jetbrains.annotations.Nullable;
3739
import org.lwjgl.opengl.*;
3840
import org.lwjgl.system.MemoryStack;
@@ -41,6 +43,7 @@
4143
import org.slf4j.Logger;
4244

4345
import java.nio.ByteBuffer;
46+
import java.nio.LongBuffer;
4447
import java.util.*;
4548
import java.util.function.BiConsumer;
4649
import java.util.function.Supplier;
@@ -599,19 +602,75 @@ public GpuFence createFence() {
599602
if (this.inRenderPass) {
600603
throw new IllegalStateException("Close the existing render pass before performing additional commands");
601604
} else {
602-
// throw new UnsupportedOperationException();
603-
// TODO
604-
return new GpuFence() {
605-
@Override
606-
public void close() {
605+
return new VkGpuFence(createFenceHandle());
606+
}
607+
}
607608

608-
}
609+
private static final class VkGpuFence implements GpuFence {
610+
private long fence;
609611

610-
@Override
611-
public boolean awaitCompletion(long l) {
612-
return true;
613-
}
614-
};
612+
private VkGpuFence(long fence) {
613+
this.fence = fence;
614+
}
615+
616+
@Override
617+
public void close() {
618+
if (this.fence == VK_NULL_HANDLE) {
619+
return;
620+
}
621+
622+
Synchronization.waitFence(this.fence);
623+
this.destroyFence();
624+
}
625+
626+
@Override
627+
public boolean awaitCompletion(long timeout) {
628+
if (this.fence == VK_NULL_HANDLE) {
629+
return true;
630+
}
631+
632+
int vkResult = vkWaitForFences(Vulkan.getVkDevice(), this.fence, true, timeout);
633+
if (vkResult == VK_SUCCESS) {
634+
this.destroyFence();
635+
return true;
636+
}
637+
638+
if (vkResult == VK_TIMEOUT) {
639+
return false;
640+
}
641+
642+
throw new RuntimeException("Failed waiting for GPU fence: %s".formatted(VkResult.decode(vkResult)));
643+
}
644+
645+
private void destroyFence() {
646+
vkDestroyFence(Vulkan.getVkDevice(), this.fence, null);
647+
this.fence = VK_NULL_HANDLE;
648+
}
649+
}
650+
651+
private static long createFenceHandle() {
652+
try (MemoryStack stack = stackPush()) {
653+
VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.calloc(stack);
654+
fenceInfo.sType$Default();
655+
656+
LongBuffer pFence = stack.mallocLong(1);
657+
int vkResult = vkCreateFence(Vulkan.getVkDevice(), fenceInfo, null, pFence);
658+
if (vkResult != VK_SUCCESS) {
659+
throw new RuntimeException("Failed to create GPU fence: %s".formatted(VkResult.decode(vkResult)));
660+
}
661+
662+
long fence = pFence.get(0);
663+
664+
VkSubmitInfo submitInfo = VkSubmitInfo.calloc(stack);
665+
submitInfo.sType$Default();
666+
667+
vkResult = vkQueueSubmit(DeviceManager.getGraphicsQueue().vkQueue(), submitInfo, fence);
668+
if (vkResult != VK_SUCCESS) {
669+
vkDestroyFence(Vulkan.getVkDevice(), fence, null);
670+
throw new RuntimeException("Failed to submit GPU fence: %s".formatted(VkResult.decode(vkResult)));
671+
}
672+
673+
return fence;
615674
}
616675
}
617676

0 commit comments

Comments
 (0)