DirectX12 ⑥ パイプラインステートの作成

パイプラインステートの作成 

描画するためのパイプライン

環境

言語 : C++
開発環境 : Visual Studio 2020
OS : Windows10
CPU : AMD Ryzen5 3600
RAM : 24.0GB
GPU : NVIDIA GeForce GTX 1050

ソースコード

PipelineState.h

#pragma once

#include <d3d12.h>
#include <d3dcompiler.h>
#include <cstdint>
#include <wrl/client.h>
#include <iostream>
#include <string>

#include "Dx.h"
#include "DxStruct.h"

#pragma comment(lib, "d3d12.lib")
#pragma comment(lib, "d3dcompiler.lib")

using namespace Microsoft::WRL;


class PipelineState
{
public:
    PipelineState();
    bool CreatePipelineState();

    void SetInputLayout(D3D12_INPUT_LAYOUT_DESC layout);
    void SetRootSignature(ID3D12RootSignature* rootSignature);
    bool SetVertexShader(std::wstring filePath);
    bool SetPixelShader(std::wstring filePath);

    ID3D12PipelineState* GetPipelineState();

private:
    D3D12_GRAPHICS_PIPELINE_STATE_DESC _desc;
    ComPtr<ID3D12PipelineState> _pPipelineState;

    ComPtr<ID3DBlob> _pBlobVS;
    ComPtr<ID3DBlob> _pBlobPS;
};

PipelieState.cpp

#include "PipelineState.h"

//初期化
PipelineState::PipelineState() {
    _desc = {};

    // ラスタライザーステートの設定
    D3D12_RASTERIZER_DESC descRS;
    descRS.FillMode = D3D12_FILL_MODE_SOLID;    //ソリッドモデル
    descRS.CullMode = D3D12_CULL_MODE_NONE;     //カリングはしない
    descRS.FrontCounterClockwise = false;       //インデックスは時計回り
    descRS.DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
    descRS.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
    descRS.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
    descRS.DepthClipEnable = true;
    descRS.MultisampleEnable = false;       //サンプリングはしない
    descRS.AntialiasedLineEnable = false;   //アンチエイリアスはしない
    descRS.ForcedSampleCount = 0;
    descRS.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;

    // レンダーターゲットのブレンド設定
    D3D12_RENDER_TARGET_BLEND_DESC descRTBS = {};
    descRTBS.BlendEnable = true;        //アルファブレンドはON
    descRTBS.LogicOpEnable = false;     

    descRTBS.SrcBlend = D3D12_BLEND_ONE;  
    descRTBS.DestBlend = D3D12_BLEND_ZERO;
    descRTBS.BlendOp = D3D12_BLEND_OP_ADD;

    descRTBS.SrcBlendAlpha = D3D12_BLEND_ONE;
    descRTBS.DestBlendAlpha = D3D12_BLEND_ZERO;
    descRTBS.BlendOpAlpha = D3D12_BLEND_OP_MIN;

    descRTBS.LogicOp = D3D12_LOGIC_OP_NOOP;
    descRTBS.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;

    //ブレンドステート
    D3D12_BLEND_DESC descBS;
    descBS.AlphaToCoverageEnable = true;
    descBS.IndependentBlendEnable = true;
    for (uint32_t i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) {
        descBS.RenderTarget[i] = descRTBS;
    }

    //深度ステンシルステート
    D3D12_DEPTH_STENCIL_DESC descDSS = {};
    descDSS.DepthEnable = true;     //深度ON
    descDSS.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
    descDSS.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
    descDSS.StencilEnable = true;   //ステンシルON
    descDSS.StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;
    descDSS.StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;
    descDSS.FrontFace.StencilFailOp = D3D12_STENCIL_OP_KEEP;
    descDSS.FrontFace.StencilDepthFailOp = D3D12_STENCIL_OP_KEEP;
    descDSS.FrontFace.StencilPassOp = D3D12_STENCIL_OP_INCR;
    descDSS.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL;
    descDSS.BackFace.StencilFailOp = D3D12_STENCIL_OP_KEEP;
    descDSS.BackFace.StencilDepthFailOp = D3D12_STENCIL_OP_KEEP;
    descDSS.BackFace.StencilPassOp = D3D12_STENCIL_OP_INCR;
    descDSS.BackFace.StencilFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL;

    _desc.RasterizerState = descRS;
    _desc.BlendState = descBS;
    _desc.DepthStencilState = descDSS;
    _desc.SampleMask = UINT_MAX;
    _desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
    _desc.NumRenderTargets = 1;
    _desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
    _desc.DSVFormat = DXGI_FORMAT_D32_FLOAT;
    _desc.SampleDesc.Count = 1;
    _desc.SampleDesc.Quality = 0;
}

//入力レイアウトをセット
void PipelineState::SetInputLayout(D3D12_INPUT_LAYOUT_DESC layout) {
    _desc.InputLayout = layout;
}

//ルートシグネチャをセット
void PipelineState::SetRootSignature(ID3D12RootSignature* rootSignature) {
    _desc.pRootSignature = rootSignature;
}

//頂点シェーダをセット
bool PipelineState::SetVertexShader(std::wstring filePath) {
    HRESULT hResult = D3DReadFileToBlob(filePath.c_str(), _pBlobVS.GetAddressOf());
    if (FAILED(hResult)) {
        std::cout << "Failed to read VertexShader" << std::endl;
        return false;
    }
    _desc.VS.pShaderBytecode = _pBlobVS->GetBufferPointer();
    _desc.VS.BytecodeLength = _pBlobVS->GetBufferSize();

    return true;
}

//ピクセルシェーダをセット
bool PipelineState::SetPixelShader(std::wstring filePath) {
    HRESULT hResult = D3DReadFileToBlob(filePath.c_str(), _pBlobPS.GetAddressOf());
    if (FAILED(hResult)) {
        std::cout << "Failed to read PixelShader" << std::endl;
        return false;
    }
    _desc.PS.pShaderBytecode = _pBlobPS->GetBufferPointer();
    _desc.PS.BytecodeLength = _pBlobPS->GetBufferSize();
    
    return true;
}

//パイプラインステートの作成
bool PipelineState::CreatePipelineState() {
    HRESULT hResult = dx->GetDevice()->CreateGraphicsPipelineState(&_desc, IID_PPV_ARGS(_pPipelineState.GetAddressOf()));
    if (FAILED(hResult)) {
        std::cout << "Failed to create GraphicsPipelineState" << std::endl;
        return false;
    }

    return true;
}

//パイプラインステートの取得
ID3D12PipelineState* PipelineState::GetPipelineState() {
    return _pPipelineState.Get();
}

参考資料

書籍

サイト

qiita.com

learn.microsoft.com