Skip to content

Commit ca1c505

Browse files
committed
Mitigate uniform upload sync hazard
1 parent 0535bd2 commit ca1c505

4 files changed

Lines changed: 79 additions & 13 deletions

File tree

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

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,13 @@
2121
import net.vulkanmod.vulkan.Renderer;
2222
import net.vulkanmod.vulkan.Synchronization;
2323
import net.vulkanmod.vulkan.VRenderSystem;
24+
import net.vulkanmod.vulkan.Vulkan;
2425
import net.vulkanmod.vulkan.device.DeviceManager;
2526
import net.vulkanmod.vulkan.framebuffer.Framebuffer;
26-
import net.vulkanmod.vulkan.memory.buffer.IndexBuffer;
27+
import net.vulkanmod.vulkan.memory.buffer.StagingBuffer;
2728
import net.vulkanmod.vulkan.queue.GraphicsQueue;
28-
import net.vulkanmod.vulkan.queue.Queue;
2929
import net.vulkanmod.vulkan.shader.GraphicsPipeline;
3030
import net.vulkanmod.vulkan.shader.Pipeline;
31-
import net.vulkanmod.vulkan.shader.converter.Sampler;
3231
import net.vulkanmod.vulkan.shader.descriptor.ImageDescriptor;
3332
import net.vulkanmod.vulkan.shader.descriptor.UBO;
3433
import net.vulkanmod.vulkan.texture.ImageUtil;
@@ -37,9 +36,7 @@
3736
import org.lwjgl.opengl.*;
3837
import org.lwjgl.system.MemoryStack;
3938
import org.lwjgl.system.MemoryUtil;
40-
import org.lwjgl.vulkan.KHRDynamicRendering;
41-
import org.lwjgl.vulkan.VK11;
42-
import org.lwjgl.vulkan.VkCommandBuffer;
39+
import org.lwjgl.vulkan.*;
4340
import org.slf4j.Logger;
4441

4542
import java.nio.ByteBuffer;
@@ -48,8 +45,7 @@
4845
import java.util.function.Supplier;
4946

5047
import static org.lwjgl.system.MemoryStack.stackPush;
51-
import static org.lwjgl.vulkan.VK10.VK_INDEX_TYPE_UINT16;
52-
import static org.lwjgl.vulkan.VK10.VK_INDEX_TYPE_UINT32;
48+
import static org.lwjgl.vulkan.VK10.*;
5349

5450
public class VkCommandEncoder implements CommandEncoder {
5551
private static final Logger LOGGER = LogUtils.getLogger();
@@ -260,13 +256,33 @@ public void writeToBuffer(GpuBufferSlice gpuBufferSlice, ByteBuffer byteBuffer)
260256
throw new IllegalStateException("Buffer already closed");
261257
}
262258
else {
263-
int remaining = byteBuffer.remaining();
264-
if (remaining + gpuBufferSlice.offset() > vkGpuBuffer.size()) {
259+
int size = byteBuffer.remaining();
260+
if (size + gpuBufferSlice.offset() > vkGpuBuffer.size()) {
265261
throw new IllegalArgumentException(
266-
"Cannot write more data than this buffer can hold (attempting to write " + remaining + " bytes at offset " + gpuBufferSlice.offset() + " to " + gpuBufferSlice.length() + " slice size)"
262+
"Cannot write more data than this buffer can hold (attempting to write " + size + " bytes at offset " + gpuBufferSlice.offset() + " to " + gpuBufferSlice.length() + " slice size)"
267263
);
268264
} else {
269-
vkGpuBuffer.buffer.copyBuffer(byteBuffer, byteBuffer.remaining(), gpuBufferSlice.offset());
265+
int dstOffset = gpuBufferSlice.offset();
266+
267+
var commandBuffer = Renderer.getInstance().getTransferCb();
268+
269+
StagingBuffer stagingBuffer = Vulkan.getStagingBuffer();
270+
stagingBuffer.copyBuffer(size, byteBuffer);
271+
272+
long srcOffset = stagingBuffer.getOffset();
273+
274+
try (MemoryStack stack = MemoryStack.stackPush()) {
275+
if (!commandBuffer.isRecording()) {
276+
commandBuffer.begin(stack);
277+
}
278+
279+
VkBufferCopy.Buffer copyRegion = VkBufferCopy.calloc(1, stack);
280+
copyRegion.size(size);
281+
copyRegion.srcOffset(srcOffset);
282+
copyRegion.dstOffset(dstOffset);
283+
284+
vkCmdCopyBuffer(commandBuffer.handle, stagingBuffer.getId(), vkGpuBuffer.buffer.getId(), copyRegion);
285+
}
270286
}
271287
}
272288
}

