예제 #1
0
파일: Device.cs 프로젝트: Gaiaxis/SharpGame
        public static VkDevice Create(Settings settings, VkPhysicalDeviceFeatures enabledFeatures, CStringList enabledExtensions,
                                      VkQueueFlags requestedQueueTypes = VkQueueFlags.Graphics | VkQueueFlags.Compute | VkQueueFlags.Transfer)
        {
            instanceExtensions.Add(Vulkan.KHRSurfaceExtensionName);
            instanceExtensions.Add(Vulkan.KHRGetPhysicalDeviceProperties2ExtensionName);

            enabledExtensions.Add(Vulkan.KHRMaintenance1ExtensionName);
            enabledExtensions.Add(Vulkan.EXTInlineUniformBlockExtensionName);

            //enabledExtensions.Add(Strings.VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT);

            CreateInstance(settings);

            // Physical Device
            var physicalDevices = Vulkan.vkEnumeratePhysicalDevices(VkInstance);

            // TODO: Implement arg parsing, etc.
            int selectedDevice = 0;

            PhysicalDevice = physicalDevices[selectedDevice];
            Debug.Assert(PhysicalDevice.Handle != IntPtr.Zero);

            vkGetPhysicalDeviceProperties(PhysicalDevice, out VkPhysicalDeviceProperties properties);
            Properties = properties;

            vkGetPhysicalDeviceFeatures(PhysicalDevice, out VkPhysicalDeviceFeatures features);
            Features = features;

            if (features.tessellationShader)
            {
                enabledFeatures.tessellationShader = true;
            }

            if (features.multiDrawIndirect)
            {
                enabledFeatures.multiDrawIndirect = true;
            }
            // Enable anisotropic filtering if supported
            if (features.samplerAnisotropy)
            {
                enabledFeatures.samplerAnisotropy = true;
            }
            // Enable texture compression
            if (features.textureCompressionBC)
            {
                enabledFeatures.textureCompressionBC = true;
            }
            else if (features.textureCompressionASTC_LDR)
            {
                enabledFeatures.textureCompressionASTC_LDR = true;
            }
            else if (features.textureCompressionETC2)
            {
                enabledFeatures.textureCompressionETC2 = true;
            }

            if (features.sparseBinding && features.sparseResidencyImage2D)
            {
                enabledFeatures.shaderResourceResidency = true;
                enabledFeatures.shaderResourceMinLod    = true;
                enabledFeatures.sparseBinding           = true;
                enabledFeatures.sparseResidencyImage2D  = true;
            }
            else
            {
                Log.Warn("Sparse binding not supported");
            }

            // Memory properties are used regularly for creating all kinds of buffers
            VkPhysicalDeviceMemoryProperties memoryProperties;

            vkGetPhysicalDeviceMemoryProperties(PhysicalDevice, out memoryProperties);
            MemoryProperties = memoryProperties;

            var qf = Vulkan.vkGetPhysicalDeviceQueueFamilyProperties(PhysicalDevice);

            QueueFamilyProperties.Add(qf);

            var extensions = Vulkan.vkEnumerateDeviceExtensionProperties(PhysicalDevice);

            foreach (var ext in extensions)
            {
                string strExt = UTF8String.FromPointer(ext.extensionName);
                //enabledExtensions.Add((IntPtr)ext.extensionName);
                supportedExtensions.Add(strExt);
            }

            device = CreateLogicalDevice(Features, enabledExtensions, true, requestedQueueTypes);

            if (device != VkDevice.Null)
            {
                VkPipelineCacheCreateInfo pipelineCacheCreateInfo = new VkPipelineCacheCreateInfo()
                {
                    sType = VkStructureType.PipelineCacheCreateInfo
                };

                VulkanUtil.CheckResult(vkCreatePipelineCache(device, &pipelineCacheCreateInfo, null, out pipelineCache));
            }

            return(device);
        }
