feat(renderer): Implement cloning of RenderingBo objects in commit process

This commit is contained in:
extio-de
2025-12-25 15:43:04 +01:00
parent e8aee54a34
commit b2c7747782
2 changed files with 42 additions and 10 deletions

View File

@@ -2,10 +2,8 @@ package de.extio.game_engine.renderer.work;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@@ -21,8 +19,6 @@ public class RendererWorkingSetImpl implements RendererWorkingSet {
private final BlockingQueue<Map<String, RenderingBo>> mapsPool = new ArrayBlockingQueue<>(100); private final BlockingQueue<Map<String, RenderingBo>> mapsPool = new ArrayBlockingQueue<>(100);
private final BlockingQueue<Set<Class<? extends RenderingBo>>> setsPool = new ArrayBlockingQueue<>(100);
private final RenderingBoPool rendererBoPool; private final RenderingBoPool rendererBoPool;
public RendererWorkingSetImpl(final RenderingBoPool rendererBoPool) { public RendererWorkingSetImpl(final RenderingBoPool rendererBoPool) {
@@ -98,17 +94,22 @@ public class RendererWorkingSetImpl implements RendererWorkingSet {
previousLiveRef.set(v.live()); previousLiveRef.set(v.live());
if (clone) { if (clone) {
final Map<String, RenderingBo> newNext = this.obtainMapFromPool(); final Map<String, RenderingBo> newNext = this.obtainMapFromPool();
newNext.putAll(v.next()); v.next().entrySet().forEach(e -> {
final RenderingBo copy = this.rendererBoPool.copy(e.getValue());
newNext.put(e.getKey(), copy);
});
return new RendererWork(v.next(), newNext); return new RendererWork(v.next(), newNext);
} }
else { else {
v.live().values().forEach(this.rendererBoPool::release);
return new RendererWork(v.next(), this.obtainMapFromPool()); return new RendererWork(v.next(), this.obtainMapFromPool());
} }
}); });
final var previousLiveSet = previousLiveRef.get(); final var previousLiveSet = previousLiveRef.get();
if (previousLiveSet != null) { if (previousLiveSet != null) {
if (clone) {
previousLiveSet.values().forEach(this.rendererBoPool::release);
}
this.returnMapToPool(previousLiveSet); this.returnMapToPool(previousLiveSet);
} }

View File

