From c399e2bc40b3d6e28a8d1b0152d1dceed4c3a119 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 25 Jun 2017 20:57:46 +0200 Subject: [PATCH 1/9] D3DBase: Upgrade to DXGI 1.2. This effectively drops for Vista and Windows 7 without the Platform Update in this backend. --- Source/Core/VideoBackends/D3D/D3DBase.cpp | 97 ++++++----------------- Source/Core/VideoBackends/D3D/D3DBase.h | 2 +- 2 files changed, 27 insertions(+), 72 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 327fece109..489db6a14a 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -26,13 +26,7 @@ CREATEDXGIFACTORY PCreateDXGIFactory = nullptr; HINSTANCE hDXGIDll = nullptr; int dxgi_dll_ref = 0; -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**); static D3D11CREATEDEVICE PD3D11CreateDevice = nullptr; -D3D11CREATEDEVICEANDSWAPCHAIN PD3D11CreateDeviceAndSwapChain = nullptr; HINSTANCE hD3DDll = nullptr; int d3d_dll_ref = 0; @@ -40,7 +34,7 @@ namespace D3D { ID3D11Device* device = nullptr; ID3D11DeviceContext* context = nullptr; -static IDXGISwapChain* swapchain = nullptr; +static IDXGISwapChain1* swapchain = nullptr; static ID3D11Debug* debug = nullptr; D3D_FEATURE_LEVEL featlevel; D3DTexture2D* backbuf = nullptr; @@ -99,12 +93,6 @@ HRESULT LoadD3D() MessageBoxA(nullptr, "GetProcAddress failed for D3D11CreateDevice!", "Critical error", MB_OK | MB_ICONERROR); - PD3D11CreateDeviceAndSwapChain = - (D3D11CREATEDEVICEANDSWAPCHAIN)GetProcAddress(hD3DDll, "D3D11CreateDeviceAndSwapChain"); - if (PD3D11CreateDeviceAndSwapChain == nullptr) - MessageBoxA(nullptr, "GetProcAddress failed for D3D11CreateDeviceAndSwapChain!", - "Critical error", MB_OK | MB_ICONERROR); - return S_OK; } @@ -172,7 +160,6 @@ void UnloadD3D() FreeLibrary(hD3DDll); hD3DDll = nullptr; PD3D11CreateDevice = nullptr; - PD3D11CreateDeviceAndSwapChain = nullptr; } void UnloadD3DCompiler() @@ -276,14 +263,13 @@ HRESULT Create(HWND wnd) return hr; } - IDXGIFactory* factory; - IDXGIAdapter* adapter; - IDXGIOutput* output; + IDXGIFactory2* factory; 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); + IDXGIAdapter* adapter; hr = factory->EnumAdapters(g_ActiveConfig.iAdapter, &adapter); if (FAILED(hr)) { @@ -294,25 +280,6 @@ HRESULT Create(HWND wnd) MB_OK | MB_ICONERROR); } - // TODO: Make this configurable - hr = adapter->EnumOutputs(0, &output); - if (FAILED(hr)) - { - // try using the first one - 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 ") - _T("GPU in an Optimus-equipped system.\n") - _T("Set Dolphin to use the high-performance graphics in Nvidia's drivers ") - _T("instead and leave Dolphin's video adapter set to the Intel GPU."), - _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR); - SAFE_RELEASE(firstadapter); - } - // get supported AA modes aa_modes = EnumAAModes(adapter); @@ -324,45 +291,30 @@ HRESULT Create(HWND wnd) UpdateActiveConfig(); } - DXGI_SWAP_CHAIN_DESC swap_chain_desc = {}; + DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {}; 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; - swap_chain_desc.Windowed = - !SConfig::GetInstance().bFullscreen || g_ActiveConfig.bBorderlessFullscreen; - - DXGI_OUTPUT_DESC out_desc = {}; - output->GetDesc(&out_desc); - - DXGI_MODE_DESC mode_desc = {}; - mode_desc.Width = out_desc.DesktopCoordinates.right - out_desc.DesktopCoordinates.left; - mode_desc.Height = out_desc.DesktopCoordinates.bottom - out_desc.DesktopCoordinates.top; - mode_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - mode_desc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; - hr = output->FindClosestMatchingMode(&mode_desc, &swap_chain_desc.BufferDesc, nullptr); - if (FAILED(hr)) - MessageBox(wnd, _T("Failed to find a supported video mode"), _T("Dolphin Direct3D 11 backend"), - MB_OK | MB_ICONERROR); - - 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; - } + swap_chain_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + swap_chain_desc.Scaling = DXGI_SCALING_STRETCH; + swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + swap_chain_desc.Width = xres; + swap_chain_desc.Height = yres; #if defined(_DEBUG) || defined(DEBUGFAST) // 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. { - hr = PD3D11CreateDeviceAndSwapChain( - adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, - 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); + hr = PD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, + D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_DEBUG, + supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS, + D3D11_SDK_VERSION, &device, &featlevel, &context); + + if (SUCCEEDED(hr)) + hr = factory->CreateSwapChainForHwnd(device, hWnd, &swap_chain_desc, nullptr, nullptr, + &swapchain); + // Debugbreak on D3D error if (SUCCEEDED(hr) && SUCCEEDED(device->QueryInterface(__uuidof(ID3D11Debug), (void**)&debug))) { @@ -386,10 +338,14 @@ HRESULT Create(HWND wnd) if (FAILED(hr)) #endif { - hr = PD3D11CreateDeviceAndSwapChain( - adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, D3D11_CREATE_DEVICE_SINGLETHREADED, - supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS, D3D11_SDK_VERSION, &swap_chain_desc, - &swapchain, &device, &featlevel, &context); + hr = PD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, + D3D11_CREATE_DEVICE_SINGLETHREADED, supported_feature_levels, + NUM_SUPPORTED_FEATURE_LEVELS, D3D11_SDK_VERSION, &device, &featlevel, + &context); + + if (SUCCEEDED(hr)) + hr = factory->CreateSwapChainForHwnd(device, hWnd, &swap_chain_desc, nullptr, nullptr, + &swapchain); } if (FAILED(hr)) @@ -414,7 +370,6 @@ HRESULT Create(HWND wnd) SetDebugObjectName((ID3D11DeviceChild*)context, "device context"); SAFE_RELEASE(factory); - SAFE_RELEASE(output); SAFE_RELEASE(adapter); ID3D11Texture2D* buf; diff --git a/Source/Core/VideoBackends/D3D/D3DBase.h b/Source/Core/VideoBackends/D3D/D3DBase.h index dec8d5206f..288be59a9f 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.h +++ b/Source/Core/VideoBackends/D3D/D3DBase.h @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include "Common/Common.h" From 6863abb31d1cebacf972abfd6e701636ef557ec0 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 26 Jun 2017 11:22:40 +0200 Subject: [PATCH 2/9] D3DBase: Switch to a flip-model swap chain. --- Source/Core/VideoBackends/D3D/D3DBase.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 489db6a14a..95ef31c458 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -52,6 +52,8 @@ unsigned int xres, yres; bool bFrameInProgress = false; +#define NUM_SWAPCHAIN_BUFFERS 2 + HRESULT LoadDXGI() { if (dxgi_dll_ref++ > 0) @@ -292,13 +294,13 @@ HRESULT Create(HWND wnd) } DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {}; - swap_chain_desc.BufferCount = 1; + swap_chain_desc.BufferCount = NUM_SWAPCHAIN_BUFFERS; swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swap_chain_desc.SampleDesc.Count = 1; swap_chain_desc.SampleDesc.Quality = 0; swap_chain_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swap_chain_desc.Scaling = DXGI_SCALING_STRETCH; - swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; swap_chain_desc.Width = xres; swap_chain_desc.Height = yres; @@ -529,7 +531,7 @@ void Reset() GetClientRect(hWnd, &client); xres = client.right - client.left; yres = client.bottom - client.top; - D3D::swapchain->ResizeBuffers(1, xres, yres, DXGI_FORMAT_R8G8B8A8_UNORM, 0); + D3D::swapchain->ResizeBuffers(NUM_SWAPCHAIN_BUFFERS, xres, yres, DXGI_FORMAT_R8G8B8A8_UNORM, 0); // recreate back buffer texture ID3D11Texture2D* buf; From 179602e921583c5c1edbad22583e540077507627 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 25 Jun 2017 21:08:17 +0200 Subject: [PATCH 3/9] D3D: Add quad-buffer stereoscopy support. --- Source/Core/DolphinWX/VideoConfigDiag.cpp | 4 ++-- Source/Core/VideoBackends/D3D/D3DBase.cpp | 1 + Source/Core/VideoBackends/D3D/Render.cpp | 14 +++++++++----- Source/Core/VideoCommon/VideoConfig.h | 1 + 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index 2dc76ae456..ad47030df1 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -622,8 +622,8 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title) szr_stereo->Add(new wxStaticText(page_enh, wxID_ANY, _("Stereoscopic 3D Mode:")), 0, wxALIGN_CENTER_VERTICAL); - const wxString stereo_choices[] = {_("Off"), _("Side-by-Side"), _("Top-and-Bottom"), - _("Anaglyph"), _("Nvidia 3D Vision")}; + const wxString stereo_choices[] = {_("Off"), _("Side-by-Side"), _("Top-and-Bottom"), + _("Anaglyph"), _("Quad-Buffer"), _("Nvidia 3D Vision")}; wxChoice* stereo_choice = CreateChoice(page_enh, Config::GFX_STEREO_MODE, wxGetTranslation(stereo_3d_desc), vconfig.backend_info.bSupports3DVision ? ArraySize(stereo_choices) : diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 95ef31c458..9609297f4b 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -303,6 +303,7 @@ HRESULT Create(HWND wnd) swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; swap_chain_desc.Width = xres; swap_chain_desc.Height = yres; + swap_chain_desc.Stereo = g_ActiveConfig.iStereoMode == STEREO_QUADBUFFER; #if defined(_DEBUG) || defined(DEBUGFAST) // Creating debug devices can sometimes fail if the user doesn't have the correct diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 3fef05973b..027c3611c0 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -1220,12 +1220,16 @@ void Renderer::BlitScreen(TargetRectangle src, TargetRectangle dst, D3DTexture2D D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)dst.left, (float)dst.top, (float)dst.GetWidth(), (float)dst.GetHeight()); D3D::context->RSSetViewports(1, &vp); - D3D::drawShadedTexQuad(src_texture->GetSRV(), src.AsRECT(), src_width, src_height, - (g_Config.iStereoMode == STEREO_ANAGLYPH) ? - PixelShaderCache::GetAnaglyphProgram() : - PixelShaderCache::GetColorCopyProgram(false), + + ID3D11PixelShader* pixelShader = (g_Config.iStereoMode == STEREO_ANAGLYPH) ? + PixelShaderCache::GetAnaglyphProgram() : + PixelShaderCache::GetColorCopyProgram(false); + ID3D11GeometryShader* geomShader = (g_ActiveConfig.iStereoMode == STEREO_QUADBUFFER) ? + GeometryShaderCache::GetCopyGeometryShader() : + nullptr; + D3D::drawShadedTexQuad(src_texture->GetSRV(), src.AsRECT(), src_width, src_height, pixelShader, VertexShaderCache::GetSimpleVertexShader(), - VertexShaderCache::GetSimpleInputLayout(), nullptr, Gamma); + VertexShaderCache::GetSimpleInputLayout(), geomShader, Gamma); } } diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index ef4c33fa43..e706cea1c3 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -47,6 +47,7 @@ enum StereoMode STEREO_SBS, STEREO_TAB, STEREO_ANAGLYPH, + STEREO_QUADBUFFER, STEREO_3DVISION }; From 383645a4b1dfc0d056ac0c4c8a914b0745343cd1 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 26 Jun 2017 11:52:24 +0200 Subject: [PATCH 4/9] VideoConfigDiag: Rename Quad-Buffer to HDMI 3D. This 3D mode is often associated with the HDMI 1.4a standard, so this name is more helpful to users with such a setup. --- Source/Core/DolphinWX/VideoConfigDiag.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index ad47030df1..30e93a6ff4 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -277,8 +277,9 @@ static wxString cache_efb_copies_desc = static wxString stereo_3d_desc = wxTRANSLATE("Selects the stereoscopic 3D mode. Stereoscopy allows you to get a better feeling " "of depth if you have the necessary hardware.\nSide-by-Side and Top-and-Bottom are " - "used by most 3D TVs.\nAnaglyph is used for Red-Cyan colored glasses.\nHeavily " - "decreases emulation speed and sometimes causes issues.\n\nIf unsure, select Off."); + "used by most 3D TVs.\nAnaglyph is used for Red-Cyan colored glasses.\nHDMI 3D is " + "used when your monitor supports 3D display resolutions.\nHeavily decreases " + "emulation speed and sometimes causes issues.\n\nIf unsure, select Off."); static wxString stereo_depth_desc = wxTRANSLATE("Controls the separation distance between the virtual cameras.\nA higher value " "creates a stronger feeling of depth while a lower value is more comfortable."); @@ -623,7 +624,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title) wxALIGN_CENTER_VERTICAL); const wxString stereo_choices[] = {_("Off"), _("Side-by-Side"), _("Top-and-Bottom"), - _("Anaglyph"), _("Quad-Buffer"), _("Nvidia 3D Vision")}; + _("Anaglyph"), _("HDMI 3D"), _("Nvidia 3D Vision")}; wxChoice* stereo_choice = CreateChoice(page_enh, Config::GFX_STEREO_MODE, wxGetTranslation(stereo_3d_desc), vconfig.backend_info.bSupports3DVision ? ArraySize(stereo_choices) : From 2ab068d3f2b252ad1f8dead9771d0396d03efbce Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 26 Jun 2017 11:55:28 +0200 Subject: [PATCH 5/9] D3DBase: Always create a stereo swapchain. --- Source/Core/VideoBackends/D3D/D3DBase.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 9609297f4b..0f9f260bd8 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -303,7 +303,10 @@ HRESULT Create(HWND wnd) swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; swap_chain_desc.Width = xres; swap_chain_desc.Height = yres; - swap_chain_desc.Stereo = g_ActiveConfig.iStereoMode == STEREO_QUADBUFFER; + + // By always creating a stereo swapchain we can toggle Quad-Buffered stereoscopy + // while the game is running. + swap_chain_desc.Stereo = TRUE; #if defined(_DEBUG) || defined(DEBUGFAST) // Creating debug devices can sometimes fail if the user doesn't have the correct From f3508742ac3ef87ab1093ab284e36034f7639a5f Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 26 Jun 2017 12:32:09 +0200 Subject: [PATCH 6/9] OGL: Support Quad-Buffered stereoscopy. --- Source/Core/Common/GL/GLInterface/AGL.h | 2 +- Source/Core/Common/GL/GLInterface/AGL.mm | 13 ++++++++----- Source/Core/Common/GL/GLInterface/BGL.cpp | 2 +- Source/Core/Common/GL/GLInterface/BGL.h | 2 +- Source/Core/Common/GL/GLInterface/EGL.cpp | 2 +- Source/Core/Common/GL/GLInterface/EGL.h | 2 +- Source/Core/Common/GL/GLInterface/GLX.cpp | 4 +++- Source/Core/Common/GL/GLInterface/GLX.h | 2 +- Source/Core/Common/GL/GLInterface/WGL.cpp | 8 +++++--- Source/Core/Common/GL/GLInterface/WGL.h | 2 +- Source/Core/Common/GL/GLInterfaceBase.h | 2 +- Source/Core/VideoBackends/OGL/Render.cpp | 10 ++++++++++ Source/Core/VideoBackends/OGL/main.cpp | 2 +- 13 files changed, 35 insertions(+), 18 deletions(-) diff --git a/Source/Core/Common/GL/GLInterface/AGL.h b/Source/Core/Common/GL/GLInterface/AGL.h index f3c3bd47cf..5f9a138282 100644 --- a/Source/Core/Common/GL/GLInterface/AGL.h +++ b/Source/Core/Common/GL/GLInterface/AGL.h @@ -17,7 +17,7 @@ class cInterfaceAGL : public cInterfaceBase { public: void Swap() override; - bool Create(void* window_handle, bool core) override; + bool Create(void* window_handle, bool stereo, bool core) override; bool MakeCurrent() override; bool ClearCurrent() override; void Shutdown() override; diff --git a/Source/Core/Common/GL/GLInterface/AGL.mm b/Source/Core/Common/GL/GLInterface/AGL.mm index 37fec99440..bdae829cbc 100644 --- a/Source/Core/Common/GL/GLInterface/AGL.mm +++ b/Source/Core/Common/GL/GLInterface/AGL.mm @@ -51,12 +51,15 @@ void cInterfaceAGL::Swap() // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool cInterfaceAGL::Create(void* window_handle, bool core) +bool cInterfaceAGL::Create(void* window_handle, bool stereo, bool core) { - NSOpenGLPixelFormatAttribute attr[] = {NSOpenGLPFADoubleBuffer, NSOpenGLPFAOpenGLProfile, - core ? NSOpenGLProfileVersion3_2Core : - NSOpenGLProfileVersionLegacy, - NSOpenGLPFAAccelerated, 0}; + NSOpenGLPixelFormatAttribute attr[] = { + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAOpenGLProfile, + core ? NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy, + NSOpenGLPFAAccelerated, + stereo ? NSOpenGLPFAStereo : static_cast(0), + 0}; NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr]; if (fmt == nil) { diff --git a/Source/Core/Common/GL/GLInterface/BGL.cpp b/Source/Core/Common/GL/GLInterface/BGL.cpp index 7cc9070a49..ed2670efc5 100644 --- a/Source/Core/Common/GL/GLInterface/BGL.cpp +++ b/Source/Core/Common/GL/GLInterface/BGL.cpp @@ -13,7 +13,7 @@ void cInterfaceBGL::Swap() m_gl->SwapBuffers(); } -bool cInterfaceBGL::Create(void* window_handle, bool core) +bool cInterfaceBGL::Create(void* window_handle, bool stereo, bool core) { m_window = static_cast(window_handle); diff --git a/Source/Core/Common/GL/GLInterface/BGL.h b/Source/Core/Common/GL/GLInterface/BGL.h index aeb678f804..b26e5e3fc8 100644 --- a/Source/Core/Common/GL/GLInterface/BGL.h +++ b/Source/Core/Common/GL/GLInterface/BGL.h @@ -14,7 +14,7 @@ class cInterfaceBGL final : public cInterfaceBase public: void Swap() override; void* GetFuncAddress(const std::string& name) override; - bool Create(void* window_handle, bool core) override; + bool Create(void* window_handle, bool stereo, bool core) override; bool MakeCurrent() override; bool ClearCurrent() override; void Shutdown() override; diff --git a/Source/Core/Common/GL/GLInterface/EGL.cpp b/Source/Core/Common/GL/GLInterface/EGL.cpp index 9deb4f20e7..32cd705d73 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.cpp +++ b/Source/Core/Common/GL/GLInterface/EGL.cpp @@ -111,7 +111,7 @@ void cInterfaceEGL::DetectMode() // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool cInterfaceEGL::Create(void* window_handle, bool core) +bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) { EGLint egl_major, egl_minor; bool supports_core_profile = false; diff --git a/Source/Core/Common/GL/GLInterface/EGL.h b/Source/Core/Common/GL/GLInterface/EGL.h index 2352f9b646..69a351851f 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.h +++ b/Source/Core/Common/GL/GLInterface/EGL.h @@ -38,7 +38,7 @@ public: void SwapInterval(int interval) override; void SetMode(GLInterfaceMode mode) override { s_opengl_mode = mode; } void* GetFuncAddress(const std::string& name) override; - bool Create(void* window_handle, bool core) override; + bool Create(void* window_handle, bool stereo, bool core) override; bool Create(cInterfaceBase* main_context) override; bool MakeCurrent() override; bool ClearCurrent() override; diff --git a/Source/Core/Common/GL/GLInterface/GLX.cpp b/Source/Core/Common/GL/GLInterface/GLX.cpp index d3550c688f..f6fea067ef 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.cpp +++ b/Source/Core/Common/GL/GLInterface/GLX.cpp @@ -43,7 +43,7 @@ void cInterfaceGLX::Swap() // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool cInterfaceGLX::Create(void* window_handle, bool core) +bool cInterfaceGLX::Create(void* window_handle, bool stereo, bool core) { dpy = XOpenDisplay(nullptr); int screen = DefaultScreen(dpy); @@ -87,6 +87,8 @@ bool cInterfaceGLX::Create(void* window_handle, bool core) 0, GLX_DOUBLEBUFFER, True, + GLX_STEREO, + stereo ? True : False, None}; int fbcount = 0; GLXFBConfig* fbc = glXChooseFBConfig(dpy, screen, visual_attribs, &fbcount); diff --git a/Source/Core/Common/GL/GLInterface/GLX.h b/Source/Core/Common/GL/GLInterface/GLX.h index 20feba27e0..ae019ccbf9 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.h +++ b/Source/Core/Common/GL/GLInterface/GLX.h @@ -24,7 +24,7 @@ public: void SwapInterval(int Interval) override; void Swap() override; void* GetFuncAddress(const std::string& name) override; - bool Create(void* window_handle, bool core) override; + bool Create(void* window_handle, bool stereo, bool core) override; bool MakeCurrent() override; bool ClearCurrent() override; void Shutdown() override; diff --git a/Source/Core/Common/GL/GLInterface/WGL.cpp b/Source/Core/Common/GL/GLInterface/WGL.cpp index 3e500f5866..4d4647e838 100644 --- a/Source/Core/Common/GL/GLInterface/WGL.cpp +++ b/Source/Core/Common/GL/GLInterface/WGL.cpp @@ -200,7 +200,7 @@ bool cInterfaceWGL::PeekMessages() // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool cInterfaceWGL::Create(void* window_handle, bool core) +bool cInterfaceWGL::Create(void* window_handle, bool stereo, bool core) { if (!window_handle) return false; @@ -219,12 +219,14 @@ bool cInterfaceWGL::Create(void* window_handle, bool core) s_backbuffer_width = twidth; s_backbuffer_height = theight; - static constexpr PIXELFORMATDESCRIPTOR pfd = { + const DWORD stereo_flag = stereo ? PFD_STEREO : 0; + static const PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor 1, // Version Number PFD_DRAW_TO_WINDOW | // Format Must Support Window PFD_SUPPORT_OPENGL | // Format Must Support OpenGL - PFD_DOUBLEBUFFER, // Must Support Double Buffering + PFD_DOUBLEBUFFER | // Must Support Double Buffering + stereo_flag, // Could Support Quad Buffering PFD_TYPE_RGBA, // Request An RGBA Format 32, // Select Our Color Depth 0, diff --git a/Source/Core/Common/GL/GLInterface/WGL.h b/Source/Core/Common/GL/GLInterface/WGL.h index e6f0ff3c66..efa9655713 100644 --- a/Source/Core/Common/GL/GLInterface/WGL.h +++ b/Source/Core/Common/GL/GLInterface/WGL.h @@ -14,7 +14,7 @@ public: void SwapInterval(int interval) override; void Swap() override; void* GetFuncAddress(const std::string& name) override; - bool Create(void* window_handle, bool core) override; + bool Create(void* window_handle, bool stereo, bool core) override; bool Create(cInterfaceBase* main_context) override; bool MakeCurrent() override; bool ClearCurrent() override; diff --git a/Source/Core/Common/GL/GLInterfaceBase.h b/Source/Core/Common/GL/GLInterfaceBase.h index b19f5698bc..4ffb7f5f53 100644 --- a/Source/Core/Common/GL/GLInterfaceBase.h +++ b/Source/Core/Common/GL/GLInterfaceBase.h @@ -34,7 +34,7 @@ public: virtual void SetMode(GLInterfaceMode mode) { s_opengl_mode = GLInterfaceMode::MODE_OPENGL; } virtual GLInterfaceMode GetMode() { return s_opengl_mode; } virtual void* GetFuncAddress(const std::string& name) { return nullptr; } - virtual bool Create(void* window_handle, bool core = true) { return true; } + virtual bool Create(void* window_handle, bool stereo = false, bool core = true) { return true; } virtual bool Create(cInterfaceBase* main_context) { return true; } virtual bool MakeCurrent() { return true; } virtual bool ClearCurrent() { return true; } diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 494a478501..3282489369 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -1196,6 +1196,16 @@ void Renderer::BlitScreen(TargetRectangle src, TargetRectangle dst, GLuint src_t post_processor->BlitFromTexture(src, leftRc, src_texture, src_width, src_height, 0); post_processor->BlitFromTexture(src, rightRc, src_texture, src_width, src_height, 1); } + else if (g_ActiveConfig.iStereoMode == STEREO_QUADBUFFER) + { + glDrawBuffer(GL_BACK_LEFT); + post_processor->BlitFromTexture(src, dst, src_texture, src_width, src_height, 0); + + glDrawBuffer(GL_BACK_RIGHT); + post_processor->BlitFromTexture(src, dst, src_texture, src_width, src_height, 1); + + glDrawBuffer(GL_BACK); + } else { post_processor->BlitFromTexture(src, dst, src_texture, src_width, src_height, 0); diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index f9bf7c069e..c00782ee70 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -167,7 +167,7 @@ bool VideoBackend::Initialize(void* window_handle) InitInterface(); GLInterface->SetMode(GLInterfaceMode::MODE_DETECT); - if (!GLInterface->Create(window_handle)) + if (!GLInterface->Create(window_handle, g_ActiveConfig.iStereoMode == STEREO_QUADBUFFER)) return false; return true; From 1f2d43c8709e5fab2f8c3c7de81bdf160b5f6363 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 26 Jun 2017 21:08:21 +0200 Subject: [PATCH 7/9] Vulkan: Implement Quad-Buffered stereoscopy support. --- Source/Core/VideoBackends/Vulkan/PostProcessing.cpp | 5 ++++- Source/Core/VideoBackends/Vulkan/Renderer.cpp | 9 +++++++++ Source/Core/VideoBackends/Vulkan/SwapChain.cpp | 8 ++++++-- Source/Core/VideoBackends/Vulkan/SwapChain.h | 2 ++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoBackends/Vulkan/PostProcessing.cpp b/Source/Core/VideoBackends/Vulkan/PostProcessing.cpp index db8da49499..971de51180 100644 --- a/Source/Core/VideoBackends/Vulkan/PostProcessing.cpp +++ b/Source/Core/VideoBackends/Vulkan/PostProcessing.cpp @@ -41,11 +41,14 @@ void VulkanPostProcessing::BlitFromTexture(const TargetRectangle& dst, const Tar const Texture2D* src_tex, int src_layer, VkRenderPass render_pass) { + // If the source layer is negative we simply copy all available layers. + VkShaderModule geometry_shader = + src_layer < 0 ? g_object_cache->GetPassthroughGeometryShader() : VK_NULL_HANDLE; VkShaderModule fragment_shader = m_fragment_shader != VK_NULL_HANDLE ? m_fragment_shader : m_default_fragment_shader; UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(), g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), render_pass, - g_object_cache->GetPassthroughVertexShader(), VK_NULL_HANDLE, + g_object_cache->GetPassthroughVertexShader(), geometry_shader, fragment_shader); // Source is always bound. diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index 4800d99424..9a26df8548 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -949,6 +949,10 @@ void Renderer::BlitScreen(VkRenderPass render_pass, const TargetRectangle& dst_r post_processor->BlitFromTexture(left_rect, src_rect, src_tex, 0, render_pass); post_processor->BlitFromTexture(right_rect, src_rect, src_tex, 1, render_pass); } + else if (g_ActiveConfig.iStereoMode == STEREO_QUADBUFFER) + { + post_processor->BlitFromTexture(dst_rect, src_rect, src_tex, -1, render_pass); + } else { post_processor->BlitFromTexture(dst_rect, src_rect, src_tex, 0, render_pass); @@ -1186,6 +1190,11 @@ void Renderer::CheckForConfigChanges() m_swap_chain->SetVSync(g_ActiveConfig.IsVSync()); } + // For quad-buffered stereo we need to change the layer count, so recreate the swap chain. + if (m_swap_chain && + (g_ActiveConfig.iStereoMode == STEREO_QUADBUFFER) != m_swap_chain->IsStereoEnabled()) + ResizeSwapChain(); + // Wipe sampler cache if force texture filtering or anisotropy changes. if (anisotropy_changed || force_texture_filtering_changed) ResetSamplerStates(); diff --git a/Source/Core/VideoBackends/Vulkan/SwapChain.cpp b/Source/Core/VideoBackends/Vulkan/SwapChain.cpp index d43a0e4499..21009510bb 100644 --- a/Source/Core/VideoBackends/Vulkan/SwapChain.cpp +++ b/Source/Core/VideoBackends/Vulkan/SwapChain.cpp @@ -320,6 +320,9 @@ bool SwapChain::CreateSwapChain() return false; } + // Select the number of image layers for Quad-Buffered stereoscopy + uint32_t image_layers = g_ActiveConfig.iStereoMode == STEREO_QUADBUFFER ? 2 : 1; + // Store the old/current swap chain when recreating for resize VkSwapchainKHR old_swap_chain = m_swap_chain; @@ -333,7 +336,7 @@ bool SwapChain::CreateSwapChain() m_surface_format.format, m_surface_format.colorSpace, size, - 1, + image_layers, image_usage, VK_SHARING_MODE_EXCLUSIVE, 0, @@ -359,6 +362,7 @@ bool SwapChain::CreateSwapChain() m_width = size.width; m_height = size.height; + m_layers = image_layers; return true; } @@ -400,7 +404,7 @@ bool SwapChain::SetupSwapChainImages() &view, m_width, m_height, - 1}; + m_layers}; res = vkCreateFramebuffer(g_vulkan_context->GetDevice(), &framebuffer_info, nullptr, &image.framebuffer); diff --git a/Source/Core/VideoBackends/Vulkan/SwapChain.h b/Source/Core/VideoBackends/Vulkan/SwapChain.h index 0ff480d64c..37c3460796 100644 --- a/Source/Core/VideoBackends/Vulkan/SwapChain.h +++ b/Source/Core/VideoBackends/Vulkan/SwapChain.h @@ -32,6 +32,7 @@ public: VkSurfaceKHR GetSurface() const { return m_surface; } VkSurfaceFormatKHR GetSurfaceFormat() const { return m_surface_format; } bool IsVSyncEnabled() const { return m_vsync_enabled; } + bool IsStereoEnabled() const { return m_layers == 2; } VkSwapchainKHR GetSwapChain() const { return m_swap_chain; } VkRenderPass GetRenderPass() const { return m_render_pass; } u32 GetWidth() const { return m_width; } @@ -94,6 +95,7 @@ private: u32 m_width = 0; u32 m_height = 0; + u32 m_layers = 0; }; } // namespace Vulkan From b48532935326b095b252c0a51571877e73ef3cdb Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 26 Jun 2017 21:47:34 +0200 Subject: [PATCH 8/9] D3DBase: Set the monoscopic flag when we don't use stereoscopy. --- Source/Core/VideoBackends/D3D/D3DBase.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 0f9f260bd8..ad989f4188 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -579,8 +579,11 @@ void EndFrame() void Present() { + UINT present_flags = + g_ActiveConfig.iStereoMode != STEREO_QUADBUFFER ? DXGI_PRESENT_STEREO_TEMPORARY_MONO : 0; + // TODO: Is 1 the correct value for vsyncing? - swapchain->Present((UINT)g_ActiveConfig.IsVSync(), 0); + swapchain->Present((UINT)g_ActiveConfig.IsVSync(), present_flags); } HRESULT SetFullscreenState(bool enable_fullscreen) From 8476d0271d56ef2d49657d31d97d42395585ad3b Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 26 Jun 2017 21:48:52 +0200 Subject: [PATCH 9/9] PixelShaderGen: Add missing inputs. This fixes a linkage warning in D3D because of mismatched inputs. --- Source/Core/VideoCommon/PixelShaderGen.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index 335c180b30..cec2c5183d 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -606,6 +606,8 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data* GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa), uid_data->genMode_numtexgens + 2); } + out.Write(",\n in float clipDist0 : SV_ClipDistance0\n"); + out.Write(",\n in float clipDist1 : SV_ClipDistance1\n"); if (uid_data->stereo) out.Write(",\n in uint layer : SV_RenderTargetArrayIndex\n"); out.Write(" ) {\n");