diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/engine/DefaultGameEngine.java b/engine/src/main/java/com/bartlomiejpluta/base/core/engine/DefaultGameEngine.java index a69c3c0d..aa6711cb 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/engine/DefaultGameEngine.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/engine/DefaultGameEngine.java @@ -1,5 +1,6 @@ package com.bartlomiejpluta.base.core.engine; +import com.bartlomiejpluta.base.core.gc.OffHeapGarbageCollector; import com.bartlomiejpluta.base.core.logic.GameLogic; import com.bartlomiejpluta.base.core.thread.ThreadManager; import com.bartlomiejpluta.base.core.time.ChronoMeter; @@ -18,6 +19,7 @@ public class DefaultGameEngine implements GameEngine { private final WindowManager windowManager; private final ThreadManager threadManager; private final GameLogic logic; + private final OffHeapGarbageCollector garbageCollector; private final Thread thread; private final Window window; @@ -30,6 +32,7 @@ public class DefaultGameEngine implements GameEngine { public DefaultGameEngine(WindowManager windowManager, ThreadManager threadManager, GameLogic logic, + OffHeapGarbageCollector garbageCollector, @Value("${app.window.title}") String title, @Value("${app.window.width}") int width, @Value("${app.window.height}") int height, @@ -37,6 +40,7 @@ public class DefaultGameEngine implements GameEngine { this.windowManager = windowManager; this.threadManager = threadManager; this.logic = logic; + this.garbageCollector = garbageCollector; this.window = windowManager.createWindow(title, width, height); this.thread = threadManager.createThread(THREAD_NAME, this::run); @@ -96,7 +100,8 @@ public class DefaultGameEngine implements GameEngine { } private void cleanUp() { - logic.cleanUp(); + log.info("Performing off heap garbage collection"); + garbageCollector.cleanUp(); } @Override diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/gc/Cleanable.java b/engine/src/main/java/com/bartlomiejpluta/base/core/gc/Cleanable.java new file mode 100755 index 00000000..4eec5c50 --- /dev/null +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/gc/Cleanable.java @@ -0,0 +1,5 @@ +package com.bartlomiejpluta.base.core.gc; + +public interface Cleanable { + void cleanUp(); +} diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/gc/DefaultOffHeapGarbageCollector.java b/engine/src/main/java/com/bartlomiejpluta/base/core/gc/DefaultOffHeapGarbageCollector.java new file mode 100755 index 00000000..980f910a --- /dev/null +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/gc/DefaultOffHeapGarbageCollector.java @@ -0,0 +1,22 @@ +package com.bartlomiejpluta.base.core.gc; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Slf4j +@Component +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class DefaultOffHeapGarbageCollector implements OffHeapGarbageCollector { + private final List cleanables; + + @Override + public void cleanUp() { + cleanables.stream() + .peek(cleanable -> log.info("Performing {} cleaning", cleanable.getClass().getSimpleName())) + .forEach(Cleanable::cleanUp); + } +} diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/gc/Disposable.java b/engine/src/main/java/com/bartlomiejpluta/base/core/gc/Disposable.java new file mode 100755 index 00000000..14c95506 --- /dev/null +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/gc/Disposable.java @@ -0,0 +1,5 @@ +package com.bartlomiejpluta.base.core.gc; + +public interface Disposable { + void dispose(); +} diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/gc/OffHeapGarbageCollector.java b/engine/src/main/java/com/bartlomiejpluta/base/core/gc/OffHeapGarbageCollector.java new file mode 100755 index 00000000..a9b6edb0 --- /dev/null +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/gc/OffHeapGarbageCollector.java @@ -0,0 +1,5 @@ +package com.bartlomiejpluta.base.core.gc; + +public interface OffHeapGarbageCollector { + void cleanUp(); +} diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/object/mesh/Mesh.java b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/object/mesh/Mesh.java index f7e6d01d..af6822b5 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/object/mesh/Mesh.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/object/mesh/Mesh.java @@ -1,5 +1,6 @@ package com.bartlomiejpluta.base.core.gl.object.mesh; +import com.bartlomiejpluta.base.core.gc.Disposable; import com.bartlomiejpluta.base.core.gl.render.Renderable; import com.bartlomiejpluta.base.core.gl.shader.manager.ShaderManager; import com.bartlomiejpluta.base.core.ui.Window; @@ -13,7 +14,7 @@ import static org.lwjgl.opengl.GL15.*; import static org.lwjgl.opengl.GL20.*; import static org.lwjgl.opengl.GL30.*; -public class Mesh implements Renderable { +public class Mesh implements Renderable, Disposable { private final int vaoId; private final List vboIds = new ArrayList<>(2); private final int elementsCount; @@ -65,7 +66,7 @@ public class Mesh implements Renderable { } @Override - public void cleanUp() { + public void dispose() { glDisableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/object/texture/DefaultTextureManager.java b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/object/texture/DefaultTextureManager.java index a41bc749..d6b7866c 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/object/texture/DefaultTextureManager.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/object/texture/DefaultTextureManager.java @@ -29,4 +29,11 @@ public class DefaultTextureManager implements TextureManager { return texture; } + + @Override + public void cleanUp() { + log.info("Disposing textures"); + loadedTextures.forEach((name, texture) -> texture.dispose()); + log.info("{} textures has been disposed", loadedTextures.size()); + } } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/object/texture/Texture.java b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/object/texture/Texture.java index a106d38f..0d4c7fd5 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/object/texture/Texture.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/object/texture/Texture.java @@ -1,6 +1,7 @@ package com.bartlomiejpluta.base.core.gl.object.texture; import com.bartlomiejpluta.base.core.error.AppException; +import com.bartlomiejpluta.base.core.gc.Disposable; import lombok.Getter; import org.lwjgl.system.MemoryStack; @@ -12,7 +13,7 @@ import static org.lwjgl.opengl.GL13.glActiveTexture; import static org.lwjgl.stb.STBImage.stbi_failure_reason; import static org.lwjgl.stb.STBImage.stbi_load_from_memory; -public class Texture { +public class Texture implements Disposable { private static final int DESIRED_CHANNELS = 4; private final int textureId; @@ -57,4 +58,9 @@ public class Texture { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textureId); } + + @Override + public void dispose() { + glDeleteTextures(textureId); + } } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/object/texture/TextureManager.java b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/object/texture/TextureManager.java index f896df17..c56cd6a9 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/object/texture/TextureManager.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/object/texture/TextureManager.java @@ -1,5 +1,7 @@ package com.bartlomiejpluta.base.core.gl.object.texture; -public interface TextureManager { +import com.bartlomiejpluta.base.core.gc.Cleanable; + +public interface TextureManager extends Cleanable { Texture loadTexture(String textureFileName); } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/render/DefaultRenderer.java b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/render/DefaultRenderer.java index 0d1bb710..9a9ba4d7 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/render/DefaultRenderer.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/render/DefaultRenderer.java @@ -57,6 +57,6 @@ public class DefaultRenderer implements Renderer { @Override public void cleanUp() { - shaderManager.cleanUp(); + log.info("There is nothing to clean up here"); } } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/render/Renderable.java b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/render/Renderable.java index d3fb962a..6dbd8151 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/render/Renderable.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/render/Renderable.java @@ -5,5 +5,4 @@ import com.bartlomiejpluta.base.core.ui.Window; public interface Renderable { void render(Window window, ShaderManager shaderManager); - void cleanUp(); } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/render/Renderer.java b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/render/Renderer.java index f8f8c514..d8931e8a 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/render/Renderer.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/render/Renderer.java @@ -1,11 +1,9 @@ package com.bartlomiejpluta.base.core.gl.render; +import com.bartlomiejpluta.base.core.gc.Cleanable; import com.bartlomiejpluta.base.core.ui.Window; -public interface Renderer { +public interface Renderer extends Cleanable { void init(); - void render(Window window, Renderable renderable); - - void cleanUp(); } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/shader/manager/DefaultShaderManager.java b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/shader/manager/DefaultShaderManager.java index 1e5e6bf5..8953ca0f 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/shader/manager/DefaultShaderManager.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/shader/manager/DefaultShaderManager.java @@ -142,7 +142,8 @@ public class DefaultShaderManager implements ShaderManager { @Override public void cleanUp() { - log.info("Cleaning up shaders"); - shaders.forEach((name, program) -> program.cleanUp()); + log.info("Disposing shaders"); + shaders.forEach((name, program) -> program.dispose()); + log.info("{} shaders has been disposed", shaders.size()); } } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/shader/manager/ShaderManager.java b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/shader/manager/ShaderManager.java index e000245f..43582dc5 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/shader/manager/ShaderManager.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/shader/manager/ShaderManager.java @@ -1,9 +1,10 @@ package com.bartlomiejpluta.base.core.gl.shader.manager; +import com.bartlomiejpluta.base.core.gc.Cleanable; import com.bartlomiejpluta.base.core.gl.shader.uniform.Uniform; import org.joml.*; -public interface ShaderManager { +public interface ShaderManager extends Cleanable { ShaderManager createShader(String programName, String vertexShaderFilename, String fragmentShaderFilename); ShaderManager selectShader(String programName); @@ -41,6 +42,4 @@ public interface ShaderManager { ShaderManager setUniform(String uniformName, int index, Uniform uniform); ShaderManager setUniforms(String uniformName, Uniform[] uniforms); - - void cleanUp(); } \ No newline at end of file diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/shader/program/ShaderProgram.java b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/shader/program/ShaderProgram.java index e17844b8..d2250531 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/gl/shader/program/ShaderProgram.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/gl/shader/program/ShaderProgram.java @@ -1,6 +1,7 @@ package com.bartlomiejpluta.base.core.gl.shader.program; import com.bartlomiejpluta.base.core.error.AppException; +import com.bartlomiejpluta.base.core.gc.Disposable; import com.bartlomiejpluta.base.core.gl.shader.uniform.Uniform; import lombok.extern.slf4j.Slf4j; import org.joml.*; @@ -13,7 +14,7 @@ import static java.lang.String.format; import static org.lwjgl.opengl.GL20.*; @Slf4j -public class ShaderProgram { +public class ShaderProgram implements Disposable { private final int programId; private final int vertexShaderId; private final int fragmentShaderId; @@ -159,7 +160,8 @@ public class ShaderProgram { glUseProgram(0); } - public void cleanUp() { + @Override + public void dispose() { glUseProgram(0); if(programId != 0) { diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/logic/GameLogic.java b/engine/src/main/java/com/bartlomiejpluta/base/core/logic/GameLogic.java index c45c030f..1f2f5293 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/logic/GameLogic.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/logic/GameLogic.java @@ -1,8 +1,9 @@ package com.bartlomiejpluta.base.core.logic; +import com.bartlomiejpluta.base.core.gc.Cleanable; import com.bartlomiejpluta.base.core.ui.Window; -public interface GameLogic { +public interface GameLogic extends Cleanable { void init(Window window); void input(Window window); @@ -10,6 +11,4 @@ public interface GameLogic { void update(float dt); void render(Window window); - - void cleanUp(); } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/util/mesh/DefaultMeshManager.java b/engine/src/main/java/com/bartlomiejpluta/base/core/util/mesh/DefaultMeshManager.java index 6fb61892..52597958 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/util/mesh/DefaultMeshManager.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/util/mesh/DefaultMeshManager.java @@ -28,6 +28,13 @@ public class DefaultMeshManager implements MeshManager { return mesh; } + @Override + public void cleanUp() { + log.info("Disposing meshes"); + quads.forEach((dim, mesh) -> mesh.dispose()); + log.info("{} meshes has been disposed", quads.size()); + } + @Data private static class QuadDimension { private final Vector2f size; diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/util/mesh/MeshManager.java b/engine/src/main/java/com/bartlomiejpluta/base/core/util/mesh/MeshManager.java index ee2e5827..23dfc0d0 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/util/mesh/MeshManager.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/util/mesh/MeshManager.java @@ -1,7 +1,8 @@ package com.bartlomiejpluta.base.core.util.mesh; +import com.bartlomiejpluta.base.core.gc.Cleanable; import com.bartlomiejpluta.base.core.gl.object.mesh.Mesh; -public interface MeshManager { +public interface MeshManager extends Cleanable { Mesh createQuad(float width, float height, float originX, float originY); } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/world/map/GameMap.java b/engine/src/main/java/com/bartlomiejpluta/base/core/world/map/GameMap.java index ae0e7c6e..26716ec5 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/world/map/GameMap.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/world/map/GameMap.java @@ -5,14 +5,11 @@ import com.bartlomiejpluta.base.core.world.movement.Movement; import com.bartlomiejpluta.base.core.world.tileset.model.Tile; import com.bartlomiejpluta.base.core.world.tileset.model.TileSet; import lombok.Getter; -import lombok.extern.slf4j.Slf4j; import org.joml.Vector2f; import org.joml.Vector2i; import java.util.Arrays; -import java.util.Objects; -@Slf4j public class GameMap { private static final int LAYERS = 4; private final TileSet tileSet; @@ -92,8 +89,4 @@ public class GameMap { return isTargetReachable && canMoveFromCurrentTile; } - - public void cleanUp() { - Arrays.stream(map).flatMap(Arrays::stream).filter(Objects::nonNull).forEach(Tile::cleanUp); - } } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/world/object/RenderableObject.java b/engine/src/main/java/com/bartlomiejpluta/base/core/world/object/RenderableObject.java index 45ac2d66..cd2b19b3 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/world/object/RenderableObject.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/world/object/RenderableObject.java @@ -25,11 +25,6 @@ public abstract class RenderableObject extends Object implements Renderable { mesh.render(window, shaderManager); } - @Override - public void cleanUp() { - mesh.cleanUp(); - } - public void setAlpha(float alpha) { material.setAlpha(alpha); } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/world/scene/Scene.java b/engine/src/main/java/com/bartlomiejpluta/base/core/world/scene/Scene.java index 592af87c..3c2096e6 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/world/scene/Scene.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/world/scene/Scene.java @@ -7,8 +7,8 @@ import com.bartlomiejpluta.base.core.ui.Window; import com.bartlomiejpluta.base.core.world.animation.AnimationableObject; import com.bartlomiejpluta.base.core.world.animation.Animator; import com.bartlomiejpluta.base.core.world.camera.Camera; -import com.bartlomiejpluta.base.core.world.object.RenderableObject; import com.bartlomiejpluta.base.core.world.map.GameMap; +import com.bartlomiejpluta.base.core.world.object.RenderableObject; import lombok.AllArgsConstructor; import lombok.Setter; @@ -71,9 +71,4 @@ public class Scene implements Renderable { object.render(window, shaderManager); } - - @Override - public void cleanUp() { - map.cleanUp(); - } } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/world/tileset/manager/DefaultTileSetManager.java b/engine/src/main/java/com/bartlomiejpluta/base/core/world/tileset/manager/DefaultTileSetManager.java index ce9dfca4..169f3ebb 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/world/tileset/manager/DefaultTileSetManager.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/world/tileset/manager/DefaultTileSetManager.java @@ -34,4 +34,9 @@ public class DefaultTileSetManager implements TileSetManager { return tileset; } + + @Override + public void cleanUp() { + log.info("There is nothing to clean up here"); + } } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/world/tileset/manager/TileSetManager.java b/engine/src/main/java/com/bartlomiejpluta/base/core/world/tileset/manager/TileSetManager.java index fa430da9..fe87153f 100755 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/world/tileset/manager/TileSetManager.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/world/tileset/manager/TileSetManager.java @@ -1,7 +1,8 @@ package com.bartlomiejpluta.base.core.world.tileset.manager; +import com.bartlomiejpluta.base.core.gc.Cleanable; import com.bartlomiejpluta.base.core.world.tileset.model.TileSet; -public interface TileSetManager { +public interface TileSetManager extends Cleanable { TileSet createTileSet(String tileSetFileName, int rows, int columns); } diff --git a/game/src/main/java/com/bartlomiejpluta/base/game/world/entity/manager/DefaultEntityManager.java b/game/src/main/java/com/bartlomiejpluta/base/game/world/entity/manager/DefaultEntityManager.java index 9f41d128..010cb9da 100755 --- a/game/src/main/java/com/bartlomiejpluta/base/game/world/entity/manager/DefaultEntityManager.java +++ b/game/src/main/java/com/bartlomiejpluta/base/game/world/entity/manager/DefaultEntityManager.java @@ -6,10 +6,12 @@ import com.bartlomiejpluta.base.core.util.mesh.MeshManager; import com.bartlomiejpluta.base.game.world.entity.model.Entity; import com.bartlomiejpluta.base.game.world.entity.config.EntitySpriteConfiguration; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.joml.Vector2f; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +@Slf4j @Component @RequiredArgsConstructor(onConstructor = @__(@Autowired)) public class DefaultEntityManager implements EntityManager { @@ -28,4 +30,9 @@ public class DefaultEntityManager implements EntityManager { var spriteHeight = texture.getHeight() / (float) dimension.x; return meshManager.createQuad(spriteWidth, spriteHeight, spriteWidth / 2, spriteHeight*0.9f); } + + @Override + public void cleanUp() { + log.info("There is nothing to clean up"); + } } diff --git a/game/src/main/java/com/bartlomiejpluta/base/game/world/entity/manager/EntityManager.java b/game/src/main/java/com/bartlomiejpluta/base/game/world/entity/manager/EntityManager.java index 5697d48e..2f5a0415 100755 --- a/game/src/main/java/com/bartlomiejpluta/base/game/world/entity/manager/EntityManager.java +++ b/game/src/main/java/com/bartlomiejpluta/base/game/world/entity/manager/EntityManager.java @@ -1,9 +1,10 @@ package com.bartlomiejpluta.base.game.world.entity.manager; +import com.bartlomiejpluta.base.core.gc.Cleanable; import com.bartlomiejpluta.base.core.gl.object.material.Material; import com.bartlomiejpluta.base.game.world.entity.model.Entity; import org.joml.Vector2f; -public interface EntityManager { +public interface EntityManager extends Cleanable { Entity createEntity(Material material, Vector2f coordinateStepSize); }