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
This commit is contained in:
NeoBrainX 2010-11-23 19:58:02 +00:00
parent 6d93a6b698
commit d36ede020c
10 changed files with 212 additions and 53 deletions

View File

@ -51,7 +51,7 @@ public:
VideoConfigDiag(wxWindow* parent, const std::string &title, const std::string& ininame); VideoConfigDiag(wxWindow* parent, const std::string &title, const std::string& ininame);
protected: 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_Adapter(wxCommandEvent &ev) { ev.Skip(); } // TODO
void Event_EfbCopy(wxCommandEvent &ev) void Event_EfbCopy(wxCommandEvent &ev)

View File

@ -34,6 +34,7 @@ CREATEDXGIFACTORY PCreateDXGIFactory = NULL;
HINSTANCE hDXGIDll = 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**); 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; D3D11CREATEDEVICEANDSWAPCHAIN PD3D11CreateDeviceAndSwapChain = NULL;
HINSTANCE hD3DDll = NULL; HINSTANCE hD3DDll = NULL;
@ -47,6 +48,8 @@ D3D_FEATURE_LEVEL featlevel;
D3DTexture2D* backbuf = NULL; D3DTexture2D* backbuf = NULL;
HWND hWnd; HWND hWnd;
std::vector<DXGI_SAMPLE_DESC> aa_modes; // supported AA modes of the current adapter
bool bgra_textures_supported; bool bgra_textures_supported;
#define NUM_SUPPORTED_FEATURE_LEVELS 3 #define NUM_SUPPORTED_FEATURE_LEVELS 3
@ -60,8 +63,9 @@ unsigned int xres, yres;
bool bFrameInProgress = false; bool bFrameInProgress = false;
HRESULT GetDXGIFuncPointers() HRESULT LoadDXGI()
{ {
if (hDXGIDll) return S_OK;
hDXGIDll = LoadLibraryA("dxgi.dll"); hDXGIDll = LoadLibraryA("dxgi.dll");
if (!hDXGIDll) if (!hDXGIDll)
{ {
@ -74,14 +78,28 @@ HRESULT GetDXGIFuncPointers()
return S_OK; return S_OK;
} }
void UnloadDXGI() HRESULT LoadD3D()
{ {
if(hDXGIDll) FreeLibrary(hDXGIDll); if (hD3DDll) return S_OK;
PCreateDXGIFactory = NULL; 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 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 // 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()); hD3DXDll = LoadLibraryA(StringFromFormat("d3dx11_%d.dll", D3DX11_SDK_VERSION).c_str());
@ -112,22 +130,64 @@ HRESULT GetD3DFuncPointers()
PD3DX11SaveTextureToFileW = (D3DX11SAVETEXTURETOFILEWTYPE)GetProcAddress(hD3DXDll, "D3DX11SaveTextureToFileW"); PD3DX11SaveTextureToFileW = (D3DX11SAVETEXTURETOFILEWTYPE)GetProcAddress(hD3DXDll, "D3DX11SaveTextureToFileW");
if (PD3DX11SaveTextureToFileW == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11SaveTextureToFileW!", "Critical error", MB_OK | MB_ICONERROR); 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; 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<DXGI_SAMPLE_DESC>& 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) HRESULT Create(HWND wnd)
{ {
hWnd = wnd; hWnd = wnd;
@ -138,8 +198,15 @@ HRESULT Create(HWND wnd)
xres = client.right - client.left; xres = client.right - client.left;
yres = client.bottom - client.top; yres = client.bottom - client.top;
hr = GetD3DFuncPointers(); hr = LoadDXGI();
if (FAILED(hr)) return hr; if (SUCCEEDED(hr)) hr = LoadD3D();
if (SUCCEEDED(hr)) hr = LoadD3DX();
if (FAILED(hr))
{
UnloadDXGI();
UnloadD3D();
return hr;
}
IDXGIFactory* factory; IDXGIFactory* factory;
IDXGIAdapter* adapter; 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); 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 // this will need to be changed once multisampling gets implemented
DXGI_SWAP_CHAIN_DESC swap_chain_desc; DXGI_SWAP_CHAIN_DESC swap_chain_desc;
memset(&swap_chain_desc, 0, sizeof(swap_chain_desc)); memset(&swap_chain_desc, 0, sizeof(swap_chain_desc));
@ -260,14 +331,8 @@ void Close()
device = NULL; device = NULL;
// unload DLLs // unload DLLs
if(hD3DXDll) FreeLibrary(hD3DXDll); UnloadD3DX();
PD3DX11FilterTexture = NULL; UnloadD3D();
PD3DX11SaveTextureToFileA = NULL;
PD3DX11SaveTextureToFileW = NULL;
if(hD3DXDll) FreeLibrary(hD3DXDll);
PD3D11CreateDeviceAndSwapChain = NULL;
UnloadDXGI(); UnloadDXGI();
} }

View File

@ -31,8 +31,15 @@ class D3DTexture2D;
namespace D3D namespace D3D
{ {
HRESULT GetDXGIFuncPointers(); HRESULT LoadDXGI();
HRESULT LoadD3D();
HRESULT LoadD3DX();
void UnloadDXGI(); void UnloadDXGI();
void UnloadD3D();
void UnloadD3DX();
void EnumAAModes(IDXGIAdapter* adapter, std::vector<DXGI_SAMPLE_DESC>& aa_modes);
DXGI_SAMPLE_DESC GetAAMode(int index);
HRESULT Create(HWND wnd); HRESULT Create(HWND wnd);
void Close(); void Close();
@ -92,3 +99,5 @@ extern D3DX11SAVETEXTURETOFILEWTYPE PD3DX11SaveTextureToFileW;
typedef HRESULT (WINAPI* CREATEDXGIFACTORY)(REFIID, void**); typedef HRESULT (WINAPI* CREATEDXGIFACTORY)(REFIID, void**);
extern CREATEDXGIFACTORY PCreateDXGIFactory; 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;

View File

@ -92,12 +92,15 @@ ID3D11RenderTargetView* &D3DTexture2D::GetRTV() { return rtv; }
ID3D11DepthStencilView* &D3DTexture2D::GetDSV() { return dsv; } ID3D11DepthStencilView* &D3DTexture2D::GetDSV() { return dsv; }
D3DTexture2D::D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind, 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) : 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_SRV_DIMENSION srv_dim = multisampled ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D, dsv_format); D3D11_DSV_DIMENSION dsv_dim = multisampled ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = CD3D11_RENDER_TARGET_VIEW_DESC(D3D11_RTV_DIMENSION_TEXTURE2D, rtv_format); 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_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_RENDER_TARGET) D3D::device->CreateRenderTargetView(tex, &rtv_desc, &rtv);
if (bind & D3D11_BIND_DEPTH_STENCIL) D3D::device->CreateDepthStencilView(tex, &dsv_desc, &dsv); if (bind & D3D11_BIND_DEPTH_STENCIL) D3D::device->CreateDepthStencilView(tex, &dsv_desc, &dsv);

View File

@ -31,7 +31,7 @@ public:
// either create an ID3D11Texture2D object, pass it to the constructor and specify what views to create // 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 // 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); 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 // reference counting, use AddRef() when creating a new reference and Release() it when you don't need it anymore

View File

@ -33,27 +33,48 @@ D3DTexture2D* &FramebufferManager::GetEFBDepthTexture() { return m_efb.depth_tex
D3DTexture2D* &FramebufferManager::GetEFBDepthReadTexture() { return m_efb.depth_read_texture; } D3DTexture2D* &FramebufferManager::GetEFBDepthReadTexture() { return m_efb.depth_read_texture; }
ID3D11Texture2D* &FramebufferManager::GetEFBDepthStagingBuffer() { return m_efb.depth_staging_buf; } 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() 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_width = Renderer::GetFullTargetWidth();
unsigned int target_height = Renderer::GetFullTargetHeight(); unsigned int target_height = Renderer::GetFullTargetHeight();
DXGI_SAMPLE_DESC sample_desc = D3D::GetAAMode(g_ActiveConfig.iMultisampleMode);
ID3D11Texture2D* buf; ID3D11Texture2D* buf;
D3D11_TEXTURE2D_DESC texdesc; D3D11_TEXTURE2D_DESC texdesc;
HRESULT hr; HRESULT hr;
// create framebuffer color texture // 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); 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->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->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 // 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); 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)"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_staging_buf, "EFB color staging texture (used for Renderer::AccessEFB)");
// EFB depth buffer // 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); 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); 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); SAFE_RELEASE(buf);
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetTex(), "EFB depth texture"); 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"); 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); hr = D3D::device->CreateTexture2D(&texdesc, NULL, &m_efb.depth_staging_buf);
CHECK(hr==S_OK, "create EFB depth staging buffer (hr=%#x)", hr); 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)"); 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() FramebufferManager::~FramebufferManager()
{ {
SAFE_RELEASE(m_efb.color_tex); SAFE_RELEASE(m_efb.color_tex);
SAFE_RELEASE(m_efb.color_staging_buf); 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_tex);
SAFE_RELEASE(m_efb.depth_staging_buf); SAFE_RELEASE(m_efb.depth_staging_buf);
SAFE_RELEASE(m_efb.depth_read_texture); 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) void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)

View File

@ -80,6 +80,9 @@ public:
static D3DTexture2D* &GetEFBDepthReadTexture(); static D3DTexture2D* &GetEFBDepthReadTexture();
static ID3D11Texture2D* &GetEFBDepthStagingBuffer(); static ID3D11Texture2D* &GetEFBDepthStagingBuffer();
static D3DTexture2D* &GetResolvedEFBColorTexture();
static D3DTexture2D* &GetResolvedEFBDepthTexture();
private: private:
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height); XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc); void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc);
@ -94,6 +97,9 @@ private:
D3DTexture2D* depth_tex; D3DTexture2D* depth_tex;
ID3D11Texture2D* depth_staging_buf; ID3D11Texture2D* depth_staging_buf;
D3DTexture2D* depth_read_texture; D3DTexture2D* depth_read_texture;
D3DTexture2D* resolved_color_tex;
D3DTexture2D* resolved_depth_tex;
} m_efb; } m_efb;
}; };

