コード例 #1
0
        internal static void SelectAvailableDevices(VulkanInstance instance,
                                                    VulkanSurface surface, bool preferDiscreteGpu, string preferredDevice)
        {
            uint physicalDeviceCount;

            instance.Api.EnumeratePhysicalDevices(instance.InternalHandle, &physicalDeviceCount, null).ThrowOnError();

            var physicalDevices = new PhysicalDevice[physicalDeviceCount];

            fixed(PhysicalDevice *pPhysicalDevices = physicalDevices)
            {
                instance.Api.EnumeratePhysicalDevices(instance.InternalHandle, &physicalDeviceCount, pPhysicalDevices)
                .ThrowOnError();
            }

            PhysicalDevices = new Dictionary <PhysicalDevice, PhysicalDeviceProperties>();

            foreach (var physicalDevice in physicalDevices)
            {
                instance.Api.GetPhysicalDeviceProperties(physicalDevice, out var properties);
                PhysicalDevices.Add(physicalDevice, properties);
            }

            SuitableDevices = PhysicalDevices.Where(x => IsSuitableDevice(
                                                        instance.Api,
                                                        x.Key,
                                                        x.Value,
                                                        surface.ApiHandle,
                                                        out _,
                                                        out _));
        }
コード例 #2
0
        internal static VulkanPhysicalDevice FindSuitablePhysicalDevice(VulkanInstance instance,
                                                                        VulkanSurface surface, bool preferDiscreteGpu, string preferredDevice)
        {
            SelectAvailableDevices(instance, surface, preferDiscreteGpu, preferredDevice);

            uint queueFamilyIndex = 0;
            uint queueCount       = 0;

            if (!string.IsNullOrWhiteSpace(preferredDevice))
            {
                var physicalDevice = SuitableDevices.FirstOrDefault(x => VulkanInitialization.StringFromIdPair(x.Value.VendorID, x.Value.DeviceID) == preferredDevice);

                queueFamilyIndex = FindSuitableQueueFamily(instance.Api, physicalDevice.Key,
                                                           surface.ApiHandle, out queueCount);
                if (queueFamilyIndex != int.MaxValue)
                {
                    return(new VulkanPhysicalDevice(physicalDevice.Key, instance.Api, queueCount, queueFamilyIndex));
                }
            }

            if (preferDiscreteGpu)
            {
                var discreteGpus = SuitableDevices.Where(p => p.Value.DeviceType == PhysicalDeviceType.DiscreteGpu);

                foreach (var gpu in discreteGpus)
                {
                    queueFamilyIndex = FindSuitableQueueFamily(instance.Api, gpu.Key,
                                                               surface.ApiHandle, out queueCount);
                    if (queueFamilyIndex != int.MaxValue)
                    {
                        return(new VulkanPhysicalDevice(gpu.Key, instance.Api, queueCount, queueFamilyIndex));
                    }
                }
            }

            foreach (var physicalDevice in SuitableDevices)
            {
                queueFamilyIndex = FindSuitableQueueFamily(instance.Api, physicalDevice.Key,
                                                           surface.ApiHandle, out queueCount);
                if (queueFamilyIndex != int.MaxValue)
                {
                    return(new VulkanPhysicalDevice(physicalDevice.Key, instance.Api, queueCount, queueFamilyIndex));
                }
            }

            throw new Exception("No suitable physical device found");
        }
コード例 #3
0
ファイル: VulkanDisplay.cs プロジェクト: Ryujinx/Ryujinx
        private VulkanDisplay(VulkanInstance instance, VulkanDevice device,
                              VulkanPhysicalDevice physicalDevice, VulkanSurface surface, SwapchainKHR swapchain,
                              Extent2D swapchainExtent)
        {
            _instance        = instance;
            _device          = device;
            _physicalDevice  = physicalDevice;
            _swapchain       = swapchain;
            _swapchainExtent = swapchainExtent;
            _surface         = surface;

            CreateSwapchainImages();

            _semaphorePair = new VulkanSemaphorePair(_device);

            CommandBufferPool = new VulkanCommandBufferPool(device, physicalDevice);
        }
コード例 #4
0
        public VulkanSurfaceRenderTarget CreateRenderTarget(IVulkanPlatformSurface platformSurface)
        {
            var surface = VulkanSurface.CreateSurface(Instance, platformSurface);

            if (PhysicalDevice == null)
            {
                PhysicalDevice = VulkanPhysicalDevice.FindSuitablePhysicalDevice(Instance, surface, _options.PreferDiscreteGpu, _options.PreferredDevice);
            }

            var renderTarget = new VulkanSurfaceRenderTarget(this, surface);

            if (MainSurface == null && surface != null)
            {
                MainSurface = renderTarget;
            }

            return(renderTarget);
        }
コード例 #5
0
ファイル: VulkanDisplay.cs プロジェクト: Ryujinx/Ryujinx
        private static unsafe Extent2D GetSwapchainExtent(VulkanSurface surface, SurfaceCapabilitiesKHR capabilities)
        {
            Extent2D swapchainExtent;

            if (capabilities.CurrentExtent.Width != uint.MaxValue)
            {
                swapchainExtent = capabilities.CurrentExtent;
            }
            else
            {
                var surfaceSize = surface.SurfaceSize;

                var width  = Math.Clamp((uint)surfaceSize.Width, capabilities.MinImageExtent.Width, capabilities.MaxImageExtent.Width);
                var height = Math.Clamp((uint)surfaceSize.Height, capabilities.MinImageExtent.Height, capabilities.MaxImageExtent.Height);

                swapchainExtent = new Extent2D(width, height);
            }

            return(swapchainExtent);
        }
