CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Windows/GPU/D3D11Context.cpp
Views: 1401
#include "ppsspp_config.h"12#include "Common/CommonWindows.h"3#include <d3d11.h>4#include <WinError.h>56#include "Common/Log.h"7#include "Common/System/Display.h"8#include "Common/Data/Encoding/Utf8.h"9#include "Common/Data/Text/I18n.h"1011#include "Core/Config.h"12#include "Core/ConfigValues.h"13#include "Core/System.h"14#include "Windows/GPU/D3D11Context.h"15#include "Windows/W32Util/Misc.h"16#include "Common/GPU/thin3d.h"17#include "Common/GPU/thin3d_create.h"18#include "Common/GPU/D3D11/D3D11Loader.h"1920#ifdef __MINGW32__21#undef __uuidof22#define __uuidof(type) IID_##type23#endif2425#ifndef DXGI_ERROR_NOT_FOUND26#define _FACDXGI 0x87a27#define MAKE_DXGI_HRESULT(code) MAKE_HRESULT(1, _FACDXGI, code)28#define DXGI_ERROR_NOT_FOUND MAKE_DXGI_HRESULT(2)29#endif3031#if PPSSPP_PLATFORM(UWP)32#error This file should not be compiled for UWP.33#endif3435HRESULT D3D11Context::CreateTheDevice(IDXGIAdapter *adapter) {36bool windowed = true;37// D3D11 has no need for display rotation.38g_display.rotation = DisplayRotation::ROTATE_0;39g_display.rot_matrix.setIdentity();40#if defined(_DEBUG) && !PPSSPP_ARCH(ARM) && !PPSSPP_ARCH(ARM64)41UINT createDeviceFlags = D3D11_CREATE_DEVICE_DEBUG;42#else43UINT createDeviceFlags = 0;44#endif4546static const D3D_FEATURE_LEVEL featureLevels[] = {47D3D_FEATURE_LEVEL_12_1,48D3D_FEATURE_LEVEL_12_0,49D3D_FEATURE_LEVEL_11_1,50D3D_FEATURE_LEVEL_11_0,51D3D_FEATURE_LEVEL_10_1,52D3D_FEATURE_LEVEL_10_0,53};54const UINT numFeatureLevels = ARRAYSIZE(featureLevels);5556HRESULT hr = S_OK;57D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_UNKNOWN;58hr = ptr_D3D11CreateDevice(adapter, driverType, nullptr, createDeviceFlags, (D3D_FEATURE_LEVEL *)featureLevels, numFeatureLevels,59D3D11_SDK_VERSION, &device_, &featureLevel_, &context_);60if (hr == E_INVALIDARG) {61// DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it62hr = ptr_D3D11CreateDevice(adapter, driverType, nullptr, createDeviceFlags, (D3D_FEATURE_LEVEL *)&featureLevels[3], numFeatureLevels - 3,63D3D11_SDK_VERSION, &device_, &featureLevel_, &context_);64}65return hr;66}6768bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) {69hWnd_ = wnd;70LoadD3D11Error result = LoadD3D11();7172HRESULT hr = E_FAIL;73std::vector<std::string> adapterNames;74std::string chosenAdapterName;75if (result == LoadD3D11Error::SUCCESS) {76std::vector<IDXGIAdapter *> adapters;77int chosenAdapter = 0;78IDXGIFactory* pFactory = nullptr;7980hr = ptr_CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&pFactory);81if (SUCCEEDED(hr)) {82IDXGIAdapter* pAdapter;83for (UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; i++) {84adapters.push_back(pAdapter);85DXGI_ADAPTER_DESC desc;86pAdapter->GetDesc(&desc);87std::string str = ConvertWStringToUTF8(desc.Description);88adapterNames.push_back(str);89if (str == g_Config.sD3D11Device) {90chosenAdapter = i;91}92}93if (!adapters.empty()) {94chosenAdapterName = adapterNames[chosenAdapter];95hr = CreateTheDevice(adapters[chosenAdapter]);96for (int i = 0; i < (int)adapters.size(); i++) {97adapters[i]->Release();98}99} else {100// No adapters found. Trip the error path below.101hr = E_FAIL;102}103pFactory->Release();104}105}106107if (FAILED(hr)) {108const char *defaultError = "Your GPU does not appear to support Direct3D 11.\n\nWould you like to try again using Direct3D 9 instead?";109auto err = GetI18NCategory(I18NCat::ERRORS);110111std::wstring error;112113if (result == LoadD3D11Error::FAIL_NO_COMPILER) {114error = ConvertUTF8ToWString(err->T("D3D11CompilerMissing", "D3DCompiler_47.dll not found. Please install. Or press Yes to try again using Direct3D9 instead."));115} else if (result == LoadD3D11Error::FAIL_NO_D3D11) {116error = ConvertUTF8ToWString(err->T("D3D11Missing", "Your operating system version does not include D3D11. Please run Windows Update.\n\nPress Yes to try again using Direct3D9 instead."));117}118119error = ConvertUTF8ToWString(err->T("D3D11NotSupported", defaultError));120std::wstring title = ConvertUTF8ToWString(err->T("D3D11InitializationError", "Direct3D 11 initialization error"));121bool yes = IDYES == MessageBox(hWnd_, error.c_str(), title.c_str(), MB_ICONERROR | MB_YESNO);122if (yes) {123// Change the config to D3D9 and restart.124g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D9;125g_Config.sFailedGPUBackends.clear();126g_Config.Save("save_d3d9_fallback");127128W32Util::ExitAndRestart();129}130return false;131}132133if (FAILED(device_->QueryInterface(__uuidof (ID3D11Device1), (void **)&device1_))) {134device1_ = nullptr;135}136137if (FAILED(context_->QueryInterface(__uuidof (ID3D11DeviceContext1), (void **)&context1_))) {138context1_ = nullptr;139}140141#ifdef _DEBUG142if (SUCCEEDED(device_->QueryInterface(__uuidof(ID3D11Debug), (void**)&d3dDebug_))) {143if (SUCCEEDED(d3dDebug_->QueryInterface(__uuidof(ID3D11InfoQueue), (void**)&d3dInfoQueue_))) {144d3dInfoQueue_->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true);145d3dInfoQueue_->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true);146d3dInfoQueue_->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING, true);147}148}149#endif150151152int width;153int height;154W32Util::GetWindowRes(hWnd_, &width, &height);155156// Obtain DXGI factory from device (since we used nullptr for pAdapter above)157IDXGIFactory1 *dxgiFactory = nullptr;158IDXGIDevice *dxgiDevice = nullptr;159IDXGIAdapter *adapter = nullptr;160hr = device_->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice));161if (SUCCEEDED(hr)) {162hr = dxgiDevice->GetAdapter(&adapter);163if (SUCCEEDED(hr)) {164hr = adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory));165DXGI_ADAPTER_DESC desc;166adapter->GetDesc(&desc);167adapter->Release();168}169dxgiDevice->Release();170}171172// DirectX 11.0 systems173DXGI_SWAP_CHAIN_DESC sd;174ZeroMemory(&sd, sizeof(sd));175sd.BufferCount = 1;176sd.BufferDesc.Width = width;177sd.BufferDesc.Height = height;178sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;179sd.BufferDesc.RefreshRate.Numerator = 60;180sd.BufferDesc.RefreshRate.Denominator = 1;181sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;182sd.OutputWindow = hWnd_;183sd.SampleDesc.Count = 1;184sd.SampleDesc.Quality = 0;185sd.Windowed = TRUE;186187hr = dxgiFactory->CreateSwapChain(device_, &sd, &swapChain_);188dxgiFactory->MakeWindowAssociation(hWnd_, DXGI_MWA_NO_ALT_ENTER);189dxgiFactory->Release();190191draw_ = Draw::T3DCreateD3D11Context(device_, context_, device1_, context1_, swapChain_, featureLevel_, hWnd_, adapterNames, g_Config.iInflightFrames);192SetGPUBackend(GPUBackend::DIRECT3D11, chosenAdapterName);193bool success = draw_->CreatePresets(); // If we can run D3D11, there's a compiler installed. I think.194_assert_msg_(success, "Failed to compile preset shaders");195196GotBackbuffer();197return true;198}199200void D3D11Context::LostBackbuffer() {201draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, width, height, nullptr);202bbRenderTargetTex_->Release();203bbRenderTargetTex_ = nullptr;204bbRenderTargetView_->Release();205bbRenderTargetView_ = nullptr;206}207208void D3D11Context::GotBackbuffer() {209// Create a render target view210ID3D11Texture2D* pBackBuffer = nullptr;211HRESULT hr = swapChain_->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&bbRenderTargetTex_));212if (FAILED(hr))213return;214215D3D11_TEXTURE2D_DESC bbDesc{};216bbRenderTargetTex_->GetDesc(&bbDesc);217width = bbDesc.Width;218height = bbDesc.Height;219220hr = device_->CreateRenderTargetView(bbRenderTargetTex_, nullptr, &bbRenderTargetView_);221if (FAILED(hr))222return;223draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, width, height, bbRenderTargetView_, bbRenderTargetTex_);224}225226void D3D11Context::Resize() {227LostBackbuffer();228int width;229int height;230W32Util::GetWindowRes(hWnd_, &width, &height);231swapChain_->ResizeBuffers(0, width, height, DXGI_FORMAT_UNKNOWN, 0);232GotBackbuffer();233}234235void D3D11Context::Shutdown() {236LostBackbuffer();237238delete draw_;239draw_ = nullptr;240241swapChain_->Release();242swapChain_ = nullptr;243if (context1_)244context1_->Release();245if (device1_)246device1_->Release();247device1_ = nullptr;248device_->Release();249device_ = nullptr;250251context_->ClearState();252context_->Flush();253context_->Release();254context_ = nullptr;255256#ifdef _DEBUG257if (d3dInfoQueue_) {258d3dInfoQueue_->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, false);259d3dInfoQueue_->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, false);260d3dInfoQueue_->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING, false);261}262if (d3dDebug_) {263d3dDebug_->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL);264d3dDebug_->Release();265d3dDebug_ = nullptr;266}267if (d3dInfoQueue_) {268d3dInfoQueue_->Release();269d3dInfoQueue_ = nullptr;270}271#endif272273hWnd_ = nullptr;274UnloadD3D11();275}276277278