|
33 | 33 | import net.vulkanmod.vulkan.shader.descriptor.UBO; |
34 | 34 | import net.vulkanmod.vulkan.texture.ImageUtil; |
35 | 35 | import net.vulkanmod.vulkan.texture.VTextureSelector; |
| 36 | +import net.vulkanmod.vulkan.util.VUtil; |
| 37 | +import net.vulkanmod.vulkan.util.VkResult; |
36 | 38 | import org.jetbrains.annotations.Nullable; |
37 | 39 | import org.lwjgl.opengl.*; |
38 | 40 | import org.lwjgl.system.MemoryStack; |
|
41 | 43 | import org.slf4j.Logger; |
42 | 44 |
|
43 | 45 | import java.nio.ByteBuffer; |
| 46 | +import java.nio.LongBuffer; |
44 | 47 | import java.util.*; |
45 | 48 | import java.util.function.BiConsumer; |
46 | 49 | import java.util.function.Supplier; |
@@ -599,19 +602,75 @@ public GpuFence createFence() { |
599 | 602 | if (this.inRenderPass) { |
600 | 603 | throw new IllegalStateException("Close the existing render pass before performing additional commands"); |
601 | 604 | } else { |
602 | | -// throw new UnsupportedOperationException(); |
603 | | - // TODO |
604 | | - return new GpuFence() { |
605 | | - @Override |
606 | | - public void close() { |
| 605 | + return new VkGpuFence(createFenceHandle()); |
| 606 | + } |
| 607 | + } |
607 | 608 |
|
608 | | - } |
| 609 | + private static final class VkGpuFence implements GpuFence { |
| 610 | + private long fence; |
609 | 611 |
|
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; |
615 | 674 | } |
616 | 675 | } |
617 | 676 |
|
|
0 commit comments