View File

@ -51,6 +51,8 @@
static int s_fps = 0; static int s_fps = 0;
static u32 s_LastAA = 0;
static u32 s_blendMode; static u32 s_blendMode;
ID3D11Buffer* access_efb_cbuf = NULL; ID3D11Buffer* access_efb_cbuf = NULL;
@ -329,6 +331,7 @@ Renderer::Renderer()
CalculateXYScale(dst_rect); CalculateXYScale(dst_rect);
s_LastAA = g_ActiveConfig.iMultisampleMode;
s_LastEFBScale = g_ActiveConfig.iEFBScale; s_LastEFBScale = g_ActiveConfig.iEFBScale;
CalculateTargetSize(); CalculateTargetSize();
@ -492,6 +495,7 @@ void Renderer::SetColorMask()
// - GX_PokeZMode (TODO) // - GX_PokeZMode (TODO)
u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) 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; D3D11_MAPPED_SUBRESOURCE map;
ID3D11Texture2D* read_tex; 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->PSSetConstantBuffers(0, 1, &access_efb_cbuf);
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBDepthReadTexture()->GetRTV(), NULL); D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBDepthReadTexture()->GetRTV(), NULL);
D3D::SetPointCopySampler(); D3D::SetPointCopySampler();
D3D::drawShadedTexQuad(FramebufferManager::GetEFBDepthTexture()->GetSRV(), D3D::drawShadedTexQuad(FramebufferManager::GetResolvedEFBDepthTexture()->GetSRV(),
&RectToLock, &RectToLock,
Renderer::GetFullTargetWidth(), Renderer::GetFullTargetWidth(),
Renderer::GetFullTargetHeight(), Renderer::GetFullTargetHeight(),
@ -572,7 +576,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
else if (type == PEEK_COLOR) else if (type == PEEK_COLOR)
{ {
// we can directly copy to system memory here // 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); 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); 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 else
{ {
TargetRectangle targetRc = Renderer::ConvertEFBRectangle(rc); 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()); 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 // 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 // resize the back buffers NOW to avoid flickering
if (xfbchanged || WindowResized || 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? // TODO: Aren't we still holding a reference to the back buffer right now?
D3D::Reset(); D3D::Reset();
s_backbuffer_width = D3D::GetBackBufferWidth(); s_backbuffer_width = D3D::GetBackBufferWidth();

View File

@ -147,7 +147,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleB
D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), NULL); D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), NULL);
D3D::drawShadedTexQuad( D3D::drawShadedTexQuad(
(bFromZBuffer) ? FramebufferManager::GetEFBDepthTexture()->GetSRV() : FramebufferManager::GetEFBColorTexture()->GetSRV(), (bFromZBuffer) ? FramebufferManager::GetResolvedEFBDepthTexture()->GetSRV() : FramebufferManager::GetResolvedEFBColorTexture()->GetSRV(),
&sourcerect, Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(), &sourcerect, Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(),
(bFromZBuffer) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram(), (bFromZBuffer) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram(),
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout()); VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());

View File

@ -161,8 +161,13 @@ void DllConfig(void *_hParent)
#if defined(HAVE_WX) && HAVE_WX #if defined(HAVE_WX) && HAVE_WX
InitBackendInfo(); InitBackendInfo();
HRESULT hr = D3D::GetDXGIFuncPointers(); HRESULT hr = D3D::LoadDXGI();
if (FAILED(hr)) return; if (SUCCEEDED(hr)) hr = D3D::LoadD3D();
if (FAILED(hr))
{
if (!s_PluginInitialized) D3D::UnloadDXGI();
return;
}
IDXGIFactory* factory; IDXGIFactory* factory;
IDXGIAdapter* ad; IDXGIAdapter* ad;
@ -174,10 +179,27 @@ void DllConfig(void *_hParent)
DXGI_ADAPTER_DESC desc; DXGI_ADAPTER_DESC desc;
// adapters // adapters
g_Config.backend_info.Adapters.clear(); 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) while (factory->EnumAdapters((UINT)g_Config.backend_info.Adapters.size(), &ad) != DXGI_ERROR_NOT_FOUND)
{ {
ad->GetDesc(&desc); ad->GetDesc(&desc);
WideCharToMultiByte(/*CP_UTF8*/CP_ACP, 0, desc.Description, -1, tmpstr, 512, 0, false); 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<DXGI_SAMPLE_DESC> 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); g_Config.backend_info.Adapters.push_back(tmpstr);
ad->Release(); ad->Release();
} }
@ -188,7 +210,11 @@ void DllConfig(void *_hParent)
diag->ShowModal(); diag->ShowModal();
diag->Destroy(); diag->Destroy();
D3D::UnloadDXGI(); if (!s_PluginInitialized)
{
D3D::UnloadDXGI();
D3D::UnloadD3D();
}
#endif #endif
} }