Skip zero-size buffer uploads and readbacks on SDL-GPU (#2249)

This commit is contained in:
Jason Mitchell authored and GitHub committed 2026-10-11 09:41:28 -07:00
1 parent 3d3d0f9e18
commit d3dee841e8
3 files changed
+69

No files matched your search

@@ -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;
@@ -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;
@@ -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);
}
}