コード例 #6
0
ファイル: VulkanDisplay.cs プロジェクト: Ryujinx/Ryujinx
        private static unsafe SwapchainKHR CreateSwapchain(VulkanInstance instance, VulkanDevice device,
                                                           VulkanPhysicalDevice physicalDevice, VulkanSurface surface, out Extent2D swapchainExtent,
                                                           SwapchainKHR?oldswapchain = null, bool vsyncEnabled = true)
        {
            if (_swapchainExtension == null)
            {
                instance.Api.TryGetDeviceExtension(instance.InternalHandle, device.InternalHandle, out _swapchainExtension);
            }

            while (!surface.CanSurfacePresent(physicalDevice))
            {
                Thread.Sleep(16);
            }

            VulkanSurface.SurfaceExtension.GetPhysicalDeviceSurfaceCapabilities(physicalDevice.InternalHandle,
                                                                                surface.ApiHandle, out var capabilities);

            var imageCount = capabilities.MinImageCount + 1;

            if (capabilities.MaxImageCount > 0 && imageCount > capabilities.MaxImageCount)
            {
                imageCount = capabilities.MaxImageCount;
            }

            var surfaceFormat = surface.GetSurfaceFormat(physicalDevice);

            bool supportsIdentityTransform = capabilities.SupportedTransforms.HasFlag(SurfaceTransformFlagsKHR.SurfaceTransformIdentityBitKhr);
            bool isRotated = capabilities.CurrentTransform.HasFlag(SurfaceTransformFlagsKHR.SurfaceTransformRotate90BitKhr) ||
                             capabilities.CurrentTransform.HasFlag(SurfaceTransformFlagsKHR.SurfaceTransformRotate270BitKhr);

            swapchainExtent = GetSwapchainExtent(surface, capabilities);

            CompositeAlphaFlagsKHR compositeAlphaFlags = GetSuitableCompositeAlphaFlags(capabilities);

            PresentModeKHR presentMode = GetSuitablePresentMode(physicalDevice, surface, vsyncEnabled);

            var swapchainCreateInfo = new SwapchainCreateInfoKHR
            {
                SType           = StructureType.SwapchainCreateInfoKhr,
                Surface         = surface.ApiHandle,
                MinImageCount   = imageCount,
                ImageFormat     = surfaceFormat.Format,
                ImageColorSpace = surfaceFormat.ColorSpace,
                ImageExtent     = swapchainExtent,
                ImageUsage      =
                    ImageUsageFlags.ImageUsageColorAttachmentBit | ImageUsageFlags.ImageUsageTransferDstBit,
                ImageSharingMode = SharingMode.Exclusive,
                ImageArrayLayers = 1,
                PreTransform     = supportsIdentityTransform && isRotated ?
                                   SurfaceTransformFlagsKHR.SurfaceTransformIdentityBitKhr :
                                   capabilities.CurrentTransform,
                CompositeAlpha = compositeAlphaFlags,
                PresentMode    = presentMode,
                Clipped        = true,
                OldSwapchain   = oldswapchain ?? new SwapchainKHR()
            };

            _swapchainExtension.CreateSwapchain(device.InternalHandle, swapchainCreateInfo, null, out var swapchain)
            .ThrowOnError();

            if (oldswapchain != null)
            {
                _swapchainExtension.DestroySwapchain(device.InternalHandle, oldswapchain.Value, null);
            }

            return(swapchain);
        }
コード例 #7
0
ファイル: VulkanDisplay.cs プロジェクト: Ryujinx/Ryujinx
        internal static VulkanDisplay CreateDisplay(VulkanInstance instance, VulkanDevice device,
                                                    VulkanPhysicalDevice physicalDevice, VulkanSurface surface)
        {
            var swapchain = CreateSwapchain(instance, device, physicalDevice, surface, out var extent, null, true);

            return(new VulkanDisplay(instance, device, physicalDevice, surface, swapchain, extent));
        }
コード例 #8
0
ファイル: VulkanDisplay.cs プロジェクト: Ryujinx/Ryujinx
        private static unsafe PresentModeKHR GetSuitablePresentMode(VulkanPhysicalDevice physicalDevice, VulkanSurface surface, bool vsyncEnabled)
        {
            uint presentModesCount;

            VulkanSurface.SurfaceExtension.GetPhysicalDeviceSurfacePresentModes(physicalDevice.InternalHandle,
                                                                                surface.ApiHandle,
                                                                                &presentModesCount, null);

            var presentModes = new PresentModeKHR[presentModesCount];

            fixed(PresentModeKHR *pPresentModes = presentModes)
            {
                VulkanSurface.SurfaceExtension.GetPhysicalDeviceSurfacePresentModes(physicalDevice.InternalHandle,
                                                                                    surface.ApiHandle, &presentModesCount, pPresentModes);
            }

            var modes = presentModes.ToList();

            if (!vsyncEnabled && modes.Contains(PresentModeKHR.PresentModeImmediateKhr))
            {
                return(PresentModeKHR.PresentModeImmediateKhr);
            }
            else if (modes.Contains(PresentModeKHR.PresentModeMailboxKhr))
            {
                return(PresentModeKHR.PresentModeMailboxKhr);
            }
            else if (modes.Contains(PresentModeKHR.PresentModeFifoKhr))
            {
                return(PresentModeKHR.PresentModeFifoKhr);
            }
            else
            {
                return(PresentModeKHR.PresentModeImmediateKhr);
            }
        }