当前位置:首页 > 安卓源码 > 技术博客 >

使用Kotlin Native的Vulkan表面,物理和逻辑设备

时间:2019-04-29 15:57 来源:互联网 作者:源码搜藏 浏览: 收藏 挑错 推荐 打印

介绍 好的,现在是时候创建Vulkan表面,物理和逻辑设备了。 Vulkan surface是我们已经创建的Windows,Linux或Android窗口(或其他支持的平台)的抽象。 物理设备就是它所说的 - 安装了物理设备。 从用户的角度来看,逻辑设备是物理设备。 此外,在创建逻辑设

介绍

好的,现在是时候创建Vulkan表面,物理和逻辑设备了。Vulkan surface是我们已经创建的Windows,Linux或Android窗口(或其他支持的平台)的抽象。物理设备就是它所说的 - 安装了物理设备。从用户的角度来看,逻辑设备是物理设备。此外,在创建逻辑设备时,我们将创建命令池和队列。但首先,让我对代码进行一些小改动。当我们在一个且只有一个平台上工作时,我们会将Platform更改为单例。在Kotlin,这很容易 - 只需class改为object相应地,它应该为两者expectactual

表面

我们将在实际Platform类中创建的Vulkan表面,因为它的创建对于每个平台是不同的。这取决于是否支持相应的扩展。VK_KHR_WIN32_SURFACE_EXTENSION_NAME- 对于Windows,VK_KHR_XCB_SURFACE_EXTENSION_NAME- 对于Linux等。对于Linux,我们也已经知道xcb_connection_t并且有一个窗口id对于Windows - HWNDHINSTANCE

因此,对于Windows,它将如下所示:

...
            val surfaceInfo = alloc<VkWin32SurfaceCreateInfoKHR> {
                sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR
                pNext = null
                flags = 0u
                @Suppress("UNCHECKED_CAST")
                hinstance = sharedData.hInstance!! as vulkan.HINSTANCE
                @Suppress("UNCHECKED_CAST")
                hwnd = sharedData.hwnd!! as vulkan.HWND

            }

            if (!VK_CHECK(vkCreateWin32SurfaceKHR
                  (instance, surfaceInfo.ptr, null, surfaceVar.ptr))) {
                throw RuntimeException("Failed to create surface.")
            }
...

而对于Linux:

...
            val surfaceinfo = alloc<VkXcbSurfaceCreateInfoKHR> {
                sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR
                pNext = null
                flags = 0u
                window = sharedData.wnd
                connection = sharedData.connection

            }

            val surface = alloc<VkSurfaceKHRVar>()

            if (!VK_CHECK(vkCreateXcbSurfaceKHR
                 (instance, surfaceinfo.ptr, null, surface.ptr))) {
                throw RuntimeException("Failed to create surface.")
            }

...

没什么新的,只是结构和功能调用。

物理设备

在这里,我们会更有趣。我们将枚举物理设备,选择第一个离散设备,获取驱动程序版本,表面功能,设备扩展。现在让我们在系统中查找并选择支持我们所需功能的显卡。为此,请使用我们已使用的标准方法:

...
         var buffer: CArrayPointer<VkPhysicalDeviceVar>? = null

            while (result == VK_INCOMPLETE) {

                if (!VK_CHECK(vkEnumeratePhysicalDevices(instance, gpuCount.ptr, null)))
                    throw RuntimeException("Could not enumerate GPUs.")

                buffer?.let {
                    nativeHeap.free(it)
                    buffer = null
                }

                buffer = nativeHeap.allocArray(gpuCount.value.toInt())

                result = vkEnumeratePhysicalDevices(instance, gpuCount.ptr, buffer)
                if (result != VK_INCOMPLETE && !VK_CHECK(result))
                    throw RuntimeException("Could not enumerate GPUs.")
            }
...

拥有物理设备后,我们可以获得其属性。为此,我们将为表面功能,设备属性,队列属性等创建延迟初始化属性。例如,如果我们只想获得一个可呈现的队列,它将如下所示:

...
    val presentableQueue by lazy {

        val props = queueProperties.filter {
            (it.queueFlags and VK_QUEUE_GRAPHICS_BIT) > 0u
        }

        memScoped {

            props.mapIndexed { index, it ->
                Pair(index, it)
            }.indexOfFirst {
                val p = alloc<VkBool32Var>()
                vkGetPhysicalDeviceSurfaceSupportKHR(device, it.first.toUInt(), surface, p.ptr)
                if (p.value == 1u) true else false
            }
        }
    }
...

好的,现在我们掌握了有关物理设备的所有信息。

逻辑设备

现在我们将创建与物理设备的连接。根据Vulkan规范:“ 应用程序必须为它将使用的每个物理设备创建一个单独的逻辑设备。创建的逻辑设备是物理设备的主要接口。 ”所以,让我们这样做,一路上也创建一个队列和命令池:

...            
            val queueCreateInfos: ArrayList<VkDeviceQueueCreateInfo> = ArrayList()
            val defaultQueuePriority = allocArrayOf(1.0f)

            val queueInfo = alloc<VkDeviceQueueCreateInfo>().apply {
                sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO
                queueCount = 1u
                pQueuePriorities = defaultQueuePriority

            }

            if (presentable) {     
                val queue = pdevice.presentableQueue

                if (queue < 0)
                    throw RuntimeException("Presentable queue not found")

                _queueFamilyIndices.graphics = queue.toUInt()
                queueInfo.queueFamilyIndex = _queueFamilyIndices.graphics!!
                _poolType = PoolType.GRAPHICS
            else {
                ...
            }

            if (useSwapChain && !enabledExtensions.contains(VK_KHR_SWAPCHAIN_EXTENSION_NAME))
                enabledExtensions.add(VK_KHR_SWAPCHAIN_EXTENSION_NAME)

            var idx = 0
            val queueInfos = allocArray<VkDeviceQueueCreateInfo>(queueCreateInfos.size) {
                val info = queueCreateInfos[idx++]
                this.flags = info.flags
                this.sType = info.sType
                this.flags = info.flags
                this.pNext = info.pNext
                this.pQueuePriorities = info.pQueuePriorities
                this.queueCount = info.queueCount
                this.queueFamilyIndex = info.queueFamilyIndex
            }

            val deviceCreateInfo = alloc<VkDeviceCreateInfo>().apply {
                sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO
                queueCreateInfoCount = queueCreateInfos.size.toUInt()
                pQueueCreateInfos = queueInfos
                pEnabledFeatures = enabledFeatures?.ptr
            }

            if (enabledExtensions.size > 0) {
                deviceCreateInfo.enabledExtensionCount = enabledExtensions.size.toUInt()
                deviceCreateInfo.ppEnabledExtensionNames = 
                                 enabledExtensions.toCStringArray(memScope)
            }

            if (!VK_CHECK(vkCreateDevice
                   (pdevice.device, deviceCreateInfo.ptr, null, _device.ptr)))
                throw RuntimeException("Failed to create _device")
            logDebug("Ok logical device")

            ....
            
            if (!VK_CHECK(vkCreateCommandPool
                  (_device.value, commandPoolCreateInfo.ptr, null, _commandPool.ptr)))
                throw RuntimeException("Failed to create command pool")
            
            vkGetDeviceQueue(
                _device.value, when (_poolType) {
                    PoolType.GRAPHICS -> _queueFamilyIndices.graphics!!
                    PoolType.COMPUTE -> _queueFamilyIndices.compute!!
                    PoolType.TRANSFER -> _queueFamilyIndices.transfer!!
                }, 0u, _deviceQueue.ptr
            )

           
...

精细。现在我们有了物理设备,逻辑设备,命令池和队列。将它们添加到我们的渲染器类中,不要忘记处置资源和释放已分配的内存。

使用Kotlin Native的Vulkan表面,物理和逻辑设备 转载https://www.codesocang.com/appboke/39912.html

技术博客阅读排行

最新文章