diff --git a/src/main/java/com/github/halotroop/litecraft/Litecraft.java b/src/main/java/com/github/halotroop/litecraft/Litecraft.java index 3539968..42eb545 100644 --- a/src/main/java/com/github/halotroop/litecraft/Litecraft.java +++ b/src/main/java/com/github/halotroop/litecraft/Litecraft.java @@ -12,12 +12,12 @@ import com.github.hydos.ginger.engine.common.Constants; import com.github.hydos.ginger.engine.common.api.*; import com.github.hydos.ginger.engine.common.api.game.*; import com.github.hydos.ginger.engine.common.cameras.*; -import com.github.hydos.ginger.engine.common.elements.objects.*; +import com.github.hydos.ginger.engine.common.elements.objects.Light; import com.github.hydos.ginger.engine.common.font.FontType; import com.github.hydos.ginger.engine.common.info.RenderAPI; import com.github.hydos.ginger.engine.common.io.Window; import com.github.hydos.ginger.engine.common.obj.ModelLoader; -import com.github.hydos.ginger.engine.opengl.api.*; +import com.github.hydos.ginger.engine.opengl.api.GingerGL; import com.github.hydos.ginger.engine.opengl.postprocessing.PostProcessing; import com.github.hydos.ginger.engine.opengl.render.GLRenderManager; import com.github.hydos.ginger.engine.opengl.render.models.GLTexturedModel; @@ -28,7 +28,6 @@ import tk.valoeghese.gateways.client.io.*; public class Litecraft extends Game { // FIXME: search for ((GingerGL)engine) and properly implement both render APIs when Vulkan is complete. - private static Litecraft INSTANCE; private World world; private LitecraftSave save; @@ -49,7 +48,7 @@ public class Litecraft extends Game // setup keybinds setupKeybinds(); // Open the title screen if nothing is already open. - if (GingerRegister.getInstance().currentScreen == null && world == null) ((GingerGL)engine).openScreen(new TitleScreen()); + if (GingerRegister.getInstance().currentScreen == null && world == null) ((GingerGL) engine).openScreen(new TitleScreen()); // start the game loop this.engine.startGameLoop(); } @@ -71,10 +70,8 @@ public class Litecraft extends Game System.exit(0); } - /** - * Things that ARE rendering: Anything that results in something being drawn to the frame buffer - * Things that are NOT rendering: Things that happen to update between frames but do not result in things being drawn to the screen - */ + /** Things that ARE rendering: Anything that results in something being drawn to the frame buffer + * Things that are NOT rendering: Things that happen to update between frames but do not result in things being drawn to the screen */ @Override public void render() { @@ -89,34 +86,33 @@ public class Litecraft extends Game // Put what's stored in the inactive framebuffer on the screen Window.swapBuffers(); } - + // Updates the debug stats once per real-time second, regardless of how many frames have been rendered private void updateDebugStats() { this.dbgStats.set(fps, ups, tps, 0); - this.fps=0; - this.ups=0; - this.tps=0; + this.fps = 0; + this.ups = 0; + this.tps = 0; this.frameTimer += 1000; } - + public void renderWorld() { GameData data = GingerRegister.getInstance().game.data; if (Window.renderAPI == RenderAPI.OpenGL) { - GLUtils.preRenderScene(((GingerGL)engine).getRegistry().masterRenderer); - ((GingerGL)engine).contrastFbo.bindFBO(); - ((GingerGL)engine).getRegistry().masterRenderer.renderScene(data.entities, data.normalMapEntities, data.lights, data.camera, data.clippingPlane); - ((GingerGL)engine).contrastFbo.unbindFBO(); - PostProcessing.doPostProcessing(((GingerGL)engine).contrastFbo.colorTexture); + GLUtils.preRenderScene(((GingerGL) engine).getRegistry().masterRenderer); + ((GingerGL) engine).contrastFbo.bindFBO(); + ((GingerGL) engine).getRegistry().masterRenderer.renderScene(data.entities, data.normalMapEntities, data.lights, data.camera, data.clippingPlane); + ((GingerGL) engine).contrastFbo.unbindFBO(); + PostProcessing.doPostProcessing(((GingerGL) engine).contrastFbo.colorTexture); } } - + + @Override public void update() - { - ups += 1; - } + { ups += 1; } private void setupConstants() { @@ -137,30 +133,29 @@ public class Litecraft extends Game MouseCallbackHandler.trackWindow(Window.getWindow()); // set up ginger utilities GLUtils.init(); - switch (Window.renderAPI) { - case OpenGL: - { - this.engine = new GingerGL(); - //Set the player model - GLTexturedModel playerModel = ModelLoader.loadGenericCube("block/cubes/stone/brick/stonebrick.png"); - FontType font = new FontType(GLLoader.loadFontAtlas("candara.png"), "candara.fnt"); - this.player = new PlayerEntity(playerModel, new Vector3f(0, 0, -3), 0, 180f, 0, new Vector3f(0.2f, 0.2f, 0.2f)); - this.camera = new FirstPersonCamera(player); - this.data = new GameData(this.player, this.camera, 20); - this.data.handleGuis = false; - ((GingerGL)engine).setup(new GLRenderManager(this.camera), INSTANCE); - ((GingerGL)engine).setGlobalFont(font); - this.data.entities.add(this.player); - break; - } - case Vulkan: - { - // TODO: Setup Vulkan - exit(); - break; - } + case OpenGL: + { + this.engine = new GingerGL(); + //Set the player model + GLTexturedModel playerModel = ModelLoader.loadGenericCube("block/cubes/stone/brick/stonebrick.png"); + FontType font = new FontType(GLLoader.loadFontAtlas("candara.png"), "candara.fnt"); + this.player = new PlayerEntity(playerModel, new Vector3f(0, 0, -3), 0, 180f, 0, new Vector3f(0.2f, 0.2f, 0.2f)); + this.camera = new FirstPersonCamera(player); + this.data = new GameData(this.player, this.camera, 20); + this.data.handleGuis = false; + ((GingerGL) engine).setup(new GLRenderManager(this.camera), INSTANCE); + ((GingerGL) engine).setGlobalFont(font); + this.data.entities.add(this.player); + break; + } + case Vulkan: + { + // TODO: Setup Vulkan + exit(); + break; + } } Light sun = new Light(new Vector3f(0, 105, 0), new Vector3f(0.9765625f, 0.98828125f, 0.05859375f), new Vector3f(0.002f, 0.002f, 0.002f)); this.data.lights.add(sun); @@ -180,14 +175,12 @@ public class Litecraft extends Game Input.addPressCallback(Keybind.FLY_DOWN, () -> ((PlayerEntity) this.player).move(RelativeDirection.DOWN)); } - /** - * Things that should be ticked: Entities when deciding an action, in-game timers (such as smelting), the in-game time - * Things that should not be ticked: Rendering, input, player movement - */ + /** Things that should be ticked: Entities when deciding an action, in-game timers (such as smelting), the in-game time + * Things that should not be ticked: Rendering, input, player movement */ @Override public void tick() { - tps += 1; + tps += 1; if (this.player instanceof PlayerEntity && camera != null) { Input.invokeAllListeners(); @@ -195,7 +188,7 @@ public class Litecraft extends Game camera.updateMovement(); } } - + // @formatter=off public static Litecraft getInstance() { return INSTANCE; } @@ -208,16 +201,14 @@ public class Litecraft extends Game public World getWorld() { return this.world; } - + public void changeWorld(World world) { this.world = world; } - + public void setSave(LitecraftSave save) { this.save = save; } @Override public void renderScene() - { - world.render(GingerRegister.getInstance().masterRenderer.blockRenderer); - } + { world.render(GingerRegister.getInstance().masterRenderer.blockRenderer); } } \ No newline at end of file diff --git a/src/main/java/com/github/halotroop/litecraft/render/BlockRenderer.java b/src/main/java/com/github/halotroop/litecraft/render/BlockRenderer.java index 7d8d2d3..1066fae 100644 --- a/src/main/java/com/github/halotroop/litecraft/render/BlockRenderer.java +++ b/src/main/java/com/github/halotroop/litecraft/render/BlockRenderer.java @@ -75,17 +75,17 @@ public class BlockRenderer extends Renderer implements WorldGenConstants public void render(BlockInstance[] renderList) { prepareRender(); - - for (BlockInstance entity : renderList) { - if (entity != null && entity.getModel() != null) - { - GLTexturedModel blockModel = entity.getModel(); - GL11.glBindTexture(GL11.GL_TEXTURE_2D, blockModel.getTexture().getTextureID()); - prepBlockInstance(entity); - GL11.glDrawElements(GL11.GL_TRIANGLES, blockModel.getRawModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0); - } - } -// disableWireframe(); -// shader.stop(); + for (BlockInstance entity : renderList) + { + if (entity != null && entity.getModel() != null) + { + GLTexturedModel blockModel = entity.getModel(); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, blockModel.getTexture().getTextureID()); + prepBlockInstance(entity); + GL11.glDrawElements(GL11.GL_TRIANGLES, blockModel.getRawModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0); + } + } + // disableWireframe(); + // shader.stop(); } } diff --git a/src/main/java/com/github/halotroop/litecraft/render/VoxelLoader.java b/src/main/java/com/github/halotroop/litecraft/render/VoxelLoader.java index 0a814f7..234fcfb 100644 --- a/src/main/java/com/github/halotroop/litecraft/render/VoxelLoader.java +++ b/src/main/java/com/github/halotroop/litecraft/render/VoxelLoader.java @@ -14,37 +14,36 @@ public class VoxelLoader extends GLLoader int width = 16; int height = 16; //Prepare the atlas texture and gen it - int atlasId = GL40.glGenTextures(); + int atlasId = GL11.glGenTextures(); //Bind it to openGL - GL40.glBindTexture(GL40.GL_TEXTURE_2D, atlasId); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, atlasId); //Apply the settings for the texture - GL40.glTexParameteri(GL40.GL_TEXTURE_2D, GL40.GL_TEXTURE_MIN_FILTER, GL40.GL_NEAREST); - GL40.glTexParameteri(GL40.GL_TEXTURE_2D, GL40.GL_TEXTURE_MAG_FILTER, GL40.GL_NEAREST); - //Fill the image with blank image data - GL40.glTexImage2D(GL40.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width*2, height*2, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (ByteBuffer) null); - - long maxX = Math.round(Math.sqrt(Blocks.blocks.size())); - int currentX = 0; - int currentY = 0; - for(Block block: Blocks.blocks) { + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); + //Fill the image with blank image data + GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width * 2, height * 2, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (ByteBuffer) null); + long maxX = Math.round(Math.sqrt(Blocks.blocks.size())); + int currentX = 0; + int currentY = 0; + for (Block block : Blocks.blocks) + { //just in case - - if(!block.texture.equals("DONTLOAD")) { + if (!block.texture.equals("DONTLOAD")) + { System.out.println(block.texture); block.updateBlockModelData(); - if(currentX > maxX) { + if (currentX > maxX) + { currentX = 0; currentY--; } - GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, - currentX*width, currentY*height, - width, height, - GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, - block.model.getTexture().getTexture().getImage() - ); + GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, + currentX * width, currentY * height, + width, height, + GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, + block.model.getTexture().getTexture().getImage()); currentX++; } - } return atlasId; } diff --git a/src/main/java/com/github/halotroop/litecraft/screens/ExitGameScreen.java b/src/main/java/com/github/halotroop/litecraft/screens/ExitGameScreen.java index 3dba678..a3ab75c 100644 --- a/src/main/java/com/github/halotroop/litecraft/screens/ExitGameScreen.java +++ b/src/main/java/com/github/halotroop/litecraft/screens/ExitGameScreen.java @@ -13,18 +13,16 @@ public class ExitGameScreen extends Screen private GUIText infoText; // TODO: Add Vulkan text renderer private GingerEngine engine = GingerGL.getInstance(); - + public ExitGameScreen() { - infoText = ((GingerGL)engine).registerText("Saving and exiting...", 3, new Vector2f(Window.getWidth() / 2, Window.getHeight() / 2), 1f, true, "info"); + infoText = ((GingerGL) engine).registerText("Saving and exiting...", 3, new Vector2f(Window.getWidth() / 2, Window.getHeight() / 2), 1f, true, "info"); infoText.setBorderWidth(0.5f); } - + @Override public void render() - { - - } + {} @Override public void tick() diff --git a/src/main/java/com/github/halotroop/litecraft/screens/IngameHUD.java b/src/main/java/com/github/halotroop/litecraft/screens/IngameHUD.java index 877e103..f3d9e60 100644 --- a/src/main/java/com/github/halotroop/litecraft/screens/IngameHUD.java +++ b/src/main/java/com/github/halotroop/litecraft/screens/IngameHUD.java @@ -15,32 +15,30 @@ public class IngameHUD extends Screen // TODO: Add Vulkan text renderer private GingerEngine engine = GingerGL.getInstance(); private Litecraft litecraft = Litecraft.getInstance(); - + public IngameHUD() { - debugText = ((GingerGL)engine).registerText("Loading...", 2, new Vector2f(0, 0), 1f, true, "debugInfo"); + debugText = ((GingerGL) engine).registerText("Loading...", 2, new Vector2f(0, 0), 1f, true, "debugInfo"); debugText.setBorderWidth(0.5f); - positionText = ((GingerGL)engine).registerText("Loading...", 2, new Vector2f(0, -0.1f), 1f, true, "posInfo"); + positionText = ((GingerGL) engine).registerText("Loading...", 2, new Vector2f(0, -0.1f), 1f, true, "posInfo"); positionText.setBorderWidth(0.5f); } - + @Override public void render() - { - - } + {} @Override public void tick() { -// long maxMemory = Runtime.getRuntime().maxMemory(); + // long maxMemory = Runtime.getRuntime().maxMemory(); long totalMemory = Runtime.getRuntime().totalMemory(); long freeMemory = Runtime.getRuntime().freeMemory(); long usedMemory = (totalMemory - freeMemory) / 1024 / 1024; Vector4i dbg = litecraft.dbgStats; Vector3f position = GingerRegister.getInstance().game.data.playerObject.getPosition(); debugText.setText("FPS: " + dbg.x() + " UPS: " + dbg.y() + " TPS: " + dbg.z() + " TWL: " + dbg.w() + " Mem: " + usedMemory + "MB"); - positionText.setText("Position: " + (int) position.x() + ", " + (int) position.y() + ", "+ (int) position.z() ); + positionText.setText("Position: " + (int) position.x() + ", " + (int) position.y() + ", " + (int) position.z()); } @Override diff --git a/src/main/java/com/github/halotroop/litecraft/screens/TitleScreen.java b/src/main/java/com/github/halotroop/litecraft/screens/TitleScreen.java index 57f2c96..6ea01a8 100644 --- a/src/main/java/com/github/halotroop/litecraft/screens/TitleScreen.java +++ b/src/main/java/com/github/halotroop/litecraft/screens/TitleScreen.java @@ -15,9 +15,7 @@ import com.github.hydos.ginger.engine.common.io.Window; import com.github.hydos.ginger.engine.common.screen.Screen; import com.github.hydos.ginger.engine.opengl.api.GingerGL; -/** - * YeS - */ +/** YeS */ public class TitleScreen extends Screen { private GUIText debugText; @@ -29,9 +27,9 @@ public class TitleScreen extends Screen public TitleScreen() { elements = new ArrayList(); - playButton = ((GingerGL)engine).registerButton("/textures/guis/playbutton.png", new Vector2f(0, 0), new Vector2f(0.25f, 0.1f)); + playButton = ((GingerGL) engine).registerButton("/textures/guis/playbutton.png", new Vector2f(0, 0), new Vector2f(0.25f, 0.1f)); playButton.show(Litecraft.getInstance().data.guis); - debugText = ((GingerGL)engine).registerText("Loading...", 2, new Vector2f(0, 0), 1f, true, "debugInfo"); + debugText = ((GingerGL) engine).registerText("Loading...", 2, new Vector2f(0, 0), 1f, true, "debugInfo"); debugText.setBorderWidth(0.5f); } @@ -48,16 +46,15 @@ public class TitleScreen extends Screen if (playButton.isClicked()) { Window.lockMouse(); - if (Litecraft.getInstance().getWorld() == null) { Litecraft.getInstance().setSave(new LitecraftSave("SegregatedOrdinalData", false)); Litecraft.getInstance().changeWorld(Litecraft.getInstance().getSave().getWorldOrCreate(Dimensions.OVERWORLD)); - ((GingerGL)engine).setGingerPlayer(Litecraft.getInstance().getWorld().playerEntity); + ((GingerGL) engine).setGingerPlayer(Litecraft.getInstance().getWorld().playerEntity); } if (Litecraft.getInstance().getWorld() != null) { - ((GingerGL)engine).openScreen(new IngameHUD()); + ((GingerGL) engine).openScreen(new IngameHUD()); this.cleanup(); } //TODO: add world creation gui so it takes u to world creation place diff --git a/src/main/java/com/github/halotroop/litecraft/types/block/Block.java b/src/main/java/com/github/halotroop/litecraft/types/block/Block.java index b380a31..c4425aa 100644 --- a/src/main/java/com/github/halotroop/litecraft/types/block/Block.java +++ b/src/main/java/com/github/halotroop/litecraft/types/block/Block.java @@ -13,7 +13,7 @@ public class Block private boolean fullCube = true; private float caveCarveThreshold = -1f; // cannot carve private final String identifier; - + public Properties(String identifier) { this.identifier = identifier; } @@ -55,8 +55,8 @@ public class Block { this((GLTexturedModel) null, properties); } protected Block(String texture, Properties properties) - { - this(ModelLoader.loadGenericCube("block/"+texture), properties); + { + this(ModelLoader.loadGenericCube("block/" + texture), properties); this.texture = texture; } @@ -67,20 +67,24 @@ public class Block this.fullCube = properties.fullCube; this.identifier = properties.identifier; this.caveCarveThreshold = properties.caveCarveThreshold; - if(model != null) { + if (model != null) + { this.texture = model.getTexture().getTexture().getLocation(); - }else { + } + else + { this.texture = "DONTLOAD"; } IDENTIFIER_TO_BLOCK.put(this.identifier, this); Blocks.blocks.add(this); } - - public void updateBlockModelData() { - System.out.println("Updating block with texture at block/"+texture); - this.model = ModelLoader.loadGenericCube("block/"+texture); + + public void updateBlockModelData() + { + System.out.println("Updating block with texture at block/" + texture); + this.model = ModelLoader.loadGenericCube("block/" + texture); } - + public static final Block getBlock(String identifier) { return IDENTIFIER_TO_BLOCK.get(identifier); } diff --git a/src/main/java/com/github/halotroop/litecraft/types/block/Blocks.java b/src/main/java/com/github/halotroop/litecraft/types/block/Blocks.java index 6a2eff3..5273902 100644 --- a/src/main/java/com/github/halotroop/litecraft/types/block/Blocks.java +++ b/src/main/java/com/github/halotroop/litecraft/types/block/Blocks.java @@ -6,9 +6,7 @@ import com.github.halotroop.litecraft.types.block.Block.Properties; public final class Blocks { - public static ArrayList blocks = new ArrayList(); - public static final Block AIR = new Block(new Properties("air").visible(false).fullCube(false)); public static final Block GRASS = new Block(new Properties("cubes/soil/grass/grass_top.png").caveCarveThreshold(0.04f)); public static final Block DIRT = new Block("cubes/soil/dirt.png", new Properties("dirt").caveCarveThreshold(0.04f)); @@ -18,7 +16,5 @@ public final class Blocks public static final Block GNEISS = new Block("cubes/stone/basic/gneiss.png", new Properties("gneiss").caveCarveThreshold(0.09f)); public static Block init() - { - return AIR; - } + { return AIR; } } diff --git a/src/main/java/com/github/halotroop/litecraft/types/entity/PlayerEntity.java b/src/main/java/com/github/halotroop/litecraft/types/entity/PlayerEntity.java index 1611ef0..97d5799 100644 --- a/src/main/java/com/github/halotroop/litecraft/types/entity/PlayerEntity.java +++ b/src/main/java/com/github/halotroop/litecraft/types/entity/PlayerEntity.java @@ -50,7 +50,8 @@ public class PlayerEntity extends Entity implements WorldGenConstants position.x += Math.sin(ry) * Constants.movementSpeed; break; case UP: - if (this.noWeight) position.y += Constants.movementSpeed; + if (this.noWeight) + position.y += Constants.movementSpeed; else this.jump(); break; case DOWN: @@ -85,11 +86,9 @@ public class PlayerEntity extends Entity implements WorldGenConstants upwardsSpeed += Constants.gravity.y() * Window.getTime(); // TODO: Implement 3D gravity isInAir = false; upwardsSpeed = 0; - int newChunkX = (int) position.x >> POS_SHIFT; int newChunkY = (int) position.y >> POS_SHIFT; int newChunkZ = (int) position.z >> POS_SHIFT; - if (newChunkX != this.chunkX || newChunkY != this.chunkY || newChunkZ != this.chunkZ) { Litecraft.getInstance().getWorld().updateLoadedChunks(newChunkX, newChunkY, newChunkZ); diff --git a/src/main/java/com/github/halotroop/litecraft/util/RelativeDirection.java b/src/main/java/com/github/halotroop/litecraft/util/RelativeDirection.java index 73d3bfa..778e1ea 100644 --- a/src/main/java/com/github/halotroop/litecraft/util/RelativeDirection.java +++ b/src/main/java/com/github/halotroop/litecraft/util/RelativeDirection.java @@ -2,10 +2,10 @@ package com.github.halotroop.litecraft.util; public enum RelativeDirection { - UP, // up up - DOWN, // down down - LEFT, // >left< right - RIGHT, // left >right< - FORWARD,// b + UP, // up up + DOWN, // down down + LEFT, // >left< right + RIGHT, // left >right< + FORWARD, // b BACKWARD,// a } diff --git a/src/main/java/com/github/halotroop/litecraft/util/noise/OctaveSimplexNoise.java b/src/main/java/com/github/halotroop/litecraft/util/noise/OctaveSimplexNoise.java index d58217c..342a8cd 100644 --- a/src/main/java/com/github/halotroop/litecraft/util/noise/OctaveSimplexNoise.java +++ b/src/main/java/com/github/halotroop/litecraft/util/noise/OctaveSimplexNoise.java @@ -9,9 +9,7 @@ public final class OctaveSimplexNoise private double spread, amplitudeLow, amplitudeHigh; public OctaveSimplexNoise(Random rand, int octaves) - { - this(rand, octaves, 1D, 1D, 1D); - } + { this(rand, octaves, 1D, 1D, 1D); } public OctaveSimplexNoise(Random rand, int octaves, double spread, double amplitudeHigh, double amplitudeLow) { diff --git a/src/main/java/com/github/halotroop/litecraft/util/noise/SimplexNoise.java b/src/main/java/com/github/halotroop/litecraft/util/noise/SimplexNoise.java index decd4c4..dd69f2c 100644 --- a/src/main/java/com/github/halotroop/litecraft/util/noise/SimplexNoise.java +++ b/src/main/java/com/github/halotroop/litecraft/util/noise/SimplexNoise.java @@ -1,20 +1,17 @@ package com.github.halotroop.litecraft.util.noise; -/** - * OpenSimplex Noise in Java. +/** OpenSimplex Noise in Java. * (Using implementation by Kurt Spencer) - * * v1.1 (October 5, 2014) * - Added 2D and 4D implementations. * - Proper gradient sets for all dimensions, from a - * dimensionally-generalizable scheme with an actual - * rhyme and reason behind it. + * dimensionally-generalizable scheme with an actual + * rhyme and reason behind it. * - Removed default permutation array in favor of - * default seed. + * default seed. * - Changed seed-based constructor to be independent - * of any particular randomization library, so results - * will be the same when ported to other languages. - */ + * of any particular randomization library, so results + * will be the same when ported to other languages. */ public class SimplexNoise { private static final double STRETCH_CONSTANT_2D = -0.211324865405187; //(1/Math.sqrt(2+1)-1)/2; diff --git a/src/main/java/com/github/halotroop/litecraft/world/Chunk.java b/src/main/java/com/github/halotroop/litecraft/world/Chunk.java index 56e55fe..ac282f7 100644 --- a/src/main/java/com/github/halotroop/litecraft/world/Chunk.java +++ b/src/main/java/com/github/halotroop/litecraft/world/Chunk.java @@ -16,12 +16,10 @@ import tk.valoeghese.sod.*; public class Chunk implements BlockAccess, WorldGenConstants, SODSerializable { - /** - * @param x in-chunk x coordinate. - * @param y in-chunk y coordinate. - * @param z in-chunk z coordinate. - * @return creates a long that represents a coordinate, for use as a key in arrays. - */ + /** @param x in-chunk x coordinate. + * @param y in-chunk y coordinate. + * @param z in-chunk z coordinate. + * @return creates a long that represents a coordinate, for use as a key in arrays. */ public static int index(int x, int y, int z) { return (x & MAX_POS) | ((y & MAX_POS) << POS_SHIFT) | ((z & MAX_POS) << DOUBLE_SHIFT); } @@ -33,10 +31,8 @@ public class Chunk implements BlockAccess, WorldGenConstants, SODSerializable private boolean fullyGenerated = false; public final int dimension; private boolean dirty = true; - /** - * A holder for the rendered blocks in this chunk. This array is *NOT* safe to use for getting BIs at a position! - * It can vary in size from 0 to 512 elements long and must only be read linearly. - */ + /** A holder for the rendered blocks in this chunk. This array is *NOT* safe to use for getting BIs at a position! + * It can vary in size from 0 to 512 elements long and must only be read linearly. */ private BlockInstance[] renderedBlocks = new BlockInstance[CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE]; public Chunk(World world, int chunkX, int chunkY, int chunkZ, int dimension) @@ -83,81 +79,74 @@ public class Chunk implements BlockAccess, WorldGenConstants, SODSerializable for (int x = 0; x < CHUNK_SIZE; x++) for (int y = 0; y < CHUNK_SIZE; y++) for (int z = 0; z < CHUNK_SIZE; z++) - { - BlockInstance block = getBlockInstance(x, y, z); - - // Check for chunk edges to avoid errors when get the neighboring blocks, TODO fix this - if (x == 0 || x == CHUNK_SIZE - 1 || z == 0 || z == CHUNK_SIZE - 1 || y == 0 || y == CHUNK_SIZE - 1) - { - tempList.add(block); - continue; - } - - // Check for air. Yes this is stupid, TODO fix this too - try - { - if (getBlockInstance(x - 1, y, z).getModel() == null || getBlockInstance(x + 1, y, z).getModel() == null || - getBlockInstance(x, y - 1, z).getModel() == null || getBlockInstance(x, y + 1, z).getModel() == null || - getBlockInstance(x, y, z - 1).getModel() == null || getBlockInstance(x, y, z + 1).getModel() == null) - { - tempList.add(block); - } - } catch (NullPointerException e) - { // this seems to be a hotspot for errors - e.printStackTrace(); // so I can add a debug breakpoint on this line - throw e; // e - } - - } + { + BlockInstance block = getBlockInstance(x, y, z); + // Check for chunk edges to avoid errors when get the neighboring blocks, TODO fix this + if (x == 0 || x == CHUNK_SIZE - 1 || z == 0 || z == CHUNK_SIZE - 1 || y == 0 || y == CHUNK_SIZE - 1) + { + tempList.add(block); + continue; + } + // Check for air. Yes this is stupid, TODO fix this too + try + { + if (getBlockInstance(x - 1, y, z).getModel() == null || getBlockInstance(x + 1, y, z).getModel() == null || + getBlockInstance(x, y - 1, z).getModel() == null || getBlockInstance(x, y + 1, z).getModel() == null || + getBlockInstance(x, y, z - 1).getModel() == null || getBlockInstance(x, y, z + 1).getModel() == null) + { tempList.add(block); } + } + catch (NullPointerException e) + { // this seems to be a hotspot for errors + e.printStackTrace(); // so I can add a debug breakpoint on this line + throw e; // e + } + } renderedBlocks = tempList.toArray(BlockInstance[]::new); } - blockRenderer.prepareRender(); blockRenderer.render(renderedBlocks); blockRenderer.shader.stop(); } } - /** - * Change the block in this exact position - * @param x, y, z The coordinate position of block to overwrite - * @param block The block to place there - */ + /** Change the block in this exact position + * + * @param x, y, z The coordinate position of block to overwrite + * @param block The block to place there */ @Override public void setBlock(int x, int y, int z, Block block) { // This section makes sure the blocks don't go out of range - if (x > MAX_POS) x = MAX_POS; + if (x > MAX_POS) + x = MAX_POS; else if (x < 0) x = 0; - if (y > MAX_POS) y = MAX_POS; + if (y > MAX_POS) + y = MAX_POS; else if (y < 0) y = 0; - if (z > MAX_POS) z = MAX_POS; + if (z > MAX_POS) + z = MAX_POS; else if (z < 0) z = 0; // this.blocks[index(x, y, z)] = block; - if (this.shouldRender) this.blockInstances[index(x, y, z)] = - new BlockInstance(block, new Vector3f(this.chunkStartX + x, this.chunkStartY + y, this.chunkStartZ + z)); + if (this.shouldRender) this.blockInstances[index(x, y, z)] = new BlockInstance(block, new Vector3f(this.chunkStartX + x, this.chunkStartY + y, this.chunkStartZ + z)); dirty = true; } - /** - * Set whether or not the chunk should render - */ + /** Set whether or not the chunk should render */ public void setRender(boolean render) { if (render && !this.shouldRender) // if it has been changed to true for (int x = 0; x < CHUNK_SIZE; ++x) for (int y = 0; y < CHUNK_SIZE; ++y) for (int z = 0; z < CHUNK_SIZE; ++z) - { - Block block = this.blocks[index(x, y, z)]; - - this.blockInstances[index(x, y, z)] = new BlockInstance(block, - new Vector3f( - this.chunkStartX + x, - this.chunkStartY + y, - this.chunkStartZ + z)); - } + { + Block block = this.blocks[index(x, y, z)]; + this.blockInstances[index(x, y, z)] = new BlockInstance(block, + new Vector3f( + this.chunkStartX + x, + this.chunkStartY + y, + this.chunkStartZ + z)); + } else if (!render && this.shouldRender) // else if it has been changed to false. // we need to check both variables because there are two cases that make // the if statement fall to here @@ -197,10 +186,10 @@ public class Chunk implements BlockAccess, WorldGenConstants, SODSerializable for (int z = 0; z < CHUNK_SIZE; ++z) // z, y, x order for data saving and loading so we can use incremental pos hashes for (int y = 0; y < CHUNK_SIZE; ++y) for (int x = 0; x < CHUNK_SIZE; ++x) - { - blocks[index] = palette.get(blockData.readInt(index)); - ++index; - } + { + blocks[index] = palette.get(blockData.readInt(index)); + ++index; + } // DataSection properties = data.get("properties"); try @@ -218,7 +207,6 @@ public class Chunk implements BlockAccess, WorldGenConstants, SODSerializable } private static boolean readExceptionNotif = false; - private int nextId; // for saving @Override @@ -234,11 +222,11 @@ public class Chunk implements BlockAccess, WorldGenConstants, SODSerializable for (int z = 0; z < CHUNK_SIZE; ++z) // z, y, x order for data saving and loading so we can use incremental pos hashes for (int y = 0; y < CHUNK_SIZE; ++y) for (int x = 0; x < CHUNK_SIZE; ++x) - { - Block b = blocks[index]; - blockData.writeInt(palette.computeIntIfAbsent(b, nextIdProvider)); - ++index; - } + { + Block b = blocks[index]; + blockData.writeInt(palette.computeIntIfAbsent(b, nextIdProvider)); + ++index; + } // palette.forEach((b, id) -> { diff --git a/src/main/java/com/github/halotroop/litecraft/world/World.java b/src/main/java/com/github/halotroop/litecraft/world/World.java index e0afe89..6af1a16 100644 --- a/src/main/java/com/github/halotroop/litecraft/world/World.java +++ b/src/main/java/com/github/halotroop/litecraft/world/World.java @@ -33,6 +33,7 @@ public class World implements BlockAccess, WorldGenConstants int renderBoundVertical; // dummy block instance for retrieving the default block model private final BlockInstance dummy; + public World(long seed, int renderSize, Dimension dim, LitecraftSave save) { this.threadPool = new ForkJoinPool(4, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true); @@ -44,32 +45,26 @@ public class World implements BlockAccess, WorldGenConstants this.worldModifiers = dim.getWorldModifierArray(); // initialize world modifiers with seed for (WorldModifier modifier : this.worldModifiers) - { - modifier.initialize(seed); - } + { modifier.initialize(seed); } this.genBlockAccess = new GenerationWorld(this); this.save = save; this.dimension = dim.id; this.renderBound = renderSize / 2; this.renderBoundVertical = this.renderBound / 2; if (this.renderBoundVertical < 2) - { - this.renderBoundVertical = 2; - } + { this.renderBoundVertical = 2; } } public int findAir(int x, int z) { int y = SEA_LEVEL; int attemptsRemaining = 255; - while (attemptsRemaining-- > 0) { // DO NOT CHANGE TO y++ if (this.getBlock(x, ++y, z) == Blocks.AIR) return y; } - return -1; // if it fails, returns -1 } @@ -78,7 +73,6 @@ public class World implements BlockAccess, WorldGenConstants int y = this.findAir(0, 0); if (y == -1) y = 300; // yeet - this.spawnPlayer(0, y, -3); } @@ -86,7 +80,6 @@ public class World implements BlockAccess, WorldGenConstants { this.playerEntity = (PlayerEntity) Litecraft.getInstance().player; this.playerEntity.setVisible(false); - // Generate world around player long time = System.currentTimeMillis(); System.out.println("Generating world!"); @@ -142,9 +135,7 @@ public class World implements BlockAccess, WorldGenConstants } void populateChunk(Chunk chunk) - { - this.populateChunk(chunk.chunkX, chunk.chunkY, chunk.chunkZ, chunk.chunkStartX, chunk.chunkStartY, chunk.chunkStartZ); - } + { this.populateChunk(chunk.chunkX, chunk.chunkY, chunk.chunkZ, chunk.chunkStartX, chunk.chunkStartY, chunk.chunkStartZ); } private void populateChunk(int chunkX, int chunkY, int chunkZ, int chunkStartX, int chunkStartY, int chunkStartZ) { @@ -178,7 +169,7 @@ public class World implements BlockAccess, WorldGenConstants public void render(BlockRenderer blockRenderer) { blockRenderer.prepareModel(this.dummy.getModel()); - this.chunks.forEach((pos, c) -> + this.chunks.forEach((pos, c) -> { if (c != null && c.isFullyGenerated()) c.render(blockRenderer); @@ -220,7 +211,6 @@ public class World implements BlockAccess, WorldGenConstants for (int z = chunkZ - this.renderBound; z < chunkZ + this.renderBound; z++) for (int y = chunkY - this.renderBound; y < chunkY + this.renderBound; y++) toKeep.add(this.getChunkToLoad(x, y, z)); - LongList toRemove = new LongArrayList(); // check which loaded chunks are not neccesary chunks.forEach((pos, chunk) -> @@ -230,7 +220,6 @@ public class World implements BlockAccess, WorldGenConstants }); // unload unneccesary chunks from chunk array toRemove.forEach((LongConsumer) this::unloadChunk); - toKeep.forEach(chunk -> { if (!chunk.isFullyGenerated()) diff --git a/src/main/java/com/github/halotroop/litecraft/world/gen/modifier/CavesModifier.java b/src/main/java/com/github/halotroop/litecraft/world/gen/modifier/CavesModifier.java index 83f71d4..674251a 100644 --- a/src/main/java/com/github/halotroop/litecraft/world/gen/modifier/CavesModifier.java +++ b/src/main/java/com/github/halotroop/litecraft/world/gen/modifier/CavesModifier.java @@ -10,6 +10,7 @@ import com.github.halotroop.litecraft.world.gen.WorldGenConstants; public class CavesModifier implements WorldModifier, WorldGenConstants { private OctaveSimplexNoise caveNoise; + @Override public void initialize(long seed) { @@ -21,7 +22,6 @@ public class CavesModifier implements WorldModifier, WorldGenConstants public void modifyWorld(BlockAccess world, Random rand, int chunkStartX, int chunkStartY, int chunkStartZ) { final int subChunks = CHUNK_SIZE >> 2; // in 4x4x4 blocks - for (int subChunkX = 0; subChunkX < subChunks; subChunkX++) { int scOffsetX = subChunkX << 2; // sub chunk offset x @@ -34,7 +34,7 @@ public class CavesModifier implements WorldModifier, WorldGenConstants { int scOffsetY = subChunkY << 2; // sub chunk offset y int scTotalY = scOffsetY + chunkStartY; - double scSampleY = (double) scTotalY * 1.5; // squish caves along y axis a bit + double scSampleY = scTotalY * 1.5; // squish caves along y axis a bit double scUpperYOffset = 4.0 * 1.5; // calculate noise at each corner of the cube [lower|upper][south|north][west|east] double noiseLSW = this.caveNoise.sample(scTotalX, scSampleY, scTotalZ); // base = lower south west @@ -82,9 +82,7 @@ public class CavesModifier implements WorldModifier, WorldGenConstants // if the noise is within the threshold for that block for caves float threshold = world.getBlock(totalX, totalY, totalZ).getCaveCarveThreshold(); if (-threshold < lerpNoise && lerpNoise < threshold) - { - world.setBlock(totalX, totalY, totalZ, Blocks.AIR); - } + { world.setBlock(totalX, totalY, totalZ, Blocks.AIR); } // add progress to the noise lerpNoise += lerpProg; } diff --git a/src/main/java/com/github/halotroop/litecraft/world/gen/modifier/WorldModifier.java b/src/main/java/com/github/halotroop/litecraft/world/gen/modifier/WorldModifier.java index 4ab25af..6f9ecb4 100644 --- a/src/main/java/com/github/halotroop/litecraft/world/gen/modifier/WorldModifier.java +++ b/src/main/java/com/github/halotroop/litecraft/world/gen/modifier/WorldModifier.java @@ -7,5 +7,6 @@ import com.github.halotroop.litecraft.world.BlockAccess; public interface WorldModifier { void modifyWorld(BlockAccess world, Random rand, int chunkStartX, int chunkStartY, int chunkStartZ); + void initialize(long seed); } diff --git a/src/main/java/com/github/hydos/ginger/VulkanExample.java b/src/main/java/com/github/hydos/ginger/VulkanExample.java index c57d92e..4372d4b 100644 --- a/src/main/java/com/github/hydos/ginger/VulkanExample.java +++ b/src/main/java/com/github/hydos/ginger/VulkanExample.java @@ -29,1838 +29,1465 @@ import com.github.hydos.ginger.engine.vulkan.misc.*; import com.github.hydos.ginger.engine.vulkan.misc.VKModelLoader.VKMesh; import com.github.hydos.ginger.engine.vulkan.swapchain.VKSwapchainManager; -public class VulkanExample { - - public static class VulkanDemoGinger2 { - - private static final int UINT32_MAX = 0xFFFFFFFF; - private static final long UINT64_MAX = 0xFFFFFFFFFFFFFFFFL; - - private static final int MAX_FRAMES_IN_FLIGHT = 2; - - private static final Set DEVICE_EXTENSIONS = Stream.of(VK_KHR_SWAPCHAIN_EXTENSION_NAME) - .collect(toSet()); - - - - public static class QueueFamilyIndices { - - // We use Integer to use null as the empty value - public Integer graphicsFamily; - public Integer presentFamily; - - private boolean isComplete() { - return graphicsFamily != null && presentFamily != null; - } - - public int[] unique() { - return IntStream.of(graphicsFamily, presentFamily).distinct().toArray(); - } - } - - public static class SwapChainSupportDetails { - - public VkSurfaceCapabilitiesKHR capabilities; - public VkSurfaceFormatKHR.Buffer formats; - public IntBuffer presentModes; - - } - - private static class UniformBufferObject { - - private static final int SIZEOF = 3 * 16 * Float.BYTES; - - private Matrix4f model; - private Matrix4f view; - private Matrix4f proj; - - public UniformBufferObject() { - model = new Matrix4f(); - view = new Matrix4f(); - proj = new Matrix4f(); - } - } - - public static class Vertex { - - private static final int SIZEOF = (3 + 3 + 2) * Float.BYTES; - private static final int OFFSETOF_POS = 0; - private static final int OFFSETOF_COLOR = 3 * Float.BYTES; - private static final int OFFSETOF_TEXTCOORDS = (3 + 3) * Float.BYTES; - - private Vector3fc pos; - private Vector3fc color; - private Vector2fc texCoords; - - public Vertex(Vector3fc pos, Vector3fc color, Vector2fc texCoords) { - this.pos = pos; - this.color = color; - this.texCoords = texCoords; - } - - public static VkVertexInputBindingDescription.Buffer getBindingDescription() { - - VkVertexInputBindingDescription.Buffer bindingDescription = - VkVertexInputBindingDescription.callocStack(1); - - bindingDescription.binding(0); - bindingDescription.stride(Vertex.SIZEOF); - bindingDescription.inputRate(VK_VERTEX_INPUT_RATE_VERTEX); - - return bindingDescription; - } - - public static VkVertexInputAttributeDescription.Buffer getAttributeDescriptions() { - - VkVertexInputAttributeDescription.Buffer attributeDescriptions = - VkVertexInputAttributeDescription.callocStack(3); - - // Position - VkVertexInputAttributeDescription posDescription = attributeDescriptions.get(0); - posDescription.binding(0); - posDescription.location(0); - posDescription.format(VK_FORMAT_R32G32B32_SFLOAT); - posDescription.offset(OFFSETOF_POS); - - // Color - VkVertexInputAttributeDescription colorDescription = attributeDescriptions.get(1); - colorDescription.binding(0); - colorDescription.location(1); - colorDescription.format(VK_FORMAT_R32G32B32_SFLOAT); - colorDescription.offset(OFFSETOF_COLOR); - - // Texture coordinates - VkVertexInputAttributeDescription texCoordsDescription = attributeDescriptions.get(2); - texCoordsDescription.binding(0); - texCoordsDescription.location(2); - texCoordsDescription.format(VK_FORMAT_R32G32_SFLOAT); - texCoordsDescription.offset(OFFSETOF_TEXTCOORDS); - - return attributeDescriptions.rewind(); - } - - } - - // ======= FIELDS ======= // - - private VkInstance instance; - public static long surface; - - public static VkPhysicalDevice physicalDevice; - public static int msaaSamples = VK_SAMPLE_COUNT_1_BIT; - public static VkDevice device; - - private static VkQueue graphicsQueue; - private VkQueue presentQueue; - - public static long swapChain; - public static List swapChainImages; - public static int swapChainImageFormat; - public static VkExtent2D swapChainExtent; - public static List swapChainImageViews; - public static List swapChainFramebuffers; - - public static long renderPass; - public static long descriptorPool; - public static long descriptorSetLayout; - private static List descriptorSets; - public static long pipelineLayout; - public static long graphicsPipeline; - - public static long commandPool; - - public static long colorImage; - public static long colorImageMemory; - public static long colorImageView; - - public static long depthImage; - public static long depthImageMemory; - public static long depthImageView; - - private int mipLevels; - private long textureImage; - private long textureImageMemory; - private static long textureImageView; - private static long textureSampler; - - private Vertex[] vertices; - public static int[] indices; - private static long vertexBuffer; - private long vertexBufferMemory; - private static long indexBuffer; - private long indexBufferMemory; - - public static List uniformBuffers; - public static List uniformBuffersMemory; - - public static List commandBuffers; - - private List inFlightFrames; - private Map imagesInFlight; - private int currentFrame; - - boolean framebufferResize; - - // ======= METHODS ======= // - - public void run() { - initWindow(); - initVulkan(); - mainLoop(); - cleanup(); - } - - private void initWindow() { - Window.create(1200, 800, "Vulkan Ginger2", 60, RenderAPI.Vulkan); - glfwSetFramebufferSizeCallback(Window.getWindow(), this::framebufferResizeCallback); - } - - private void framebufferResizeCallback(long window, int width, int height) { - // HelloTriangleApplication app = MemoryUtil.memGlobalRefToObject(glfwGetWindowUserPointer(window)); - // app.framebufferResize = true; - framebufferResize = true; - } - - private void initVulkan() { - createInstance(); - createSurface(); - pickPhysicalDevice(); - createLogicalDevice(); - createCommandPool(); - createTextureImage(); - createTextureImageView(); - createTextureSampler(); - loadModel(); - createVertexBuffer(); - createIndexBuffer(); - createDescriptorSetLayout(); - VKSwapchainManager.createSwapChainObjects(); - createSyncObjects(); - } - - private void mainLoop() { - - while(!Window.closed()) { - if(Window.shouldRender()) { - drawFrame(); - } - glfwPollEvents(); - } - - // Wait for the device to complete all operations before release resources - vkDeviceWaitIdle(device); - } - - private void cleanup() { - - VKSwapchainManager.cleanupSwapChain(); - - vkDestroySampler(device, textureSampler, null); - vkDestroyImageView(device, textureImageView, null); - vkDestroyImage(device, textureImage, null); - vkFreeMemory(device, textureImageMemory, null); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, null); - - vkDestroyBuffer(device, indexBuffer, null); - vkFreeMemory(device, indexBufferMemory, null); - - vkDestroyBuffer(device, vertexBuffer, null); - vkFreeMemory(device, vertexBufferMemory, null); - - inFlightFrames.forEach(frame -> { - - vkDestroySemaphore(device, frame.renderFinishedSemaphore(), null); - vkDestroySemaphore(device, frame.imageAvailableSemaphore(), null); - vkDestroyFence(device, frame.fence(), null); - }); - inFlightFrames.clear(); - - vkDestroyCommandPool(device, commandPool, null); - - vkDestroyDevice(device, null); - - vkDestroySurfaceKHR(instance, surface, null); - - vkDestroyInstance(instance, null); - - glfwDestroyWindow(Window.getWindow()); - - glfwTerminate(); - } - - private void createInstance() { - - try(MemoryStack stack = stackPush()) { - - // Use calloc to initialize the structs with 0s. Otherwise, the program can crash due to random values - - VkApplicationInfo appInfo = VkApplicationInfo.callocStack(stack); - - appInfo.sType(VK_STRUCTURE_TYPE_APPLICATION_INFO); - appInfo.pApplicationName(stack.UTF8Safe("Hello Triangle")); - appInfo.applicationVersion(VK_MAKE_VERSION(1, 0, 0)); - appInfo.pEngineName(stack.UTF8Safe("No Engine")); - appInfo.engineVersion(VK_MAKE_VERSION(1, 0, 0)); - appInfo.apiVersion(VK_API_VERSION_1_0); - - VkInstanceCreateInfo createInfo = VkInstanceCreateInfo.callocStack(stack); - - createInfo.sType(VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO); - createInfo.pApplicationInfo(appInfo); - // enabledExtensionCount is implicitly set when you call ppEnabledExtensionNames - createInfo.ppEnabledExtensionNames(getRequiredExtensions()); - - // We need to retrieve the pointer of the created instance - PointerBuffer instancePtr = stack.mallocPointer(1); - - if(vkCreateInstance(createInfo, null, instancePtr) != VK_SUCCESS) { - throw new RuntimeException("Failed to create instance"); - } - - instance = new VkInstance(instancePtr.get(0), createInfo); - } - } - - private void createSurface() { - - try(MemoryStack stack = stackPush()) { - - LongBuffer pSurface = stack.longs(VK_NULL_HANDLE); - - if(glfwCreateWindowSurface(instance, Window.getWindow(), null, pSurface) != VK_SUCCESS) { - throw new RuntimeException("Failed to create window surface"); - } - - surface = pSurface.get(0); - } - } - - private void pickPhysicalDevice() { - - try(MemoryStack stack = stackPush()) { - - IntBuffer deviceCount = stack.ints(0); - - vkEnumeratePhysicalDevices(instance, deviceCount, null); - - if(deviceCount.get(0) == 0) { - throw new RuntimeException("Failed to find GPUs with Vulkan support"); - } - - PointerBuffer ppPhysicalDevices = stack.mallocPointer(deviceCount.get(0)); - - vkEnumeratePhysicalDevices(instance, deviceCount, ppPhysicalDevices); - - VkPhysicalDevice device = null; - - for(int i = 0;i < ppPhysicalDevices.capacity();i++) { - - device = new VkPhysicalDevice(ppPhysicalDevices.get(i), instance); - - if(isDeviceSuitable(device)) { - break; - } - } - - if(device == null) { - throw new RuntimeException("Failed to find a suitable GPU"); - } - - physicalDevice = device; - msaaSamples = getMaxUsableSampleCount(); - } - } - - private void createLogicalDevice() { - - try(MemoryStack stack = stackPush()) { - - QueueFamilyIndices indices = findQueueFamilies(physicalDevice); - - int[] uniqueQueueFamilies = indices.unique(); - - VkDeviceQueueCreateInfo.Buffer queueCreateInfos = VkDeviceQueueCreateInfo.callocStack(uniqueQueueFamilies.length, stack); - - for(int i = 0;i < uniqueQueueFamilies.length;i++) { - VkDeviceQueueCreateInfo queueCreateInfo = queueCreateInfos.get(i); - queueCreateInfo.sType(VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO); - queueCreateInfo.queueFamilyIndex(uniqueQueueFamilies[i]); - queueCreateInfo.pQueuePriorities(stack.floats(1.0f)); - } - - VkPhysicalDeviceFeatures deviceFeatures = VkPhysicalDeviceFeatures.callocStack(stack); - deviceFeatures.samplerAnisotropy(true); - deviceFeatures.sampleRateShading(true); // Enable sample shading feature for the device - - VkDeviceCreateInfo createInfo = VkDeviceCreateInfo.callocStack(stack); - - createInfo.sType(VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO); - createInfo.pQueueCreateInfos(queueCreateInfos); - // queueCreateInfoCount is automatically set - - createInfo.pEnabledFeatures(deviceFeatures); - - createInfo.ppEnabledExtensionNames(asPointerBuffer(DEVICE_EXTENSIONS)); - - PointerBuffer pDevice = stack.pointers(VK_NULL_HANDLE); - - if(vkCreateDevice(physicalDevice, createInfo, null, pDevice) != VK_SUCCESS) { - throw new RuntimeException("Failed to create logical device"); - } - - device = new VkDevice(pDevice.get(0), physicalDevice, createInfo); - - PointerBuffer pQueue = stack.pointers(VK_NULL_HANDLE); - - vkGetDeviceQueue(device, indices.graphicsFamily, 0, pQueue); - graphicsQueue = new VkQueue(pQueue.get(0), device); - - vkGetDeviceQueue(device, indices.presentFamily, 0, pQueue); - presentQueue = new VkQueue(pQueue.get(0), device); - } - } - - public static void createImageViews() { - - swapChainImageViews = new ArrayList<>(swapChainImages.size()); - - for(long swapChainImage : swapChainImages) { - swapChainImageViews.add(createImageView(swapChainImage, swapChainImageFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1)); - } - } - - public static void createRenderPass() { - - try(MemoryStack stack = stackPush()) { - - VkAttachmentDescription.Buffer attachments = VkAttachmentDescription.callocStack(3, stack); - VkAttachmentReference.Buffer attachmentRefs = VkAttachmentReference.callocStack(3, stack); - - // Color attachments - - // MSAA Image - VkAttachmentDescription colorAttachment = attachments.get(0); - colorAttachment.format(swapChainImageFormat); - colorAttachment.samples(msaaSamples); - colorAttachment.loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR); - colorAttachment.storeOp(VK_ATTACHMENT_STORE_OP_STORE); - colorAttachment.stencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE); - colorAttachment.stencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE); - colorAttachment.initialLayout(VK_IMAGE_LAYOUT_UNDEFINED); - colorAttachment.finalLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - VkAttachmentReference colorAttachmentRef = attachmentRefs.get(0); - colorAttachmentRef.attachment(0); - colorAttachmentRef.layout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - // Present Image - VkAttachmentDescription colorAttachmentResolve = attachments.get(2); - colorAttachmentResolve.format(swapChainImageFormat); - colorAttachmentResolve.samples(VK_SAMPLE_COUNT_1_BIT); - colorAttachmentResolve.loadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE); - colorAttachmentResolve.storeOp(VK_ATTACHMENT_STORE_OP_STORE); - colorAttachmentResolve.stencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE); - colorAttachmentResolve.stencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE); - colorAttachmentResolve.initialLayout(VK_IMAGE_LAYOUT_UNDEFINED); - colorAttachmentResolve.finalLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); - - VkAttachmentReference colorAttachmentResolveRef = attachmentRefs.get(2); - colorAttachmentResolveRef.attachment(2); - colorAttachmentResolveRef.layout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - - // Depth-Stencil attachments - - VkAttachmentDescription depthAttachment = attachments.get(1); - depthAttachment.format(findDepthFormat()); - depthAttachment.samples(msaaSamples); - depthAttachment.loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR); - depthAttachment.storeOp(VK_ATTACHMENT_STORE_OP_DONT_CARE); - depthAttachment.stencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE); - depthAttachment.stencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE); - depthAttachment.initialLayout(VK_IMAGE_LAYOUT_UNDEFINED); - depthAttachment.finalLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - - VkAttachmentReference depthAttachmentRef = attachmentRefs.get(1); - depthAttachmentRef.attachment(1); - depthAttachmentRef.layout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - - VkSubpassDescription.Buffer subpass = VkSubpassDescription.callocStack(1, stack); - subpass.pipelineBindPoint(VK_PIPELINE_BIND_POINT_GRAPHICS); - subpass.colorAttachmentCount(1); - subpass.pColorAttachments(VkAttachmentReference.callocStack(1, stack).put(0, colorAttachmentRef)); - subpass.pDepthStencilAttachment(depthAttachmentRef); - subpass.pResolveAttachments(VkAttachmentReference.callocStack(1, stack).put(0, colorAttachmentResolveRef)); - - VkSubpassDependency.Buffer dependency = VkSubpassDependency.callocStack(1, stack); - dependency.srcSubpass(VK_SUBPASS_EXTERNAL); - dependency.dstSubpass(0); - dependency.srcStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); - dependency.srcAccessMask(0); - dependency.dstStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); - dependency.dstAccessMask(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); - - VkRenderPassCreateInfo renderPassInfo = VkRenderPassCreateInfo.callocStack(stack); - renderPassInfo.sType(VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO); - renderPassInfo.pAttachments(attachments); - renderPassInfo.pSubpasses(subpass); - renderPassInfo.pDependencies(dependency); - - LongBuffer pRenderPass = stack.mallocLong(1); - - if(vkCreateRenderPass(device, renderPassInfo, null, pRenderPass) != VK_SUCCESS) { - throw new RuntimeException("Failed to create render pass"); - } - - renderPass = pRenderPass.get(0); - } - } - - private void createDescriptorSetLayout() { - - try(MemoryStack stack = stackPush()) { - - VkDescriptorSetLayoutBinding.Buffer bindings = VkDescriptorSetLayoutBinding.callocStack(2, stack); - - VkDescriptorSetLayoutBinding uboLayoutBinding = bindings.get(0); - uboLayoutBinding.binding(0); - uboLayoutBinding.descriptorCount(1); - uboLayoutBinding.descriptorType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - uboLayoutBinding.pImmutableSamplers(null); - uboLayoutBinding.stageFlags(VK_SHADER_STAGE_VERTEX_BIT); - - VkDescriptorSetLayoutBinding samplerLayoutBinding = bindings.get(1); - samplerLayoutBinding.binding(1); - samplerLayoutBinding.descriptorCount(1); - samplerLayoutBinding.descriptorType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); - samplerLayoutBinding.pImmutableSamplers(null); - samplerLayoutBinding.stageFlags(VK_SHADER_STAGE_FRAGMENT_BIT); - - VkDescriptorSetLayoutCreateInfo layoutInfo = VkDescriptorSetLayoutCreateInfo.callocStack(stack); - layoutInfo.sType(VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO); - layoutInfo.pBindings(bindings); - - LongBuffer pDescriptorSetLayout = stack.mallocLong(1); - - if(vkCreateDescriptorSetLayout(device, layoutInfo, null, pDescriptorSetLayout) != VK_SUCCESS) { - throw new RuntimeException("Failed to create descriptor set layout"); - } - descriptorSetLayout = pDescriptorSetLayout.get(0); - } - } - - public static void createFramebuffers() { - - swapChainFramebuffers = new ArrayList<>(swapChainImageViews.size()); - - try(MemoryStack stack = stackPush()) { - - LongBuffer attachments = stack.longs(colorImageView, depthImageView, VK_NULL_HANDLE); - LongBuffer pFramebuffer = stack.mallocLong(1); - - // Lets allocate the create info struct once and just update the pAttachments field each iteration - VkFramebufferCreateInfo framebufferInfo = VkFramebufferCreateInfo.callocStack(stack); - framebufferInfo.sType(VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO); - framebufferInfo.renderPass(renderPass); - framebufferInfo.width(swapChainExtent.width()); - framebufferInfo.height(swapChainExtent.height()); - framebufferInfo.layers(1); - - for(long imageView : swapChainImageViews) { - - attachments.put(2, imageView); - - framebufferInfo.pAttachments(attachments); - - if(vkCreateFramebuffer(device, framebufferInfo, null, pFramebuffer) != VK_SUCCESS) { - throw new RuntimeException("Failed to create framebuffer"); - } - - swapChainFramebuffers.add(pFramebuffer.get(0)); - } - } - } - - private void createCommandPool() { - - try(MemoryStack stack = stackPush()) { - - QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice); - - VkCommandPoolCreateInfo poolInfo = VkCommandPoolCreateInfo.callocStack(stack); - poolInfo.sType(VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO); - poolInfo.queueFamilyIndex(queueFamilyIndices.graphicsFamily); - - LongBuffer pCommandPool = stack.mallocLong(1); - - if (vkCreateCommandPool(device, poolInfo, null, pCommandPool) != VK_SUCCESS) { - throw new RuntimeException("Failed to create command pool"); - } - - commandPool = pCommandPool.get(0); - } - } - - public static void createColorResources() { - - try(MemoryStack stack = stackPush()) { - - LongBuffer pColorImage = stack.mallocLong(1); - LongBuffer pColorImageMemory = stack.mallocLong(1); - - createImage(swapChainExtent.width(), swapChainExtent.height(), - 1, - msaaSamples, - swapChainImageFormat, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - pColorImage, - pColorImageMemory); - - colorImage = pColorImage.get(0); - colorImageMemory = pColorImageMemory.get(0); - - colorImageView = createImageView(colorImage, swapChainImageFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1); - - transitionImageLayout(colorImage, swapChainImageFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1); - } - } - - public static void createDepthResources() { - - try(MemoryStack stack = stackPush()) { - - int depthFormat = findDepthFormat(); - - LongBuffer pDepthImage = stack.mallocLong(1); - LongBuffer pDepthImageMemory = stack.mallocLong(1); - - createImage( - swapChainExtent.width(), swapChainExtent.height(), - 1, - msaaSamples, - depthFormat, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - pDepthImage, - pDepthImageMemory); - - depthImage = pDepthImage.get(0); - depthImageMemory = pDepthImageMemory.get(0); - - depthImageView = createImageView(depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1); - - // Explicitly transitioning the depth image - transitionImageLayout(depthImage, depthFormat, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - 1); - - } - } - - private static int findSupportedFormat(IntBuffer formatCandidates, int tiling, int features) { - - try(MemoryStack stack = stackPush()) { - - VkFormatProperties props = VkFormatProperties.callocStack(stack); - - for(int i = 0; i < formatCandidates.capacity(); ++i) { - - int format = formatCandidates.get(i); - - vkGetPhysicalDeviceFormatProperties(physicalDevice, format, props); - - if(tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures() & features) == features) { - return format; - } else if(tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures() & features) == features) { - return format; - } - - } - } - - throw new RuntimeException("Failed to find supported format"); - } - - - private static int findDepthFormat() { - return findSupportedFormat( - stackGet().ints(VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT), - VK_IMAGE_TILING_OPTIMAL, - VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); - } - - private static boolean hasStencilComponent(int format) { - return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT; - } - - private double log2(double n) { - return Math.log(n) / Math.log(2); - } - - private void createTextureImage() { - - try(MemoryStack stack = stackPush()) { - - String filename = Paths.get(new URI(ClassLoader.getSystemClassLoader().getResource("textures/chalet.jpg").toExternalForm())).toString(); - - IntBuffer pWidth = stack.mallocInt(1); - IntBuffer pHeight = stack.mallocInt(1); - IntBuffer pChannels = stack.mallocInt(1); - - ByteBuffer pixels = stbi_load(filename, pWidth, pHeight, pChannels, STBI_rgb_alpha); - - long imageSize = pWidth.get(0) * pHeight.get(0) * 4; // pChannels.get(0); - - mipLevels = (int) Math.floor(log2(Math.max(pWidth.get(0), pHeight.get(0)))) + 1; - - if(pixels == null) { - throw new RuntimeException("Failed to load texture image " + filename); - } - - LongBuffer pStagingBuffer = stack.mallocLong(1); - LongBuffer pStagingBufferMemory = stack.mallocLong(1); - createBuffer(imageSize, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - pStagingBuffer, - pStagingBufferMemory); - - - PointerBuffer data = stack.mallocPointer(1); - vkMapMemory(device, pStagingBufferMemory.get(0), 0, imageSize, 0, data); - { - memcpy(data.getByteBuffer(0, (int)imageSize), pixels, imageSize); - } - vkUnmapMemory(device, pStagingBufferMemory.get(0)); - - stbi_image_free(pixels); - - LongBuffer pTextureImage = stack.mallocLong(1); - LongBuffer pTextureImageMemory = stack.mallocLong(1); - createImage(pWidth.get(0), pHeight.get(0), - mipLevels, - VK_SAMPLE_COUNT_1_BIT, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - pTextureImage, - pTextureImageMemory); - - textureImage = pTextureImage.get(0); - textureImageMemory = pTextureImageMemory.get(0); - - transitionImageLayout(textureImage, - VK_FORMAT_R8G8B8A8_SRGB, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - mipLevels); - - copyBufferToImage(pStagingBuffer.get(0), textureImage, pWidth.get(0), pHeight.get(0)); - - // Transitioned to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL while generating mipmaps - generateMipmaps(textureImage, VK_FORMAT_R8G8B8A8_SRGB, pWidth.get(0), pHeight.get(0), mipLevels); - - vkDestroyBuffer(device, pStagingBuffer.get(0), null); - vkFreeMemory(device, pStagingBufferMemory.get(0), null); - - } catch (URISyntaxException e) { - e.printStackTrace(); - } - } - - private void generateMipmaps(long image, int imageFormat, int width, int height, int mipLevels) { - - try(MemoryStack stack = stackPush()) { - - // Check if image format supports linear blitting - VkFormatProperties formatProperties = VkFormatProperties.mallocStack(stack); - vkGetPhysicalDeviceFormatProperties(physicalDevice, imageFormat, formatProperties); - - if((formatProperties.optimalTilingFeatures() & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) == 0) { - throw new RuntimeException("Texture image format does not support linear blitting"); - } - - VkCommandBuffer commandBuffer = beginSingleTimeCommands(); - - VkImageMemoryBarrier.Buffer barrier = VkImageMemoryBarrier.callocStack(1, stack); - barrier.sType(VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER); - barrier.image(image); - barrier.srcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); - barrier.dstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); - barrier.dstAccessMask(VK_QUEUE_FAMILY_IGNORED); - barrier.subresourceRange().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); - barrier.subresourceRange().baseArrayLayer(0); - barrier.subresourceRange().layerCount(1); - barrier.subresourceRange().levelCount(1); - - int mipWidth = width; - int mipHeight = height; - - for(int i = 1;i < mipLevels;i++) { - - barrier.subresourceRange().baseMipLevel(i - 1); - barrier.oldLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - barrier.newLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - barrier.srcAccessMask(VK_ACCESS_TRANSFER_WRITE_BIT); - barrier.dstAccessMask(VK_ACCESS_TRANSFER_READ_BIT); - - vkCmdPipelineBarrier(commandBuffer, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, - null, - null, - barrier); - - VkImageBlit.Buffer blit = VkImageBlit.callocStack(1, stack); - blit.srcOffsets(0).set(0, 0, 0); - blit.srcOffsets(1).set(mipWidth, mipHeight, 1); - blit.srcSubresource().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); - blit.srcSubresource().mipLevel(i - 1); - blit.srcSubresource().baseArrayLayer(0); - blit.srcSubresource().layerCount(1); - blit.dstOffsets(0).set(0, 0, 0); - blit.dstOffsets(1).set(mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1); - blit.dstSubresource().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); - blit.dstSubresource().mipLevel(i); - blit.dstSubresource().baseArrayLayer(0); - blit.dstSubresource().layerCount(1); - - vkCmdBlitImage(commandBuffer, - image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - blit, - VK_FILTER_LINEAR); - - barrier.oldLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - barrier.newLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - barrier.srcAccessMask(VK_ACCESS_TRANSFER_READ_BIT); - barrier.dstAccessMask(VK_ACCESS_SHADER_READ_BIT); - - vkCmdPipelineBarrier(commandBuffer, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, - null, - null, - barrier); - - if(mipWidth > 1) { - mipWidth /= 2; - } - - if(mipHeight > 1) { - mipHeight /= 2; - } - } - - barrier.subresourceRange().baseMipLevel(mipLevels - 1); - barrier.oldLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - barrier.newLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - barrier.srcAccessMask(VK_ACCESS_TRANSFER_WRITE_BIT); - barrier.dstAccessMask(VK_ACCESS_SHADER_READ_BIT); - - vkCmdPipelineBarrier(commandBuffer, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, - null, - null, - barrier); - - endSingleTimeCommands(commandBuffer); - } - } - - private int getMaxUsableSampleCount() { - - try(MemoryStack stack = stackPush()) { - - VkPhysicalDeviceProperties physicalDeviceProperties = VkPhysicalDeviceProperties.mallocStack(stack); - vkGetPhysicalDeviceProperties(physicalDevice, physicalDeviceProperties); - - int sampleCountFlags = physicalDeviceProperties.limits().framebufferColorSampleCounts() - & physicalDeviceProperties.limits().framebufferDepthSampleCounts(); - - if((sampleCountFlags & VK_SAMPLE_COUNT_64_BIT) != 0) { - return VK_SAMPLE_COUNT_64_BIT; - } - if((sampleCountFlags & VK_SAMPLE_COUNT_32_BIT) != 0) { - return VK_SAMPLE_COUNT_32_BIT; - } - if((sampleCountFlags & VK_SAMPLE_COUNT_16_BIT) != 0) { - return VK_SAMPLE_COUNT_16_BIT; - } - if((sampleCountFlags & VK_SAMPLE_COUNT_8_BIT) != 0) { - return VK_SAMPLE_COUNT_8_BIT; - } - if((sampleCountFlags & VK_SAMPLE_COUNT_4_BIT) != 0) { - return VK_SAMPLE_COUNT_4_BIT; - } - if((sampleCountFlags & VK_SAMPLE_COUNT_2_BIT) != 0) { - return VK_SAMPLE_COUNT_2_BIT; - } - - return VK_SAMPLE_COUNT_1_BIT; - } - } - - private void createTextureImageView() { - textureImageView = createImageView(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT, mipLevels); - } - - private void createTextureSampler() { - - try(MemoryStack stack = stackPush()) { - - VkSamplerCreateInfo samplerInfo = VkSamplerCreateInfo.callocStack(stack); - samplerInfo.sType(VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO); - samplerInfo.magFilter(VK_FILTER_LINEAR); - samplerInfo.minFilter(VK_FILTER_LINEAR); - samplerInfo.addressModeU(VK_SAMPLER_ADDRESS_MODE_REPEAT); - samplerInfo.addressModeV(VK_SAMPLER_ADDRESS_MODE_REPEAT); - samplerInfo.addressModeW(VK_SAMPLER_ADDRESS_MODE_REPEAT); - samplerInfo.anisotropyEnable(true); - samplerInfo.maxAnisotropy(16.0f); - samplerInfo.borderColor(VK_BORDER_COLOR_INT_OPAQUE_BLACK); - samplerInfo.unnormalizedCoordinates(false); - samplerInfo.compareEnable(false); - samplerInfo.compareOp(VK_COMPARE_OP_ALWAYS); - samplerInfo.mipmapMode(VK_SAMPLER_MIPMAP_MODE_LINEAR); - samplerInfo.minLod(0); // Optional - samplerInfo.maxLod((float) mipLevels); - samplerInfo.mipLodBias(0); // Optional - - LongBuffer pTextureSampler = stack.mallocLong(1); - - if(vkCreateSampler(device, samplerInfo, null, pTextureSampler) != VK_SUCCESS) { - throw new RuntimeException("Failed to create texture sampler"); - } - - textureSampler = pTextureSampler.get(0); - } - } - - private static long createImageView(long image, int format, int aspectFlags, int mipLevels) { - - try(MemoryStack stack = stackPush()) { - - VkImageViewCreateInfo viewInfo = VkImageViewCreateInfo.callocStack(stack); - viewInfo.sType(VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO); - viewInfo.image(image); - viewInfo.viewType(VK_IMAGE_VIEW_TYPE_2D); - viewInfo.format(format); - viewInfo.subresourceRange().aspectMask(aspectFlags); - viewInfo.subresourceRange().baseMipLevel(0); - viewInfo.subresourceRange().levelCount(mipLevels); - viewInfo.subresourceRange().baseArrayLayer(0); - viewInfo.subresourceRange().layerCount(1); - - LongBuffer pImageView = stack.mallocLong(1); - - if(vkCreateImageView(device, viewInfo, null, pImageView) != VK_SUCCESS) { - throw new RuntimeException("Failed to create texture image view"); - } - - return pImageView.get(0); - } - } - - private static void createImage(int width, int height, int mipLevels, int numSamples, int format, int tiling, int usage, int memProperties, - LongBuffer pTextureImage, LongBuffer pTextureImageMemory) { - - try(MemoryStack stack = stackPush()) { - - VkImageCreateInfo imageInfo = VkImageCreateInfo.callocStack(stack); - imageInfo.sType(VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO); - imageInfo.imageType(VK_IMAGE_TYPE_2D); - imageInfo.extent().width(width); - imageInfo.extent().height(height); - imageInfo.extent().depth(1); - imageInfo.mipLevels(mipLevels); - imageInfo.arrayLayers(1); - imageInfo.format(format); - imageInfo.tiling(tiling); - imageInfo.initialLayout(VK_IMAGE_LAYOUT_UNDEFINED); - imageInfo.usage(usage); - imageInfo.samples(numSamples); - imageInfo.sharingMode(VK_SHARING_MODE_EXCLUSIVE); - - if(vkCreateImage(device, imageInfo, null, pTextureImage) != VK_SUCCESS) { - throw new RuntimeException("Failed to create image"); - } - - VkMemoryRequirements memRequirements = VkMemoryRequirements.mallocStack(stack); - vkGetImageMemoryRequirements(device, pTextureImage.get(0), memRequirements); - - VkMemoryAllocateInfo allocInfo = VkMemoryAllocateInfo.callocStack(stack); - allocInfo.sType(VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO); - allocInfo.allocationSize(memRequirements.size()); - allocInfo.memoryTypeIndex(findMemoryType(memRequirements.memoryTypeBits(), memProperties)); - - if(vkAllocateMemory(device, allocInfo, null, pTextureImageMemory) != VK_SUCCESS) { - throw new RuntimeException("Failed to allocate image memory"); - } - - vkBindImageMemory(device, pTextureImage.get(0), pTextureImageMemory.get(0), 0); - } - } - - private static void transitionImageLayout(long image, int format, int oldLayout, int newLayout, int mipLevels) { - - try(MemoryStack stack = stackPush()) { - - VkImageMemoryBarrier.Buffer barrier = VkImageMemoryBarrier.callocStack(1, stack); - barrier.sType(VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER); - barrier.oldLayout(oldLayout); - barrier.newLayout(newLayout); - barrier.srcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); - barrier.dstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); - barrier.image(image); - - barrier.subresourceRange().baseMipLevel(0); - barrier.subresourceRange().levelCount(mipLevels); - barrier.subresourceRange().baseArrayLayer(0); - barrier.subresourceRange().layerCount(1); - - if(newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { - - barrier.subresourceRange().aspectMask(VK_IMAGE_ASPECT_DEPTH_BIT); - - if(hasStencilComponent(format)) { - barrier.subresourceRange().aspectMask( - barrier.subresourceRange().aspectMask() | VK_IMAGE_ASPECT_STENCIL_BIT); - } - - } else { - barrier.subresourceRange().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); - } - - int sourceStage; - int destinationStage; - - if(oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { - - barrier.srcAccessMask(0); - barrier.dstAccessMask(VK_ACCESS_TRANSFER_WRITE_BIT); - - sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - - } else if(oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - - barrier.srcAccessMask(VK_ACCESS_TRANSFER_WRITE_BIT); - barrier.dstAccessMask(VK_ACCESS_SHADER_READ_BIT); - - sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - - } else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { - - barrier.srcAccessMask(0); - barrier.dstAccessMask(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT); - - sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - destinationStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - - } else if(oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { - - barrier.srcAccessMask(0); - barrier.dstAccessMask(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); - - sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - destinationStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - - } else { - throw new IllegalArgumentException("Unsupported layout transition"); - } - - VkCommandBuffer commandBuffer = beginSingleTimeCommands(); - - vkCmdPipelineBarrier(commandBuffer, - sourceStage, destinationStage, - 0, - null, - null, - barrier); - - endSingleTimeCommands(commandBuffer); - } - } - - private void copyBufferToImage(long buffer, long image, int width, int height) { - - try(MemoryStack stack = stackPush()) { - - VkCommandBuffer commandBuffer = beginSingleTimeCommands(); - - VkBufferImageCopy.Buffer region = VkBufferImageCopy.callocStack(1, stack); - region.bufferOffset(0); - region.bufferRowLength(0); // Tightly packed - region.bufferImageHeight(0); // Tightly packed - region.imageSubresource().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); - region.imageSubresource().mipLevel(0); - region.imageSubresource().baseArrayLayer(0); - region.imageSubresource().layerCount(1); - region.imageOffset().set(0, 0, 0); - region.imageExtent(VkExtent3D.callocStack(stack).set(width, height, 1)); - - vkCmdCopyBufferToImage(commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, region); - - endSingleTimeCommands(commandBuffer); - } - } - - private void memcpy(ByteBuffer dst, ByteBuffer src, long size) { - src.limit((int)size); - dst.put(src); - src.limit(src.capacity()).rewind(); - } - - private void loadModel() { - - File modelFile = new File(ClassLoader.getSystemClassLoader().getResource("models/chalet.obj").getFile()); - - VKMesh model = VKModelLoader.loadModel(modelFile, aiProcess_FlipUVs | aiProcess_DropNormals); - - final int vertexCount = model.positions.size(); - - vertices = new Vertex[vertexCount]; - - final Vector3fc color = new Vector3f(1.0f, 1.0f, 1.0f); - - for(int i = 0;i < vertexCount;i++) { - vertices[i] = new Vertex( - model.positions.get(i), - color, - model.texCoords.get(i)); - } - - indices = new int[model.indices.size()]; - - for(int i = 0;i < indices.length;i++) { - indices[i] = model.indices.get(i); - } - } - - private void createVertexBuffer() { - - try(MemoryStack stack = stackPush()) { - - long bufferSize = Vertex.SIZEOF * vertices.length; - - LongBuffer pBuffer = stack.mallocLong(1); - LongBuffer pBufferMemory = stack.mallocLong(1); - createBuffer(bufferSize, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - pBuffer, - pBufferMemory); - - long stagingBuffer = pBuffer.get(0); - long stagingBufferMemory = pBufferMemory.get(0); - - PointerBuffer data = stack.mallocPointer(1); - - vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, data); - { - memcpy(data.getByteBuffer(0, (int) bufferSize), vertices); - } - vkUnmapMemory(device, stagingBufferMemory); - - createBuffer(bufferSize, - VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - VK_MEMORY_HEAP_DEVICE_LOCAL_BIT, - pBuffer, - pBufferMemory); - - vertexBuffer = pBuffer.get(0); - vertexBufferMemory = pBufferMemory.get(0); - - copyBuffer(stagingBuffer, vertexBuffer, bufferSize); - - vkDestroyBuffer(device, stagingBuffer, null); - vkFreeMemory(device, stagingBufferMemory, null); - } - } - - private void createIndexBuffer() { - - try(MemoryStack stack = stackPush()) { - - long bufferSize = Integer.BYTES * indices.length; - - LongBuffer pBuffer = stack.mallocLong(1); - LongBuffer pBufferMemory = stack.mallocLong(1); - createBuffer(bufferSize, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - pBuffer, - pBufferMemory); - - long stagingBuffer = pBuffer.get(0); - long stagingBufferMemory = pBufferMemory.get(0); - - PointerBuffer data = stack.mallocPointer(1); - - vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, data); - { - memcpy(data.getByteBuffer(0, (int) bufferSize), indices); - } - vkUnmapMemory(device, stagingBufferMemory); - - createBuffer(bufferSize, - VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, - VK_MEMORY_HEAP_DEVICE_LOCAL_BIT, - pBuffer, - pBufferMemory); - - indexBuffer = pBuffer.get(0); - indexBufferMemory = pBufferMemory.get(0); - - copyBuffer(stagingBuffer, indexBuffer, bufferSize); - - vkDestroyBuffer(device, stagingBuffer, null); - vkFreeMemory(device, stagingBufferMemory, null); - } - } - - public static void createUniformBuffers() { - - try(MemoryStack stack = stackPush()) { - - uniformBuffers = new ArrayList<>(swapChainImages.size()); - uniformBuffersMemory = new ArrayList<>(swapChainImages.size()); - - LongBuffer pBuffer = stack.mallocLong(1); - LongBuffer pBufferMemory = stack.mallocLong(1); - - for(int i = 0;i < swapChainImages.size();i++) { - createBuffer(UniformBufferObject.SIZEOF, - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - pBuffer, - pBufferMemory); - - uniformBuffers.add(pBuffer.get(0)); - uniformBuffersMemory.add(pBufferMemory.get(0)); - } - - } - } - - - public static void createDescriptorPool() { - - try(MemoryStack stack = stackPush()) { - - VkDescriptorPoolSize.Buffer poolSizes = VkDescriptorPoolSize.callocStack(2, stack); - - VkDescriptorPoolSize uniformBufferPoolSize = poolSizes.get(0); - uniformBufferPoolSize.type(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - uniformBufferPoolSize.descriptorCount(swapChainImages.size()); - - VkDescriptorPoolSize textureSamplerPoolSize = poolSizes.get(1); - textureSamplerPoolSize.type(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); - textureSamplerPoolSize.descriptorCount(swapChainImages.size()); - - VkDescriptorPoolCreateInfo poolInfo = VkDescriptorPoolCreateInfo.callocStack(stack); - poolInfo.sType(VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO); - poolInfo.pPoolSizes(poolSizes); - poolInfo.maxSets(swapChainImages.size()); - - LongBuffer pDescriptorPool = stack.mallocLong(1); - - if(vkCreateDescriptorPool(device, poolInfo, null, pDescriptorPool) != VK_SUCCESS) { - throw new RuntimeException("Failed to create descriptor pool"); - } - - descriptorPool = pDescriptorPool.get(0); - } - } - - public static void createDescriptorSets() { - - try(MemoryStack stack = stackPush()) { - - LongBuffer layouts = stack.mallocLong(swapChainImages.size()); - for(int i = 0;i < layouts.capacity();i++) { - layouts.put(i, descriptorSetLayout); - } - - VkDescriptorSetAllocateInfo allocInfo = VkDescriptorSetAllocateInfo.callocStack(stack); - allocInfo.sType(VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO); - allocInfo.descriptorPool(descriptorPool); - allocInfo.pSetLayouts(layouts); - - LongBuffer pDescriptorSets = stack.mallocLong(swapChainImages.size()); - - if(vkAllocateDescriptorSets(device, allocInfo, pDescriptorSets) != VK_SUCCESS) { - throw new RuntimeException("Failed to allocate descriptor sets"); - } - - descriptorSets = new ArrayList<>(pDescriptorSets.capacity()); - - VkDescriptorBufferInfo.Buffer bufferInfo = VkDescriptorBufferInfo.callocStack(1, stack); - bufferInfo.offset(0); - bufferInfo.range(UniformBufferObject.SIZEOF); - - VkDescriptorImageInfo.Buffer imageInfo = VkDescriptorImageInfo.callocStack(1, stack); - imageInfo.imageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - imageInfo.imageView(textureImageView); - imageInfo.sampler(textureSampler); - - VkWriteDescriptorSet.Buffer descriptorWrites = VkWriteDescriptorSet.callocStack(2, stack); - - VkWriteDescriptorSet uboDescriptorWrite = descriptorWrites.get(0); - uboDescriptorWrite.sType(VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET); - uboDescriptorWrite.dstBinding(0); - uboDescriptorWrite.dstArrayElement(0); - uboDescriptorWrite.descriptorType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - uboDescriptorWrite.descriptorCount(1); - uboDescriptorWrite.pBufferInfo(bufferInfo); - - VkWriteDescriptorSet samplerDescriptorWrite = descriptorWrites.get(1); - samplerDescriptorWrite.sType(VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET); - samplerDescriptorWrite.dstBinding(1); - samplerDescriptorWrite.dstArrayElement(0); - samplerDescriptorWrite.descriptorType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); - samplerDescriptorWrite.descriptorCount(1); - samplerDescriptorWrite.pImageInfo(imageInfo); - - for(int i = 0;i < pDescriptorSets.capacity();i++) { - - long descriptorSet = pDescriptorSets.get(i); - - bufferInfo.buffer(uniformBuffers.get(i)); - - uboDescriptorWrite.dstSet(descriptorSet); - samplerDescriptorWrite.dstSet(descriptorSet); - - vkUpdateDescriptorSets(device, descriptorWrites, null); - - descriptorSets.add(descriptorSet); - } - } - } - - private static void createBuffer(long size, int usage, int properties, LongBuffer pBuffer, LongBuffer pBufferMemory) { - - try(MemoryStack stack = stackPush()) { - - VkBufferCreateInfo bufferInfo = VkBufferCreateInfo.callocStack(stack); - bufferInfo.sType(VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO); - bufferInfo.size(size); - bufferInfo.usage(usage); - bufferInfo.sharingMode(VK_SHARING_MODE_EXCLUSIVE); - - if(vkCreateBuffer(device, bufferInfo, null, pBuffer) != VK_SUCCESS) { - throw new RuntimeException("Failed to create vertex buffer"); - } - - VkMemoryRequirements memRequirements = VkMemoryRequirements.mallocStack(stack); - vkGetBufferMemoryRequirements(device, pBuffer.get(0), memRequirements); - - VkMemoryAllocateInfo allocInfo = VkMemoryAllocateInfo.callocStack(stack); - allocInfo.sType(VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO); - allocInfo.allocationSize(memRequirements.size()); - allocInfo.memoryTypeIndex(findMemoryType(memRequirements.memoryTypeBits(), properties)); - - if(vkAllocateMemory(device, allocInfo, null, pBufferMemory) != VK_SUCCESS) { - throw new RuntimeException("Failed to allocate vertex buffer memory"); - } - - vkBindBufferMemory(device, pBuffer.get(0), pBufferMemory.get(0), 0); - } - } - - private static VkCommandBuffer beginSingleTimeCommands() { - - try(MemoryStack stack = stackPush()) { - - VkCommandBufferAllocateInfo allocInfo = VkCommandBufferAllocateInfo.callocStack(stack); - allocInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO); - allocInfo.level(VK_COMMAND_BUFFER_LEVEL_PRIMARY); - allocInfo.commandPool(commandPool); - allocInfo.commandBufferCount(1); - - PointerBuffer pCommandBuffer = stack.mallocPointer(1); - vkAllocateCommandBuffers(device, allocInfo, pCommandBuffer); - VkCommandBuffer commandBuffer = new VkCommandBuffer(pCommandBuffer.get(0), device); - - VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.callocStack(stack); - beginInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO); - beginInfo.flags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - - vkBeginCommandBuffer(commandBuffer, beginInfo); - - return commandBuffer; - } - } - - private static void endSingleTimeCommands(VkCommandBuffer commandBuffer) { - - try(MemoryStack stack = stackPush()) { - - vkEndCommandBuffer(commandBuffer); - - VkSubmitInfo.Buffer submitInfo = VkSubmitInfo.callocStack(1, stack); - submitInfo.sType(VK_STRUCTURE_TYPE_SUBMIT_INFO); - submitInfo.pCommandBuffers(stack.pointers(commandBuffer)); - - vkQueueSubmit(graphicsQueue, submitInfo, VK_NULL_HANDLE); - vkQueueWaitIdle(graphicsQueue); - - vkFreeCommandBuffers(device, commandPool, commandBuffer); - } - } - - private void copyBuffer(long srcBuffer, long dstBuffer, long size) { - - try(MemoryStack stack = stackPush()) { - - VkCommandBuffer commandBuffer = beginSingleTimeCommands(); - - VkBufferCopy.Buffer copyRegion = VkBufferCopy.callocStack(1, stack); - copyRegion.size(size); - - vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, copyRegion); - - endSingleTimeCommands(commandBuffer); - } - } - - private void memcpy(ByteBuffer buffer, Vertex[] vertices) { - for(Vertex vertex : vertices) { - buffer.putFloat(vertex.pos.x()); - buffer.putFloat(vertex.pos.y()); - buffer.putFloat(vertex.pos.z()); - - buffer.putFloat(vertex.color.x()); - buffer.putFloat(vertex.color.y()); - buffer.putFloat(vertex.color.z()); - - buffer.putFloat(vertex.texCoords.x()); - buffer.putFloat(vertex.texCoords.y()); - } - } - - private void memcpy(ByteBuffer buffer, int[] indices) { - - for(int index : indices) { - buffer.putInt(index); - } - - buffer.rewind(); - } - - private void memcpy(ByteBuffer buffer, UniformBufferObject ubo) { - - final int mat4Size = 16 * Float.BYTES; - - ubo.model.get(0, buffer); - ubo.view.get(AlignmentUtils.alignas(mat4Size, AlignmentUtils.alignof(ubo.view)), buffer); - ubo.proj.get(AlignmentUtils.alignas(mat4Size * 2, AlignmentUtils.alignof(ubo.view)), buffer); - } - - private static int findMemoryType(int typeFilter, int properties) { - - VkPhysicalDeviceMemoryProperties memProperties = VkPhysicalDeviceMemoryProperties.mallocStack(); - vkGetPhysicalDeviceMemoryProperties(physicalDevice, memProperties); - - for(int i = 0;i < memProperties.memoryTypeCount();i++) { - if((typeFilter & (1 << i)) != 0 && (memProperties.memoryTypes(i).propertyFlags() & properties) == properties) { - return i; - } - } - - throw new RuntimeException("Failed to find suitable memory type"); - } - - public static void createCommandBuffers() { - - final int commandBuffersCount = swapChainFramebuffers.size(); - - commandBuffers = new ArrayList<>(commandBuffersCount); - - try(MemoryStack stack = stackPush()) { - - VkCommandBufferAllocateInfo allocInfo = VkCommandBufferAllocateInfo.callocStack(stack); - allocInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO); - allocInfo.commandPool(commandPool); - allocInfo.level(VK_COMMAND_BUFFER_LEVEL_PRIMARY); - allocInfo.commandBufferCount(commandBuffersCount); - - PointerBuffer pCommandBuffers = stack.mallocPointer(commandBuffersCount); - - if(vkAllocateCommandBuffers(device, allocInfo, pCommandBuffers) != VK_SUCCESS) { - throw new RuntimeException("Failed to allocate command buffers"); - } - - for(int i = 0;i < commandBuffersCount;i++) { - commandBuffers.add(new VkCommandBuffer(pCommandBuffers.get(i), device)); - } - - VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.callocStack(stack); - beginInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO); - - VkRenderPassBeginInfo renderPassInfo = VkRenderPassBeginInfo.callocStack(stack); - renderPassInfo.sType(VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO); - - renderPassInfo.renderPass(renderPass); - - VkRect2D renderArea = VkRect2D.callocStack(stack); - renderArea.offset(VkOffset2D.callocStack(stack).set(0, 0)); - renderArea.extent(swapChainExtent); - renderPassInfo.renderArea(renderArea); - - VkClearValue.Buffer clearValues = VkClearValue.callocStack(2, stack); - clearValues.get(0).color().float32(stack.floats(Window.getColour().x / 255, Window.getColour().y / 255, Window.getColour().z / 255, 1.0f)); //The screens clear colour - clearValues.get(1).depthStencil().set(1.0f, 0); - - renderPassInfo.pClearValues(clearValues); - - for(int i = 0;i < commandBuffersCount;i++) { - - VkCommandBuffer commandBuffer = commandBuffers.get(i); - - if(vkBeginCommandBuffer(commandBuffer, beginInfo) != VK_SUCCESS) { - throw new RuntimeException("Failed to begin recording command buffer"); - } - - renderPassInfo.framebuffer(swapChainFramebuffers.get(i)); - - - vkCmdBeginRenderPass(commandBuffer, renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); - { - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); - - LongBuffer vertexBuffers = stack.longs(vertexBuffer); - LongBuffer offsets = stack.longs(0); - vkCmdBindVertexBuffers(commandBuffer, 0, vertexBuffers, offsets); - - vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 0, VK_INDEX_TYPE_UINT32); - - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - pipelineLayout, - 0, stack.longs( - descriptorSets.get(i) - ), - null); - - vkCmdDrawIndexed(commandBuffer, indices.length, 1, 0, 0, 0); - } - vkCmdEndRenderPass(commandBuffer); - - - if(vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) { - throw new RuntimeException("Failed to record command buffer"); - } - - } - - } - } - - private void createSyncObjects() { - - inFlightFrames = new ArrayList<>(MAX_FRAMES_IN_FLIGHT); - imagesInFlight = new HashMap<>(swapChainImages.size()); - - try(MemoryStack stack = stackPush()) { - - VkSemaphoreCreateInfo semaphoreInfo = VkSemaphoreCreateInfo.callocStack(stack); - semaphoreInfo.sType(VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO); - - VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.callocStack(stack); - fenceInfo.sType(VK_STRUCTURE_TYPE_FENCE_CREATE_INFO); - fenceInfo.flags(VK_FENCE_CREATE_SIGNALED_BIT); - - LongBuffer pImageAvailableSemaphore = stack.mallocLong(1); - LongBuffer pRenderFinishedSemaphore = stack.mallocLong(1); - LongBuffer pFence = stack.mallocLong(1); - - for(int i = 0;i < MAX_FRAMES_IN_FLIGHT;i++) { - - if(vkCreateSemaphore(device, semaphoreInfo, null, pImageAvailableSemaphore) != VK_SUCCESS - || vkCreateSemaphore(device, semaphoreInfo, null, pRenderFinishedSemaphore) != VK_SUCCESS - || vkCreateFence(device, fenceInfo, null, pFence) != VK_SUCCESS) { - - throw new RuntimeException("Failed to create synchronization objects for the frame " + i); - } - - inFlightFrames.add(new Frame(pImageAvailableSemaphore.get(0), pRenderFinishedSemaphore.get(0), pFence.get(0))); - } - - } - } - - private void updateUniformBuffer(int currentImage) { - - try(MemoryStack stack = stackPush()) { - - UniformBufferObject ubo = new UniformBufferObject(); - - ubo.model.rotate((float) (glfwGetTime() * Math.toRadians(90)), 0.0f, 0.0f, 1.0f); - ubo.view.lookAt(2.0f, 2.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); - ubo.proj.perspective((float) Math.toRadians(45), - (float)swapChainExtent.width() / (float)swapChainExtent.height(), 0.1f, 10.0f); - ubo.proj.m11(ubo.proj.m11() * -1); - - PointerBuffer data = stack.mallocPointer(1); - vkMapMemory(device, uniformBuffersMemory.get(currentImage), 0, UniformBufferObject.SIZEOF, 0, data); - { - memcpy(data.getByteBuffer(0, UniformBufferObject.SIZEOF), ubo); - } - vkUnmapMemory(device, uniformBuffersMemory.get(currentImage)); - } - } - - private void drawFrame() { - - try(MemoryStack stack = stackPush()) { - - Frame thisFrame = inFlightFrames.get(currentFrame); - - vkWaitForFences(device, thisFrame.pFence(), true, UINT64_MAX); - - IntBuffer pImageIndex = stack.mallocInt(1); - - int vkResult = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, - thisFrame.imageAvailableSemaphore(), VK_NULL_HANDLE, pImageIndex); - - if(vkResult == VK_ERROR_OUT_OF_DATE_KHR) { - VKSwapchainManager.recreateSwapChain(); - return; - } else if(vkResult != VK_SUCCESS) { - throw new RuntimeException("Cannot get image"); - } - - final int imageIndex = pImageIndex.get(0); - - updateUniformBuffer(imageIndex); - - if(imagesInFlight.containsKey(imageIndex)) { - vkWaitForFences(device, imagesInFlight.get(imageIndex).fence(), true, UINT64_MAX); - } - - imagesInFlight.put(imageIndex, thisFrame); - - VkSubmitInfo submitInfo = VkSubmitInfo.callocStack(stack); - submitInfo.sType(VK_STRUCTURE_TYPE_SUBMIT_INFO); - - submitInfo.waitSemaphoreCount(1); - submitInfo.pWaitSemaphores(thisFrame.pImageAvailableSemaphore()); - submitInfo.pWaitDstStageMask(stack.ints(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)); - - submitInfo.pSignalSemaphores(thisFrame.pRenderFinishedSemaphore()); - - submitInfo.pCommandBuffers(stack.pointers(commandBuffers.get(imageIndex))); - - vkResetFences(device, thisFrame.pFence()); - - if((vkResult = vkQueueSubmit(graphicsQueue, submitInfo, thisFrame.fence())) != VK_SUCCESS) { - vkResetFences(device, thisFrame.pFence()); - throw new RuntimeException("Failed to submit draw command buffer: " + vkResult); - } - - VkPresentInfoKHR presentInfo = VkPresentInfoKHR.callocStack(stack); - presentInfo.sType(VK_STRUCTURE_TYPE_PRESENT_INFO_KHR); - - presentInfo.pWaitSemaphores(thisFrame.pRenderFinishedSemaphore()); - - presentInfo.swapchainCount(1); - presentInfo.pSwapchains(stack.longs(swapChain)); - - presentInfo.pImageIndices(pImageIndex); - - vkResult = vkQueuePresentKHR(presentQueue, presentInfo); - - if(vkResult == VK_ERROR_OUT_OF_DATE_KHR || vkResult == VK_SUBOPTIMAL_KHR || framebufferResize) { - framebufferResize = false; - VKSwapchainManager.recreateSwapChain(); - } else if(vkResult != VK_SUCCESS) { - throw new RuntimeException("Failed to present swap chain image"); - } - - currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; - } - } - - public static VkSurfaceFormatKHR chooseSwapSurfaceFormat(VkSurfaceFormatKHR.Buffer availableFormats) { - return availableFormats.stream() - .filter(availableFormat -> availableFormat.format() == VK_FORMAT_B8G8R8_SRGB) - .filter(availableFormat -> availableFormat.colorSpace() == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) - .findAny() - .orElse(availableFormats.get(0)); - } - - public static int chooseSwapPresentMode(IntBuffer availablePresentModes) { - - for(int i = 0;i < availablePresentModes.capacity();i++) { - if(availablePresentModes.get(i) == VK_PRESENT_MODE_MAILBOX_KHR) { - return availablePresentModes.get(i); - } - } - - return VK_PRESENT_MODE_FIFO_KHR; - } - - public static VkExtent2D chooseSwapExtent(VkSurfaceCapabilitiesKHR capabilities) { - - if(capabilities.currentExtent().width() != UINT32_MAX) { - return capabilities.currentExtent(); - } - - IntBuffer width = stackGet().ints(0); - IntBuffer height = stackGet().ints(0); - - glfwGetFramebufferSize(Window.getWindow(), width, height); - - VkExtent2D actualExtent = VkExtent2D.mallocStack().set(width.get(0), height.get(0)); - - VkExtent2D minExtent = capabilities.minImageExtent(); - VkExtent2D maxExtent = capabilities.maxImageExtent(); - - actualExtent.width(clamp(minExtent.width(), maxExtent.width(), actualExtent.width())); - actualExtent.height(clamp(minExtent.height(), maxExtent.height(), actualExtent.height())); - - return actualExtent; - } - - private static int clamp(int min, int max, int value) { - return Math.max(min, Math.min(max, value)); - } - - private boolean isDeviceSuitable(VkPhysicalDevice device) { - - QueueFamilyIndices indices = findQueueFamilies(device); - - boolean extensionsSupported = checkDeviceExtensionSupport(device); - boolean swapChainAdequate = false; - boolean anisotropySupported = false; - - if(extensionsSupported) { - try(MemoryStack stack = stackPush()) { - SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device, stack); - swapChainAdequate = swapChainSupport.formats.hasRemaining() && swapChainSupport.presentModes.hasRemaining(); - VkPhysicalDeviceFeatures supportedFeatures = VkPhysicalDeviceFeatures.mallocStack(stack); - vkGetPhysicalDeviceFeatures(device, supportedFeatures); - anisotropySupported = supportedFeatures.samplerAnisotropy(); - } - } - - return indices.isComplete() && extensionsSupported && swapChainAdequate && anisotropySupported; - } - - private boolean checkDeviceExtensionSupport(VkPhysicalDevice device) { - - try(MemoryStack stack = stackPush()) { - - IntBuffer extensionCount = stack.ints(0); - - vkEnumerateDeviceExtensionProperties(device, (String)null, extensionCount, null); - - VkExtensionProperties.Buffer availableExtensions = VkExtensionProperties.mallocStack(extensionCount.get(0), stack); - - return availableExtensions.stream().collect(toSet()).containsAll(DEVICE_EXTENSIONS); - } - } - - public static SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device, MemoryStack stack) { - - SwapChainSupportDetails details = new SwapChainSupportDetails(); - - details.capabilities = VkSurfaceCapabilitiesKHR.mallocStack(stack); - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, details.capabilities); - - IntBuffer count = stack.ints(0); - - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, count, null); - - if(count.get(0) != 0) { - details.formats = VkSurfaceFormatKHR.mallocStack(count.get(0), stack); - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, count, details.formats); - } - - vkGetPhysicalDeviceSurfacePresentModesKHR(device,surface, count, null); - - if(count.get(0) != 0) { - details.presentModes = stack.mallocInt(count.get(0)); - vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, count, details.presentModes); - } - - return details; - } - - public static QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) { - - QueueFamilyIndices indices = new QueueFamilyIndices(); - - try(MemoryStack stack = stackPush()) { - - IntBuffer queueFamilyCount = stack.ints(0); - - vkGetPhysicalDeviceQueueFamilyProperties(device, queueFamilyCount, null); - - VkQueueFamilyProperties.Buffer queueFamilies = VkQueueFamilyProperties.mallocStack(queueFamilyCount.get(0), stack); - - vkGetPhysicalDeviceQueueFamilyProperties(device, queueFamilyCount, queueFamilies); - - IntBuffer presentSupport = stack.ints(VK_FALSE); - - for(int i = 0;i < queueFamilies.capacity() || !indices.isComplete();i++) { - - if((queueFamilies.get(i).queueFlags() & VK_QUEUE_GRAPHICS_BIT) != 0) { - indices.graphicsFamily = i; - } - - vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, presentSupport); - - if(presentSupport.get(0) == VK_TRUE) { - indices.presentFamily = i; - } - } - - return indices; - } - } - - private PointerBuffer asPointerBuffer(Collection collection) { - - MemoryStack stack = stackGet(); - - PointerBuffer buffer = stack.mallocPointer(collection.size()); - - collection.stream() - .map(stack::UTF8) - .forEach(buffer::put); - - return buffer.rewind(); - } - - public static PointerBuffer asPointerBuffer(List list) { - - MemoryStack stack = stackGet(); - - PointerBuffer buffer = stack.mallocPointer(list.size()); - - list.forEach(buffer::put); - - return buffer.rewind(); - } - - private PointerBuffer getRequiredExtensions() { - - PointerBuffer glfwExtensions = glfwGetRequiredInstanceExtensions(); - - return glfwExtensions; - } - - } - - public static void main(String[] args) { - - VulkanDemoGinger2 app = new VulkanDemoGinger2(); - - app.run(); - } - +public class VulkanExample +{ + public static class VulkanDemoGinger2 + { + private static final int UINT32_MAX = 0xFFFFFFFF; + private static final long UINT64_MAX = 0xFFFFFFFFFFFFFFFFL; + private static final int MAX_FRAMES_IN_FLIGHT = 2; + private static final Set DEVICE_EXTENSIONS = Stream.of(VK_KHR_SWAPCHAIN_EXTENSION_NAME) + .collect(toSet()); + + public static class QueueFamilyIndices + { + // We use Integer to use null as the empty value + public Integer graphicsFamily; + public Integer presentFamily; + + private boolean isComplete() + { return graphicsFamily != null && presentFamily != null; } + + public int[] unique() + { return IntStream.of(graphicsFamily, presentFamily).distinct().toArray(); } + } + + public static class SwapChainSupportDetails + { + public VkSurfaceCapabilitiesKHR capabilities; + public VkSurfaceFormatKHR.Buffer formats; + public IntBuffer presentModes; + } + + private static class UniformBufferObject + { + private static final int SIZEOF = 3 * 16 * Float.BYTES; + private Matrix4f model; + private Matrix4f view; + private Matrix4f proj; + + public UniformBufferObject() + { + model = new Matrix4f(); + view = new Matrix4f(); + proj = new Matrix4f(); + } + } + + public static class Vertex + { + private static final int SIZEOF = (3 + 3 + 2) * Float.BYTES; + private static final int OFFSETOF_POS = 0; + private static final int OFFSETOF_COLOR = 3 * Float.BYTES; + private static final int OFFSETOF_TEXTCOORDS = (3 + 3) * Float.BYTES; + private Vector3fc pos; + private Vector3fc color; + private Vector2fc texCoords; + + public Vertex(Vector3fc pos, Vector3fc color, Vector2fc texCoords) + { + this.pos = pos; + this.color = color; + this.texCoords = texCoords; + } + + public static VkVertexInputBindingDescription.Buffer getBindingDescription() + { + VkVertexInputBindingDescription.Buffer bindingDescription = VkVertexInputBindingDescription.callocStack(1); + bindingDescription.binding(0); + bindingDescription.stride(Vertex.SIZEOF); + bindingDescription.inputRate(VK_VERTEX_INPUT_RATE_VERTEX); + return bindingDescription; + } + + public static VkVertexInputAttributeDescription.Buffer getAttributeDescriptions() + { + VkVertexInputAttributeDescription.Buffer attributeDescriptions = VkVertexInputAttributeDescription.callocStack(3); + // Position + VkVertexInputAttributeDescription posDescription = attributeDescriptions.get(0); + posDescription.binding(0); + posDescription.location(0); + posDescription.format(VK_FORMAT_R32G32B32_SFLOAT); + posDescription.offset(OFFSETOF_POS); + // Color + VkVertexInputAttributeDescription colorDescription = attributeDescriptions.get(1); + colorDescription.binding(0); + colorDescription.location(1); + colorDescription.format(VK_FORMAT_R32G32B32_SFLOAT); + colorDescription.offset(OFFSETOF_COLOR); + // Texture coordinates + VkVertexInputAttributeDescription texCoordsDescription = attributeDescriptions.get(2); + texCoordsDescription.binding(0); + texCoordsDescription.location(2); + texCoordsDescription.format(VK_FORMAT_R32G32_SFLOAT); + texCoordsDescription.offset(OFFSETOF_TEXTCOORDS); + return attributeDescriptions.rewind(); + } + } + // ======= FIELDS ======= // + + private VkInstance instance; + public static long surface; + public static VkPhysicalDevice physicalDevice; + public static int msaaSamples = VK_SAMPLE_COUNT_1_BIT; + public static VkDevice device; + private static VkQueue graphicsQueue; + private VkQueue presentQueue; + public static long swapChain; + public static List swapChainImages; + public static int swapChainImageFormat; + public static VkExtent2D swapChainExtent; + public static List swapChainImageViews; + public static List swapChainFramebuffers; + public static long renderPass; + public static long descriptorPool; + public static long descriptorSetLayout; + private static List descriptorSets; + public static long pipelineLayout; + public static long graphicsPipeline; + public static long commandPool; + public static long colorImage; + public static long colorImageMemory; + public static long colorImageView; + public static long depthImage; + public static long depthImageMemory; + public static long depthImageView; + private int mipLevels; + private long textureImage; + private long textureImageMemory; + private static long textureImageView; + private static long textureSampler; + private Vertex[] vertices; + public static int[] indices; + private static long vertexBuffer; + private long vertexBufferMemory; + private static long indexBuffer; + private long indexBufferMemory; + public static List uniformBuffers; + public static List uniformBuffersMemory; + public static List commandBuffers; + private List inFlightFrames; + private Map imagesInFlight; + private int currentFrame; + boolean framebufferResize; + // ======= METHODS ======= // + + public void run() + { + initWindow(); + initVulkan(); + mainLoop(); + cleanup(); + } + + private void initWindow() + { + Window.create(1200, 800, "Vulkan Ginger2", 60, RenderAPI.Vulkan); + glfwSetFramebufferSizeCallback(Window.getWindow(), this::framebufferResizeCallback); + } + + private void framebufferResizeCallback(long window, int width, int height) + { + // HelloTriangleApplication app = MemoryUtil.memGlobalRefToObject(glfwGetWindowUserPointer(window)); + // app.framebufferResize = true; + framebufferResize = true; + } + + private void initVulkan() + { + createInstance(); + createSurface(); + pickPhysicalDevice(); + createLogicalDevice(); + createCommandPool(); + createTextureImage(); + createTextureImageView(); + createTextureSampler(); + loadModel(); + createVertexBuffer(); + createIndexBuffer(); + createDescriptorSetLayout(); + VKSwapchainManager.createSwapChainObjects(); + createSyncObjects(); + } + + private void mainLoop() + { + while (!Window.closed()) + { + if (Window.shouldRender()) + { drawFrame(); } + glfwPollEvents(); + } + // Wait for the device to complete all operations before release resources + vkDeviceWaitIdle(device); + } + + private void cleanup() + { + VKSwapchainManager.cleanupSwapChain(); + vkDestroySampler(device, textureSampler, null); + vkDestroyImageView(device, textureImageView, null); + vkDestroyImage(device, textureImage, null); + vkFreeMemory(device, textureImageMemory, null); + vkDestroyDescriptorSetLayout(device, descriptorSetLayout, null); + vkDestroyBuffer(device, indexBuffer, null); + vkFreeMemory(device, indexBufferMemory, null); + vkDestroyBuffer(device, vertexBuffer, null); + vkFreeMemory(device, vertexBufferMemory, null); + inFlightFrames.forEach(frame -> + { + vkDestroySemaphore(device, frame.renderFinishedSemaphore(), null); + vkDestroySemaphore(device, frame.imageAvailableSemaphore(), null); + vkDestroyFence(device, frame.fence(), null); + }); + inFlightFrames.clear(); + vkDestroyCommandPool(device, commandPool, null); + vkDestroyDevice(device, null); + vkDestroySurfaceKHR(instance, surface, null); + vkDestroyInstance(instance, null); + glfwDestroyWindow(Window.getWindow()); + glfwTerminate(); + } + + private void createInstance() + { + try (MemoryStack stack = stackPush()) + { + // Use calloc to initialize the structs with 0s. Otherwise, the program can crash due to random values + VkApplicationInfo appInfo = VkApplicationInfo.callocStack(stack); + appInfo.sType(VK_STRUCTURE_TYPE_APPLICATION_INFO); + appInfo.pApplicationName(stack.UTF8Safe("Hello Triangle")); + appInfo.applicationVersion(VK_MAKE_VERSION(1, 0, 0)); + appInfo.pEngineName(stack.UTF8Safe("No Engine")); + appInfo.engineVersion(VK_MAKE_VERSION(1, 0, 0)); + appInfo.apiVersion(VK_API_VERSION_1_0); + VkInstanceCreateInfo createInfo = VkInstanceCreateInfo.callocStack(stack); + createInfo.sType(VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO); + createInfo.pApplicationInfo(appInfo); + // enabledExtensionCount is implicitly set when you call ppEnabledExtensionNames + createInfo.ppEnabledExtensionNames(getRequiredExtensions()); + // We need to retrieve the pointer of the created instance + PointerBuffer instancePtr = stack.mallocPointer(1); + if (vkCreateInstance(createInfo, null, instancePtr) != VK_SUCCESS) + { throw new RuntimeException("Failed to create instance"); } + instance = new VkInstance(instancePtr.get(0), createInfo); + } + } + + private void createSurface() + { + try (MemoryStack stack = stackPush()) + { + LongBuffer pSurface = stack.longs(VK_NULL_HANDLE); + if (glfwCreateWindowSurface(instance, Window.getWindow(), null, pSurface) != VK_SUCCESS) + { throw new RuntimeException("Failed to create window surface"); } + surface = pSurface.get(0); + } + } + + private void pickPhysicalDevice() + { + try (MemoryStack stack = stackPush()) + { + IntBuffer deviceCount = stack.ints(0); + vkEnumeratePhysicalDevices(instance, deviceCount, null); + if (deviceCount.get(0) == 0) + { throw new RuntimeException("Failed to find GPUs with Vulkan support"); } + PointerBuffer ppPhysicalDevices = stack.mallocPointer(deviceCount.get(0)); + vkEnumeratePhysicalDevices(instance, deviceCount, ppPhysicalDevices); + VkPhysicalDevice device = null; + for (int i = 0; i < ppPhysicalDevices.capacity(); i++) + { + device = new VkPhysicalDevice(ppPhysicalDevices.get(i), instance); + if (isDeviceSuitable(device)) + { break; } + } + if (device == null) + { throw new RuntimeException("Failed to find a suitable GPU"); } + physicalDevice = device; + msaaSamples = getMaxUsableSampleCount(); + } + } + + private void createLogicalDevice() + { + try (MemoryStack stack = stackPush()) + { + QueueFamilyIndices indices = findQueueFamilies(physicalDevice); + int[] uniqueQueueFamilies = indices.unique(); + VkDeviceQueueCreateInfo.Buffer queueCreateInfos = VkDeviceQueueCreateInfo.callocStack(uniqueQueueFamilies.length, stack); + for (int i = 0; i < uniqueQueueFamilies.length; i++) + { + VkDeviceQueueCreateInfo queueCreateInfo = queueCreateInfos.get(i); + queueCreateInfo.sType(VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO); + queueCreateInfo.queueFamilyIndex(uniqueQueueFamilies[i]); + queueCreateInfo.pQueuePriorities(stack.floats(1.0f)); + } + VkPhysicalDeviceFeatures deviceFeatures = VkPhysicalDeviceFeatures.callocStack(stack); + deviceFeatures.samplerAnisotropy(true); + deviceFeatures.sampleRateShading(true); // Enable sample shading feature for the device + VkDeviceCreateInfo createInfo = VkDeviceCreateInfo.callocStack(stack); + createInfo.sType(VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO); + createInfo.pQueueCreateInfos(queueCreateInfos); + // queueCreateInfoCount is automatically set + createInfo.pEnabledFeatures(deviceFeatures); + createInfo.ppEnabledExtensionNames(asPointerBuffer(DEVICE_EXTENSIONS)); + PointerBuffer pDevice = stack.pointers(VK_NULL_HANDLE); + if (vkCreateDevice(physicalDevice, createInfo, null, pDevice) != VK_SUCCESS) + { throw new RuntimeException("Failed to create logical device"); } + device = new VkDevice(pDevice.get(0), physicalDevice, createInfo); + PointerBuffer pQueue = stack.pointers(VK_NULL_HANDLE); + vkGetDeviceQueue(device, indices.graphicsFamily, 0, pQueue); + graphicsQueue = new VkQueue(pQueue.get(0), device); + vkGetDeviceQueue(device, indices.presentFamily, 0, pQueue); + presentQueue = new VkQueue(pQueue.get(0), device); + } + } + + public static void createImageViews() + { + swapChainImageViews = new ArrayList<>(swapChainImages.size()); + for (long swapChainImage : swapChainImages) + { swapChainImageViews.add(createImageView(swapChainImage, swapChainImageFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1)); } + } + + public static void createRenderPass() + { + try (MemoryStack stack = stackPush()) + { + VkAttachmentDescription.Buffer attachments = VkAttachmentDescription.callocStack(3, stack); + VkAttachmentReference.Buffer attachmentRefs = VkAttachmentReference.callocStack(3, stack); + // Color attachments + // MSAA Image + VkAttachmentDescription colorAttachment = attachments.get(0); + colorAttachment.format(swapChainImageFormat); + colorAttachment.samples(msaaSamples); + colorAttachment.loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR); + colorAttachment.storeOp(VK_ATTACHMENT_STORE_OP_STORE); + colorAttachment.stencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE); + colorAttachment.stencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE); + colorAttachment.initialLayout(VK_IMAGE_LAYOUT_UNDEFINED); + colorAttachment.finalLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + VkAttachmentReference colorAttachmentRef = attachmentRefs.get(0); + colorAttachmentRef.attachment(0); + colorAttachmentRef.layout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + // Present Image + VkAttachmentDescription colorAttachmentResolve = attachments.get(2); + colorAttachmentResolve.format(swapChainImageFormat); + colorAttachmentResolve.samples(VK_SAMPLE_COUNT_1_BIT); + colorAttachmentResolve.loadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE); + colorAttachmentResolve.storeOp(VK_ATTACHMENT_STORE_OP_STORE); + colorAttachmentResolve.stencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE); + colorAttachmentResolve.stencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE); + colorAttachmentResolve.initialLayout(VK_IMAGE_LAYOUT_UNDEFINED); + colorAttachmentResolve.finalLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + VkAttachmentReference colorAttachmentResolveRef = attachmentRefs.get(2); + colorAttachmentResolveRef.attachment(2); + colorAttachmentResolveRef.layout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + // Depth-Stencil attachments + VkAttachmentDescription depthAttachment = attachments.get(1); + depthAttachment.format(findDepthFormat()); + depthAttachment.samples(msaaSamples); + depthAttachment.loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR); + depthAttachment.storeOp(VK_ATTACHMENT_STORE_OP_DONT_CARE); + depthAttachment.stencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE); + depthAttachment.stencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE); + depthAttachment.initialLayout(VK_IMAGE_LAYOUT_UNDEFINED); + depthAttachment.finalLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + VkAttachmentReference depthAttachmentRef = attachmentRefs.get(1); + depthAttachmentRef.attachment(1); + depthAttachmentRef.layout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + VkSubpassDescription.Buffer subpass = VkSubpassDescription.callocStack(1, stack); + subpass.pipelineBindPoint(VK_PIPELINE_BIND_POINT_GRAPHICS); + subpass.colorAttachmentCount(1); + subpass.pColorAttachments(VkAttachmentReference.callocStack(1, stack).put(0, colorAttachmentRef)); + subpass.pDepthStencilAttachment(depthAttachmentRef); + subpass.pResolveAttachments(VkAttachmentReference.callocStack(1, stack).put(0, colorAttachmentResolveRef)); + VkSubpassDependency.Buffer dependency = VkSubpassDependency.callocStack(1, stack); + dependency.srcSubpass(VK_SUBPASS_EXTERNAL); + dependency.dstSubpass(0); + dependency.srcStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + dependency.srcAccessMask(0); + dependency.dstStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + dependency.dstAccessMask(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); + VkRenderPassCreateInfo renderPassInfo = VkRenderPassCreateInfo.callocStack(stack); + renderPassInfo.sType(VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO); + renderPassInfo.pAttachments(attachments); + renderPassInfo.pSubpasses(subpass); + renderPassInfo.pDependencies(dependency); + LongBuffer pRenderPass = stack.mallocLong(1); + if (vkCreateRenderPass(device, renderPassInfo, null, pRenderPass) != VK_SUCCESS) + { throw new RuntimeException("Failed to create render pass"); } + renderPass = pRenderPass.get(0); + } + } + + private void createDescriptorSetLayout() + { + try (MemoryStack stack = stackPush()) + { + VkDescriptorSetLayoutBinding.Buffer bindings = VkDescriptorSetLayoutBinding.callocStack(2, stack); + VkDescriptorSetLayoutBinding uboLayoutBinding = bindings.get(0); + uboLayoutBinding.binding(0); + uboLayoutBinding.descriptorCount(1); + uboLayoutBinding.descriptorType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + uboLayoutBinding.pImmutableSamplers(null); + uboLayoutBinding.stageFlags(VK_SHADER_STAGE_VERTEX_BIT); + VkDescriptorSetLayoutBinding samplerLayoutBinding = bindings.get(1); + samplerLayoutBinding.binding(1); + samplerLayoutBinding.descriptorCount(1); + samplerLayoutBinding.descriptorType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + samplerLayoutBinding.pImmutableSamplers(null); + samplerLayoutBinding.stageFlags(VK_SHADER_STAGE_FRAGMENT_BIT); + VkDescriptorSetLayoutCreateInfo layoutInfo = VkDescriptorSetLayoutCreateInfo.callocStack(stack); + layoutInfo.sType(VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO); + layoutInfo.pBindings(bindings); + LongBuffer pDescriptorSetLayout = stack.mallocLong(1); + if (vkCreateDescriptorSetLayout(device, layoutInfo, null, pDescriptorSetLayout) != VK_SUCCESS) + { throw new RuntimeException("Failed to create descriptor set layout"); } + descriptorSetLayout = pDescriptorSetLayout.get(0); + } + } + + public static void createFramebuffers() + { + swapChainFramebuffers = new ArrayList<>(swapChainImageViews.size()); + try (MemoryStack stack = stackPush()) + { + LongBuffer attachments = stack.longs(colorImageView, depthImageView, VK_NULL_HANDLE); + LongBuffer pFramebuffer = stack.mallocLong(1); + // Lets allocate the create info struct once and just update the pAttachments field each iteration + VkFramebufferCreateInfo framebufferInfo = VkFramebufferCreateInfo.callocStack(stack); + framebufferInfo.sType(VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO); + framebufferInfo.renderPass(renderPass); + framebufferInfo.width(swapChainExtent.width()); + framebufferInfo.height(swapChainExtent.height()); + framebufferInfo.layers(1); + for (long imageView : swapChainImageViews) + { + attachments.put(2, imageView); + framebufferInfo.pAttachments(attachments); + if (vkCreateFramebuffer(device, framebufferInfo, null, pFramebuffer) != VK_SUCCESS) + { throw new RuntimeException("Failed to create framebuffer"); } + swapChainFramebuffers.add(pFramebuffer.get(0)); + } + } + } + + private void createCommandPool() + { + try (MemoryStack stack = stackPush()) + { + QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice); + VkCommandPoolCreateInfo poolInfo = VkCommandPoolCreateInfo.callocStack(stack); + poolInfo.sType(VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO); + poolInfo.queueFamilyIndex(queueFamilyIndices.graphicsFamily); + LongBuffer pCommandPool = stack.mallocLong(1); + if (vkCreateCommandPool(device, poolInfo, null, pCommandPool) != VK_SUCCESS) + { throw new RuntimeException("Failed to create command pool"); } + commandPool = pCommandPool.get(0); + } + } + + public static void createColorResources() + { + try (MemoryStack stack = stackPush()) + { + LongBuffer pColorImage = stack.mallocLong(1); + LongBuffer pColorImageMemory = stack.mallocLong(1); + createImage(swapChainExtent.width(), swapChainExtent.height(), + 1, + msaaSamples, + swapChainImageFormat, + VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + pColorImage, + pColorImageMemory); + colorImage = pColorImage.get(0); + colorImageMemory = pColorImageMemory.get(0); + colorImageView = createImageView(colorImage, swapChainImageFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1); + transitionImageLayout(colorImage, swapChainImageFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1); + } + } + + public static void createDepthResources() + { + try (MemoryStack stack = stackPush()) + { + int depthFormat = findDepthFormat(); + LongBuffer pDepthImage = stack.mallocLong(1); + LongBuffer pDepthImageMemory = stack.mallocLong(1); + createImage( + swapChainExtent.width(), swapChainExtent.height(), + 1, + msaaSamples, + depthFormat, + VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + pDepthImage, + pDepthImageMemory); + depthImage = pDepthImage.get(0); + depthImageMemory = pDepthImageMemory.get(0); + depthImageView = createImageView(depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1); + // Explicitly transitioning the depth image + transitionImageLayout(depthImage, depthFormat, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + 1); + } + } + + private static int findSupportedFormat(IntBuffer formatCandidates, int tiling, int features) + { + try (MemoryStack stack = stackPush()) + { + VkFormatProperties props = VkFormatProperties.callocStack(stack); + for (int i = 0; i < formatCandidates.capacity(); ++i) + { + int format = formatCandidates.get(i); + vkGetPhysicalDeviceFormatProperties(physicalDevice, format, props); + if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures() & features) == features) + { + return format; + } + else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures() & features) == features) + { return format; } + } + } + throw new RuntimeException("Failed to find supported format"); + } + + private static int findDepthFormat() + { return findSupportedFormat( + stackGet().ints(VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT), + VK_IMAGE_TILING_OPTIMAL, + VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); } + + private static boolean hasStencilComponent(int format) + { return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT; } + + private double log2(double n) + { return Math.log(n) / Math.log(2); } + + private void createTextureImage() + { + try (MemoryStack stack = stackPush()) + { + String filename = Paths.get(new URI(ClassLoader.getSystemClassLoader().getResource("textures/chalet.jpg").toExternalForm())).toString(); + IntBuffer pWidth = stack.mallocInt(1); + IntBuffer pHeight = stack.mallocInt(1); + IntBuffer pChannels = stack.mallocInt(1); + ByteBuffer pixels = stbi_load(filename, pWidth, pHeight, pChannels, STBI_rgb_alpha); + long imageSize = pWidth.get(0) * pHeight.get(0) * 4; // pChannels.get(0); + mipLevels = (int) Math.floor(log2(Math.max(pWidth.get(0), pHeight.get(0)))) + 1; + if (pixels == null) + { throw new RuntimeException("Failed to load texture image " + filename); } + LongBuffer pStagingBuffer = stack.mallocLong(1); + LongBuffer pStagingBufferMemory = stack.mallocLong(1); + createBuffer(imageSize, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + pStagingBuffer, + pStagingBufferMemory); + PointerBuffer data = stack.mallocPointer(1); + vkMapMemory(device, pStagingBufferMemory.get(0), 0, imageSize, 0, data); + { + memcpy(data.getByteBuffer(0, (int) imageSize), pixels, imageSize); + } + vkUnmapMemory(device, pStagingBufferMemory.get(0)); + stbi_image_free(pixels); + LongBuffer pTextureImage = stack.mallocLong(1); + LongBuffer pTextureImageMemory = stack.mallocLong(1); + createImage(pWidth.get(0), pHeight.get(0), + mipLevels, + VK_SAMPLE_COUNT_1_BIT, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + pTextureImage, + pTextureImageMemory); + textureImage = pTextureImage.get(0); + textureImageMemory = pTextureImageMemory.get(0); + transitionImageLayout(textureImage, + VK_FORMAT_R8G8B8A8_SRGB, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + mipLevels); + copyBufferToImage(pStagingBuffer.get(0), textureImage, pWidth.get(0), pHeight.get(0)); + // Transitioned to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL while generating mipmaps + generateMipmaps(textureImage, VK_FORMAT_R8G8B8A8_SRGB, pWidth.get(0), pHeight.get(0), mipLevels); + vkDestroyBuffer(device, pStagingBuffer.get(0), null); + vkFreeMemory(device, pStagingBufferMemory.get(0), null); + } + catch (URISyntaxException e) + { + e.printStackTrace(); + } + } + + private void generateMipmaps(long image, int imageFormat, int width, int height, int mipLevels) + { + try (MemoryStack stack = stackPush()) + { + // Check if image format supports linear blitting + VkFormatProperties formatProperties = VkFormatProperties.mallocStack(stack); + vkGetPhysicalDeviceFormatProperties(physicalDevice, imageFormat, formatProperties); + if ((formatProperties.optimalTilingFeatures() & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) == 0) + { throw new RuntimeException("Texture image format does not support linear blitting"); } + VkCommandBuffer commandBuffer = beginSingleTimeCommands(); + VkImageMemoryBarrier.Buffer barrier = VkImageMemoryBarrier.callocStack(1, stack); + barrier.sType(VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER); + barrier.image(image); + barrier.srcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); + barrier.dstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); + barrier.dstAccessMask(VK_QUEUE_FAMILY_IGNORED); + barrier.subresourceRange().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); + barrier.subresourceRange().baseArrayLayer(0); + barrier.subresourceRange().layerCount(1); + barrier.subresourceRange().levelCount(1); + int mipWidth = width; + int mipHeight = height; + for (int i = 1; i < mipLevels; i++) + { + barrier.subresourceRange().baseMipLevel(i - 1); + barrier.oldLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + barrier.newLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + barrier.srcAccessMask(VK_ACCESS_TRANSFER_WRITE_BIT); + barrier.dstAccessMask(VK_ACCESS_TRANSFER_READ_BIT); + vkCmdPipelineBarrier(commandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, + null, + null, + barrier); + VkImageBlit.Buffer blit = VkImageBlit.callocStack(1, stack); + blit.srcOffsets(0).set(0, 0, 0); + blit.srcOffsets(1).set(mipWidth, mipHeight, 1); + blit.srcSubresource().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); + blit.srcSubresource().mipLevel(i - 1); + blit.srcSubresource().baseArrayLayer(0); + blit.srcSubresource().layerCount(1); + blit.dstOffsets(0).set(0, 0, 0); + blit.dstOffsets(1).set(mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1); + blit.dstSubresource().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); + blit.dstSubresource().mipLevel(i); + blit.dstSubresource().baseArrayLayer(0); + blit.dstSubresource().layerCount(1); + vkCmdBlitImage(commandBuffer, + image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + blit, + VK_FILTER_LINEAR); + barrier.oldLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + barrier.newLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + barrier.srcAccessMask(VK_ACCESS_TRANSFER_READ_BIT); + barrier.dstAccessMask(VK_ACCESS_SHADER_READ_BIT); + vkCmdPipelineBarrier(commandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, + null, + null, + barrier); + if (mipWidth > 1) + { mipWidth /= 2; } + if (mipHeight > 1) + { mipHeight /= 2; } + } + barrier.subresourceRange().baseMipLevel(mipLevels - 1); + barrier.oldLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + barrier.newLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + barrier.srcAccessMask(VK_ACCESS_TRANSFER_WRITE_BIT); + barrier.dstAccessMask(VK_ACCESS_SHADER_READ_BIT); + vkCmdPipelineBarrier(commandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, + null, + null, + barrier); + endSingleTimeCommands(commandBuffer); + } + } + + private int getMaxUsableSampleCount() + { + try (MemoryStack stack = stackPush()) + { + VkPhysicalDeviceProperties physicalDeviceProperties = VkPhysicalDeviceProperties.mallocStack(stack); + vkGetPhysicalDeviceProperties(physicalDevice, physicalDeviceProperties); + int sampleCountFlags = physicalDeviceProperties.limits().framebufferColorSampleCounts() + & physicalDeviceProperties.limits().framebufferDepthSampleCounts(); + if ((sampleCountFlags & VK_SAMPLE_COUNT_64_BIT) != 0) + { return VK_SAMPLE_COUNT_64_BIT; } + if ((sampleCountFlags & VK_SAMPLE_COUNT_32_BIT) != 0) + { return VK_SAMPLE_COUNT_32_BIT; } + if ((sampleCountFlags & VK_SAMPLE_COUNT_16_BIT) != 0) + { return VK_SAMPLE_COUNT_16_BIT; } + if ((sampleCountFlags & VK_SAMPLE_COUNT_8_BIT) != 0) + { return VK_SAMPLE_COUNT_8_BIT; } + if ((sampleCountFlags & VK_SAMPLE_COUNT_4_BIT) != 0) + { return VK_SAMPLE_COUNT_4_BIT; } + if ((sampleCountFlags & VK_SAMPLE_COUNT_2_BIT) != 0) + { return VK_SAMPLE_COUNT_2_BIT; } + return VK_SAMPLE_COUNT_1_BIT; + } + } + + private void createTextureImageView() + { textureImageView = createImageView(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT, mipLevels); } + + private void createTextureSampler() + { + try (MemoryStack stack = stackPush()) + { + VkSamplerCreateInfo samplerInfo = VkSamplerCreateInfo.callocStack(stack); + samplerInfo.sType(VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO); + samplerInfo.magFilter(VK_FILTER_LINEAR); + samplerInfo.minFilter(VK_FILTER_LINEAR); + samplerInfo.addressModeU(VK_SAMPLER_ADDRESS_MODE_REPEAT); + samplerInfo.addressModeV(VK_SAMPLER_ADDRESS_MODE_REPEAT); + samplerInfo.addressModeW(VK_SAMPLER_ADDRESS_MODE_REPEAT); + samplerInfo.anisotropyEnable(true); + samplerInfo.maxAnisotropy(16.0f); + samplerInfo.borderColor(VK_BORDER_COLOR_INT_OPAQUE_BLACK); + samplerInfo.unnormalizedCoordinates(false); + samplerInfo.compareEnable(false); + samplerInfo.compareOp(VK_COMPARE_OP_ALWAYS); + samplerInfo.mipmapMode(VK_SAMPLER_MIPMAP_MODE_LINEAR); + samplerInfo.minLod(0); // Optional + samplerInfo.maxLod(mipLevels); + samplerInfo.mipLodBias(0); // Optional + LongBuffer pTextureSampler = stack.mallocLong(1); + if (vkCreateSampler(device, samplerInfo, null, pTextureSampler) != VK_SUCCESS) + { throw new RuntimeException("Failed to create texture sampler"); } + textureSampler = pTextureSampler.get(0); + } + } + + private static long createImageView(long image, int format, int aspectFlags, int mipLevels) + { + try (MemoryStack stack = stackPush()) + { + VkImageViewCreateInfo viewInfo = VkImageViewCreateInfo.callocStack(stack); + viewInfo.sType(VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO); + viewInfo.image(image); + viewInfo.viewType(VK_IMAGE_VIEW_TYPE_2D); + viewInfo.format(format); + viewInfo.subresourceRange().aspectMask(aspectFlags); + viewInfo.subresourceRange().baseMipLevel(0); + viewInfo.subresourceRange().levelCount(mipLevels); + viewInfo.subresourceRange().baseArrayLayer(0); + viewInfo.subresourceRange().layerCount(1); + LongBuffer pImageView = stack.mallocLong(1); + if (vkCreateImageView(device, viewInfo, null, pImageView) != VK_SUCCESS) + { throw new RuntimeException("Failed to create texture image view"); } + return pImageView.get(0); + } + } + + private static void createImage(int width, int height, int mipLevels, int numSamples, int format, int tiling, int usage, int memProperties, + LongBuffer pTextureImage, LongBuffer pTextureImageMemory) + { + try (MemoryStack stack = stackPush()) + { + VkImageCreateInfo imageInfo = VkImageCreateInfo.callocStack(stack); + imageInfo.sType(VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO); + imageInfo.imageType(VK_IMAGE_TYPE_2D); + imageInfo.extent().width(width); + imageInfo.extent().height(height); + imageInfo.extent().depth(1); + imageInfo.mipLevels(mipLevels); + imageInfo.arrayLayers(1); + imageInfo.format(format); + imageInfo.tiling(tiling); + imageInfo.initialLayout(VK_IMAGE_LAYOUT_UNDEFINED); + imageInfo.usage(usage); + imageInfo.samples(numSamples); + imageInfo.sharingMode(VK_SHARING_MODE_EXCLUSIVE); + if (vkCreateImage(device, imageInfo, null, pTextureImage) != VK_SUCCESS) + { throw new RuntimeException("Failed to create image"); } + VkMemoryRequirements memRequirements = VkMemoryRequirements.mallocStack(stack); + vkGetImageMemoryRequirements(device, pTextureImage.get(0), memRequirements); + VkMemoryAllocateInfo allocInfo = VkMemoryAllocateInfo.callocStack(stack); + allocInfo.sType(VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO); + allocInfo.allocationSize(memRequirements.size()); + allocInfo.memoryTypeIndex(findMemoryType(memRequirements.memoryTypeBits(), memProperties)); + if (vkAllocateMemory(device, allocInfo, null, pTextureImageMemory) != VK_SUCCESS) + { throw new RuntimeException("Failed to allocate image memory"); } + vkBindImageMemory(device, pTextureImage.get(0), pTextureImageMemory.get(0), 0); + } + } + + private static void transitionImageLayout(long image, int format, int oldLayout, int newLayout, int mipLevels) + { + try (MemoryStack stack = stackPush()) + { + VkImageMemoryBarrier.Buffer barrier = VkImageMemoryBarrier.callocStack(1, stack); + barrier.sType(VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER); + barrier.oldLayout(oldLayout); + barrier.newLayout(newLayout); + barrier.srcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); + barrier.dstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); + barrier.image(image); + barrier.subresourceRange().baseMipLevel(0); + barrier.subresourceRange().levelCount(mipLevels); + barrier.subresourceRange().baseArrayLayer(0); + barrier.subresourceRange().layerCount(1); + if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) + { + barrier.subresourceRange().aspectMask(VK_IMAGE_ASPECT_DEPTH_BIT); + if (hasStencilComponent(format)) + { barrier.subresourceRange().aspectMask( + barrier.subresourceRange().aspectMask() | VK_IMAGE_ASPECT_STENCIL_BIT); } + } + else + { + barrier.subresourceRange().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); + } + int sourceStage; + int destinationStage; + if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) + { + barrier.srcAccessMask(0); + barrier.dstAccessMask(VK_ACCESS_TRANSFER_WRITE_BIT); + sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + } + else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + { + barrier.srcAccessMask(VK_ACCESS_TRANSFER_WRITE_BIT); + barrier.dstAccessMask(VK_ACCESS_SHADER_READ_BIT); + sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } + else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) + { + barrier.srcAccessMask(0); + barrier.dstAccessMask(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT); + sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + destinationStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + } + else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + { + barrier.srcAccessMask(0); + barrier.dstAccessMask(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); + sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + destinationStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + } + else + { + throw new IllegalArgumentException("Unsupported layout transition"); + } + VkCommandBuffer commandBuffer = beginSingleTimeCommands(); + vkCmdPipelineBarrier(commandBuffer, + sourceStage, destinationStage, + 0, + null, + null, + barrier); + endSingleTimeCommands(commandBuffer); + } + } + + private void copyBufferToImage(long buffer, long image, int width, int height) + { + try (MemoryStack stack = stackPush()) + { + VkCommandBuffer commandBuffer = beginSingleTimeCommands(); + VkBufferImageCopy.Buffer region = VkBufferImageCopy.callocStack(1, stack); + region.bufferOffset(0); + region.bufferRowLength(0); // Tightly packed + region.bufferImageHeight(0); // Tightly packed + region.imageSubresource().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT); + region.imageSubresource().mipLevel(0); + region.imageSubresource().baseArrayLayer(0); + region.imageSubresource().layerCount(1); + region.imageOffset().set(0, 0, 0); + region.imageExtent(VkExtent3D.callocStack(stack).set(width, height, 1)); + vkCmdCopyBufferToImage(commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, region); + endSingleTimeCommands(commandBuffer); + } + } + + private void memcpy(ByteBuffer dst, ByteBuffer src, long size) + { + src.limit((int) size); + dst.put(src); + src.limit(src.capacity()).rewind(); + } + + private void loadModel() + { + File modelFile = new File(ClassLoader.getSystemClassLoader().getResource("models/chalet.obj").getFile()); + VKMesh model = VKModelLoader.loadModel(modelFile, aiProcess_FlipUVs | aiProcess_DropNormals); + final int vertexCount = model.positions.size(); + vertices = new Vertex[vertexCount]; + final Vector3fc color = new Vector3f(1.0f, 1.0f, 1.0f); + for (int i = 0; i < vertexCount; i++) + { vertices[i] = new Vertex( + model.positions.get(i), + color, + model.texCoords.get(i)); } + indices = new int[model.indices.size()]; + for (int i = 0; i < indices.length; i++) + { indices[i] = model.indices.get(i); } + } + + private void createVertexBuffer() + { + try (MemoryStack stack = stackPush()) + { + long bufferSize = Vertex.SIZEOF * vertices.length; + LongBuffer pBuffer = stack.mallocLong(1); + LongBuffer pBufferMemory = stack.mallocLong(1); + createBuffer(bufferSize, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + pBuffer, + pBufferMemory); + long stagingBuffer = pBuffer.get(0); + long stagingBufferMemory = pBufferMemory.get(0); + PointerBuffer data = stack.mallocPointer(1); + vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, data); + { + memcpy(data.getByteBuffer(0, (int) bufferSize), vertices); + } + vkUnmapMemory(device, stagingBufferMemory); + createBuffer(bufferSize, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + VK_MEMORY_HEAP_DEVICE_LOCAL_BIT, + pBuffer, + pBufferMemory); + vertexBuffer = pBuffer.get(0); + vertexBufferMemory = pBufferMemory.get(0); + copyBuffer(stagingBuffer, vertexBuffer, bufferSize); + vkDestroyBuffer(device, stagingBuffer, null); + vkFreeMemory(device, stagingBufferMemory, null); + } + } + + private void createIndexBuffer() + { + try (MemoryStack stack = stackPush()) + { + long bufferSize = Integer.BYTES * indices.length; + LongBuffer pBuffer = stack.mallocLong(1); + LongBuffer pBufferMemory = stack.mallocLong(1); + createBuffer(bufferSize, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + pBuffer, + pBufferMemory); + long stagingBuffer = pBuffer.get(0); + long stagingBufferMemory = pBufferMemory.get(0); + PointerBuffer data = stack.mallocPointer(1); + vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, data); + { + memcpy(data.getByteBuffer(0, (int) bufferSize), indices); + } + vkUnmapMemory(device, stagingBufferMemory); + createBuffer(bufferSize, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, + VK_MEMORY_HEAP_DEVICE_LOCAL_BIT, + pBuffer, + pBufferMemory); + indexBuffer = pBuffer.get(0); + indexBufferMemory = pBufferMemory.get(0); + copyBuffer(stagingBuffer, indexBuffer, bufferSize); + vkDestroyBuffer(device, stagingBuffer, null); + vkFreeMemory(device, stagingBufferMemory, null); + } + } + + public static void createUniformBuffers() + { + try (MemoryStack stack = stackPush()) + { + uniformBuffers = new ArrayList<>(swapChainImages.size()); + uniformBuffersMemory = new ArrayList<>(swapChainImages.size()); + LongBuffer pBuffer = stack.mallocLong(1); + LongBuffer pBufferMemory = stack.mallocLong(1); + for (int i = 0; i < swapChainImages.size(); i++) + { + createBuffer(UniformBufferObject.SIZEOF, + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + pBuffer, + pBufferMemory); + uniformBuffers.add(pBuffer.get(0)); + uniformBuffersMemory.add(pBufferMemory.get(0)); + } + } + } + + public static void createDescriptorPool() + { + try (MemoryStack stack = stackPush()) + { + VkDescriptorPoolSize.Buffer poolSizes = VkDescriptorPoolSize.callocStack(2, stack); + VkDescriptorPoolSize uniformBufferPoolSize = poolSizes.get(0); + uniformBufferPoolSize.type(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + uniformBufferPoolSize.descriptorCount(swapChainImages.size()); + VkDescriptorPoolSize textureSamplerPoolSize = poolSizes.get(1); + textureSamplerPoolSize.type(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + textureSamplerPoolSize.descriptorCount(swapChainImages.size()); + VkDescriptorPoolCreateInfo poolInfo = VkDescriptorPoolCreateInfo.callocStack(stack); + poolInfo.sType(VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO); + poolInfo.pPoolSizes(poolSizes); + poolInfo.maxSets(swapChainImages.size()); + LongBuffer pDescriptorPool = stack.mallocLong(1); + if (vkCreateDescriptorPool(device, poolInfo, null, pDescriptorPool) != VK_SUCCESS) + { throw new RuntimeException("Failed to create descriptor pool"); } + descriptorPool = pDescriptorPool.get(0); + } + } + + public static void createDescriptorSets() + { + try (MemoryStack stack = stackPush()) + { + LongBuffer layouts = stack.mallocLong(swapChainImages.size()); + for (int i = 0; i < layouts.capacity(); i++) + { layouts.put(i, descriptorSetLayout); } + VkDescriptorSetAllocateInfo allocInfo = VkDescriptorSetAllocateInfo.callocStack(stack); + allocInfo.sType(VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO); + allocInfo.descriptorPool(descriptorPool); + allocInfo.pSetLayouts(layouts); + LongBuffer pDescriptorSets = stack.mallocLong(swapChainImages.size()); + if (vkAllocateDescriptorSets(device, allocInfo, pDescriptorSets) != VK_SUCCESS) + { throw new RuntimeException("Failed to allocate descriptor sets"); } + descriptorSets = new ArrayList<>(pDescriptorSets.capacity()); + VkDescriptorBufferInfo.Buffer bufferInfo = VkDescriptorBufferInfo.callocStack(1, stack); + bufferInfo.offset(0); + bufferInfo.range(UniformBufferObject.SIZEOF); + VkDescriptorImageInfo.Buffer imageInfo = VkDescriptorImageInfo.callocStack(1, stack); + imageInfo.imageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + imageInfo.imageView(textureImageView); + imageInfo.sampler(textureSampler); + VkWriteDescriptorSet.Buffer descriptorWrites = VkWriteDescriptorSet.callocStack(2, stack); + VkWriteDescriptorSet uboDescriptorWrite = descriptorWrites.get(0); + uboDescriptorWrite.sType(VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET); + uboDescriptorWrite.dstBinding(0); + uboDescriptorWrite.dstArrayElement(0); + uboDescriptorWrite.descriptorType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + uboDescriptorWrite.descriptorCount(1); + uboDescriptorWrite.pBufferInfo(bufferInfo); + VkWriteDescriptorSet samplerDescriptorWrite = descriptorWrites.get(1); + samplerDescriptorWrite.sType(VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET); + samplerDescriptorWrite.dstBinding(1); + samplerDescriptorWrite.dstArrayElement(0); + samplerDescriptorWrite.descriptorType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + samplerDescriptorWrite.descriptorCount(1); + samplerDescriptorWrite.pImageInfo(imageInfo); + for (int i = 0; i < pDescriptorSets.capacity(); i++) + { + long descriptorSet = pDescriptorSets.get(i); + bufferInfo.buffer(uniformBuffers.get(i)); + uboDescriptorWrite.dstSet(descriptorSet); + samplerDescriptorWrite.dstSet(descriptorSet); + vkUpdateDescriptorSets(device, descriptorWrites, null); + descriptorSets.add(descriptorSet); + } + } + } + + private static void createBuffer(long size, int usage, int properties, LongBuffer pBuffer, LongBuffer pBufferMemory) + { + try (MemoryStack stack = stackPush()) + { + VkBufferCreateInfo bufferInfo = VkBufferCreateInfo.callocStack(stack); + bufferInfo.sType(VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO); + bufferInfo.size(size); + bufferInfo.usage(usage); + bufferInfo.sharingMode(VK_SHARING_MODE_EXCLUSIVE); + if (vkCreateBuffer(device, bufferInfo, null, pBuffer) != VK_SUCCESS) + { throw new RuntimeException("Failed to create vertex buffer"); } + VkMemoryRequirements memRequirements = VkMemoryRequirements.mallocStack(stack); + vkGetBufferMemoryRequirements(device, pBuffer.get(0), memRequirements); + VkMemoryAllocateInfo allocInfo = VkMemoryAllocateInfo.callocStack(stack); + allocInfo.sType(VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO); + allocInfo.allocationSize(memRequirements.size()); + allocInfo.memoryTypeIndex(findMemoryType(memRequirements.memoryTypeBits(), properties)); + if (vkAllocateMemory(device, allocInfo, null, pBufferMemory) != VK_SUCCESS) + { throw new RuntimeException("Failed to allocate vertex buffer memory"); } + vkBindBufferMemory(device, pBuffer.get(0), pBufferMemory.get(0), 0); + } + } + + private static VkCommandBuffer beginSingleTimeCommands() + { + try (MemoryStack stack = stackPush()) + { + VkCommandBufferAllocateInfo allocInfo = VkCommandBufferAllocateInfo.callocStack(stack); + allocInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO); + allocInfo.level(VK_COMMAND_BUFFER_LEVEL_PRIMARY); + allocInfo.commandPool(commandPool); + allocInfo.commandBufferCount(1); + PointerBuffer pCommandBuffer = stack.mallocPointer(1); + vkAllocateCommandBuffers(device, allocInfo, pCommandBuffer); + VkCommandBuffer commandBuffer = new VkCommandBuffer(pCommandBuffer.get(0), device); + VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.callocStack(stack); + beginInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO); + beginInfo.flags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); + vkBeginCommandBuffer(commandBuffer, beginInfo); + return commandBuffer; + } + } + + private static void endSingleTimeCommands(VkCommandBuffer commandBuffer) + { + try (MemoryStack stack = stackPush()) + { + vkEndCommandBuffer(commandBuffer); + VkSubmitInfo.Buffer submitInfo = VkSubmitInfo.callocStack(1, stack); + submitInfo.sType(VK_STRUCTURE_TYPE_SUBMIT_INFO); + submitInfo.pCommandBuffers(stack.pointers(commandBuffer)); + vkQueueSubmit(graphicsQueue, submitInfo, VK_NULL_HANDLE); + vkQueueWaitIdle(graphicsQueue); + vkFreeCommandBuffers(device, commandPool, commandBuffer); + } + } + + private void copyBuffer(long srcBuffer, long dstBuffer, long size) + { + try (MemoryStack stack = stackPush()) + { + VkCommandBuffer commandBuffer = beginSingleTimeCommands(); + VkBufferCopy.Buffer copyRegion = VkBufferCopy.callocStack(1, stack); + copyRegion.size(size); + vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, copyRegion); + endSingleTimeCommands(commandBuffer); + } + } + + private void memcpy(ByteBuffer buffer, Vertex[] vertices) + { + for (Vertex vertex : vertices) + { + buffer.putFloat(vertex.pos.x()); + buffer.putFloat(vertex.pos.y()); + buffer.putFloat(vertex.pos.z()); + buffer.putFloat(vertex.color.x()); + buffer.putFloat(vertex.color.y()); + buffer.putFloat(vertex.color.z()); + buffer.putFloat(vertex.texCoords.x()); + buffer.putFloat(vertex.texCoords.y()); + } + } + + private void memcpy(ByteBuffer buffer, int[] indices) + { + for (int index : indices) + { buffer.putInt(index); } + buffer.rewind(); + } + + private void memcpy(ByteBuffer buffer, UniformBufferObject ubo) + { + final int mat4Size = 16 * Float.BYTES; + ubo.model.get(0, buffer); + ubo.view.get(AlignmentUtils.alignas(mat4Size, AlignmentUtils.alignof(ubo.view)), buffer); + ubo.proj.get(AlignmentUtils.alignas(mat4Size * 2, AlignmentUtils.alignof(ubo.view)), buffer); + } + + private static int findMemoryType(int typeFilter, int properties) + { + VkPhysicalDeviceMemoryProperties memProperties = VkPhysicalDeviceMemoryProperties.mallocStack(); + vkGetPhysicalDeviceMemoryProperties(physicalDevice, memProperties); + for (int i = 0; i < memProperties.memoryTypeCount(); i++) + { + if ((typeFilter & (1 << i)) != 0 && (memProperties.memoryTypes(i).propertyFlags() & properties) == properties) + { return i; } + } + throw new RuntimeException("Failed to find suitable memory type"); + } + + public static void createCommandBuffers() + { + final int commandBuffersCount = swapChainFramebuffers.size(); + commandBuffers = new ArrayList<>(commandBuffersCount); + try (MemoryStack stack = stackPush()) + { + VkCommandBufferAllocateInfo allocInfo = VkCommandBufferAllocateInfo.callocStack(stack); + allocInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO); + allocInfo.commandPool(commandPool); + allocInfo.level(VK_COMMAND_BUFFER_LEVEL_PRIMARY); + allocInfo.commandBufferCount(commandBuffersCount); + PointerBuffer pCommandBuffers = stack.mallocPointer(commandBuffersCount); + if (vkAllocateCommandBuffers(device, allocInfo, pCommandBuffers) != VK_SUCCESS) + { throw new RuntimeException("Failed to allocate command buffers"); } + for (int i = 0; i < commandBuffersCount; i++) + { commandBuffers.add(new VkCommandBuffer(pCommandBuffers.get(i), device)); } + VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.callocStack(stack); + beginInfo.sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO); + VkRenderPassBeginInfo renderPassInfo = VkRenderPassBeginInfo.callocStack(stack); + renderPassInfo.sType(VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO); + renderPassInfo.renderPass(renderPass); + VkRect2D renderArea = VkRect2D.callocStack(stack); + renderArea.offset(VkOffset2D.callocStack(stack).set(0, 0)); + renderArea.extent(swapChainExtent); + renderPassInfo.renderArea(renderArea); + VkClearValue.Buffer clearValues = VkClearValue.callocStack(2, stack); + clearValues.get(0).color().float32(stack.floats(Window.getColour().x / 255, Window.getColour().y / 255, Window.getColour().z / 255, 1.0f)); //The screens clear colour + clearValues.get(1).depthStencil().set(1.0f, 0); + renderPassInfo.pClearValues(clearValues); + for (int i = 0; i < commandBuffersCount; i++) + { + VkCommandBuffer commandBuffer = commandBuffers.get(i); + if (vkBeginCommandBuffer(commandBuffer, beginInfo) != VK_SUCCESS) + { throw new RuntimeException("Failed to begin recording command buffer"); } + renderPassInfo.framebuffer(swapChainFramebuffers.get(i)); + vkCmdBeginRenderPass(commandBuffer, renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); + { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); + LongBuffer vertexBuffers = stack.longs(vertexBuffer); + LongBuffer offsets = stack.longs(0); + vkCmdBindVertexBuffers(commandBuffer, 0, vertexBuffers, offsets); + vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + pipelineLayout, + 0, stack.longs( + descriptorSets.get(i)), + null); + vkCmdDrawIndexed(commandBuffer, indices.length, 1, 0, 0, 0); + } + vkCmdEndRenderPass(commandBuffer); + if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) + { throw new RuntimeException("Failed to record command buffer"); } + } + } + } + + private void createSyncObjects() + { + inFlightFrames = new ArrayList<>(MAX_FRAMES_IN_FLIGHT); + imagesInFlight = new HashMap<>(swapChainImages.size()); + try (MemoryStack stack = stackPush()) + { + VkSemaphoreCreateInfo semaphoreInfo = VkSemaphoreCreateInfo.callocStack(stack); + semaphoreInfo.sType(VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO); + VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.callocStack(stack); + fenceInfo.sType(VK_STRUCTURE_TYPE_FENCE_CREATE_INFO); + fenceInfo.flags(VK_FENCE_CREATE_SIGNALED_BIT); + LongBuffer pImageAvailableSemaphore = stack.mallocLong(1); + LongBuffer pRenderFinishedSemaphore = stack.mallocLong(1); + LongBuffer pFence = stack.mallocLong(1); + for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + { + if (vkCreateSemaphore(device, semaphoreInfo, null, pImageAvailableSemaphore) != VK_SUCCESS + || vkCreateSemaphore(device, semaphoreInfo, null, pRenderFinishedSemaphore) != VK_SUCCESS + || vkCreateFence(device, fenceInfo, null, pFence) != VK_SUCCESS) + { throw new RuntimeException("Failed to create synchronization objects for the frame " + i); } + inFlightFrames.add(new Frame(pImageAvailableSemaphore.get(0), pRenderFinishedSemaphore.get(0), pFence.get(0))); + } + } + } + + private void updateUniformBuffer(int currentImage) + { + try (MemoryStack stack = stackPush()) + { + UniformBufferObject ubo = new UniformBufferObject(); + ubo.model.rotate((float) (glfwGetTime() * Math.toRadians(90)), 0.0f, 0.0f, 1.0f); + ubo.view.lookAt(2.0f, 2.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); + ubo.proj.perspective((float) Math.toRadians(45), + (float) swapChainExtent.width() / (float) swapChainExtent.height(), 0.1f, 10.0f); + ubo.proj.m11(ubo.proj.m11() * -1); + PointerBuffer data = stack.mallocPointer(1); + vkMapMemory(device, uniformBuffersMemory.get(currentImage), 0, UniformBufferObject.SIZEOF, 0, data); + { + memcpy(data.getByteBuffer(0, UniformBufferObject.SIZEOF), ubo); + } + vkUnmapMemory(device, uniformBuffersMemory.get(currentImage)); + } + } + + private void drawFrame() + { + try (MemoryStack stack = stackPush()) + { + Frame thisFrame = inFlightFrames.get(currentFrame); + vkWaitForFences(device, thisFrame.pFence(), true, UINT64_MAX); + IntBuffer pImageIndex = stack.mallocInt(1); + int vkResult = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, + thisFrame.imageAvailableSemaphore(), VK_NULL_HANDLE, pImageIndex); + if (vkResult == VK_ERROR_OUT_OF_DATE_KHR) + { + VKSwapchainManager.recreateSwapChain(); + return; + } + else if (vkResult != VK_SUCCESS) + { throw new RuntimeException("Cannot get image"); } + final int imageIndex = pImageIndex.get(0); + updateUniformBuffer(imageIndex); + if (imagesInFlight.containsKey(imageIndex)) + { vkWaitForFences(device, imagesInFlight.get(imageIndex).fence(), true, UINT64_MAX); } + imagesInFlight.put(imageIndex, thisFrame); + VkSubmitInfo submitInfo = VkSubmitInfo.callocStack(stack); + submitInfo.sType(VK_STRUCTURE_TYPE_SUBMIT_INFO); + submitInfo.waitSemaphoreCount(1); + submitInfo.pWaitSemaphores(thisFrame.pImageAvailableSemaphore()); + submitInfo.pWaitDstStageMask(stack.ints(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)); + submitInfo.pSignalSemaphores(thisFrame.pRenderFinishedSemaphore()); + submitInfo.pCommandBuffers(stack.pointers(commandBuffers.get(imageIndex))); + vkResetFences(device, thisFrame.pFence()); + if ((vkResult = vkQueueSubmit(graphicsQueue, submitInfo, thisFrame.fence())) != VK_SUCCESS) + { + vkResetFences(device, thisFrame.pFence()); + throw new RuntimeException("Failed to submit draw command buffer: " + vkResult); + } + VkPresentInfoKHR presentInfo = VkPresentInfoKHR.callocStack(stack); + presentInfo.sType(VK_STRUCTURE_TYPE_PRESENT_INFO_KHR); + presentInfo.pWaitSemaphores(thisFrame.pRenderFinishedSemaphore()); + presentInfo.swapchainCount(1); + presentInfo.pSwapchains(stack.longs(swapChain)); + presentInfo.pImageIndices(pImageIndex); + vkResult = vkQueuePresentKHR(presentQueue, presentInfo); + if (vkResult == VK_ERROR_OUT_OF_DATE_KHR || vkResult == VK_SUBOPTIMAL_KHR || framebufferResize) + { + framebufferResize = false; + VKSwapchainManager.recreateSwapChain(); + } + else if (vkResult != VK_SUCCESS) + { throw new RuntimeException("Failed to present swap chain image"); } + currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; + } + } + + public static VkSurfaceFormatKHR chooseSwapSurfaceFormat(VkSurfaceFormatKHR.Buffer availableFormats) + { return availableFormats.stream() + .filter(availableFormat -> availableFormat.format() == VK_FORMAT_B8G8R8_SRGB) + .filter(availableFormat -> availableFormat.colorSpace() == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + .findAny() + .orElse(availableFormats.get(0)); } + + public static int chooseSwapPresentMode(IntBuffer availablePresentModes) + { + for (int i = 0; i < availablePresentModes.capacity(); i++) + { + if (availablePresentModes.get(i) == VK_PRESENT_MODE_MAILBOX_KHR) + { return availablePresentModes.get(i); } + } + return VK_PRESENT_MODE_FIFO_KHR; + } + + public static VkExtent2D chooseSwapExtent(VkSurfaceCapabilitiesKHR capabilities) + { + if (capabilities.currentExtent().width() != UINT32_MAX) + { return capabilities.currentExtent(); } + IntBuffer width = stackGet().ints(0); + IntBuffer height = stackGet().ints(0); + glfwGetFramebufferSize(Window.getWindow(), width, height); + VkExtent2D actualExtent = VkExtent2D.mallocStack().set(width.get(0), height.get(0)); + VkExtent2D minExtent = capabilities.minImageExtent(); + VkExtent2D maxExtent = capabilities.maxImageExtent(); + actualExtent.width(clamp(minExtent.width(), maxExtent.width(), actualExtent.width())); + actualExtent.height(clamp(minExtent.height(), maxExtent.height(), actualExtent.height())); + return actualExtent; + } + + private static int clamp(int min, int max, int value) + { return Math.max(min, Math.min(max, value)); } + + private boolean isDeviceSuitable(VkPhysicalDevice device) + { + QueueFamilyIndices indices = findQueueFamilies(device); + boolean extensionsSupported = checkDeviceExtensionSupport(device); + boolean swapChainAdequate = false; + boolean anisotropySupported = false; + if (extensionsSupported) + { + try (MemoryStack stack = stackPush()) + { + SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device, stack); + swapChainAdequate = swapChainSupport.formats.hasRemaining() && swapChainSupport.presentModes.hasRemaining(); + VkPhysicalDeviceFeatures supportedFeatures = VkPhysicalDeviceFeatures.mallocStack(stack); + vkGetPhysicalDeviceFeatures(device, supportedFeatures); + anisotropySupported = supportedFeatures.samplerAnisotropy(); + } + } + return indices.isComplete() && extensionsSupported && swapChainAdequate && anisotropySupported; + } + + private boolean checkDeviceExtensionSupport(VkPhysicalDevice device) + { + try (MemoryStack stack = stackPush()) + { + IntBuffer extensionCount = stack.ints(0); + vkEnumerateDeviceExtensionProperties(device, (String) null, extensionCount, null); + VkExtensionProperties.Buffer availableExtensions = VkExtensionProperties.mallocStack(extensionCount.get(0), stack); + return availableExtensions.stream().collect(toSet()).containsAll(DEVICE_EXTENSIONS); + } + } + + public static SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device, MemoryStack stack) + { + SwapChainSupportDetails details = new SwapChainSupportDetails(); + details.capabilities = VkSurfaceCapabilitiesKHR.mallocStack(stack); + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, details.capabilities); + IntBuffer count = stack.ints(0); + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, count, null); + if (count.get(0) != 0) + { + details.formats = VkSurfaceFormatKHR.mallocStack(count.get(0), stack); + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, count, details.formats); + } + vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, count, null); + if (count.get(0) != 0) + { + details.presentModes = stack.mallocInt(count.get(0)); + vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, count, details.presentModes); + } + return details; + } + + public static QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) + { + QueueFamilyIndices indices = new QueueFamilyIndices(); + try (MemoryStack stack = stackPush()) + { + IntBuffer queueFamilyCount = stack.ints(0); + vkGetPhysicalDeviceQueueFamilyProperties(device, queueFamilyCount, null); + VkQueueFamilyProperties.Buffer queueFamilies = VkQueueFamilyProperties.mallocStack(queueFamilyCount.get(0), stack); + vkGetPhysicalDeviceQueueFamilyProperties(device, queueFamilyCount, queueFamilies); + IntBuffer presentSupport = stack.ints(VK_FALSE); + for (int i = 0; i < queueFamilies.capacity() || !indices.isComplete(); i++) + { + if ((queueFamilies.get(i).queueFlags() & VK_QUEUE_GRAPHICS_BIT) != 0) + { indices.graphicsFamily = i; } + vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, presentSupport); + if (presentSupport.get(0) == VK_TRUE) + { indices.presentFamily = i; } + } + return indices; + } + } + + private PointerBuffer asPointerBuffer(Collection collection) + { + MemoryStack stack = stackGet(); + PointerBuffer buffer = stack.mallocPointer(collection.size()); + collection.stream() + .map(stack::UTF8) + .forEach(buffer::put); + return buffer.rewind(); + } + + public static PointerBuffer asPointerBuffer(List list) + { + MemoryStack stack = stackGet(); + PointerBuffer buffer = stack.mallocPointer(list.size()); + list.forEach(buffer::put); + return buffer.rewind(); + } + + private PointerBuffer getRequiredExtensions() + { + PointerBuffer glfwExtensions = glfwGetRequiredInstanceExtensions(); + return glfwExtensions; + } + } + + public static void main(String[] args) + { + VulkanDemoGinger2 app = new VulkanDemoGinger2(); + app.run(); + } } diff --git a/src/main/java/com/github/hydos/ginger/engine/common/api/GingerEngine.java b/src/main/java/com/github/hydos/ginger/engine/common/api/GingerEngine.java index 88fec91..4f93a9c 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/api/GingerEngine.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/api/GingerEngine.java @@ -10,12 +10,10 @@ public abstract class GingerEngine { protected static GingerEngine INSTANCE; protected GingerRegister registry; - + public static GingerEngine getInstance() - { - return INSTANCE; - } - + { return INSTANCE; } + protected Timer timer; protected TickListener gameTickListener = new TickListener() { @@ -26,7 +24,7 @@ public abstract class GingerEngine if (GingerRegister.getInstance().currentScreen != null) GingerRegister.getInstance().currentScreen.tick(); }; }; - + public void startGameLoop() { while (!Window.closed()) diff --git a/src/main/java/com/github/hydos/ginger/engine/common/api/GingerRegister.java b/src/main/java/com/github/hydos/ginger/engine/common/api/GingerRegister.java index 6bc1c63..d9ec755 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/api/GingerRegister.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/api/GingerRegister.java @@ -26,9 +26,7 @@ public class GingerRegister public boolean wireframe = false; public GingerRegister() - { - INSTANCE = this; - } + { INSTANCE = this; } public void registerButton(TextureButton button) { @@ -59,9 +57,7 @@ public class GingerRegister } public void toggleWireframe() - { - this.wireframe = !this.wireframe; - } + { this.wireframe = !this.wireframe; } public GUIText retrieveText(String string) { diff --git a/src/main/java/com/github/hydos/ginger/engine/common/api/game/Game.java b/src/main/java/com/github/hydos/ginger/engine/common/api/game/Game.java index 32da21a..2e0fb42 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/api/game/Game.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/api/game/Game.java @@ -17,7 +17,7 @@ public abstract class Game public abstract void render(); public abstract void renderScene(); - + public abstract void tick(); public abstract void update(); diff --git a/src/main/java/com/github/hydos/ginger/engine/common/api/game/GameData.java b/src/main/java/com/github/hydos/ginger/engine/common/api/game/GameData.java index de22f1a..c28166d 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/api/game/GameData.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/api/game/GameData.java @@ -8,10 +8,8 @@ import com.github.hydos.ginger.engine.common.cameras.Camera; import com.github.hydos.ginger.engine.common.elements.GuiTexture; import com.github.hydos.ginger.engine.common.elements.objects.*; -/** - * Used for storing essential engine game data so main class isn't messy - * Also in general used with Game Class - */ +/** Used for storing essential engine game data so main class isn't messy + * Also in general used with Game Class */ public class GameData { public List guis; diff --git a/src/main/java/com/github/hydos/ginger/engine/common/cameras/Camera.java b/src/main/java/com/github/hydos/ginger/engine/common/cameras/Camera.java index e85cbbc..741be4b 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/cameras/Camera.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/cameras/Camera.java @@ -12,7 +12,7 @@ public abstract class Camera public Vector3f getPosition() { return position; } - + public float getPitch() { return pitch; } diff --git a/src/main/java/com/github/hydos/ginger/engine/common/cameras/FirstPersonCamera.java b/src/main/java/com/github/hydos/ginger/engine/common/cameras/FirstPersonCamera.java index a3b7535..0ae242d 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/cameras/FirstPersonCamera.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/cameras/FirstPersonCamera.java @@ -17,18 +17,23 @@ public class FirstPersonCamera extends Camera playerEntity.setVisible(false); } + @Override public float getPitch() { return pitch; } + @Override public Vector3f getPosition() { return position; } + @Override public float getRoll() { return roll; } + @Override public float getYaw() { return yaw; } + @Override public void updateMovement() { position.x = player.getPosition().x; diff --git a/src/main/java/com/github/hydos/ginger/engine/common/cameras/ThirdPersonCamera.java b/src/main/java/com/github/hydos/ginger/engine/common/cameras/ThirdPersonCamera.java index 66f7576..1320bc7 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/cameras/ThirdPersonCamera.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/cameras/ThirdPersonCamera.java @@ -8,12 +8,11 @@ import com.github.hydos.ginger.engine.common.io.Window; public class ThirdPersonCamera extends Camera { public ThirdPersonCamera(RenderObject playerEntity) - { - this.player = playerEntity; - } + { this.player = playerEntity; } private float distanceFromPlayer = 5; private float angleAroundPlayer = 0; + private void calculatePitch() { if (Window.isMouseDown(1)) @@ -28,7 +27,8 @@ public class ThirdPersonCamera extends Camera { setPitch(90); } } } - + + @Override public void updateMovement() { calculateZoom(); diff --git a/src/main/java/com/github/hydos/ginger/engine/common/elements/objects/Player.java b/src/main/java/com/github/hydos/ginger/engine/common/elements/objects/Player.java index 1304786..aec8922 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/elements/objects/Player.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/elements/objects/Player.java @@ -50,7 +50,8 @@ public class Player extends RenderObject implements WorldGenConstants position.x += Math.sin(ry) * Constants.movementSpeed; break; case UP: - if (this.noWeight) position.y += Constants.movementSpeed; + if (this.noWeight) + position.y += Constants.movementSpeed; else this.jump(); break; case DOWN: @@ -85,11 +86,9 @@ public class Player extends RenderObject implements WorldGenConstants upwardsSpeed += Constants.gravity.y() * Window.getTime(); // TODO: Implement 3D gravity isInAir = false; upwardsSpeed = 0; - int newChunkX = (int) position.x >> POS_SHIFT; int newChunkY = (int) position.y >> POS_SHIFT; int newChunkZ = (int) position.z >> POS_SHIFT; - if (newChunkX != this.chunkX || newChunkY != this.chunkY || newChunkZ != this.chunkZ) { Litecraft.getInstance().getWorld().updateLoadedChunks(newChunkX, newChunkY, newChunkZ); diff --git a/src/main/java/com/github/hydos/ginger/engine/common/elements/objects/RenderObject.java b/src/main/java/com/github/hydos/ginger/engine/common/elements/objects/RenderObject.java index 7b7bf92..e79c871 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/elements/objects/RenderObject.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/elements/objects/RenderObject.java @@ -82,12 +82,8 @@ public class RenderObject { this.scale = scale; } public boolean isVisible() - { - return visible; - } + { return visible; } public void setVisible(boolean visible) - { - this.visible = visible; - } + { this.visible = visible; } } diff --git a/src/main/java/com/github/hydos/ginger/engine/common/font/TextMaster.java b/src/main/java/com/github/hydos/ginger/engine/common/font/TextMaster.java index 72c9f8e..4a6b653 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/font/TextMaster.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/font/TextMaster.java @@ -2,6 +2,7 @@ package com.github.hydos.ginger.engine.common.font; import java.util.*; +import com.github.hydos.ginger.engine.common.api.GingerEngine; import com.github.hydos.ginger.engine.common.info.RenderAPI; import com.github.hydos.ginger.engine.common.io.Window; import com.github.hydos.ginger.engine.opengl.api.GingerGL; @@ -51,10 +52,10 @@ public class TextMaster if (Window.renderAPI == RenderAPI.OpenGL) { Map> oldTexts = texts; - List oldFontText = texts.get(((GingerGL)GingerGL.getInstance()).globalFont); + List oldFontText = texts.get(((GingerGL) GingerEngine.getInstance()).globalFont); oldFontText.add(buildText); texts.clear(); - texts.put(((GingerGL)GingerGL.getInstance()).globalFont, oldFontText); + texts.put(((GingerGL) GingerEngine.getInstance()).globalFont, oldFontText); texts = oldTexts; } } diff --git a/src/main/java/com/github/hydos/ginger/engine/common/info/RenderAPI.java b/src/main/java/com/github/hydos/ginger/engine/common/info/RenderAPI.java index 3d7e755..00e6885 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/info/RenderAPI.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/info/RenderAPI.java @@ -1,4 +1,6 @@ package com.github.hydos.ginger.engine.common.info; public enum RenderAPI -{OpenGL, Vulkan} +{ + OpenGL, Vulkan +} diff --git a/src/main/java/com/github/hydos/ginger/engine/common/io/Window.java b/src/main/java/com/github/hydos/ginger/engine/common/io/Window.java index c6d54bb..8260752 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/io/Window.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/io/Window.java @@ -9,6 +9,7 @@ import org.lwjgl.BufferUtils; import org.lwjgl.glfw.*; import org.lwjgl.opengl.*; +import com.github.hydos.ginger.engine.common.api.GingerEngine; import com.github.hydos.ginger.engine.common.info.RenderAPI; import com.github.hydos.ginger.engine.opengl.api.GingerGL; import com.github.hydos.ginger.engine.opengl.render.texture.Image; @@ -29,7 +30,7 @@ public class Window public static boolean isFullscreen() { return fullscreen; } - + public static RenderAPI renderAPI; public static int width; public static int height; @@ -63,7 +64,7 @@ public class Window System.exit(-1); } renderAPI = api; - if(renderAPI == RenderAPI.OpenGL) + if (renderAPI == RenderAPI.OpenGL) { GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 4); GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 6); @@ -72,10 +73,9 @@ public class Window } else if (renderAPI == RenderAPI.Vulkan) { - GLFW.glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - if (!GLFWVulkan.glfwVulkanSupported()) { - throw new AssertionError("GLFW failed to find the Vulkan loader"); - } + GLFW.glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + if (!GLFWVulkan.glfwVulkanSupported()) + { throw new AssertionError("GLFW failed to find the Vulkan loader"); } } GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE); GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 4); @@ -91,7 +91,8 @@ public class Window System.exit(-1); } GLFW.glfwMakeContextCurrent(getWindow()); - if(api == RenderAPI.OpenGL) { + if (api == RenderAPI.OpenGL) + { glContext = GL.createCapabilities(); GL11.glEnable(GL11.GL_DEPTH_TEST); } @@ -99,7 +100,6 @@ public class Window GLFW.glfwShowWindow(getWindow()); time = getTime(); getCurrentTime(); - oldWindowWidth = getWidth(); oldWindowHeight = getHeight(); } @@ -208,15 +208,16 @@ public class Window public static void update() { - if(renderAPI == RenderAPI.OpenGL) { + if (renderAPI == RenderAPI.OpenGL) + { if ((oldWindowHeight != Window.getHeight() || oldWindowWidth != Window.getWidth()) && Window.getHeight() > 10 && Window.getWidth() > 10) { - ((GingerGL)GingerGL.getInstance()).contrastFbo.resizeFBOs(); + ((GingerGL) GingerEngine.getInstance()).contrastFbo.resizeFBOs(); oldWindowWidth = Window.getWidth(); oldWindowHeight = Window.getHeight(); } GL11.glViewport(0, 0, width, height); - GL11.glClearColor(backgroundColour.x/255, backgroundColour.y/255, backgroundColour.z/255, 1.0f); + GL11.glClearColor(backgroundColour.x / 255, backgroundColour.y / 255, backgroundColour.z / 255, 1.0f); GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); } IntBuffer widthBuffer = BufferUtils.createIntBuffer(1); @@ -237,7 +238,5 @@ public class Window { Window.fullscreen = !Window.isFullscreen(); } public static long getWindow() - { - return window; - } + { return window; } } diff --git a/src/main/java/com/github/hydos/ginger/engine/common/math/Maths.java b/src/main/java/com/github/hydos/ginger/engine/common/math/Maths.java index fa8902d..e0f1175 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/math/Maths.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/math/Maths.java @@ -44,7 +44,6 @@ public class Maths private static final Vector3f ZVEC = new Vector3f(0, 0, 1); private static final Matrix4f matrix = new Matrix4f(); - public static Matrix4f createTransformationMatrix(Vector3f translation, float rx, float ry, float rz, Vector3f scale) { matrix.zero(); diff --git a/src/main/java/com/github/hydos/ginger/engine/common/obj/ModelLoader.java b/src/main/java/com/github/hydos/ginger/engine/common/obj/ModelLoader.java index e0b14ca..8f4aec4 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/obj/ModelLoader.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/obj/ModelLoader.java @@ -13,18 +13,18 @@ public class ModelLoader GLTexturedModel tm = new GLTexturedModel(GLLoader.loadToVAO(data.getVertices(), data.getIndices(), data.getNormals(), data.getTextureCoords()), new ModelTexture(cubeTexture)); return tm; } - - public static Mesh getCubeMesh() { - return StaticCube.getCube(); - } + + public static Mesh getCubeMesh() + { return StaticCube.getCube(); } public static GLTexturedModel loadModel(String objPath, String texturePath) { Mesh data = OBJFileLoader.loadModel(objPath); return new GLTexturedModel(GLLoader.loadToVAO(data.getVertices(), data.getIndices(), data.getNormals(), data.getTextureCoords()), new ModelTexture(texturePath)); } - - public static Mesh loadMesh(String meshPath) { + + public static Mesh loadMesh(String meshPath) + { Mesh data = OBJFileLoader.loadModel(meshPath); return data; } diff --git a/src/main/java/com/github/hydos/ginger/engine/common/obj/OBJFileLoader.java b/src/main/java/com/github/hydos/ginger/engine/common/obj/OBJFileLoader.java index a2cb7d2..207f556 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/obj/OBJFileLoader.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/obj/OBJFileLoader.java @@ -15,9 +15,9 @@ public class OBJFileLoader { scene = Assimp.aiImportFile(resourceLocation + filePath, Assimp.aiProcess_JoinIdenticalVertices | Assimp.aiProcess_Triangulate); if (scene == null) - { + { System.err.println("The model " + resourceLocation + filePath + " has failed to load"); - return new Mesh(new float[0], new float[0], new float[0], new int[0], 1F); + return new Mesh(new float[0], new float[0], new float[0], new int[0], 1F); } AIMesh mesh = AIMesh.create(scene.mMeshes().get(0)); int vertexCount = mesh.mNumVertices(); diff --git a/src/main/java/com/github/hydos/ginger/engine/common/screen/Screen.java b/src/main/java/com/github/hydos/ginger/engine/common/screen/Screen.java index adaf694..cc98aef 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/screen/Screen.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/screen/Screen.java @@ -8,9 +8,9 @@ public abstract class Screen { public List elements; - public abstract void render(); // FIXME: This never gets called!!! + public abstract void render(); // FIXME: This never gets called!!! public abstract void tick(); - + public abstract void cleanup(); } diff --git a/src/main/java/com/github/hydos/ginger/engine/opengl/api/GingerGL.java b/src/main/java/com/github/hydos/ginger/engine/opengl/api/GingerGL.java index 3eb2d78..03f593e 100644 --- a/src/main/java/com/github/hydos/ginger/engine/opengl/api/GingerGL.java +++ b/src/main/java/com/github/hydos/ginger/engine/opengl/api/GingerGL.java @@ -21,6 +21,7 @@ public class GingerGL extends GingerEngine public FontType globalFont; public FrameBufferObject contrastFbo; + @Override public void cleanup() { Window.stop(); @@ -30,12 +31,13 @@ public class GingerGL extends GingerEngine GLLoader.cleanUp(); } + @Override public void openScreen(Screen screen) { if (getRegistry().currentScreen != null) getRegistry().currentScreen.cleanup(); getRegistry().currentScreen = screen; } - + public void setGingerPlayer(RenderObject player) { registry.game.data.entities.remove(registry.game.player); // remove the old player @@ -60,6 +62,7 @@ public class GingerGL extends GingerEngine return text; } + @Override public void renderOverlays() { getRegistry().masterRenderer.renderGuis(getRegistry().game.data.guis); @@ -82,7 +85,7 @@ public class GingerGL extends GingerEngine picker = new MousePicker(game.data.camera, masterRenderer.getProjectionMatrix()); PostProcessing.init(); } - + @Override public void update() { @@ -92,7 +95,5 @@ public class GingerGL extends GingerEngine } public GingerRegister getRegistry() - { - return registry; - } + { return registry; } } \ No newline at end of file diff --git a/src/main/java/com/github/hydos/ginger/engine/opengl/api/ResourceManager.java b/src/main/java/com/github/hydos/ginger/engine/opengl/api/ResourceManager.java index 46a611a..f33930a 100644 --- a/src/main/java/com/github/hydos/ginger/engine/opengl/api/ResourceManager.java +++ b/src/main/java/com/github/hydos/ginger/engine/opengl/api/ResourceManager.java @@ -1,8 +1,6 @@ package com.github.hydos.ginger.engine.opengl.api; -/** - * make your own resource manager if you want! - */ +/** make your own resource manager if you want! */ public abstract class ResourceManager { public abstract boolean getResourceInternally(String path); diff --git a/src/main/java/com/github/hydos/ginger/engine/opengl/render/GLRenderManager.java b/src/main/java/com/github/hydos/ginger/engine/opengl/render/GLRenderManager.java index df16333..ed1a485 100644 --- a/src/main/java/com/github/hydos/ginger/engine/opengl/render/GLRenderManager.java +++ b/src/main/java/com/github/hydos/ginger/engine/opengl/render/GLRenderManager.java @@ -37,7 +37,7 @@ public class GLRenderManager public GLObjectRenderer entityRenderer; private GuiShader guiShader; private GLGuiRenderer guiRenderer; -// private SkyboxRenderer skyboxRenderer; + // private SkyboxRenderer skyboxRenderer; private GLNormalMappingRenderer normalRenderer; private Matrix4f projectionMatrix; private ShadowMapMasterRenderer shadowMapRenderer; @@ -162,7 +162,7 @@ public class GLRenderManager renderEntities(entities, camera, lights); renderNormalEntities(normalEntities, lights, camera, clipPlane); GingerRegister.getInstance().game.renderScene(); -// skyboxRenderer.render(camera); + // skyboxRenderer.render(camera); } public void renderShadowMap(List entityList, Light sun) diff --git a/src/main/java/com/github/hydos/ginger/engine/opengl/render/renderers/GLGuiRenderer.java b/src/main/java/com/github/hydos/ginger/engine/opengl/render/renderers/GLGuiRenderer.java index 93b988f..4183e26 100644 --- a/src/main/java/com/github/hydos/ginger/engine/opengl/render/renderers/GLGuiRenderer.java +++ b/src/main/java/com/github/hydos/ginger/engine/opengl/render/renderers/GLGuiRenderer.java @@ -40,7 +40,6 @@ public class GLGuiRenderer extends Renderer GL11.glEnable(GL11.GL_BLEND); GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - for (GuiTexture gui : guis) { GL13.glActiveTexture(GL13.GL_TEXTURE0); diff --git a/src/main/java/com/github/hydos/ginger/engine/opengl/render/texture/Image.java b/src/main/java/com/github/hydos/ginger/engine/opengl/render/texture/Image.java index 836779a..089a4d9 100644 --- a/src/main/java/com/github/hydos/ginger/engine/opengl/render/texture/Image.java +++ b/src/main/java/com/github/hydos/ginger/engine/opengl/render/texture/Image.java @@ -64,7 +64,6 @@ public class Image public IntBuffer getComp() { return comp; } - public String getLocation() { - return location; - } + public String getLocation() + { return location; } } \ No newline at end of file diff --git a/src/main/java/com/github/hydos/ginger/engine/opengl/utils/GLLoader.java b/src/main/java/com/github/hydos/ginger/engine/opengl/utils/GLLoader.java index 619947a..a98aaf6 100644 --- a/src/main/java/com/github/hydos/ginger/engine/opengl/utils/GLLoader.java +++ b/src/main/java/com/github/hydos/ginger/engine/opengl/utils/GLLoader.java @@ -1,4 +1,3 @@ - package com.github.hydos.ginger.engine.opengl.utils; import java.nio.*; @@ -47,11 +46,14 @@ public class GLLoader public static int createEmptyVbo(int floatCount) { int vbo; - if (Window.glContext.GL_ARB_vertex_buffer_object) { //checks if gpu can handle faster vbos + if (Window.glContext.GL_ARB_vertex_buffer_object) + { //checks if gpu can handle faster vbos IntBuffer buffer = BufferUtils.createIntBuffer(1); ARBVertexBufferObject.glGenBuffersARB(buffer); vbo = buffer.get(0); - }else { + } + else + { vbo = GL15.glGenBuffers(); } vbos.add(vbo); @@ -102,47 +104,46 @@ public class GLLoader public static int loadTexture(String path) { return loadTextureDirectly("/textures/" + path); } - + public static int createBlockAtlas() { int width = 16; int height = 16; //Prepare the atlas texture and gen it - int atlasId = GL40.glGenTextures(); + int atlasId = GL11.glGenTextures(); //Bind it to openGL - GL40.glBindTexture(GL40.GL_TEXTURE_2D, atlasId); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, atlasId); //Apply the settings for the texture - GL40.glTexParameteri(GL40.GL_TEXTURE_2D, GL40.GL_TEXTURE_MIN_FILTER, GL40.GL_NEAREST); - GL40.glTexParameteri(GL40.GL_TEXTURE_2D, GL40.GL_TEXTURE_MAG_FILTER, GL40.GL_NEAREST); - //Fill the image with blank image data - GL40.glTexImage2D(GL40.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width*2, height*2, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (ByteBuffer) null); - - long maxX = Math.round(Math.sqrt(Blocks.blocks.size())); - int currentX = 0; - int currentY = 0; - for(Block block: Blocks.blocks) { + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); + //Fill the image with blank image data + GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width * 2, height * 2, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (ByteBuffer) null); + long maxX = Math.round(Math.sqrt(Blocks.blocks.size())); + int currentX = 0; + int currentY = 0; + for (Block block : Blocks.blocks) + { //just in case - - if(!block.texture.equals("DONTLOAD")) { + if (!block.texture.equals("DONTLOAD")) + { System.out.println(block.texture); block.updateBlockModelData(); - if(currentX > maxX) { + if (currentX > maxX) + { currentX = 0; currentY--; } - GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, - currentX*width, currentY*height, - width, height, - GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, - block.model.getTexture().getTexture().getImage() - ); + GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, + currentX * width, currentY * height, + width, height, + GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, + block.model.getTexture().getTexture().getImage()); currentX++; } - } return atlasId; } - + public static int loadTextureDirectly(String path) { int textureID = GL11.glGenTextures(); diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/VKRegister.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/VKRegister.java index 120fdb3..6cc9a53 100644 --- a/src/main/java/com/github/hydos/ginger/engine/vulkan/VKRegister.java +++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/VKRegister.java @@ -2,7 +2,4 @@ package com.github.hydos.ginger.engine.vulkan; public class VKRegister { - - - } diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/misc/AlignmentUtils.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/misc/AlignmentUtils.java index 8b26108..9c322ad 100644 --- a/src/main/java/com/github/hydos/ginger/engine/vulkan/misc/AlignmentUtils.java +++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/misc/AlignmentUtils.java @@ -4,48 +4,40 @@ import java.util.*; import org.joml.*; -/** - * An utility class for dealing with alignments in Uniform Buffer Objects - * +/** An utility class for dealing with alignments in Uniform Buffer Objects * Vulkan expects the data in your structure to be aligned in memory in a specific way, for example: - * * Scalars have to be aligned by N (= 4 bytes given 32 bit floats). * A vec2 must be aligned by 2N (= 8 bytes) * A vec3 or vec4 must be aligned by 4N (= 16 bytes) * A nested structure must be aligned by the base alignment of its members rounded up to a multiple of 16. - * A mat4 matrix must have the same alignment as a vec4. - * - * */ -public final class AlignmentUtils { + * A mat4 matrix must have the same alignment as a vec4. */ +public final class AlignmentUtils +{ + private AlignmentUtils() + {} - private AlignmentUtils() {} + public static int sizeof(Object obj) + { return obj == null ? 0 : SIZEOF_CACHE.getOrDefault(obj.getClass(), 0); } - public static int sizeof(Object obj) { - return obj == null ? 0 : SIZEOF_CACHE.getOrDefault(obj.getClass(), 0); - } + public static int alignof(Object obj) + { return obj == null ? 0 : SIZEOF_CACHE.getOrDefault(obj.getClass(), Integer.BYTES); } - public static int alignof(Object obj) { - return obj == null ? 0 : SIZEOF_CACHE.getOrDefault(obj.getClass(), Integer.BYTES); - } + public static int alignas(int offset, int alignment) + { return offset % alignment == 0 ? offset : ((offset - 1) | (alignment - 1)) + 1; } - public static int alignas(int offset, int alignment) { - return offset % alignment == 0 ? offset : ((offset - 1) | (alignment - 1)) + 1; - } - - private static final Map, Integer> SIZEOF_CACHE = new HashMap<>(); - static { - SIZEOF_CACHE.put(Byte.class, Byte.BYTES); - SIZEOF_CACHE.put(Character.class, Character.BYTES); - SIZEOF_CACHE.put(Short.class, Short.BYTES); - SIZEOF_CACHE.put(Integer.class, Integer.BYTES); - SIZEOF_CACHE.put(Float.class, Float.BYTES); - SIZEOF_CACHE.put(Long.class, Long.BYTES); - SIZEOF_CACHE.put(Double.class, Double.BYTES); - - SIZEOF_CACHE.put(Vector2f.class, 2 * Float.BYTES); - SIZEOF_CACHE.put(Vector3f.class, 3 * Float.BYTES); - SIZEOF_CACHE.put(Vector4f.class, 4 * Float.BYTES); - - SIZEOF_CACHE.put(Matrix4f.class, SIZEOF_CACHE.get(Vector4f.class)); - } + private static final Map, Integer> SIZEOF_CACHE = new HashMap<>(); + static + { + SIZEOF_CACHE.put(Byte.class, Byte.BYTES); + SIZEOF_CACHE.put(Character.class, Character.BYTES); + SIZEOF_CACHE.put(Short.class, Short.BYTES); + SIZEOF_CACHE.put(Integer.class, Integer.BYTES); + SIZEOF_CACHE.put(Float.class, Float.BYTES); + SIZEOF_CACHE.put(Long.class, Long.BYTES); + SIZEOF_CACHE.put(Double.class, Double.BYTES); + SIZEOF_CACHE.put(Vector2f.class, 2 * Float.BYTES); + SIZEOF_CACHE.put(Vector3f.class, 3 * Float.BYTES); + SIZEOF_CACHE.put(Vector4f.class, 4 * Float.BYTES); + SIZEOF_CACHE.put(Matrix4f.class, SIZEOF_CACHE.get(Vector4f.class)); + } } diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/misc/Frame.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/misc/Frame.java index 28ec737..07eb15d 100644 --- a/src/main/java/com/github/hydos/ginger/engine/vulkan/misc/Frame.java +++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/misc/Frame.java @@ -1,47 +1,39 @@ package com.github.hydos.ginger.engine.vulkan.misc; -import java.nio.LongBuffer; - import static org.lwjgl.system.MemoryStack.stackGet; -/** - * Wraps the needed sync objects for an in flight frame - * - * This frame's sync objects must be deleted manually - * */ -public class Frame { +import java.nio.LongBuffer; - private final long imageAvailableSemaphore; - private final long renderFinishedSemaphore; - private final long fence; +/** Wraps the needed sync objects for an in flight frame + * This frame's sync objects must be deleted manually */ +public class Frame +{ + private final long imageAvailableSemaphore; + private final long renderFinishedSemaphore; + private final long fence; - public Frame(long imageAvailableSemaphore, long renderFinishedSemaphore, long fence) { - this.imageAvailableSemaphore = imageAvailableSemaphore; - this.renderFinishedSemaphore = renderFinishedSemaphore; - this.fence = fence; - } + public Frame(long imageAvailableSemaphore, long renderFinishedSemaphore, long fence) + { + this.imageAvailableSemaphore = imageAvailableSemaphore; + this.renderFinishedSemaphore = renderFinishedSemaphore; + this.fence = fence; + } - public long imageAvailableSemaphore() { - return imageAvailableSemaphore; - } + public long imageAvailableSemaphore() + { return imageAvailableSemaphore; } - public LongBuffer pImageAvailableSemaphore() { - return stackGet().longs(imageAvailableSemaphore); - } + public LongBuffer pImageAvailableSemaphore() + { return stackGet().longs(imageAvailableSemaphore); } - public long renderFinishedSemaphore() { - return renderFinishedSemaphore; - } + public long renderFinishedSemaphore() + { return renderFinishedSemaphore; } - public LongBuffer pRenderFinishedSemaphore() { - return stackGet().longs(renderFinishedSemaphore); - } + public LongBuffer pRenderFinishedSemaphore() + { return stackGet().longs(renderFinishedSemaphore); } - public long fence() { - return fence; - } + public long fence() + { return fence; } - public LongBuffer pFence() { - return stackGet().longs(fence); - } + public LongBuffer pFence() + { return stackGet().longs(fence); } } diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/misc/VKModelLoader.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/misc/VKModelLoader.java index 4292495..fc54c9c 100644 --- a/src/main/java/com/github/hydos/ginger/engine/vulkan/misc/VKModelLoader.java +++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/misc/VKModelLoader.java @@ -11,110 +11,93 @@ import org.joml.*; import org.lwjgl.PointerBuffer; import org.lwjgl.assimp.*; -public class VKModelLoader { +public class VKModelLoader +{ + public static VKMesh loadModel(File file, int flags) + { + try (AIScene scene = aiImportFile(file.getAbsolutePath(), flags)) + { + if (scene == null || scene.mRootNode() == null) + { throw new RuntimeException("Could not load model: " + aiGetErrorString()); } + VKMesh model = new VKMesh(); + processNode(scene.mRootNode(), scene, model); + return model; + } + } - public static VKMesh loadModel(File file, int flags) { + private static void processNode(AINode node, AIScene scene, VKMesh model) + { + if (node.mMeshes() != null) + { processNodeMeshes(scene, node, model); } + if (node.mChildren() != null) + { + PointerBuffer children = node.mChildren(); + for (int i = 0; i < node.mNumChildren(); i++) + { processNode(AINode.create(children.get(i)), scene, model); } + } + } - try(AIScene scene = aiImportFile(file.getAbsolutePath(), flags)) { + private static void processNodeMeshes(AIScene scene, AINode node, VKMesh model) + { + PointerBuffer pMeshes = scene.mMeshes(); + IntBuffer meshIndices = node.mMeshes(); + for (int i = 0; i < meshIndices.capacity(); i++) + { + AIMesh mesh = AIMesh.create(pMeshes.get(meshIndices.get(i))); + processMesh(scene, mesh, model); + } + } - if(scene == null || scene.mRootNode() == null) { - throw new RuntimeException("Could not load model: " + aiGetErrorString()); - } + private static void processMesh(AIScene scene, AIMesh mesh, VKMesh model) + { + processPositions(mesh, model.positions); + processTexCoords(mesh, model.texCoords); + processIndices(mesh, model.indices); + } - VKMesh model = new VKMesh(); + private static void processPositions(AIMesh mesh, List positions) + { + AIVector3D.Buffer vertices = requireNonNull(mesh.mVertices()); + for (int i = 0; i < vertices.capacity(); i++) + { + AIVector3D position = vertices.get(i); + positions.add(new Vector3f(position.x(), position.y(), position.z())); + } + } - processNode(scene.mRootNode(), scene, model); + private static void processTexCoords(AIMesh mesh, List texCoords) + { + AIVector3D.Buffer aiTexCoords = requireNonNull(mesh.mTextureCoords(0)); + for (int i = 0; i < aiTexCoords.capacity(); i++) + { + final AIVector3D coords = aiTexCoords.get(i); + texCoords.add(new Vector2f(coords.x(), coords.y())); + } + } - return model; - } - } - - private static void processNode(AINode node, AIScene scene, VKMesh model) { - - if(node.mMeshes() != null) { - processNodeMeshes(scene, node, model); - } - - if(node.mChildren() != null) { - - PointerBuffer children = node.mChildren(); - - for(int i = 0;i < node.mNumChildren();i++) { - processNode(AINode.create(children.get(i)), scene, model); - } - - } - - } - - private static void processNodeMeshes(AIScene scene, AINode node, VKMesh model) { - - PointerBuffer pMeshes = scene.mMeshes(); - IntBuffer meshIndices = node.mMeshes(); - - for(int i = 0;i < meshIndices.capacity();i++) { - AIMesh mesh = AIMesh.create(pMeshes.get(meshIndices.get(i))); - processMesh(scene, mesh, model); - } - - } - - private static void processMesh(AIScene scene, AIMesh mesh, VKMesh model) { - - processPositions(mesh, model.positions); - processTexCoords(mesh, model.texCoords); - - processIndices(mesh, model.indices); - } - - private static void processPositions(AIMesh mesh, List positions) { - - AIVector3D.Buffer vertices = requireNonNull(mesh.mVertices()); - - for(int i = 0;i < vertices.capacity();i++) { - AIVector3D position = vertices.get(i); - positions.add(new Vector3f(position.x(), position.y(), position.z())); - } - - } - - private static void processTexCoords(AIMesh mesh, List texCoords) { - - AIVector3D.Buffer aiTexCoords = requireNonNull(mesh.mTextureCoords(0)); - - for(int i = 0;i < aiTexCoords.capacity();i++) { - final AIVector3D coords = aiTexCoords.get(i); - texCoords.add(new Vector2f(coords.x(), coords.y())); - } - - } - - private static void processIndices(AIMesh mesh, List indices) { - - AIFace.Buffer aiFaces = mesh.mFaces(); - - for(int i = 0;i < mesh.mNumFaces();i++) { - AIFace face = aiFaces.get(i); - IntBuffer pIndices = face.mIndices(); - for(int j = 0;j < face.mNumIndices();j++) { - indices.add(pIndices.get(j)); - } - } - - } - - public static class VKMesh { - - public final List positions; - public final List texCoords; - public final List indices; - - public VKMesh() { - this.positions = new ArrayList<>(); - this.texCoords = new ArrayList<>(); - this.indices = new ArrayList<>(); - } - } + private static void processIndices(AIMesh mesh, List indices) + { + AIFace.Buffer aiFaces = mesh.mFaces(); + for (int i = 0; i < mesh.mNumFaces(); i++) + { + AIFace face = aiFaces.get(i); + IntBuffer pIndices = face.mIndices(); + for (int j = 0; j < face.mNumIndices(); j++) + { indices.add(pIndices.get(j)); } + } + } + public static class VKMesh + { + public final List positions; + public final List texCoords; + public final List indices; + public VKMesh() + { + this.positions = new ArrayList<>(); + this.texCoords = new ArrayList<>(); + this.indices = new ArrayList<>(); + } + } } diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/render/pipelines/VKPipelineManager.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/render/pipelines/VKPipelineManager.java index 52fc559..c98210f 100644 --- a/src/main/java/com/github/hydos/ginger/engine/vulkan/render/pipelines/VKPipelineManager.java +++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/render/pipelines/VKPipelineManager.java @@ -15,156 +15,118 @@ import com.github.hydos.ginger.engine.vulkan.shaders.VKShaderUtils.SPIRV; public class VKPipelineManager { - - public static void createGraphicsPipeline() { - - try(MemoryStack stack = stackPush()) { - SPIRV vertShaderSPIRV = VKShaderUtils.compileShaderFile("vulkan/shaders/entity.vert", VKShaderUtils.ShaderType.VERTEX_SHADER); - SPIRV fragShaderSPIRV = VKShaderUtils.compileShaderFile("vulkan/shaders/entity.frag", VKShaderUtils.ShaderType.FRAGMENT_SHADER); - - long vertShaderModule = VKShaderManager.createShaderModule(vertShaderSPIRV.bytecode()); - long fragShaderModule = VKShaderManager.createShaderModule(fragShaderSPIRV.bytecode()); - - ByteBuffer entryPoint = stack.UTF8("main"); - - VkPipelineShaderStageCreateInfo.Buffer shaderStages = VkPipelineShaderStageCreateInfo.callocStack(2, stack); - - VkPipelineShaderStageCreateInfo vertShaderStageInfo = shaderStages.get(0); - - vertShaderStageInfo.sType(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO); - vertShaderStageInfo.stage(VK_SHADER_STAGE_VERTEX_BIT); - vertShaderStageInfo.module(vertShaderModule); - vertShaderStageInfo.pName(entryPoint); - - VkPipelineShaderStageCreateInfo fragShaderStageInfo = shaderStages.get(1); - - fragShaderStageInfo.sType(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO); - fragShaderStageInfo.stage(VK_SHADER_STAGE_FRAGMENT_BIT); - fragShaderStageInfo.module(fragShaderModule); - fragShaderStageInfo.pName(entryPoint); - - // VERTEX STAGE - - VkPipelineVertexInputStateCreateInfo vertexInputInfo = VkPipelineVertexInputStateCreateInfo.callocStack(stack); - vertexInputInfo.sType(VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO); - vertexInputInfo.pVertexBindingDescriptions(Vertex.getBindingDescription()); - vertexInputInfo.pVertexAttributeDescriptions(Vertex.getAttributeDescriptions()); - - // ASSEMBLY STAGE - - VkPipelineInputAssemblyStateCreateInfo inputAssembly = VkPipelineInputAssemblyStateCreateInfo.callocStack(stack); - inputAssembly.sType(VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO); - inputAssembly.topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); - inputAssembly.primitiveRestartEnable(false); - - // VIEWPORT & SCISSOR - - VkViewport.Buffer viewport = VkViewport.callocStack(1, stack); - viewport.x(0.0f); - viewport.y(0.0f); - viewport.width(VulkanExample.VulkanDemoGinger2.swapChainExtent.width()); - viewport.height(VulkanExample.VulkanDemoGinger2.swapChainExtent.height()); - viewport.minDepth(0.0f); - viewport.maxDepth(1.0f); - - VkRect2D.Buffer scissor = VkRect2D.callocStack(1, stack); - scissor.offset(VkOffset2D.callocStack(stack).set(0, 0)); - scissor.extent(VulkanExample.VulkanDemoGinger2.swapChainExtent); - - VkPipelineViewportStateCreateInfo viewportState = VkPipelineViewportStateCreateInfo.callocStack(stack); - viewportState.sType(VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO); - viewportState.pViewports(viewport); - viewportState.pScissors(scissor); - - // RASTERIZATION STAGE - - VkPipelineRasterizationStateCreateInfo rasterizer = VkPipelineRasterizationStateCreateInfo.callocStack(stack); - rasterizer.sType(VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO); - rasterizer.depthClampEnable(false); - rasterizer.rasterizerDiscardEnable(false); - rasterizer.polygonMode(VK_POLYGON_MODE_FILL); - rasterizer.lineWidth(1.0f); - rasterizer.cullMode(VK_CULL_MODE_BACK_BIT); - rasterizer.frontFace(VK_FRONT_FACE_COUNTER_CLOCKWISE); - rasterizer.depthBiasEnable(false); - - // MULTISAMPLING - - VkPipelineMultisampleStateCreateInfo multisampling = VkPipelineMultisampleStateCreateInfo.callocStack(stack); - multisampling.sType(VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO); - multisampling.sampleShadingEnable(true); - multisampling.minSampleShading(0.2f); // Enable sample shading in the pipeline - multisampling.rasterizationSamples(VulkanExample.VulkanDemoGinger2.msaaSamples); // Min fraction for sample shading; closer to one is smoother - - VkPipelineDepthStencilStateCreateInfo depthStencil = VkPipelineDepthStencilStateCreateInfo.callocStack(stack); - depthStencil.sType(VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO); - depthStencil.depthTestEnable(true); - depthStencil.depthWriteEnable(true); - depthStencil.depthCompareOp(VK_COMPARE_OP_LESS); - depthStencil.depthBoundsTestEnable(false); - depthStencil.minDepthBounds(0.0f); - depthStencil.maxDepthBounds(1.0f); - depthStencil.stencilTestEnable(false); - - // COLOR BLENDING - - VkPipelineColorBlendAttachmentState.Buffer colorBlendAttachment = VkPipelineColorBlendAttachmentState.callocStack(1, stack); - colorBlendAttachment.colorWriteMask(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT); - colorBlendAttachment.blendEnable(false); - - VkPipelineColorBlendStateCreateInfo colorBlending = VkPipelineColorBlendStateCreateInfo.callocStack(stack); - colorBlending.sType(VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO); - colorBlending.logicOpEnable(false); - colorBlending.logicOp(VK_LOGIC_OP_COPY); - colorBlending.pAttachments(colorBlendAttachment); - colorBlending.blendConstants(stack.floats(0.0f, 0.0f, 0.0f, 0.0f)); - - // PIPELINE LAYOUT CREATION - - VkPipelineLayoutCreateInfo pipelineLayoutInfo = VkPipelineLayoutCreateInfo.callocStack(stack); - pipelineLayoutInfo.sType(VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO); - pipelineLayoutInfo.pSetLayouts(stack.longs(VulkanExample.VulkanDemoGinger2.descriptorSetLayout)); - - LongBuffer pPipelineLayout = stack.longs(VK_NULL_HANDLE); - - if(vkCreatePipelineLayout(VulkanExample.VulkanDemoGinger2.device, pipelineLayoutInfo, null, pPipelineLayout) != VK_SUCCESS) { - throw new RuntimeException("Failed to create pipeline layout"); - } - - VulkanExample.VulkanDemoGinger2.pipelineLayout = pPipelineLayout.get(0); - - VkGraphicsPipelineCreateInfo.Buffer pipelineInfo = VkGraphicsPipelineCreateInfo.callocStack(1, stack); - pipelineInfo.sType(VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO); - pipelineInfo.pStages(shaderStages); - pipelineInfo.pVertexInputState(vertexInputInfo); - pipelineInfo.pInputAssemblyState(inputAssembly); - pipelineInfo.pViewportState(viewportState); - pipelineInfo.pRasterizationState(rasterizer); - pipelineInfo.pMultisampleState(multisampling); - pipelineInfo.pDepthStencilState(depthStencil); - pipelineInfo.pColorBlendState(colorBlending); - pipelineInfo.layout(VulkanExample.VulkanDemoGinger2.pipelineLayout); - pipelineInfo.renderPass(VulkanExample.VulkanDemoGinger2.renderPass); - pipelineInfo.subpass(0); - pipelineInfo.basePipelineHandle(VK_NULL_HANDLE); - pipelineInfo.basePipelineIndex(-1); - - LongBuffer pGraphicsPipeline = stack.mallocLong(1); - - if(vkCreateGraphicsPipelines(VulkanExample.VulkanDemoGinger2.device, VK_NULL_HANDLE, pipelineInfo, null, pGraphicsPipeline) != VK_SUCCESS) { - throw new RuntimeException("Failed to create graphics pipeline"); - } - - VulkanExample.VulkanDemoGinger2.graphicsPipeline = pGraphicsPipeline.get(0); - - // Cleanup - - vkDestroyShaderModule(VulkanExample.VulkanDemoGinger2.device, vertShaderModule, null); - vkDestroyShaderModule(VulkanExample.VulkanDemoGinger2.device, fragShaderModule, null); - - vertShaderSPIRV.free(); - fragShaderSPIRV.free(); - } - } - + public static void createGraphicsPipeline() + { + try (MemoryStack stack = stackPush()) + { + SPIRV vertShaderSPIRV = VKShaderUtils.compileShaderFile("vulkan/shaders/entity.vert", VKShaderUtils.ShaderType.VERTEX_SHADER); + SPIRV fragShaderSPIRV = VKShaderUtils.compileShaderFile("vulkan/shaders/entity.frag", VKShaderUtils.ShaderType.FRAGMENT_SHADER); + long vertShaderModule = VKShaderManager.createShaderModule(vertShaderSPIRV.bytecode()); + long fragShaderModule = VKShaderManager.createShaderModule(fragShaderSPIRV.bytecode()); + ByteBuffer entryPoint = stack.UTF8("main"); + VkPipelineShaderStageCreateInfo.Buffer shaderStages = VkPipelineShaderStageCreateInfo.callocStack(2, stack); + VkPipelineShaderStageCreateInfo vertShaderStageInfo = shaderStages.get(0); + vertShaderStageInfo.sType(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO); + vertShaderStageInfo.stage(VK_SHADER_STAGE_VERTEX_BIT); + vertShaderStageInfo.module(vertShaderModule); + vertShaderStageInfo.pName(entryPoint); + VkPipelineShaderStageCreateInfo fragShaderStageInfo = shaderStages.get(1); + fragShaderStageInfo.sType(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO); + fragShaderStageInfo.stage(VK_SHADER_STAGE_FRAGMENT_BIT); + fragShaderStageInfo.module(fragShaderModule); + fragShaderStageInfo.pName(entryPoint); + // VERTEX STAGE + VkPipelineVertexInputStateCreateInfo vertexInputInfo = VkPipelineVertexInputStateCreateInfo.callocStack(stack); + vertexInputInfo.sType(VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO); + vertexInputInfo.pVertexBindingDescriptions(Vertex.getBindingDescription()); + vertexInputInfo.pVertexAttributeDescriptions(Vertex.getAttributeDescriptions()); + // ASSEMBLY STAGE + VkPipelineInputAssemblyStateCreateInfo inputAssembly = VkPipelineInputAssemblyStateCreateInfo.callocStack(stack); + inputAssembly.sType(VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO); + inputAssembly.topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); + inputAssembly.primitiveRestartEnable(false); + // VIEWPORT & SCISSOR + VkViewport.Buffer viewport = VkViewport.callocStack(1, stack); + viewport.x(0.0f); + viewport.y(0.0f); + viewport.width(VulkanExample.VulkanDemoGinger2.swapChainExtent.width()); + viewport.height(VulkanExample.VulkanDemoGinger2.swapChainExtent.height()); + viewport.minDepth(0.0f); + viewport.maxDepth(1.0f); + VkRect2D.Buffer scissor = VkRect2D.callocStack(1, stack); + scissor.offset(VkOffset2D.callocStack(stack).set(0, 0)); + scissor.extent(VulkanExample.VulkanDemoGinger2.swapChainExtent); + VkPipelineViewportStateCreateInfo viewportState = VkPipelineViewportStateCreateInfo.callocStack(stack); + viewportState.sType(VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO); + viewportState.pViewports(viewport); + viewportState.pScissors(scissor); + // RASTERIZATION STAGE + VkPipelineRasterizationStateCreateInfo rasterizer = VkPipelineRasterizationStateCreateInfo.callocStack(stack); + rasterizer.sType(VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO); + rasterizer.depthClampEnable(false); + rasterizer.rasterizerDiscardEnable(false); + rasterizer.polygonMode(VK_POLYGON_MODE_FILL); + rasterizer.lineWidth(1.0f); + rasterizer.cullMode(VK_CULL_MODE_BACK_BIT); + rasterizer.frontFace(VK_FRONT_FACE_COUNTER_CLOCKWISE); + rasterizer.depthBiasEnable(false); + // MULTISAMPLING + VkPipelineMultisampleStateCreateInfo multisampling = VkPipelineMultisampleStateCreateInfo.callocStack(stack); + multisampling.sType(VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO); + multisampling.sampleShadingEnable(true); + multisampling.minSampleShading(0.2f); // Enable sample shading in the pipeline + multisampling.rasterizationSamples(VulkanExample.VulkanDemoGinger2.msaaSamples); // Min fraction for sample shading; closer to one is smoother + VkPipelineDepthStencilStateCreateInfo depthStencil = VkPipelineDepthStencilStateCreateInfo.callocStack(stack); + depthStencil.sType(VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO); + depthStencil.depthTestEnable(true); + depthStencil.depthWriteEnable(true); + depthStencil.depthCompareOp(VK_COMPARE_OP_LESS); + depthStencil.depthBoundsTestEnable(false); + depthStencil.minDepthBounds(0.0f); + depthStencil.maxDepthBounds(1.0f); + depthStencil.stencilTestEnable(false); + // COLOR BLENDING + VkPipelineColorBlendAttachmentState.Buffer colorBlendAttachment = VkPipelineColorBlendAttachmentState.callocStack(1, stack); + colorBlendAttachment.colorWriteMask(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT); + colorBlendAttachment.blendEnable(false); + VkPipelineColorBlendStateCreateInfo colorBlending = VkPipelineColorBlendStateCreateInfo.callocStack(stack); + colorBlending.sType(VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO); + colorBlending.logicOpEnable(false); + colorBlending.logicOp(VK_LOGIC_OP_COPY); + colorBlending.pAttachments(colorBlendAttachment); + colorBlending.blendConstants(stack.floats(0.0f, 0.0f, 0.0f, 0.0f)); + // PIPELINE LAYOUT CREATION + VkPipelineLayoutCreateInfo pipelineLayoutInfo = VkPipelineLayoutCreateInfo.callocStack(stack); + pipelineLayoutInfo.sType(VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO); + pipelineLayoutInfo.pSetLayouts(stack.longs(VulkanExample.VulkanDemoGinger2.descriptorSetLayout)); + LongBuffer pPipelineLayout = stack.longs(VK_NULL_HANDLE); + if (vkCreatePipelineLayout(VulkanExample.VulkanDemoGinger2.device, pipelineLayoutInfo, null, pPipelineLayout) != VK_SUCCESS) + { throw new RuntimeException("Failed to create pipeline layout"); } + VulkanExample.VulkanDemoGinger2.pipelineLayout = pPipelineLayout.get(0); + VkGraphicsPipelineCreateInfo.Buffer pipelineInfo = VkGraphicsPipelineCreateInfo.callocStack(1, stack); + pipelineInfo.sType(VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO); + pipelineInfo.pStages(shaderStages); + pipelineInfo.pVertexInputState(vertexInputInfo); + pipelineInfo.pInputAssemblyState(inputAssembly); + pipelineInfo.pViewportState(viewportState); + pipelineInfo.pRasterizationState(rasterizer); + pipelineInfo.pMultisampleState(multisampling); + pipelineInfo.pDepthStencilState(depthStencil); + pipelineInfo.pColorBlendState(colorBlending); + pipelineInfo.layout(VulkanExample.VulkanDemoGinger2.pipelineLayout); + pipelineInfo.renderPass(VulkanExample.VulkanDemoGinger2.renderPass); + pipelineInfo.subpass(0); + pipelineInfo.basePipelineHandle(VK_NULL_HANDLE); + pipelineInfo.basePipelineIndex(-1); + LongBuffer pGraphicsPipeline = stack.mallocLong(1); + if (vkCreateGraphicsPipelines(VulkanExample.VulkanDemoGinger2.device, VK_NULL_HANDLE, pipelineInfo, null, pGraphicsPipeline) != VK_SUCCESS) + { throw new RuntimeException("Failed to create graphics pipeline"); } + VulkanExample.VulkanDemoGinger2.graphicsPipeline = pGraphicsPipeline.get(0); + // Cleanup + vkDestroyShaderModule(VulkanExample.VulkanDemoGinger2.device, vertShaderModule, null); + vkDestroyShaderModule(VulkanExample.VulkanDemoGinger2.device, fragShaderModule, null); + vertShaderSPIRV.free(); + fragShaderSPIRV.free(); + } + } } diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/render/renderers/VKRenderManager.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/render/renderers/VKRenderManager.java index bfbfda9..4c93b9d 100644 --- a/src/main/java/com/github/hydos/ginger/engine/vulkan/render/renderers/VKRenderManager.java +++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/render/renderers/VKRenderManager.java @@ -1,9 +1,8 @@ package com.github.hydos.ginger.engine.vulkan.render.renderers; -/** - * used to manage all the renderers and shaders to go with them - * @author hydos - * - */ + +/** used to manage all the renderers and shaders to go with them + * + * @author hydos */ public class VKRenderManager { } diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/shaders/VKShaderManager.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/shaders/VKShaderManager.java index 2124627..fbbaa65 100644 --- a/src/main/java/com/github/hydos/ginger/engine/vulkan/shaders/VKShaderManager.java +++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/shaders/VKShaderManager.java @@ -10,31 +10,22 @@ import org.lwjgl.vulkan.VkShaderModuleCreateInfo; import com.github.hydos.ginger.VulkanExample; -/** - * will be used in the future to manage multiple shaders - * @author hydos - * - */ +/** will be used in the future to manage multiple shaders + * + * @author hydos */ public class VKShaderManager { - public static long createShaderModule(ByteBuffer spirvCode) { - - try(MemoryStack stack = stackPush()) { - - VkShaderModuleCreateInfo createInfo = VkShaderModuleCreateInfo.callocStack(stack); - - createInfo.sType(VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO); - createInfo.pCode(spirvCode); - - LongBuffer pShaderModule = stack.mallocLong(1); - - if(vkCreateShaderModule(VulkanExample.VulkanDemoGinger2.device, createInfo, null, pShaderModule) != VK_SUCCESS) { - throw new RuntimeException("Failed to create shader module"); - } - - return pShaderModule.get(0); - } - } - - + public static long createShaderModule(ByteBuffer spirvCode) + { + try (MemoryStack stack = stackPush()) + { + VkShaderModuleCreateInfo createInfo = VkShaderModuleCreateInfo.callocStack(stack); + createInfo.sType(VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO); + createInfo.pCode(spirvCode); + LongBuffer pShaderModule = stack.mallocLong(1); + if (vkCreateShaderModule(VulkanExample.VulkanDemoGinger2.device, createInfo, null, pShaderModule) != VK_SUCCESS) + { throw new RuntimeException("Failed to create shader module"); } + return pShaderModule.get(0); + } + } } diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/shaders/VKShaderUtils.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/shaders/VKShaderUtils.java index 6a73fe6..437e584 100644 --- a/src/main/java/com/github/hydos/ginger/engine/vulkan/shaders/VKShaderUtils.java +++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/shaders/VKShaderUtils.java @@ -1,89 +1,80 @@ package com.github.hydos.ginger.engine.vulkan.shaders; -import org.lwjgl.system.NativeResource; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.ByteBuffer; -import java.nio.file.Files; -import java.nio.file.Paths; - import static java.lang.ClassLoader.getSystemClassLoader; import static org.lwjgl.system.MemoryUtil.NULL; import static org.lwjgl.util.shaderc.Shaderc.*; -public class VKShaderUtils { +import java.io.IOException; +import java.net.*; +import java.nio.ByteBuffer; +import java.nio.file.*; - public static SPIRV compileShaderFile(String shaderFile, ShaderType shaderKind) { - return compileShaderAbsoluteFile(getSystemClassLoader().getResource(shaderFile).toExternalForm(), shaderKind); - } +import org.lwjgl.system.NativeResource; - public static SPIRV compileShaderAbsoluteFile(String shaderFile, ShaderType shaderKind) { - try { - String source = new String(Files.readAllBytes(Paths.get(new URI(shaderFile)))); - return compileShader(shaderFile, source, shaderKind); - } catch (IOException | URISyntaxException e) { - e.printStackTrace(); - } - return null; - } +public class VKShaderUtils +{ + public static SPIRV compileShaderFile(String shaderFile, ShaderType shaderKind) + { return compileShaderAbsoluteFile(getSystemClassLoader().getResource(shaderFile).toExternalForm(), shaderKind); } - public static SPIRV compileShader(String filename, String source, ShaderType shaderKind) { + public static SPIRV compileShaderAbsoluteFile(String shaderFile, ShaderType shaderKind) + { + try + { + String source = new String(Files.readAllBytes(Paths.get(new URI(shaderFile)))); + return compileShader(shaderFile, source, shaderKind); + } + catch (IOException | URISyntaxException e) + { + e.printStackTrace(); + } + return null; + } - long compiler = shaderc_compiler_initialize(); + public static SPIRV compileShader(String filename, String source, ShaderType shaderKind) + { + long compiler = shaderc_compiler_initialize(); + if (compiler == NULL) + { throw new RuntimeException("Failed to create shader compiler"); } + long result = shaderc_compile_into_spv(compiler, source, shaderKind.kind, filename, "main", NULL); + if (result == NULL) + { throw new RuntimeException("Failed to compile shader " + filename + " into SPIR-V"); } + if (shaderc_result_get_compilation_status(result) != shaderc_compilation_status_success) + { throw new RuntimeException("Failed to compile shader " + filename + "into SPIR-V:\n " + shaderc_result_get_error_message(result)); } + shaderc_compiler_release(compiler); + return new SPIRV(result, shaderc_result_get_bytes(result)); + } - if(compiler == NULL) { - throw new RuntimeException("Failed to create shader compiler"); - } + public enum ShaderType + { + VERTEX_SHADER(shaderc_glsl_vertex_shader), + GEOMETRY_SHADER(shaderc_glsl_geometry_shader), + FRAGMENT_SHADER(shaderc_glsl_fragment_shader); - long result = shaderc_compile_into_spv(compiler, source, shaderKind.kind, filename, "main", NULL); + private final int kind; - if(result == NULL) { - throw new RuntimeException("Failed to compile shader " + filename + " into SPIR-V"); - } + ShaderType(int kind) + { this.kind = kind; } + } - if(shaderc_result_get_compilation_status(result) != shaderc_compilation_status_success) { - throw new RuntimeException("Failed to compile shader " + filename + "into SPIR-V:\n " + shaderc_result_get_error_message(result)); - } + public static final class SPIRV implements NativeResource + { + private final long handle; + private ByteBuffer bytecode; - shaderc_compiler_release(compiler); + public SPIRV(long handle, ByteBuffer bytecode) + { + this.handle = handle; + this.bytecode = bytecode; + } - return new SPIRV(result, shaderc_result_get_bytes(result)); - } - - public enum ShaderType { - - VERTEX_SHADER(shaderc_glsl_vertex_shader), - GEOMETRY_SHADER(shaderc_glsl_geometry_shader), - FRAGMENT_SHADER(shaderc_glsl_fragment_shader); - - private final int kind; - - ShaderType(int kind) { - this.kind = kind; - } - } - - public static final class SPIRV implements NativeResource { - - private final long handle; - private ByteBuffer bytecode; - - public SPIRV(long handle, ByteBuffer bytecode) { - this.handle = handle; - this.bytecode = bytecode; - } - - public ByteBuffer bytecode() { - return bytecode; - } - - @Override - public void free() { - shaderc_result_release(handle); - bytecode = null; // Help the GC - } - } + public ByteBuffer bytecode() + { return bytecode; } + @Override + public void free() + { + shaderc_result_release(handle); + bytecode = null; // Help the GC + } + } } diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/swapchain/VKSwapchainManager.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/swapchain/VKSwapchainManager.java index c80ab8f..22f270f 100644 --- a/src/main/java/com/github/hydos/ginger/engine/vulkan/swapchain/VKSwapchainManager.java +++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/swapchain/VKSwapchainManager.java @@ -19,143 +19,107 @@ import com.github.hydos.ginger.engine.vulkan.render.pipelines.VKPipelineManager; public class VKSwapchainManager { - - public static void cleanupSwapChain() { + public static void cleanupSwapChain() + { + vkDestroyImageView(VulkanDemoGinger2.device, VulkanDemoGinger2.colorImageView, null); + vkDestroyImage(VulkanDemoGinger2.device, VulkanDemoGinger2.colorImage, null); + vkFreeMemory(VulkanDemoGinger2.device, VulkanDemoGinger2.colorImageMemory, null); + vkDestroyImageView(VulkanDemoGinger2.device, VulkanDemoGinger2.depthImageView, null); + vkDestroyImage(VulkanDemoGinger2.device, VulkanDemoGinger2.depthImage, null); + vkFreeMemory(VulkanDemoGinger2.device, VulkanDemoGinger2.depthImageMemory, null); + VulkanDemoGinger2.uniformBuffers.forEach(ubo -> vkDestroyBuffer(VulkanDemoGinger2.device, ubo, null)); + VulkanDemoGinger2.uniformBuffersMemory.forEach(uboMemory -> vkFreeMemory(VulkanDemoGinger2.device, uboMemory, null)); + vkDestroyDescriptorPool(VulkanDemoGinger2.device, VulkanDemoGinger2.descriptorPool, null); + VulkanDemoGinger2.swapChainFramebuffers.forEach(framebuffer -> vkDestroyFramebuffer(VulkanDemoGinger2.device, framebuffer, null)); + vkFreeCommandBuffers(VulkanDemoGinger2.device, VulkanDemoGinger2.commandPool, VulkanDemoGinger2.asPointerBuffer(VulkanDemoGinger2.commandBuffers)); + vkDestroyPipeline(VulkanDemoGinger2.device, VulkanDemoGinger2.graphicsPipeline, null); + vkDestroyPipelineLayout(VulkanDemoGinger2.device, VulkanDemoGinger2.pipelineLayout, null); + vkDestroyRenderPass(VulkanDemoGinger2.device, VulkanDemoGinger2.renderPass, null); + VulkanDemoGinger2.swapChainImageViews.forEach(imageView -> vkDestroyImageView(VulkanDemoGinger2.device, imageView, null)); + vkDestroySwapchainKHR(VulkanDemoGinger2.device, VulkanDemoGinger2.swapChain, null); + } - vkDestroyImageView(VulkanDemoGinger2.device, VulkanDemoGinger2.colorImageView, null); - vkDestroyImage(VulkanDemoGinger2.device, VulkanDemoGinger2.colorImage, null); - vkFreeMemory(VulkanDemoGinger2.device, VulkanDemoGinger2.colorImageMemory, null); + public static void recreateSwapChain() + { + try (MemoryStack stack = stackPush()) + { + IntBuffer width = stack.ints(0); + IntBuffer height = stack.ints(0); + while (width.get(0) == 0 && height.get(0) == 0) + { + glfwGetFramebufferSize(Window.getWindow(), width, height); + glfwWaitEvents(); + } + } + vkDeviceWaitIdle(VulkanDemoGinger2.device); + VKSwapchainManager.cleanupSwapChain(); + createSwapChainObjects(); + } - vkDestroyImageView(VulkanDemoGinger2.device, VulkanDemoGinger2.depthImageView, null); - vkDestroyImage(VulkanDemoGinger2.device, VulkanDemoGinger2.depthImage, null); - vkFreeMemory(VulkanDemoGinger2.device, VulkanDemoGinger2.depthImageMemory, null); + public static void createSwapChain() + { + try (MemoryStack stack = stackPush()) + { + SwapChainSupportDetails swapChainSupport = VulkanDemoGinger2.querySwapChainSupport(VulkanDemoGinger2.physicalDevice, stack); + VkSurfaceFormatKHR surfaceFormat = VulkanDemoGinger2.chooseSwapSurfaceFormat(swapChainSupport.formats); + int presentMode = VulkanDemoGinger2.chooseSwapPresentMode(swapChainSupport.presentModes); + VkExtent2D extent = VulkanDemoGinger2.chooseSwapExtent(swapChainSupport.capabilities); + IntBuffer imageCount = stack.ints(swapChainSupport.capabilities.minImageCount() + 1); + if (swapChainSupport.capabilities.maxImageCount() > 0 && imageCount.get(0) > swapChainSupport.capabilities.maxImageCount()) + { imageCount.put(0, swapChainSupport.capabilities.maxImageCount()); } + VkSwapchainCreateInfoKHR createInfo = VkSwapchainCreateInfoKHR.callocStack(stack); + createInfo.sType(VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR); + createInfo.surface(VulkanDemoGinger2.surface); + // Image settings + createInfo.minImageCount(imageCount.get(0)); + createInfo.imageFormat(surfaceFormat.format()); + createInfo.imageColorSpace(surfaceFormat.colorSpace()); + createInfo.imageExtent(extent); + createInfo.imageArrayLayers(1); + createInfo.imageUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); + QueueFamilyIndices indices = VulkanDemoGinger2.findQueueFamilies(VulkanDemoGinger2.physicalDevice); + if (!indices.graphicsFamily.equals(indices.presentFamily)) + { + createInfo.imageSharingMode(VK_SHARING_MODE_CONCURRENT); + createInfo.pQueueFamilyIndices(stack.ints(indices.graphicsFamily, indices.presentFamily)); + } + else + { + createInfo.imageSharingMode(VK_SHARING_MODE_EXCLUSIVE); + } + createInfo.preTransform(swapChainSupport.capabilities.currentTransform()); + createInfo.compositeAlpha(VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR); + createInfo.presentMode(presentMode); + createInfo.clipped(true); + createInfo.oldSwapchain(VK_NULL_HANDLE); + LongBuffer pSwapChain = stack.longs(VK_NULL_HANDLE); + if (vkCreateSwapchainKHR(VulkanDemoGinger2.device, createInfo, null, pSwapChain) != VK_SUCCESS) + { throw new RuntimeException("Failed to create swap chain"); } + VulkanDemoGinger2.swapChain = pSwapChain.get(0); + vkGetSwapchainImagesKHR(VulkanDemoGinger2.device, VulkanDemoGinger2.swapChain, imageCount, null); + LongBuffer pSwapchainImages = stack.mallocLong(imageCount.get(0)); + vkGetSwapchainImagesKHR(VulkanDemoGinger2.device, VulkanDemoGinger2.swapChain, imageCount, pSwapchainImages); + VulkanDemoGinger2.swapChainImages = new ArrayList<>(imageCount.get(0)); + for (int i = 0; i < pSwapchainImages.capacity(); i++) + { VulkanDemoGinger2.swapChainImages.add(pSwapchainImages.get(i)); } + VulkanDemoGinger2.swapChainImageFormat = surfaceFormat.format(); + VulkanDemoGinger2.swapChainExtent = VkExtent2D.create().set(extent); + } + } - VulkanDemoGinger2.uniformBuffers.forEach(ubo -> vkDestroyBuffer(VulkanDemoGinger2.device, ubo, null)); - VulkanDemoGinger2.uniformBuffersMemory.forEach(uboMemory -> vkFreeMemory(VulkanDemoGinger2.device, uboMemory, null)); - - vkDestroyDescriptorPool(VulkanDemoGinger2.device, VulkanDemoGinger2.descriptorPool, null); - - VulkanDemoGinger2.swapChainFramebuffers.forEach(framebuffer -> vkDestroyFramebuffer(VulkanDemoGinger2.device, framebuffer, null)); - - vkFreeCommandBuffers(VulkanDemoGinger2.device, VulkanDemoGinger2.commandPool, VulkanDemoGinger2.asPointerBuffer(VulkanDemoGinger2.commandBuffers)); - - vkDestroyPipeline(VulkanDemoGinger2.device, VulkanDemoGinger2.graphicsPipeline, null); - - vkDestroyPipelineLayout(VulkanDemoGinger2.device, VulkanDemoGinger2.pipelineLayout, null); - - vkDestroyRenderPass(VulkanDemoGinger2.device, VulkanDemoGinger2.renderPass, null); - - VulkanDemoGinger2.swapChainImageViews.forEach(imageView -> vkDestroyImageView(VulkanDemoGinger2.device, imageView, null)); - - vkDestroySwapchainKHR(VulkanDemoGinger2.device, VulkanDemoGinger2.swapChain, null); - } - - public static void recreateSwapChain() { - - try(MemoryStack stack = stackPush()) { - - IntBuffer width = stack.ints(0); - IntBuffer height = stack.ints(0); - - while(width.get(0) == 0 && height.get(0) == 0) { - glfwGetFramebufferSize(Window.getWindow(), width, height); - glfwWaitEvents(); - } - } - - vkDeviceWaitIdle(VulkanDemoGinger2.device); - - VKSwapchainManager.cleanupSwapChain(); - - createSwapChainObjects(); - } - - public static void createSwapChain() { - - try(MemoryStack stack = stackPush()) { - - SwapChainSupportDetails swapChainSupport = VulkanDemoGinger2.querySwapChainSupport(VulkanDemoGinger2.physicalDevice, stack); - - VkSurfaceFormatKHR surfaceFormat = VulkanDemoGinger2.chooseSwapSurfaceFormat(swapChainSupport.formats); - int presentMode = VulkanDemoGinger2.chooseSwapPresentMode(swapChainSupport.presentModes); - VkExtent2D extent = VulkanDemoGinger2.chooseSwapExtent(swapChainSupport.capabilities); - - IntBuffer imageCount = stack.ints(swapChainSupport.capabilities.minImageCount() + 1); - - if(swapChainSupport.capabilities.maxImageCount() > 0 && imageCount.get(0) > swapChainSupport.capabilities.maxImageCount()) { - imageCount.put(0, swapChainSupport.capabilities.maxImageCount()); - } - - VkSwapchainCreateInfoKHR createInfo = VkSwapchainCreateInfoKHR.callocStack(stack); - - createInfo.sType(VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR); - createInfo.surface(VulkanDemoGinger2.surface); - - // Image settings - createInfo.minImageCount(imageCount.get(0)); - createInfo.imageFormat(surfaceFormat.format()); - createInfo.imageColorSpace(surfaceFormat.colorSpace()); - createInfo.imageExtent(extent); - createInfo.imageArrayLayers(1); - createInfo.imageUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); - - QueueFamilyIndices indices = VulkanDemoGinger2.findQueueFamilies(VulkanDemoGinger2.physicalDevice); - - if(!indices.graphicsFamily.equals(indices.presentFamily)) { - createInfo.imageSharingMode(VK_SHARING_MODE_CONCURRENT); - createInfo.pQueueFamilyIndices(stack.ints(indices.graphicsFamily, indices.presentFamily)); - } else { - createInfo.imageSharingMode(VK_SHARING_MODE_EXCLUSIVE); - } - - createInfo.preTransform(swapChainSupport.capabilities.currentTransform()); - createInfo.compositeAlpha(VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR); - createInfo.presentMode(presentMode); - createInfo.clipped(true); - - createInfo.oldSwapchain(VK_NULL_HANDLE); - - LongBuffer pSwapChain = stack.longs(VK_NULL_HANDLE); - - if(vkCreateSwapchainKHR(VulkanDemoGinger2.device, createInfo, null, pSwapChain) != VK_SUCCESS) { - throw new RuntimeException("Failed to create swap chain"); - } - - VulkanDemoGinger2.swapChain = pSwapChain.get(0); - - vkGetSwapchainImagesKHR(VulkanDemoGinger2.device, VulkanDemoGinger2.swapChain, imageCount, null); - - LongBuffer pSwapchainImages = stack.mallocLong(imageCount.get(0)); - - vkGetSwapchainImagesKHR(VulkanDemoGinger2.device, VulkanDemoGinger2.swapChain, imageCount, pSwapchainImages); - - VulkanDemoGinger2.swapChainImages = new ArrayList<>(imageCount.get(0)); - - for(int i = 0;i < pSwapchainImages.capacity();i++) { - VulkanDemoGinger2.swapChainImages.add(pSwapchainImages.get(i)); - } - - VulkanDemoGinger2.swapChainImageFormat = surfaceFormat.format(); - VulkanDemoGinger2.swapChainExtent = VkExtent2D.create().set(extent); - } - } - - - /** - * i tried organising it but if i change the order everything breaks - */ - public static void createSwapChainObjects() { - createSwapChain(); - VulkanDemoGinger2.createImageViews(); - VulkanDemoGinger2.createRenderPass(); - VKPipelineManager.createGraphicsPipeline(); - VulkanDemoGinger2.createColorResources(); - VulkanDemoGinger2.createDepthResources(); - VulkanDemoGinger2.createFramebuffers(); - VulkanDemoGinger2.createUniformBuffers(); - VulkanDemoGinger2.createDescriptorPool(); - VulkanDemoGinger2.createDescriptorSets(); - VulkanDemoGinger2.createCommandBuffers(); - } - + /** i tried organising it but if i change the order everything breaks */ + public static void createSwapChainObjects() + { + createSwapChain(); + VulkanDemoGinger2.createImageViews(); + VulkanDemoGinger2.createRenderPass(); + VKPipelineManager.createGraphicsPipeline(); + VulkanDemoGinger2.createColorResources(); + VulkanDemoGinger2.createDepthResources(); + VulkanDemoGinger2.createFramebuffers(); + VulkanDemoGinger2.createUniformBuffers(); + VulkanDemoGinger2.createDescriptorPool(); + VulkanDemoGinger2.createDescriptorSets(); + VulkanDemoGinger2.createCommandBuffers(); + } } diff --git a/src/main/java/tk/valoeghese/gateways/client/io/InitialPressHandler.java b/src/main/java/tk/valoeghese/gateways/client/io/InitialPressHandler.java index 979cebb..bf021f5 100644 --- a/src/main/java/tk/valoeghese/gateways/client/io/InitialPressHandler.java +++ b/src/main/java/tk/valoeghese/gateways/client/io/InitialPressHandler.java @@ -1,8 +1,6 @@ package tk.valoeghese.gateways.client.io; -/** - * Author: Valoeghese - */ +/** Author: Valoeghese */ public final class InitialPressHandler implements KeyListener { private boolean activatedPreviously = false; diff --git a/src/main/java/tk/valoeghese/gateways/client/io/Input.java b/src/main/java/tk/valoeghese/gateways/client/io/Input.java index 2f46b79..fe029cf 100644 --- a/src/main/java/tk/valoeghese/gateways/client/io/Input.java +++ b/src/main/java/tk/valoeghese/gateways/client/io/Input.java @@ -2,9 +2,7 @@ package tk.valoeghese.gateways.client.io; import java.util.*; -/** - * Author: Valoeghese - */ +/** Author: Valoeghese */ public class Input { private static final Map> CALLBACKS = new HashMap<>(); diff --git a/src/main/java/tk/valoeghese/gateways/client/io/KeyCallback.java b/src/main/java/tk/valoeghese/gateways/client/io/KeyCallback.java index bdf0234..7874a40 100644 --- a/src/main/java/tk/valoeghese/gateways/client/io/KeyCallback.java +++ b/src/main/java/tk/valoeghese/gateways/client/io/KeyCallback.java @@ -1,8 +1,6 @@ package tk.valoeghese.gateways.client.io; -/** - * Author: Valoeghese - */ +/** Author: Valoeghese */ public interface KeyCallback { public void onCallback(); diff --git a/src/main/java/tk/valoeghese/gateways/client/io/KeyCallbackHandler.java b/src/main/java/tk/valoeghese/gateways/client/io/KeyCallbackHandler.java index 2335900..8369ce7 100644 --- a/src/main/java/tk/valoeghese/gateways/client/io/KeyCallbackHandler.java +++ b/src/main/java/tk/valoeghese/gateways/client/io/KeyCallbackHandler.java @@ -2,9 +2,7 @@ package tk.valoeghese.gateways.client.io; import org.lwjgl.glfw.*; -/** - * Author: Valoeghese - */ +/** Author: Valoeghese */ public class KeyCallbackHandler extends GLFWKeyCallback { private static final KeyCallbackHandler INSTANCE = new KeyCallbackHandler(); diff --git a/src/main/java/tk/valoeghese/gateways/client/io/KeyListener.java b/src/main/java/tk/valoeghese/gateways/client/io/KeyListener.java index 6d69222..4f9c233 100644 --- a/src/main/java/tk/valoeghese/gateways/client/io/KeyListener.java +++ b/src/main/java/tk/valoeghese/gateways/client/io/KeyListener.java @@ -1,8 +1,6 @@ package tk.valoeghese.gateways.client.io; -/** - * Author: Valoeghese - */ +/** Author: Valoeghese */ public interface KeyListener { public void listen(boolean active); diff --git a/src/main/java/tk/valoeghese/gateways/client/io/Keybind.java b/src/main/java/tk/valoeghese/gateways/client/io/Keybind.java index 4dd0014..ad18499 100644 --- a/src/main/java/tk/valoeghese/gateways/client/io/Keybind.java +++ b/src/main/java/tk/valoeghese/gateways/client/io/Keybind.java @@ -2,9 +2,7 @@ package tk.valoeghese.gateways.client.io; import org.lwjgl.glfw.GLFW; -/** - * Author: Valoeghese - */ +/** Author: Valoeghese */ public enum Keybind { MOVE_FORWARD(GLFW.GLFW_KEY_W, false), // Move the player forward relative to its facing direction @@ -15,15 +13,15 @@ public enum Keybind FLY_DOWN(GLFW.GLFW_KEY_LEFT_SHIFT, false), // Move the player downward BREAK(GLFW.GLFW_MOUSE_BUTTON_1, true), // Place a block in front of the player PLACE(GLFW.GLFW_MOUSE_BUTTON_2, true), // Break the block in front of the player - SLOT_1(GLFW.GLFW_KEY_1, false), // Select the first item slot in the toolbar - SLOT_2(GLFW.GLFW_KEY_2, false), // Select the second item slot in the toolbar - SLOT_3(GLFW.GLFW_KEY_3, false), // Select the third item slot in the toolbar - SLOT_4(GLFW.GLFW_KEY_4, false), // Select the fourth item slot in the toolbar - SLOT_5(GLFW.GLFW_KEY_5, false), // Select the fifth item slot in the toolbar - SLOT_6(GLFW.GLFW_KEY_6, false), // Select the sixth item slot in the toolbar - SLOT_7(GLFW.GLFW_KEY_7, false), // Select the seventh item slot in the toolbar - SLOT_8(GLFW.GLFW_KEY_8, false), // Select the eighth item slot in the toolbar - SLOT_9(GLFW.GLFW_KEY_9, false), // Select the ninth item slot in the toolbar + SLOT_1(GLFW.GLFW_KEY_1, false), // Select the first item slot in the toolbar + SLOT_2(GLFW.GLFW_KEY_2, false), // Select the second item slot in the toolbar + SLOT_3(GLFW.GLFW_KEY_3, false), // Select the third item slot in the toolbar + SLOT_4(GLFW.GLFW_KEY_4, false), // Select the fourth item slot in the toolbar + SLOT_5(GLFW.GLFW_KEY_5, false), // Select the fifth item slot in the toolbar + SLOT_6(GLFW.GLFW_KEY_6, false), // Select the sixth item slot in the toolbar + SLOT_7(GLFW.GLFW_KEY_7, false), // Select the seventh item slot in the toolbar + SLOT_8(GLFW.GLFW_KEY_8, false), // Select the eighth item slot in the toolbar + SLOT_9(GLFW.GLFW_KEY_9, false), // Select the ninth item slot in the toolbar SLOT_10(GLFW.GLFW_KEY_0, false), // Select the tenth item slot in the toolbar EXIT(GLFW.GLFW_KEY_ESCAPE, false), // Save and exit the game // (Open the pause menu later) DEBUG(GLFW.GLFW_KEY_F3, false), // Toggle debug text onscreen diff --git a/src/main/java/tk/valoeghese/gateways/client/io/MouseCallbackHandler.java b/src/main/java/tk/valoeghese/gateways/client/io/MouseCallbackHandler.java index 7b420d6..6df1130 100644 --- a/src/main/java/tk/valoeghese/gateways/client/io/MouseCallbackHandler.java +++ b/src/main/java/tk/valoeghese/gateways/client/io/MouseCallbackHandler.java @@ -2,9 +2,7 @@ package tk.valoeghese.gateways.client.io; import org.lwjgl.glfw.*; -/** - * Author: Valoeghese - */ +/** Author: Valoeghese */ public class MouseCallbackHandler extends GLFWMouseButtonCallback { private static final MouseCallbackHandler INSTANCE = new MouseCallbackHandler(); diff --git a/src/main/java/tk/valoeghese/sod/BaseDataSection.java b/src/main/java/tk/valoeghese/sod/BaseDataSection.java index 0a4fe63..4571683 100644 --- a/src/main/java/tk/valoeghese/sod/BaseDataSection.java +++ b/src/main/java/tk/valoeghese/sod/BaseDataSection.java @@ -1,9 +1,8 @@ package tk.valoeghese.sod; -interface BaseDataSection extends Iterable { - /** - * @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. - */ +interface BaseDataSection extends Iterable +{ + /** @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. */ @Deprecated void writeForParser(T data); } diff --git a/src/main/java/tk/valoeghese/sod/BinaryData.java b/src/main/java/tk/valoeghese/sod/BinaryData.java index a391cff..e119636 100644 --- a/src/main/java/tk/valoeghese/sod/BinaryData.java +++ b/src/main/java/tk/valoeghese/sod/BinaryData.java @@ -6,62 +6,55 @@ import java.util.*; import tk.valoeghese.sod.exception.SODParseException; @SuppressWarnings("rawtypes") -public class BinaryData implements Iterable> { - public BinaryData() { - this.sections = new HashMap<>(); - } +public class BinaryData implements Iterable> +{ + public BinaryData() + { this.sections = new HashMap<>(); } private final Map sections; - public DataSection get(String name) { - return (DataSection) this.sections.get(name); - } + public DataSection get(String name) + { return (DataSection) this.sections.get(name); } - public ByteArrayDataSection getByteArray(String name) { - return (ByteArrayDataSection) this.sections.get(name); - } + public ByteArrayDataSection getByteArray(String name) + { return (ByteArrayDataSection) this.sections.get(name); } - public ShortArrayDataSection getShortArray(String name) { - return (ShortArrayDataSection) this.sections.get(name); - } + public ShortArrayDataSection getShortArray(String name) + { return (ShortArrayDataSection) this.sections.get(name); } - public IntArrayDataSection getIntArray(String name) { - return (IntArrayDataSection) this.sections.get(name); - } + public IntArrayDataSection getIntArray(String name) + { return (IntArrayDataSection) this.sections.get(name); } - public LongArrayDataSection getLongArray(String name) { - return (LongArrayDataSection) this.sections.get(name); - } + public LongArrayDataSection getLongArray(String name) + { return (LongArrayDataSection) this.sections.get(name); } - public FloatArrayDataSection getFloatArray(String name) { - return (FloatArrayDataSection) this.sections.get(name); - } + public FloatArrayDataSection getFloatArray(String name) + { return (FloatArrayDataSection) this.sections.get(name); } - public DoubleArrayDataSection getDoubleArray(String name) { - return (DoubleArrayDataSection) this.sections.get(name); - } + public DoubleArrayDataSection getDoubleArray(String name) + { return (DoubleArrayDataSection) this.sections.get(name); } - public StringArrayDataSection getStringArray(String name) { - return (StringArrayDataSection) this.sections.get(name); - } + public StringArrayDataSection getStringArray(String name) + { return (StringArrayDataSection) this.sections.get(name); } - public DataSection getOrCreate(String name) { - return (DataSection) this.sections.computeIfAbsent(name, k -> new DataSection()); - } + public DataSection getOrCreate(String name) + { return (DataSection) this.sections.computeIfAbsent(name, k -> new DataSection()); } - public void put(String name, BaseDataSection section) { - this.sections.put(name, section); - } + public void put(String name, BaseDataSection section) + { this.sections.put(name, section); } - public boolean containsSection(String name) { - return this.sections.containsKey(name); - } + public boolean containsSection(String name) + { return this.sections.containsKey(name); } - public boolean write(File file) { - try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(file))) { + public boolean write(File file) + { + try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(file))) + { Parser.write(this, dos); return true; - } catch (IOException e) { + } + catch (IOException e) + { e.printStackTrace(); return false; } @@ -76,11 +69,8 @@ public class BinaryData implements Iterable> try (DataInputStream dis = new DataInputStream(new FileInputStream(file))) { long magic = dis.readLong(); - - if (magic != 0xA77D1E) { - throw new SODParseException("Not a valid SOD file!"); - } - + if (magic != 0xA77D1E) + { throw new SODParseException("Not a valid SOD file!"); } return Parser.parse(dis); } catch (IOException e) diff --git a/src/main/java/tk/valoeghese/sod/ByteArrayDataSection.java b/src/main/java/tk/valoeghese/sod/ByteArrayDataSection.java index 5ac7ecd..3a0308f 100644 --- a/src/main/java/tk/valoeghese/sod/ByteArrayDataSection.java +++ b/src/main/java/tk/valoeghese/sod/ByteArrayDataSection.java @@ -4,40 +4,38 @@ import java.util.Iterator; import it.unimi.dsi.fastutil.bytes.*; -public class ByteArrayDataSection implements BaseDataSection { - public ByteArrayDataSection() { - this.array = new ByteArrayList(); - } +public class ByteArrayDataSection implements BaseDataSection +{ + public ByteArrayDataSection() + { this.array = new ByteArrayList(); } private final ByteList array; - public void writeByte(byte value) { - this.array.add(value); - } + public void writeByte(byte value) + { this.array.add(value); } - public int size() { - return array.size(); - } + public int size() + { return array.size(); } - /** - * @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. - */ + /** @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. */ @Deprecated @Override - public void writeForParser(T data) throws UnsupportedOperationException { - if (data instanceof Byte) { + public void writeForParser(T data) throws UnsupportedOperationException + { + if (data instanceof Byte) + { this.writeByte((byte) data); - } else { + } + else + { throw new UnsupportedOperationException("Invalid data type parameter for this data section"); } } - public byte readByte(int index) { - return this.array.getByte(index); - } + public byte readByte(int index) + { return this.array.getByte(index); } @Override - public Iterator iterator() { - return this.array.iterator(); - } + public Iterator iterator() + { return this.array.iterator(); } } diff --git a/src/main/java/tk/valoeghese/sod/DataSection.java b/src/main/java/tk/valoeghese/sod/DataSection.java index 55a1336..3390970 100644 --- a/src/main/java/tk/valoeghese/sod/DataSection.java +++ b/src/main/java/tk/valoeghese/sod/DataSection.java @@ -2,118 +2,91 @@ package tk.valoeghese.sod; import java.util.*; -/** - * Represents a section of SOD data. - * @author Valoeghese - */ -public class DataSection implements BaseDataSection { - public DataSection() { - this.data = new ArrayList<>(); - } +/** Represents a section of SOD data. + * + * @author Valoeghese */ +public class DataSection implements BaseDataSection +{ + public DataSection() + { this.data = new ArrayList<>(); } - private final List data; + private final List data; - /** - * @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. - */ + /** @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. */ @Deprecated @Override - public void writeForParser(T data) { - this.data.add(data); - } + public void writeForParser(T data) + { this.data.add(data); } - public void writeByte(byte data) { - this.data.add(data); - } + public void writeByte(byte data) + { this.data.add(data); } - public void writeShort(short data) { - this.data.add(data); - } + public void writeShort(short data) + { this.data.add(data); } - public void writeInt(int data) { - this.data.add(data); - } + public void writeInt(int data) + { this.data.add(data); } - public void writeLong(long data) { - this.data.add(data); - } + public void writeLong(long data) + { this.data.add(data); } - public void writeFloat(float data) { - this.data.add(data); - } + public void writeFloat(float data) + { this.data.add(data); } - public void writeDouble(double data) { - this.data.add(data); - } + public void writeDouble(double data) + { this.data.add(data); } - public void writeString(String data) { - this.data.add(data); - } + public void writeString(String data) + { this.data.add(data); } - public void writeBoolean(boolean data) { - this.data.add(data ? (byte) 1 : (byte) 0); - } - - public > void writeEnum(T enumValue) { - this.data.add(enumValue.ordinal()); - } + public void writeBoolean(boolean data) + { this.data.add(data ? (byte) 1 : (byte) 0); } - public > void writeEnumAsString(T enumValue) { - this.data.add(enumValue.toString()); - } + public > void writeEnum(T enumValue) + { this.data.add(enumValue.ordinal()); } - public int size() { - return this.data.size(); - } + public > void writeEnumAsString(T enumValue) + { this.data.add(enumValue.toString()); } - public byte readByte(int index) { - return (byte) this.data.get(index); - } + public int size() + { return this.data.size(); } - public short readShort(int index) { - return (short) this.data.get(index); - } + public byte readByte(int index) + { return (byte) this.data.get(index); } - public int readInt(int index) { - return (int) this.data.get(index); - } + public short readShort(int index) + { return (short) this.data.get(index); } - public long readLong(int index) { - return (long) this.data.get(index); - } + public int readInt(int index) + { return (int) this.data.get(index); } - public float readFloat(int index) { - return (float) this.data.get(index); - } + public long readLong(int index) + { return (long) this.data.get(index); } - public double readDouble(int index) { - return (double) this.data.get(index); - } + public float readFloat(int index) + { return (float) this.data.get(index); } - public String readString(int index) { - return (String) this.data.get(index); - } + public double readDouble(int index) + { return (double) this.data.get(index); } - public boolean readBoolean(int index) { - return ((byte) this.data.get(index)) != 0; - } + public String readString(int index) + { return (String) this.data.get(index); } - public > T readEnumString(int index, Class type) { - return Enum.valueOf(type, (String) this.data.get(index)); - } + public boolean readBoolean(int index) + { return ((byte) this.data.get(index)) != 0; } - public > T readEnum(int index, T[] values) { + public > T readEnumString(int index, Class type) + { return Enum.valueOf(type, (String) this.data.get(index)); } + + public > T readEnum(int index, T[] values) + { Integer i = (Integer) this.data.get(index); - - if (i == null) { - return null; - } - + if (i == null) + { return null; } return values[i]; } @Override - public Iterator iterator() { - return this.data.iterator(); - } + public Iterator iterator() + { return this.data.iterator(); } } diff --git a/src/main/java/tk/valoeghese/sod/DoubleArrayDataSection.java b/src/main/java/tk/valoeghese/sod/DoubleArrayDataSection.java index dda91f6..542bec5 100644 --- a/src/main/java/tk/valoeghese/sod/DoubleArrayDataSection.java +++ b/src/main/java/tk/valoeghese/sod/DoubleArrayDataSection.java @@ -4,40 +4,38 @@ import java.util.Iterator; import it.unimi.dsi.fastutil.doubles.*; -public class DoubleArrayDataSection implements BaseDataSection { - public DoubleArrayDataSection() { - this.array = new DoubleArrayList(); - } +public class DoubleArrayDataSection implements BaseDataSection +{ + public DoubleArrayDataSection() + { this.array = new DoubleArrayList(); } private final DoubleList array; - public void writeDouble(double value) { - this.array.add(value); - } + public void writeDouble(double value) + { this.array.add(value); } - public int size() { - return array.size(); - } + public int size() + { return array.size(); } - /** - * @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. - */ + /** @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. */ @Deprecated @Override - public void writeForParser(T data) throws UnsupportedOperationException { - if (data instanceof Double) { + public void writeForParser(T data) throws UnsupportedOperationException + { + if (data instanceof Double) + { this.writeDouble((double) data); - } else { + } + else + { throw new UnsupportedOperationException("Invalid data type parameter for this data section"); } } - public double readDouble(int index) { - return this.array.getDouble(index); - } + public double readDouble(int index) + { return this.array.getDouble(index); } @Override - public Iterator iterator() { - return this.array.iterator(); - } + public Iterator iterator() + { return this.array.iterator(); } } diff --git a/src/main/java/tk/valoeghese/sod/FloatArrayDataSection.java b/src/main/java/tk/valoeghese/sod/FloatArrayDataSection.java index ebc4497..e5646b9 100644 --- a/src/main/java/tk/valoeghese/sod/FloatArrayDataSection.java +++ b/src/main/java/tk/valoeghese/sod/FloatArrayDataSection.java @@ -4,40 +4,38 @@ import java.util.Iterator; import it.unimi.dsi.fastutil.floats.*; -public class FloatArrayDataSection implements BaseDataSection { - public FloatArrayDataSection() { - this.array = new FloatArrayList(); - } +public class FloatArrayDataSection implements BaseDataSection +{ + public FloatArrayDataSection() + { this.array = new FloatArrayList(); } private final FloatList array; - public void writeFloat(float value) { - this.array.add(value); - } + public void writeFloat(float value) + { this.array.add(value); } - public int size() { - return array.size(); - } + public int size() + { return array.size(); } - /** - * @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. - */ + /** @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. */ @Deprecated @Override - public void writeForParser(T data) throws UnsupportedOperationException { - if (data instanceof Float) { + public void writeForParser(T data) throws UnsupportedOperationException + { + if (data instanceof Float) + { this.writeFloat((float) data); - } else { + } + else + { throw new UnsupportedOperationException("Invalid data type parameter for this data section"); } } - public float readFloat(int index) { - return this.array.getFloat(index); - } + public float readFloat(int index) + { return this.array.getFloat(index); } @Override - public Iterator iterator() { - return this.array.iterator(); - } + public Iterator iterator() + { return this.array.iterator(); } } diff --git a/src/main/java/tk/valoeghese/sod/IntArrayDataSection.java b/src/main/java/tk/valoeghese/sod/IntArrayDataSection.java index 8072118..1912d24 100644 --- a/src/main/java/tk/valoeghese/sod/IntArrayDataSection.java +++ b/src/main/java/tk/valoeghese/sod/IntArrayDataSection.java @@ -4,40 +4,38 @@ import java.util.Iterator; import it.unimi.dsi.fastutil.ints.*; -public class IntArrayDataSection implements BaseDataSection { - public IntArrayDataSection() { - this.array = new IntArrayList(); - } +public class IntArrayDataSection implements BaseDataSection +{ + public IntArrayDataSection() + { this.array = new IntArrayList(); } private final IntList array; - public void writeInt(int value) { - this.array.add(value); - } + public void writeInt(int value) + { this.array.add(value); } - public int size() { - return array.size(); - } + public int size() + { return array.size(); } - /** - * @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. - */ + /** @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. */ @Deprecated @Override - public void writeForParser(T data) throws UnsupportedOperationException { - if (data instanceof Integer) { + public void writeForParser(T data) throws UnsupportedOperationException + { + if (data instanceof Integer) + { this.writeInt((int) data); - } else { + } + else + { throw new UnsupportedOperationException("Invalid data type parameter for this data section"); } } - public int readInt(int index) { - return this.array.getInt(index); - } + public int readInt(int index) + { return this.array.getInt(index); } @Override - public Iterator iterator() { - return this.array.iterator(); - } + public Iterator iterator() + { return this.array.iterator(); } } diff --git a/src/main/java/tk/valoeghese/sod/LongArrayDataSection.java b/src/main/java/tk/valoeghese/sod/LongArrayDataSection.java index c4044dc..552f530 100644 --- a/src/main/java/tk/valoeghese/sod/LongArrayDataSection.java +++ b/src/main/java/tk/valoeghese/sod/LongArrayDataSection.java @@ -4,40 +4,38 @@ import java.util.Iterator; import it.unimi.dsi.fastutil.longs.*; -public class LongArrayDataSection implements BaseDataSection { - public LongArrayDataSection() { - this.array = new LongArrayList(); - } +public class LongArrayDataSection implements BaseDataSection +{ + public LongArrayDataSection() + { this.array = new LongArrayList(); } private final LongList array; - public void writeLong(long value) { - this.array.add(value); - } + public void writeLong(long value) + { this.array.add(value); } - public int size() { - return array.size(); - } + public int size() + { return array.size(); } - /** - * @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. - */ + /** @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. */ @Deprecated @Override - public void writeForParser(T data) throws UnsupportedOperationException { - if (data instanceof Long) { + public void writeForParser(T data) throws UnsupportedOperationException + { + if (data instanceof Long) + { this.writeLong((long) data); - } else { + } + else + { throw new UnsupportedOperationException("Invalid data type parameter for this data section"); } } - public long readLong(int index) { - return this.array.getLong(index); - } + public long readLong(int index) + { return this.array.getLong(index); } @Override - public Iterator iterator() { - return this.array.iterator(); - } + public Iterator iterator() + { return this.array.iterator(); } } diff --git a/src/main/java/tk/valoeghese/sod/Parser.java b/src/main/java/tk/valoeghese/sod/Parser.java index 46f9b81..5540ed7 100644 --- a/src/main/java/tk/valoeghese/sod/Parser.java +++ b/src/main/java/tk/valoeghese/sod/Parser.java @@ -5,168 +5,186 @@ import java.util.*; import tk.valoeghese.sod.exception.SODParseException; -final class Parser { - @SuppressWarnings({"deprecation", "rawtypes", "unchecked"}) - static BinaryData parse(DataInputStream input) throws IOException, SODParseException { +final class Parser +{ + @SuppressWarnings( + { + "deprecation", "rawtypes", "unchecked" + }) + static BinaryData parse(DataInputStream input) throws IOException, SODParseException + { BinaryData data = new BinaryData(); - DataType dataType; DataType sectionType; dataType = DataType.of(input.readByte()); sectionType = dataType; - BaseDataSection currentSection; int arraySizeCountdown = 0; - - try { + try + { currentSection = dataType.createSection(); - if (dataType != DataType.SECTION) { - arraySizeCountdown = input.readInt(); - } - } catch (SODParseException e) { + if (dataType != DataType.SECTION) + { arraySizeCountdown = input.readInt(); } + } + catch (SODParseException e) + { throw new SODParseException("Data must be segregated into sections!"); } - data.put(input.readUTF(), currentSection); - - while (input.available() > 0) { - switch (sectionType) { + while (input.available() > 0) + { + switch (sectionType) + { case BYTE_ARRAY_SECTION: - while (arraySizeCountdown --> 0) { - currentSection.writeForParser(input.readByte()); - } + while (arraySizeCountdown-- > 0) + { currentSection.writeForParser(input.readByte()); } // create new section if available - if (input.available() > 0) { - try { + if (input.available() > 0) + { + try + { dataType = DataType.of(input.readByte()); sectionType = dataType; currentSection = dataType.createSection(); data.put(input.readUTF(), currentSection); // set countdown - if (dataType != DataType.SECTION) { - arraySizeCountdown = input.readInt(); - } - } catch (SODParseException e) { + if (dataType != DataType.SECTION) + { arraySizeCountdown = input.readInt(); } + } + catch (SODParseException e) + { throw new RuntimeException("This error should never be thrown! If this error occurs, the parser is not properly dealing with a most-likely-invalid data type."); } } break; case SHORT_ARRAY_SECTION: - while (arraySizeCountdown --> 0) { - currentSection.writeForParser(input.readShort()); - } + while (arraySizeCountdown-- > 0) + { currentSection.writeForParser(input.readShort()); } // create new section if available - if (input.available() > 0) { - try { + if (input.available() > 0) + { + try + { dataType = DataType.of(input.readByte()); sectionType = dataType; currentSection = dataType.createSection(); data.put(input.readUTF(), currentSection); // set countdown - if (dataType != DataType.SECTION) { - arraySizeCountdown = input.readInt(); - } - } catch (SODParseException e) { + if (dataType != DataType.SECTION) + { arraySizeCountdown = input.readInt(); } + } + catch (SODParseException e) + { throw new RuntimeException("This error should never be thrown! If this error occurs, the parser is not properly dealing with a most-likely-invalid data type."); } } break; case INT_ARRAY_SECTION: - while (arraySizeCountdown --> 0) { - currentSection.writeForParser(input.readInt()); - } + while (arraySizeCountdown-- > 0) + { currentSection.writeForParser(input.readInt()); } // create new section if available - if (input.available() > 0) { - try { + if (input.available() > 0) + { + try + { dataType = DataType.of(input.readByte()); sectionType = dataType; currentSection = dataType.createSection(); data.put(input.readUTF(), currentSection); // set countdown - if (dataType != DataType.SECTION) { - arraySizeCountdown = input.readInt(); - } - } catch (SODParseException e) { + if (dataType != DataType.SECTION) + { arraySizeCountdown = input.readInt(); } + } + catch (SODParseException e) + { throw new RuntimeException("This error should never be thrown! If this error occurs, the parser is not properly dealing with a most-likely-invalid data type."); } } break; case LONG_ARRAY_SECTION: - while (arraySizeCountdown --> 0) { - currentSection.writeForParser(input.readLong()); - } + while (arraySizeCountdown-- > 0) + { currentSection.writeForParser(input.readLong()); } // create new section if available - if (input.available() > 0) { - try { + if (input.available() > 0) + { + try + { dataType = DataType.of(input.readByte()); sectionType = dataType; currentSection = dataType.createSection(); data.put(input.readUTF(), currentSection); // set countdown - if (dataType != DataType.SECTION) { - arraySizeCountdown = input.readInt(); - } - } catch (SODParseException e) { + if (dataType != DataType.SECTION) + { arraySizeCountdown = input.readInt(); } + } + catch (SODParseException e) + { throw new RuntimeException("This error should never be thrown! If this error occurs, the parser is not properly dealing with a most-likely-invalid data type."); } } break; case FLOAT_ARRAY_SECTION: - while (arraySizeCountdown --> 0) { - currentSection.writeForParser(input.readFloat()); - } + while (arraySizeCountdown-- > 0) + { currentSection.writeForParser(input.readFloat()); } // create new section if available - if (input.available() > 0) { - try { + if (input.available() > 0) + { + try + { dataType = DataType.of(input.readByte()); sectionType = dataType; currentSection = dataType.createSection(); data.put(input.readUTF(), currentSection); // set countdown - if (dataType != DataType.SECTION) { - arraySizeCountdown = input.readInt(); - } - } catch (SODParseException e) { + if (dataType != DataType.SECTION) + { arraySizeCountdown = input.readInt(); } + } + catch (SODParseException e) + { throw new RuntimeException("This error should never be thrown! If this error occurs, the parser is not properly dealing with a most-likely-invalid data type."); } } break; case DOUBLE_ARRAY_SECTION: - while (arraySizeCountdown --> 0) { - currentSection.writeForParser(input.readDouble()); - } + while (arraySizeCountdown-- > 0) + { currentSection.writeForParser(input.readDouble()); } // create new section if available - if (input.available() > 0) { - try { + if (input.available() > 0) + { + try + { dataType = DataType.of(input.readByte()); sectionType = dataType; currentSection = dataType.createSection(); data.put(input.readUTF(), currentSection); // set countdown - if (dataType != DataType.SECTION) { - arraySizeCountdown = input.readInt(); - } - } catch (SODParseException e) { + if (dataType != DataType.SECTION) + { arraySizeCountdown = input.readInt(); } + } + catch (SODParseException e) + { throw new RuntimeException("This error should never be thrown! If this error occurs, the parser is not properly dealing with a most-likely-invalid data type."); } } break; case STRING_ARRAY_SECTION: - while (arraySizeCountdown --> 0) { - currentSection.writeForParser(input.readUTF()); - } + while (arraySizeCountdown-- > 0) + { currentSection.writeForParser(input.readUTF()); } // create new section if available - if (input.available() > 0) { - try { + if (input.available() > 0) + { + try + { dataType = DataType.of(input.readByte()); sectionType = dataType; currentSection = dataType.createSection(); data.put(input.readUTF(), currentSection); // set countdown - if (dataType != DataType.SECTION) { - arraySizeCountdown = input.readInt(); - } - } catch (SODParseException e) { + if (dataType != DataType.SECTION) + { arraySizeCountdown = input.readInt(); } + } + catch (SODParseException e) + { throw new RuntimeException("This error should never be thrown! If this error occurs, the parser is not properly dealing with a most-likely-invalid data type."); } } @@ -174,8 +192,8 @@ final class Parser { case SECTION: default: dataType = DataType.of(input.readByte()); - - switch (dataType) { + switch (dataType) + { case BYTE: currentSection.writeForParser(input.readByte()); break; @@ -198,14 +216,16 @@ final class Parser { currentSection.writeForParser(input.readUTF()); break; default: - try { + try + { currentSection = dataType.createSection(); sectionType = dataType; data.put(input.readUTF(), currentSection); - if (dataType != DataType.SECTION) { - arraySizeCountdown = input.readInt(); - } - } catch (SODParseException e) { + if (dataType != DataType.SECTION) + { arraySizeCountdown = input.readInt(); } + } + catch (SODParseException e) + { throw new RuntimeException("This error should never be thrown! If this error occurs, the parser is not properly dealing with a most-likely-invalid data type."); } break; @@ -213,114 +233,125 @@ final class Parser { break; } } - return data; } @SuppressWarnings("rawtypes") - static void write(BinaryData data, DataOutputStream dos) throws IOException { + static void write(BinaryData data, DataOutputStream dos) throws IOException + { dos.writeLong(0xA77D1E); - Iterator> sectionStream = data.iterator(); - - while (sectionStream.hasNext()) { + while (sectionStream.hasNext()) + { Map.Entry entry = sectionStream.next(); BaseDataSection section = entry.getValue(); - - if (section instanceof DataSection) { + if (section instanceof DataSection) + { dos.writeByte(DataType.SECTION.id); dos.writeUTF(entry.getKey()); - Iterator dataStream = ((DataSection) section).iterator(); - - while (dataStream.hasNext()) { + while (dataStream.hasNext()) + { Object o = dataStream.next(); - - if (o instanceof Byte) { + if (o instanceof Byte) + { dos.writeByte(DataType.BYTE.id); dos.writeByte((byte) o); - } else if (o instanceof Short) { + } + else if (o instanceof Short) + { dos.writeByte(DataType.SHORT.id); dos.writeShort((short) o); - } else if (o instanceof Integer) { + } + else if (o instanceof Integer) + { dos.writeByte(DataType.INT.id); dos.writeInt((int) o); - } else if (o instanceof Long) { + } + else if (o instanceof Long) + { dos.writeByte(DataType.LONG.id); dos.writeLong((long) o); - } else if (o instanceof Float) { + } + else if (o instanceof Float) + { dos.writeByte(DataType.FLOAT.id); dos.writeFloat((float) o); - } else if (o instanceof Double) { + } + else if (o instanceof Double) + { dos.writeByte(DataType.DOUBLE.id); dos.writeDouble((double) o); - } else if (o instanceof String) { + } + else if (o instanceof String) + { dos.writeByte(DataType.STRING.id); dos.writeUTF((String) o); } } - } else if (section instanceof ByteArrayDataSection) { // byte array + } + else if (section instanceof ByteArrayDataSection) + { // byte array dos.writeByte(DataType.BYTE_ARRAY_SECTION.id); dos.writeUTF(entry.getKey()); dos.writeInt(((ByteArrayDataSection) section).size()); - - for (byte b : (ByteArrayDataSection) section) { - dos.writeByte(b); - } - } else if (section instanceof ShortArrayDataSection) { // short array + for (byte b : (ByteArrayDataSection) section) + { dos.writeByte(b); } + } + else if (section instanceof ShortArrayDataSection) + { // short array dos.writeByte(DataType.SHORT_ARRAY_SECTION.id); dos.writeUTF(entry.getKey()); dos.writeInt(((ShortArrayDataSection) section).size()); - - for (short s : (ShortArrayDataSection) section) { - dos.writeShort(s); - } - } else if (section instanceof IntArrayDataSection) { // int array + for (short s : (ShortArrayDataSection) section) + { dos.writeShort(s); } + } + else if (section instanceof IntArrayDataSection) + { // int array dos.writeByte(DataType.INT_ARRAY_SECTION.id); dos.writeUTF(entry.getKey()); dos.writeInt(((IntArrayDataSection) section).size()); - - for (int i : (IntArrayDataSection) section) { - dos.writeInt(i); - } - } else if (section instanceof LongArrayDataSection) { // long array + for (int i : (IntArrayDataSection) section) + { dos.writeInt(i); } + } + else if (section instanceof LongArrayDataSection) + { // long array dos.writeByte(DataType.LONG_ARRAY_SECTION.id); dos.writeUTF(entry.getKey()); dos.writeInt(((LongArrayDataSection) section).size()); - - for (long l : (LongArrayDataSection) section) { - dos.writeLong(l); - } - } else if (section instanceof FloatArrayDataSection) { // float array + for (long l : (LongArrayDataSection) section) + { dos.writeLong(l); } + } + else if (section instanceof FloatArrayDataSection) + { // float array dos.writeByte(DataType.FLOAT_ARRAY_SECTION.id); dos.writeUTF(entry.getKey()); dos.writeInt(((FloatArrayDataSection) section).size()); - - for (float f: (FloatArrayDataSection) section) { - dos.writeFloat(f); - } - } else if (section instanceof DoubleArrayDataSection) { // double array + for (float f : (FloatArrayDataSection) section) + { dos.writeFloat(f); } + } + else if (section instanceof DoubleArrayDataSection) + { // double array dos.writeByte(DataType.DOUBLE_ARRAY_SECTION.id); dos.writeUTF(entry.getKey()); dos.writeInt(((DoubleArrayDataSection) section).size()); - - for (double d : (DoubleArrayDataSection) section) { - dos.writeDouble(d); - } - } else if (section instanceof StringArrayDataSection) { // string array + for (double d : (DoubleArrayDataSection) section) + { dos.writeDouble(d); } + } + else if (section instanceof StringArrayDataSection) + { // string array dos.writeByte(DataType.STRING_ARRAY_SECTION.id); dos.writeUTF(entry.getKey()); dos.writeInt(((StringArrayDataSection) section).size()); - - for (String s : (StringArrayDataSection) section) { - dos.writeUTF(s); - } + for (String s : (StringArrayDataSection) section) + { dos.writeUTF(s); } } } } } -enum DataType { +enum DataType +{ SECTION(0), BYTE(1), SHORT(2), @@ -337,14 +368,15 @@ enum DataType { DOUBLE_ARRAY_SECTION(13), STRING_ARRAY_SECTION(14); - private DataType(int id) { - this.id = (byte) id; - } + private DataType(int id) + { this.id = (byte) id; } public final byte id; - public static DataType of(byte id) throws SODParseException { - switch (id) { + public static DataType of(byte id) throws SODParseException + { + switch (id) + { case 0: return SECTION; case 1: @@ -381,8 +413,10 @@ enum DataType { } @SuppressWarnings("rawtypes") - BaseDataSection createSection() { - switch (this) { + BaseDataSection createSection() + { + switch (this) + { case SECTION: return new DataSection(); case BYTE_ARRAY_SECTION: diff --git a/src/main/java/tk/valoeghese/sod/ShortArrayDataSection.java b/src/main/java/tk/valoeghese/sod/ShortArrayDataSection.java index 6cc99c4..66e8595 100644 --- a/src/main/java/tk/valoeghese/sod/ShortArrayDataSection.java +++ b/src/main/java/tk/valoeghese/sod/ShortArrayDataSection.java @@ -4,40 +4,38 @@ import java.util.Iterator; import it.unimi.dsi.fastutil.shorts.*; -public class ShortArrayDataSection implements BaseDataSection { - public ShortArrayDataSection() { - this.array = new ShortArrayList(); - } +public class ShortArrayDataSection implements BaseDataSection +{ + public ShortArrayDataSection() + { this.array = new ShortArrayList(); } private final ShortList array; - public void writeShort(short value) { - this.array.add(value); - } + public void writeShort(short value) + { this.array.add(value); } - public int size() { - return array.size(); - } + public int size() + { return array.size(); } - /** - * @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. - */ + /** @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. */ @Deprecated @Override - public void writeForParser(T data) throws UnsupportedOperationException { - if (data instanceof Short) { + public void writeForParser(T data) throws UnsupportedOperationException + { + if (data instanceof Short) + { this.writeShort((short) data); - } else { + } + else + { throw new UnsupportedOperationException("Invalid data type parameter for this data section"); } } - public short readShort(int index) { - return this.array.getShort(index); - } + public short readShort(int index) + { return this.array.getShort(index); } @Override - public Iterator iterator() { - return this.array.iterator(); - } + public Iterator iterator() + { return this.array.iterator(); } } diff --git a/src/main/java/tk/valoeghese/sod/StringArrayDataSection.java b/src/main/java/tk/valoeghese/sod/StringArrayDataSection.java index d360d4a..3d266f0 100644 --- a/src/main/java/tk/valoeghese/sod/StringArrayDataSection.java +++ b/src/main/java/tk/valoeghese/sod/StringArrayDataSection.java @@ -2,40 +2,38 @@ package tk.valoeghese.sod; import java.util.*; -public class StringArrayDataSection implements BaseDataSection { - public StringArrayDataSection() { - this.array = new ArrayList(); - } +public class StringArrayDataSection implements BaseDataSection +{ + public StringArrayDataSection() + { this.array = new ArrayList(); } private final List array; - public void writeString(String value) { - this.array.add(value); - } + public void writeString(String value) + { this.array.add(value); } - public int size() { - return array.size(); - } + public int size() + { return array.size(); } - /** - * @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. - */ + /** @deprecated Should only be used by the parser! Please use the type specific methods instead for writing data. */ @Deprecated @Override - public void writeForParser(T data) throws UnsupportedOperationException { - if (data instanceof String) { + public void writeForParser(T data) throws UnsupportedOperationException + { + if (data instanceof String) + { this.writeString((String) data); - } else { + } + else + { throw new UnsupportedOperationException("Invalid data type parameter for this data section"); } } - public String readString(int index) { - return this.array.get(index); - } + public String readString(int index) + { return this.array.get(index); } @Override - public Iterator iterator() { - return this.array.iterator(); - } + public Iterator iterator() + { return this.array.iterator(); } } diff --git a/src/main/java/tk/valoeghese/sod/TestMain.java b/src/main/java/tk/valoeghese/sod/TestMain.java index c9940d6..6f8ab1c 100644 --- a/src/main/java/tk/valoeghese/sod/TestMain.java +++ b/src/main/java/tk/valoeghese/sod/TestMain.java @@ -2,75 +2,60 @@ package tk.valoeghese.sod; import java.io.*; -class TestMain { - - public static void main(String[] args) throws IOException { +class TestMain +{ + public static void main(String[] args) throws IOException + { writeTest(); readTest(); } - static void readTest() throws IOException { + static void readTest() throws IOException + { File f = new File("../test.sod"); - - if (!f.createNewFile()) { + if (!f.createNewFile()) + { BinaryData bd = BinaryData.read(f); - StringArrayDataSection ds0 = bd.getStringArray("StringArray"); - - for (String s : ds0) { - System.out.println(s); - } - + for (String s : ds0) + { System.out.println(s); } DataSection ds1 = bd.get("DS1"); - - for (Object i : ds1) { - System.out.println(i); - } - + for (Object i : ds1) + { System.out.println(i); } DataSection ds2 = bd.get("yeet"); - - for (Object i : ds2) { - System.out.println(i); - } - + for (Object i : ds2) + { System.out.println(i); } ByteArrayDataSection ds3 = bd.getByteArray("ByteArray"); - - for (byte i : ds3) { - System.out.println(i); - } + for (byte i : ds3) + { System.out.println(i); } } } - static void writeTest() throws IOException { + static void writeTest() throws IOException + { File f = new File("../test.sod"); f.createNewFile(); BinaryData bd = new BinaryData(); - StringArrayDataSection ds0 = new StringArrayDataSection(); ds0.writeString("Once upon a time"); ds0.writeString("There was a programmer who went by the username of \"Valoeghese\""); ds0.writeString("One day he updated his data format SOD to have array sections"); bd.put("StringArray", ds0); - DataSection ds1 = bd.getOrCreate("DS1"); ds1.writeBoolean(false); ds1.writeDouble(0.666D); ds1.writeLong(69696969); ds1.writeString("yaY33T"); - DataSection ds2 = bd.getOrCreate("yeet"); ds2.writeByte((byte) 4); ds2.writeFloat(1.3F); ds2.writeString("e"); ds2.writeString("ff"); - ByteArrayDataSection ds3 = new ByteArrayDataSection(); - ds3.writeByte((byte)0); - ds3.writeByte((byte)9); - ds3.writeByte((byte)-10); + ds3.writeByte((byte) 0); + ds3.writeByte((byte) 9); + ds3.writeByte((byte) -10); bd.put("ByteArray", ds3); - bd.write(f); } - } diff --git a/src/main/java/tk/valoeghese/sod/exception/SODParseException.java b/src/main/java/tk/valoeghese/sod/exception/SODParseException.java index f91639a..ef13b2a 100644 --- a/src/main/java/tk/valoeghese/sod/exception/SODParseException.java +++ b/src/main/java/tk/valoeghese/sod/exception/SODParseException.java @@ -1,9 +1,9 @@ package tk.valoeghese.sod.exception; -public class SODParseException extends RuntimeException { +public class SODParseException extends RuntimeException +{ private static final long serialVersionUID = -3337517517501006140L; - public SODParseException(String message) { - super(message); - } + public SODParseException(String message) + { super(message); } }