Start work on the Device Interface Layer, the layers go
Instance -> PhysicalDevice -> Device
This commit is contained in:
parent
9f4c78aae2
commit
d8653120d2
2 changed files with 168 additions and 5 deletions
|
|
@ -1,4 +1,44 @@
|
||||||
package net.halbear.Terrain4J.EngineCore.VulkanDeviceManagement;
|
package net.halbear.Terrain4J.EngineCore.VulkanDeviceManagement;
|
||||||
|
|
||||||
|
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.tinylog.Logger;
|
||||||
|
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
|
import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck;
|
||||||
|
import static org.lwjgl.vulkan.VK10.vkCreateDevice;
|
||||||
|
|
||||||
public class Device {
|
public class Device {
|
||||||
|
VkDevice VulkanDevice;
|
||||||
|
|
||||||
|
public Device(PhysicalDevice PhysDevice){
|
||||||
|
PointerBuffer RequiredExtensions = null; // to be finished later
|
||||||
|
|
||||||
|
Logger.debug("Creating Device Interface Layer");
|
||||||
|
try (var MemStack = MemoryStack.stackPush()) {
|
||||||
|
var QueuePropertyBuffer = PhysDevice.GetQueueFamilyProperties();
|
||||||
|
int QueueFamilyCount = QueuePropertyBuffer.capacity();
|
||||||
|
var QueueCreationInfoBuffer = VkDeviceQueueCreateInfo.calloc(QueueFamilyCount, MemStack);
|
||||||
|
for(int i = 0; i < QueueFamilyCount; i++){
|
||||||
|
FloatBuffer Priorities = MemStack.callocFloat(QueuePropertyBuffer.get(i).queueCount());
|
||||||
|
QueueCreationInfoBuffer.get(i)
|
||||||
|
.sType$Default()
|
||||||
|
.queueFamilyIndex(i)
|
||||||
|
.pQueuePriorities(Priorities);
|
||||||
}
|
}
|
||||||
|
var DeviceCreateInfo = VkDeviceCreateInfo.calloc(MemStack)
|
||||||
|
.sType$Default()
|
||||||
|
.ppEnabledExtensionNames(RequiredExtensions)
|
||||||
|
.pQueueCreateInfos(QueueCreationInfoBuffer);
|
||||||
|
PointerBuffer pp = MemStack.mallocPointer(1);
|
||||||
|
vkCheck(vkCreateDevice(PhysDevice.GetPhysicalDevice(), DeviceCreateInfo, null, pp), "Failed to create device");
|
||||||
|
VulkanDevice = new VkDevice(pp.get(0), PhysDevice.GetPhysicalDevice(), DeviceCreateInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,34 +3,99 @@ package net.halbear.Terrain4J.EngineCore.VulkanDeviceManagement;
|
||||||
import net.halbear.Terrain4J.EngineCore.Display.VulkanInstance;
|
import net.halbear.Terrain4J.EngineCore.Display.VulkanInstance;
|
||||||
import org.lwjgl.PointerBuffer;
|
import org.lwjgl.PointerBuffer;
|
||||||
import org.lwjgl.system.MemoryStack;
|
import org.lwjgl.system.MemoryStack;
|
||||||
import org.lwjgl.vulkan.VkPhysicalDevice;
|
import org.lwjgl.vulkan.*;
|
||||||
|
import org.tinylog.Logger;
|
||||||
|
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
import java.sql.Array;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck;
|
import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck;
|
||||||
import static org.lwjgl.vulkan.VK10.vkEnumeratePhysicalDevices;
|
import static org.lwjgl.vulkan.VK10.*;
|
||||||
|
import static org.lwjgl.vulkan.VK11.vkGetPhysicalDeviceProperties2;
|
||||||
|
import static org.lwjgl.vulkan.VK11.vkGetPhysicalDeviceQueueFamilyProperties2;
|
||||||
|
|
||||||
public class PhysicalDevice {
|
public class PhysicalDevice {
|
||||||
|
private final VkExtensionProperties.Buffer vkDeviceExtensions;
|
||||||
|
private final VkPhysicalDeviceMemoryProperties vkMemoryProperties;
|
||||||
|
private final VkPhysicalDevice vkPhysicalDevice;
|
||||||
|
private final VkPhysicalDeviceFeatures vkPhysicalDeviceFeatures;
|
||||||
|
private final VkPhysicalDeviceProperties2 vkPhysicalDeviceProperties;
|
||||||
|
private final VkQueueFamilyProperties.Buffer vkQueueFamilyProperties;
|
||||||
|
|
||||||
|
protected static final Set<String> REQUIRED_EXTENSIONS;
|
||||||
|
|
||||||
|
static{
|
||||||
|
REQUIRED_EXTENSIONS = new HashSet<>();
|
||||||
|
REQUIRED_EXTENSIONS.add(KHRSwapchain.VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
private PhysicalDevice(VkPhysicalDevice VulkanPhysicalDevice){
|
private PhysicalDevice(VkPhysicalDevice VulkanPhysicalDevice){
|
||||||
|
try(var MemStack = MemoryStack.stackPush()){
|
||||||
|
this.vkPhysicalDevice = VulkanPhysicalDevice;
|
||||||
|
IntBuffer intBuffer = MemStack.mallocInt(1);
|
||||||
|
vkPhysicalDeviceProperties = VkPhysicalDeviceProperties2.calloc().sType$Default();
|
||||||
|
vkGetPhysicalDeviceProperties2(vkPhysicalDevice, vkPhysicalDeviceProperties);
|
||||||
|
|
||||||
|
vkCheck(vkEnumerateDeviceExtensionProperties(vkPhysicalDevice, (String)null, intBuffer, null), "Failed to get extension property count");
|
||||||
|
vkDeviceExtensions = VkExtensionProperties.calloc(intBuffer.get(0));
|
||||||
|
vkCheck(vkEnumerateDeviceExtensionProperties(vkPhysicalDevice, (String)null, intBuffer, vkDeviceExtensions), "Failed to get extension property");
|
||||||
|
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, intBuffer, null);
|
||||||
|
vkQueueFamilyProperties = VkQueueFamilyProperties.calloc(intBuffer.get(0));
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, intBuffer, vkQueueFamilyProperties);
|
||||||
|
|
||||||
|
vkPhysicalDeviceFeatures = VkPhysicalDeviceFeatures.calloc();
|
||||||
|
vkGetPhysicalDeviceFeatures(vkPhysicalDevice, vkPhysicalDeviceFeatures);
|
||||||
|
|
||||||
|
vkMemoryProperties = VkPhysicalDeviceMemoryProperties.calloc();
|
||||||
|
vkGetPhysicalDeviceMemoryProperties(vkPhysicalDevice, vkMemoryProperties);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PhysicalDevice createPhysicalDevice(VulkanInstance instance, String PreferredDeviceName){
|
public static PhysicalDevice createPhysicalDevice(VulkanInstance instance, String PreferredDeviceName){
|
||||||
|
Logger.debug("selecting physical devices");
|
||||||
PhysicalDevice result = null;
|
PhysicalDevice result = null;
|
||||||
try (var MemStack = MemoryStack.stackPush()){
|
try (var MemStack = MemoryStack.stackPush()){
|
||||||
PointerBuffer PointerPhyiscalDevices = getPhysicalDevices(instance, MemStack);
|
PointerBuffer PointerPhyiscalDevices = getPhysicalDevices(instance, MemStack);
|
||||||
int DeviceCount = PointerPhyiscalDevices.capacity();
|
int DeviceCount = PointerPhyiscalDevices.capacity();
|
||||||
|
|
||||||
var physDevices = new ArrayList<PhysicalDevice>();
|
var PhysicalDevices = new ArrayList<PhysicalDevice>();
|
||||||
for(int i = 0; i < DeviceCount; i++){
|
for(int i = 0; i < DeviceCount; i++){
|
||||||
var vkPhysicalDevice = new VkPhysicalDevice(PointerPhyiscalDevices.get(i),instance.getVkInstance());
|
var vkPhysicalDevice = new VkPhysicalDevice(PointerPhyiscalDevices.get(i),instance.getVkInstance());
|
||||||
var PhysDevice = new PhysicalDevice(vkPhysicalDevice);
|
var PhysDevice = new PhysicalDevice(vkPhysicalDevice);
|
||||||
|
|
||||||
|
String DeviceName = PhysDevice.FetchDeviceName();
|
||||||
|
if(!PhysDevice.HasGraphicsQueueFamily()){
|
||||||
|
Logger.debug("Device [{}] does not support graphics queue family",DeviceName);
|
||||||
|
PhysDevice.cleanup();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!PhysDevice.SupportsExtensions(REQUIRED_EXTENSIONS)){
|
||||||
|
Logger.debug("Device [{}] does not support some required extensions",DeviceName);
|
||||||
|
PhysDevice.cleanup();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(PreferredDeviceName != null && PreferredDeviceName.equals(DeviceName)){
|
||||||
|
result = PhysDevice;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(PhysDevice.vkPhysicalDeviceProperties.properties().deviceType() == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU){
|
||||||
|
PhysicalDevices.addFirst(PhysDevice);
|
||||||
|
} else{
|
||||||
|
PhysicalDevices.add(PhysDevice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
result = result == null && !PhysicalDevices.isEmpty() ? PhysicalDevices.removeFirst() : result;
|
||||||
|
PhysicalDevices.forEach(PhysicalDevice::cleanup);
|
||||||
|
if (result == null){
|
||||||
|
throw new RuntimeException("No Graphics Driver Found!");
|
||||||
|
}
|
||||||
|
Logger.debug("Selected Graphics Driver: [{}]", result.FetchDeviceName());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PointerBuffer getPhysicalDevices(VulkanInstance instance, MemoryStack MemStack){
|
public static PointerBuffer getPhysicalDevices(VulkanInstance instance, MemoryStack MemStack){
|
||||||
|
|
@ -38,8 +103,66 @@ public class PhysicalDevice {
|
||||||
IntBuffer intBuffer = MemStack.mallocInt(1);
|
IntBuffer intBuffer = MemStack.mallocInt(1);
|
||||||
vkCheck(vkEnumeratePhysicalDevices(instance.getVkInstance(),intBuffer,null),"Failed to fetch physical device count");
|
vkCheck(vkEnumeratePhysicalDevices(instance.getVkInstance(),intBuffer,null),"Failed to fetch physical device count");
|
||||||
int DeviceCount = intBuffer.get(0);
|
int DeviceCount = intBuffer.get(0);
|
||||||
|
Logger.debug("Detected Physical Device Count: {}",DeviceCount);
|
||||||
PointerPhysicalDevices = MemStack.mallocPointer(DeviceCount);
|
PointerPhysicalDevices = MemStack.mallocPointer(DeviceCount);
|
||||||
vkCheck(vkEnumeratePhysicalDevices(instance.getVkInstance(),intBuffer,PointerPhysicalDevices),"Failed to fetch physical devices");
|
vkCheck(vkEnumeratePhysicalDevices(instance.getVkInstance(),intBuffer,PointerPhysicalDevices),"Failed to fetch physical devices");
|
||||||
return PointerPhysicalDevices;
|
return PointerPhysicalDevices;
|
||||||
}
|
}
|
||||||
|
//Display Drivers have specific queues for specific tasks organised into "families", this makes sure the gpu can push queues that process graphics
|
||||||
|
private boolean HasGraphicsQueueFamily(){
|
||||||
|
boolean CanHanldeGraphicsQueues = false;
|
||||||
|
int FamilyCount = vkQueueFamilyProperties != null ? vkQueueFamilyProperties.capacity() : 0;
|
||||||
|
for(int i = 0; i < FamilyCount; i ++){
|
||||||
|
VkQueueFamilyProperties FamilyProperties = vkQueueFamilyProperties.get(i);
|
||||||
|
if((FamilyProperties.queueFlags() & VK_QUEUE_GRAPHICS_BIT) != 0){
|
||||||
|
CanHanldeGraphicsQueues = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CanHanldeGraphicsQueues;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean SupportsExtensions(Set<String> Extensions){
|
||||||
|
var ExtensionsClone = new HashSet<>(Extensions);
|
||||||
|
int ExtensionCount = vkDeviceExtensions != null ? vkDeviceExtensions.capacity() : 0;
|
||||||
|
for(int i = 0; i < ExtensionCount; i++){
|
||||||
|
String ExtensionName = vkDeviceExtensions.get(i).extensionNameString();
|
||||||
|
ExtensionsClone.remove(ExtensionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean AllSupported = ExtensionsClone.isEmpty();
|
||||||
|
if (!AllSupported){
|
||||||
|
Logger.debug("A detected [{}] number of extensions are not compatible with the device [{}]",ExtensionsClone.iterator().next(), FetchDeviceName());
|
||||||
|
}
|
||||||
|
return AllSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanup(){
|
||||||
|
Logger.debug("freeing physical device [{}]", FetchDeviceName());
|
||||||
|
vkMemoryProperties.free();
|
||||||
|
vkPhysicalDeviceFeatures.free();
|
||||||
|
vkQueueFamilyProperties.free();
|
||||||
|
vkDeviceExtensions.free();
|
||||||
|
vkPhysicalDeviceProperties.free();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String FetchDeviceName(){
|
||||||
|
return vkPhysicalDeviceProperties.properties().deviceNameString();
|
||||||
|
}
|
||||||
|
public VkPhysicalDeviceMemoryProperties GetMemoryProperties(){
|
||||||
|
return vkMemoryProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VkPhysicalDevice GetPhysicalDevice(){
|
||||||
|
return vkPhysicalDevice;
|
||||||
|
}
|
||||||
|
public VkPhysicalDeviceFeatures GetPhysicalDeviceFeatures(){
|
||||||
|
return vkPhysicalDeviceFeatures;
|
||||||
|
}
|
||||||
|
public VkPhysicalDeviceProperties2 GetPhysicalDeviceProperties(){
|
||||||
|
return vkPhysicalDeviceProperties;
|
||||||
|
}
|
||||||
|
public VkQueueFamilyProperties.Buffer GetQueueFamilyProperties(){
|
||||||
|
return vkQueueFamilyProperties;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue