Merge pull request #5697 from Armada651/quad-buffer
Implement Quad-Buffered stereoscopy support
This commit is contained in:
commit
29cc009706
|
@ -17,7 +17,7 @@ class cInterfaceAGL : public cInterfaceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void Swap() override;
|
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 MakeCurrent() override;
|
||||||
bool ClearCurrent() override;
|
bool ClearCurrent() override;
|
||||||
void Shutdown() override;
|
void Shutdown() override;
|
||||||
|
|
|
@ -51,12 +51,15 @@ void cInterfaceAGL::Swap()
|
||||||
|
|
||||||
// Create rendering window.
|
// Create rendering window.
|
||||||
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
|
// 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,
|
NSOpenGLPixelFormatAttribute attr[] = {
|
||||||
core ? NSOpenGLProfileVersion3_2Core :
|
NSOpenGLPFADoubleBuffer,
|
||||||
NSOpenGLProfileVersionLegacy,
|
NSOpenGLPFAOpenGLProfile,
|
||||||
NSOpenGLPFAAccelerated, 0};
|
core ? NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy,
|
||||||
|
NSOpenGLPFAAccelerated,
|
||||||
|
stereo ? NSOpenGLPFAStereo : static_cast<NSOpenGLPixelFormatAttribute>(0),
|
||||||
|
0};
|
||||||
NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
|
NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
|
||||||
if (fmt == nil)
|
if (fmt == nil)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,7 +13,7 @@ void cInterfaceBGL::Swap()
|
||||||
m_gl->SwapBuffers();
|
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<BWindow*>(window_handle);
|
m_window = static_cast<BWindow*>(window_handle);
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ class cInterfaceBGL final : public cInterfaceBase
|
||||||
public:
|
public:
|
||||||
void Swap() override;
|
void Swap() override;
|
||||||
void* GetFuncAddress(const std::string& name) 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 MakeCurrent() override;
|
||||||
bool ClearCurrent() override;
|
bool ClearCurrent() override;
|
||||||
void Shutdown() override;
|
void Shutdown() override;
|
||||||
|
|
|
@ -111,7 +111,7 @@ void cInterfaceEGL::DetectMode()
|
||||||
|
|
||||||
// Create rendering window.
|
// Create rendering window.
|
||||||
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
|
// 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;
|
EGLint egl_major, egl_minor;
|
||||||
bool supports_core_profile = false;
|
bool supports_core_profile = false;
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
void SwapInterval(int interval) override;
|
void SwapInterval(int interval) override;
|
||||||
void SetMode(GLInterfaceMode mode) override { s_opengl_mode = mode; }
|
void SetMode(GLInterfaceMode mode) override { s_opengl_mode = mode; }
|
||||||
void* GetFuncAddress(const std::string& name) 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 Create(cInterfaceBase* main_context) override;
|
||||||
bool MakeCurrent() override;
|
bool MakeCurrent() override;
|
||||||
bool ClearCurrent() override;
|
bool ClearCurrent() override;
|
||||||
|
|
|
@ -43,7 +43,7 @@ void cInterfaceGLX::Swap()
|
||||||
|
|
||||||
// Create rendering window.
|
// Create rendering window.
|
||||||
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
|
// 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);
|
dpy = XOpenDisplay(nullptr);
|
||||||
int screen = DefaultScreen(dpy);
|
int screen = DefaultScreen(dpy);
|
||||||
|
@ -87,6 +87,8 @@ bool cInterfaceGLX::Create(void* window_handle, bool core)
|
||||||
0,
|
0,
|
||||||
GLX_DOUBLEBUFFER,
|
GLX_DOUBLEBUFFER,
|
||||||
True,
|
True,
|
||||||
|
GLX_STEREO,
|
||||||
|
stereo ? True : False,
|
||||||
None};
|
None};
|
||||||
int fbcount = 0;
|
int fbcount = 0;
|
||||||
GLXFBConfig* fbc = glXChooseFBConfig(dpy, screen, visual_attribs, &fbcount);
|
GLXFBConfig* fbc = glXChooseFBConfig(dpy, screen, visual_attribs, &fbcount);
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
void SwapInterval(int Interval) override;
|
void SwapInterval(int Interval) override;
|
||||||
void Swap() override;
|
void Swap() override;
|
||||||
void* GetFuncAddress(const std::string& name) 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 MakeCurrent() override;
|
||||||
bool ClearCurrent() override;
|
bool ClearCurrent() override;
|
||||||
void Shutdown() override;
|
void Shutdown() override;
|
||||||
|
|
|
@ -200,7 +200,7 @@ bool cInterfaceWGL::PeekMessages()
|
||||||
|
|
||||||
// Create rendering window.
|
// Create rendering window.
|
||||||
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
|
// 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)
|
if (!window_handle)
|
||||||
return false;
|
return false;
|
||||||
|
@ -219,12 +219,14 @@ bool cInterfaceWGL::Create(void* window_handle, bool core)
|
||||||
s_backbuffer_width = twidth;
|
s_backbuffer_width = twidth;
|
||||||
s_backbuffer_height = theight;
|
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
|
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
|
||||||
1, // Version Number
|
1, // Version Number
|
||||||
PFD_DRAW_TO_WINDOW | // Format Must Support Window
|
PFD_DRAW_TO_WINDOW | // Format Must Support Window
|
||||||
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
|
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
|
PFD_TYPE_RGBA, // Request An RGBA Format
|
||||||
32, // Select Our Color Depth
|
32, // Select Our Color Depth
|
||||||
0,
|
0,
|
||||||
|
|
|
@ -14,7 +14,7 @@ public:
|
||||||
void SwapInterval(int interval) override;
|
void SwapInterval(int interval) override;
|
||||||
void Swap() override;
|
void Swap() override;
|
||||||
void* GetFuncAddress(const std::string& name) 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 Create(cInterfaceBase* main_context) override;
|
||||||
bool MakeCurrent() override;
|
bool MakeCurrent() override;
|
||||||
bool ClearCurrent() override;
|
bool ClearCurrent() override;
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
virtual void SetMode(GLInterfaceMode mode) { s_opengl_mode = GLInterfaceMode::MODE_OPENGL; }
|
virtual void SetMode(GLInterfaceMode mode) { s_opengl_mode = GLInterfaceMode::MODE_OPENGL; }
|
||||||
virtual GLInterfaceMode GetMode() { return s_opengl_mode; }
|
virtual GLInterfaceMode GetMode() { return s_opengl_mode; }
|
||||||
virtual void* GetFuncAddress(const std::string& name) { return nullptr; }
|
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 Create(cInterfaceBase* main_context) { return true; }
|
||||||
virtual bool MakeCurrent() { return true; }
|
virtual bool MakeCurrent() { return true; }
|
||||||
virtual bool ClearCurrent() { return true; }
|
virtual bool ClearCurrent() { return true; }
|
||||||
|
|
|
@ -277,8 +277,9 @@ static wxString cache_efb_copies_desc =
|
||||||
static wxString stereo_3d_desc =
|
static wxString stereo_3d_desc =
|
||||||
wxTRANSLATE("Selects the stereoscopic 3D mode. Stereoscopy allows you to get a better feeling "
|
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 "
|
"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 "
|
"used by most 3D TVs.\nAnaglyph is used for Red-Cyan colored glasses.\nHDMI 3D is "
|
||||||
"decreases emulation speed and sometimes causes issues.\n\nIf unsure, select Off.");
|
"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 =
|
static wxString stereo_depth_desc =
|
||||||
wxTRANSLATE("Controls the separation distance between the virtual cameras.\nA higher value "
|
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.");
|
"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);
|
wxALIGN_CENTER_VERTICAL);
|
||||||
|
|
||||||
const wxString stereo_choices[] = {_("Off"), _("Side-by-Side"), _("Top-and-Bottom"),
|
const wxString stereo_choices[] = {_("Off"), _("Side-by-Side"), _("Top-and-Bottom"),
|
||||||
_("Anaglyph"), _("Nvidia 3D Vision")};
|
_("Anaglyph"), _("HDMI 3D"), _("Nvidia 3D Vision")};
|
||||||
wxChoice* stereo_choice =
|
wxChoice* stereo_choice =
|
||||||
CreateChoice(page_enh, Config::GFX_STEREO_MODE, wxGetTranslation(stereo_3d_desc),
|
CreateChoice(page_enh, Config::GFX_STEREO_MODE, wxGetTranslation(stereo_3d_desc),
|
||||||
vconfig.backend_info.bSupports3DVision ? ArraySize(stereo_choices) :
|
vconfig.backend_info.bSupports3DVision ? ArraySize(stereo_choices) :
|
||||||
|
|
|
@ -26,13 +26,7 @@ CREATEDXGIFACTORY PCreateDXGIFactory = nullptr;
|
||||||
HINSTANCE hDXGIDll = nullptr;
|
HINSTANCE hDXGIDll = nullptr;
|
||||||
int dxgi_dll_ref = 0;
|
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;
|
static D3D11CREATEDEVICE PD3D11CreateDevice = nullptr;
|
||||||
D3D11CREATEDEVICEANDSWAPCHAIN PD3D11CreateDeviceAndSwapChain = nullptr;
|
|
||||||
HINSTANCE hD3DDll = nullptr;
|
HINSTANCE hD3DDll = nullptr;
|
||||||
int d3d_dll_ref = 0;
|
int d3d_dll_ref = 0;
|
||||||
|
|
||||||
|
@ -40,7 +34,7 @@ namespace D3D
|
||||||
{
|
{
|
||||||
ID3D11Device* device = nullptr;
|
ID3D11Device* device = nullptr;
|
||||||
ID3D11DeviceContext* context = nullptr;
|
ID3D11DeviceContext* context = nullptr;
|
||||||
static IDXGISwapChain* swapchain = nullptr;
|
static IDXGISwapChain1* swapchain = nullptr;
|
||||||
static ID3D11Debug* debug = nullptr;
|
static ID3D11Debug* debug = nullptr;
|
||||||
D3D_FEATURE_LEVEL featlevel;
|
D3D_FEATURE_LEVEL featlevel;
|
||||||
D3DTexture2D* backbuf = nullptr;
|
D3DTexture2D* backbuf = nullptr;
|
||||||
|
@ -58,6 +52,8 @@ unsigned int xres, yres;
|
||||||
|
|
||||||
bool bFrameInProgress = false;
|
bool bFrameInProgress = false;
|
||||||
|
|
||||||
|
#define NUM_SWAPCHAIN_BUFFERS 2
|
||||||
|
|
||||||
HRESULT LoadDXGI()
|
HRESULT LoadDXGI()
|
||||||
{
|
{
|
||||||
if (dxgi_dll_ref++ > 0)
|
if (dxgi_dll_ref++ > 0)
|
||||||
|
@ -99,12 +95,6 @@ HRESULT LoadD3D()
|
||||||
MessageBoxA(nullptr, "GetProcAddress failed for D3D11CreateDevice!", "Critical error",
|
MessageBoxA(nullptr, "GetProcAddress failed for D3D11CreateDevice!", "Critical error",
|
||||||
MB_OK | MB_ICONERROR);
|
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;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +162,6 @@ void UnloadD3D()
|
||||||
FreeLibrary(hD3DDll);
|
FreeLibrary(hD3DDll);
|
||||||
hD3DDll = nullptr;
|
hD3DDll = nullptr;
|
||||||
PD3D11CreateDevice = nullptr;
|
PD3D11CreateDevice = nullptr;
|
||||||
PD3D11CreateDeviceAndSwapChain = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnloadD3DCompiler()
|
void UnloadD3DCompiler()
|
||||||
|
@ -276,14 +265,13 @@ HRESULT Create(HWND wnd)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
IDXGIFactory* factory;
|
IDXGIFactory2* factory;
|
||||||
IDXGIAdapter* adapter;
|
|
||||||
IDXGIOutput* output;
|
|
||||||
hr = PCreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);
|
hr = PCreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
MessageBox(wnd, _T("Failed to create IDXGIFactory object"), _T("Dolphin Direct3D 11 backend"),
|
MessageBox(wnd, _T("Failed to create IDXGIFactory object"), _T("Dolphin Direct3D 11 backend"),
|
||||||
MB_OK | MB_ICONERROR);
|
MB_OK | MB_ICONERROR);
|
||||||
|
|
||||||
|
IDXGIAdapter* adapter;
|
||||||
hr = factory->EnumAdapters(g_ActiveConfig.iAdapter, &adapter);
|
hr = factory->EnumAdapters(g_ActiveConfig.iAdapter, &adapter);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
|
@ -294,25 +282,6 @@ HRESULT Create(HWND wnd)
|
||||||
MB_OK | MB_ICONERROR);
|
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
|
// get supported AA modes
|
||||||
aa_modes = EnumAAModes(adapter);
|
aa_modes = EnumAAModes(adapter);
|
||||||
|
|
||||||
|
@ -324,45 +293,34 @@ HRESULT Create(HWND wnd)
|
||||||
UpdateActiveConfig();
|
UpdateActiveConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
DXGI_SWAP_CHAIN_DESC swap_chain_desc = {};
|
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.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
swap_chain_desc.OutputWindow = wnd;
|
|
||||||
swap_chain_desc.SampleDesc.Count = 1;
|
swap_chain_desc.SampleDesc.Count = 1;
|
||||||
swap_chain_desc.SampleDesc.Quality = 0;
|
swap_chain_desc.SampleDesc.Quality = 0;
|
||||||
swap_chain_desc.Windowed =
|
swap_chain_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
!SConfig::GetInstance().bFullscreen || g_ActiveConfig.bBorderlessFullscreen;
|
swap_chain_desc.Scaling = DXGI_SCALING_STRETCH;
|
||||||
|
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
||||||
|
swap_chain_desc.Width = xres;
|
||||||
|
swap_chain_desc.Height = yres;
|
||||||
|
|
||||||
DXGI_OUTPUT_DESC out_desc = {};
|
// By always creating a stereo swapchain we can toggle Quad-Buffered stereoscopy
|
||||||
output->GetDesc(&out_desc);
|
// while the game is running.
|
||||||
|
swap_chain_desc.Stereo = TRUE;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
// Creating debug devices can sometimes fail if the user doesn't have the correct
|
// 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.
|
// version of the DirectX SDK. If it does, simply fallback to a non-debug device.
|
||||||
{
|
{
|
||||||
hr = PD3D11CreateDeviceAndSwapChain(
|
hr = PD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
|
||||||
adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
|
D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_DEBUG,
|
||||||
D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_DEBUG, supported_feature_levels,
|
supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS,
|
||||||
NUM_SUPPORTED_FEATURE_LEVELS, D3D11_SDK_VERSION, &swap_chain_desc, &swapchain, &device,
|
D3D11_SDK_VERSION, &device, &featlevel, &context);
|
||||||
&featlevel, &context);
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
hr = factory->CreateSwapChainForHwnd(device, hWnd, &swap_chain_desc, nullptr, nullptr,
|
||||||
|
&swapchain);
|
||||||
|
|
||||||
// Debugbreak on D3D error
|
// Debugbreak on D3D error
|
||||||
if (SUCCEEDED(hr) && SUCCEEDED(device->QueryInterface(__uuidof(ID3D11Debug), (void**)&debug)))
|
if (SUCCEEDED(hr) && SUCCEEDED(device->QueryInterface(__uuidof(ID3D11Debug), (void**)&debug)))
|
||||||
{
|
{
|
||||||
|
@ -386,10 +344,14 @@ HRESULT Create(HWND wnd)
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
hr = PD3D11CreateDeviceAndSwapChain(
|
hr = PD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
|
||||||
adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, D3D11_CREATE_DEVICE_SINGLETHREADED,
|
D3D11_CREATE_DEVICE_SINGLETHREADED, supported_feature_levels,
|
||||||
supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS, D3D11_SDK_VERSION, &swap_chain_desc,
|
NUM_SUPPORTED_FEATURE_LEVELS, D3D11_SDK_VERSION, &device, &featlevel,
|
||||||
&swapchain, &device, &featlevel, &context);
|
&context);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
hr = factory->CreateSwapChainForHwnd(device, hWnd, &swap_chain_desc, nullptr, nullptr,
|
||||||
|
&swapchain);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
|
@ -414,7 +376,6 @@ HRESULT Create(HWND wnd)
|
||||||
|
|
||||||
SetDebugObjectName((ID3D11DeviceChild*)context, "device context");
|
SetDebugObjectName((ID3D11DeviceChild*)context, "device context");
|
||||||
SAFE_RELEASE(factory);
|
SAFE_RELEASE(factory);
|
||||||
SAFE_RELEASE(output);
|
|
||||||
SAFE_RELEASE(adapter);
|
SAFE_RELEASE(adapter);
|
||||||
|
|
||||||
ID3D11Texture2D* buf;
|
ID3D11Texture2D* buf;
|
||||||
|
@ -574,7 +535,7 @@ void Reset()
|
||||||
GetClientRect(hWnd, &client);
|
GetClientRect(hWnd, &client);
|
||||||
xres = client.right - client.left;
|
xres = client.right - client.left;
|
||||||
yres = client.bottom - client.top;
|
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
|
// recreate back buffer texture
|
||||||
ID3D11Texture2D* buf;
|
ID3D11Texture2D* buf;
|
||||||
|
@ -618,8 +579,11 @@ void EndFrame()
|
||||||
|
|
||||||
void Present()
|
void Present()
|
||||||
{
|
{
|
||||||
|
UINT present_flags =
|
||||||
|
g_ActiveConfig.iStereoMode != STEREO_QUADBUFFER ? DXGI_PRESENT_STEREO_TEMPORARY_MONO : 0;
|
||||||
|
|
||||||
// TODO: Is 1 the correct value for vsyncing?
|
// 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)
|
HRESULT SetFullscreenState(bool enable_fullscreen)
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include <d3d11.h>
|
#include <d3d11.h>
|
||||||
#include <d3dcompiler.h>
|
#include <d3dcompiler.h>
|
||||||
#include <dxgi.h>
|
#include <dxgi1_2.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/Common.h"
|
#include "Common/Common.h"
|
||||||
|
|
|
@ -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(),
|
D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)dst.left, (float)dst.top, (float)dst.GetWidth(),
|
||||||
(float)dst.GetHeight());
|
(float)dst.GetHeight());
|
||||||
D3D::context->RSSetViewports(1, &vp);
|
D3D::context->RSSetViewports(1, &vp);
|
||||||
D3D::drawShadedTexQuad(src_texture->GetSRV(), src.AsRECT(), src_width, src_height,
|
|
||||||
(g_Config.iStereoMode == STEREO_ANAGLYPH) ?
|
ID3D11PixelShader* pixelShader = (g_Config.iStereoMode == STEREO_ANAGLYPH) ?
|
||||||
PixelShaderCache::GetAnaglyphProgram() :
|
PixelShaderCache::GetAnaglyphProgram() :
|
||||||
PixelShaderCache::GetColorCopyProgram(false),
|
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::GetSimpleVertexShader(),
|
||||||
VertexShaderCache::GetSimpleInputLayout(), nullptr, Gamma);
|
VertexShaderCache::GetSimpleInputLayout(), geomShader, Gamma);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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, leftRc, src_texture, src_width, src_height, 0);
|
||||||
post_processor->BlitFromTexture(src, rightRc, src_texture, src_width, src_height, 1);
|
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
|
else
|
||||||
{
|
{
|
||||||
post_processor->BlitFromTexture(src, dst, src_texture, src_width, src_height, 0);
|
post_processor->BlitFromTexture(src, dst, src_texture, src_width, src_height, 0);
|
||||||
|
|
|
@ -167,7 +167,7 @@ bool VideoBackend::Initialize(void* window_handle)
|
||||||
|
|
||||||
InitInterface();
|
InitInterface();
|
||||||
GLInterface->SetMode(GLInterfaceMode::MODE_DETECT);
|
GLInterface->SetMode(GLInterfaceMode::MODE_DETECT);
|
||||||
if (!GLInterface->Create(window_handle))
|
if (!GLInterface->Create(window_handle, g_ActiveConfig.iStereoMode == STEREO_QUADBUFFER))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -41,11 +41,14 @@ void VulkanPostProcessing::BlitFromTexture(const TargetRectangle& dst, const Tar
|
||||||
const Texture2D* src_tex, int src_layer,
|
const Texture2D* src_tex, int src_layer,
|
||||||
VkRenderPass render_pass)
|
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 =
|
VkShaderModule fragment_shader =
|
||||||
m_fragment_shader != VK_NULL_HANDLE ? m_fragment_shader : m_default_fragment_shader;
|
m_fragment_shader != VK_NULL_HANDLE ? m_fragment_shader : m_default_fragment_shader;
|
||||||
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), render_pass,
|
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), render_pass,
|
||||||
g_object_cache->GetPassthroughVertexShader(), VK_NULL_HANDLE,
|
g_object_cache->GetPassthroughVertexShader(), geometry_shader,
|
||||||
fragment_shader);
|
fragment_shader);
|
||||||
|
|
||||||
// Source is always bound.
|
// Source is always bound.
|
||||||
|
|
|
@ -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(left_rect, src_rect, src_tex, 0, render_pass);
|
||||||
post_processor->BlitFromTexture(right_rect, src_rect, src_tex, 1, 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
|
else
|
||||||
{
|
{
|
||||||
post_processor->BlitFromTexture(dst_rect, src_rect, src_tex, 0, render_pass);
|
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());
|
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.
|
// Wipe sampler cache if force texture filtering or anisotropy changes.
|
||||||
if (anisotropy_changed || force_texture_filtering_changed)
|
if (anisotropy_changed || force_texture_filtering_changed)
|
||||||
ResetSamplerStates();
|
ResetSamplerStates();
|
||||||
|
|
|
@ -320,6 +320,9 @@ bool SwapChain::CreateSwapChain()
|
||||||
return false;
|
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
|
// Store the old/current swap chain when recreating for resize
|
||||||
VkSwapchainKHR old_swap_chain = m_swap_chain;
|
VkSwapchainKHR old_swap_chain = m_swap_chain;
|
||||||
|
|
||||||
|
@ -333,7 +336,7 @@ bool SwapChain::CreateSwapChain()
|
||||||
m_surface_format.format,
|
m_surface_format.format,
|
||||||
m_surface_format.colorSpace,
|
m_surface_format.colorSpace,
|
||||||
size,
|
size,
|
||||||
1,
|
image_layers,
|
||||||
image_usage,
|
image_usage,
|
||||||
VK_SHARING_MODE_EXCLUSIVE,
|
VK_SHARING_MODE_EXCLUSIVE,
|
||||||
0,
|
0,
|
||||||
|
@ -359,6 +362,7 @@ bool SwapChain::CreateSwapChain()
|
||||||
|
|
||||||
m_width = size.width;
|
m_width = size.width;
|
||||||
m_height = size.height;
|
m_height = size.height;
|
||||||
|
m_layers = image_layers;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,7 +404,7 @@ bool SwapChain::SetupSwapChainImages()
|
||||||
&view,
|
&view,
|
||||||
m_width,
|
m_width,
|
||||||
m_height,
|
m_height,
|
||||||
1};
|
m_layers};
|
||||||
|
|
||||||
res = vkCreateFramebuffer(g_vulkan_context->GetDevice(), &framebuffer_info, nullptr,
|
res = vkCreateFramebuffer(g_vulkan_context->GetDevice(), &framebuffer_info, nullptr,
|
||||||
&image.framebuffer);
|
&image.framebuffer);
|
||||||
|
|
|
@ -32,6 +32,7 @@ public:
|
||||||
VkSurfaceKHR GetSurface() const { return m_surface; }
|
VkSurfaceKHR GetSurface() const { return m_surface; }
|
||||||
VkSurfaceFormatKHR GetSurfaceFormat() const { return m_surface_format; }
|
VkSurfaceFormatKHR GetSurfaceFormat() const { return m_surface_format; }
|
||||||
bool IsVSyncEnabled() const { return m_vsync_enabled; }
|
bool IsVSyncEnabled() const { return m_vsync_enabled; }
|
||||||
|
bool IsStereoEnabled() const { return m_layers == 2; }
|
||||||
VkSwapchainKHR GetSwapChain() const { return m_swap_chain; }
|
VkSwapchainKHR GetSwapChain() const { return m_swap_chain; }
|
||||||
VkRenderPass GetRenderPass() const { return m_render_pass; }
|
VkRenderPass GetRenderPass() const { return m_render_pass; }
|
||||||
u32 GetWidth() const { return m_width; }
|
u32 GetWidth() const { return m_width; }
|
||||||
|
@ -94,6 +95,7 @@ private:
|
||||||
|
|
||||||
u32 m_width = 0;
|
u32 m_width = 0;
|
||||||
u32 m_height = 0;
|
u32 m_height = 0;
|
||||||
|
u32 m_layers = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -606,6 +606,8 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data*
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa),
|
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa),
|
||||||
uid_data->genMode_numtexgens + 2);
|
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)
|
if (uid_data->stereo)
|
||||||
out.Write(",\n in uint layer : SV_RenderTargetArrayIndex\n");
|
out.Write(",\n in uint layer : SV_RenderTargetArrayIndex\n");
|
||||||
out.Write(" ) {\n");
|
out.Write(" ) {\n");
|
||||||
|
|
|
@ -47,6 +47,7 @@ enum StereoMode
|
||||||
STEREO_SBS,
|
STEREO_SBS,
|
||||||
STEREO_TAB,
|
STEREO_TAB,
|
||||||
STEREO_ANAGLYPH,
|
STEREO_ANAGLYPH,
|
||||||
|
STEREO_QUADBUFFER,
|
||||||
STEREO_3DVISION
|
STEREO_3DVISION
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue