/// <summary> /// Gets the version-aware features associated with the physical device. /// </summary> /// <param name="device">The device to get the features for.</param> /// <param name="props">The Vulkan 1.0 features.</param> /// <param name="props11">The Vulkan 1.1 features.</param> /// <param name="props12">The Vulkan 1.2 features.</param> public static void GetFeatures(VkPhysicalDevice device, out VkPhysicalDeviceFeatures feats, out VkPhysicalDeviceVulkan11Features feats11, out VkPhysicalDeviceVulkan12Features feats12) { if (!device) { throw new ArgumentNullException(nameof(device), "Cannot pass null device or device handle"); } VkPhysicalDeviceFeatures.New(out feats); VkPhysicalDeviceVulkan11Features.New(out feats11); VkPhysicalDeviceVulkan12Features.New(out feats12); var version = device.Parent.Functions.CoreVersion; // 1.0 if (version < VkVersion.VK_VERSION_1_1) { device.GetPhysicalDeviceFeatures(out feats); } // 1.1 else if (version < VkVersion.VK_VERSION_1_2) { VkPhysicalDeviceFeatures2.New(out var feats2); fixed(VkPhysicalDeviceVulkan11Features *ptr11 = &feats11) { feats2.pNext = ptr11; device.GetPhysicalDeviceFeatures2(&feats2); feats = feats2.Features; } } // 1.2 else { VkPhysicalDeviceFeatures2.New(out var feats2); fixed(VkPhysicalDeviceVulkan11Features *ptr11 = &feats11) fixed(VkPhysicalDeviceVulkan12Features * ptr12 = &feats12) { feats2.pNext = ptr11; ptr11->pNext = ptr12; device.GetPhysicalDeviceFeatures2(&feats2); feats = feats2.Features; ptr11->pNext = null; } } }
private void CreateLogicalDevice() { QueueFamilyIndices indices = this.FindQueueFamilies(physicalDevice); List <VkDeviceQueueCreateInfo> queueCreateInfos = new List <VkDeviceQueueCreateInfo>(); HashSet <uint> uniqueQueueFamilies = new HashSet <uint>() { indices.graphicsFamily.Value, indices.presentFamily.Value }; float queuePriority = 1.0f; foreach (uint queueFamily in uniqueQueueFamilies) { VkDeviceQueueCreateInfo queueCreateInfo = new VkDeviceQueueCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, queueFamilyIndex = queueFamily, queueCount = 1, pQueuePriorities = &queuePriority, }; queueCreateInfos.Add(queueCreateInfo); } VkPhysicalDeviceFeatures deviceFeatures = default; // Raytracing extensions VkPhysicalDeviceRayTracingFeaturesKHR deviceRayTracingFeatures = new VkPhysicalDeviceRayTracingFeaturesKHR() { sType = VkStructureType.VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR, pNext = null, rayTracing = true, }; VkPhysicalDeviceVulkan12Features deviceVulkan12Features = new VkPhysicalDeviceVulkan12Features() { sType = VkStructureType.VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, pNext = &deviceRayTracingFeatures, bufferDeviceAddress = true, }; int deviceExtensionsCount = deviceExtensions.Length; IntPtr *deviceExtensionsArray = stackalloc IntPtr[deviceExtensionsCount]; for (int i = 0; i < deviceExtensionsCount; i++) { string extension = deviceExtensions[i]; deviceExtensionsArray[i] = Marshal.StringToHGlobalAnsi(extension); } VkDeviceCreateInfo createInfo = new VkDeviceCreateInfo(); createInfo.sType = VkStructureType.VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; createInfo.pNext = &deviceVulkan12Features; VkDeviceQueueCreateInfo[] queueCreateInfosArray = queueCreateInfos.ToArray(); fixed(VkDeviceQueueCreateInfo *queueCreateInfosArrayPtr = &queueCreateInfosArray[0]) { createInfo.queueCreateInfoCount = (uint)queueCreateInfos.Count; createInfo.pQueueCreateInfos = queueCreateInfosArrayPtr; } createInfo.pEnabledFeatures = &deviceFeatures; createInfo.enabledExtensionCount = (uint)deviceExtensions.Length; createInfo.ppEnabledExtensionNames = (byte **)deviceExtensionsArray; fixed(VkDevice *devicePtr = &device) { Helpers.CheckErrors(VulkanNative.vkCreateDevice(physicalDevice, &createInfo, null, devicePtr)); } fixed(VkQueue *graphicsQueuePtr = &graphicsQueue) { VulkanNative.vkGetDeviceQueue(device, indices.graphicsFamily.Value, 0, graphicsQueuePtr); } fixed(VkQueue *presentQueuePtr = &presentQueue) { VulkanNative.vkGetDeviceQueue(device, indices.presentFamily.Value, 0, presentQueuePtr); // TODO queue index 0 ?¿?¿ } }
public GraphicsDevice(string applicationName, bool enableValidation, Window?window) { VkString name = applicationName; var appInfo = new VkApplicationInfo { sType = VkStructureType.ApplicationInfo, pApplicationName = name, applicationVersion = new VkVersion(1, 0, 0), pEngineName = s_EngineName, engineVersion = new VkVersion(1, 0, 0), apiVersion = vkEnumerateInstanceVersion() }; List <string> instanceExtensions = new List <string> { KHRSurfaceExtensionName }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { instanceExtensions.Add(KHRWin32SurfaceExtensionName); } List <string> instanceLayers = new List <string>(); if (enableValidation) { FindValidationLayers(instanceLayers); } if (instanceLayers.Count > 0) { instanceExtensions.Add(EXTDebugUtilsExtensionName); } using var vkInstanceExtensions = new VkStringArray(instanceExtensions); var instanceCreateInfo = new VkInstanceCreateInfo { sType = VkStructureType.InstanceCreateInfo, pApplicationInfo = &appInfo, enabledExtensionCount = vkInstanceExtensions.Length, ppEnabledExtensionNames = vkInstanceExtensions }; using var vkLayerNames = new VkStringArray(instanceLayers); if (instanceLayers.Count > 0) { instanceCreateInfo.enabledLayerCount = vkLayerNames.Length; instanceCreateInfo.ppEnabledLayerNames = vkLayerNames; } var debugUtilsCreateInfo = new VkDebugUtilsMessengerCreateInfoEXT { sType = VkStructureType.DebugUtilsMessengerCreateInfoEXT }; if (instanceLayers.Count > 0) { _debugMessengerCallbackFunc = DebugMessengerCallback; debugUtilsCreateInfo.messageSeverity = VkDebugUtilsMessageSeverityFlagsEXT.Error | VkDebugUtilsMessageSeverityFlagsEXT.Warning; debugUtilsCreateInfo.messageType = VkDebugUtilsMessageTypeFlagsEXT.Validation | VkDebugUtilsMessageTypeFlagsEXT.Performance; debugUtilsCreateInfo.pfnUserCallback = Marshal.GetFunctionPointerForDelegate(_debugMessengerCallbackFunc); instanceCreateInfo.pNext = &debugUtilsCreateInfo; } VkResult result = vkCreateInstance(&instanceCreateInfo, null, out VkInstance); if (result != VkResult.Success) { throw new InvalidOperationException($"Failed to create vulkan instance: {result}"); } vkLoadInstance(VkInstance); if (instanceLayers.Count > 0) { vkCreateDebugUtilsMessengerEXT(VkInstance, &debugUtilsCreateInfo, null, out _debugMessenger).CheckResult(); } Log.Info($"Created VkInstance with version: {appInfo.apiVersion.Major}.{appInfo.apiVersion.Minor}.{appInfo.apiVersion.Patch}"); if (instanceLayers.Count > 0) { foreach (var layer in instanceLayers) { Log.Info($"Instance layer '{layer}'"); } } foreach (string extension in instanceExtensions) { Log.Info($"Instance extension '{extension}'"); } _surface = CreateSurface(window); // Find physical device, setup queue's and create device. var physicalDevices = vkEnumeratePhysicalDevices(VkInstance); foreach (var physicalDevice in physicalDevices) { //vkGetPhysicalDeviceProperties(physicalDevice, out var properties); //var deviceName = properties.GetDeviceName(); } PhysicalDevice = physicalDevices[0]; vkGetPhysicalDeviceProperties(PhysicalDevice, out VkPhysicalDeviceProperties properties); var queueFamilies = FindQueueFamilies(PhysicalDevice, _surface); var availableDeviceExtensions = vkEnumerateDeviceExtensionProperties(PhysicalDevice); var priority = 1.0f; var queueCreateInfo = new VkDeviceQueueCreateInfo { sType = VkStructureType.DeviceQueueCreateInfo, queueFamilyIndex = queueFamilies.graphicsFamily, queueCount = 1, pQueuePriorities = &priority }; List <string> deviceExtensions = new List <string> { KHRSwapchainExtensionName }; if (CheckDeviceExtensionSupport(KHRSpirv14ExtensionName, availableDeviceExtensions)) { deviceExtensions.Add(KHRSpirv14ExtensionName); } if (CheckDeviceExtensionSupport(KHRFragmentShadingRateExtensionName, availableDeviceExtensions)) { deviceExtensions.Add(KHRFragmentShadingRateExtensionName); } if (CheckDeviceExtensionSupport(NVMeshShaderExtensionName, availableDeviceExtensions)) { deviceExtensions.Add(NVMeshShaderExtensionName); } VkPhysicalDeviceVulkan11Features features_1_1 = new VkPhysicalDeviceVulkan11Features { sType = VkStructureType.PhysicalDeviceVulkan11Features }; VkPhysicalDeviceVulkan12Features features_1_2 = new VkPhysicalDeviceVulkan12Features { sType = VkStructureType.PhysicalDeviceVulkan12Features }; VkPhysicalDeviceFeatures2 deviceFeatures2 = new VkPhysicalDeviceFeatures2 { sType = VkStructureType.PhysicalDeviceFeatures2 }; deviceFeatures2.pNext = &features_1_1; features_1_1.pNext = &features_1_2; void **features_chain = &features_1_2.pNext; VkPhysicalDevice8BitStorageFeatures storage_8bit_features = default; if (properties.apiVersion <= VkVersion.Version_1_2) { if (CheckDeviceExtensionSupport(KHR8bitStorageExtensionName, availableDeviceExtensions)) { deviceExtensions.Add(KHR8bitStorageExtensionName); storage_8bit_features.sType = VkStructureType.PhysicalDevice8bitStorageFeatures; *features_chain = &storage_8bit_features; features_chain = &storage_8bit_features.pNext; } } VkPhysicalDeviceAccelerationStructureFeaturesKHR acceleration_structure_features = default; if (CheckDeviceExtensionSupport(KHRAccelerationStructureExtensionName, availableDeviceExtensions)) { deviceExtensions.Add(KHRAccelerationStructureExtensionName); acceleration_structure_features.sType = VkStructureType.PhysicalDeviceAccelerationStructureFeaturesKHR; *features_chain = &acceleration_structure_features; features_chain = &acceleration_structure_features.pNext; } vkGetPhysicalDeviceFeatures2(PhysicalDevice, out deviceFeatures2); using var deviceExtensionNames = new VkStringArray(deviceExtensions); var deviceCreateInfo = new VkDeviceCreateInfo { sType = VkStructureType.DeviceCreateInfo, pNext = &deviceFeatures2, queueCreateInfoCount = 1, pQueueCreateInfos = &queueCreateInfo, enabledExtensionCount = deviceExtensionNames.Length, ppEnabledExtensionNames = deviceExtensionNames, pEnabledFeatures = null, }; result = vkCreateDevice(PhysicalDevice, &deviceCreateInfo, null, out VkDevice); if (result != VkResult.Success) { throw new Exception($"Failed to create Vulkan Logical Device, {result}"); } vkGetDeviceQueue(VkDevice, queueFamilies.graphicsFamily, 0, out GraphicsQueue); vkGetDeviceQueue(VkDevice, queueFamilies.presentFamily, 0, out PresentQueue); // Create swap chain Swapchain = new Swapchain(this, window); _perFrame = new PerFrame[Swapchain.ImageCount]; for (var i = 0; i < _perFrame.Length; i++) { VkFenceCreateInfo fenceCreateInfo = new VkFenceCreateInfo(VkFenceCreateFlags.Signaled); vkCreateFence(VkDevice, &fenceCreateInfo, null, out _perFrame[i].QueueSubmitFence).CheckResult(); VkCommandPoolCreateInfo poolCreateInfo = new VkCommandPoolCreateInfo { sType = VkStructureType.CommandPoolCreateInfo, flags = VkCommandPoolCreateFlags.Transient, queueFamilyIndex = queueFamilies.graphicsFamily, }; vkCreateCommandPool(VkDevice, &poolCreateInfo, null, out _perFrame[i].PrimaryCommandPool).CheckResult(); VkCommandBufferAllocateInfo commandBufferInfo = new VkCommandBufferAllocateInfo { sType = VkStructureType.CommandBufferAllocateInfo, commandPool = _perFrame[i].PrimaryCommandPool, level = VkCommandBufferLevel.Primary, commandBufferCount = 1 }; vkAllocateCommandBuffers(VkDevice, &commandBufferInfo, out _perFrame[i].PrimaryCommandBuffer).CheckResult(); } }
public static void Init() { optionalExtn_avail = new bool[optionalDeviceExtns.Length]; Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.White; Window = new GameWindow(AppName); fixed(IntPtr *instancePtr = &instanceHndl) fixed(IntPtr * surfacePtr = &surfaceHndl) { VkResult res; var instLayers = new List <string>(); var instExtns = new List <string>(); var devExtns = new List <string>(); uint glfwExtnCnt = 0; var glfwExtns = glfwGetRequiredInstanceExtensions(&glfwExtnCnt); for (int i = 0; i < glfwExtnCnt; i++) { instExtns.Add(Marshal.PtrToStringAnsi(glfwExtns[i])); } instExtns.Add(VkKhrGetPhysicalDeviceProperties2ExtensionName); if (EnableValidation) { instLayers.Add("VK_LAYER_KHRONOS_validation"); instExtns.Add(VkExtDebugUtilsExtensionName); } var layers = stackalloc IntPtr[instLayers.Count]; for (int i = 0; i < instLayers.Count; i++) { layers[i] = Marshal.StringToHGlobalAnsi(instLayers[i]); } var extns = stackalloc IntPtr[instExtns.Count]; for (int i = 0; i < instExtns.Count; i++) { extns[i] = Marshal.StringToHGlobalAnsi(instExtns[i]); } { var appInfo = new VkApplicationInfo() { sType = VkStructureType.StructureTypeApplicationInfo, pApplicationName = AppName, pEngineName = EngineName, apiVersion = VkApiVersion12, applicationVersion = 1, engineVersion = 1, pNext = IntPtr.Zero }; var appInfo_ptr = appInfo.Pointer(); var instCreatInfo = new VkInstanceCreateInfo() { sType = VkStructureType.StructureTypeInstanceCreateInfo, pApplicationInfo = appInfo_ptr, }; instCreatInfo.ppEnabledLayerNames = layers; instCreatInfo.enabledLayerCount = (uint)instLayers.Count; instCreatInfo.ppEnabledExtensionNames = extns; instCreatInfo.enabledExtensionCount = (uint)instExtns.Count; var instCreatInfo_ptr = instCreatInfo.Pointer(); //register instance create debug message handler debugCreatInfo = new VkDebugUtilsMessengerCreateInfoEXT() { sType = VkStructureType.StructureTypeDebugUtilsMessengerCreateInfoExt, messageSeverity = VkDebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityErrorBitExt | VkDebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityWarningBitExt | VkDebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityVerboseBitExt | VkDebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityInfoBitExt, messageType = VkDebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypeGeneralBitExt | VkDebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypePerformanceBitExt | VkDebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypeValidationBitExt, pfnUserCallback = DebugCallback }; var debugCreatInfo_ptr = debugCreatInfo.Pointer(); if (EnableValidation) { instCreatInfo.pNext = debugCreatInfo_ptr; } res = vkCreateInstance(instCreatInfo_ptr, null, instancePtr); if (res != VkResult.Success) { throw new Exception("Failed to create instance."); } } if (EnableValidation) { SetupDebugMessengers(instanceHndl); var debugCreatInfo_ptr = debugCreatInfo.Pointer(); fixed(IntPtr *dbg_ptr = &debugMessenger) res = CreateDebugUtilsMessengerEXT(instanceHndl, debugCreatInfo_ptr, IntPtr.Zero, dbg_ptr); if (res != VkResult.Success) { throw new Exception("Failed to register debug callback."); } } res = Window.CreateSurface(instanceHndl, surfacePtr); if (res != VkResult.Success) { throw new Exception("Failed to create surface."); } uint devCount = 0; vkEnumeratePhysicalDevices(instanceHndl, &devCount, null); if (devCount == 0) { throw new Exception("Failed to find Vulkan compatible devices."); } var devices = new IntPtr[devCount]; fixed(IntPtr *devicesPtr = devices) vkEnumeratePhysicalDevices(instanceHndl, &devCount, devicesPtr); var ratedDevices = new List <(uint, IntPtr)>(); for (int i = 0; i < devices.Length; i++) { //rate each device ratedDevices.Add((RateDevice(devices[i]), devices[i])); } var orderedDevices = ratedDevices.OrderByDescending(a => a.Item1) .Select(a => a.Item2) .ToArray(); DeviceInformation = new DeviceInfo[orderedDevices.Length]; DeviceInformation[0] = new DeviceInfo() { PhysicalDevice = orderedDevices[0] }; //TODO for now just choose the first device { //allocate queues for primary device uint graphicsFamily = ~0u; uint computeFamily = ~0u; uint transferFamily = ~0u; uint presentFamily = ~0u; uint qfam_cnt = 0; vkGetPhysicalDeviceQueueFamilyProperties(orderedDevices[0], &qfam_cnt, null); var qFams_ptr = new ManagedPtrArray <VkQueueFamilyProperties>(qfam_cnt); vkGetPhysicalDeviceQueueFamilyProperties(orderedDevices[0], &qfam_cnt, qFams_ptr); var qFams = qFams_ptr.Value; uint qFamIdx = 0; foreach (var qFam in qFams) { bool presentSupport = false; vkGetPhysicalDeviceSurfaceSupportKHR(orderedDevices[0], qFamIdx, surfaceHndl, &presentSupport); if ((qFam.queueFlags & VkQueueFlags.QueueGraphicsBit) != 0 && graphicsFamily == ~0u) { graphicsFamily = qFamIdx; if (presentSupport) { presentFamily = qFamIdx; } qFamIdx++; continue; } if ((qFam.queueFlags & VkQueueFlags.QueueComputeBit) != 0 && computeFamily == ~0u) { computeFamily = qFamIdx; if ((qFam.queueFlags & VkQueueFlags.QueueTransferBit) != 0) { transferFamily = qFamIdx; } qFamIdx++; continue; } if ((qFam.queueFlags & VkQueueFlags.QueueTransferBit) != 0) { transferFamily = qFamIdx; } if (graphicsFamily != ~0u && computeFamily != ~0u && transferFamily != ~0u && presentFamily != ~0u) { break; } qFamIdx++; } if (presentFamily == ~0u) { throw new Exception("Separate present queue support hasn't been implemented."); } var max_q_priority = stackalloc float[] { 1.0f }; var dual_graph_q_priority = stackalloc float[] { 1.0f }; var triple_graph_q_priority = stackalloc float[] { 1.0f, 1.0f, 1.0f }; VkDeviceQueueCreateInfo graphics_qCreatInfo = new VkDeviceQueueCreateInfo() { sType = VkStructureType.StructureTypeDeviceQueueCreateInfo, queueFamilyIndex = graphicsFamily, queueCount = 1, pQueuePriorities = max_q_priority }; VkDeviceQueueCreateInfo compute_qCreatInfo = new VkDeviceQueueCreateInfo { sType = VkStructureType.StructureTypeDeviceQueueCreateInfo, queueFamilyIndex = computeFamily, queueCount = 1, pQueuePriorities = max_q_priority }; VkDeviceQueueCreateInfo transfer_qCreatInfo = new VkDeviceQueueCreateInfo(); if (transferFamily != graphicsFamily) { transfer_qCreatInfo.sType = VkStructureType.StructureTypeDeviceQueueCreateInfo; transfer_qCreatInfo.queueFamilyIndex = transferFamily; transfer_qCreatInfo.queueCount = 1; transfer_qCreatInfo.pQueuePriorities = max_q_priority; } else { graphics_qCreatInfo.queueCount = 2; graphics_qCreatInfo.pQueuePriorities = dual_graph_q_priority; } var qCreatInfos = new VkDeviceQueueCreateInfo[3]; qCreatInfos[0] = graphics_qCreatInfo; qCreatInfos[1] = compute_qCreatInfo; if (transferFamily != graphicsFamily) { qCreatInfos[2] = transfer_qCreatInfo; } DeviceInformation[0].GraphicsFamily = graphicsFamily; DeviceInformation[0].ComputeFamily = computeFamily; DeviceInformation[0].TransferFamily = transferFamily; DeviceInformation[0].PresentFamily = presentFamily; VkPhysicalDeviceFeatures devFeats = new VkPhysicalDeviceFeatures() { multiDrawIndirect = true, drawIndirectFirstInstance = true, fullDrawIndexUint32 = true, tessellationShader = true, fragmentStoresAndAtomics = true, vertexPipelineStoresAndAtomics = true, robustBufferAccess = EnableValidation, shaderInt16 = true, samplerAnisotropy = true, fillModeNonSolid = true, largePoints = true, }; var devFeats11 = new VkPhysicalDeviceVulkan11Features() { sType = VkStructureType.StructureTypePhysicalDeviceVulkan11Features, shaderDrawParameters = true, //storageBuffer16BitAccess = true, //uniformAndStorageBuffer16BitAccess = true, //storagePushConstant16 = true, }; var devFeats11_ptr = devFeats11.Pointer(); /* * var depthStenc = new VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures() * { * sType = VkStructureType.StructureTypePhysicalDeviceSeparateDepthStencilLayoutsFeatures, * separateDepthStencilLayouts = true, * pNext = devFeats11_ptr * }; * var depthStenc_ptr = depthStenc.Pointer(); * * var timelineSems = new VkPhysicalDeviceTimelineSemaphoreFeatures() * { * sType = VkStructureType.StructureTypePhysicalDeviceTimelineSemaphoreFeatures, * timelineSemaphore = true, * pNext = depthStenc_ptr, * }; * var timelineSems_ptr = timelineSems.Pointer(); * * var indirectCnt = new VkPhysicalDeviceShaderFloat16Int8Features() * { * sType = VkStructureType.StructureTypePhysicalDeviceShaderFloat16Int8Features, * shaderFloat16 = true, * shaderInt8 = true, * pNext = timelineSems_ptr, * }; * var indirectCnt_ptr = indirectCnt.Pointer(); * * var uboLayout = new VkPhysicalDeviceUniformBufferStandardLayoutFeatures() * { * sType = VkStructureType.StructureTypePhysicalDeviceUniformBufferStandardLayoutFeatures, * uniformBufferStandardLayout = true, * pNext = indirectCnt_ptr * }; * var uboLayout_ptr = uboLayout.Pointer(); * * var storageByte = new VkPhysicalDevice8BitStorageFeatures() * { * sType = VkStructureType.StructureTypePhysicalDevice8bitStorageFeatures, * storageBuffer8BitAccess = true, * uniformAndStorageBuffer8BitAccess = true, * pNext = uboLayout_ptr * }; * var storageByte_ptr = storageByte.Pointer(); * var descIndexing = new VkPhysicalDeviceDescriptorIndexingFeatures() * { * sType = VkStructureType.StructureTypePhysicalDeviceDescriptorIndexingFeatures, * descriptorBindingSampledImageUpdateAfterBind = true, * descriptorBindingStorageBufferUpdateAfterBind = true, * descriptorBindingStorageImageUpdateAfterBind = true, * descriptorBindingStorageTexelBufferUpdateAfterBind = true, * descriptorBindingUniformBufferUpdateAfterBind = true, * descriptorBindingUniformTexelBufferUpdateAfterBind = true, * descriptorBindingUpdateUnusedWhilePending = true, * descriptorBindingPartiallyBound = true, * shaderStorageTexelBufferArrayDynamicIndexing = true, * pNext = storageByte_ptr, * }; * var descIndexing_ptr = descIndexing.Pointer();*/ //var drawIndirectCount = new VkDrawIndirecCount var devFeats12 = new VkPhysicalDeviceVulkan12Features() { sType = VkStructureType.StructureTypePhysicalDeviceVulkan12Features, separateDepthStencilLayouts = true, timelineSemaphore = true, drawIndirectCount = true, shaderFloat16 = true, shaderInt8 = true, uniformBufferStandardLayout = true, storageBuffer8BitAccess = true, uniformAndStorageBuffer8BitAccess = true, descriptorIndexing = true, descriptorBindingSampledImageUpdateAfterBind = true, descriptorBindingStorageBufferUpdateAfterBind = true, descriptorBindingStorageImageUpdateAfterBind = true, descriptorBindingStorageTexelBufferUpdateAfterBind = true, descriptorBindingUniformBufferUpdateAfterBind = true, descriptorBindingUniformTexelBufferUpdateAfterBind = true, descriptorBindingUpdateUnusedWhilePending = true, descriptorBindingPartiallyBound = true, shaderStorageTexelBufferArrayDynamicIndexing = true, shaderStorageBufferArrayNonUniformIndexing = true, runtimeDescriptorArray = true, descriptorBindingVariableDescriptorCount = true, pNext = devFeats11_ptr }; var devFeats12_ptr = devFeats12.Pointer(); devExtns.AddRange(requiredDeviceExtns); for (int i = 0; i < optionalExtn_avail.Length; i++) { if (optionalExtn_avail[i]) { devExtns.Add(optionalDeviceExtns[i]); } } var devExtns_ptr = stackalloc IntPtr[devExtns.Count]; for (int i = 0; i < devExtns.Count; i++) { devExtns_ptr[i] = Marshal.StringToHGlobalAnsi(devExtns[i]); } var qCreatInfos_ptr = qCreatInfos.Pointer(); var devFeats_ptr = devFeats.Pointer(); var devCreatInfo = new VkDeviceCreateInfo() { sType = VkStructureType.StructureTypeDeviceCreateInfo, queueCreateInfoCount = (uint)(transferFamily != graphicsFamily ? 3 : 2), enabledExtensionCount = (uint)devExtns.Count, ppEnabledExtensionNames = devExtns_ptr, enabledLayerCount = (uint)instLayers.Count, ppEnabledLayerNames = layers, pEnabledFeatures = devFeats_ptr, pQueueCreateInfos = qCreatInfos_ptr, pNext = devFeats12_ptr }; var devCreatInfo_ptr = devCreatInfo.Pointer(); IntPtr deviceHndl = IntPtr.Zero; res = vkCreateDevice(orderedDevices[0], devCreatInfo_ptr, null, &deviceHndl); if (res != VkResult.Success) { throw new Exception("Failed to create logical device."); } DeviceInformation[0].Device = deviceHndl; //Setup memory allocator var allocCreatInfo = new VmaAllocatorCreateInfo() { physicalDevice = DeviceInformation[0].PhysicalDevice, device = DeviceInformation[0].Device }; var allocCreatInfo_ptr = allocCreatInfo.Pointer(); fixed(IntPtr *vma_alloc_ptr = &DeviceInformation[0].vmaAllocator) res = vmaCreateAllocator(allocCreatInfo_ptr, vma_alloc_ptr); if (res != VkResult.Success) { throw new Exception("Failed to initialize allocator."); } IntPtr graph_q_hndl = IntPtr.Zero; IntPtr trans_q_hndl = IntPtr.Zero; IntPtr comp_q_hndl = IntPtr.Zero; vkGetDeviceQueue(DeviceInformation[0].Device, graphicsFamily, 0, &graph_q_hndl); vkGetDeviceQueue(DeviceInformation[0].Device, computeFamily, 0, &comp_q_hndl); if (transferFamily != graphicsFamily) { vkGetDeviceQueue(DeviceInformation[0].Device, transferFamily, 0, &trans_q_hndl); } else { vkGetDeviceQueue(DeviceInformation[0].Device, graphicsFamily, 1, &trans_q_hndl); } DeviceInformation[0].GraphicsQueue = new GpuQueue(CommandQueueKind.Graphics, graph_q_hndl, graphicsFamily, 0); DeviceInformation[0].TransferQueue = new GpuQueue(CommandQueueKind.Transfer, trans_q_hndl, transferFamily, 0); DeviceInformation[0].ComputeQueue = new GpuQueue(CommandQueueKind.Compute, comp_q_hndl, computeFamily, 0); var queue_indices = new List <uint>(); if (!queue_indices.Contains(DeviceInformation[0].GraphicsFamily)) { queue_indices.Add(DeviceInformation[0].GraphicsFamily); } if (!queue_indices.Contains(DeviceInformation[0].ComputeFamily)) { queue_indices.Add(DeviceInformation[0].ComputeFamily); } if (!queue_indices.Contains(DeviceInformation[0].PresentFamily)) { queue_indices.Add(DeviceInformation[0].PresentFamily); } if (!queue_indices.Contains(DeviceInformation[0].TransferFamily)) { queue_indices.Add(DeviceInformation[0].TransferFamily); } DeviceInformation[0].QueueFamilyIndices = queue_indices.ToArray(); var physDeviceProps = new ManagedPtr <VkPhysicalDeviceProperties>(); vkGetPhysicalDeviceProperties(DeviceInformation[0].PhysicalDevice, physDeviceProps); DeviceInformation[0].Properties = physDeviceProps.Value; var caps_ptr = new ManagedPtr <VkSurfaceCapabilitiesKHR>(); vkGetPhysicalDeviceSurfaceCapabilitiesKHR(DeviceInformation[0].PhysicalDevice, surfaceHndl, caps_ptr); var caps = caps_ptr.Value; VkExtent2D cur_extent = new VkExtent2D(); if (caps.currentExtent.width != uint.MaxValue) { cur_extent = caps.currentExtent; } else { cur_extent.width = System.Math.Clamp((uint)Window.Width, caps.minImageExtent.width, caps.maxImageExtent.width); cur_extent.height = System.Math.Clamp((uint)Window.Height, caps.minImageExtent.height, caps.maxImageExtent.height); } uint img_cnt = caps.minImageCount + 1; VkSwapchainCreateInfoKHR swapCreatInfo = new VkSwapchainCreateInfoKHR() { sType = VkStructureType.StructureTypeSwapchainCreateInfoKhr, surface = surfaceHndl, minImageCount = img_cnt, imageFormat = surface_fmt.format, imageColorSpace = surface_fmt.colorSpace, imageExtent = cur_extent, imageArrayLayers = 1, imageUsage = VkImageUsageFlags.ImageUsageColorAttachmentBit | VkImageUsageFlags.ImageUsageTransferDstBit | VkImageUsageFlags.ImageUsageTransferSrcBit, imageSharingMode = VkSharingMode.SharingModeExclusive, queueFamilyIndexCount = 0, pQueueFamilyIndices = null, preTransform = caps.currentTransform, compositeAlpha = VkCompositeAlphaFlagsKHR.CompositeAlphaOpaqueBitKhr, presentMode = present_mode, clipped = true, oldSwapchain = IntPtr.Zero }; var swapCreatInfo_ptr = swapCreatInfo.Pointer(); fixed(IntPtr *swapchain_ptr = &swapChainHndl) res = vkCreateSwapchainKHR(DeviceInformation[0].Device, swapCreatInfo_ptr, null, swapchain_ptr); if (res != VkResult.Success) throw new Exception("Failed to create swapchain."); fixed(uint *swapchain_img_cnt_ptr = &swapchain_img_cnt) { vkGetSwapchainImagesKHR(DeviceInformation[0].Device, swapChainHndl, swapchain_img_cnt_ptr, null); var swapchainImages_l = new IntPtr[swapchain_img_cnt]; fixed(IntPtr *swapchain_imgs = swapchainImages_l) vkGetSwapchainImagesKHR(DeviceInformation[0].Device, swapChainHndl, swapchain_img_cnt_ptr, swapchain_imgs); MaxFramesInFlight = swapchain_img_cnt; MaxFrameCount = swapchain_img_cnt; swapchainImages = new Image[swapchain_img_cnt]; for (int i = 0; i < swapchainImages.Length; i++) { swapchainImages[i] = new Image($"Swapchain_{i}") { Dimensions = 2, Width = cur_extent.width, Height = cur_extent.height, Depth = 1, Format = (ImageFormat)surface_fmt.format, Layers = 1, Levels = 1, MemoryUsage = MemoryUsage.GpuOnly, Usage = ImageUsage.Sampled, InitialLayout = ImageLayout.Undefined, Cubemappable = false, }; swapchainImages[i].Build(0, swapchainImages_l[i]); } surface_extent = cur_extent; swapchainViews = new ImageView[swapchain_img_cnt]; DefaultFramebuffer = new Framebuffer[swapchain_img_cnt]; for (int i = 0; i < swapchainImages.Length; i++) { swapchainViews[i] = new ImageView($"Swapchain_{i}") { BaseLayer = 0, BaseLevel = 0, Format = (ImageFormat)surface_fmt.format, LayerCount = 1, LevelCount = 1, ViewType = ImageViewType.View2D, }; swapchainViews[i].Build(swapchainImages[i]); DefaultFramebuffer[i] = new Framebuffer(); DefaultFramebuffer[i].Width = surface_extent.width; DefaultFramebuffer[i].Height = surface_extent.height; DefaultFramebuffer[i].Name = $"Swapchain_{i}"; DefaultFramebuffer[i].ColorAttachments = new ImageView[] { swapchainViews[i] }; } } for (int i = 0; i < instLayers.Count; i++) { Marshal.FreeHGlobal(layers[i]); } for (int i = 0; i < instExtns.Count; i++) { Marshal.FreeHGlobal(extns[i]); } for (int i = 0; i < devExtns.Count; i++) { Marshal.FreeHGlobal(devExtns_ptr[i]); } //TODO allocate compute and trasnfer queues for all secondary devices } for (int i = 0; i < 1 /*DeviceInformation.Length*/; i++) { var devInfo = DeviceInformation[i]; IntPtr rrCtxtHndl = IntPtr.Zero; if (rrCreateContextVk(RrApiVersion, devInfo.Device, devInfo.PhysicalDevice, devInfo.ComputeQueue.Handle, devInfo.ComputeFamily, &rrCtxtHndl) != RRError.RrSuccess) { Console.WriteLine($"Failed to initialize RadeonRays for device #{i}."); } DeviceInformation[i].RaysContext = rrCtxtHndl; } FrameFinishedSemaphore = new GpuSemaphore[MaxFramesInFlight]; ImageAvailableSemaphore = new GpuSemaphore[MaxFramesInFlight]; InflightFences = new Fence[MaxFramesInFlight]; for (int i = 0; i < MaxFramesInFlight; i++) { FrameFinishedSemaphore[i] = new GpuSemaphore(); FrameFinishedSemaphore[i].Build(0, false, 0); ImageAvailableSemaphore[i] = new GpuSemaphore(); ImageAvailableSemaphore[i].Build(0, false, 0); InflightFences[i] = new Fence { CreateSignaled = true }; InflightFences[i].Build(0); } Width = (uint)Window.Width; Height = (uint)Window.Height; } }