src/main/java/net/vulkanmod/vulkan/Renderer.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import net.vulkanmod.vulkan.memory.MemoryManager;
2020
import net.vulkanmod.vulkan.pass.DefaultMainPass;
2121
import net.vulkanmod.vulkan.pass.MainPass;
22+
import net.vulkanmod.vulkan.queue.CommandPool;
2223
import net.vulkanmod.vulkan.shader.GraphicsPipeline;
2324
import net.vulkanmod.vulkan.shader.Pipeline;
2425
import net.vulkanmod.vulkan.shader.PipelineState;
@@ -89,6 +90,7 @@ public static int getCurrentImage() {
8990
private ArrayList<Long> imageAvailableSemaphores;
9091
private ArrayList<Long> renderFinishedSemaphores;
9192
private ArrayList<Long> inFlightFences;
93+
private List<CommandPool.CommandBuffer> transferCbs;
9294

9395
private Framebuffer boundFramebuffer;
9496
private RenderPass boundRenderPass;
@@ -158,6 +160,19 @@ private void allocateCommandBuffers() {
158160
commandBuffers.add(new VkCommandBuffer(pCommandBuffers.get(i), device));
159161
}
160162
}
163+
164+
if (transferCbs != null) {
165+
transferCbs.forEach(commandBuffer -> {
166+
vkResetCommandBuffer(commandBuffer.handle, 0);
167+
commandBuffer.reset();
168+
});
169+
}
170+
171+
transferCbs = new ArrayList<>(framesNum);
172+
173+
for (int i = 0; i < framesNum; i++) {
174+
transferCbs.add(DeviceManager.getTransferQueue().getCommandPool().getCommandBuffer());
175+
}
161176
}
162177

163178
private void createSyncObjects() {
@@ -302,6 +317,7 @@ public void endFrame() {
302317

303318
mainPass.end(currentCmdBuffer);
304319

320+
submitUploads();
305321
waitFences();
306322

307323
submitFrame();
@@ -377,6 +393,7 @@ public void flushCmds() {
377393

378394
vkResetFences(device, inFlightFences.get(currentFrame));
379395

396+
submitUploads();
380397
waitFences();
381398

382399
if ((vkResult = vkQueueSubmit(DeviceManager.getGraphicsQueue().queue(), submitInfo, inFlightFences.get(currentFrame))) != VK_SUCCESS) {
@@ -390,6 +407,25 @@ public void flushCmds() {
390407
}
391408
}
392409

410+
public void submitUploads() {
411+
var transferCb = transferCbs.get(currentFrame);
412+
413+
if (transferCb.isRecording()) {
414+
415+
try (MemoryStack stack = MemoryStack.stackPush()) {
416+
transferCb.submitCommands(stack,
417+
DeviceManager.getTransferQueue().queue(),
418+
false);
419+
}
420+
421+
Synchronization.INSTANCE.addCommandBuffer(transferCb);
422+
423+
transferCbs.set(currentFrame, DeviceManager.getTransferQueue()
424+
.getCommandPool()
425+
.getCommandBuffer());
426+
}
427+
}
428+
393429
public void endRenderPass() {
394430
endRenderPass(currentCmdBuffer);
395431
}
@@ -465,6 +501,7 @@ void waitForSwapChain() {
465501

466502
@SuppressWarnings("UnreachableCode")
467503
private void recreateSwapChain() {
504+
submitUploads();
468505
waitFences();
469506
Vulkan.waitIdle();
470507

@@ -593,6 +630,10 @@ public SwapChain getSwapChain() {
593630
return swapChain;
594631
}
595632

633+
public CommandPool.CommandBuffer getTransferCb() {
634+
return transferCbs.get(currentFrame);
635+
}
636+
596637
private static void resetDynamicState(VkCommandBuffer commandBuffer) {
597638
vkCmdSetDepthBias(commandBuffer, 0.0F, 0.0F, 0.0F);
598639

src/main/java/net/vulkanmod/vulkan/memory/MemoryTypes.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,10 @@ static abstract class MappableMemory extends MemoryType {
106106

107107
@Override
108108
public void copyToBuffer(Buffer buffer, ByteBuffer src, long size, long srcOffset, long dstOffset) {
109-
VUtil.memcpy(src, buffer, size, srcOffset, dstOffset);
109+
StagingBuffer stagingBuffer = Vulkan.getStagingBuffer();
110+
stagingBuffer.copyBuffer((int) size, src);
111+
112+
DeviceManager.getTransferQueue().copyBufferCmd(stagingBuffer.getId(), stagingBuffer.getOffset(), buffer.getId(), dstOffset, size);
110113
}
111114

112115
@Override

src/main/java/net/vulkanmod/vulkan/queue/CommandPool.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ public void createCommandPool(int queueFamily) {
4141
}
4242
}
4343

44+
public CommandBuffer getCommandBuffer() {
45+
try (MemoryStack stack = stackPush()) {
46+
return getCommandBuffer(stack);
47+
}
48+
}
49+
4450
public CommandBuffer getCommandBuffer(MemoryStack stack) {
4551
if (availableCmdBuffers.isEmpty()) {
4652
allocateCommandBuffers(stack);

0 commit comments

Comments
 (0)