Construction d’un graphique de liaison de fonction et liaison de celui-ci à du code compilé
Ici, nous vous montrons comment construire des graphiques de liaison de fonction (FLG) pour les nuanceurs et comment lier ces nuanceurs à une bibliothèque de nuanceurs pour produire des objets blob de nuanceur que le runtime Direct3D peut utiliser.
Objectif: Pour construire un graphe de liaison de fonction et le lier au code compilé.
Prérequis
Nous partons du principe que vous êtes familiarisé avec C++. Vous avez également besoin d’une expérience de base dans les concepts de programmation graphique.
Nous partons également du principe que vous avez passé par Empaquetage d’une bibliothèque de nuanceurs.
Durée d’exécution : 30 minutes.
Instructions
1. Construisez un graphe de liaison de fonction pour le nuanceur de vertex.
Appelez la fonction D3DCreateFunctionLinkingGraph pour créer un graphe de liaison de fonction (ID3D11FunctionLinkingGraph) pour représenter le nuanceur de vertex.
Utilisez un tableau de structures D3D11_PARAMETER_DESC pour définir les paramètres d’entrée du nuanceur de vertex. La phase d’assembleur d’entrée alimente les paramètres d’entrée dans le nuanceur de vertex. La disposition des paramètres d’entrée du nuanceur de vertex correspond à la disposition du nuanceur de vertex dans le code compilé. Après avoir défini les paramètres d’entrée, appelez la méthode ID3D11FunctionLinkingGraph::SetInputSignature pour définir le nœud d’entrée (ID3D11LinkingNode) pour le nuanceur de vertex.
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());
Appelez la méthode ID3D11FunctionLinkingGraph::CallFunction pour créer un nœud pour la fonction de nuanceur de vertex main et effectuer des appels à ID3D11FunctionLinkingGraph::P assValue pour passer des valeurs du nœud d’entrée au nœud pour la fonction de nuanceur de vertex main.
// 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());
Utilisez un tableau de structures D3D11_PARAMETER_DESC pour définir les paramètres de sortie du nuanceur de vertex. Le nuanceur de vertex alimente ses paramètres de sortie dans le nuanceur de pixels. La disposition des paramètres de sortie du nuanceur de vertex correspond à la disposition du nuanceur de pixels dans le code compilé. Après avoir défini les paramètres de sortie, appelez la méthode ID3D11FunctionLinkingGraph::SetOutputSignature pour définir le nœud de sortie (ID3D11LinkingNode) pour le nuanceur de vertex.
// 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());
Effectuez des appels à ID3D11FunctionLinkingGraph::P assValue pour passer des valeurs du nœud pour la fonction de nuanceur de vertex main au nœud de sortie.
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());
Appelez la méthode ID3D11FunctionLinkingGraph::CreateModuleInstance pour finaliser le graphique de nuanceur de vertex.
// Finalize the vertex shader graph.
ComPtr<ID3D11ModuleInstance> vertexShaderGraphInstance;
LinkingThrowIfFailed(vertexShaderGraph->CreateModuleInstance(&vertexShaderGraphInstance, nullptr), vertexShaderGraph.Get());
2. Lier le nuanceur de vertex
Appelez la fonction D3DCreateLinker pour créer un éditeur de liens (ID3D11Linker) que vous pouvez utiliser pour lier les instance de la bibliothèque de nuanceurs que vous avez créée dans Empaquetage d’une bibliothèque de nuanceurs avec le instance du graphique de nuanceur de vertex que vous avez créé à l’étape précédente. Appelez la méthode ID3D11Linker::UseLibrary pour spécifier la bibliothèque de nuanceur à utiliser pour la liaison. Appelez la méthode ID3D11Linker::Link pour lier la bibliothèque de nuanceurs au graphique de nuanceur de vertex et produire un pointeur vers l’interface ID3DBlob que vous pouvez utiliser pour accéder au code de nuanceur de vertex compilé. Vous pouvez ensuite passer ce code de nuanceur de vertex compilé à la méthode ID3D11Device::CreateVertexShader pour créer l’objet de nuanceur de vertex et à la méthode ID3D11Device::CreateInputLayout pour créer l’objet 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. Construisez un graphe de liaison de fonction pour le nuanceur de pixels.
Appelez la fonction D3DCreateFunctionLinkingGraph pour créer un graphe de liaison de fonction (ID3D11FunctionLinkingGraph) pour représenter le nuanceur de pixels.
Utilisez un tableau de structures D3D11_PARAMETER_DESC pour définir les paramètres d’entrée du nuanceur de pixels. L’étape du nuanceur de vertex alimente les paramètres d’entrée dans le nuanceur de pixels. La disposition des paramètres d’entrée du nuanceur de pixels correspond à la disposition du nuanceur de pixels dans le code compilé. Après avoir défini les paramètres d’entrée, appelez la méthode ID3D11FunctionLinkingGraph::SetInputSignature pour définir le nœud d’entrée (ID3D11LinkingNode) pour le nuanceur de pixels.
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());
Appelez la méthode ID3D11FunctionLinkingGraph::CallFunction pour créer un nœud pour la fonction de nuanceur de pixels main et effectuer des appels à ID3D11FunctionLinkingGraph::P assValue pour passer des valeurs du nœud d’entrée au nœud pour la fonction de nuanceur de pixels main.
// 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());
Utilisez un tableau de structures D3D11_PARAMETER_DESC pour définir les paramètres de sortie du nuanceur de pixels. Le nuanceur de pixels alimente ses paramètres de sortie dans l’étape Sortie-fusion. Après avoir défini les paramètres de sortie, appelez la méthode ID3D11FunctionLinkingGraph::SetOutputSignature pour définir le nœud de sortie (ID3D11LinkingNode) pour le nuanceur de pixels et appeler ID3D11FunctionLinkingGraph::P assValue pour passer les valeurs d’un nœud de fonction nuanceur de pixels au nœud de sortie.
// 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());
Appelez la méthode ID3D11FunctionLinkingGraph::CreateModuleInstance pour finaliser le graphe de nuanceur de pixels.
// Finalize the pixel shader graph.
ComPtr<ID3D11ModuleInstance> pixelShaderGraphInstance;
LinkingThrowIfFailed(pixelShaderGraph->CreateModuleInstance(&pixelShaderGraphInstance, nullptr), pixelShaderGraph.Get());
4. Lier le nuanceur de pixels
Appelez la fonction D3DCreateLinker pour créer un éditeur de liens (ID3D11Linker) que vous pouvez utiliser pour lier les instance de la bibliothèque de nuanceurs que vous avez créée dans Empaquetage d’une bibliothèque de nuanceurs avec le instance du graphique de nuanceur de pixels que vous avez créé à l’étape précédente. Appelez la méthode ID3D11Linker::UseLibrary pour spécifier la bibliothèque de nuanceur à utiliser pour la liaison. Appelez la méthode ID3D11Linker::Link pour lier la bibliothèque de nuanceurs au graphique de nuanceur de pixels et produire un pointeur vers l’interface ID3DBlob que vous pouvez utiliser pour accéder au code de nuanceur de pixels compilé. Vous pouvez ensuite passer ce code de nuanceur de pixels compilé à la méthode ID3D11Device::CreatePixelShader pour créer l’objet de nuanceur de pixels.
// 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);
Récapitulatif
Nous avons utilisé les méthodes ID3D11FunctionLinkingGraph pour construire les graphiques de nuanceur de vertex et de pixels et pour spécifier la structure du nuanceur par programmation.
Ces constructions de graphe se composent de séquences d’appels de fonction précompilés qui se transmettent des valeurs. Les nœuds FLG (ID3D11LinkingNode) représentent les nœuds de nuanceur d’entrée et de sortie et les appels de fonctions de bibliothèque précompilées. L’ordre dans lequel vous inscrivez les nœuds d’appel de fonction définit la séquence d’appels. Vous devez d’abord spécifier le nœud d’entrée (ID3D11FunctionLinkingGraph::SetInputSignature) et le dernier nœud de sortie (ID3D11FunctionLinkingGraph::SetOutputSignature). Les bords FLG définissent la façon dont les valeurs sont transmises d’un nœud à un autre. Les types de données des valeurs passées doivent être les mêmes ; il n’y a pas de conversion de type implicite. Les règles de forme et de basculement suivent le comportement HLSL. Les valeurs ne peuvent être transmises vers l’avant que dans cette séquence.
Nous avons également utilisé des méthodes ID3D11Linker pour lier la bibliothèque de nuanceurs aux graphiques de nuanceur et pour produire des objets blob de nuanceur à utiliser par le runtime Direct3D.
Félicitations ! Vous êtes maintenant prêt à utiliser la liaison de nuanceur dans vos propres applications.
Rubriques connexes