Construcción de un grafo de vinculación de función y vinculación a código compilado
Aquí se muestra cómo construir gráficos de vinculación de funciones (FLG) para sombreadores y cómo vincular esos sombreadores con una biblioteca de sombreadores para generar blobs de sombreador que el entorno de ejecución de Direct3D puede usar.
Objetivo: Para construir un grafo de vinculación de funciones y vincularlo al código compilado.
Prerrequisitos
Suponemos que estás familiarizado con C++. También necesitas tener experiencia básica en los conceptos de programación de elementos gráficos.
También suponemos que ha pasado por Empaquetar una biblioteca de sombreador.
Tiempo de finalización: 30 minutos.
Instrucciones
1. Construya un grafo de vinculación de función para el sombreador de vértices.
Llame a la función D3DCreateFunctionLinkingGraph para crear un gráfico de vinculación de funciones (ID3D11FunctionLinkingGraph) para representar el sombreador de vértices.
Use una matriz de estructuras de D3D11_PARAMETER_DESC para definir los parámetros de entrada para el sombreador de vértices. La fase de ensamblador de entrada alimenta los parámetros de entrada al sombreador de vértices. El diseño de los parámetros de entrada del sombreador de vértices coincide con el diseño del sombreador de vértices en el código compilado. Después de definir los parámetros de entrada, llame al método ID3D11FunctionLinkingGraph::SetInputSignature para definir el nodo de entrada (ID3D11LinkingNode) para el sombreador de vértices.
ComPtr<ID3D11FunctionLinkingGraph> vertexShaderGraph;
DX::ThrowIfFailed(D3DCreateFunctionLinkingGraph(0, &vertexShaderGraph));
// Define the main input node which will be fed by the Input Assembler pipeline stage.
static const D3D11_PARAMETER_DESC vertexShaderInputParameters[] =
{
{"inputPos", "POSITION0", D3D_SVT_FLOAT, D3D_SVC_VECTOR, 1, 3, D3D_INTERPOLATION_LINEAR, D3D_PF_IN, 0, 0, 0, 0},
{"inputTex", "TEXCOORD0", D3D_SVT_FLOAT, D3D_SVC_VECTOR, 1, 2, D3D_INTERPOLATION_LINEAR, D3D_PF_IN, 0, 0, 0, 0},
{"inputNorm", "NORMAL0", D3D_SVT_FLOAT, D3D_SVC_VECTOR, 1, 3, D3D_INTERPOLATION_LINEAR, D3D_PF_IN, 0, 0, 0, 0}
};
ComPtr<ID3D11LinkingNode> vertexShaderInputNode;
LinkingThrowIfFailed(vertexShaderGraph->SetInputSignature(vertexShaderInputParameters, ARRAYSIZE(vertexShaderInputParameters),
&vertexShaderInputNode), vertexShaderGraph.Get());
Llame al método ID3D11FunctionLinkingGraph::CallFunction para crear un nodo para la función principal del sombreador de vértices y realizar llamadas a ID3D11FunctionLinkingGraph::P assValue para pasar valores desde el nodo de entrada al nodo para la función del sombreador de vértices principal.
// Create a node for the main VertexFunction call using the output of the helper functions.
ComPtr<ID3D11LinkingNode> vertexFunctionCallNode;
LinkingThrowIfFailed(vertexShaderGraph->CallFunction("", shaderLibrary.Get(), "VertexFunction", &vertexFunctionCallNode),
vertexShaderGraph.Get());
// Define the graph edges from the input node and helper function nodes.
LinkingThrowIfFailed(vertexShaderGraph->PassValue(homogenizeCallNodeForPos.Get(), D3D_RETURN_PARAMETER_INDEX,
vertexFunctionCallNode.Get(), 0), vertexShaderGraph.Get());
LinkingThrowIfFailed(vertexShaderGraph->PassValue(vertexShaderInputNode.Get(), 1, vertexFunctionCallNode.Get(), 1),
vertexShaderGraph.Get());
LinkingThrowIfFailed(vertexShaderGraph->PassValue(homogenizeCallNodeForNorm.Get(), D3D_RETURN_PARAMETER_INDEX,
vertexFunctionCallNode.Get(), 2), vertexShaderGraph.Get());
Use una matriz de estructuras de D3D11_PARAMETER_DESC para definir los parámetros de salida para el sombreador de vértices. El sombreador de vértices alimenta sus parámetros de salida al sombreador de píxeles. El diseño de los parámetros de salida del sombreador de vértices coincide con el diseño del sombreador de píxeles en el código compilado. Después de definir los parámetros de salida, llame al método ID3D11FunctionLinkingGraph::SetOutputSignature para definir el nodo de salida (ID3D11LinkingNode) para el sombreador de vértices.
// Define the main output node which will feed the Pixel Shader pipeline stage.
static const D3D11_PARAMETER_DESC vertexShaderOutputParameters[] =
{
{"outputTex", "TEXCOORD0", D3D_SVT_FLOAT, D3D_SVC_VECTOR, 1, 2, D3D_INTERPOLATION_UNDEFINED, D3D_PF_OUT, 0, 0, 0, 0},
{"outputNorm", "NORMAL0", D3D_SVT_FLOAT, D3D_SVC_VECTOR, 1, 3, D3D_INTERPOLATION_UNDEFINED, D3D_PF_OUT, 0, 0, 0, 0},
{"outputPos", "SV_POSITION", D3D_SVT_FLOAT, D3D_SVC_VECTOR, 1, 4, D3D_INTERPOLATION_UNDEFINED, D3D_PF_OUT, 0, 0, 0, 0}
};
ComPtr<ID3D11LinkingNode> vertexShaderOutputNode;
LinkingThrowIfFailed(vertexShaderGraph->SetOutputSignature(vertexShaderOutputParameters, ARRAYSIZE(vertexShaderOutputParameters),
&vertexShaderOutputNode), vertexShaderGraph.Get());
Realice llamadas a ID3D11FunctionLinkingGraph::P assValue para pasar valores del nodo para la función de sombreador de vértices principal al nodo de salida.
LinkingThrowIfFailed(vertexShaderGraph->PassValue(vertexFunctionCallNode.Get(), 0, vertexShaderOutputNode.Get(), 2),
vertexShaderGraph.Get());
LinkingThrowIfFailed(vertexShaderGraph->PassValue(vertexFunctionCallNode.Get(), 1, vertexShaderOutputNode.Get(), 0),
vertexShaderGraph.Get());
LinkingThrowIfFailed(vertexShaderGraph->PassValue(vertexFunctionCallNode.Get(), 2, vertexShaderOutputNode.Get(), 1),
vertexShaderGraph.Get());
Llame al método ID3D11FunctionLinkingGraph::CreateModuleInstance para finalizar el gráfico del sombreador de vértices.
// Finalize the vertex shader graph.
ComPtr<ID3D11ModuleInstance> vertexShaderGraphInstance;
LinkingThrowIfFailed(vertexShaderGraph->CreateModuleInstance(&vertexShaderGraphInstance, nullptr), vertexShaderGraph.Get());
2. Vincular el sombreador de vértices
Llame a la función D3DCreateLinker para crear un enlazador (ID3D11Linker) que puede usar para vincular la instancia de la biblioteca de sombreadores que creó en Empaquetado de una biblioteca de sombreadores con la instancia del gráfico de sombreador de vértices que creó en el paso anterior. Llame al método ID3D11Linker::UseLibrary para especificar la biblioteca de sombreador que se va a usar para vincular. Llame al método ID3D11Linker::Link para vincular la biblioteca de sombreadores con el gráfico del sombreador de vértices y para generar un puntero a la interfaz ID3DBlob que puede usar para tener acceso al código del sombreador de vértices compilado. A continuación, puede pasar este código de sombreador de vértices compilado al método ID3D11Device::CreateVertexShader para crear el objeto sombreador de vértices y al método ID3D11Device::CreateInputLayout para crear el objeto input-layout.
// Create a linker and hook up the module instance.
ComPtr<ID3D11Linker> linker;
DX::ThrowIfFailed(D3DCreateLinker(&linker));
DX::ThrowIfFailed(linker->UseLibrary(shaderLibraryInstance.Get()));
// Link the vertex shader.
ComPtr<ID3DBlob> errorBlob;
if (FAILED(linker->Link(vertexShaderGraphInstance.Get(), "main", ("vs" + m_shaderModelSuffix).c_str(), 0, &vertexShaderBlob,
&errorBlob)))
{
throw errorBlob;
}
ComPtr<ID3D11VertexShader> vertexShader;
DX::ThrowIfFailed(
device->CreateVertexShader(
vertexShaderBlob->GetBufferPointer(),
vertexShaderBlob->GetBufferSize(),
nullptr,
&vertexShader
)
);
context->VSSetShader(vertexShader.Get(), nullptr, 0);
D3D11_INPUT_ELEMENT_DESC inputLayoutDesc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
ComPtr<ID3D11InputLayout> inputLayout;
DX::ThrowIfFailed(device->CreateInputLayout(inputLayoutDesc, ARRAYSIZE(inputLayoutDesc), vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &inputLayout));
context->IASetInputLayout(inputLayout.Get());
3. Construya un grafo de vinculación de función para el sombreador de píxeles.
Llame a la función D3DCreateFunctionLinkingGraph para crear un gráfico de vinculación de funciones (ID3D11FunctionLinkingGraph) para representar el sombreador de píxeles.
Use una matriz de estructuras de D3D11_PARAMETER_DESC para definir los parámetros de entrada para el sombreador de píxeles. La fase del sombreador de vértices alimenta los parámetros de entrada al sombreador de píxeles. El diseño de los parámetros de entrada del sombreador de píxeles coincide con el diseño del sombreador de píxeles en el código compilado. Después de definir los parámetros de entrada, llame al método ID3D11FunctionLinkingGraph::SetInputSignature para definir el nodo de entrada (ID3D11LinkingNode) para el sombreador de píxeles.
ComPtr<ID3D11FunctionLinkingGraph> pixelShaderGraph;
DX::ThrowIfFailed(D3DCreateFunctionLinkingGraph(0, &pixelShaderGraph));
// Define the main input node which will be fed by the vertex shader pipeline stage.
static const D3D11_PARAMETER_DESC pixelShaderInputParameters[] =
{
{"inputTex", "TEXCOORD0", D3D_SVT_FLOAT, D3D_SVC_VECTOR, 1, 2, D3D_INTERPOLATION_UNDEFINED, D3D_PF_IN, 0, 0, 0, 0},
{"inputNorm", "NORMAL0", D3D_SVT_FLOAT, D3D_SVC_VECTOR, 1, 3, D3D_INTERPOLATION_UNDEFINED, D3D_PF_IN, 0, 0, 0, 0},
{"inputPos", "SV_POSITION", D3D_SVT_FLOAT, D3D_SVC_VECTOR, 1, 4, D3D_INTERPOLATION_UNDEFINED, D3D_PF_IN, 0, 0, 0, 0}
};
ComPtr<ID3D11LinkingNode> pixelShaderInputNode;
LinkingThrowIfFailed(pixelShaderGraph->SetInputSignature(pixelShaderInputParameters, ARRAYSIZE(pixelShaderInputParameters),
&pixelShaderInputNode), pixelShaderGraph.Get());
Llame al método ID3D11FunctionLinkingGraph::CallFunction para crear un nodo para la función de sombreador de píxeles principal y realizar llamadas a ID3D11FunctionLinkingGraph::P assValue para pasar valores desde el nodo de entrada al nodo para la función del sombreador de píxeles principal.
// Create a node for the main ColorFunction call and connect it to the pixel shader inputs.
ComPtr<ID3D11LinkingNode> colorValueNode;
LinkingThrowIfFailed(pixelShaderGraph->CallFunction("", shaderLibrary.Get(), "ColorFunction", &colorValueNode),
pixelShaderGraph.Get());
// Define the graph edges from the input node.
LinkingThrowIfFailed(pixelShaderGraph->PassValue(pixelShaderInputNode.Get(), 0, colorValueNode.Get(), 0),
pixelShaderGraph.Get());
LinkingThrowIfFailed(pixelShaderGraph->PassValue(pixelShaderInputNode.Get(), 1, colorValueNode.Get(), 1),
pixelShaderGraph.Get());
Use una matriz de estructuras de D3D11_PARAMETER_DESC para definir los parámetros de salida para el sombreador de píxeles. El sombreador de píxeles alimenta sus parámetros de salida a la fase de fusión de salida. Después de definir los parámetros de salida, llame al método ID3D11FunctionLinkingGraph::SetOutputSignature para definir el nodo de salida (ID3D11LinkingNode) para el sombreador de píxeles y realice llamadas a ID3D11FunctionLinkingGraph::P assValue para pasar valores de un nodo de función de sombreador de píxeles al nodo de salida.
// Define the main output node which will feed the Output Merger pipeline stage.
D3D11_PARAMETER_DESC pixelShaderOutputParameters[] =
{
{"outputColor", "SV_TARGET", D3D_SVT_FLOAT, D3D_SVC_VECTOR, 1, 4, D3D_INTERPOLATION_UNDEFINED, D3D_PF_OUT, 0, 0, 0, 0}
};
ComPtr<ID3D11LinkingNode> pixelShaderOutputNode;
LinkingThrowIfFailed(pixelShaderGraph->SetOutputSignature(pixelShaderOutputParameters, ARRAYSIZE(pixelShaderOutputParameters),
&pixelShaderOutputNode), pixelShaderGraph.Get());
LinkingThrowIfFailed(pixelShaderGraph->PassValue(fillAlphaCallNode.Get(), D3D_RETURN_PARAMETER_INDEX, pixelShaderOutputNode.Get(), 0),
pixelShaderGraph.Get());
Llame al método ID3D11FunctionLinkingGraph::CreateModuleInstance para finalizar el gráfico del sombreador de píxeles.
// Finalize the pixel shader graph.
ComPtr<ID3D11ModuleInstance> pixelShaderGraphInstance;
LinkingThrowIfFailed(pixelShaderGraph->CreateModuleInstance(&pixelShaderGraphInstance, nullptr), pixelShaderGraph.Get());
4. Vincular el sombreador de píxeles
Llame a la función D3DCreateLinker para crear un enlazador (ID3D11Linker) que puede usar para vincular la instancia de la biblioteca de sombreadores que creó en Empaquetado de una biblioteca de sombreadores con la instancia del gráfico de sombreador de píxeles que creó en el paso anterior. Llame al método ID3D11Linker::UseLibrary para especificar la biblioteca de sombreador que se va a usar para vincular. Llame al método ID3D11Linker::Link para vincular la biblioteca de sombreadores con el gráfico del sombreador de píxeles y para generar un puntero a la interfaz ID3DBlob que puede usar para acceder al código del sombreador de píxeles compilado. A continuación, puede pasar este código de sombreador de píxeles compilado al método ID3D11Device::CreatePixelShader para crear el objeto de sombreador de píxeles.
// Create a linker and hook up the module instance.
ComPtr<ID3D11Linker> linker;
DX::ThrowIfFailed(D3DCreateLinker(&linker));
DX::ThrowIfFailed(linker->UseLibrary(shaderLibraryInstance.Get()));
// Link the pixel shader.
ComPtr<ID3DBlob> errorBlob;
if (FAILED(linker->Link(pixelShaderGraphInstance.Get(), "main", ("ps" + m_shaderModelSuffix).c_str(), 0, &pixelShaderBlob, &errorBlob)))
{
throw errorBlob;
}
ComPtr<ID3D11PixelShader> pixelShader;
DX::ThrowIfFailed(
device->CreatePixelShader(
pixelShaderBlob->GetBufferPointer(),
pixelShaderBlob->GetBufferSize(),
nullptr,
&pixelShader
)
);
context->PSSetShader(pixelShader.Get(), nullptr, 0);
Resumen
Usamos los métodos ID3D11FunctionLinkingGraph para construir los gráficos de vértices y sombreador de píxeles y especificar la estructura del sombreador mediante programación.
Estas construcciones de grafos constan de secuencias de llamadas de función precompiladas que pasan valores entre sí. Los nodos FLG (ID3D11LinkingNode) representan nodos de sombreador de entrada y salida e invocaciones de funciones de biblioteca precompiladas. El orden en el que registra los nodos de llamada de función define la secuencia de invocaciones. Primero debe especificar el nodo de entrada (ID3D11FunctionLinkingGraph::SetInputSignature) y el último nodo de salida (ID3D11FunctionLinkingGraph::SetOutputSignature). Los bordes FLG definen cómo se pasan los valores de un nodo a otro. Los tipos de datos de valores pasados deben ser los mismos; no hay ninguna conversión de tipos implícita. Las reglas de forma y desbaste siguen el comportamiento de HLSL. Los valores solo se pueden pasar adelante en esta secuencia.
También hemos usado métodos ID3D11Linker para vincular la biblioteca de sombreadores con los gráficos de sombreador y para generar blobs de sombreador para que el entorno de ejecución de Direct3D lo use.
¡Enhorabuena! Ya está listo para usar la vinculación del sombreador en sus propias aplicaciones.
Temas relacionados