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:
|
||||
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;
|
||||
|
|
|
@ -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<NSOpenGLPixelFormatAttribute>(0),
|
||||
0};
|
||||
NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
|
||||
if (fmt == nil)
|
||||
{
|
||||
|
|
|
@ -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<BWindow*>(window_handle);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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.");
|
||||
|
@ -622,8 +623,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"), _("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) :
|
||||
|
|
|
@ -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;
|
||||
|
@ -58,6 +52,8 @@ unsigned int xres, yres;
|
|||
|
||||
bool bFrameInProgress = false;
|
||||
|
||||
#define NUM_SWAPCHAIN_BUFFERS 2
|
||||
|
||||
HRESULT LoadDXGI()
|
||||
{
|
||||
if (dxgi_dll_ref++ > 0)
|
||||
|
@ -99,12 +95,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 +162,6 @@ void UnloadD3D()
|
|||
FreeLibrary(hD3DDll);
|
||||
hD3DDll = nullptr;
|
||||
PD3D11CreateDevice = nullptr;
|
||||
PD3D11CreateDeviceAndSwapChain = nullptr;
|
||||
}
|
||||
|
||||
void UnloadD3DCompiler()
|
||||
|
@ -276,14 +265,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 +282,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 +293,34 @@ HRESULT Create(HWND wnd)
|
|||
UpdateActiveConfig();
|
||||
}
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC swap_chain_desc = {};
|
||||
swap_chain_desc.BufferCount = 1;
|
||||
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {};
|
||||
swap_chain_desc.BufferCount = NUM_SWAPCHAIN_BUFFERS;
|
||||
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;
|
||||
swap_chain_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
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 = {};
|
||||
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;
|
||||
}
|
||||
// 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
|
||||
// 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 +344,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 +376,6 @@ HRESULT Create(HWND wnd)
|
|||
|
||||
SetDebugObjectName((ID3D11DeviceChild*)context, "device context");
|
||||
SAFE_RELEASE(factory);
|
||||
SAFE_RELEASE(output);
|
||||
SAFE_RELEASE(adapter);
|
||||
|
||||
ID3D11Texture2D* buf;
|
||||
|
@ -574,7 +535,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;
|
||||
|
@ -618,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)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include <d3d11.h>
|
||||
#include <d3dcompiler.h>
|
||||
#include <dxgi.h>
|
||||
#include <dxgi1_2.h>
|
||||
#include <vector>
|
||||
|
||||
#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(),
|
||||
(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -47,6 +47,7 @@ enum StereoMode
|
|||
STEREO_SBS,
|
||||
STEREO_TAB,
|
||||
STEREO_ANAGLYPH,
|
||||
STEREO_QUADBUFFER,
|
||||
STEREO_3DVISION
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue