Vulkan surface, this is what displays an image to the screen, working on queues next

This commit is contained in:
Harrison Corlett 2026-01-19 14:33:43 +00:00
parent 6717970a23
commit 934f949881
2 changed files with 149 additions and 4 deletions

View file

@ -1,25 +1,33 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import org.lwjgl.PointerBuffer;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.VkDevice;
import org.lwjgl.vulkan.VkDeviceCreateInfo;
import org.lwjgl.vulkan.VkDeviceQueueCreateInfo;
import org.lwjgl.vulkan.VkExtensionProperties;
import org.tinylog.Logger;
import java.awt.*;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck;
import static org.lwjgl.vulkan.VK10.vkCreateDevice;
import static org.lwjgl.vulkan.KHRPortabilitySubset.VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME;
import static org.lwjgl.vulkan.VK10.*;
public class Device {
VkDevice VulkanDevice;
private final VkDevice VulkanDevice;
public Device(PhysicalDevice PhysDevice){
PointerBuffer RequiredExtensions = null; // to be finished later
Logger.debug("Creating Device Interface Layer");
try (var MemStack = MemoryStack.stackPush()) {
PointerBuffer RequiredExtensions = CreateRequiredExtensions(PhysDevice, MemStack);
var QueuePropertyBuffer = PhysDevice.GetQueueFamilyProperties();
int QueueFamilyCount = QueuePropertyBuffer.capacity();
var QueueCreationInfoBuffer = VkDeviceQueueCreateInfo.calloc(QueueFamilyCount, MemStack);
@ -39,6 +47,62 @@ public class Device {
VulkanDevice = new VkDevice(pp.get(0), PhysDevice.GetPhysicalDevice(), DeviceCreateInfo);
}
}
private static PointerBuffer CreateRequiredExtensions(PhysicalDevice PhysDevice, MemoryStack MemStack){
Set<String> DeviceExtensions = GetDeviceExtensions(PhysDevice);
//cross platform support for that fuckass Metal API mac uses
boolean UsePortability = DeviceExtensions.contains(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) && VulkanUtils.getOS() == VulkanUtils.OSType.MACOS;
var ExtentionList = new ArrayList<ByteBuffer>();
for(String Extension : PhysicalDevice.REQUIRED_EXTENSIONS){
ExtentionList.add(MemStack.ASCII(Extension));
}
if (UsePortability){
ExtentionList.add(MemStack.ASCII(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME));
}
PointerBuffer RequiredExtensions = MemStack.mallocPointer(ExtentionList.size());
ExtentionList.forEach(RequiredExtensions::put);
RequiredExtensions.flip();
return RequiredExtensions;
}
private static Set<String> GetDeviceExtensions(PhysicalDevice PhysDevice){
Set<String> DeviceExtensions = new HashSet<>();
try(var MemStack = MemoryStack.stackPush()){
IntBuffer ExtensionsBufferCount = MemStack.callocInt(1);
vkEnumerateDeviceExtensionProperties(PhysDevice.GetPhysicalDevice(),(String) null, ExtensionsBufferCount, null);
int ExtensionCount = ExtensionsBufferCount.get(0);
Logger.trace("Device supports [{}] number of extensions", ExtensionCount);
try(var PropertiesBuffer = VkExtensionProperties.calloc(ExtensionCount)){
vkEnumerateDeviceExtensionProperties(PhysDevice.GetPhysicalDevice(), (String) null, ExtensionsBufferCount,PropertiesBuffer);
for(int i = 0; i < ExtensionCount; i++){
VkExtensionProperties Properties = PropertiesBuffer.get(i);
String ExtensionName = Properties.extensionNameString();
DeviceExtensions.add(ExtensionName);
Logger.trace("[{}] is a supported extension", ExtensionCount);
}
}
}
return DeviceExtensions;
}
public void cleanup(){
Logger.debug("Removing Vulkan Device");
vkDestroyDevice(VulkanDevice,null);
}
public VkDevice FetchVulkanDevice()
{
return VulkanDevice;
}
public void waitIdle(){
vkDeviceWaitIdle(VulkanDevice);
}
}

View file

@ -1,4 +1,85 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Structure;
import net.halbear.Terrain4J.EngineCore.Display.Window;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.PhysicalDevice;
import org.lwjgl.glfw.GLFWVulkan;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.KHRSurface;
import org.lwjgl.vulkan.VkSurfaceCapabilitiesKHR;
import org.lwjgl.vulkan.VkSurfaceFormatKHR;
import org.tinylog.Logger;
import java.awt.*;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck;
import static org.lwjgl.vulkan.VK10.VK_FORMAT_B8G8R8A8_SRGB;
public class Surface {
private final VkSurfaceCapabilitiesKHR SurfaceCapabilities;
private final SurfaceFormat SurfaceFormatVar;
private final long VulkanSurface;
public record SurfaceFormat(int ImageFormat, int ColourSpace){
}
public Surface(VulkanInstance VkInstance, PhysicalDevice PhysDevice, Window window){
Logger.debug("Creating Vulkan Surface");
try(var MemStack = MemoryStack.stackPush()){
LongBuffer SurfacePtr = MemStack.mallocLong(1);
GLFWVulkan.glfwCreateWindowSurface(VkInstance.getVkInstance(), window.getHandle(), null, SurfacePtr);
VulkanSurface = SurfacePtr.get(0);
SurfaceCapabilities = VkSurfaceCapabilitiesKHR.calloc();
vkCheck(KHRSurface.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(PhysDevice.GetPhysicalDevice(), VulkanSurface,SurfaceCapabilities),"Failed to get surface capabilities");
SurfaceFormatVar = CalculateSurfaceFormat(PhysDevice, VulkanSurface);
}
}
public static SurfaceFormat CalculateSurfaceFormat(PhysicalDevice PhysDevice, long VulkanSurface){
int ImageFormat;
int ColourSpace ;
try(var MemStack = MemoryStack.stackPush()){
IntBuffer IntPointer = MemStack.mallocInt(1);
vkCheck(KHRSurface.vkGetPhysicalDeviceSurfaceFormatsKHR(PhysDevice.GetPhysicalDevice(), VulkanSurface, IntPointer, null),"Failed to get number of surface formats");
int SurfaceFormatCount = IntPointer.get(0);
if (SurfaceFormatCount <= 0){
throw new RuntimeException("Vulkan Error: Unable to locate and surface formats");
}
var SurfaceFormats = VkSurfaceFormatKHR.calloc(SurfaceFormatCount, MemStack);
vkCheck(KHRSurface.vkGetPhysicalDeviceSurfaceFormatsKHR(PhysDevice.GetPhysicalDevice(),VulkanSurface, IntPointer, SurfaceFormats), "Failed to get surface formats");
ImageFormat = VK_FORMAT_B8G8R8A8_SRGB;
ColourSpace = SurfaceFormats.get(0).colorSpace();
for(int i = 0; i < SurfaceFormatCount; i++){
VkSurfaceFormatKHR SurfaceFormatKHR = SurfaceFormats.get(i);
if (SurfaceFormatKHR.format() == VK_FORMAT_B8G8R8A8_SRGB && SurfaceFormatKHR.colorSpace() == KHRSurface.VK_COLOR_SPACE_SRGB_NONLINEAR_KHR){
ImageFormat = SurfaceFormatKHR.format();
ColourSpace = SurfaceFormatKHR.colorSpace();
break;
}
}
}
return new SurfaceFormat(ImageFormat, ColourSpace);
}
public void cleanup(VulkanInstance instance){
Logger.debug("Cleaning Up Surfaces");
SurfaceCapabilities.free();
KHRSurface.vkDestroySurfaceKHR(instance.getVkInstance(), VulkanSurface, null);
}
public VkSurfaceCapabilitiesKHR GetSurfaceCapabilities(){
return SurfaceCapabilities;
}
public SurfaceFormat GetSurfaceFormat(){
return SurfaceFormatVar;
}
public long GetVkSurface(){
return VulkanSurface;
}
}