1 module sbylib.graphics.wrapper.device; 2 3 import std; 4 import erupted; 5 import sbylib.wrapper.vulkan; 6 import sbylib.wrapper.glfw : Window, GLFW; 7 import sbylib.graphics.layer; 8 import sbylib.graphics.util.functions; 9 import sbylib.graphics.wrapper.fence; 10 import sbylib.graphics.wrapper.queue; 11 12 class VDevice { 13 14 struct CreateInfo { 15 VkPhysicalDeviceFeatures features; 16 LayerSettings layerSettings; 17 string appName; 18 uint appVersion; 19 } 20 21 Instance instance; 22 PhysicalDevice gpu; 23 Device device; 24 alias device this; 25 26 private LayerSettings layerSettings; 27 28 mixin ImplResourceStack; 29 30 static void initialize(CreateInfo info, Window window) { 31 import erupted.vulkan_lib_loader : loadGlobalLevelFunctions; 32 33 const globalFunctionLoaded = loadGlobalLevelFunctions(); 34 assert(globalFunctionLoaded); 35 36 info.layerSettings.settings ~= new StandardValidationLayerSetting; 37 info.layerSettings.settings ~= new KhronosValidationLayerSetting; 38 scope (exit) info.layerSettings.finalize(); 39 40 Instance.CreateInfo instanceCreateInfo = { 41 applicationInfo: { 42 applicationName: info.appName, 43 applicationVersion: info.appVersion, 44 engineName: "sbylib", 45 engineVersion: VK_MAKE_VERSION(1,0,0), 46 apiVersion : VK_API_VERSION_1_0 47 }, 48 enabledLayerNames: info.layerSettings.use(), 49 enabledExtensionNames: GLFW.getRequiredInstanceExtensions() ~ ["VK_EXT_debug_report"] 50 }; 51 52 enforce(instanceCreateInfo.enabledLayerNames.all!(n => 53 LayerProperties.getAvailableInstanceLayerProperties().canFind!(l => l.layerName == n))); 54 55 auto instance = new Instance(instanceCreateInfo); 56 57 inst = new VDevice(instance, info.features, window); 58 } 59 60 static void deinitialize() { 61 inst.destroyStack(); 62 } 63 64 private static typeof(this) inst; 65 66 static typeof(this) opCall() { 67 return inst; 68 } 69 70 private this(Instance instance, VkPhysicalDeviceFeatures feature, Window window) { 71 this.instance = instance; 72 73 auto surface = window.createSurface(instance); 74 scope (exit) 75 surface.destroy(); 76 77 this.gpu = instance.findPhysicalDevice!((PhysicalDevice gpu) => gpu.getSurfaceSupport(surface)); 78 79 this.device = createDevice(feature); 80 81 pushResource(instance); 82 pushResource(device); 83 } 84 85 public uint findQueueFamilyIndex(QueueFamilyProperties.Flags flags) { 86 return gpu.findQueueFamilyIndex!(prop => prop.supports(flags)); 87 } 88 89 private Device createDevice(VkPhysicalDeviceFeatures features) { 90 auto graphicsQueueFamilyIndex = findQueueFamilyIndex(QueueFamilyProperties.Flags.Graphics); 91 auto computeQueueFamilyIndex = findQueueFamilyIndex(QueueFamilyProperties.Flags.Compute); 92 Device.QueueCreateInfo[] queueCreateInfos = [{ 93 queuePriorities: [0.0f], 94 queueFamilyIndex: graphicsQueueFamilyIndex, 95 }]; 96 if (graphicsQueueFamilyIndex != computeQueueFamilyIndex) { 97 Device.QueueCreateInfo computeQueueCreateInfo = { 98 queuePriorities: [0.0f], 99 queueFamilyIndex: computeQueueFamilyIndex, 100 }; 101 queueCreateInfos ~= computeQueueCreateInfo; 102 } 103 Device.DeviceCreateInfo deviceCreateInfo = { 104 queueCreateInfos: queueCreateInfos, 105 enabledExtensionNames: ["VK_KHR_swapchain", "VK_EXT_debug_marker"], 106 pEnabledFeatures: &features 107 }; 108 return new Device(gpu, deviceCreateInfo); 109 } 110 }