Compartilhar via


Comparar o pipeline do sombreador do OpenGL ES 2.0 com o Direct3D

APIs importantes

Conceitualmente, o pipeline do sombreador Direct3D 11 é muito semelhante ao do OpenGL ES 2.0. Em termos de design de API, no entanto, os principais componentes para criar e gerenciar os estágios do sombreador são partes de duas interfaces primárias, ID3D11Device1 e ID3D11DeviceContext1. Este tópico tenta mapear padrões comuns de API de pipeline de sombreador do OpenGL ES 2.0 para os equivalentes do Direct3D 11 nessas interfaces.

Revisando o pipeline do sombreador do Direct3D 11

Os objetos de sombreador são criados com métodos na interface ID3D11Device1 , como ID3D11Device1::CreateVertexShader e ID3D11Device1::CreatePixelShader.

O pipeline de gráficos do Direct3D 11 é gerenciado por instâncias da interface ID3D11DeviceContext1 e tem os seguintes estágios:

  • Estágio do montador de entrada. O estágio do assembler de entrada fornece dados (triângulos, linhas e pontos) para o pipeline. Os métodos ID3D11DeviceContext1 que dão suporte a esse estágio são prefixados com "IA".
  • Estágio do sombreador de vértice – o estágio do sombreador de vértice processa vértices, normalmente executando operações como transformações, esfolamento e iluminação. Um sombreador de vértice sempre usa um único vértice de entrada e produz um único vértice de saída. Os métodos ID3D11DeviceContext1 que dão suporte a esse estágio são prefixados com "VS".
  • Estágio de saída de fluxo - O estágio de saída de fluxo transmite dados primitivos do pipeline para a memória a caminho do rasterizador. Os dados podem ser transmitidos e/ou passados para o rasterizador. Os dados transmitidos para a memória podem ser recirculados de volta para o pipeline como dados de entrada ou leitura da CPU. ID3D11DeviceContext1 métodos que dão suporte a esse estágio são prefixados com "SO".
  • Estágio do rasterizador - O rasterizador recorta primitivos, prepara primitivos para o sombreador de pixel e determina como invocar sombreadores de pixel. Você pode desabilitar a rasterização informando ao pipeline que não há sombreador de pixel (defina o estágio do sombreador de pixel como NULL com ID3D11DeviceContext::P SSetShader) e desabilitando o teste de profundidade e estêncil (defina DepthEnable e StencilEnable como FALSE no D3D11_DEPTH_STENCIL_DESC). Enquanto desabilitados, os contadores de pipeline relacionados à rasterização não serão atualizados.
  • Estágio de sombreador de pixel - O estágio de sombreador de pixel recebe dados interpolados para um primitivo e gera dados por pixel, como cor. Os métodos ID3D11DeviceContext1 que dão suporte a esse estágio são prefixados com "PS".
  • Estágio de Fusão de Saída – o estágio de fusão de saída combina vários tipos de dados de saída (valores de sombreador de pixel, informações de profundidade e estêncil) com o conteúdo do destino de renderização e buffers de profundidade/estêncil para gerar o resultado final do pipeline. Os métodos ID3D11DeviceContext1 que dão suporte a esse estágio são prefixados com "OM".

(Também há estágios para sombreadores de geometria, sombreadores de casco, tesseladores e sombreadores de domínio, mas como eles não têm análogos no OpenGL ES 2.0, não os discutiremos aqui.) Para obter uma lista completa dos métodos para esses estágios, consulte as páginas de referência ID3D11DeviceContext e ID3D11DeviceContext1 . ID3D11DeviceContext1 estende ID3D11DeviceContext para Direct3D 11.

Criando um sombreador

No Direct3D, os recursos de sombreador não são criados antes de compilá-los e carregá-los; em vez disso, o recurso é criado quando o HLSLis é carregado. Portanto, não há nenhuma função diretamente análoga a glCreateShader, que cria um recurso de sombreador inicializado de um tipo específico (como GL_VERTEX_SHADER ou GL_FRAGMENT_SHADER). Em vez disso, os sombreadores são criados depois que o HLSL é carregado com funções específicas, como ID3D11Device1::CreateVertexShader e ID3D11Device1::CreatePixelShader, e que usam o tipo e o HLSL compilado como parâmetros.

OpenGL ES 2.0 Direct3D 11
glCreateShader Chame ID3D11Device1::CreateVertexShader e ID3D11Device1::CreatePixelShader depois de carregar com êxito o objeto de sombreador compilado, passando a eles o CSO como um buffer.

 

Compilando um sombreador

Os sombreadores Direct3D devem ser pré-compilados como arquivos .cso (Objeto de Sombreador Compilado) em aplicativos UWP (Plataforma Universal do Windows) e carregados usando uma das APIs de arquivo do Tempo de Execução do Windows. (Os aplicativos da área de trabalho podem compilar os sombreadores de arquivos de texto ou cadeia de caracteres em tempo de execução.) Os arquivos CSO são criados a partir de qualquer arquivo .hlsl que faça parte do seu projeto do Microsoft Visual Studio e mantêm os mesmos nomes, apenas com uma extensão de arquivo .cso. Certifique-se de que eles estão incluídos no seu pacote quando você enviar!

OpenGL ES 2.0 Direct3D 11
glCompileShader N/D Compile os sombreadores para arquivos .cso no Visual Studio e inclua-os em seu pacote.
Usando glGetShaderiv para compilar o status N/D Consulte a saída de compilação do FXC (FX Compiler) do Visual Studio se houver erros na compilação. Se a compilação for bem-sucedida, um arquivo CSO correspondente será criado.

 

Carregando um sombreador

Conforme observado na seção sobre como criar um sombreador, o Direct3D 11 cria o sombreador quando o arquivo CSO correspondente é carregado em um buffer e passado para um dos métodos na tabela a seguir.

OpenGL ES 2.0 Direct3D 11
ShaderSource Chame ID3D11Device1::CreateVertexShader e ID3D11Device1::CreatePixelShader depois de carregar com êxito o objeto de sombreador compilado.

 

Configurando o pipeline

O OpenGL ES 2.0 tem o objeto "programa de sombreamento", que contém vários sombreadores para execução. Sombreadores individuais são anexados ao objeto de programa do sombreador. No entanto, no Direct3D 11, você trabalha com o contexto de renderização (ID3D11DeviceContext1) diretamente e cria sombreadores nele.

OpenGL ES 2.0 Direct3D 11
glCreateProgram N/D O Direct3D 11 não usa a abstração do objeto do programa de sombreador.
Programa glLinkProgram N/D O Direct3D 11 não usa a abstração do objeto do programa de sombreador.
glUseProgram N/D O Direct3D 11 não usa a abstração do objeto do programa de sombreador.
glGetProgramiv Use a referência que você criou para ID3D11DeviceContext1.

 

Crie uma instância de ID3D11DeviceContext1 e ID3D11Device1 com o método estático D3D11CreateDevice .

Microsoft::WRL::ComPtr<ID3D11Device1>          m_d3dDevice;
Microsoft::WRL::ComPtr<ID3D11DeviceContext1>  m_d3dContext;

// ...

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 for UWP apps.
  &device, // Returns the Direct3D device created.
  &m_featureLevel, // Returns feature level of device created.
  &m_d3dContext // Returns the device's immediate context.
);

Configurando a(s) viewport(s)

Definir um visor no Direct3D 11 é muito semelhante a como você define um visor no OpenGL ES 2.0. No Direct3D 11, chame ID3D11DeviceContext::RSSetViewports com um CD3D11_VIEWPORT configurado.

Direct3D 11: Definindo um visor.

CD3D11_VIEWPORT viewport(
        0.0f,
        0.0f,
        m_d3dRenderTargetSize.Width,
        m_d3dRenderTargetSize.Height
        );
m_d3dContext->RSSetViewports(1, &viewport);
OpenGL ES 2.0 Direct3D 11
glViewport CD3D11_VIEWPORT, ID3D11DeviceContext::RSSetViewports

 

Configurando os sombreadores de vértice

A configuração de um sombreador de vértice no Direct3D 11 é feita quando o sombreador é carregado. Os uniformes são passados como buffers constantes usando ID3D11DeviceContext1::VSSetConstantBuffers1.

OpenGL ES 2.0 Direct3D 11
glAttachShader ID3D11Device1::CreateVertexShader
glGetShaderiv, glGetShaderSource ID3D11DeviceContext1::VSGetShader
glGetUniformfv, glGetUniformiv ID3D11DeviceContext1::VSGetConstantBuffers1.

 

Configurando os sombreadores de pixel

A configuração de um sombreador de pixel no Direct3D 11 é feita quando o sombreador é carregado. Os uniformes são passados como buffers constantes usando ID3D11DeviceContext1::P SSetConstantBuffers1.

OpenGL ES 2.0 Direct3D 11
glAttachShader ID3D11Device1::CreatePixelShader
glGetShaderiv, glGetShaderSource ID3D11DeviceContext1::P SGetShader
glGetUniformfv, glGetUniformiv ID3D11DeviceContext1::P SGetConstantBuffers1.

 

Gerando os resultados finais

Quando o pipeline for concluído, você desenhará os resultados dos estágios do sombreador no buffer traseiro. No Direct3D 11, assim como no Open GL ES 2.0, isso envolve chamar um comando draw para gerar os resultados como um mapa de cores no buffer traseiro e, em seguida, enviar esse buffer traseiro para a exibição.

OpenGL ES 2.0 Direct3D 11
glDrawElements ID3D11DeviceContext1::D raw, ID3D11DeviceContext1::D rawIndexed (ou outros métodos Draw* em ID3D11DeviceContext1).
eglSwapBuffers IDXGISwapChain1::P resent1

 

Portabilidade de GLSL para HLSL

