diff --git a/sdl-gpu/src/main/java/com/gtnewhorizons/angelica/sdlgpu/SDLGPURenderBackend.java b/sdl-gpu/src/main/java/com/gtnewhorizons/angelica/sdlgpu/SDLGPURenderBackend.java index 40320b58b..f5f03d835 100644 --- a/sdl-gpu/src/main/java/com/gtnewhorizons/angelica/sdlgpu/SDLGPURenderBackend.java +++ b/sdl-gpu/src/main/java/com/gtnewhorizons/angelica/sdlgpu/SDLGPURenderBackend.java @@ -3425,6 +3425,7 @@ public class SDLGPURenderBackend extends RenderBackend { } private void downloadBufferBlocking(long handle, int offset, int size, ByteBuffer out) { + if (size <= 0) return; flushAndSubmitMidFrame(); final long cb = SDL_AcquireGPUCommandBuffer(device.getDevice()); if (cb == 0) return; diff --git a/sdl-gpu/src/main/java/com/gtnewhorizons/angelica/sdlgpu/resource/ResourceManager.java b/sdl-gpu/src/main/java/com/gtnewhorizons/angelica/sdlgpu/resource/ResourceManager.java index d5b853cba..cb2003ff8 100644 --- a/sdl-gpu/src/main/java/com/gtnewhorizons/angelica/sdlgpu/resource/ResourceManager.java +++ b/sdl-gpu/src/main/java/com/gtnewhorizons/angelica/sdlgpu/resource/ResourceManager.java @@ -1585,6 +1585,7 @@ public final class ResourceManager { public boolean arenaUpload(ByteBuffer data, long dstHandle, long dstOffset, boolean cycle) { final FrameManager.FrameState f = frameManager.frame(); final int size = data.remaining(); + if (size == 0) return true; if (!f.arena.fits(size)) { return false; } @@ -1682,6 +1683,7 @@ public final class ResourceManager { if (srcOff < 0 || size < 0 || srcOff + size > src.capacity()) { throw new IllegalStateException("uploadRangeToBuffer: bad source range srcOff=" + srcOff + " size=" + size + " src.capacity=" + src.capacity()); } + if (size == 0) return; final long xfer = acquireTransferBuffer(size); if (xfer == 0) return; diff --git a/sdl-gpu/src/test/java/com/gtnewhorizons/angelica/sdlgpu/glsm/GlsmSdlEmptyBufferTransferTest.java b/sdl-gpu/src/test/java/com/gtnewhorizons/angelica/sdlgpu/glsm/GlsmSdlEmptyBufferTransferTest.java new file mode 100644 index 000000000..1a88e70f2 --- /dev/null +++ b/sdl-gpu/src/test/java/com/gtnewhorizons/angelica/sdlgpu/glsm/GlsmSdlEmptyBufferTransferTest.java @@ -0,0 +1,66 @@ +package com.gtnewhorizons.angelica.sdlgpu.glsm; + +import com.gtnewhorizons.angelica.glsm.GLStateManager; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.lwjgl.opengl.GL15; +import org.lwjgl.opengl.GL40; +import org.lwjgl.opengl.GL43; +import org.lwjgl.system.MemoryUtil; + +import java.nio.ByteBuffer; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@Tag("glsm-sdl") +@ExtendWith(GlsmSdlFrameExtension.class) +class GlsmSdlEmptyBufferTransferTest { + + private int id; + private ByteBuffer empty; + + @BeforeEach + void setUp() { + id = GLStateManager.glGenBuffers(); + empty = MemoryUtil.memAlloc(16); + empty.limit(0); + } + + @AfterEach + void tearDown() { + MemoryUtil.memFree(empty); + GLStateManager.glDeleteBuffers(id); + } + + @Test + void emptyBufferDataReplacesTheStoreWithoutACopy() { + final int target = GL40.GL_DRAW_INDIRECT_BUFFER; + GLStateManager.glBindBuffer(target, id); + GLStateManager.glBufferData(target, 256L, GL15.GL_STATIC_DRAW); + GlsmSdlHeadlessRig.resourceManager().flushUploadArena(); + GLStateManager.glBufferData(target, empty, GL15.GL_STATIC_DRAW); + assertEquals(0L, GlsmSdlHeadlessRig.frameManager().frame().arenaCopyPass); + assertEquals(0, GLStateManager.glGetBufferParameteri(target, GL15.GL_BUFFER_SIZE)); + } + + @Test + void emptyStorageBufferSubDataIssuesNoCopy() { + final int target = GL43.GL_SHADER_STORAGE_BUFFER; + GLStateManager.glBindBuffer(target, id); + GLStateManager.glBufferData(target, 256L, GL15.GL_DYNAMIC_DRAW); + final int before = GlsmSdlHeadlessRig.frameManager().frame().pendingUploadCommands; + GLStateManager.glBufferSubData(target, 0, empty); + assertEquals(before, GlsmSdlHeadlessRig.frameManager().frame().pendingUploadCommands); + } + + @Test + void emptyGetBufferSubDataDoesNotReachTheDevice() { + final int target = GL43.GL_SHADER_STORAGE_BUFFER; + GLStateManager.glBindBuffer(target, id); + GLStateManager.glBufferData(target, 256L, GL15.GL_DYNAMIC_DRAW); + GLStateManager.glGetBufferSubData(target, 0, empty); + } +}