함수 연결 그래프 구문 및 컴파일된 코드에 연결

여기서는 셰이더용 FLG(함수 연결 그래프)를 구성하는 방법과 해당 셰이더를 셰이더 라이브러리와 연결하여 Direct3D 런타임에서 사용할 수 있는 셰이더 Blob을 생성하는 방법을 보여 줍니다.

목표: 함수 연결 그래프를 구성하고 컴파일된 코드에 연결합니다.

필수 구성 요소

사용자가 C++에 익숙하다고 가정합니다. 그래픽 프로그래밍 개념에 대한 기본 경험도 필요합니다.

또한 셰이더 라이브러리 패키지 과정을 거쳤다고 가정합니다.

완료 시간: 30분입니다.

지침

1. 꼭짓점 셰이더에 대한 함수 연결 그래프를 구성합니다.

D3DCreateFunctionLinkingGraph 함수를 호출하여 꼭짓점 셰이더를 나타내는 함수 연결 그래프(ID3D11FunctionLinkingGraph)를 만듭니다.

D3D11_PARAMETER_DESC 구조체의 배열을 사용하여 꼭짓점 셰이더의 입력 매개 변수를 정의합니다. 입력 어셈블러 단계는 꼭짓점 셰이더에 입력 매개 변수를 제공합니다. 꼭짓점 셰이더의 입력 매개 변수 레이아웃은 컴파일된 코드의 꼭짓점 셰이더 레이아웃과 일치합니다. 입력 매개 변수를 정의한 후 ID3D11FunctionLinkingGraph::SetInputSignature 메서드를 호출하여 꼭짓점 셰이더에 대한 입력 노드(ID3D11LinkingNode)를 정의합니다. .

            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());

ID3D11FunctionLinkingGraph::CallFunction 메서드를 호출하여 기본 꼭짓점 셰이더 함수에 대한 노드를 만들고 ID3D11FunctionLinkingGraph::PassValue를 호출하여 입력 노드에서 기본 꼭짓점 셰이더 함수의 노드로 값을 전달합니다.

            // 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());

D3D11_PARAMETER_DESC 구조체의 배열을 사용하여 꼭짓점 셰이더의 출력 매개 변수를 정의합니다. 꼭짓점 셰이더는 출력 매개 변수를 픽셀 셰이더에 공급합니다. 꼭짓점 셰이더의 출력 매개 변수 레이아웃은 컴파일된 코드의 픽셀 셰이더 레이아웃과 일치합니다. 출력 매개 변수를 정의한 후 ID3D11FunctionLinkingGraph::SetOutputSignature 메서드를 호출하여 꼭짓점 셰이더에 대한 출력 노드(ID3D11LinkingNode)를 정의합니다. .

            // 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());

ID3D11FunctionLinkingGraph::PassValue를 호출하여 기본 꼭짓점 셰이더 함수의 노드에서 출력 노드로 값을 전달합니다.

            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());

ID3D11FunctionLinkingGraph::CreateModuleInstance 메서드를 호출하여 꼭짓점 셰이더 그래프를 마무리합니다.

            // Finalize the vertex shader graph.
            ComPtr<ID3D11ModuleInstance> vertexShaderGraphInstance;
            LinkingThrowIfFailed(vertexShaderGraph->CreateModuleInstance(&vertexShaderGraphInstance, nullptr), vertexShaderGraph.Get());

D3DCreateLinker 함수를 호출하여 이전 단계에서 만든 꼭짓점 셰이더 그래프의 인스턴스로 셰이더 라이브러리 패키지에서 만든 셰이더 라이브러리의 인스턴스를 연결하는 데 사용할 수 있는 링커(ID3D11Linker)를 만듭니다. ID3D11Linker::UseLibrary 메서드를 호출하여 연결에 사용할 셰이더 라이브러리를 지정합니다. ID3D11Linker::Link 메서드를 호출하여 셰이더 라이브러리를 꼭짓점 셰이더 그래프와 연결하고 ID3DBlob 인터페이스에 대한 포인터를 생성합니다. 컴파일된 꼭짓점 셰이더 코드에 액세스하는 데 사용할 수 있습니다. 그런 다음 이 컴파일된 꼭짓점 셰이더 코드를 ID3D11Device::CreateVertexShader 메서드에 전달하여 꼭짓점 셰이더 개체를 만들고 ID3D11Device::CreateInputLayout에 전달할 수 있습니다. 메서드를 사용하여 입력 레이아웃 개체를 만듭니다.

            // 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. 픽셀 셰이더에 대한 함수 연결 그래프를 구성합니다.

D3DCreateFunctionLinkingGraph 함수를 호출하여 함수 연결 그래프(ID3D11FunctionLinkingGraph)를 만들어 픽셀 셰이더를 나타냅니다.

D3D11_PARAMETER_DESC 구조체의 배열을 사용하여 픽셀 셰이더의 입력 매개 변수를 정의합니다. 꼭짓점 셰이더 단계는 입력 매개 변수를 픽셀 셰이더에 공급합니다. 픽셀 셰이더의 입력 매개 변수 레이아웃은 컴파일된 코드의 픽셀 셰이더 레이아웃과 일치합니다. 입력 매개 변수를 정의한 후 ID3D11FunctionLinkingGraph::SetInputSignature 메서드를 호출하여 픽셀 셰이더에 대한 입력 노드(ID3D11LinkingNode)를 정의합니다. .

            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());

ID3D11FunctionLinkingGraph::CallFunction 메서드를 호출하여 기본 픽셀 셰이더 함수에 대한 노드를 만들고 ID3D11FunctionLinkingGraph::PassValue를 호출하여 기본 픽셀 셰이더 함수의 입력 노드에서 노드로 값을 전달합니다.

            // 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());

D3D11_PARAMETER_DESC 구조체의 배열을 사용하여 픽셀 셰이더의 출력 매개 변수를 정의합니다. 픽셀 셰이더는 출력 매개 변수를 출력 병합기 단계에 공급합니다. 출력 매개 변수를 정의한 후 ID3D11FunctionLinkingGraph::SetOutputSignature 메서드를 호출하여 픽셀 셰이더에 대한 출력 노드(ID3D11LinkingNode)를 정의합니다. ID3D11FunctionLinkingGraph::PassValue를 호출하여 픽셀 셰이더 함수 노드에서 출력 노드로 값을 전달합니다.

            // 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());

ID3D11FunctionLinkingGraph::CreateModuleInstance 메서드를 호출하여 픽셀 셰이더 그래프를 마무리합니다.

            // Finalize the pixel shader graph.
            ComPtr<ID3D11ModuleInstance> pixelShaderGraphInstance;
            LinkingThrowIfFailed(pixelShaderGraph->CreateModuleInstance(&pixelShaderGraphInstance, nullptr), pixelShaderGraph.Get());

D3DCreateLinker 함수를 호출하여 이전 단계에서 만든 픽셀 셰이더 그래프의 인스턴스로 셰이더 라이브러리 패키지에서 만든 셰이더 라이브러리의 인스턴스를 연결하는 데 사용할 수 있는 링커(ID3D11Linker)를 만듭니다. ID3D11Linker::UseLibrary 메서드를 호출하여 연결에 사용할 셰이더 라이브러리를 지정합니다. ID3D11Linker::Link 메서드를 호출하여 셰이더 라이브러리를 픽셀 셰이더 그래프와 연결하고 ID3DBlob 인터페이스에 대한 포인터를 생성합니다. 컴파일된 픽셀 셰이더 코드에 액세스하는 데 사용할 수 있습니다. 그런 다음 이 컴파일된 픽셀 셰이더 코드를 ID3D11Device::CreatePixelShader 메서드에 전달하여 픽셀 셰이더 개체를 만들 수 있습니다.

            // 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);

요약

ID3D11FunctionLinkingGraph 메서드를 사용하여 꼭짓점 및 픽셀 셰이더 그래프를 구성하고 프로그래밍 방식으로 셰이더 구조체를 지정했습니다.

이러한 그래프 구문은 값을 서로 전달하는 미리 컴파일된 함수 호출 시퀀스로 구성됩니다. FLG 노드(ID3D11LinkingNode)는 입출력 셰이더 노드와 미리 컴파일된 라이브러리 함수의 호출을 나타냅니다. 함수 호출 노드를 등록하는 시퀀스는 호출 시퀀스를 정의합니다. 입력 노드(ID3D11FunctionLinkingGraph::SetInputSignature)를 먼저 지정하고 출력 노드를 마지막(ID3D11FunctionLinkingGraph::SetOutputSignature)으로 지정해야 합니다. FLG 에지는 한 노드에서 다른 노드로 값이 전달되는 방식을 정의합니다. 전달된 값의 데이터 형식은 동일해야 합니다. 암시적 형식 변환이 없습니다. 모양 및 swizzling 규칙은 HLSL 동작을 따릅니다. 값은 이 시퀀스로만 전달될 수 있습니다.

또한 ID3D11Linker 메서드를 사용하여 셰이더 라이브러리를 셰이더 그래프와 연결하고 Direct3D 런타임에서 사용할 셰이더 Blob을 생성했습니다.

축하합니다! 이제 고유의 앱에서 셰이더 연결을 사용할 준비가 되었습니다.

셰이더 연결 사용