DirectX11 マルチスクリーン3

続き

モニターの数を取得してスワップチェインの生成,デプスステンシルバッファの生成をできるようになったので書きます.

変数の宣言

std::vector<IDXGISwapChain*> _pSwapChains;
std::vector<ID3D11Texture2D*> _pRenderTargets;
std::vector<ID3D11RenderTargetView*> _pRenderTargetViews;
std::vector<ID3D11DepthStencilState*> _pDepthStencilStates;
std::vector<ID3D11Texture2D*> _pDepthStencilTextures;
std::vector<ID3D11DepthStencilView*> _pDepthStencilViews;

uint32_t _monitorNum;

初期化

スワップチェインとデプスステンシルバッファの生成をモニターの数繰り返す

bool DxManager::Init(SCREEN* monitorInfo, uint32_t monitorNum) {
    _monitorNum = monitorNum;

    if (!CreateFactory()) {
        return false;
    }

    if (!CreateDevice()) {
        return false;
    }
    _pSwapChains.resize(monitorNum);
    _pRenderTargets.resize(monitorNum);
    _pRenderTargetViews.resize(monitorNum);
    _pDepthStencilStates.resize(monitorNum);
    _pDepthStencilTextures.resize(monitorNum);
    _pDepthStencilViews.resize(monitorNum);

    for (uint32_t i = 0; i < _monitorNum; i++) {
        if (!CreateSwapChain(monitorInfo[i], i)) {
            return false;
        }
        
        if (!CreateDepthStencilBuffer(monitorInfo[i], i)) {
            return false;
        }
    }
    return true;
}

ソースコード

DxManager.cpp

#include "DxManager.h"

DxManager* dx;

DxManager::DxManager() {
    _monitorNum = 0;
}
bool DxManager::Init(SCREEN* monitorInfo, uint32_t monitorNum) {
    _monitorNum = monitorNum;

    if (!CreateFactory()) {
        return false;
    }

    if (!CreateDevice()) {
        return false;
    }
    _pSwapChains.resize(monitorNum);
    _pRenderTargets.resize(monitorNum);
    _pRenderTargetViews.resize(monitorNum);
    _pDepthStencilStates.resize(monitorNum);
    _pDepthStencilTextures.resize(monitorNum);
    _pDepthStencilViews.resize(monitorNum);

    for (uint32_t i = 0; i < _monitorNum; i++) {
        if (!CreateSwapChain(monitorInfo[i], i)) {
            return false;
        }
        
        if (!CreateDepthStencilBuffer(monitorInfo[i], i)) {
            return false;
        }
    }

    if (!CreateBlendState()) {
        return false;
    }

    return true;
}

bool DxManager::CreateFactory() {
    ComPtr<IDXGIOutput> pOutput;
    DXGI_ADAPTER_DESC adapterDesc = {};
    size_t stringLength;
    uint32_t numModes = 0;
    uint32_t GPUMaxMem = 0;
    uint32_t GPUNum = 0;

    HRESULT hResult = S_OK;
    //DXGIファクトリーの作成
    hResult = CreateDXGIFactory(IID_PPV_ARGS(_pFactory.GetAddressOf()));
    if (FAILED(hResult)) {
        return false;
    }

    //GPUを列挙
    for (uint32_t i = 0; i < 100; i++) {
        IDXGIAdapter* adapter;
        hResult = _pFactory->EnumAdapters(i, &adapter);
        if (FAILED(hResult)) {
            break;
        }

        //GPUの情報を取得
        hResult = adapter->GetDesc(&adapterDesc);
        if (FAILED(hResult)) {
            return false;
        }

        char videoCardDesc[128];
        int error = wcstombs_s(&stringLength, videoCardDesc, 128, adapterDesc.Description, 128);
        if (error != 0) {
            break;
        }

        uint32_t videoCardMemory = (uint32_t)(adapterDesc.DedicatedVideoMemory / 1028 / 1024);
        std::cout << "ビデオカード名: " << videoCardDesc << std::endl;
        std::cout << "ビデオメモリ: " << videoCardMemory << std::endl;   

        hResult = adapter->EnumOutputs(0, pOutput.GetAddressOf());
        if (FAILED(hResult)) {
            continue;
        }

        hResult = pOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, nullptr);
        if (FAILED(hResult)) {
            continue;
        }

        //一番メモリが多いGPUを探す
        if (videoCardMemory > GPUMaxMem) {
            GPUMaxMem = videoCardMemory;
            GPUNum = i;
        }
    
    }

    //GPUを選ぶやでー
    hResult = _pFactory->EnumAdapters(GPUNum, _pAdapter.GetAddressOf());
    if (FAILED(hResult)) {
        return false;
    }
    
    return true;
}

