<commit_before>// Copyright (c) 2013-2015 mogemimi.
// Distributed under the MIT license. See LICENSE.md file for details.

#include "GraphicsDeviceDirect3D11.hpp"
#include "BufferDirect3D11.hpp"
#include "EffectReflectionDirect3D11.hpp"
#include "PipelineStateDirect3D11.hpp"
#include "RenderTarget2DDirect3D11.hpp"
#include "SamplerStateDirect3D11.hpp"
#include "Texture2DDirect3D11.hpp"
#include "../RenderSystem/ShaderBytecode.hpp"
#include "../RenderSystem/ShaderCompileOptions.hpp"
#include "Pomdog/Graphics/BufferUsage.hpp"
#include "Pomdog/Graphics/ShaderLanguage.hpp"
#include "Pomdog/Logging/Log.hpp"
#include "Pomdog/Utility/StringFormat.hpp"
#include "Pomdog/Utility/Assert.hpp"
#include "Pomdog/Utility/Exception.hpp"
#include <array>

namespace Pomdog {
namespace Detail {
namespace RenderSystem {
namespace Direct3D11 {
namespace {

using Microsoft::WRL::ComPtr;

class AdapterManager final {
private:
    std::vector<ComPtr<IDXGIAdapter1>> adapters;
    ComPtr<IDXGIAdapter1> activeAdapter;

public:
    void EnumAdapters();
    void Clear();

    IDXGIAdapter1* ActiveAdapter() const
    {
        POMDOG_ASSERT(activeAdapter);
        return activeAdapter.Get();
    }

    ComPtr<IDXGIFactory1> GetFactory()
    {
        ComPtr<IDXGIFactory1> dxgiFactory;

        POMDOG_ASSERT(activeAdapter);
        HRESULT hr = activeAdapter->GetParent(__uuidof(IDXGIFactory1), &dxgiFactory);
        if (FAILED(hr))
        {
            ///@todo throw exception

            // FUS RO DAH!
            Log::Internal("Failed to get DXGIFactory1");
        }

        return std::move(dxgiFactory);
    }
};
//-----------------------------------------------------------------------
void AdapterManager::EnumAdapters()
{
    Microsoft::WRL::ComPtr<IDXGIFactory1> dxgiFactory;
    HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(dxgiFactory.GetAddressOf()));

    if (FAILED(hr))
    {
        // error
        ///@todo throw exception
        Log::Internal("Failed to create DXGIFactory1.");
        return;
    }

    UINT i = 0;
    Microsoft::WRL::ComPtr<IDXGIAdapter1> newAdapter;
    while ((hr = dxgiFactory->EnumAdapters1(i, &newAdapter)) != DXGI_ERROR_NOT_FOUND)
    {
        if (FAILED(hr))
        {
            // error
            ///@todo throw exception
            Log::Internal("Failed to enumerate adapters.");
            break;
        }

        adapters.push_back(newAdapter);
        newAdapter.Reset();
        ++i;
    }

    if (adapters.empty())
    {
        // error
        ///@todo throw exception
        return;
    }

