using the Vulkan Memory Allocator to reduce the amount of stuff needed to do to allocate memory to the GPU

This commit is contained in:
Halbear 2026-06-08 15:06:25 +01:00
parent f725d12810
commit fa266ee48d
11 changed files with 125 additions and 50 deletions

View file

@ -9,6 +9,7 @@ import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.PhysicalDe
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.Surface; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.Surface;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SwapChain; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SwapChain;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.VulkanInstance; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.VulkanInstance;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanMemoryAllocator;
import org.tinylog.Logger; import org.tinylog.Logger;
public class VulkanContext { public class VulkanContext {
@ -20,6 +21,7 @@ public class VulkanContext {
private SwapChain swapChain; private SwapChain swapChain;
private final PipelineCache VkPipelineCache; private final PipelineCache VkPipelineCache;
private final DescriptorAllocator descriptorAllocator; private final DescriptorAllocator descriptorAllocator;
private final VulkanMemoryAllocator MemoryAllocator;
public VulkanContext(Window window){ public VulkanContext(Window window){
var EngineGlobals = EngineConfig.getInstance(); var EngineGlobals = EngineConfig.getInstance();
@ -31,6 +33,7 @@ public class VulkanContext {
VulkanLayersOpen+=5; VulkanLayersOpen+=5;
VkPipelineCache = new PipelineCache(device); VkPipelineCache = new PipelineCache(device);
descriptorAllocator = new DescriptorAllocator(PhysDevice, device); descriptorAllocator = new DescriptorAllocator(PhysDevice, device);
MemoryAllocator = new VulkanMemoryAllocator(Instance, PhysDevice, device);
} }
public void Resize(Window window){ public void Resize(Window window){
swapChain.cleanup(device); swapChain.cleanup(device);
@ -40,6 +43,7 @@ public class VulkanContext {
swapChain = new SwapChain(window, device, surface, EngCfg.GetRequestedImages(),EngCfg.GetVSYNC()); swapChain = new SwapChain(window, device, surface, EngCfg.GetRequestedImages(),EngCfg.GetVSYNC());
} }
public void cleanup(){ public void cleanup(){
MemoryAllocator.CleanUp();
descriptorAllocator.CleanUp(device); descriptorAllocator.CleanUp(device);
swapChain.cleanup(device); swapChain.cleanup(device);
surface.cleanup(Instance); surface.cleanup(Instance);
@ -50,6 +54,7 @@ public class VulkanContext {
Logger.debug("Render Thread Finished ending Vulkan Processes\nVulkan Layers Open:[{}]", VulkanContext.VulkanLayersOpen < 0 ? "All processes closed and vulkan instance removed" : VulkanContext.VulkanLayersOpen); Logger.debug("Render Thread Finished ending Vulkan Processes\nVulkan Layers Open:[{}]", VulkanContext.VulkanLayersOpen < 0 ? "All processes closed and vulkan instance removed" : VulkanContext.VulkanLayersOpen);
VulkanLayersOpen--; VulkanLayersOpen--;
} }
public VulkanMemoryAllocator GetVkMemoryAllocator(){return MemoryAllocator;}
public PipelineCache GetVkPipelineCache(){return VkPipelineCache;} public PipelineCache GetVkPipelineCache(){return VkPipelineCache;}
public SwapChain GetSwapChain(){return swapChain;} public SwapChain GetSwapChain(){return swapChain;}
public Device GetDevice(){ public Device GetDevice(){

View file

@ -121,7 +121,6 @@ public class GameCore implements GameLogic {
float DeltaTime = (float)(FrameDiffNanoSeconds/16000000.0); float DeltaTime = (float)(FrameDiffNanoSeconds/16000000.0);
for(int i = 0; i < angles.size()/2; i++) { for(int i = 0; i < angles.size()/2; i++) {
angles.set(i, (angles.get(i) + 0.1f* DeltaTime) % 360); angles.set(i, (angles.get(i) + 0.1f* DeltaTime) % 360);
Camera camera = engineInstance.scene().GetCamera();
CubeActors.get(i).GetRotation().identity().rotateAxis((float) EngineConfig.DegToRad * angles.get(i), rotatingAngles.get(i)); CubeActors.get(i).GetRotation().identity().rotateAxis((float) EngineConfig.DegToRad * angles.get(i), rotatingAngles.get(i));
//CubeActors.get(i).GetPosition().add((Velocities.get(i).x/100.0f) * DeltaTime,(Velocities.get(i).y/100.0f) * DeltaTime,(Velocities.get(i).z/100.0f) * DeltaTime); //CubeActors.get(i).GetPosition().add((Velocities.get(i).x/100.0f) * DeltaTime,(Velocities.get(i).y/100.0f) * DeltaTime,(Velocities.get(i).z/100.0f) * DeltaTime);
CubeActors.get(i).UpdateModelMatrix(); CubeActors.get(i).UpdateModelMatrix();

View file

@ -3,6 +3,7 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.ImageView; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.ImageView;
import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
import static org.lwjgl.vulkan.VK13.*; import static org.lwjgl.vulkan.VK13.*;
public class Attachment { public class Attachment {
private final Image VkImage; private final Image VkImage;
@ -11,7 +12,7 @@ public class Attachment {
public Attachment(VulkanContext VkCtx, int Width, int Height, int Format, int Usage){ public Attachment(VulkanContext VkCtx, int Width, int Height, int Format, int Usage){
var ImageData = new Image.ImageData().Width(Width).Height(Height).Format(Format) var ImageData = new Image.ImageData().Width(Width).Height(Height).Format(Format)
.Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT); .Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT).MemoryUsage(VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT);
VkImage = new Image(VkCtx, ImageData); VkImage = new Image(VkCtx, ImageData);
int AspectMask = 0; int AspectMask = 0;

View file

@ -3,22 +3,26 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import org.lwjgl.PointerBuffer;
import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryStack;
import org.lwjgl.util.vma.VmaAllocationCreateInfo;
import org.lwjgl.vulkan.VkImageCreateInfo; import org.lwjgl.vulkan.VkImageCreateInfo;
import org.lwjgl.vulkan.VkMemoryAllocateInfo; import org.lwjgl.vulkan.VkMemoryAllocateInfo;
import org.lwjgl.vulkan.VkMemoryRequirements; import org.lwjgl.vulkan.VkMemoryRequirements;
import java.nio.LongBuffer; import java.nio.LongBuffer;
import static org.lwjgl.util.vma.Vma.*;
import static org.lwjgl.vulkan.VK10.*; import static org.lwjgl.vulkan.VK10.*;
import static org.lwjgl.vulkan.VK13.VK_FORMAT_R8G8B8A8_SRGB; import static org.lwjgl.vulkan.VK13.VK_FORMAT_R8G8B8A8_SRGB;
public class Image { public class Image {
private final long Allocation;
private final int Format; private final int Format;
private final int MipLevels; private final int MipLevels;
private final long VulkanImage; private final long VulkanImage;
private final long VulkanMemory; //private final long VulkanMemory;
public Image(VulkanContext VkCtx, ImageData imageData){ public Image(VulkanContext VkCtx, ImageData imageData){
try(var MemStack = MemoryStack.stackPush()){ try(var MemStack = MemoryStack.stackPush()){
@ -40,36 +44,30 @@ public class Image {
.sharingMode(VK_SHARING_MODE_EXCLUSIVE) .sharingMode(VK_SHARING_MODE_EXCLUSIVE)
.tiling(VK_IMAGE_TILING_OPTIMAL) .tiling(VK_IMAGE_TILING_OPTIMAL)
.usage(imageData.Usage); .usage(imageData.Usage);
Device device = VkCtx.GetDevice();
LongBuffer LongPtr = MemStack.mallocLong(1);
VulkanUtils.vkCheck(vkCreateImage(device.FetchVulkanDevice(),vkImageCreateInfo,null,LongPtr),
"Failed to create Vulkan Image");
VulkanImage = LongPtr.get(0);
VkMemoryRequirements memoryRequirements = VkMemoryRequirements.calloc(MemStack);
vkGetImageMemoryRequirements(device.FetchVulkanDevice(), VulkanImage, memoryRequirements);
var MemoryAllocation = VkMemoryAllocateInfo.calloc(MemStack) var AllocationCreateInfo = VmaAllocationCreateInfo.calloc(1,MemStack)
.sType$Default() .get(0)
.allocationSize(memoryRequirements.size()) .usage(VMA_MEMORY_USAGE_AUTO)
.memoryTypeIndex(VulkanUtils.MemoryTypeFromProperties(VkCtx, memoryRequirements.memoryTypeBits(),0)); .flags(imageData.MemoryUsage)
.priority(1.0f);
PointerBuffer AllocationPointer = MemStack.callocPointer(1);
LongBuffer LongPtr = MemStack.mallocLong(1);
//allocate //allocate
VulkanUtils.vkCheck(vkAllocateMemory(device.FetchVulkanDevice(),MemoryAllocation,null,LongPtr) VulkanUtils.vkCheck(vmaCreateImage(VkCtx.GetVkMemoryAllocator().GetVmaAllocator(),vkImageCreateInfo,AllocationCreateInfo,LongPtr,AllocationPointer,null)
,"Failed to allocate Memory for Vulkan Image"); ,"Failed to allocate Memory for Vulkan Image");
VulkanMemory = LongPtr.get(0); VulkanImage = LongPtr.get(0);
//bind Allocation = AllocationPointer.get(0);
VulkanUtils.vkCheck(vkBindImageMemory(device.FetchVulkanDevice(),VulkanImage,VulkanMemory,0)
,"Failed to bind memory for Vulkan Image");
} }
} }
public void CleanUp(VulkanContext VkCtx){ public void CleanUp(VulkanContext VkCtx){
vkDestroyImage(VkCtx.GetDevice().FetchVulkanDevice(), VulkanImage,null); vmaDestroyImage(VkCtx.GetVkMemoryAllocator().GetVmaAllocator(),VulkanImage,Allocation);
vkFreeMemory(VkCtx.GetDevice().FetchVulkanDevice(), VulkanMemory,null);
} }
public int GetFormat(){return Format;} public int GetFormat(){return Format;}
public int GetMipLevels(){return MipLevels;} public int GetMipLevels(){return MipLevels;}
public long getVulkanImage(){return VulkanImage;} public long getVulkanImage(){return VulkanImage;}
public static class ImageData{ public static class ImageData{
private int MemoryUsage;
private int ArrayLayers; private int ArrayLayers;
private int Format; private int Format;
private int Height; private int Height;
@ -83,6 +81,11 @@ public class Image {
MipMapLevels = 1; MipMapLevels = 1;
SampleCount = 1; SampleCount = 1;
ArrayLayers = 1; ArrayLayers = 1;
MemoryUsage = 0;
}
public ImageData MemoryUsage(int memoryUsage){
this.MemoryUsage = memoryUsage;
return this;
} }
public ImageData ArrayLayers(int ArrayLayers){ public ImageData ArrayLayers(int ArrayLayers){
this.ArrayLayers = ArrayLayers; this.ArrayLayers = ArrayLayers;

View file

@ -12,6 +12,8 @@ import org.lwjgl.vulkan.*;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
import static org.lwjgl.util.vma.Vma.VMA_MEMORY_USAGE_AUTO;
import static org.lwjgl.vulkan.VK10.*; import static org.lwjgl.vulkan.VK10.*;
import static org.lwjgl.vulkan.VK13.VK_ACCESS_2_NONE; import static org.lwjgl.vulkan.VK13.VK_ACCESS_2_NONE;
import static org.lwjgl.vulkan.VK13.vkCmdPipelineBarrier2; import static org.lwjgl.vulkan.VK13.vkCmdPipelineBarrier2;
@ -58,7 +60,7 @@ public class Texture {
} }
public void CreateStgBuffer(VulkanContext VkCtx, ByteBuffer data){ public void CreateStgBuffer(VulkanContext VkCtx, ByteBuffer data){
int Size = data.remaining(); int Size = data.remaining();
stgBuffer = new VulkanBuffer(VkCtx, Size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); stgBuffer = new VulkanBuffer(VkCtx, Size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,VMA_MEMORY_USAGE_AUTO,VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
long MappedMemory = stgBuffer.MapMemory(VkCtx); long MappedMemory = stgBuffer.MapMemory(VkCtx);
ByteBuffer buffer = MemoryUtil.memByteBuffer(MappedMemory, (int) stgBuffer.GetRequestedSize()); ByteBuffer buffer = MemoryUtil.memByteBuffer(MappedMemory, (int) stgBuffer.GetRequestedSize());
buffer.put(data); buffer.put(data);

View file

@ -18,6 +18,8 @@ import java.nio.ByteBuffer;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
import static org.lwjgl.util.vma.Vma.VMA_MEMORY_USAGE_AUTO;
import static org.lwjgl.vulkan.VK10.*; import static org.lwjgl.vulkan.VK10.*;
public class MaterialsCache { public class MaterialsCache {
@ -34,9 +36,9 @@ public class MaterialsCache {
int MaterialCount = Materials.size(); int MaterialCount = Materials.size();
int BufferSize = MATERIAL_SIZE * MaterialCount; int BufferSize = MATERIAL_SIZE * MaterialCount;
var SrcBuffer = new VulkanBuffer(VkCtx, BufferSize, var SrcBuffer = new VulkanBuffer(VkCtx, BufferSize,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); VK_BUFFER_USAGE_TRANSFER_SRC_BIT,VMA_MEMORY_USAGE_AUTO,VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
MaterialsBuffer = new VulkanBuffer(VkCtx, BufferSize, MaterialsBuffer = new VulkanBuffer(VkCtx, BufferSize,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO,0,0);
var CmdBuffer = new CommandBuffer(VkCtx, commandPool, true, true); var CmdBuffer = new CommandBuffer(VkCtx, commandPool, true, true);
CmdBuffer.BeginRecording(); CmdBuffer.BeginRecording();

View file

@ -21,6 +21,8 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
import static org.lwjgl.util.vma.Vma.VMA_MEMORY_USAGE_AUTO;
import static org.lwjgl.vulkan.VK13.*; import static org.lwjgl.vulkan.VK13.*;
public class ModelsCache { public class ModelsCache {
@ -70,10 +72,10 @@ public class ModelsCache {
private static TransferBuffer CreateVerticesBuffer(VulkanContext VkCtx, MeshData meshData, DataInputStream VertexStream) throws IOException { private static TransferBuffer CreateVerticesBuffer(VulkanContext VkCtx, MeshData meshData, DataInputStream VertexStream) throws IOException {
Logger.debug("Creating Vertices Transfer Buffer, Mesh Data -> ID=[{}] VertexSize=[{}]",meshData.ID(),meshData.VertexSize()); Logger.debug("Creating Vertices Transfer Buffer, Mesh Data -> ID=[{}] VertexSize=[{}]",meshData.ID(),meshData.VertexSize());
int BufferSize = meshData.VertexSize(); int BufferSize = meshData.VertexSize();
var SrcBuffer = new VulkanBuffer(VkCtx,BufferSize, var SrcBuffer = new VulkanBuffer(VkCtx,BufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO,VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
var DstBuffer = new VulkanBuffer(VkCtx, BufferSize, var DstBuffer = new VulkanBuffer(VkCtx, BufferSize,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO,0,0);
if (BufferSize <= 0) { if (BufferSize <= 0) {
Logger.error("Computed buffer allocation size cannot be 0. SrcBuffer -> [{}] DstBuffer -> [{}]",SrcBuffer,DstBuffer); Logger.error("Computed buffer allocation size cannot be 0. SrcBuffer -> [{}] DstBuffer -> [{}]",SrcBuffer,DstBuffer);
throw new RuntimeException("Computed buffer allocation size cannot be 0. SrcBuffer -> ["+SrcBuffer+"] DstBuffer -> ["+DstBuffer+"]"); throw new RuntimeException("Computed buffer allocation size cannot be 0. SrcBuffer -> ["+SrcBuffer+"] DstBuffer -> ["+DstBuffer+"]");
@ -96,10 +98,10 @@ public class ModelsCache {
private static TransferBuffer CreateIndicesBuffer(VulkanContext VkCtx, MeshData meshData, DataInputStream IndexStream) throws IOException{ private static TransferBuffer CreateIndicesBuffer(VulkanContext VkCtx, MeshData meshData, DataInputStream IndexStream) throws IOException{
int BufferSize = meshData.IndexSize(); int BufferSize = meshData.IndexSize();
var SrcBuffer = new VulkanBuffer(VkCtx,BufferSize, var SrcBuffer = new VulkanBuffer(VkCtx,BufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO,VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
var DstBuffer = new VulkanBuffer(VkCtx, BufferSize, var DstBuffer = new VulkanBuffer(VkCtx, BufferSize,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO,0,0);
long MappedMemory = SrcBuffer.MapMemory(VkCtx); long MappedMemory = SrcBuffer.MapMemory(VkCtx);
IntBuffer data = MemoryUtil.memIntBuffer(MappedMemory,(int) SrcBuffer.GetRequestedSize()); IntBuffer data = MemoryUtil.memIntBuffer(MappedMemory,(int) SrcBuffer.GetRequestedSize());

View file

@ -5,6 +5,8 @@ import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device;
import org.lwjgl.PointerBuffer; import org.lwjgl.PointerBuffer;
import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import org.lwjgl.util.vma.VmaAllocationCreateInfo;
import org.lwjgl.util.vma.VmaAllocatorCreateInfo;
import org.lwjgl.vulkan.VkBufferCreateInfo; import org.lwjgl.vulkan.VkBufferCreateInfo;
import org.lwjgl.vulkan.VkDevice; import org.lwjgl.vulkan.VkDevice;
import org.lwjgl.vulkan.VkMemoryAllocateInfo; import org.lwjgl.vulkan.VkMemoryAllocateInfo;
@ -15,31 +17,46 @@ import java.nio.LongBuffer;
import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck; import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck;
import static org.lwjgl.system.MemoryUtil.NULL; import static org.lwjgl.system.MemoryUtil.NULL;
import static org.lwjgl.util.vma.Vma.*;
import static org.lwjgl.vulkan.VK13.*; import static org.lwjgl.vulkan.VK13.*;
public class VulkanBuffer { public class VulkanBuffer {
private final long AllocationSize;
private final long Allocation;
//private final long AllocationSize;
private final long Buffer; private final long Buffer;
private final long Memory; //private final long Memory;
private final PointerBuffer pointerBuffer; private final PointerBuffer pointerBuffer;
private final long RequestedSize; private final long RequestedSize;
private long MappedMemory; private long MappedMemory;
public VulkanBuffer(VulkanContext vulkanContext, long Size, int Usage, int RequestMask){ public VulkanBuffer(VulkanContext vulkanContext, long Size, int BufferUsage,int VmaUsage,int VmaFlags, int RequiredFlags){
RequestedSize = Size; RequestedSize = Size;
MappedMemory = NULL; MappedMemory = NULL;
try(var MemStack = MemoryStack.stackPush()){ try(var MemStack = MemoryStack.stackPush()){
Device device = vulkanContext.GetDevice(); //Device device = vulkanContext.GetDevice();
var BufferCreationInfo = VkBufferCreateInfo.calloc(MemStack) var BufferCreationInfo = VkBufferCreateInfo.calloc(MemStack)
.sType$Default() .sType$Default()
.size(Size) .size(Size)
.usage(Usage) .usage(BufferUsage)
.sharingMode(VK_SHARING_MODE_EXCLUSIVE); .sharingMode(VK_SHARING_MODE_EXCLUSIVE);
LongBuffer LongPointer = MemStack.mallocLong(1); //vkCheck(vkCreateBuffer(device.FetchVulkanDevice(), BufferCreationInfo, null, LongPointer),"Failed to create Vulkan Buffer");
vkCheck(vkCreateBuffer(device.FetchVulkanDevice(), BufferCreationInfo, null, LongPointer),"Failed to create Vulkan Buffer");
Buffer = LongPointer.get(0);
var MemoryRequirements = VkMemoryRequirements.calloc(MemStack); VmaAllocationCreateInfo AllocatorInfo = VmaAllocationCreateInfo.calloc(MemStack)
.usage(VmaUsage)
.flags(VmaFlags)
.requiredFlags(RequiredFlags);
PointerBuffer AllocationPointer = MemStack.callocPointer(1);
LongBuffer LongPointer = MemStack.mallocLong(1);
vkCheck(vmaCreateBuffer(vulkanContext.GetVkMemoryAllocator().GetVmaAllocator(),BufferCreationInfo,AllocatorInfo,LongPointer,AllocationPointer,null),
"Failed to create VMA buffer");
Buffer = LongPointer.get(0);
Allocation = AllocationPointer.get(0);
pointerBuffer = MemoryUtil.memAllocPointer(1);
/* var MemoryRequirements = VkMemoryRequirements.calloc(MemStack);
vkGetBufferMemoryRequirements(device.FetchVulkanDevice(), Buffer, MemoryRequirements); vkGetBufferMemoryRequirements(device.FetchVulkanDevice(), Buffer, MemoryRequirements);
var MemoryAllocation = VkMemoryAllocateInfo.calloc(MemStack) var MemoryAllocation = VkMemoryAllocateInfo.calloc(MemStack)
@ -59,17 +76,18 @@ public class VulkanBuffer {
Logger.error("Vulkan crash blocked: Native memoryHandle cannot be 0! Device out of memory or allocation failed."); Logger.error("Vulkan crash blocked: Native memoryHandle cannot be 0! Device out of memory or allocation failed.");
throw new IllegalArgumentException("Vulkan crash blocked: Native memoryHandle cannot be 0! Device out of memory or allocation failed."); throw new IllegalArgumentException("Vulkan crash blocked: Native memoryHandle cannot be 0! Device out of memory or allocation failed.");
} }
vkCheck(vkBindBufferMemory(device.FetchVulkanDevice(),Buffer,Memory,0),"Failed to Bind Vulkan Memory Buffer"); vkCheck(vkBindBufferMemory(device.FetchVulkanDevice(),Buffer,Memory,0),"Failed to Bind Vulkan Memory Buffer");*/
} }
} }
public void cleanup(VulkanContext vulkanContext){ public void cleanup(VulkanContext vulkanContext){
MemoryUtil.memFree(pointerBuffer); MemoryUtil.memFree(pointerBuffer);
VkDevice vulkanDevice = vulkanContext.GetDevice().FetchVulkanDevice(); UnMapMemory(vulkanContext);
vkDestroyBuffer(vulkanDevice,Buffer, null); vmaDestroyBuffer(vulkanContext.GetVkMemoryAllocator().GetVmaAllocator(), Buffer, Allocation);
vkFreeMemory(vulkanDevice, Memory, null);
Logger.debug("Freed Vulkan Memory Buffer"); Logger.debug("Freed Vulkan Memory Buffer");
} }
public void Flush(VulkanContext VkCtx){
vmaFlushAllocation(VkCtx.GetVkMemoryAllocator().GetVmaAllocator(),Allocation,0,VK_WHOLE_SIZE);
}
public long GetBuffer(){ public long GetBuffer(){
return Buffer; return Buffer;
} }
@ -78,14 +96,14 @@ public class VulkanBuffer {
} }
public long MapMemory(VulkanContext vulkanContext){ public long MapMemory(VulkanContext vulkanContext){
if(MappedMemory == NULL){ if(MappedMemory == NULL){
vkCheck(vkMapMemory(vulkanContext.GetDevice().FetchVulkanDevice(), Memory,0,AllocationSize,0,pointerBuffer),"Failed to map Vulkan Buffer"); vkCheck(vmaMapMemory(vulkanContext.GetVkMemoryAllocator().GetVmaAllocator(),Allocation,pointerBuffer),"Failed to map Vulkan Buffer");
MappedMemory = pointerBuffer.get(0); MappedMemory = pointerBuffer.get(0);
} }
return MappedMemory; return MappedMemory;
} }
public void UnMapMemory(VulkanContext vulkanContext){ public void UnMapMemory(VulkanContext vulkanContext){
if(MappedMemory != NULL){ if(MappedMemory != NULL){
vkUnmapMemory(vulkanContext.GetDevice().FetchVulkanDevice(), Memory); vmaUnmapMemory(vulkanContext.GetVkMemoryAllocator().GetVmaAllocator(),Allocation);
MappedMemory = NULL; MappedMemory = NULL;
} }
} }

View file

@ -0,0 +1,41 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Util;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.PhysicalDevice;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.VulkanInstance;
import org.lwjgl.PointerBuffer;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.util.vma.VmaAllocatorCreateInfo;
import org.lwjgl.util.vma.VmaVulkanFunctions;
import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck;
import static org.lwjgl.util.vma.Vma.vmaCreateAllocator;
import static org.lwjgl.util.vma.Vma.vmaDestroyAllocator;
import static org.lwjgl.vulkan.VK13.VK_API_VERSION_1_3;
public class VulkanMemoryAllocator {
private final long VmaAllocator;
public VulkanMemoryAllocator(VulkanInstance Instance, PhysicalDevice physicalDevice, Device device){
try(var MemStack = MemoryStack.stackPush()){
PointerBuffer AllocatorPointer = MemStack.mallocPointer(1);
var vmaVulkanFunctions = VmaVulkanFunctions.calloc(MemStack)
.set(Instance.getVkInstance(),device.FetchVulkanDevice());
var AllocatorCreateInfo = VmaAllocatorCreateInfo.calloc(MemStack)
.instance(Instance.getVkInstance())
.vulkanApiVersion(VK_API_VERSION_1_3)
.device(device.FetchVulkanDevice())
.physicalDevice(physicalDevice.GetPhysicalDevice())
.pVulkanFunctions(vmaVulkanFunctions);
vkCheck(vmaCreateAllocator(AllocatorCreateInfo,AllocatorPointer),"Failed to create Vulkan Memory Allocator");
VmaAllocator = AllocatorPointer.get(0);
}
}
public void CleanUp(){
vmaDestroyAllocator(VmaAllocator);
}
public long GetVmaAllocator(){
return VmaAllocator;
}
}

View file

@ -13,6 +13,8 @@ import org.lwjgl.vulkan.*;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Locale; import java.util.Locale;
import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
import static org.lwjgl.util.vma.Vma.VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
import static org.lwjgl.vulkan.VK13.*; import static org.lwjgl.vulkan.VK13.*;
public class VulkanUtils { public class VulkanUtils {
@ -38,7 +40,7 @@ public class VulkanUtils {
descriptorAllocator.AddDescriptorSets(device, ID, BufferCount, layout); descriptorAllocator.AddDescriptorSets(device, ID, BufferCount, layout);
DescriptorSetLayout.LayoutInformation LayoutInfo = layout.GetLayoutInfo(); DescriptorSetLayout.LayoutInformation LayoutInfo = layout.GetLayoutInfo();
for(int i = 0; i < BufferCount; i++){ for(int i = 0; i < BufferCount; i++){
Result[i] = new VulkanBuffer(VkCtx, BufferSize, Usage, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); Result[i] = new VulkanBuffer(VkCtx, BufferSize, Usage,VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
DescriptorSet descriptorSet = descriptorAllocator.GetDescriptorSet(ID, i); DescriptorSet descriptorSet = descriptorAllocator.GetDescriptorSet(ID, i);
descriptorSet.SetBuffer(device, Result[i], Result[i].GetRequestedSize(), layout.GetLayoutInfo().Binding(),layout.GetLayoutInfo().DescriptorType()); descriptorSet.SetBuffer(device, Result[i], Result[i].GetRequestedSize(), layout.GetLayoutInfo().Binding(),layout.GetLayoutInfo().DescriptorType());
@ -46,7 +48,7 @@ public class VulkanUtils {
return Result; return Result;
} }
public static VulkanBuffer CreateHostVisibleBuffer(VulkanContext VkCtx, long BufferSize, int Usage, String ID, DescriptorSetLayout layout){ public static VulkanBuffer CreateHostVisibleBuffer(VulkanContext VkCtx, long BufferSize, int Usage, String ID, DescriptorSetLayout layout){
var Buffer = new VulkanBuffer(VkCtx, BufferSize, Usage, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); var Buffer = new VulkanBuffer(VkCtx, BufferSize, Usage,VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
Device device = VkCtx.GetDevice(); Device device = VkCtx.GetDevice();
DescriptorSet descriptorSet = VkCtx.GetDescriptorAllocator().AddDescriptorSet(device, ID, layout); DescriptorSet descriptorSet = VkCtx.GetDescriptorAllocator().AddDescriptorSet(device, ID, layout);
descriptorSet.SetBuffer(device, Buffer, Buffer.GetRequestedSize(), layout.GetLayoutInfo().Binding(),layout.GetLayoutInfo().DescriptorType()); descriptorSet.SetBuffer(device, Buffer, Buffer.GetRequestedSize(), layout.GetLayoutInfo().Binding(),layout.GetLayoutInfo().DescriptorType());

View file

@ -34,7 +34,7 @@ PhysicalDeviceName=
#3D Projection Properties #3D Projection Properties
field_of_view=60.0f field_of_view=60.0f
z_near_plane=1.0f z_near_plane=0.10f
z_far_plane=100.0f z_far_plane=1000.0f