bool DxManager::CreateDevice() {
    HRESULT hResult = S_OK;
    UINT cdev_flags = 0;

    //デバッグレイヤーを有効にするやでー
#ifdef _DEBUG
    cdev_flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

    D3D_FEATURE_LEVEL featureLevels[] = {
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_11_1,
    };

    hResult = D3D11CreateDevice(
        _pAdapter.Get(),
        D3D_DRIVER_TYPE_UNKNOWN,
        nullptr,
        cdev_flags,
        featureLevels,
        4,
        D3D11_SDK_VERSION,
        _pDevice.GetAddressOf(),
        &_featurelevel,
        _pDeviceContext.GetAddressOf()
    );
    if (FAILED(hResult)) {
        return false;
    }

    return true;
}

bool DxManager::CreateSwapChain(SCREEN monitor, uint32_t index) {
    HRESULT hResult = S_OK;
    DXGI_MODE_DESC modeDesc = {};
    modeDesc.Width = monitor.Width;
    modeDesc.Height = monitor.Height;
    modeDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
    modeDesc.RefreshRate.Numerator = 60;
    modeDesc.RefreshRate.Denominator = 1;
    modeDesc.Scaling = DXGI_MODE_SCALING_CENTERED;
    modeDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;

    DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
    ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
    swapChainDesc.BufferCount = 2;
    swapChainDesc.BufferDesc = modeDesc;
    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapChainDesc.OutputWindow = monitor.Hwnd;
    swapChainDesc.SampleDesc.Count = 1;
    swapChainDesc.SampleDesc.Quality = 0;
    swapChainDesc.Windowed = true;
    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
    swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

    hResult = _pFactory->CreateSwapChain(_pDevice.Get(), &swapChainDesc, &_pSwapChains[index]);
    if (FAILED(hResult)) {
        return false;
    }

    _pAdapter->Release();
    _pFactory->Release();
    

    hResult = _pSwapChains[index]->GetBuffer(0, IID_PPV_ARGS(&_pRenderTargets[index]));
    if (FAILED(hResult)) {
        return false;
    }

    hResult = _pDevice->CreateRenderTargetView(_pRenderTargets[index], nullptr, &_pRenderTargetViews[index]);
    if (FAILED(hResult)) {
        return false;
    }

    _viewport.Width = static_cast<float>(monitor.Width);
    _viewport.Height = static_cast<float>(monitor.Height);
    _viewport.MinDepth = 0.0f;
    _viewport.MaxDepth = 1.0f;
    _viewport.TopLeftX = 0;
    _viewport.TopLeftY = 0;
    
    

    return true;
}

bool DxManager::CreateDepthStencilBuffer(SCREEN monitor, uint32_t index) {
    D3D11_DEPTH_STENCIL_DESC desc = {};
    desc.DepthEnable = true;
    desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
    desc.DepthFunc = D3D11_COMPARISON_LESS;
    desc.StencilEnable = false;
    desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
    desc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
    desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;

    HRESULT hResult = _pDevice->CreateDepthStencilState(&desc, &_pDepthStencilStates[index]);
    if (FAILED(hResult)) {
        return false;
    }

    D3D11_TEXTURE2D_DESC Tex2Desc = {};
    Tex2Desc.Format = DXGI_FORMAT_R24G8_TYPELESS;
    Tex2Desc.Width = monitor.Width;
    Tex2Desc.Height = monitor.Height;
    Tex2Desc.ArraySize = 1;
    Tex2Desc.MipLevels = 1;
    Tex2Desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    Tex2Desc.Usage = D3D11_USAGE_DEFAULT;
    Tex2Desc.CPUAccessFlags = 0;
    Tex2Desc.SampleDesc.Count = 1;
    Tex2Desc.SampleDesc.Quality = 0;
    Tex2Desc.MiscFlags = 0;

    hResult = _pDevice->CreateTexture2D(&Tex2Desc, nullptr, &_pDepthStencilTextures[index]);
    if (FAILED(hResult)) {
        return false;
    }

    D3D11_DEPTH_STENCIL_VIEW_DESC DSVDesc = {};
    DSVDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    DSVDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    DSVDesc.Texture2D.MipSlice = 0;
    DSVDesc.Flags = 0;

    hResult = _pDevice->CreateDepthStencilView(_pDepthStencilTextures[index], &DSVDesc, &_pDepthStencilViews[index]);
    if (FAILED(hResult)) {
        return false;
    }


    return true;
}

