1 // Copyright (C) 2003 Dolphin Project.
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0.
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official SVN repository and contact information can be found at
16 // http://code.google.com/p/dolphin-emu/
19 #include "D3DTexture.h"
20 #include "D3DShader.h"
21 #include "D3Dcompiler.h"
22 #include "VideoConfig.h"
24 #include "XFStructs.h"
25 #include "StringUtil.h"
32 HINSTANCE hD3DXDll
= NULL
;
33 D3DX11COMPILEFROMMEMORYTYPE PD3DX11CompileFromMemory
= NULL
;
34 D3DX11FILTERTEXTURETYPE PD3DX11FilterTexture
= NULL
;
35 D3DX11SAVETEXTURETOFILEATYPE PD3DX11SaveTextureToFileA
= NULL
;
36 D3DX11SAVETEXTURETOFILEWTYPE PD3DX11SaveTextureToFileW
= NULL
;
41 ID3D11Device
* device
= NULL
;
42 ID3D11DeviceContext
* context
= NULL
;
43 IDXGISwapChain
* swapchain
= NULL
;
44 D3D_FEATURE_LEVEL featlevel
;
45 D3DTexture2D
* backbuf
= NULL
;
48 bool bgra_textures_supported
;
50 #define NUM_SUPPORTED_FEATURE_LEVELS 3
51 const D3D_FEATURE_LEVEL supported_feature_levels
[NUM_SUPPORTED_FEATURE_LEVELS
] = {
52 D3D_FEATURE_LEVEL_11_0
,
53 D3D_FEATURE_LEVEL_10_1
,
54 D3D_FEATURE_LEVEL_10_0
57 unsigned int xres
, yres
;
59 bool bFrameInProgress
= false;
61 HRESULT
Create(HWND wnd
)
67 GetClientRect(hWnd
, &client
);
68 xres
= client
.right
- client
.left
;
69 yres
= client
.bottom
- client
.top
;
71 // try to load D3DX11 first to check whether we have proper runtime support
72 // try to use the dll the plugin was compiled against first - don't bother about debug runtimes
73 hD3DXDll
= LoadLibraryA(StringFromFormat("d3dx11_%d.dll", D3DX11_SDK_VERSION
).c_str());
76 // if that fails, use the dll which should be available in every SDK which officially supports DX11.
77 hD3DXDll
= LoadLibraryA("d3dx11_42.dll");
80 MessageBoxA(NULL
, "Failed to load d3dx11_42.dll, update your DX11 runtime, please", "Critical error", MB_OK
| MB_ICONERROR
);
85 NOTICE_LOG(VIDEO
, "Successfully loaded d3dx11_42.dll. If you're having trouble, try updating your DX runtime first.");
90 NOTICE_LOG(VIDEO
, "Successfully loaded %s.", StringFromFormat("d3dx11_%d.dll", D3DX11_SDK_VERSION
).c_str());
93 PD3DX11CompileFromMemory
= (D3DX11COMPILEFROMMEMORYTYPE
)GetProcAddress(hD3DXDll
, "D3DX11CompileFromMemory");
94 if (PD3DX11CompileFromMemory
== NULL
) MessageBoxA(NULL
, "GetProcAddress failed for D3DX11CompileFromMemory!", "Critical error", MB_OK
| MB_ICONERROR
);
96 PD3DX11FilterTexture
= (D3DX11FILTERTEXTURETYPE
)GetProcAddress(hD3DXDll
, "D3DX11FilterTexture");
97 if (PD3DX11FilterTexture
== NULL
) MessageBoxA(NULL
, "GetProcAddress failed for D3DX11FilterTexture!", "Critical error", MB_OK
| MB_ICONERROR
);
99 PD3DX11SaveTextureToFileA
= (D3DX11SAVETEXTURETOFILEATYPE
)GetProcAddress(hD3DXDll
, "D3DX11SaveTextureToFileA");
100 if (PD3DX11SaveTextureToFileA
== NULL
) MessageBoxA(NULL
, "GetProcAddress failed for D3DX11SaveTextureToFileA!", "Critical error", MB_OK
| MB_ICONERROR
);
102 PD3DX11SaveTextureToFileW
= (D3DX11SAVETEXTURETOFILEWTYPE
)GetProcAddress(hD3DXDll
, "D3DX11SaveTextureToFileW");
103 if (PD3DX11SaveTextureToFileW
== NULL
) MessageBoxA(NULL
, "GetProcAddress failed for D3DX11SaveTextureToFileW!", "Critical error", MB_OK
| MB_ICONERROR
);
105 // D3DX11 is fine, initialize D3D11
106 IDXGIFactory
* factory
;
107 IDXGIAdapter
* adapter
;
109 hr
= CreateDXGIFactory(__uuidof(IDXGIFactory
), (void**)&factory
);
110 if (FAILED(hr
)) MessageBox(wnd
, _T("Failed to create IDXGIFactory object"), _T("Dolphin Direct3D 11 plugin"), MB_OK
| MB_ICONERROR
);
112 hr
= factory
->EnumAdapters(g_ActiveConfig
.iAdapter
, &adapter
);
115 // try using the first one
116 hr
= factory
->EnumAdapters(0, &adapter
);
117 if (FAILED(hr
)) MessageBox(wnd
, _T("Failed to enumerate adapters"), _T("Dolphin Direct3D 11 plugin"), MB_OK
| MB_ICONERROR
);
120 // TODO: Make this configurable
121 hr
= adapter
->EnumOutputs(0, &output
);
124 // try using the first one
125 hr
= adapter
->EnumOutputs(0, &output
);
126 if (FAILED(hr
)) MessageBox(wnd
, _T("Failed to enumerate outputs"), _T("Dolphin Direct3D 11 plugin"), MB_OK
| MB_ICONERROR
);
129 // this will need to be changed once multisampling gets implemented
130 DXGI_SWAP_CHAIN_DESC swap_chain_desc
;
131 memset(&swap_chain_desc
, 0, sizeof(swap_chain_desc
));
132 swap_chain_desc
.BufferCount
= 1;
133 swap_chain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
134 swap_chain_desc
.OutputWindow
= wnd
;
135 swap_chain_desc
.SampleDesc
.Count
= 1;
136 swap_chain_desc
.SampleDesc
.Quality
= 0;
137 swap_chain_desc
.Windowed
= TRUE
;
139 DXGI_MODE_DESC mode_desc
;
140 memset(&mode_desc
, 0, sizeof(mode_desc
));
141 mode_desc
.Width
= xres
;
142 mode_desc
.Height
= yres
;
143 mode_desc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
144 mode_desc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
145 hr
= output
->FindClosestMatchingMode(&mode_desc
, &swap_chain_desc
.BufferDesc
, NULL
);
146 if (FAILED(hr
)) MessageBox(wnd
, _T("Failed to find a supported video mode"), _T("Dolphin Direct3D 11 plugin"), MB_OK
| MB_ICONERROR
);
148 // forcing buffer resolution to xres and yres.. TODO: The new video mode might not actually be supported!
149 swap_chain_desc
.BufferDesc
.Width
= xres
;
150 swap_chain_desc
.BufferDesc
.Height
= yres
;
152 #if defined(_DEBUG) || defined(DEBUGFAST)
153 D3D11_CREATE_DEVICE_FLAG device_flags
= (D3D11_CREATE_DEVICE_FLAG
)(D3D11_CREATE_DEVICE_DEBUG
|D3D11_CREATE_DEVICE_SINGLETHREADED
);
155 D3D11_CREATE_DEVICE_FLAG device_flags
= D3D11_CREATE_DEVICE_SINGLETHREADED
;
157 hr
= D3D11CreateDeviceAndSwapChain(adapter
, D3D_DRIVER_TYPE_UNKNOWN
, NULL
, device_flags
,
158 supported_feature_levels
, NUM_SUPPORTED_FEATURE_LEVELS
,
159 D3D11_SDK_VERSION
, &swap_chain_desc
, &swapchain
, &device
,
160 &featlevel
, &context
);
161 if (FAILED(hr
) || !device
|| !context
|| !swapchain
)
163 MessageBox(wnd
, _T("Failed to initialize Direct3D.\nMake sure your video card supports at least D3D 10.0"), _T("Dolphin Direct3D 11 plugin"), MB_OK
| MB_ICONERROR
);
164 SAFE_RELEASE(device
);
165 SAFE_RELEASE(context
);
166 SAFE_RELEASE(swapchain
);
169 SetDebugObjectName((ID3D11DeviceChild
*)context
, "device context");
174 ID3D11Texture2D
* buf
;
175 hr
= swapchain
->GetBuffer(0, IID_ID3D11Texture2D
, (void**)&buf
);
178 MessageBox(wnd
, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 plugin"), MB_OK
| MB_ICONERROR
);
181 swapchain
->Release();
184 backbuf
= new D3DTexture2D(buf
, D3D11_BIND_RENDER_TARGET
);
186 CHECK(backbuf
!=NULL
, "Create back buffer texture");
187 SetDebugObjectName((ID3D11DeviceChild
*)backbuf
->GetTex(), "backbuffer texture");
188 SetDebugObjectName((ID3D11DeviceChild
*)backbuf
->GetRTV(), "backbuffer render target view");
190 context
->OMSetRenderTargets(1, &backbuf
->GetRTV(), NULL
);
192 // BGRA textures are easier to deal with in TextureCache, but might not be supported by the hardware
194 device
->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM
, &format_support
);
195 bgra_textures_supported
= (format_support
& D3D11_FORMAT_SUPPORT_TEXTURE2D
) != 0;
197 gfxstate
= new EmuGfxState
;
198 stateman
= new StateManager
;
205 FreeLibrary(hD3DXDll
);
206 PD3DX11FilterTexture
= NULL
;
207 PD3DX11SaveTextureToFileA
= NULL
;
208 PD3DX11SaveTextureToFileW
= NULL
;
210 // release all bound resources
211 context
->ClearState();
212 SAFE_RELEASE(backbuf
);
213 SAFE_RELEASE(swapchain
);
214 SAFE_DELETE(gfxstate
);
215 SAFE_DELETE(stateman
);
216 context
->Flush(); // immediately destroy device objects
218 SAFE_RELEASE(context
);
219 ULONG references
= device
->Release();
222 ERROR_LOG(VIDEO
, "Unreleased references: %i.", references
);
226 NOTICE_LOG(VIDEO
, "Successfully released all device references!");
231 /* just returning the 4_0 ones here */
232 const char* VertexShaderVersionString() { return "vs_4_0"; }
233 const char* PixelShaderVersionString() { return "ps_4_0"; }
235 D3DTexture2D
* &GetBackBuffer() { return backbuf
; }
236 unsigned int GetBackBufferWidth() { return xres
; }
237 unsigned int GetBackBufferHeight() { return yres
; }
239 bool BGRATexturesSupported() { return bgra_textures_supported
; }
241 // Returns the maximum width/height of a texture. This value only depends upon the feature level in DX11
242 unsigned int GetMaxTextureSize()
246 case D3D_FEATURE_LEVEL_11_0
:
249 case D3D_FEATURE_LEVEL_10_1
:
250 case D3D_FEATURE_LEVEL_10_0
:
253 case D3D_FEATURE_LEVEL_9_3
:
256 case D3D_FEATURE_LEVEL_9_2
:
257 case D3D_FEATURE_LEVEL_9_1
:
264 // release all back buffer references
265 SAFE_RELEASE(backbuf
);
267 // resize swapchain buffers
269 GetClientRect(hWnd
, &client
);
270 xres
= client
.right
- client
.left
;
271 yres
= client
.bottom
- client
.top
;
272 D3D::swapchain
->ResizeBuffers(1, xres
, yres
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0);
274 // recreate back buffer texture
275 ID3D11Texture2D
* buf
;
276 HRESULT hr
= swapchain
->GetBuffer(0, IID_ID3D11Texture2D
, (void**)&buf
);
279 MessageBox(hWnd
, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 plugin"), MB_OK
| MB_ICONERROR
);
282 swapchain
->Release();
285 backbuf
= new D3DTexture2D(buf
, D3D11_BIND_RENDER_TARGET
);
287 CHECK(backbuf
!=NULL
, "Create back buffer texture");
288 SetDebugObjectName((ID3D11DeviceChild
*)backbuf
->GetTex(), "backbuffer texture");
289 SetDebugObjectName((ID3D11DeviceChild
*)backbuf
->GetRTV(), "backbuffer render target view");
294 if (bFrameInProgress
)
296 PanicAlert("BeginFrame called although a frame is already in progress");
299 bFrameInProgress
= true;
300 return (device
!= NULL
);
305 if (!bFrameInProgress
)
307 PanicAlert("EndFrame called although no frame is in progress");
310 bFrameInProgress
= false;
315 // TODO: Is 1 the correct value for vsyncing?
316 swapchain
->Present((UINT
)g_ActiveConfig
.bVSync
, 0);