mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-29 17:19:44 -06:00
Renderer: Handle resize events on-demand instead of polling
We now differentiate between a resize event and surface change/destroyed event, reducing the overhead for resizes in the Vulkan backend. It is also now now safe to change the surface multiple times if the video thread is lagging behind.
This commit is contained in:
@ -37,9 +37,9 @@ namespace D3D
|
||||
ID3D11Device* device = nullptr;
|
||||
ID3D11Device1* device1 = nullptr;
|
||||
ID3D11DeviceContext* context = nullptr;
|
||||
HWND hWnd;
|
||||
IDXGISwapChain1* swapchain = nullptr;
|
||||
|
||||
static IDXGISwapChain1* s_swapchain;
|
||||
static IDXGIFactory2* s_dxgi_factory;
|
||||
static ID3D11Debug* s_debug;
|
||||
static D3D_FEATURE_LEVEL s_featlevel;
|
||||
static D3DTexture2D* s_backbuf;
|
||||
@ -49,9 +49,6 @@ static std::vector<DXGI_SAMPLE_DESC> s_aa_modes; // supported AA modes of the c
|
||||
static bool s_bgra_textures_supported;
|
||||
static bool s_allow_tearing_supported;
|
||||
|
||||
static unsigned int s_xres;
|
||||
static unsigned int s_yres;
|
||||
|
||||
constexpr UINT NUM_SUPPORTED_FEATURE_LEVELS = 3;
|
||||
constexpr D3D_FEATURE_LEVEL supported_feature_levels[NUM_SUPPORTED_FEATURE_LEVELS] = {
|
||||
D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0};
|
||||
@ -247,17 +244,74 @@ static bool SupportsBPTCTextures(ID3D11Device* dev)
|
||||
return (bc7_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;
|
||||
}
|
||||
|
||||
static bool CreateSwapChainTextures()
|
||||
{
|
||||
ID3D11Texture2D* buf;
|
||||
HRESULT hr = swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf);
|
||||
CHECK(SUCCEEDED(hr), "GetBuffer for swap chain failed with HRESULT %08X", hr);
|
||||
if (FAILED(hr))
|
||||
return false;
|
||||
|
||||
s_backbuf = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
|
||||
SAFE_RELEASE(buf);
|
||||
SetDebugObjectName(s_backbuf->GetTex(), "backbuffer texture");
|
||||
SetDebugObjectName(s_backbuf->GetRTV(), "backbuffer render target view");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CreateSwapChain(HWND hWnd)
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {};
|
||||
swap_chain_desc.BufferCount = 2;
|
||||
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_FLIP_DISCARD;
|
||||
swap_chain_desc.Stereo = g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer;
|
||||
|
||||
// This flag is necessary if we want to use a flip-model swapchain without locking the framerate
|
||||
swap_chain_desc.Flags = s_allow_tearing_supported ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
|
||||
|
||||
HRESULT hr = s_dxgi_factory->CreateSwapChainForHwnd(device, hWnd, &swap_chain_desc, nullptr,
|
||||
nullptr, &swapchain);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Flip-model discard swapchains aren't supported on Windows 8, so here we fall back to
|
||||
// a sequential swapchain
|
||||
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
||||
hr = s_dxgi_factory->CreateSwapChainForHwnd(device, hWnd, &swap_chain_desc, nullptr, nullptr,
|
||||
&swapchain);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Flip-model swapchains aren't supported on Windows 7, so here we fall back to a legacy
|
||||
// BitBlt-model swapchain
|
||||
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||
hr = s_dxgi_factory->CreateSwapChainForHwnd(device, hWnd, &swap_chain_desc, nullptr, nullptr,
|
||||
&swapchain);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Failed to create swap chain with HRESULT %08X", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreateSwapChainTextures())
|
||||
{
|
||||
SAFE_RELEASE(swapchain);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
HRESULT Create(HWND wnd)
|
||||
{
|
||||
hWnd = wnd;
|
||||
HRESULT hr;
|
||||
|
||||
RECT client;
|
||||
GetClientRect(hWnd, &client);
|
||||
s_xres = client.right - client.left;
|
||||
s_yres = client.bottom - client.top;
|
||||
|
||||
hr = LoadDXGI();
|
||||
HRESULT hr = LoadDXGI();
|
||||
if (SUCCEEDED(hr))
|
||||
hr = LoadD3D();
|
||||
if (SUCCEEDED(hr))
|
||||
@ -270,18 +324,17 @@ HRESULT Create(HWND wnd)
|
||||
return hr;
|
||||
}
|
||||
|
||||
IDXGIFactory2* factory;
|
||||
hr = PCreateDXGIFactory(__uuidof(IDXGIFactory2), (void**)&factory);
|
||||
hr = PCreateDXGIFactory(__uuidof(IDXGIFactory2), (void**)&s_dxgi_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);
|
||||
hr = s_dxgi_factory->EnumAdapters(g_ActiveConfig.iAdapter, &adapter);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// try using the first one
|
||||
hr = factory->EnumAdapters(0, &adapter);
|
||||
hr = s_dxgi_factory->EnumAdapters(0, &adapter);
|
||||
if (FAILED(hr))
|
||||
MessageBox(wnd, _T("Failed to enumerate adapters"), _T("Dolphin Direct3D 11 backend"),
|
||||
MB_OK | MB_ICONERROR);
|
||||
@ -301,7 +354,7 @@ HRESULT Create(HWND wnd)
|
||||
// Check support for allow tearing, we query the interface for backwards compatibility
|
||||
UINT allow_tearing = FALSE;
|
||||
IDXGIFactory5* factory5;
|
||||
hr = factory->QueryInterface(&factory5);
|
||||
hr = s_dxgi_factory->QueryInterface(&factory5);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allow_tearing,
|
||||
@ -310,21 +363,6 @@ HRESULT Create(HWND wnd)
|
||||
}
|
||||
s_allow_tearing_supported = SUCCEEDED(hr) && allow_tearing;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {};
|
||||
swap_chain_desc.BufferCount = 2;
|
||||
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_FLIP_DISCARD;
|
||||
swap_chain_desc.Width = s_xres;
|
||||
swap_chain_desc.Height = s_yres;
|
||||
swap_chain_desc.Stereo = g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer;
|
||||
|
||||
// This flag is necessary if we want to use a flip-model swapchain without locking the framerate
|
||||
swap_chain_desc.Flags = s_allow_tearing_supported ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
|
||||
|
||||
// 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.
|
||||
if (g_Config.bEnableValidationLayer)
|
||||
@ -360,30 +398,9 @@ HRESULT Create(HWND wnd)
|
||||
D3D11_SDK_VERSION, &device, &s_featlevel, &context);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = factory->CreateSwapChainForHwnd(device, hWnd, &swap_chain_desc, nullptr, nullptr,
|
||||
&s_swapchain);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Flip-model discard swapchains aren't supported on Windows 8, so here we fall back to
|
||||
// a sequential swapchain
|
||||
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
||||
hr = factory->CreateSwapChainForHwnd(device, hWnd, &swap_chain_desc, nullptr, nullptr,
|
||||
&s_swapchain);
|
||||
}
|
||||
SAFE_RELEASE(adapter);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Flip-model swapchains aren't supported on Windows 7, so here we fall back to a legacy
|
||||
// BitBlt-model swapchain
|
||||
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||
hr = factory->CreateSwapChainForHwnd(device, hWnd, &swap_chain_desc, nullptr, nullptr,
|
||||
&s_swapchain);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
if (FAILED(hr) || (wnd && !CreateSwapChain(wnd)))
|
||||
{
|
||||
MessageBox(
|
||||
wnd,
|
||||
@ -391,7 +408,7 @@ HRESULT Create(HWND wnd)
|
||||
_T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);
|
||||
SAFE_RELEASE(device);
|
||||
SAFE_RELEASE(context);
|
||||
SAFE_RELEASE(s_swapchain);
|
||||
SAFE_RELEASE(s_dxgi_factory);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
@ -399,52 +416,23 @@ HRESULT Create(HWND wnd)
|
||||
if (FAILED(hr))
|
||||
WARN_LOG(VIDEO, "Missing Direct3D 11.1 support. Logical operations will not be supported.");
|
||||
|
||||
// prevent DXGI from responding to Alt+Enter, unfortunately DXGI_MWA_NO_ALT_ENTER
|
||||
// does not work so we disable all monitoring of window messages. However this
|
||||
// may make it more difficult for DXGI to handle display mode changes.
|
||||
hr = factory->MakeWindowAssociation(wnd, DXGI_MWA_NO_WINDOW_CHANGES);
|
||||
if (FAILED(hr))
|
||||
MessageBox(wnd, _T("Failed to associate the window"), _T("Dolphin Direct3D 11 backend"),
|
||||
MB_OK | MB_ICONERROR);
|
||||
|
||||
SetDebugObjectName(context, "device context");
|
||||
SAFE_RELEASE(factory);
|
||||
SAFE_RELEASE(adapter);
|
||||
|
||||
if (SConfig::GetInstance().bFullscreen && !g_ActiveConfig.bBorderlessFullscreen)
|
||||
{
|
||||
s_swapchain->SetFullscreenState(true, nullptr);
|
||||
s_swapchain->ResizeBuffers(0, s_xres, s_yres, DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
swap_chain_desc.Flags);
|
||||
}
|
||||
|
||||
ID3D11Texture2D* buf;
|
||||
hr = s_swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
MessageBox(wnd, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 backend"),
|
||||
MB_OK | MB_ICONERROR);
|
||||
SAFE_RELEASE(device);
|
||||
SAFE_RELEASE(context);
|
||||
SAFE_RELEASE(s_swapchain);
|
||||
return E_FAIL;
|
||||
}
|
||||
s_backbuf = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
|
||||
SAFE_RELEASE(buf);
|
||||
CHECK(s_backbuf != nullptr, "Create back buffer texture");
|
||||
SetDebugObjectName(s_backbuf->GetTex(), "backbuffer texture");
|
||||
SetDebugObjectName(s_backbuf->GetRTV(), "backbuffer render target view");
|
||||
|
||||
context->OMSetRenderTargets(1, &s_backbuf->GetRTV(), nullptr);
|
||||
|
||||
// BGRA textures are easier to deal with in TextureCache, but might not be supported by the
|
||||
// hardware
|
||||
// BGRA textures are easier to deal with in TextureCache, but might not be supported
|
||||
UINT format_support;
|
||||
device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &format_support);
|
||||
s_bgra_textures_supported = (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;
|
||||
g_Config.backend_info.bSupportsST3CTextures = SupportsS3TCTextures(device);
|
||||
g_Config.backend_info.bSupportsBPTCTextures = SupportsBPTCTextures(device);
|
||||
|
||||
// prevent DXGI from responding to Alt+Enter, unfortunately DXGI_MWA_NO_ALT_ENTER
|
||||
// does not work so we disable all monitoring of window messages. However this
|
||||
// may make it more difficult for DXGI to handle display mode changes.
|
||||
hr = s_dxgi_factory->MakeWindowAssociation(wnd, DXGI_MWA_NO_WINDOW_CHANGES);
|
||||
if (FAILED(hr))
|
||||
MessageBox(wnd, _T("Failed to associate the window"), _T("Dolphin Direct3D 11 backend"),
|
||||
MB_OK | MB_ICONERROR);
|
||||
|
||||
SetDebugObjectName(context, "device context");
|
||||
|
||||
stateman = new StateManager;
|
||||
return S_OK;
|
||||
}
|
||||
@ -452,12 +440,13 @@ HRESULT Create(HWND wnd)
|
||||
void Close()
|
||||
{
|
||||
// we can't release the swapchain while in fullscreen.
|
||||
s_swapchain->SetFullscreenState(false, nullptr);
|
||||
if (swapchain)
|
||||
swapchain->SetFullscreenState(false, nullptr);
|
||||
|
||||
// release all bound resources
|
||||
context->ClearState();
|
||||
SAFE_RELEASE(s_backbuf);
|
||||
SAFE_RELEASE(s_swapchain);
|
||||
SAFE_RELEASE(swapchain);
|
||||
SAFE_DELETE(stateman);
|
||||
context->Flush(); // immediately destroy device objects
|
||||
|
||||
@ -465,7 +454,6 @@ void Close()
|
||||
SAFE_RELEASE(device1);
|
||||
ULONG references = device->Release();
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (s_debug)
|
||||
{
|
||||
--references; // the debug interface increases the refcount of the device, subtract that.
|
||||
@ -477,7 +465,6 @@ void Close()
|
||||
}
|
||||
SAFE_RELEASE(s_debug)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (references)
|
||||
{
|
||||
@ -524,19 +511,10 @@ const char* PixelShaderVersionString()
|
||||
return "ps_4_0";
|
||||
}
|
||||
|
||||
D3DTexture2D*& GetBackBuffer()
|
||||
D3DTexture2D* GetBackBuffer()
|
||||
{
|
||||
return s_backbuf;
|
||||
}
|
||||
unsigned int GetBackBufferWidth()
|
||||
{
|
||||
return s_xres;
|
||||
}
|
||||
unsigned int GetBackBufferHeight()
|
||||
{
|
||||
return s_yres;
|
||||
}
|
||||
|
||||
bool BGRATexturesSupported()
|
||||
{
|
||||
return s_bgra_textures_supported;
|
||||
@ -572,37 +550,31 @@ u32 GetMaxTextureSize(D3D_FEATURE_LEVEL feature_level)
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
void Reset(HWND new_wnd)
|
||||
{
|
||||
// release all back buffer references
|
||||
SAFE_RELEASE(s_backbuf);
|
||||
|
||||
UINT swap_chain_flags = AllowTearingSupported() ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
|
||||
|
||||
// resize swapchain buffers
|
||||
RECT client;
|
||||
GetClientRect(hWnd, &client);
|
||||
s_xres = client.right - client.left;
|
||||
s_yres = client.bottom - client.top;
|
||||
s_swapchain->ResizeBuffers(0, s_xres, s_yres, DXGI_FORMAT_R8G8B8A8_UNORM, swap_chain_flags);
|
||||
|
||||
// recreate back buffer texture
|
||||
ID3D11Texture2D* buf;
|
||||
HRESULT hr = s_swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf);
|
||||
if (FAILED(hr))
|
||||
if (swapchain)
|
||||
{
|
||||
MessageBox(hWnd, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 backend"),
|
||||
MB_OK | MB_ICONERROR);
|
||||
SAFE_RELEASE(device);
|
||||
SAFE_RELEASE(context);
|
||||
SAFE_RELEASE(s_swapchain);
|
||||
return;
|
||||
if (GetFullscreenState())
|
||||
swapchain->SetFullscreenState(FALSE, nullptr);
|
||||
SAFE_RELEASE(swapchain);
|
||||
}
|
||||
|
||||
if (new_wnd)
|
||||
CreateSwapChain(new_wnd);
|
||||
}
|
||||
|
||||
void ResizeSwapChain()
|
||||
{
|
||||
SAFE_RELEASE(s_backbuf);
|
||||
const UINT swap_chain_flags = AllowTearingSupported() ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
|
||||
swapchain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_R8G8B8A8_UNORM, swap_chain_flags);
|
||||
if (!CreateSwapChainTextures())
|
||||
{
|
||||
PanicAlert("Failed to get swap chain textures");
|
||||
SAFE_RELEASE(swapchain);
|
||||
}
|
||||
s_backbuf = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
|
||||
SAFE_RELEASE(buf);
|
||||
CHECK(s_backbuf != nullptr, "Create back buffer texture");
|
||||
SetDebugObjectName(s_backbuf->GetTex(), "backbuffer texture");
|
||||
SetDebugObjectName(s_backbuf->GetRTV(), "backbuffer render target view");
|
||||
}
|
||||
|
||||
void Present()
|
||||
@ -616,25 +588,24 @@ void Present()
|
||||
if (AllowTearingSupported() && !g_ActiveConfig.IsVSync() && !GetFullscreenState())
|
||||
present_flags |= DXGI_PRESENT_ALLOW_TEARING;
|
||||
|
||||
if (s_swapchain->IsTemporaryMonoSupported() &&
|
||||
g_ActiveConfig.stereo_mode != StereoMode::QuadBuffer)
|
||||
if (swapchain->IsTemporaryMonoSupported() && g_ActiveConfig.stereo_mode != StereoMode::QuadBuffer)
|
||||
{
|
||||
present_flags |= DXGI_PRESENT_STEREO_TEMPORARY_MONO;
|
||||
}
|
||||
|
||||
// TODO: Is 1 the correct value for vsyncing?
|
||||
s_swapchain->Present((UINT)g_ActiveConfig.IsVSync(), present_flags);
|
||||
swapchain->Present(static_cast<UINT>(g_ActiveConfig.IsVSync()), present_flags);
|
||||
}
|
||||
|
||||
HRESULT SetFullscreenState(bool enable_fullscreen)
|
||||
{
|
||||
return s_swapchain->SetFullscreenState(enable_fullscreen, nullptr);
|
||||
return swapchain->SetFullscreenState(enable_fullscreen, nullptr);
|
||||
}
|
||||
|
||||
bool GetFullscreenState()
|
||||
{
|
||||
BOOL state = FALSE;
|
||||
s_swapchain->GetFullscreenState(&state, nullptr);
|
||||
swapchain->GetFullscreenState(&state, nullptr);
|
||||
return !!state;
|
||||
}
|
||||
|
||||
|
@ -59,14 +59,13 @@ void Close();
|
||||
extern ID3D11Device* device;
|
||||
extern ID3D11Device1* device1;
|
||||
extern ID3D11DeviceContext* context;
|
||||
extern HWND hWnd;
|
||||
extern IDXGISwapChain1* swapchain;
|
||||
|
||||
void Reset();
|
||||
void Reset(HWND new_wnd);
|
||||
void ResizeSwapChain();
|
||||
void Present();
|
||||
|
||||
unsigned int GetBackBufferWidth();
|
||||
unsigned int GetBackBufferHeight();
|
||||
D3DTexture2D*& GetBackBuffer();
|
||||
D3DTexture2D* GetBackBuffer();
|
||||
const char* PixelShaderVersionString();
|
||||
const char* GeometryShaderVersionString();
|
||||
const char* VertexShaderVersionString();
|
||||
|
@ -387,9 +387,9 @@ int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dw
|
||||
UINT stride = sizeof(FONT2DVERTEX);
|
||||
UINT bufoffset = 0;
|
||||
|
||||
float scalex = 1 / (float)D3D::GetBackBufferWidth() * 2.f;
|
||||
float scaley = 1 / (float)D3D::GetBackBufferHeight() * 2.f;
|
||||
float sizeratio = size / (float)m_LineHeight;
|
||||
float scalex = 1.0f / g_renderer->GetBackbufferWidth() * 2.f;
|
||||
float scaley = 1.0f / g_renderer->GetBackbufferHeight() * 2.f;
|
||||
float sizeratio = size / m_LineHeight;
|
||||
|
||||
// translate starting positions
|
||||
float sx = x * scalex - 1.f;
|
||||
|
@ -53,12 +53,12 @@ typedef struct _Nv_Stereo_Image_Header
|
||||
|
||||
#define NVSTEREO_IMAGE_SIGNATURE 0x4433564e
|
||||
|
||||
Renderer::Renderer() : ::Renderer(D3D::GetBackBufferWidth(), D3D::GetBackBufferHeight())
|
||||
Renderer::Renderer(int backbuffer_width, int backbuffer_height)
|
||||
: ::Renderer(backbuffer_width, backbuffer_height)
|
||||
{
|
||||
m_last_multisamples = g_ActiveConfig.iMultisamples;
|
||||
m_last_stereo_mode = g_ActiveConfig.stereo_mode != StereoMode::Off;
|
||||
m_last_fullscreen_mode = D3D::GetFullscreenState();
|
||||
|
||||
m_last_fullscreen_state = D3D::GetFullscreenState();
|
||||
g_framebuffer_manager = std::make_unique<FramebufferManager>(m_target_width, m_target_height);
|
||||
SetupDeviceObjects();
|
||||
|
||||
@ -239,25 +239,6 @@ TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
|
||||
return result;
|
||||
}
|
||||
|
||||
// With D3D, we have to resize the backbuffer if the window changed
|
||||
// size.
|
||||
bool Renderer::CheckForResize()
|
||||
{
|
||||
RECT rcWindow;
|
||||
GetClientRect(D3D::hWnd, &rcWindow);
|
||||
int client_width = rcWindow.right - rcWindow.left;
|
||||
int client_height = rcWindow.bottom - rcWindow.top;
|
||||
|
||||
// Sanity check
|
||||
if ((client_width != GetBackbufferWidth() || client_height != GetBackbufferHeight()) &&
|
||||
client_width >= 4 && client_height >= 4)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Renderer::SetScissorRect(const MathUtil::Rectangle<int>& rc)
|
||||
{
|
||||
const RECT rect = {rc.left, rc.top, rc.right, rc.bottom};
|
||||
@ -549,12 +530,13 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
|
||||
ResetAPIState();
|
||||
|
||||
// Prepare to copy the XFBs to our backbuffer
|
||||
CheckForSurfaceChange();
|
||||
CheckForSurfaceResize();
|
||||
UpdateDrawRectangle();
|
||||
|
||||
TargetRectangle targetRc = GetTargetRectangle();
|
||||
|
||||
static constexpr std::array<float, 4> clear_color{{0.f, 0.f, 0.f, 1.f}};
|
||||
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), nullptr);
|
||||
|
||||
constexpr std::array<float, 4> clear_color{{0.f, 0.f, 0.f, 1.f}};
|
||||
D3D::context->ClearRenderTargetView(D3D::GetBackBuffer()->GetRTV(), clear_color.data());
|
||||
|
||||
// activate linear filtering for the buffer copies
|
||||
@ -565,8 +547,8 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
|
||||
xfb_texture->GetConfig().width, xfb_texture->GetConfig().height, Gamma);
|
||||
|
||||
// Reset viewport for drawing text
|
||||
D3D11_VIEWPORT vp =
|
||||
CD3D11_VIEWPORT(0.0f, 0.0f, (float)GetBackbufferWidth(), (float)GetBackbufferHeight());
|
||||
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.0f, 0.0f, static_cast<float>(m_backbuffer_width),
|
||||
static_cast<float>(m_backbuffer_height));
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
|
||||
Renderer::DrawDebugText();
|
||||
@ -580,41 +562,21 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
|
||||
g_texture_cache->OnConfigChanged(g_ActiveConfig);
|
||||
VertexShaderCache::RetreiveAsyncShaders();
|
||||
|
||||
const bool window_resized = CheckForResize();
|
||||
const bool fullscreen = D3D::GetFullscreenState();
|
||||
const bool fs_changed = m_last_fullscreen_mode != fullscreen;
|
||||
|
||||
// Flip/present backbuffer to frontbuffer here
|
||||
D3D::Present();
|
||||
if (D3D::swapchain)
|
||||
D3D::Present();
|
||||
|
||||
// Resize the back buffers NOW to avoid flickering
|
||||
if (CalculateTargetSize() || window_resized || fs_changed ||
|
||||
m_last_multisamples != g_ActiveConfig.iMultisamples ||
|
||||
if (CalculateTargetSize() || m_last_multisamples != g_ActiveConfig.iMultisamples ||
|
||||
m_last_stereo_mode != (g_ActiveConfig.stereo_mode != StereoMode::Off))
|
||||
{
|
||||
m_last_multisamples = g_ActiveConfig.iMultisamples;
|
||||
m_last_fullscreen_mode = fullscreen;
|
||||
PixelShaderCache::InvalidateMSAAShaders();
|
||||
|
||||
if (window_resized || fs_changed)
|
||||
{
|
||||
// TODO: Aren't we still holding a reference to the back buffer right now?
|
||||
D3D::Reset();
|
||||
SAFE_RELEASE(m_screenshot_texture);
|
||||
SAFE_RELEASE(m_3d_vision_texture);
|
||||
m_backbuffer_width = D3D::GetBackBufferWidth();
|
||||
m_backbuffer_height = D3D::GetBackBufferHeight();
|
||||
}
|
||||
|
||||
UpdateDrawRectangle();
|
||||
|
||||
m_last_stereo_mode = g_ActiveConfig.stereo_mode != StereoMode::Off;
|
||||
|
||||
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), nullptr);
|
||||
PixelShaderCache::InvalidateMSAAShaders();
|
||||
UpdateDrawRectangle();
|
||||
|
||||
g_framebuffer_manager.reset();
|
||||
g_framebuffer_manager = std::make_unique<FramebufferManager>(m_target_width, m_target_height);
|
||||
|
||||
D3D::context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(),
|
||||
clear_color.data());
|
||||
D3D::context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(),
|
||||
@ -633,6 +595,54 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
|
||||
FramebufferManager::BindEFBRenderTarget();
|
||||
}
|
||||
|
||||
void Renderer::CheckForSurfaceChange()
|
||||
{
|
||||
if (!m_surface_changed.TestAndClear())
|
||||
return;
|
||||
|
||||
m_surface_handle = m_new_surface_handle;
|
||||
m_new_surface_handle = nullptr;
|
||||
|
||||
SAFE_RELEASE(m_screenshot_texture);
|
||||
SAFE_RELEASE(m_3d_vision_texture);
|
||||
D3D::Reset(reinterpret_cast<HWND>(m_new_surface_handle));
|
||||
UpdateBackbufferSize();
|
||||
}
|
||||
|
||||
void Renderer::CheckForSurfaceResize()
|
||||
{
|
||||
const bool fullscreen_state = D3D::GetFullscreenState();
|
||||
const bool exclusive_fullscreen_changed = fullscreen_state != m_last_fullscreen_state;
|
||||
if (!m_surface_resized.TestAndClear() && !exclusive_fullscreen_changed)
|
||||
return;
|
||||
|
||||
m_backbuffer_width = m_new_backbuffer_width;
|
||||
m_backbuffer_height = m_new_backbuffer_height;
|
||||
|
||||
SAFE_RELEASE(m_screenshot_texture);
|
||||
SAFE_RELEASE(m_3d_vision_texture);
|
||||
m_last_fullscreen_state = fullscreen_state;
|
||||
if (D3D::swapchain)
|
||||
D3D::ResizeSwapChain();
|
||||
UpdateBackbufferSize();
|
||||
}
|
||||
|
||||
void Renderer::UpdateBackbufferSize()
|
||||
{
|
||||
if (D3D::swapchain)
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC1 desc = {};
|
||||
D3D::swapchain->GetDesc1(&desc);
|
||||
m_backbuffer_width = std::max(desc.Width, 1u);
|
||||
m_backbuffer_height = std::max(desc.Height, 1u);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_backbuffer_width = 1;
|
||||
m_backbuffer_height = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// ALWAYS call RestoreAPIState for each ResetAPIState call you're doing
|
||||
void Renderer::ResetAPIState()
|
||||
{
|
||||
|
@ -18,7 +18,7 @@ class D3DTexture2D;
|
||||
class Renderer : public ::Renderer
|
||||
{
|
||||
public:
|
||||
Renderer();
|
||||
Renderer(int backbuffer_width, int backbuffer_height);
|
||||
~Renderer() override;
|
||||
|
||||
StateCache& GetStateCache() { return m_state_cache; }
|
||||
@ -63,8 +63,6 @@ public:
|
||||
|
||||
void ReinterpretPixelData(unsigned int convtype) override;
|
||||
|
||||
bool CheckForResize();
|
||||
|
||||
private:
|
||||
struct GXPipelineState
|
||||
{
|
||||
@ -77,6 +75,9 @@ private:
|
||||
void SetupDeviceObjects();
|
||||
void TeardownDeviceObjects();
|
||||
void Create3DVisionTexture(int width, int height);
|
||||
void CheckForSurfaceChange();
|
||||
void CheckForSurfaceResize();
|
||||
void UpdateBackbufferSize();
|
||||
|
||||
void BlitScreen(TargetRectangle src, TargetRectangle dst, D3DTexture2D* src_texture,
|
||||
u32 src_width, u32 src_height, float Gamma);
|
||||
@ -95,6 +96,6 @@ private:
|
||||
|
||||
u32 m_last_multisamples = 1;
|
||||
bool m_last_stereo_mode = false;
|
||||
bool m_last_fullscreen_mode = false;
|
||||
bool m_last_fullscreen_state = false;
|
||||
};
|
||||
}
|
||||
|
@ -137,7 +137,17 @@ bool VideoBackend::Initialize(void* window_handle)
|
||||
return false;
|
||||
}
|
||||
|
||||
g_renderer = std::make_unique<Renderer>();
|
||||
int backbuffer_width = 1, backbuffer_height = 1;
|
||||
if (D3D::swapchain)
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC1 desc = {};
|
||||
D3D::swapchain->GetDesc1(&desc);
|
||||
backbuffer_width = std::max(desc.Width, 1u);
|
||||
backbuffer_height = std::max(desc.Height, 1u);
|
||||
}
|
||||
|
||||
// internal interfaces
|
||||
g_renderer = std::make_unique<Renderer>(backbuffer_width, backbuffer_height);
|
||||
g_texture_cache = std::make_unique<TextureCache>();
|
||||
g_vertex_manager = std::make_unique<VertexManager>();
|
||||
g_perf_query = std::make_unique<PerfQuery>();
|
||||
|
Reference in New Issue
Block a user