Adreno GPU上从 OpenGL ES 迁移到 Direct3D11.1介绍 (1)

  • 6 从 OpenGL ES 迁移到 Direct3D11.1
  • 6.1 OpenGL ES 2.0/3.0 与 Direct3D11.1 Feature Level 9_3 的特性对比
  • 6.2 将 OpenGL ES 代码映射到 Direct3D11
  • 6.2.1 顶点和索引缓冲区对象


6 从 OpenGL ES 迁移到 Direct3D11.1

本章是为开发人员将应用程序从 OpenGL ES 2.0/3.0 迁移到 Direct3D11.1 功能级别 9_3 的指南。 在提供与 OpenGL ES 类似的功能的同时,Direct3D11.1 是一个完全不同的 API。 以下部分详细介绍了 OpenGL ES API 的各个部分如何映射到 Direct3D11.1。

6.1 OpenGL ES 2.0/3.0 与 Direct3D11.1 Feature Level 9_3 的特性对比

Adreno GPU 支持 OpenGL ES 2.0、OpenGL ES 3.0 和 Direct3D11.1 功能级别 9_3。 下表列出了 Adreno 的每个 API 中公开的功能。 对于不属于核心 OpenGL ES 2.0/3.0 的功能,会列出支持该功能的扩展。 此表为开发人员提供了有关其 OpenGL ES 2.0 或 OpenGL ES 3.0 应用程序功能是否可以在 Direct3D11.1 功能级别 9_3 中使用的高级指南。

opengapps刷入android10_顶点着色器


opengapps刷入android10_directx_02

6.2 将 OpenGL ES 代码映射到 Direct3D11

开发人员将应用程序从 OpenGL ES 移植到 Direct3D11 会遇到 OpenGL ES 和 Direct3D11 之间的大量 API 差异。 本节提供了将 OpenGL ES 功能移植到 Direct3D11 的指南。

6.2.1 顶点和索引缓冲区对象

大多数 OpenGL ES 应用程序都将静态顶点数据存储在顶点缓冲区对象 (VBO) 中。 一些 OpenGL ES 应用程序还依赖客户端顶点数组在绘制时将数据从 CPU 传输到 GPU。 Direct3D11 中没有等效的客户端顶点数组; 所有顶点数据必须存储在缓冲区 (ID3D11Buffer) 中。

以下 OpenGL ES 代码显示了创建顶点缓冲区对象并为其加载数据的典型示例:

GLuint hBufferHandle;
glGenBuffers( 1, &hBufferHandle );
glBindBuffer( GL_ARRAY_BUFFER, hBufferHandle );
glBufferData( GL_ARRAY_BUFFER, nNumVertices*nVertexSize, pSrcVertices,
GL_STATIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0 );

可以在 Direct3D11 中使用以下代码创建用于字符串相同顶点数据的 ID3D11Buffer:

D3D11_BUFFER_DESC bdesc = CD3D11_BUFFER_DESC( nVertexSize * nNumVertices,
D3D11_BIND_VERTEX_BUFFER );
D3D11_SUBRESOURCE_DATA vertexBufferData;
vertexBufferData.pSysMem = pSrcVertices;
vertexBufferData.SysMemPitch = 0;
vvertexBufferData.SysMemSlicePitch = 0;
ComPtr<ID3D11Buffer> buffer;
if ( FAILED( pD3DDevice->CreateBuffer( &bdesc, &vertexBufferData, &buffer) ) )
{
return FALSE;
}

在创建 OpenGL ES 索引缓冲区对象 (IBO) 和 Direct3D11 中用于存储索引的 ID3D11Buffer 之间存在类似的代码映射。 在 OpenGL ES 中,VBO 使用 glBindBuffer() 绑定渲染,然后使用 glBindVertexAttribPointer() 和 glEnableVertexAttribArray() 绑定到顶点属性。 在 Direct3D11 中,顶点和索引缓冲区使用如下代码绑定到输入汇编器 (IA):

UINT32 offset = 0;
pD3DDeviceContext->IASetVertexBuffers(
0,								//StartSlot
1,								//NumBuffers
pVertexBuffer.GetAddressOf(),	//VertexBuffers
&m_nVertexSize,//Strides
&offset);//Offsets
DXGI_FORMAT format = (m_nIndexSize == 2) ? DXGI_FORMAT_R16_UINT :
DXGI_FORMAT_R32_UINT;
pD3DDeviceContext->IASetIndexBuffer(
pIndexBuffer.Get(),	// IndexBuffer
format,				// Format
0);					// Offset

OpenGL ES 和 Direct3D11 之间的一大区别是顶点数据作为输入绑定到顶点着色器的方式。 在 Direct3D11 中,必须使用对顶点着色器字节代码的引用来创建 ID3D11InputLayout 对象。 ID3D11InputLayout 对象定义了顶点数据在内存中的布局方式以及它如何绑定到顶点着色器中提供的 HLSL 语义。

例如,假设有一个顶点着色器声明了以下输入集:

struct VertexShaderInput
{
float2 vVertexPos : POSITION;
float4 vVertexColor: COLOR0;
float2 vVertexTex : TEXCOORD0;
};

使用以下代码描述布局:

D3D11_INPUT_ELEMENT_DESC inputDesc[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA,
0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT,
D3D11_INPUT_PER_VERTEX_DATA, 0},
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT),
D3D11_INPUT_PER_VERTEX_DATA, 0},
};

然后可以使用以下命令创建 ID3D11InputLayout 对象D3D11_INPUT_ELEMENT_DESC数组和顶点着色器字节码如下:

ComPtr<ID3D11InputLayout> inputLayout;
result = !FAILED(
pD3DDevice->CreateInputLayout(
inputDesc,
3,
vertexShaderByteCode,
vertexShaderByteCodeSize,
&inputLayout) );

在渲染时,顶点布局必须设置为输入汇编器,如下所示:

pD3DDeviceContext->IASetInputLayout(inputLayout.Get());