bool DxManager::CreateBlendState() {
    D3D11_RENDER_TARGET_BLEND_DESC descRTBS = {};
    descRTBS.BlendEnable = true;
    descRTBS.SrcBlend = D3D11_BLEND_SRC_ALPHA;
    descRTBS.DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
    descRTBS.BlendOp = D3D11_BLEND_OP_ADD;
    descRTBS.SrcBlendAlpha = D3D11_BLEND_ONE;
    descRTBS.DestBlendAlpha = D3D11_BLEND_ZERO;
    descRTBS.BlendOpAlpha = D3D11_BLEND_OP_ADD;
    descRTBS.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;

    D3D11_BLEND_DESC descBS = {};
    descBS.AlphaToCoverageEnable = true;
    descBS.IndependentBlendEnable = true;
    for (uint32_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) {
        descBS.RenderTarget[i] = descRTBS;
    }

    HRESULT hResult = _pDevice->CreateBlendState(&descBS, _pBlendState.GetAddressOf());
    if (FAILED(hResult)) {
        return false;
    }
    return true;
}


void DxManager::BeginRender() {
    for (uint32_t i = 0; i < _monitorNum; i++){
        _pDeviceContext->OMSetRenderTargets(1, &_pRenderTargetViews[i], _pDepthStencilViews[i]);
        _pDeviceContext->RSSetViewports(1, &_viewport);

        float clearColor[4] = { 1.0f, 0.0f, 0.0f, 0.0f };
        _pDeviceContext->ClearRenderTargetView(_pRenderTargetViews[i], clearColor);
        _pDeviceContext->ClearDepthStencilView(_pDepthStencilViews[i], D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
    }
}

void DxManager::EndRender() {
    for (uint32_t i = 0; i < _monitorNum; i++) {
        _pSwapChains[i]->Present(1, 0);
    }
}

DxManager.h

#pragma once

#include <iostream>
#include <cstdint>
#include <vector>
#include <d3d11.h>
#include <dxgi.h>
#include <Windows.h>
#include <windef.h>
#include <wrl/client.h>

#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")

using Microsoft::WRL::ComPtr;

struct SCREEN {
    int32_t X;
    int32_t Y;
    int32_t Width;
    int32_t Height;
    HWND Hwnd;
};

class DxManager {
private:
    D3D_FEATURE_LEVEL _featurelevel;
    ComPtr<IDXGIFactory> _pFactory = nullptr;
    ComPtr<IDXGIAdapter> _pAdapter = nullptr;

    ComPtr<ID3D11Device> _pDevice = nullptr;
    ComPtr<ID3D11DeviceContext> _pDeviceContext = nullptr;
    std::vector<IDXGISwapChain*> _pSwapChains;
    std::vector<ID3D11Texture2D*> _pRenderTargets;
    std::vector<ID3D11RenderTargetView*> _pRenderTargetViews;
    std::vector<ID3D11DepthStencilState*> _pDepthStencilStates;
    std::vector<ID3D11Texture2D*> _pDepthStencilTextures;
    std::vector<ID3D11DepthStencilView*> _pDepthStencilViews;
    ComPtr<ID3D11BlendState> _pBlendState;

    D3D11_VIEWPORT _viewport;

    uint32_t _monitorNum;

public:
    DxManager();
    bool Init(SCREEN* monitorInfo, uint32_t monitorNum);

    void BeginRender();
    void EndRender();

private:
    bool CreateFactory();
    bool CreateDevice();
    bool CreateSwapChain(SCREEN montor, uint32_t index);
    bool CreateDepthStencilBuffer(SCREEN monitor, uint32_t index);
    bool CreateBlendState();
};

extern DxManager* dx;