2015-05-24 06:55:12 +02:00
// Copyright 2010 Dolphin Emulator Project
2015-05-18 01:08:10 +02:00
// Licensed under GPLv2+
2013-04-17 23:29:41 -04:00
// Refer to the license.txt file included.
2010-06-13 19:50:06 +00:00
2015-12-12 13:00:08 +01:00
#include <algorithm>
2016-01-17 16:54:31 -05:00
#include "Common/CommonTypes.h"
#include "Common/MsgHandler.h"
2014-02-17 05:18:15 -05:00
#include "Common/StringUtil.h"
2016-01-17 16:54:31 -05:00
#include "Common/Logging/Log.h"
2014-02-17 05:18:15 -05:00
#include "VideoBackends/D3D/D3DBase.h"
2014-06-23 08:11:07 +02:00
#include "VideoBackends/D3D/D3DState.h"
2014-02-17 05:18:15 -05:00
#include "VideoBackends/D3D/D3DTexture.h"
2014-02-19 12:14:09 +01:00
#include "VideoCommon/VideoConfig.h"
2010-06-13 19:50:06 +00:00
2011-01-29 20:16:51 +00:00
namespace DX11
{
2014-03-09 21:14:26 +01:00
HINSTANCE hD3DCompilerDll = nullptr ;
D3DREFLECT PD3DReflect = nullptr ;
pD3DCompile PD3DCompile = nullptr ;
2011-02-26 23:41:02 +00:00
int d3dcompiler_dll_ref = 0 ;
2014-03-09 21:14:26 +01:00
CREATEDXGIFACTORY PCreateDXGIFactory = nullptr ;
HINSTANCE hDXGIDll = nullptr ;
2010-12-29 13:07:00 +00:00
int dxgi_dll_ref = 0 ;
2010-11-21 15:34:04 +00:00
typedef HRESULT ( WINAPI * D3D11CREATEDEVICEANDSWAPCHAIN )( IDXGIAdapter * , D3D_DRIVER_TYPE , HMODULE , UINT , CONST D3D_FEATURE_LEVEL * , UINT , UINT , CONST DXGI_SWAP_CHAIN_DESC * , IDXGISwapChain ** , ID3D11Device ** , D3D_FEATURE_LEVEL * , ID3D11DeviceContext ** );
2014-07-08 22:37:58 +02:00
static D3D11CREATEDEVICE PD3D11CreateDevice = nullptr ;
2014-03-09 21:14:26 +01:00
D3D11CREATEDEVICEANDSWAPCHAIN PD3D11CreateDeviceAndSwapChain = nullptr ;
HINSTANCE hD3DDll = nullptr ;
2010-12-29 13:07:00 +00:00
int d3d_dll_ref = 0 ;
2010-11-21 15:34:04 +00:00
2010-06-13 19:50:06 +00:00
namespace D3D
{
2014-03-09 21:14:26 +01:00
ID3D11Device * device = nullptr ;
ID3D11DeviceContext * context = nullptr ;
2014-07-26 13:00:49 +02:00
static IDXGISwapChain * swapchain = nullptr ;
2015-02-09 13:00:42 +01:00
static ID3D11Debug * debug = nullptr ;
2010-06-13 19:50:06 +00:00
D3D_FEATURE_LEVEL featlevel ;
2014-03-09 21:14:26 +01:00
D3DTexture2D * backbuf = nullptr ;
2010-06-13 19:50:06 +00:00
HWND hWnd ;
2011-06-11 19:37:21 +00:00
std :: vector < DXGI_SAMPLE_DESC > aa_modes ; // supported AA modes of the current adapter
2010-11-23 19:58:02 +00:00
2010-06-19 01:02:43 +00:00
bool bgra_textures_supported ;
2010-06-14 22:38:47 +00:00
#define NUM_SUPPORTED_FEATURE_LEVELS 3
const D3D_FEATURE_LEVEL supported_feature_levels [ NUM_SUPPORTED_FEATURE_LEVELS ] = {
D3D_FEATURE_LEVEL_11_0 ,
D3D_FEATURE_LEVEL_10_1 ,
D3D_FEATURE_LEVEL_10_0
};
2010-06-13 19:50:06 +00:00
unsigned int xres , yres ;
bool bFrameInProgress = false ;
2010-11-23 19:58:02 +00:00
HRESULT LoadDXGI ()
2010-06-13 19:50:06 +00:00
{
2010-12-29 13:07:00 +00:00
if ( dxgi_dll_ref ++ > 0 ) return S_OK ;
2010-11-23 19:58:02 +00:00
if ( hDXGIDll ) return S_OK ;
2010-11-21 15:34:04 +00:00
hDXGIDll = LoadLibraryA ( "dxgi.dll" );
if ( ! hDXGIDll )
{
2014-03-09 21:14:26 +01:00
MessageBoxA ( nullptr , "Failed to load dxgi.dll" , "Critical error" , MB_OK | MB_ICONERROR );
2010-12-29 13:07:00 +00:00
-- dxgi_dll_ref ;
2010-11-21 15:34:04 +00:00
return E_FAIL ;
}
PCreateDXGIFactory = ( CREATEDXGIFACTORY ) GetProcAddress ( hDXGIDll , "CreateDXGIFactory" );
2014-03-09 21:14:26 +01:00
if ( PCreateDXGIFactory == nullptr ) MessageBoxA ( nullptr , "GetProcAddress failed for CreateDXGIFactory!" , "Critical error" , MB_OK | MB_ICONERROR );
2010-06-13 19:50:06 +00:00
2010-11-21 15:34:04 +00:00
return S_OK ;
}
2010-06-13 19:50:06 +00:00
2010-11-23 19:58:02 +00:00
HRESULT LoadD3D ()
2010-11-21 15:34:04 +00:00
{
2011-06-11 19:37:21 +00:00
if ( d3d_dll_ref ++ > 0 ) return S_OK ;
2010-12-29 13:07:00 +00:00
2011-06-11 19:37:21 +00:00
if ( hD3DDll ) return S_OK ;
hD3DDll = LoadLibraryA ( "d3d11.dll" );
if ( ! hD3DDll )
2010-11-23 19:58:02 +00:00
{
2014-03-09 21:14:26 +01:00
MessageBoxA ( nullptr , "Failed to load d3d11.dll" , "Critical error" , MB_OK | MB_ICONERROR );
2010-12-29 13:07:00 +00:00
-- d3d_dll_ref ;
2010-11-23 19:58:02 +00:00
return E_FAIL ;
}
2011-06-11 19:37:21 +00:00
PD3D11CreateDevice = ( D3D11CREATEDEVICE ) GetProcAddress ( hD3DDll , "D3D11CreateDevice" );
2014-03-09 21:14:26 +01:00
if ( PD3D11CreateDevice == nullptr ) MessageBoxA ( nullptr , "GetProcAddress failed for D3D11CreateDevice!" , "Critical error" , MB_OK | MB_ICONERROR );
2010-11-23 19:58:02 +00:00
2011-06-11 19:37:21 +00:00
PD3D11CreateDeviceAndSwapChain = ( D3D11CREATEDEVICEANDSWAPCHAIN ) GetProcAddress ( hD3DDll , "D3D11CreateDeviceAndSwapChain" );
2014-03-09 21:14:26 +01:00
if ( PD3D11CreateDeviceAndSwapChain == nullptr ) MessageBoxA ( nullptr , "GetProcAddress failed for D3D11CreateDeviceAndSwapChain!" , "Critical error" , MB_OK | MB_ICONERROR );
2010-11-23 19:58:02 +00:00
return S_OK ;
2010-11-21 15:34:04 +00:00
}
2011-02-26 23:41:02 +00:00
HRESULT LoadD3DCompiler ()
{
if ( d3dcompiler_dll_ref ++ > 0 ) return S_OK ;
if ( hD3DCompilerDll ) return S_OK ;
// try to load D3DCompiler first to check whether we have proper runtime support
// try to use the dll the backend was compiled against first - don't bother about debug runtimes
hD3DCompilerDll = LoadLibraryA ( D3DCOMPILER_DLL_A );
if ( ! hD3DCompilerDll )
{
// if that fails, use the dll which should be available in every SDK which officially supports DX11.
hD3DCompilerDll = LoadLibraryA ( "D3DCompiler_42.dll" );
if ( ! hD3DCompilerDll )
{
2014-03-09 21:14:26 +01:00
MessageBoxA ( nullptr , "Failed to load D3DCompiler_42.dll, update your DX11 runtime, please" , "Critical error" , MB_OK | MB_ICONERROR );
2011-02-26 23:41:02 +00:00
return E_FAIL ;
}
else
{
NOTICE_LOG ( VIDEO , "Successfully loaded D3DCompiler_42.dll. If you're having trouble, try updating your DX runtime first." );
}
}
PD3DReflect = ( D3DREFLECT ) GetProcAddress ( hD3DCompilerDll , "D3DReflect" );
2014-03-09 21:14:26 +01:00
if ( PD3DReflect == nullptr ) MessageBoxA ( nullptr , "GetProcAddress failed for D3DReflect!" , "Critical error" , MB_OK | MB_ICONERROR );
2013-10-19 02:27:57 -07:00
PD3DCompile = ( pD3DCompile ) GetProcAddress ( hD3DCompilerDll , "D3DCompile" );
2014-03-09 21:14:26 +01:00
if ( PD3DCompile == nullptr ) MessageBoxA ( nullptr , "GetProcAddress failed for D3DCompile!" , "Critical error" , MB_OK | MB_ICONERROR );
2011-02-26 23:41:02 +00:00
return S_OK ;
}
2010-11-23 19:58:02 +00:00
void UnloadDXGI ()
{
2010-12-29 13:07:00 +00:00
if ( ! dxgi_dll_ref ) return ;
if ( -- dxgi_dll_ref != 0 ) return ;
2014-03-11 00:30:55 +13:00
if ( hDXGIDll ) FreeLibrary ( hDXGIDll );
2014-03-09 21:14:26 +01:00
hDXGIDll = nullptr ;
PCreateDXGIFactory = nullptr ;
2010-11-23 19:58:02 +00:00
}
void UnloadD3D ()
{
2011-06-11 19:37:21 +00:00
if ( ! d3d_dll_ref ) return ;
if ( -- d3d_dll_ref != 0 ) return ;
2010-12-29 13:07:00 +00:00
2014-03-11 00:30:55 +13:00
if ( hD3DDll ) FreeLibrary ( hD3DDll );
2014-03-09 21:14:26 +01:00
hD3DDll = nullptr ;
PD3D11CreateDevice = nullptr ;
PD3D11CreateDeviceAndSwapChain = nullptr ;
2010-11-23 19:58:02 +00:00
}
2011-02-26 23:41:02 +00:00
void UnloadD3DCompiler ()
{
if ( ! d3dcompiler_dll_ref ) return ;
if ( -- d3dcompiler_dll_ref != 0 ) return ;
if ( hD3DCompilerDll ) FreeLibrary ( hD3DCompilerDll );
2014-03-09 21:14:26 +01:00
hD3DCompilerDll = nullptr ;
PD3DReflect = nullptr ;
2011-02-26 23:41:02 +00:00
}
2011-03-30 07:17:23 +00:00
std :: vector < DXGI_SAMPLE_DESC > EnumAAModes ( IDXGIAdapter * adapter )
2010-11-23 19:58:02 +00:00
{
2015-03-15 19:28:47 -07:00
std :: vector < DXGI_SAMPLE_DESC > _aa_modes ;
2011-03-30 07:17:23 +00:00
2011-06-11 19:37:21 +00:00
// NOTE: D3D 10.0 doesn't support multisampled resources which are bound as depth buffers AND shader resources.
// Thus, we can't have MSAA with 10.0 level hardware.
2015-03-15 19:28:47 -07:00
ID3D11Device * _device ;
ID3D11DeviceContext * _context ;
2011-06-11 19:37:21 +00:00
D3D_FEATURE_LEVEL feat_level ;
2015-03-15 19:28:47 -07:00
HRESULT hr = PD3D11CreateDevice ( adapter , D3D_DRIVER_TYPE_UNKNOWN , nullptr , D3D11_CREATE_DEVICE_SINGLETHREADED , supported_feature_levels , NUM_SUPPORTED_FEATURE_LEVELS , D3D11_SDK_VERSION , & _device , & feat_level , & _context );
2010-11-28 15:23:51 +00:00
if ( FAILED ( hr ) || feat_level == D3D_FEATURE_LEVEL_10_0 )
{
2010-11-28 17:25:19 +00:00
DXGI_SAMPLE_DESC desc ;
desc . Count = 1 ;
desc . Quality = 0 ;
2015-03-15 19:28:47 -07:00
_aa_modes . push_back ( desc );
SAFE_RELEASE ( _context );
SAFE_RELEASE ( _device );
2010-11-28 15:23:51 +00:00
}
2011-03-30 07:17:23 +00:00
else
2010-11-23 19:58:02 +00:00
{
2011-06-11 19:37:21 +00:00
for ( int samples = 0 ; samples < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT ; ++ samples )
2011-03-30 07:17:23 +00:00
{
UINT quality_levels = 0 ;
2015-03-15 19:28:47 -07:00
_device -> CheckMultisampleQualityLevels ( DXGI_FORMAT_R8G8B8A8_UNORM , samples , & quality_levels );
2015-09-14 18:49:48 -07:00
DXGI_SAMPLE_DESC desc ;
desc . Count = samples ;
desc . Quality = 0 ;
2014-08-30 16:54:18 -04:00
if ( quality_levels > 0 )
2015-09-14 18:49:48 -07:00
_aa_modes . push_back ( desc );
2010-11-23 19:58:02 +00:00
}
2015-03-15 19:28:47 -07:00
_context -> Release ();
_device -> Release ();
2010-11-23 19:58:02 +00:00
}
2015-03-15 19:28:47 -07:00
return _aa_modes ;
2010-11-23 19:58:02 +00:00
}
2013-07-22 14:38:09 +02:00
D3D_FEATURE_LEVEL GetFeatureLevel ( IDXGIAdapter * adapter )
{
D3D_FEATURE_LEVEL feat_level = D3D_FEATURE_LEVEL_9_1 ;
2014-03-09 21:14:26 +01:00
PD3D11CreateDevice ( adapter , D3D_DRIVER_TYPE_UNKNOWN , nullptr , D3D11_CREATE_DEVICE_SINGLETHREADED , supported_feature_levels , NUM_SUPPORTED_FEATURE_LEVELS , D3D11_SDK_VERSION , nullptr , & feat_level , nullptr );
2013-07-22 14:38:09 +02:00
return feat_level ;
}
2010-11-21 15:34:04 +00:00
HRESULT Create ( HWND wnd )
{
hWnd = wnd ;
HRESULT hr ;
RECT client ;
GetClientRect ( hWnd , & client );
xres = client . right - client . left ;
yres = client . bottom - client . top ;
2010-11-23 19:58:02 +00:00
hr = LoadDXGI ();
if ( SUCCEEDED ( hr )) hr = LoadD3D ();
2011-02-26 23:41:02 +00:00
if ( SUCCEEDED ( hr )) hr = LoadD3DCompiler ();
2010-11-23 19:58:02 +00:00
if ( FAILED ( hr ))
{
UnloadDXGI ();
UnloadD3D ();
2011-02-26 23:41:02 +00:00
UnloadD3DCompiler ();
2010-11-23 19:58:02 +00:00
return hr ;
}
2010-11-21 15:34:04 +00:00
2010-06-14 19:20:41 +00:00
IDXGIFactory * factory ;
2011-03-30 07:17:23 +00:00
IDXGIAdapter * adapter ;
2011-06-11 19:37:21 +00:00
IDXGIOutput * output ;
hr = PCreateDXGIFactory ( __uuidof ( IDXGIFactory ), ( void ** ) & factory );
if ( FAILED ( hr )) MessageBox ( wnd , _T ( "Failed to create IDXGIFactory object" ), _T ( "Dolphin Direct3D 11 backend" ), MB_OK | MB_ICONERROR );
2010-06-14 19:20:41 +00:00
hr = factory -> EnumAdapters ( g_ActiveConfig . iAdapter , & adapter );
if ( FAILED ( hr ))
{
// try using the first one
hr = factory -> EnumAdapters ( 0 , & adapter );
2011-06-11 19:37:21 +00:00
if ( FAILED ( hr )) MessageBox ( wnd , _T ( "Failed to enumerate adapters" ), _T ( "Dolphin Direct3D 11 backend" ), MB_OK | MB_ICONERROR );
2010-06-14 19:20:41 +00:00
}
// TODO: Make this configurable
hr = adapter -> EnumOutputs ( 0 , & output );
if ( FAILED ( hr ))
{
// try using the first one
2015-01-17 14:27:11 -08:00
IDXGIAdapter * firstadapter ;
hr = factory -> EnumAdapters ( 0 , & firstadapter );
if ( ! FAILED ( hr ))
hr = firstadapter -> EnumOutputs ( 0 , & output );
if ( FAILED ( hr )) MessageBox ( wnd ,
_T ( "Failed to enumerate outputs! \n " )
_T ( "This usually happens when you've set your video adapter to the Nvidia GPU in an Optimus-equipped system. \n " )
_T ( "Set Dolphin to use the high-performance graphics in Nvidia's drivers instead and leave Dolphin's video adapter set to the Intel GPU." ),
_T ( "Dolphin Direct3D 11 backend" ), MB_OK | MB_ICONERROR );
SAFE_RELEASE ( firstadapter );
2010-06-14 19:20:41 +00:00
}
2010-11-23 19:58:02 +00:00
// get supported AA modes
2011-06-11 19:37:21 +00:00
aa_modes = EnumAAModes ( adapter );
2015-12-12 13:00:08 +01:00
if ( std :: find_if (
aa_modes . begin (),
aa_modes . end (),
[]( const DXGI_SAMPLE_DESC & desc ) { return desc . Count == g_Config . iMultisamples ;}
) == aa_modes . end ())
2010-11-28 15:23:51 +00:00
{
2015-12-12 13:00:08 +01:00
g_Config . iMultisamples = 1 ;
2010-11-28 15:23:51 +00:00
UpdateActiveConfig ();
}
2010-11-23 19:58:02 +00:00
2015-02-12 14:45:05 +01:00
DXGI_SWAP_CHAIN_DESC swap_chain_desc = {};
2010-06-14 19:20:41 +00:00
swap_chain_desc . BufferCount = 1 ;
swap_chain_desc . BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT ;
swap_chain_desc . OutputWindow = wnd ;
swap_chain_desc . SampleDesc . Count = 1 ;
swap_chain_desc . SampleDesc . Quality = 0 ;
2015-01-04 16:33:58 +01:00
swap_chain_desc . Windowed = ! g_Config . bFullscreen ;
2010-06-14 19:20:41 +00:00
2015-02-12 14:45:05 +01:00
DXGI_OUTPUT_DESC out_desc = {};
2014-06-18 15:02:42 +02:00
output -> GetDesc ( & out_desc );
2015-02-12 14:45:05 +01:00
DXGI_MODE_DESC mode_desc = {};
2014-06-18 15:02:42 +02:00
mode_desc . Width = out_desc . DesktopCoordinates . right - out_desc . DesktopCoordinates . left ;
mode_desc . Height = out_desc . DesktopCoordinates . bottom - out_desc . DesktopCoordinates . top ;
2010-06-14 19:20:41 +00:00
mode_desc . Format = DXGI_FORMAT_R8G8B8A8_UNORM ;
mode_desc . Scaling = DXGI_MODE_SCALING_UNSPECIFIED ;
2014-03-09 21:14:26 +01:00
hr = output -> FindClosestMatchingMode ( & mode_desc , & swap_chain_desc . BufferDesc , nullptr );
2011-06-11 19:37:21 +00:00
if ( FAILED ( hr )) MessageBox ( wnd , _T ( "Failed to find a supported video mode" ), _T ( "Dolphin Direct3D 11 backend" ), MB_OK | MB_ICONERROR );
2010-06-14 21:31:23 +00:00
2014-07-11 15:26:38 +02:00
if ( swap_chain_desc . Windowed )
{
// forcing buffer resolution to xres and yres..
// this is not a problem as long as we're in windowed mode
swap_chain_desc . BufferDesc . Width = xres ;
swap_chain_desc . BufferDesc . Height = yres ;
}
2010-06-13 19:50:06 +00:00
2013-08-15 10:07:52 -04:00
#if defined(_DEBUG) || defined(DEBUGFAST)
2013-08-15 10:19:14 -04:00
// Creating debug devices can sometimes fail if the user doesn't have the correct
// version of the DirectX SDK. If it does, simply fallback to a non-debug device.
{
2014-03-09 21:14:26 +01:00
hr = PD3D11CreateDeviceAndSwapChain ( adapter , D3D_DRIVER_TYPE_UNKNOWN , nullptr ,
2013-08-15 10:19:14 -04:00
D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_DEBUG ,
supported_feature_levels , NUM_SUPPORTED_FEATURE_LEVELS ,
D3D11_SDK_VERSION , & swap_chain_desc , & swapchain , & device ,
& featlevel , & context );
2015-02-09 13:00:42 +01:00
// Debugbreak on D3D error
if ( SUCCEEDED ( hr ) && SUCCEEDED ( device -> QueryInterface ( __uuidof ( ID3D11Debug ), ( void ** ) & debug )))
{
ID3D11InfoQueue * infoQueue = nullptr ;
if ( SUCCEEDED ( debug -> QueryInterface ( __uuidof ( ID3D11InfoQueue ), ( void ** ) & infoQueue )))
{
infoQueue -> SetBreakOnSeverity ( D3D11_MESSAGE_SEVERITY_CORRUPTION , true );
infoQueue -> SetBreakOnSeverity ( D3D11_MESSAGE_SEVERITY_ERROR , true );
D3D11_MESSAGE_ID hide [] =
{
D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS
};
2015-02-12 14:45:05 +01:00
D3D11_INFO_QUEUE_FILTER filter = {};
2015-02-09 13:00:42 +01:00
filter . DenyList . NumIDs = sizeof ( hide ) / sizeof ( D3D11_MESSAGE_ID );
filter . DenyList . pIDList = hide ;
infoQueue -> AddStorageFilterEntries ( & filter );
infoQueue -> Release ();
}
}
2013-08-15 10:19:14 -04:00
}
if ( FAILED ( hr ))
2013-08-15 10:07:52 -04:00
#endif
2013-08-15 10:19:14 -04:00
{
2014-03-09 21:14:26 +01:00
hr = PD3D11CreateDeviceAndSwapChain ( adapter , D3D_DRIVER_TYPE_UNKNOWN , nullptr ,
2013-08-15 10:19:14 -04:00
D3D11_CREATE_DEVICE_SINGLETHREADED ,
supported_feature_levels , NUM_SUPPORTED_FEATURE_LEVELS ,
D3D11_SDK_VERSION , & swap_chain_desc , & swapchain , & device ,
& featlevel , & context );
}
if ( FAILED ( hr ))
2010-06-13 19:50:06 +00:00
{
2011-06-11 19:37:21 +00:00
MessageBox ( wnd , _T ( "Failed to initialize Direct3D. \n Make sure your video card supports at least D3D 10.0" ), _T ( "Dolphin Direct3D 11 backend" ), MB_OK | MB_ICONERROR );
SAFE_RELEASE ( device );
SAFE_RELEASE ( context );
SAFE_RELEASE ( swapchain );
2010-06-13 19:50:06 +00:00
return E_FAIL ;
}
2014-06-17 11:15:56 +02:00
2014-07-16 22:13:13 +02:00
// prevent DXGI from responding to Alt+Enter, unfortunately DXGI_MWA_NO_ALT_ENTER
// does not work so we disable all monitoring of window messages. However this
// may make it more difficult for DXGI to handle display mode changes.
2014-06-17 11:15:56 +02:00
hr = factory -> MakeWindowAssociation ( wnd , DXGI_MWA_NO_WINDOW_CHANGES );
if ( FAILED ( hr )) MessageBox ( wnd , _T ( "Failed to associate the window" ), _T ( "Dolphin Direct3D 11 backend" ), MB_OK | MB_ICONERROR );
2011-06-11 19:37:21 +00:00
SetDebugObjectName (( ID3D11DeviceChild * ) context , "device context" );
2010-07-17 11:42:28 +00:00
SAFE_RELEASE ( factory );
SAFE_RELEASE ( output );
SAFE_RELEASE ( adapter );
2010-06-13 19:50:06 +00:00
2011-06-11 19:37:21 +00:00
ID3D11Texture2D * buf ;
hr = swapchain -> GetBuffer ( 0 , IID_ID3D11Texture2D , ( void ** ) & buf );
if ( FAILED ( hr ))
2010-06-13 19:50:06 +00:00
{
2011-02-14 02:18:03 +00:00
MessageBox ( wnd , _T ( "Failed to get swapchain buffer" ), _T ( "Dolphin Direct3D 11 backend" ), MB_OK | MB_ICONERROR );
2011-06-11 19:37:21 +00:00
SAFE_RELEASE ( device );
SAFE_RELEASE ( context );
SAFE_RELEASE ( swapchain );
2010-06-13 19:50:06 +00:00
return E_FAIL ;
}
2011-06-11 19:37:21 +00:00
backbuf = new D3DTexture2D ( buf , D3D11_BIND_RENDER_TARGET );
SAFE_RELEASE ( buf );
2014-03-09 21:14:26 +01:00
CHECK ( backbuf != nullptr , "Create back buffer texture" );
2011-06-11 19:37:21 +00:00
SetDebugObjectName (( ID3D11DeviceChild * ) backbuf -> GetTex (), "backbuffer texture" );
SetDebugObjectName (( ID3D11DeviceChild * ) backbuf -> GetRTV (), "backbuffer render target view" );
2010-06-13 19:50:06 +00:00
2014-03-09 21:14:26 +01:00
context -> OMSetRenderTargets ( 1 , & backbuf -> GetRTV (), nullptr );
2010-06-13 19:50:06 +00:00
2010-06-19 01:02:43 +00:00
// BGRA textures are easier to deal with in TextureCache, but might not be supported by the hardware
UINT format_support ;
device -> CheckFormatSupport ( DXGI_FORMAT_B8G8R8A8_UNORM , & format_support );
bgra_textures_supported = ( format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D ) != 0 ;
2011-06-11 19:37:21 +00:00
stateman = new StateManager ;
2010-06-13 19:50:06 +00:00
return S_OK ;
}
void Close ()
{
2014-06-20 03:45:42 +02:00
// we can't release the swapchain while in fullscreen.
swapchain -> SetFullscreenState ( false , nullptr );
2010-06-13 19:50:06 +00:00
// release all bound resources
2011-06-11 19:37:21 +00:00
context -> ClearState ();
SAFE_RELEASE ( backbuf );
SAFE_RELEASE ( swapchain );
SAFE_DELETE ( stateman );
context -> Flush (); // immediately destroy device objects
2010-06-17 10:42:57 +00:00
2011-06-11 19:37:21 +00:00
SAFE_RELEASE ( context );
ULONG references = device -> Release ();
2015-02-09 13:00:42 +01:00
#if defined(_DEBUG) || defined(DEBUGFAST)
if ( debug )
{
2015-02-12 14:45:05 +01:00
-- references ; // the debug interface increases the refcount of the device, subtract that.
2015-02-09 13:00:42 +01:00
if ( references )
{
// print out alive objects, but only if we actually have pending references
// note this will also print out internal live objects to the debug console
debug -> ReportLiveDeviceObjects ( D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL );
}
SAFE_RELEASE ( debug )
}
#endif
2011-06-11 19:37:21 +00:00
if ( references )
{
ERROR_LOG ( VIDEO , "Unreleased references: %i." , references );
}
else
{
NOTICE_LOG ( VIDEO , "Successfully released all device references!" );
}
2014-03-09 21:14:26 +01:00
device = nullptr ;
2010-11-21 15:34:04 +00:00
// unload DLLs
2010-11-23 19:58:02 +00:00
UnloadD3D ();
2010-11-21 15:34:04 +00:00
UnloadDXGI ();
2010-06-13 19:50:06 +00:00
}
2010-11-27 11:11:05 +00:00
const char * VertexShaderVersionString ()
{
2014-03-11 00:30:55 +13:00
if ( featlevel == D3D_FEATURE_LEVEL_11_0 ) return "vs_5_0" ;
else if ( featlevel == D3D_FEATURE_LEVEL_10_1 ) return "vs_4_1" ;
2010-11-27 11:11:05 +00:00
else /*if(featlevel == D3D_FEATURE_LEVEL_10_0)*/ return "vs_4_0" ;
}
2011-03-14 09:38:29 +00:00
const char * GeometryShaderVersionString ()
{
2014-03-11 00:30:55 +13:00
if ( featlevel == D3D_FEATURE_LEVEL_11_0 ) return "gs_5_0" ;
else if ( featlevel == D3D_FEATURE_LEVEL_10_1 ) return "gs_4_1" ;
2011-03-14 09:38:29 +00:00
else /*if(featlevel == D3D_FEATURE_LEVEL_10_0)*/ return "gs_4_0" ;
}
2010-11-27 11:11:05 +00:00
const char * PixelShaderVersionString ()
{
2014-03-11 00:30:55 +13:00
if ( featlevel == D3D_FEATURE_LEVEL_11_0 ) return "ps_5_0" ;
else if ( featlevel == D3D_FEATURE_LEVEL_10_1 ) return "ps_4_1" ;
2010-11-27 11:11:05 +00:00
else /*if(featlevel == D3D_FEATURE_LEVEL_10_0)*/ return "ps_4_0" ;
}
2010-06-13 19:50:06 +00:00
2011-06-11 19:37:21 +00:00
D3DTexture2D * & GetBackBuffer () { return backbuf ; }
2010-06-13 19:50:06 +00:00
unsigned int GetBackBufferWidth () { return xres ; }
unsigned int GetBackBufferHeight () { return yres ; }
2010-06-19 01:02:43 +00:00
bool BGRATexturesSupported () { return bgra_textures_supported ; }
2010-07-11 16:26:46 +00:00
// Returns the maximum width/height of a texture. This value only depends upon the feature level in DX11
unsigned int GetMaxTextureSize ()
{
switch ( featlevel )
{
case D3D_FEATURE_LEVEL_11_0 :
2010-11-27 11:11:05 +00:00
return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION ;
2010-07-11 16:26:46 +00:00
case D3D_FEATURE_LEVEL_10_1 :
case D3D_FEATURE_LEVEL_10_0 :
2010-11-27 11:11:05 +00:00
return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION ;
2010-07-11 16:26:46 +00:00
case D3D_FEATURE_LEVEL_9_3 :
return 4096 ;
case D3D_FEATURE_LEVEL_9_2 :
case D3D_FEATURE_LEVEL_9_1 :
return 2048 ;
2010-07-17 11:42:28 +00:00
default :
return 0 ;
2010-07-11 16:26:46 +00:00
}
}
2010-06-13 19:50:06 +00:00
void Reset ()
{
2010-06-17 10:42:57 +00:00
// release all back buffer references
2011-06-11 19:37:21 +00:00
SAFE_RELEASE ( backbuf );
2010-06-17 10:42:57 +00:00
// resize swapchain buffers
RECT client ;
GetClientRect ( hWnd , & client );
xres = client . right - client . left ;
yres = client . bottom - client . top ;
2011-06-11 19:37:21 +00:00
D3D :: swapchain -> ResizeBuffers ( 1 , xres , yres , DXGI_FORMAT_R8G8B8A8_UNORM , 0 );
2010-06-17 10:42:57 +00:00
// recreate back buffer texture
2011-06-11 19:37:21 +00:00
ID3D11Texture2D * buf ;
HRESULT hr = swapchain -> GetBuffer ( 0 , IID_ID3D11Texture2D , ( void ** ) & buf );
if ( FAILED ( hr ))
2010-06-17 10:42:57 +00:00
{
2011-02-14 02:18:03 +00:00
MessageBox ( hWnd , _T ( "Failed to get swapchain buffer" ), _T ( "Dolphin Direct3D 11 backend" ), MB_OK | MB_ICONERROR );
2011-06-11 19:37:21 +00:00
SAFE_RELEASE ( device );
SAFE_RELEASE ( context );
SAFE_RELEASE ( swapchain );
2010-06-17 10:42:57 +00:00
return ;
}
2011-06-11 19:37:21 +00:00
backbuf = new D3DTexture2D ( buf , D3D11_BIND_RENDER_TARGET );
SAFE_RELEASE ( buf );
2014-03-09 21:14:26 +01:00
CHECK ( backbuf != nullptr , "Create back buffer texture" );
2011-06-11 19:37:21 +00:00
SetDebugObjectName (( ID3D11DeviceChild * ) backbuf -> GetTex (), "backbuffer texture" );
SetDebugObjectName (( ID3D11DeviceChild * ) backbuf -> GetRTV (), "backbuffer render target view" );
2010-06-13 19:50:06 +00:00
}
bool BeginFrame ()
{
if ( bFrameInProgress )
{
PanicAlert ( "BeginFrame called although a frame is already in progress" );
return false ;
}
bFrameInProgress = true ;
2014-03-09 21:14:26 +01:00
return ( device != nullptr );
2010-06-13 19:50:06 +00:00
}
void EndFrame ()
{
if ( ! bFrameInProgress )
{
PanicAlert ( "EndFrame called although no frame is in progress" );
return ;
}
bFrameInProgress = false ;
}
void Present ()
{
// TODO: Is 1 the correct value for vsyncing?
2013-03-18 20:41:45 -04:00
swapchain -> Present (( UINT ) g_ActiveConfig . IsVSync (), 0 );
2010-06-13 19:50:06 +00:00
}
2014-07-26 13:00:49 +02:00
HRESULT SetFullscreenState ( bool enable_fullscreen )
{
return swapchain -> SetFullscreenState ( enable_fullscreen , nullptr );
}
HRESULT GetFullscreenState ( bool * fullscreen_state )
{
if ( fullscreen_state == nullptr )
{
return E_POINTER ;
}
BOOL state ;
HRESULT hr = swapchain -> GetFullscreenState ( & state , nullptr );
* fullscreen_state = !! state ;
return hr ;
}
2011-01-29 20:16:51 +00:00
} // namespace D3D
2011-02-14 02:18:03 +00:00
} // namespace DX11