예제 #2
0
        public unsafe Swapchain(IntPtr sdlWindow)
        {
            SDL_version version;

            SDL_GetVersion(&version);
            SDL_SysWMinfo sysWmInfo;

            sysWmInfo.version = version;
            int result = SDL_GetWMWindowInfo(sdlWindow, &sysWmInfo);

            if (result == 0)
            {
                throw new InvalidOperationException("Couldn't retrieve SDL window info.");
            }

            VkSurfaceKHR surface;

            if (SDL_Vulkan_CreateSurface(sdlWindow, Device.VkInstance.Handle, (IntPtr)(&surface)) == 0)
            {
                var error = UTF8String.FromPointer(SDL_GetError());
                Log.Error("create surface failed." + error);
            }
            ;

            Surface = surface;

            VkResult err;

            /*
             * if (sysWmInfo.subsystem == SysWMType.Windows)
             * {
             *  Win32WindowInfo win32Info = Unsafe.Read<Win32WindowInfo>(&sysWmInfo.info);
             *  // Create the os-specific Surface
             *  VkWin32SurfaceCreateInfoKHR surfaceCreateInfo = VkWin32SurfaceCreateInfoKHR.New();
             *  var processHandle = Process.GetCurrentProcess().SafeHandle.DangerousGetHandle();
             *  surfaceCreateInfo.hinstance = processHandle;
             *  surfaceCreateInfo.hwnd = win32Info.Sdl2Window;
             *  err = vkCreateWin32SurfaceKHR(Device.VkInstance, &surfaceCreateInfo, null, &surface);
             *  Surface = surface;
             * }
             * else if (sysWmInfo.subsystem == SysWMType.X11)
             * {
             *  X11WindowInfo x11Info = Unsafe.Read<X11WindowInfo>(&sysWmInfo.info);
             *  VkXlibSurfaceCreateInfoKHR surfaceCreateInfo = VkXlibSurfaceCreateInfoKHR.New();
             *  surfaceCreateInfo.dpy = (Vulkan.Xlib.Display*)x11Info.display;
             *  surfaceCreateInfo.window = new Vulkan.Xlib.Window { Value = x11Info.Sdl2Window };
             *  err = vkCreateXlibSurfaceKHR(Device.VkInstance, &surfaceCreateInfo, null, out surface);
             *  Surface = surface;
             * }
             * else
             * {
             *  throw new NotImplementedException($"SDL backend not implemented: {sysWmInfo.subsystem}.");
             * }*/

            var queueProps = vkGetPhysicalDeviceQueueFamilyProperties(Device.PhysicalDevice);

            // Iterate over each queue to learn whether it supports presenting:
            // Find a queue with present support
            // Will be used to present the swap chain Images to the windowing system
            VkBool32 *supportsPresent = stackalloc VkBool32[(int)queueProps.Length];

            for (int i = 0; i < queueProps.Length; i++)
            {
                vkGetPhysicalDeviceSurfaceSupportKHR(Device.PhysicalDevice, (uint)i, Surface, out supportsPresent[i]);
            }

            // Search for a graphics and a present queue in the array of queue
            // families, try to find one that supports both
            uint graphicsQueueNodeIndex = uint.MaxValue;
            uint presentQueueNodeIndex  = uint.MaxValue;

            for (int i = 0; i < queueProps.Length; i++)
            {
                if ((queueProps[i].queueFlags & VkQueueFlags.Graphics) != 0)
                {
                    if (graphicsQueueNodeIndex == uint.MaxValue)
                    {
                        graphicsQueueNodeIndex = (uint)i;
                    }

                    if (supportsPresent[i] == true)
                    {
                        graphicsQueueNodeIndex = (uint)i;
                        presentQueueNodeIndex  = (uint)i;
                        break;
                    }
                }
            }

            if (presentQueueNodeIndex == uint.MaxValue)
            {
                // If there's no queue that supports both present and graphics
                // try to find a separate present queue
                for (uint i = 0; i < queueProps.Length; ++i)
                {
                    if (supportsPresent[i] == true)
                    {
                        presentQueueNodeIndex = i;
                        break;
                    }
                }
            }

            // Exit if either a graphics or a presenting queue hasn't been found
            if (graphicsQueueNodeIndex == uint.MaxValue || presentQueueNodeIndex == uint.MaxValue)
            {
                throw new InvalidOperationException("Could not find a graphics and/or presenting queue!");
            }

            // todo : Add support for separate graphics and presenting queue
            if (graphicsQueueNodeIndex != presentQueueNodeIndex)
            {
                throw new InvalidOperationException("Separate graphics and presenting queues are not supported yet!");
            }

            QueueNodeIndex = graphicsQueueNodeIndex;

            // Get list of supported Surface formats
            uint formatCount;

            err = vkGetPhysicalDeviceSurfaceFormatsKHR(Device.PhysicalDevice, Surface, &formatCount, null);
            Debug.Assert(err == VkResult.Success);
            Debug.Assert(formatCount > 0);

            using Vector <VkSurfaceFormatKHR> surfaceFormats = new Vector <VkSurfaceFormatKHR>(formatCount);
            err = vkGetPhysicalDeviceSurfaceFormatsKHR(Device.PhysicalDevice, Surface, &formatCount, surfaceFormats.DataPtr);
            surfaceFormats.Count = formatCount;
            Debug.Assert(err == VkResult.Success);

            // If the Surface format list only includes one entry with VK_FORMAT_UNDEFINED,
            // there is no preferered format, so we assume VK_FORMAT_B8G8R8A8_UNORM
            if ((formatCount == 1) && (surfaceFormats[0].format == VkFormat.Undefined))
            {
                ColorFormat = VkFormat.B8G8R8A8UNorm;
                ColorSpace  = surfaceFormats[0].colorSpace;
            }
            else
            {
                // iterate over the list of available Surface format and
                // check for the presence of VK_FORMAT_B8G8R8A8_UNORM
                bool found_B8G8R8A8_UNORM = false;
                foreach (var surfaceFormat in surfaceFormats)
                {
                    if (surfaceFormat.format == VkFormat.B8G8R8A8UNorm)
                    {
                        ColorFormat          = surfaceFormat.format;
                        ColorSpace           = surfaceFormat.colorSpace;
                        found_B8G8R8A8_UNORM = true;
                        break;
                    }
                }

                // in case VK_FORMAT_B8G8R8A8_UNORM is not available
                // select the first available color format
                if (!found_B8G8R8A8_UNORM)
                {
                    ColorFormat = surfaceFormats[0].format;
                    ColorSpace  = surfaceFormats[0].colorSpace;
                }
            }
        }