    POMDOG_ASSERT(!adapters.empty());
    activeAdapter = adapters.front();
}
//-----------------------------------------------------------------------
void AdapterManager::Clear()
{
    activeAdapter.Reset();

    for (auto & adapter : adapters) {
        adapter.Reset();
    }
    adapters.clear();
}
//-----------------------------------------------------------------------
static ID3D11InfoQueue* BuildInfoQueue(ID3D11Device* nativeDevice)
{
    POMDOG_ASSERT(nativeDevice);

    ID3D11InfoQueue* infoQueue = nullptr;
    HRESULT hr = nativeDevice->QueryInterface(__uuidof(ID3D11InfoQueue), reinterpret_cast<void**>(&infoQueue));

    POMDOG_ASSERT(SUCCEEDED(hr));

    if (FAILED(hr)) {
        // error
        ///@todo throw exception
    }

    if (!infoQueue) {
        return nullptr;
    }

    infoQueue->ClearRetrievalFilter();
    infoQueue->ClearStorageFilter();

    D3D11_INFO_QUEUE_FILTER filter;
    ZeroMemory(&filter, sizeof(filter));

    std::array<D3D11_MESSAGE_SEVERITY, 4> severityList = {
        D3D11_MESSAGE_SEVERITY_CORRUPTION,
        D3D11_MESSAGE_SEVERITY_ERROR,
        D3D11_MESSAGE_SEVERITY_WARNING,
        D3D11_MESSAGE_SEVERITY_INFO,
    };

    filter.DenyList.pSeverityList = severityList.data();
    filter.DenyList.NumSeverities = severityList.size();

    infoQueue->AddStorageFilterEntries(&filter);
    infoQueue->AddRetrievalFilterEntries(&filter);

    return std::move(infoQueue);
}
//-----------------------------------------------------------------------
static void CheckError(ID3D11InfoQueue* infoQueue)
{
#if defined(DEBUG) && !defined(NDEBUG)
    POMDOG_ASSERT(infoQueue);
#endif

    if (!infoQueue) {
        return;
    }

    const auto storedMessageCount = infoQueue->GetNumStoredMessages();

    std::string message;
    for (UINT64 i = 0; i < storedMessageCount; ++i)
    {
        SIZE_T messageByteLength = 0;
        infoQueue->GetMessage(i, nullptr, &messageByteLength);

        if (messageByteLength <= 0) {
            continue;
        }

        std::vector<D3D11_MESSAGE> messageBuffer(messageByteLength);
        infoQueue->GetMessage(i, messageBuffer.data(), &messageByteLength);
        message += messageBuffer.data()->pDescription;
        message += "\n";
    }

    if (message.empty())
    {
        Log::Internal(message);
    }
}
//-----------------------------------------------------------------------
static D3D11_BIND_FLAG ToBindFlag(BufferBindMode bindMode) noexcept
{
    switch (bindMode) {
    case BufferBindMode::ConstantBuffer: return D3D11_BIND_CONSTANT_BUFFER;
    case BufferBindMode::IndexBuffer: return D3D11_BIND_INDEX_BUFFER;
    case BufferBindMode::VertexBuffer:
        break;
    }
    return D3D11_BIND_VERTEX_BUFFER;
}

} // unnamed namespace
//-----------------------------------------------------------------------
class GraphicsDeviceDirect3D11::Impl {
public:
    AdapterManager adapters;
    ComPtr<ID3D11Device> nativeDevice;
    ComPtr<ID3D11DeviceContext> deviceContext;
    ComPtr<ID3D11InfoQueue> infoQueue;
    D3D_DRIVER_TYPE driverType;
    D3D_FEATURE_LEVEL featureLevel;

public:
    Impl();

private:
    void BuildDevice();
};
//-----------------------------------------------------------------------
GraphicsDeviceDirect3D11::Impl::Impl()
    : driverType(D3D_DRIVER_TYPE_NULL)
    , featureLevel(D3D_FEATURE_LEVEL_11_0)
{
    adapters.EnumAdapters();
    BuildDevice();

    infoQueue = BuildInfoQueue(nativeDevice.Get());
}
//-----------------------------------------------------------------------
void GraphicsDeviceDirect3D11::Impl::BuildDevice()
{
    POMDOG_ASSERT(!nativeDevice);
    POMDOG_ASSERT(!deviceContext);

    UINT createDeviceFlags = 0;
#if defined(DEBUG) && !defined(NDEBUG)
    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
    // NOTE: supported Direct2D1
    //createDeviceFlags |= D3D11_CREATE_DEVICE_BGRA_SUPPORT;

    constexpr std::array<D3D_DRIVER_TYPE, 3> driverTypes = {
        D3D_DRIVER_TYPE_HARDWARE,
        D3D_DRIVER_TYPE_WARP,
        D3D_DRIVER_TYPE_REFERENCE,
    };

    constexpr std::array<D3D_FEATURE_LEVEL, 6> featureLevels = {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_9_3,
        D3D_FEATURE_LEVEL_9_2,
        D3D_FEATURE_LEVEL_9_1,
    };

    HRESULT hr = S_OK;

    auto adapter = adapters.ActiveAdapter();
    for (auto & type: driverTypes)
    {
        driverType = type;
        hr = D3D11CreateDevice(adapter
            , (nullptr != adapter ? D3D_DRIVER_TYPE_UNKNOWN : driverType)
            , nullptr<commit_msg>Add D3D_FEATURE_LEVEL_11_1 to feature levels<commit_after>// Copyright (c) 2013-2015 mogemimi.
// Distributed under the MIT license. See LICENSE.md file for details.

#include "GraphicsDeviceDirect3D11.hpp"
#include "BufferDirect3D11.hpp"
#include "EffectReflectionDirect3D11.hpp"
#include "PipelineStateDirect3D11.hpp"
#include "RenderTarget2DDirect3D11.hpp"
#include "SamplerStateDirect3D11.hpp"
#include "Texture2DDirect3D11.hpp"
#include "../RenderSystem/ShaderBytecode.hpp"
#include "../RenderSystem/ShaderCompileOptions.hpp"
#include "Pomdog/Graphics/BufferUsage.hpp"
#include "Pomdog/Graphics/ShaderLanguage.hpp"
#include "Pomdog/Logging/Log.hpp"
#include "Pomdog/Utility/StringFormat.hpp"
#include "Pomdog/Utility/Assert.hpp"
#include "Pomdog/Utility/Exception.hpp"
#include <array>

namespace Pomdog {
namespace Detail {
namespace RenderSystem {
namespace Direct3D11 {
namespace {

using Microsoft::WRL::ComPtr;

class AdapterManager final {
private:
    std::vector<ComPtr<IDXGIAdapter1>> adapters;
    ComPtr<IDXGIAdapter1> activeAdapter;

public:
    void EnumAdapters();
    void Clear();

    IDXGIAdapter1* ActiveAdapter() const
    {
        POMDOG_ASSERT(activeAdapter);
        return activeAdapter.Get();
    }

    ComPtr<IDXGIFactory1> GetFactory()
    {
        ComPtr<IDXGIFactory1> dxgiFactory;

        POMDOG_ASSERT(activeAdapter);
        HRESULT hr = activeAdapter->GetParent(__uuidof(IDXGIFactory1), &dxgiFactory);
        if (FAILED(hr))
        {
            ///@todo throw exception

            // FUS RO DAH!
            Log::Internal("Failed to get DXGIFactory1");
        }

        return std::move(dxgiFactory);
    }
};
//-----------------------------------------------------------------------
void AdapterManager::EnumAdapters()
{
    Microsoft::WRL::ComPtr<IDXGIFactory1> dxgiFactory;
    HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(dxgiFactory.GetAddressOf()));

    if (FAILED(hr))
    {
        // error
        ///@todo throw exception
        Log::Internal("Failed to create DXGIFactory1.");
        return;
    }

    UINT i = 0;
    Microsoft::WRL::ComPtr<IDXGIAdapter1> newAdapter;
    while ((hr = dxgiFactory->EnumAdapters1(i, &newAdapter)) != DXGI_ERROR_NOT_FOUND)
    {
        if (FAILED(hr))
        {
            // error
            ///@todo throw exception
            Log::Internal("Failed to enumerate adapters.");
            break;
        }

        adapters.push_back(newAdapter);
        newAdapter.Reset();
        ++i;
    }

    if (adapters.empty())
    {
        // error
        ///@todo throw exception
        return;
    }

    POMDOG_ASSERT(!adapters.empty());
    activeAdapter = adapters.front();
}
//-----------------------------------------------------------------------
void AdapterManager::Clear()
{
    activeAdapter.Reset();

    for (auto & adapter : adapters) {
        adapter.Reset();
    }
    adapters.clear();
}
//-----------------------------------------------------------------------
static ID3D11InfoQueue* BuildInfoQueue(ID3D11Device* nativeDevice)
{
    POMDOG_ASSERT(nativeDevice);

    ID3D11InfoQueue* infoQueue = nullptr;
    HRESULT hr = nativeDevice->QueryInterface(__uuidof(ID3D11InfoQueue), reinterpret_cast<void**>(&infoQueue));

    POMDOG_ASSERT(SUCCEEDED(hr));

    if (FAILED(hr)) {
        // error
        ///@todo throw exception
    }

    if (!infoQueue) {
        return nullptr;
    }

    infoQueue->ClearRetrievalFilter();
    infoQueue->ClearStorageFilter();

    D3D11_INFO_QUEUE_FILTER filter;
    ZeroMemory(&filter, sizeof(filter));

    std::array<D3D11_MESSAGE_SEVERITY, 4> severityList = {
        D3D11_MESSAGE_SEVERITY_CORRUPTION,
        D3D11_MESSAGE_SEVERITY_ERROR,
        D3D11_MESSAGE_SEVERITY_WARNING,
        D3D11_MESSAGE_SEVERITY_INFO,
    };

    filter.DenyList.pSeverityList = severityList.data();
    filter.DenyList.NumSeverities = severityList.size();

    infoQueue->AddStorageFilterEntries(&filter);
    infoQueue->AddRetrievalFilterEntries(&filter);

    return std::move(infoQueue);
}
//-----------------------------------------------------------------------
static void CheckError(ID3D11InfoQueue* infoQueue)
{
#if defined(DEBUG) && !defined(NDEBUG)
    POMDOG_ASSERT(infoQueue);
#endif

    if (!infoQueue) {
        return;
    }

    const auto storedMessageCount = infoQueue->GetNumStoredMessages();

    std::string message;
    for (UINT64 i = 0; i < storedMessageCount; ++i)
    {
        SIZE_T messageByteLength = 0;
        infoQueue->GetMessage(i, nullptr, &messageByteLength);

        if (messageByteLength <= 0) {
            continue;
        }

        std::vector<D3D11_MESSAGE> messageBuffer(messageByteLength);
        infoQueue->GetMessage(i, messageBuffer.data(), &messageByteLength);
        message += messageBuffer.data()->pDescription;
        message += "\n";
    }

    if (message.empty())
    {
        Log::Internal(message);
    }
}
//-----------------------------------------------------------------------
static D3D11_BIND_FLAG ToBindFlag(BufferBindMode bindMode) noexcept
{
    switch (bindMode) {
    case BufferBindMode::ConstantBuffer: return D3D11_BIND_CONSTANT_BUFFER;
    case BufferBindMode::IndexBuffer: return D3D11_BIND_INDEX_BUFFER;
    case BufferBindMode::VertexBuffer:
        break;
    }
    return D3D11_BIND_VERTEX_BUFFER;
}

} // unnamed namespace
//-----------------------------------------------------------------------
class GraphicsDeviceDirect3D11::Impl {
public:
    AdapterManager adapters;
    ComPtr<ID3D11Device> nativeDevice;
    ComPtr<ID3D11DeviceContext> deviceContext;
    ComPtr<ID3D11InfoQueue> infoQueue;
    D3D_DRIVER_TYPE driverType;
    D3D_FEATURE_LEVEL featureLevel;

public:
    Impl();

private:
    void BuildDevice();
};
//-----------------------------------------------------------------------
GraphicsDeviceDirect3D11::Impl::Impl()
    : driverType(D3D_DRIVER_TYPE_NULL)
    , featureLevel(D3D_FEATURE_LEVEL_11_0)
{
    adapters.EnumAdapters();
    BuildDevice();

    infoQueue = BuildInfoQueue(nativeDevice.Get());
}
//-----------------------------------------------------------------------
void GraphicsDeviceDirect3D11::Impl::BuildDevice()
{
    POMDOG_ASSERT(!nativeDevice);
    POMDOG_ASSERT(!deviceContext);

    UINT createDeviceFlags = 0;
#if defined(DEBUG) && !defined(NDEBUG)
    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
    // NOTE: supported Direct2D1
    //createDeviceFlags |= D3D11_CREATE_DEVICE_BGRA_SUPPORT;

    constexpr std::array<D3D_DRIVER_TYPE, 3> driverTypes = {
        D3D_DRIVER_TYPE_HARDWARE,
        D3D_DRIVER_TYPE_WARP,
        D3D_DRIVER_TYPE_REFERENCE,
    };

    constexpr std::array<D3D_FEATURE_LEVEL, 7> featureLevels = {
        D3D_FEATURE_LEVEL_11_1,
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_9_3,
        D3D_FEATURE_LEVEL_9_2,
        D3D_FEATURE_LEVEL_9_1,
    };

    HRESULT hr = S_OK;

    auto adapter = adapters.ActiveAdapter();
    for (auto & type: driverTypes)
    {
        driverType = type;
        hr = D3D11CreateDevice(adapter
            , (nullptr != adapter ? D3D_DRIVER_TYPE_UNKNOWN : driverType)
            , nullptr
{'fraction_non_alphanumeric': 0.18158496845316507, 'fraction_numerical': 0.023850793870900645, 'mean_word_length': 2.405099150141643, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6342640', 'n_tokens_mistral': 4609, 'n_tokens_neox': 4406, 'n_words': 716}