diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/MeshData.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/MeshData.java new file mode 100644 index 0000000..f67cdd9 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/MeshData.java @@ -0,0 +1,4 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel; + +public record MeshData(String ID, float[] Positions, int[] Indices) { +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/ModelData.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/ModelData.java new file mode 100644 index 0000000..ca2f33c --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/ModelData.java @@ -0,0 +1,8 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel; + +import java.util.List; + +public record ModelData(String ID, List Meshes) { +} + + diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/ModelsCache.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/ModelsCache.java new file mode 100644 index 0000000..e597e97 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/ModelsCache.java @@ -0,0 +1,102 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel; + +import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandPool; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation.TransferBuffer; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Queues.Queue; +import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanBuffer; +import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; +import org.lwjgl.system.MemoryUtil; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.lwjgl.vulkan.VK10.*; + +public class ModelsCache { + private final Map ModelsMap; + public ModelsCache(){ + ModelsMap = new HashMap<>(); + } + + public void loadModels(VulkanContext VkCtx, List Models, CommandPool commandPool, Queue queue){ + List StagingBufferList = new ArrayList<>(); + var Command = new CommandBuffer(VkCtx, commandPool, true, true); + Command.BeginRecording(); + + for(ModelData modelData : Models){ + VulkanModel VKModel = new VulkanModel(modelData.ID()); + ModelsMap.put(VKModel.GetID(), VKModel); + for(MeshData meshData : modelData.Meshes()){ + TransferBuffer VerticesBuffers = CreateVerticesBuffer(VkCtx,meshData); + TransferBuffer IndicesBuffers = CreateIndicesBuffer(VkCtx,meshData); + StagingBufferList.add(VerticesBuffers.SrcBuffer()); + StagingBufferList.add(IndicesBuffers.SrcBuffer()); + VerticesBuffers.RecordTransferCommand(Command); + IndicesBuffers.RecordTransferCommand(Command); + VulkanMesh VkMesh = new VulkanMesh(meshData.ID(), VerticesBuffers.DstBuffer(),IndicesBuffers.DstBuffer(), + meshData.Indices().length); + VKModel.GetVkMeshList().add(VkMesh); + } + } + + Command.EndRecording(); + Command.SubmitAndWait(VkCtx,queue); + Command.cleanup(VkCtx,commandPool); + + StagingBufferList.forEach(b -> b.cleanup(VkCtx)); + } + + private static TransferBuffer CreateVerticesBuffer(VulkanContext VkCtx, MeshData meshData){ + float[] Positions = meshData.Positions(); + int ElementCount = Positions.length; + int BufferSize = ElementCount * VulkanUtils.FLOAT_SIZE; + var SrcBuffer = new VulkanBuffer(VkCtx,BufferSize, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + var DstBuffer = new VulkanBuffer(VkCtx, BufferSize, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + long MappedMemory = SrcBuffer.MapMemory(VkCtx); + FloatBuffer data = MemoryUtil.memFloatBuffer(MappedMemory, (int) SrcBuffer.GetRequestedSize()); + int Rows = Positions.length / 3; + for(int Row = 0; Row < Rows; Row++){ + int StartPos = Row * 3; + data.put(Positions[StartPos]); + data.put(Positions[StartPos+1]); + data.put(Positions[StartPos+2]); + } + SrcBuffer.UnMapMemory(VkCtx); + return new TransferBuffer(SrcBuffer,DstBuffer); + } + + private static TransferBuffer CreateIndicesBuffer(VulkanContext VkCtx, MeshData meshData){ + int[] Indices = meshData.Indices(); + int IndexCount = Indices.length; + int BufferSize = IndexCount * VulkanUtils.INT_SIZE; + + var SrcBuffer = new VulkanBuffer(VkCtx,BufferSize, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + var DstBuffer = new VulkanBuffer(VkCtx, BufferSize, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + long MappedMemory = SrcBuffer.MapMemory(VkCtx); + IntBuffer data = MemoryUtil.memIntBuffer(MappedMemory,(int) SrcBuffer.GetRequestedSize()); + data.put(Indices); + SrcBuffer.UnMapMemory(VkCtx); + return new TransferBuffer(SrcBuffer,DstBuffer); + } + public VulkanModel GetModel(String modelName){ + return ModelsMap.get(modelName); + } + public Map GetModelMap(){ + return ModelsMap; + } + public void CleanUp(VulkanContext VkCtx){ + ModelsMap.forEach((key,Value)->Value.CleanUp(VkCtx)); + ModelsMap.clear(); + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/VulkanMesh.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/VulkanMesh.java new file mode 100644 index 0000000..1b5f897 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/VulkanMesh.java @@ -0,0 +1,12 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel; + +import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext; +import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanBuffer; + +public record VulkanMesh(String ID, VulkanBuffer VerticesBuffer,VulkanBuffer IndicesBuffer,int IndicesCount) { + public void Cleanup(VulkanContext VkCtx){ + VerticesBuffer.cleanup(VkCtx); + IndicesBuffer.cleanup(VkCtx); + } + +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/VulkanModel.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/VulkanModel.java new file mode 100644 index 0000000..0236319 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/VulkanModel.java @@ -0,0 +1,21 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel; + +import net.halbear.Terrain4J.EngineCore.Logic.VulkanContext; + +import java.util.ArrayList; +import java.util.List; + +public class VulkanModel { + private final String ID; + private final List VulkanMeshList; + + public VulkanModel(String id){ + this.ID = id; + VulkanMeshList = new ArrayList<>(); + } + public void CleanUp(VulkanContext VkCtx){ + VulkanMeshList.forEach(mesh -> mesh.Cleanup(VkCtx)); + } + public String GetID(){return ID;} + public List GetVkMeshList(){return this.VulkanMeshList;} +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/TransferBuffer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/TransferBuffer.java new file mode 100644 index 0000000..ea67848 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DeviceLayers/GPUSynchronisation/TransferBuffer.java @@ -0,0 +1,18 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation; + +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer; +import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanBuffer; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.vulkan.VkBufferCopy; + +import static org.lwjgl.vulkan.VK10.vkCmdCopyBuffer; + +public record TransferBuffer(VulkanBuffer SrcBuffer, VulkanBuffer DstBuffer) { + public void RecordTransferCommand(CommandBuffer commandBuffer){ + try(var MemStack = MemoryStack.stackPush()){ + VkBufferCopy.Buffer CopyRegion = VkBufferCopy.calloc(1,MemStack) + .srcOffset(0).dstOffset(0).size(SrcBuffer.GetRequestedSize()); + vkCmdCopyBuffer(commandBuffer.GetVulkanCommandBuffer(),SrcBuffer.GetBuffer(),DstBuffer.GetBuffer(),CopyRegion); + } + } +}