@@ -98,11 +98,18 @@ public class RendererWorkingSetImplTest {
void commitWithCloneCopiesUncommittedIntoNewUncommitted() { void commitWithCloneCopiesUncommittedIntoNewUncommitted() {
final RenderingBo bo1 = mock(RenderingBo.class); final RenderingBo bo1 = mock(RenderingBo.class);
when(bo1.getId()).thenReturn("bo1"); when(bo1.getId()).thenReturn("bo1");
final RenderingBo bo1Copy = mock(RenderingBo.class);
when(bo1Copy.getId()).thenReturn("bo1");
final RenderingBo bo2 = mock(RenderingBo.class); final RenderingBo bo2 = mock(RenderingBo.class);
when(bo2.getId()).thenReturn("bo2"); when(bo2.getId()).thenReturn("bo2");
final RenderingBo bo2Copy = mock(RenderingBo.class);
when(bo2Copy.getId()).thenReturn("bo2");
final RenderingBo bo3 = mock(RenderingBo.class); final RenderingBo bo3 = mock(RenderingBo.class);
when(bo3.getId()).thenReturn("bo3"); when(bo3.getId()).thenReturn("bo3");
when(this.renderingBoPool.copy(bo1)).thenReturn(bo1Copy);
when(this.renderingBoPool.copy(bo2)).thenReturn(bo2Copy);
this.workingSet.put(this.moduleA.getId(), bo1); this.workingSet.put(this.moduleA.getId(), bo1);
this.workingSet.put(this.moduleA.getId(), bo2); this.workingSet.put(this.moduleA.getId(), bo2);
@@ -110,13 +117,16 @@ public class RendererWorkingSetImplTest {
final var currentUncommitted = this.workingSet.getUncommittedWork(this.moduleA.getId()); final var currentUncommitted = this.workingSet.getUncommittedWork(this.moduleA.getId());
assertEquals(currentUncommitted, returnedUncommitted); assertEquals(currentUncommitted, returnedUncommitted);
assertEquals(Map.of("bo1", bo1, "bo2", bo2), currentUncommitted); assertEquals(Map.of("bo1", bo1Copy, "bo2", bo2Copy), currentUncommitted);
final List<RenderingBo> live = new ArrayList<>(); final List<RenderingBo> live = new ArrayList<>();
this.workingSet.getLiveSet(live, null); this.workingSet.getLiveSet(live, null);
assertEquals(2, live.size()); assertEquals(2, live.size());
assertTrue(live.containsAll(List.of(bo1, bo2))); assertTrue(live.containsAll(List.of(bo1, bo2)));
verify(this.renderingBoPool, times(1)).copy(bo1);
verify(this.renderingBoPool, times(1)).copy(bo2);
this.workingSet.put(this.moduleA.getId(), bo3); this.workingSet.put(this.moduleA.getId(), bo3);
final List<RenderingBo> liveAfterAdd = new ArrayList<>(); final List<RenderingBo> liveAfterAdd = new ArrayList<>();
this.workingSet.getLiveSet(liveAfterAdd, null); this.workingSet.getLiveSet(liveAfterAdd, null);
@@ -204,20 +214,31 @@ public class RendererWorkingSetImplTest {
} }
@Test @Test
void secondCommitReleasesPreviousLiveWork() { void secondCommitWithCloneReleasesPreviousLiveWork() {
final var bo1 = new TestBoA(); final var bo1 = new TestBoA();
bo1.setId("bo1"); bo1.setId("bo1");
final var bo2 = new TestBoA(); final var bo2 = new TestBoA();
bo2.setId("bo2"); bo2.setId("bo2");
final var bo1Copy = new TestBoA();
bo1Copy.setId("bo1");
final var bo2Copy = new TestBoA();
bo2Copy.setId("bo2");
when(this.renderingBoPool.copy(bo1)).thenReturn(bo1Copy);
when(this.renderingBoPool.copy(bo2)).thenReturn(bo2Copy);
this.workingSet.put(this.moduleA.getId(), bo1); this.workingSet.put(this.moduleA.getId(), bo1);
this.workingSet.put(this.moduleA.getId(), bo2); this.workingSet.put(this.moduleA.getId(), bo2);
this.workingSet.commit(this.moduleA.getId(), false); this.workingSet.commit(this.moduleA.getId(), true);
final var bo3 = new TestBoB(); final var bo3 = new TestBoB();
bo3.setId("bo3"); bo3.setId("bo3");
final var bo3Copy = new TestBoB();
bo3Copy.setId("bo3");
when(this.renderingBoPool.copy(bo3)).thenReturn(bo3Copy);
this.workingSet.put(this.moduleA.getId(), bo3); this.workingSet.put(this.moduleA.getId(), bo3);
this.workingSet.commit(this.moduleA.getId(), false); this.workingSet.commit(this.moduleA.getId(), true);
verify(this.renderingBoPool, times(1)).release(bo1); verify(this.renderingBoPool, times(1)).release(bo1);
verify(this.renderingBoPool, times(1)).release(bo2); verify(this.renderingBoPool, times(1)).release(bo2);
@@ -356,6 +377,10 @@ public class RendererWorkingSetImplTest {
private static abstract class TestBoBase implements RenderingBo { private static abstract class TestBoBase implements RenderingBo {
private String id; private String id;
private boolean applied;
private boolean closed;
@Override @Override
public void setId(final String id) { public void setId(final String id) {
@@ -480,9 +505,15 @@ public class RendererWorkingSetImplTest {
@Override @Override
public void setRendererData(final RendererData RendererData) { public void setRendererData(final RendererData RendererData) {
} }
@Override
public void apply(RenderingBo other) {
this.applied = true;
}
@Override @Override
public void close() { public void close() {
this.closed = true;
} }
} }