GLSL e HLSL não são muito diferentes além do suporte a tipos complexos e sintaxe alguma sintaxe geral. Muitos desenvolvedores acham mais fácil portar entre os dois aliasing de instruções e definições comuns do OpenGL ES 2.0 para seu equivalente HLSL. Observe que o Direct3D usa a versão do Modelo de Sombreador para expressar o conjunto de recursos do HLSL com suporte por uma interface gráfica; O OpenGL tem uma especificação de versão diferente para HLSL. A tabela a seguir tenta dar uma ideia aproximada dos conjuntos de recursos de linguagem de sombreador definidos para Direct3D 11 e OpenGL ES 2.0 nos termos da versão do outro.

Linguagem do sombreador Versão do recurso GLSL Modelo de sombreador Direct3D
Direct3D 11 HLSL ~4,30. SM 5.0
GLSL ES para OpenGL ES 2.0 1.40. Implementações mais antigas do GLSL ES para OpenGL ES 2.0 podem usar 1.10 a 1.30. Verifique seu código original com glGetString(GL_SHADING_LANGUAGE_VERSION) ou glGetString(SHADING_LANGUAGE_VERSION) para determiná-lo. ~ SM 2.0

 

Para obter mais detalhes sobre as diferenças entre as duas linguagens de sombreador, bem como mapeamentos de sintaxe comuns, leia a referência GLSL para HLSL.

Portabilidade dos intrínsecos do OpenGL para a semântica HLSL

A semântica HLSL do Direct3D 11 são cadeias de caracteres que, como um nome uniforme ou de atributo, são usadas para identificar um valor passado entre o aplicativo e um programa de sombreador. Embora possam ser qualquer uma das várias cadeias de caracteres possíveis, a prática recomendada é usar uma cadeia de caracteres como POSITION ou COLOR que indica o uso. Você atribui essa semântica quando está construindo um buffer constante ou um layout de entrada de buffer. Você também pode acrescentar um número entre 0 e 7 à semântica para usar registros separados para valores semelhantes. Por exemplo: COLOR0, COLOR1, COLOR2...

A semântica prefixada com "SV_" é a semântica de valor do sistema gravada pelo programa de sombreador; seu próprio aplicativo (em execução na CPU) não pode modificá-los. Normalmente, eles contêm valores que são entradas ou saídas de outro estágio de sombreador no pipeline de gráficos ou são gerados inteiramente pela GPU.

Além disso, SV_ semântica têm comportamentos diferentes quando são usadas para especificar entrada ou saída de um estágio de sombreador. Por exemplo, SV_POSITION (saída) contém os dados de vértice transformados durante o estágio do sombreador de vértice e SV_POSITION (entrada) contém os valores de posição de pixel interpolados durante a rasterização.

Aqui estão alguns mapeamentos para intrínsecos comuns do sombreador OpenGL ES 2.0:

Valor do sistema OpenGL Usar esta semântica HLSL
gl_Position POSITION(n) para dados de buffer de vértice. SV_POSITION fornece uma posição de pixel para o sombreador de pixel e não pode ser gravado pelo seu aplicativo.
gl_Normal NORMAL(n) para dados normais fornecidos pelo buffer de vértice.
gl_TexCoord[n] TEXCOORD(n) para dados de coordenadas UV de textura (ST em alguma documentação do OpenGL) fornecidos a um sombreador.
gl_FragColor COLOR(n) para dados de cor RGBA fornecidos a um sombreador. Observe que ele é tratado de forma idêntica para coordenar dados; A semântica simplesmente ajuda a identificar que são dados de cores.
gl_FragData[n] SV_Target[n] para gravar de um sombreador de pixel em uma textura de destino ou outro buffer de pixel.

 

O método pelo qual você codifica a semântica não é o mesmo que usar intrínsecos no OpenGL ES 2.0. No OpenGL, você pode acessar muitos dos intrínsecos diretamente, sem qualquer configuração ou declaração; no Direct3D, você deve declarar um campo em um buffer constante específico para usar uma semântica específica ou declará-lo como o valor retornado para o método main() de um sombreador.

Aqui está um exemplo de uma semântica usada em uma definição de buffer constante:

struct VertexShaderInput
{
  float3 pos : POSITION;
  float3 color : COLOR0;
};

// The position is interpolated to the pixel value by the system. The per-vertex color data is also interpolated and passed through the pixel shader. 
struct PixelShaderInput
{
  float4 pos : SV_POSITION;
  float3 color : COLOR0;
};

Esse código define um par de buffers constantes simples

E aqui está um exemplo de uma semântica usada para definir o valor retornado por um sombreador de fragmento:

// A pass-through for the (interpolated) color data.
float4 main(PixelShaderInput input) : SV_TARGET
{
  return float4(input.color,1.0f);
}

Nesse caso, SV_TARGET é o local do destino de renderização no qual a cor do pixel (definida como um vetor com quatro valores flutuantes) é gravada quando o sombreador conclui a execução.

Para obter mais detalhes sobre o uso da semântica com o Direct3D, leia Semântica HLSL.