From d36ede020c122ec79fdf9872bf078f83a1b5621e Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Tue, 23 Nov 2010 19:58:02 +0000 Subject: [PATCH] DX11: Add multisampling support. EFB access doesn't work with MSAA enabled, yet. Additionally clean up some stuff, fix a memory leak, ... git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6468 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Core/VideoUICommon/Src/VideoConfigDiag.h | 2 +- .../Plugins/Plugin_VideoDX11/Src/D3DBase.cpp | 121 ++++++++++++++---- Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h | 11 +- .../Plugin_VideoDX11/Src/D3DTexture.cpp | 11 +- .../Plugins/Plugin_VideoDX11/Src/D3DTexture.h | 2 +- .../Src/FramebufferManager.cpp | 63 +++++++-- .../Plugin_VideoDX11/Src/FramebufferManager.h | 6 + .../Plugins/Plugin_VideoDX11/Src/Render.cpp | 15 ++- .../Plugin_VideoDX11/Src/TextureCache.cpp | 2 +- Source/Plugins/Plugin_VideoDX11/Src/main.cpp | 32 ++++- 10 files changed, 212 insertions(+), 53 deletions(-) diff --git a/Source/Core/VideoUICommon/Src/VideoConfigDiag.h b/Source/Core/VideoUICommon/Src/VideoConfigDiag.h index 35e833eb07..5f7dbdd889 100644 --- a/Source/Core/VideoUICommon/Src/VideoConfigDiag.h +++ b/Source/Core/VideoUICommon/Src/VideoConfigDiag.h @@ -51,7 +51,7 @@ public: VideoConfigDiag(wxWindow* parent, const std::string &title, const std::string& ininame); protected: - void Event_Backend(wxCommandEvent &ev) { ev.Skip(); } // TODO + void Event_Backend(wxCommandEvent &ev) { ev.Skip(); } // TODO: Query list of supported AA modes void Event_Adapter(wxCommandEvent &ev) { ev.Skip(); } // TODO void Event_EfbCopy(wxCommandEvent &ev) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp index 43a5867002..81587fb526 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp @@ -34,6 +34,7 @@ CREATEDXGIFACTORY PCreateDXGIFactory = NULL; HINSTANCE hDXGIDll = NULL; 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**); +D3D11CREATEDEVICE PD3D11CreateDevice = NULL; D3D11CREATEDEVICEANDSWAPCHAIN PD3D11CreateDeviceAndSwapChain = NULL; HINSTANCE hD3DDll = NULL; @@ -47,6 +48,8 @@ D3D_FEATURE_LEVEL featlevel; D3DTexture2D* backbuf = NULL; HWND hWnd; +std::vector aa_modes; // supported AA modes of the current adapter + bool bgra_textures_supported; #define NUM_SUPPORTED_FEATURE_LEVELS 3 @@ -60,8 +63,9 @@ unsigned int xres, yres; bool bFrameInProgress = false; -HRESULT GetDXGIFuncPointers() +HRESULT LoadDXGI() { + if (hDXGIDll) return S_OK; hDXGIDll = LoadLibraryA("dxgi.dll"); if (!hDXGIDll) { @@ -74,14 +78,28 @@ HRESULT GetDXGIFuncPointers() return S_OK; } -void UnloadDXGI() +HRESULT LoadD3D() { - if(hDXGIDll) FreeLibrary(hDXGIDll); - PCreateDXGIFactory = NULL; + if (hD3DDll) return S_OK; + hD3DDll = LoadLibraryA("d3d11.dll"); + if (!hD3DDll) + { + MessageBoxA(NULL, "Failed to load d3d11.dll", "Critical error", MB_OK | MB_ICONERROR); + return E_FAIL; + } + PD3D11CreateDevice = (D3D11CREATEDEVICE)GetProcAddress(hD3DDll, "D3D11CreateDevice"); + if (PD3D11CreateDevice == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3D11CreateDevice!", "Critical error", MB_OK | MB_ICONERROR); + + PD3D11CreateDeviceAndSwapChain = (D3D11CREATEDEVICEANDSWAPCHAIN)GetProcAddress(hD3DDll, "D3D11CreateDeviceAndSwapChain"); + if (PD3D11CreateDeviceAndSwapChain == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3D11CreateDeviceAndSwapChain!", "Critical error", MB_OK | MB_ICONERROR); + + return S_OK; } -HRESULT GetD3DFuncPointers() +HRESULT LoadD3DX() { + if (hD3DXDll) return S_OK; + // try to load D3DX11 first to check whether we have proper runtime support // try to use the dll the plugin was compiled against first - don't bother about debug runtimes hD3DXDll = LoadLibraryA(StringFromFormat("d3dx11_%d.dll", D3DX11_SDK_VERSION).c_str()); @@ -112,22 +130,64 @@ HRESULT GetD3DFuncPointers() PD3DX11SaveTextureToFileW = (D3DX11SAVETEXTURETOFILEWTYPE)GetProcAddress(hD3DXDll, "D3DX11SaveTextureToFileW"); if (PD3DX11SaveTextureToFileW == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11SaveTextureToFileW!", "Critical error", MB_OK | MB_ICONERROR); - // D3DX11 is fine, check DXGI and D3D11 - HRESULT hr = GetDXGIFuncPointers(); - if (FAILED(hr)) return hr; - - hD3DDll = LoadLibraryA("d3d11.dll"); - if (!hD3DDll) - { - MessageBoxA(NULL, "Failed to load d3d11.dll", "Critical error", MB_OK | MB_ICONERROR); - return E_FAIL; - } - PD3D11CreateDeviceAndSwapChain = (D3D11CREATEDEVICEANDSWAPCHAIN)GetProcAddress(hD3DDll, "D3D11CreateDeviceAndSwapChain"); - if (PD3D11CreateDeviceAndSwapChain == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3D11CreateDeviceAndSwapChain!", "Critical error", MB_OK | MB_ICONERROR); - return S_OK; } +void UnloadDXGI() +{ + if(hDXGIDll) FreeLibrary(hDXGIDll); + hDXGIDll = NULL; + PCreateDXGIFactory = NULL; +} + +void UnloadD3DX() +{ + if(hD3DXDll) FreeLibrary(hD3DXDll); + hD3DXDll = NULL; + PD3DX11FilterTexture = NULL; + PD3DX11SaveTextureToFileA = NULL; + PD3DX11SaveTextureToFileW = NULL; +} + +void UnloadD3D() +{ + if(hD3DDll) FreeLibrary(hD3DDll); + hD3DDll = NULL; + PD3D11CreateDevice = NULL; + PD3D11CreateDeviceAndSwapChain = NULL; +} + +void EnumAAModes(IDXGIAdapter* adapter, std::vector& aa_modes) +{ + aa_modes.clear(); + + ID3D11Device* device; + ID3D11DeviceContext* context; + D3D_FEATURE_LEVEL feat_level; + HRESULT hr = PD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, D3D11_CREATE_DEVICE_SINGLETHREADED, NULL, 0, D3D11_SDK_VERSION, &device, &feat_level, &context); + if (FAILED(hr)) return; + + for (int samples = 0; samples < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; ++samples) + { + UINT quality_levels = 0; + device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, samples, &quality_levels); + if (quality_levels > 0) { + DXGI_SAMPLE_DESC desc; + desc.Count = samples; + for (desc.Quality = 0; desc.Quality < quality_levels; ++desc.Quality) + aa_modes.push_back(desc); + } + } + + context->Release(); + device->Release(); +} + +DXGI_SAMPLE_DESC GetAAMode(int index) +{ + return aa_modes[index]; +} + HRESULT Create(HWND wnd) { hWnd = wnd; @@ -138,8 +198,15 @@ HRESULT Create(HWND wnd) xres = client.right - client.left; yres = client.bottom - client.top; - hr = GetD3DFuncPointers(); - if (FAILED(hr)) return hr; + hr = LoadDXGI(); + if (SUCCEEDED(hr)) hr = LoadD3D(); + if (SUCCEEDED(hr)) hr = LoadD3DX(); + if (FAILED(hr)) + { + UnloadDXGI(); + UnloadD3D(); + return hr; + } IDXGIFactory* factory; IDXGIAdapter* adapter; @@ -164,6 +231,10 @@ HRESULT Create(HWND wnd) if (FAILED(hr)) MessageBox(wnd, _T("Failed to enumerate outputs"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR); } + // get supported AA modes + aa_modes.clear(); + EnumAAModes(adapter, aa_modes); + // this will need to be changed once multisampling gets implemented DXGI_SWAP_CHAIN_DESC swap_chain_desc; memset(&swap_chain_desc, 0, sizeof(swap_chain_desc)); @@ -260,14 +331,8 @@ void Close() device = NULL; // unload DLLs - if(hD3DXDll) FreeLibrary(hD3DXDll); - PD3DX11FilterTexture = NULL; - PD3DX11SaveTextureToFileA = NULL; - PD3DX11SaveTextureToFileW = NULL; - - if(hD3DXDll) FreeLibrary(hD3DXDll); - PD3D11CreateDeviceAndSwapChain = NULL; - + UnloadD3DX(); + UnloadD3D(); UnloadDXGI(); } diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h index 94e5fa4648..e76617de15 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h @@ -31,8 +31,15 @@ class D3DTexture2D; namespace D3D { -HRESULT GetDXGIFuncPointers(); +HRESULT LoadDXGI(); +HRESULT LoadD3D(); +HRESULT LoadD3DX(); void UnloadDXGI(); +void UnloadD3D(); +void UnloadD3DX(); + +void EnumAAModes(IDXGIAdapter* adapter, std::vector& aa_modes); +DXGI_SAMPLE_DESC GetAAMode(int index); HRESULT Create(HWND wnd); void Close(); @@ -92,3 +99,5 @@ extern D3DX11SAVETEXTURETOFILEWTYPE PD3DX11SaveTextureToFileW; typedef HRESULT (WINAPI* CREATEDXGIFACTORY)(REFIID, void**); extern CREATEDXGIFACTORY PCreateDXGIFactory; +typedef HRESULT (WINAPI* D3D11CREATEDEVICE)(IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL*, UINT, UINT, ID3D11Device**, D3D_FEATURE_LEVEL*, ID3D11DeviceContext**); +extern D3D11CREATEDEVICE PD3D11CreateDevice; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.cpp b/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.cpp index 38b9fe4431..ee06bc1cf2 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.cpp @@ -92,12 +92,15 @@ ID3D11RenderTargetView* &D3DTexture2D::GetRTV() { return rtv; } ID3D11DepthStencilView* &D3DTexture2D::GetDSV() { return dsv; } D3DTexture2D::D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind, - DXGI_FORMAT srv_format, DXGI_FORMAT dsv_format, DXGI_FORMAT rtv_format) + DXGI_FORMAT srv_format, DXGI_FORMAT dsv_format, DXGI_FORMAT rtv_format, bool multisampled) : ref(1), tex(texptr), srv(NULL), rtv(NULL), dsv(NULL) { - D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = CD3D11_SHADER_RESOURCE_VIEW_DESC(D3D11_SRV_DIMENSION_TEXTURE2D, srv_format); - D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D, dsv_format); - D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = CD3D11_RENDER_TARGET_VIEW_DESC(D3D11_RTV_DIMENSION_TEXTURE2D, rtv_format); + D3D11_SRV_DIMENSION srv_dim = multisampled ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D; + D3D11_DSV_DIMENSION dsv_dim = multisampled ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D; + D3D11_RTV_DIMENSION rtv_dim = multisampled ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D; + D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = CD3D11_SHADER_RESOURCE_VIEW_DESC(srv_dim, srv_format); + D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = CD3D11_DEPTH_STENCIL_VIEW_DESC(dsv_dim, dsv_format); + D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = CD3D11_RENDER_TARGET_VIEW_DESC(rtv_dim, rtv_format); if (bind & D3D11_BIND_SHADER_RESOURCE) D3D::device->CreateShaderResourceView(tex, &srv_desc, &srv); if (bind & D3D11_BIND_RENDER_TARGET) D3D::device->CreateRenderTargetView(tex, &rtv_desc, &rtv); if (bind & D3D11_BIND_DEPTH_STENCIL) D3D::device->CreateDepthStencilView(tex, &dsv_desc, &dsv); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.h b/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.h index ddde3719e9..37479378d6 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.h @@ -31,7 +31,7 @@ public: // either create an ID3D11Texture2D object, pass it to the constructor and specify what views to create // or let the texture automatically be created by D3DTexture2D::Create - D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind, DXGI_FORMAT srv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT dsv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT rtv_format = DXGI_FORMAT_UNKNOWN); + D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind, DXGI_FORMAT srv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT dsv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT rtv_format = DXGI_FORMAT_UNKNOWN, bool multisampled = false); static D3DTexture2D* Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT, unsigned int levels = 1); // reference counting, use AddRef() when creating a new reference and Release() it when you don't need it anymore diff --git a/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp index 3d540fb571..8d6efb673d 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp @@ -33,27 +33,48 @@ D3DTexture2D* &FramebufferManager::GetEFBDepthTexture() { return m_efb.depth_tex D3DTexture2D* &FramebufferManager::GetEFBDepthReadTexture() { return m_efb.depth_read_texture; } ID3D11Texture2D* &FramebufferManager::GetEFBDepthStagingBuffer() { return m_efb.depth_staging_buf; } +D3DTexture2D* &FramebufferManager::GetResolvedEFBColorTexture() +{ + if (g_ActiveConfig.iMultisampleMode) + { + D3D::context->ResolveSubresource(m_efb.resolved_color_tex->GetTex(), 0, m_efb.color_tex->GetTex(), 0, DXGI_FORMAT_R8G8B8A8_UNORM); + return m_efb.resolved_color_tex; + } + else + return m_efb.color_tex; +} + +D3DTexture2D* &FramebufferManager::GetResolvedEFBDepthTexture() +{ + if (g_ActiveConfig.iMultisampleMode) + { + D3D::context->ResolveSubresource(m_efb.resolved_color_tex->GetTex(), 0, m_efb.color_tex->GetTex(), 0, DXGI_FORMAT_R8G8B8A8_UNORM); + return m_efb.resolved_color_tex; + } + else + return m_efb.depth_tex; +} + FramebufferManager::FramebufferManager() { - m_efb.color_tex = NULL; - m_efb.color_staging_buf = NULL; - m_efb.depth_tex = NULL; - m_efb.depth_staging_buf = NULL; - m_efb.depth_read_texture = NULL; - unsigned int target_width = Renderer::GetFullTargetWidth(); unsigned int target_height = Renderer::GetFullTargetHeight(); + DXGI_SAMPLE_DESC sample_desc = D3D::GetAAMode(g_ActiveConfig.iMultisampleMode); ID3D11Texture2D* buf; D3D11_TEXTURE2D_DESC texdesc; HRESULT hr; // create framebuffer color texture - m_efb.color_tex = D3DTexture2D::Create(target_width, target_height, (D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE), D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM); + texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height, 1, 1, D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, sample_desc.Count, sample_desc.Quality); + hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf); + CHECK(hr==S_OK, "create EFB color texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); + m_efb.color_tex = new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET), DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM, (sample_desc.Count > 1)); CHECK(m_efb.color_tex!=NULL, "create EFB color texture (size: %dx%d)", target_width, target_height); + SAFE_RELEASE(buf); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetTex(), "EFB color texture"); - D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetRTV(), "EFB color texture render target view"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetSRV(), "EFB color texture shader resource view"); + D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetRTV(), "EFB color texture render target view"); // create a staging texture for Renderer::AccessEFB texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ); @@ -62,10 +83,10 @@ FramebufferManager::FramebufferManager() D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_staging_buf, "EFB color staging texture (used for Renderer::AccessEFB)"); // EFB depth buffer - texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, target_width, target_height, 1, 1, D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE); + texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, target_width, target_height, 1, 1, D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, sample_desc.Count, sample_desc.Quality); hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf); CHECK(hr==S_OK, "create EFB depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); - m_efb.depth_tex = new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE), DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT); + m_efb.depth_tex = new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE), DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, (sample_desc.Count > 1)); SAFE_RELEASE(buf); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetTex(), "EFB depth texture"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetDSV(), "EFB depth texture depth stencil view"); @@ -85,15 +106,37 @@ FramebufferManager::FramebufferManager() hr = D3D::device->CreateTexture2D(&texdesc, NULL, &m_efb.depth_staging_buf); CHECK(hr==S_OK, "create EFB depth staging buffer (hr=%#x)", hr); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_staging_buf, "EFB depth staging texture (used for Renderer::AccessEFB)"); + + if (g_ActiveConfig.iMultisampleMode) + { + // create framebuffer resolve textures (color+depth) + texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height, 1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, 1); + hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf); + m_efb.resolved_color_tex = new D3DTexture2D(buf, D3D11_BIND_SHADER_RESOURCE, DXGI_FORMAT_R8G8B8A8_UNORM); + CHECK(m_efb.resolved_color_tex!=NULL, "create EFB color resolve texture (size: %dx%d)", target_width, target_height); + SAFE_RELEASE(buf); + D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.resolved_color_tex->GetTex(), "EFB color resolve texture"); + D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.resolved_color_tex->GetSRV(), "EFB color resolve texture shader resource view"); + + texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, target_width, target_height, 1, 1, D3D11_BIND_SHADER_RESOURCE); + hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf); + CHECK(hr==S_OK, "create EFB depth resolve texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); + m_efb.resolved_depth_tex = new D3DTexture2D(buf, D3D11_BIND_SHADER_RESOURCE, DXGI_FORMAT_R24_UNORM_X8_TYPELESS); + SAFE_RELEASE(buf); + D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.resolved_depth_tex->GetTex(), "EFB depth resolve texture"); + D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.resolved_depth_tex->GetSRV(), "EFB depth resolve texture shader resource view"); + } } FramebufferManager::~FramebufferManager() { SAFE_RELEASE(m_efb.color_tex); SAFE_RELEASE(m_efb.color_staging_buf); + SAFE_RELEASE(m_efb.resolved_color_tex); SAFE_RELEASE(m_efb.depth_tex); SAFE_RELEASE(m_efb.depth_staging_buf); SAFE_RELEASE(m_efb.depth_read_texture); + SAFE_RELEASE(m_efb.resolved_depth_tex); } void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.h b/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.h index f8cebb8b56..2fadf16e68 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.h @@ -80,6 +80,9 @@ public: static D3DTexture2D* &GetEFBDepthReadTexture(); static ID3D11Texture2D* &GetEFBDepthStagingBuffer(); + static D3DTexture2D* &GetResolvedEFBColorTexture(); + static D3DTexture2D* &GetResolvedEFBDepthTexture(); + private: XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height); void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc); @@ -94,6 +97,9 @@ private: D3DTexture2D* depth_tex; ID3D11Texture2D* depth_staging_buf; D3DTexture2D* depth_read_texture; + + D3DTexture2D* resolved_color_tex; + D3DTexture2D* resolved_depth_tex; } m_efb; }; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 8be2a4d5bc..fc850dce83 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -51,6 +51,8 @@ static int s_fps = 0; +static u32 s_LastAA = 0; + static u32 s_blendMode; ID3D11Buffer* access_efb_cbuf = NULL; @@ -329,6 +331,7 @@ Renderer::Renderer() CalculateXYScale(dst_rect); + s_LastAA = g_ActiveConfig.iMultisampleMode; s_LastEFBScale = g_ActiveConfig.iEFBScale; CalculateTargetSize(); @@ -492,6 +495,7 @@ void Renderer::SetColorMask() // - GX_PokeZMode (TODO) u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) { + // TODO: This function currently is broken if anti-aliasing is enabled D3D11_MAPPED_SUBRESOURCE map; ID3D11Texture2D* read_tex; @@ -542,7 +546,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) D3D::context->PSSetConstantBuffers(0, 1, &access_efb_cbuf); D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBDepthReadTexture()->GetRTV(), NULL); D3D::SetPointCopySampler(); - D3D::drawShadedTexQuad(FramebufferManager::GetEFBDepthTexture()->GetSRV(), + D3D::drawShadedTexQuad(FramebufferManager::GetResolvedEFBDepthTexture()->GetSRV(), &RectToLock, Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(), @@ -572,7 +576,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) else if (type == PEEK_COLOR) { // we can directly copy to system memory here - read_tex = FramebufferManager::GetEFBColorStagingBuffer(); + read_tex = FramebufferManager::GetResolvedEFBColorTexture()->GetTex(); D3D11_BOX box = CD3D11_BOX(RectToLock.left, RectToLock.top, 0, RectToLock.right, RectToLock.bottom, 1); D3D::context->CopySubresourceRegion(read_tex, 0, 0, 0, 0, FramebufferManager::GetEFBColorTexture()->GetTex(), 0, &box); @@ -879,7 +883,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons else { TargetRectangle targetRc = Renderer::ConvertEFBRectangle(rc); - D3DTexture2D* read_texture = FramebufferManager::GetEFBColorTexture(); + D3DTexture2D* read_texture = FramebufferManager::GetResolvedEFBColorTexture(); D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(), PixelShaderCache::GetColorCopyProgram(),VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout()); } // done with drawing the game stuff, good moment to save a screenshot @@ -956,8 +960,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons // resize the back buffers NOW to avoid flickering if (xfbchanged || WindowResized || - s_LastEFBScale != g_ActiveConfig.iEFBScale) + s_LastEFBScale != g_ActiveConfig.iEFBScale || + s_LastAA != g_ActiveConfig.iMultisampleMode) { + s_LastAA = g_ActiveConfig.iMultisampleMode; + // TODO: Aren't we still holding a reference to the back buffer right now? D3D::Reset(); s_backbuffer_width = D3D::GetBackBufferWidth(); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp index e3f3b67087..dafdbec132 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp @@ -147,7 +147,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleB D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), NULL); D3D::drawShadedTexQuad( - (bFromZBuffer) ? FramebufferManager::GetEFBDepthTexture()->GetSRV() : FramebufferManager::GetEFBColorTexture()->GetSRV(), + (bFromZBuffer) ? FramebufferManager::GetResolvedEFBDepthTexture()->GetSRV() : FramebufferManager::GetResolvedEFBColorTexture()->GetSRV(), &sourcerect, Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(), (bFromZBuffer) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram(), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout()); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp index c114d78f17..adb79f08a3 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp @@ -161,8 +161,13 @@ void DllConfig(void *_hParent) #if defined(HAVE_WX) && HAVE_WX InitBackendInfo(); - HRESULT hr = D3D::GetDXGIFuncPointers(); - if (FAILED(hr)) return; + HRESULT hr = D3D::LoadDXGI(); + if (SUCCEEDED(hr)) hr = D3D::LoadD3D(); + if (FAILED(hr)) + { + if (!s_PluginInitialized) D3D::UnloadDXGI(); + return; + } IDXGIFactory* factory; IDXGIAdapter* ad; @@ -174,10 +179,27 @@ void DllConfig(void *_hParent) DXGI_ADAPTER_DESC desc; // adapters g_Config.backend_info.Adapters.clear(); + g_Config.backend_info.AAModes.clear(); while (factory->EnumAdapters((UINT)g_Config.backend_info.Adapters.size(), &ad) != DXGI_ERROR_NOT_FOUND) { ad->GetDesc(&desc); WideCharToMultiByte(/*CP_UTF8*/CP_ACP, 0, desc.Description, -1, tmpstr, 512, 0, false); + + // TODO: These don't get updated on adapter change, yet + if (g_Config.backend_info.Adapters.size() == g_Config.iAdapter) + { + char buf[32]; + std::vector modes; + D3D::EnumAAModes(ad, modes); + for (unsigned int i = 0; i < modes.size(); ++i) + { + if (i == 0) sprintf_s(buf, 32, "None"); + else if (modes[i].Quality) sprintf_s(buf, 32, "%d samples (quality level %d)", modes[i].Count, modes[i].Quality); + else sprintf_s(buf, 32, "%d samples", modes[i].Count); + g_Config.backend_info.AAModes.push_back(buf); + } + } + g_Config.backend_info.Adapters.push_back(tmpstr); ad->Release(); } @@ -188,7 +210,11 @@ void DllConfig(void *_hParent) diag->ShowModal(); diag->Destroy(); - D3D::UnloadDXGI(); + if (!s_PluginInitialized) + { + D3D::UnloadDXGI(); + D3D::UnloadD3D(); + } #endif }