Windows 8 DirectX 和Xaml UI 混合处理方案
2012-11-29 17:01 chenkai 阅读(2727) 评论(1) 编辑 收藏 举报[如果不想读这么长问题描述和通用的解决方案. 可以直接skip 这段直接看最后我们处理一些结果.]
本篇为译文.原文详见[Combining XAML and DirectX]
从 Windows 8 的早期开发阶段开始,我们就一直在思考将 UI 合并的方式。UI 的例子包括由 XAML 所提供的一套丰富的控制与交互性,以及诸如低级别、高性能 DirectX 渲染的图形等。
您通过开发中心论坛和其他渠道所提供的反馈有助于我们将精力集中于开发人员真正希望构建的一整套相关应用场景之中。反馈意见中包含如下共同主题:各位中有很多人希望能将 DirectX 图形添加至被称为 XAML 的应用程序之中,或可轻松将 Metro 风格 UI 添加至 DirectX 应用程序之中。
告诉您一个好消息!随着 Consumer Preview 的推出,您无需再度艰难地分析 XAML 应用程序和 DirectX 应用程序间的区别。借助一个熟悉的 XAML 模型,您可在一个相同的应用程序内获得作为丰富 UI 平台的 XAML 与作为高性能渲染解决方案的 DirectX 各自的优势。
现在,您可合并这两大领域,从而真正同时拥有其各自的最佳性能。这将让众多可能变为现实,以下列举了您向我们反映的一些关键应用场景:
- 可混合 UI 和图形的图像处理、创意和设计应用程序
- 可混合特大 DirectX 图形和某些 UI 的大规模地图和文件查看器
- 包含全屏显示、高性能 DirectX 图形和 UI 覆盖程度最低的游戏和模拟
XAML 与 DirectX 的合并可提高开发人员的工作效率,并提高应用程序的丰富程度和运行速度。
Windows 8 中的 Metro 风格 UI
XAML 与 HTML/JavaScript 类似,是 Windows 8 中全部类型应用程序的 UI 工具包,其可提供用于交互、Metro 风格控制和动画的构造,以及类似可访问性支持、数据绑定、媒体和 HTML 托管等丰富功能。您同时可从 Visual Studio 和 Expression Blend 内的设计时支持中受益匪浅,而且这些内容全部采用您所选择的编程语言。
工程团队在 XAML 和 HTML/JavaScript 中均涉及了所有这些领域,而他们不断投资的一个重要领域便是性能:在 Windows 8 中,我们在这一方面投入了大量心血,因此现在您可比以往任何时候都更轻松地构建快速、流畅的 Metro 风格应用程序。特别是在图形领域,我们不断改进了渲染和组合性能,并尽可能地使用 GPU 硬件,甚至制作了 GPU 硬件,从而让常见类型的动画可脱离 UI 线程独立运行,这样一来,无论您的应用程序在 CPU 上进行哪种操作,您都可向用户呈现流畅的动画效果。我们致力于确保 UI 框架所进行的任何操作都能快速、流畅,而且对电源的要求较低。当您使用一个 UI 框架时,您就已经开始使用 DirectX 在该应用场景背后的强大功能了;许多情况下,这将为您提供您所需要的一切,并让您获得出色的图形性能。
Windows 8 中的 DirectX
尽管上文中提到了您可获得经改进的体验,但是许多时候您仍需要原始即时模式的渲染性能并直接访问 DirectX 所提供的图形设备。从 Windows 8 开始,DirectX SDK 组件将作为主要 Windows SDK 的一部分而包含于其中,而且 DirectX 包含大量全新功能,例如统一的 3D API、包含 Direct2D 且经改进的 2D 图形和文字性能、丰富图形处理管道,以及改进的打印支持。
从开发人员平台到操作系统,再到硬件设计,Windows 8 中的所有内容都得以了优化,并围绕 DirectX 而进行构建。这样一来,您可使用 DirectX 在 Windows 8 中获得最高性能的渲染。而其主要的弊端在于纯 DirectX 解决方案的创建和维护过于复杂,而且除非您使用第三方的包装,否则您必须在 C++ 中实施这些解决方案。
以下将向您介绍 DirectX 和 XAML 的互操作性将于何处奏效:现在您可使用 C#、Visual Basic 或 C++ 来构建您的 XAML,并包含 C++ DirectX 组件。您可能也想了解有关 HTML/JavaScript 和 DirectX 的信息,正如我此前所提到的,我们投入了大量精力将 DirectX 的功能融入 UI 平台之中,但是在 Windows 8 中,我们将合并 UI 和原生 DirectX 图形的重点集中于 XAML 之上。
设计目标
鉴于上述情况,我们开发了几个主要的目标,并希望在合并 DirectX 和 XAML 后能够实现这些目标:
1.性能
- 支持低延迟的输入与交互
- 允许 XAML 和 DirectX 内容的增量重绘
- 通过使用 XAML,最大程度节省开销
主要来说,我们希望避免征收“XAML 税”:如果您的应用程序主要是 DirectX,那么如果您需要 Metro UI 的话,XAML 对您而言将是一个较容易的选择。我们知道这不仅仅对您至关重要:我们希望能帮助您确保您的客户了解应用程序的卓越性能和较长的电池使用时间。
2.灵活性
- 启用 XAML 和 DirectX 11 的所有功能
其结果是您可在 Blend 和 Visual Studio 中设计并开发 XAML 界面,并将其与任何 DirectX 内容合并。我们希望确保我们并没有限制 XAML 或 DirectX 的功能,而只是让您合并二者。
3.集成
- 确保 XAML 和 DirectX 顺利集成
您可使用 XAML 概念在同一应用程序中合并 DirectX 图形和 XAML UI。
将此前所列的一系列应用场景进行分解之后,我们发现它们可以归纳为三类:
- 将所有 DirectX 岛合并成一个主要的 XAML UI
- 将大型的可扩展的 DirectX 表面与 XAML UI 合并
- 将 Metro 风格 XAML UI 覆盖至主要 DirectX 应用程序之上
最终,我们发现通用的方法在上述所有类别中效果并不好。因此,我们针对这些关键应用场景中的每一个类型而添加了三个 XAML 类型。我们相信这将为您提供高度的灵活性,从而让您选择最符合应用程序要求的选项。而且这些选项并不具有排他性,您甚至可将这三种方法应用至同一应用程序的不同组件之中。
应用场景 1 – SurfaceImageSource:XAML UI 中的 DirectX 岛
作为合并 DirectX 和 XAML 的第一个选项,您可使用全新的 SurfaceImageSource XAML 类型来将 DirectX 内容区域添加至 Metro 风格 XAML 应用程序之中。这种类型的实例可为您提供共享的 DirectX 表面,您可使用 DirectX 的所有功能来绘制该表面,然后将该表面组合至 XAML 应用程序界面的其余部分之中。
当您希望使用 DirectX 来绘制隶属于较大 XAML UI 的特定组件时,这一选项将对您大有裨益。例如,当您向照片应用复杂图像效果或创建高性能 3D 数据可视化时,您就可能希望使用 SurfaceImageSource。
如果您曾使用过 XAML ImageSource,那么您将发现其实二者的使用方法非常类似:您可将 SurfaceImageSource 设置为 ImageBrush的源,然后您可使用它来绘制几乎所有的 XAML 元素(而且画笔可重复使用!)。例如,您可使用一个 SurfaceImageSource 来填充一个 XAML 矩形:
SurfaceImageSource^ surfaceImageSource =
ref new SurfaceImageSource(rectangle1->Width, rectangle1->Height, true);
ImageBrush^ brush = ref new ImageBrush();
brush->ImageSource = surfaceImageSource;
rectangle1->Fill = brush;
然后,您可使用 DirectX 来绘制矩形的内容,并以必要的频率来更新其内容。该表面的最佳部分在于其与 XAML 组合模型实现了无缝集成:应用至该矩形的属性同时将影响您使用 DirectX 而绘制的内容。您可轻松重叠元素,并应用渲染转换、投影、Z-索引或不透明度,而且所有这一切都在 XAML 中完成,从而避免混合渲染技术中经常遇见的空隙问题:
组合了 XAML 内容的矩形 DirectX 表面
如果您认为这似乎在概念上与 WPF 中的 D3DImage 类型相似,那么恭喜您答对了!然而,我们采纳了您有关 D3DImage 的反馈意见,并开展了大量工作来增加 SurfaceImageSource 的功能和易用性。特别是,现在 SurfaceImageSource 可:支持 DirectX 11,包括 Direct2D;消除 D3DImage 拥有的许多限制(例如,SurfaceImageSource 可在远程桌面连接上运行);改进性能;并为您管理表面,因而您无需锁定和解锁,或手动创建或管理缓冲区!SurfaceImageSource 甚至可支持大于您 Direct3D 设备最大纹理尺寸的表面。
您在创建 SurfaceImageSource 时所获得的第一印象可能是乍一看,这似乎并未引入任何新方法。然而事实上,其通过备份原生界面而实施了改进;这是因为它需要直接引用仅在 C++ 中可用的 DirectX API。也就是说,在调用 DirectX API 时,您必须在 C++ XAML 应用程序或随后可包含任何 C# 或 Visual Basic 的单独 C++ WinRT 组件中使用 C++。一旦您包含了所需的头文件:
#include "windows.ui.xaml.media.dxinterop.h"
那么您可针对 ISurfaceImageSourceNative 界面进行查询,该界面可让您访问您需要启用的三种方法:
interface ISurfaceImageSourceNative: IUnknown
{
SetDevice(IDXGIDevice *pDevice);
BeginDraw(
RECT updateRect,
IDXGISurface** pSurface,
POINT* offset
);
EndDraw();
};
BeginDraw() 采用了一个 updateRect 参数,该参数可让您限制您所希望更新的区域;因此您可通过仅对表面进行较小的增量更新而改进其性能。该方法同时可返回指定了偏移的表面和点,该偏移即您应开始绘制的位置:由于您的表面可能是较大表面中的一部分,而且框架为优化整体效果而对该较大表面进行内部维护,因此即使您是在更新整个表面,您仍应确保检查该偏移。在此,您可创建并设置一个 DXGI 设备,然后使用 DirectX 开始绘制!DirectX 与 XAML 互操作性开发中心主题将就这些详细内容为您提供一个不错的概述。
应用场景 2 – VirtualSurfaceImageSource:大规模 DirectX 内容 + XAML UI
VirtualSurfaceImageSource 扩展了 SurfaceImageSource,以更好地支持特大表面。其根植于“虚拟化”的概念,即仅当表面显示于屏幕上时绘制该表面的区域。
我们设计了这类用于显示大于屏幕的复杂内容,特别显示内容可平移或缩放的方法。适用这种方法的应用场景包括从文件查看器到医疗成像应用程序的所有应用程序,这些应用程序的分辨率可能超过了普通显示器最大分辩率数倍。地图控件便是另一个典型例子:利用VirtualSurfaceImageSource,您可实施包含 DirectX,且基于矢量的大型地图,并让系统在任何给定时间跟踪显示于屏幕中的区域。您同时可覆盖诸如图钉等地图 XAML 元素,并轻松确保其位置与 DirectX 内容一致。
VirtualSurfaceImageSource 利用拼贴和回调模式实现了虚拟化。在创建了最大尺寸的 VirtualSurfaceImageSource 后,您的 DirectX 内容将在后台拆分成一系列矩形区域;框架将在任何给定的点自动跟踪可视矩形(另外为确保顺利平移,某些额外的矩形可能不在可视范围内),并调用应用程序在需要时向较新可视区域提供内容而实施的回调。当您为使用触控设备或鼠标来启用顺畅平移,进而将VirtualSurfaceImageSource 内容放置于 ScrollViewer 中时,其效果将尤为出色。
大型表面被拆分成矩形图块
相比自我跟踪协调,该方法不仅可简化实施:它同时可大幅提高您应用程序的性能。由于系统将在内部缓存您的内容,因此在您绘制了某一区域的内容后,即使其此前已平移至视图范围之外,并于随后返回视图之中,该内容仍将保留于内存之中,GPU 将自动重新使用该内容,您完全不需要重新绘制!如果您希望更新您已经绘制的任何区域,您只需像处理 SurfaceImageSource 一样调用 BeginDraw()。作为进一步优化性能一项措施,系统将自动回收用于旧区域(该区域在某个点后将位于视图范围外)的内存,进而有助于绑定内存使用,并确保您的应用程序将在大量不同外形和硬件配置文件(即使它们拥有超大型的表面)中良好运行。这一性能优势在诸如平板电脑等便携式设备中表现得尤为明显。
与使用 SurfaceImageSource 类似,您可针对备份原生界面进行查询。在本案例中即 IVirtualSurfaceImageSourceNative,以访问所需的方法。您可查看有关 DirectX 和 XAML 互操作性的开发中心文章或 Direct2D 杂志应用程序示例,以了解详情。
应用场景 3 – SwapChainBackgroundPanel:包含 XAML 覆盖的 DirectX
SwapChainBackgroundPanel 是合并 XAML 和 DirectX 的第三个也是最后一个选项,其是用于开发全屏,主要以 DirectX 为重点的应用程序的 XAML 元素。与 SurfaceImageSource 和 VirtualSurfaceImageSource 不同,SwapChainBackgroundPanel 是一个 XAML 元素,而非一个 ImageSource;其继承了 XAML 网格布局面板,可让应用程序创建并完全控制一个全屏的 DirectX 交换链,而其他所有 XAML 内容将覆盖于交换链的顶部:
SwapChainBackgroundPanel 位于覆盖的 XAML 内容之后
我们认为这绝对是应用于游戏以及大多数图形为 DirectX 的其他应用程序之中的最佳选项;您可获得出众的性能和接近于纯 DirectX 应用程序的更新模型,而且您可同时使用 XAML,进而轻松创建提示信息显示界面,并为游戏模型绑定数据,添加交互控制,以及包含诸如AppBars 等 Metro 风格应用程序元素。
为实现这一点,我们在 SwapChainBackgroundPanel 设置了一些限制:其必须为您应用程序的根 XAML 元素,而且一些继承的 XAML 属性(如不透明性和 RenderTransform)不会对其产生影响(尽管您可将同等 DirectX 操作应用至交换链内容之中,以实现这些效果)。利用 SurfaceImageSource,您可与 XAML 框架的组成模型紧密集成,而当您直接管理交换链时您可获得最低延迟交互,以及对演示计时的额外控制能力。我们所设置的限制将让您在二者之间进行权衡。
本案例中的备份原生界面只包含一个单一的方法:
interface ISwapChainBackgroundPanelNative: IUnknown
{
SetSwapChain(IDXGISwapChain *pSwapChain);
};
您可在调用 SetSwapChain() 后开始呈现内容,从而将您的交换链与面板进行关联。在这一点上,SwapChainBackgroundPanel 同时将符合命中测试标准,而且您可使用正常 XAML 输入事件来处理输入。您向面板所添加的任何子 XAML 元素都将显示于交换链的顶部。
互操作性开发中心主题中包含有关 SwapChainBackgroundPanel 用法的详细信息,而且您可查看 DirectX 射击游戏示例的源代码,该源代码使用 SwapChainBackgroundPanel 构建,并可显示出包含 XAML 界面的 Direct3D 游戏的端到端的实现过程:
使用 DirectX 和 XAML 构建的游戏
结束语
借助 DirectX 的高性能图形功能,您可将丰富的 UI 支持与设计时工作效率合二为一,对于这些全新的突破,我们感到十分兴奋。我们希望这三个用于构建 Metro 风格应用程序的全新选项对您有所帮助,从而让您创建出让客户爱不释手的应用程序
问题的描述:
其实我们最近采用Cocos2d For Windows 8 这个框架开发一个简单的Metro版本的游戏. 在考虑添加的新的功能时.于是就出现如何在Windows 8 解决Directx 和XaML UI混合处理的问题.
很多人第一次听这个问题觉得很迷惑.主要是搞不清楚它在实际运用场景. 类似我们做了3D视野旋转寻找镜头焦点然后随机抓取视野的问题. 这时你似乎就发现如果我们控制放在Xaml UI上.吧镜头旋转和图片扑捉放到Direct 中完成.之选想Xaml控制台输出扑捉的图像资源即可. 这就形成一个这样布局的需求.Xaml UI需要包含一个局部的高性能的处理 Direct输出. 这个问题视乎就这样出现了.
第二个比较特别的场景是在我们已经发布Beta版本后发现的. 我们想在Direct 中采用Xaml UI 来排序游戏分数排名的问题. 这就形成一个全屏的Direct 内容中包含一个局部的Xaml UI问题.
其实第一个问题如果采用上述的SurfaceImageSource 就很好的解决了. 具体Demo请参考这里[XAML SurfaceImageSource DirectX interop sample] 附上源码.
针对第二个问题.具体的Demo请参考这里[XAML DirectX 3D shooting game sample] 附上源码.
这两问题的解决其实就代码了在Direct和Xaml是可以实现UI相互操作和任意组合的. 虽然存在一些操作属性的小限制.但觉得已经处理大部分核心需求.
希望这些总结给遇到这些问题一些有价值的参考的.这个问题足足耗费一个通宵的时间.
更多的参考资料:
DirectX and XAML interop (Windows Store apps using C++ and DirectX)
Creating-directx-interop-libraries-for-xaml-metro-style-apps-part-1-direct2d