信息
您所需的主题如下所示。但此主题未包含在此库中。

为 Windows Phone 8 创建 Direct3D 设备和交换链

2014/6/18

本主题介绍为 Windows Phone 创建 Direct3D 图形设备和交换链的正确方式。Windows Phone SDK 8.0 所包含的 Direct3D 应用项目模板包括了为您执行这些任务的代码。本主题旨在指出创建手机交换链时的一些要求,并提供了有关少量代码更改的建议,以用于创建帮助您在使用 Windows Phone 8 模拟器 时更加准确地测试应用的图形设备。

ID3D11Device 是 Direct3D 开发的重要界面。它用于创建您将用到的大多数其他图形资源,如纹理、顶点缓冲区和着色器。创建该设备的代码位于 Direct3Dbase 类的 CreateDeviceResources 方法中的 Direct3D 应用项目模板内。


	D3D_FEATURE_LEVEL featureLevels[] = 
	{
		D3D_FEATURE_LEVEL_11_1,
		D3D_FEATURE_LEVEL_11_0,
		D3D_FEATURE_LEVEL_10_1,
		D3D_FEATURE_LEVEL_10_0,
		D3D_FEATURE_LEVEL_9_3
	};

	// Create the Direct3D 11 API device object and a corresponding context.
	ComPtr<ID3D11Device> device;
	ComPtr<ID3D11DeviceContext> context;
	DX::ThrowIfFailed(
		D3D11CreateDevice(
			nullptr, // Specify nullptr to use the default adapter.
			D3D_DRIVER_TYPE_HARDWARE,
			nullptr,
			creationFlags, // Set set debug and Direct2D compatibility flags.
			featureLevels, // List of feature levels this app can support.
			ARRAYSIZE(featureLevels),
			D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION.
			&device, // Returns the Direct3D device created.
			&m_featureLevel, // Returns feature level of device created.
			&context // Returns the device immediate context.
			)
		);

	// Get the Direct3D 11.1 API device and context interfaces.
	DX::ThrowIfFailed(
		device.As(&m_d3dDevice)
		);

	DX::ThrowIfFailed(
		context.As(&m_d3dContext)
		);



请注意,featureLevels 数组包含的常数列表代表任何特定设备可能支持的不同设备功能级别。调用 CreateD3D11Device 时,将针对当前设备支持的数组中第一个功能级别创建设备。Windows Phone 仅支持功能级别 9_3,因此,这是在物理设备上运行时将返回的唯一设备。但是,Windows Phone 8 模拟器 可以允许创建功能级别更高的设备。不论您是在设备上还是模拟器上运行应用,为了确保您用正确的功能级别测试应用,建议您更新代码,以便只请求功能级别 9_3。为了实现这一点,请将 featureLevels 数组更改为以下内容。


	D3D_FEATURE_LEVEL featureLevels[] = 
	{
		D3D_FEATURE_LEVEL_9_3
	};


有关功能级别 9_3 支持的详细信息,请参见Windows Phone 8 的 Direct3D 功能级别 9_3

Direct3D 应用使用交换链将后台缓冲区的内容复制到屏幕上。使用 IDXGIFactory2 接口创建交换链。手机仅支持该接口公开的方法的子集。有关受支持的 API 的完整列表,请参见 Supported Direct3D APIs for Windows Phone

除了一些 DXGI 方法在手机上完全不可用的事实之外,Windows Phone 8 上的 DXGI 也展现出受支持 API 的一些关键差异,主要涉及交换链的创建及其与 IDXGIFactory2::CreateSwapChainForCoreWindow 相关的后台缓冲区。以下列表指出这些关键差异:

  1. DXGI_SWAP_CHAIN_DESC1.Format - 在 Windows Phone 8 上,唯一支持的显示格式是 DXGI_FORMAT_B8G8R8A8_UNORM。

  2. DXGI_SWAP_CHAIN_DESC1.BufferCount - 在 Windows Phone 8 上,交换链的缓冲区计数必须为 1。如果指定大于 1 的值,则 DXGI 将默认为 1。

  3. DXGI_SWAP_CHAIN_DESC1.SwapEffect - 在 Windows Phone 8 上,唯一支持的交换效果是 DXGI_SWAP_EFFECT_DISCARD。这意味着,DXGI 将不会在显示后台缓冲区的内容之后保留它。

  4. DXGI_SWAP_CHAIN_DESC1.Scaling - 在 Windows Phone 8 上,支持的缩放模式仅有 DXGI_SCALING_STRETCH 和 DXGI_SCALING_ASPECT_RATIO_STRETCH。当后台缓冲区的大小与目标输出不相等时,DXGI_SCALING_STRETCH 将缩放后台缓冲区内容,使之适合目标输出(不考虑纵横比),而 DXGI_SCALING_ASPECT_RATIO_STRETCH 将根据需要执行纵横比保留缩放并对内容执行 letterbox 操作。

以下代码显示 Direct3D 应用项目模板中的交换链创建。


	m_windowBounds = m_window->Bounds;

	// Calculate the necessary swap chain and render target size in pixels.
	m_renderTargetSize.Width = ConvertDipsToPixels(m_windowBounds.Width);
	m_renderTargetSize.Height = ConvertDipsToPixels(m_windowBounds.Height);

	DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
	swapChainDesc.Width = static_cast<UINT>(m_renderTargetSize.Width); // Match the size of the window.
	swapChainDesc.Height = static_cast<UINT>(m_renderTargetSize.Height);
	swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format.
	swapChainDesc.Stereo = false;
	swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling.
	swapChainDesc.SampleDesc.Quality = 0;
	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	swapChainDesc.BufferCount = 1; // On phone, only single buffering is supported.
	swapChainDesc.Scaling = DXGI_SCALING_STRETCH; // On phone, only stretch and aspect-ratio stretch scaling are allowed.
	swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; // On phone, no swap effects are supported.
	swapChainDesc.Flags = 0;

	ComPtr<IDXGIDevice1> dxgiDevice;
	DX::ThrowIfFailed(
		m_d3dDevice.As(&dxgiDevice)
		);

	ComPtr<IDXGIAdapter> dxgiAdapter;
	DX::ThrowIfFailed(
		dxgiDevice->GetAdapter(&dxgiAdapter)
		);

	ComPtr<IDXGIFactory2> dxgiFactory;
	DX::ThrowIfFailed(
		dxgiAdapter->GetParent(
			__uuidof(IDXGIFactory2), 
			&dxgiFactory
			)
		);

	Windows::UI::Core::CoreWindow^ window = m_window.Get();
	DX::ThrowIfFailed(
		dxgiFactory->CreateSwapChainForCoreWindow(
			m_d3dDevice.Get(),
			reinterpret_cast<IUnknown*>(window),
			&swapChainDesc,
			nullptr, // Allow on all displays.
			&m_swapChain
			)
		);


显示: