From be1511bd7a10bff23cd81a8862a09260e0a368ac Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Sun, 16 Aug 2015 19:01:08 +0200 Subject: [PATCH] d3d12: Add a d2d overlay to display debug text --- rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp | 10 +- rpcs3/Emu/RSX/D3D12/D3D12GSRender.h | 8 ++ rpcs3/Emu/RSX/D3D12/D3D12Overlay.cpp | 155 ++++++++++++++++++++++++++ rpcs3/Gui/MainFrame.cpp | 6 +- rpcs3/Ini.h | 4 + rpcs3/emucore.vcxproj | 1 + rpcs3/emucore.vcxproj.filters | 3 + 7 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 rpcs3/Emu/RSX/D3D12/D3D12Overlay.cpp diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index 213b8d6d2d4f..efc329b92b5a 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -387,6 +387,8 @@ D3D12GSRender::D3D12GSRender() m_constantsData.Init(m_device.Get(), 1024 * 1024 * 64, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_FLAG_NONE); m_vertexIndexData.Init(m_device.Get(), 1024 * 1024 * 384, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS); m_textureUploadData.Init(m_device.Get(), 1024 * 1024 * 256, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS); + + InitD2DStructures(); } D3D12GSRender::~D3D12GSRender() @@ -413,6 +415,8 @@ D3D12GSRender::~D3D12GSRender() for (auto &tmp : m_texturesCache) tmp.second->Release(); m_outputScalingPass.Release(); + + ReleaseD2DStructures(); } void D3D12GSRender::Close() @@ -899,12 +903,16 @@ void D3D12GSRender::Flip() if (m_rtts.m_currentlyBoundRenderTargets[0] != nullptr) getCurrentResourceStorage().m_currentCommandList->DrawInstanced(4, 1, 0, 0); - getCurrentResourceStorage().m_currentCommandList->ResourceBarrier(1, &getResourceBarrierTransition(m_backBuffer[m_swapChain->GetCurrentBackBufferIndex()].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT)); + if (!Ini.GSOverlay.GetValue()) + getCurrentResourceStorage().m_currentCommandList->ResourceBarrier(1, &getResourceBarrierTransition(m_backBuffer[m_swapChain->GetCurrentBackBufferIndex()].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT)); if (isFlipSurfaceInLocalMemory(m_surface_color_target) && m_rtts.m_currentlyBoundRenderTargets[0] != nullptr) getCurrentResourceStorage().m_currentCommandList->ResourceBarrier(1, &getResourceBarrierTransition(m_rtts.m_currentlyBoundRenderTargets[0], D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET)); ThrowIfFailed(getCurrentResourceStorage().m_currentCommandList->Close()); m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)&(getCurrentResourceStorage().m_currentCommandList)); + if(Ini.GSOverlay.GetValue()) + renderOverlay(); + ThrowIfFailed(m_swapChain->Present(Ini.GSVSyncEnable.GetValue() ? 1 : 0, 0)); // Add an event signaling queue completion diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index 60d31eea3f4c..40dd27bac775 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -385,6 +385,8 @@ class D3D12GSRender : public GSRender virtual void semaphorePFIFOAcquire(u32 offset, u32 value) override; private: + void InitD2DStructures(); + void ReleaseD2DStructures(); ID3D12Resource *writeColorBuffer(ID3D12Resource *RTT, ID3D12GraphicsCommandList *cmdlist); virtual void Close() override; @@ -422,6 +424,12 @@ class D3D12GSRender : public GSRender * from generic to rtt for rtt in cache). */ void PrepareRenderTargets(ID3D12GraphicsCommandList *cmdlist); + + /** + * Render D2D overlay if enabled on top of the backbuffer. + */ + void renderOverlay(); + protected: virtual void OnInit() override; virtual void OnInitThread() override; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Overlay.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Overlay.cpp new file mode 100644 index 000000000000..d6c08375e1bb --- /dev/null +++ b/rpcs3/Emu/RSX/D3D12/D3D12Overlay.cpp @@ -0,0 +1,155 @@ +#include "stdafx.h" +#if defined(DX12_SUPPORT) +#include "D3D12GSRender.h" +#include +#include +#include +#include + +// D2D +ComPtr d3d11Device; +ComPtr m_d3d11DeviceContext; +ComPtr m_d3d11On12Device; +ComPtr m_d3d12Device; +ComPtr m_dWriteFactory; +ComPtr m_d2dFactory; +ComPtr m_d2dDevice; +ComPtr m_d2dDeviceContext; +ComPtr m_wrappedBackBuffers[2]; +ComPtr m_d2dRenderTargets[2]; +ComPtr m_textFormat; +ComPtr m_textBrush; + +#pragma comment (lib, "d2d1.lib") +#pragma comment (lib, "dwrite.lib") +#pragma comment (lib, "d3d11.lib") + +void D3D12GSRender::InitD2DStructures() +{ + D3D11On12CreateDevice( + m_device.Get(), + D3D11_CREATE_DEVICE_BGRA_SUPPORT, + nullptr, + 0, + reinterpret_cast(m_commandQueueGraphic.GetAddressOf()), + 1, + 0, + &d3d11Device, + &m_d3d11DeviceContext, + nullptr + ); + + d3d11Device.As(&m_d3d11On12Device); + + D2D1_DEVICE_CONTEXT_OPTIONS deviceOptions = D2D1_DEVICE_CONTEXT_OPTIONS_NONE; + D2D1_FACTORY_OPTIONS d2dFactoryOptions = {}; + D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory3), &d2dFactoryOptions, &m_d2dFactory); + Microsoft::WRL::ComPtr dxgiDevice; + m_d3d11On12Device.As(&dxgiDevice); + m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice); + m_d2dDevice->CreateDeviceContext(deviceOptions, &m_d2dDeviceContext); + DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &m_dWriteFactory); + + float dpiX; + float dpiY; + m_d2dFactory->GetDesktopDpi(&dpiX, &dpiY); + D2D1_BITMAP_PROPERTIES1 bitmapProperties = D2D1::BitmapProperties1( + D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, + D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED), + dpiX, + dpiY + ); + + for (unsigned i = 0; i < 2; i++) + { + D3D11_RESOURCE_FLAGS d3d11Flags = { D3D11_BIND_RENDER_TARGET }; + m_d3d11On12Device->CreateWrappedResource( + m_backBuffer[i].Get(), + &d3d11Flags, + D3D12_RESOURCE_STATE_RENDER_TARGET, + D3D12_RESOURCE_STATE_PRESENT, + IID_PPV_ARGS(&m_wrappedBackBuffers[i]) + ); + + // Create a render target for D2D to draw directly to this back buffer. + Microsoft::WRL::ComPtr surface; + m_wrappedBackBuffers[i].As(&surface); + m_d2dDeviceContext->CreateBitmapFromDxgiSurface( + surface.Get(), + &bitmapProperties, + &m_d2dRenderTargets[i] + ); + } + + m_d2dDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::DarkGreen), &m_textBrush); + m_dWriteFactory->CreateTextFormat( + L"Verdana", + NULL, + DWRITE_FONT_WEIGHT_BOLD, + DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, + 14, + L"en-us", + &m_textFormat + ); + m_textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING); + m_textFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR); +} + +void D3D12GSRender::ReleaseD2DStructures() +{ + d3d11Device.Reset(); + m_d3d11DeviceContext.Reset(); + m_d3d11On12Device.Reset(); + m_d3d12Device.Reset(); + m_dWriteFactory.Reset(); + m_d2dFactory.Reset(); + m_d2dDevice.Reset(); + m_d2dDeviceContext.Reset(); + m_wrappedBackBuffers[0].Reset(); + m_d2dRenderTargets[0].Reset(); + m_wrappedBackBuffers[1].Reset(); + m_d2dRenderTargets[1].Reset(); + m_textFormat.Reset(); + m_textBrush.Reset(); +} + +void D3D12GSRender::renderOverlay() +{ + D2D1_SIZE_F rtSize = m_d2dRenderTargets[m_swapChain->GetCurrentBackBufferIndex()]->GetSize(); + std::wstring duration = L"Draw duration : " + std::to_wstring(m_timers.m_drawCallDuration) + L" ms"; + std::wstring count = L"Draw count : " + std::to_wstring(m_timers.m_drawCallCount); + + // Acquire our wrapped render target resource for the current back buffer. + m_d3d11On12Device->AcquireWrappedResources(m_wrappedBackBuffers[m_swapChain->GetCurrentBackBufferIndex()].GetAddressOf(), 1); + + // Render text directly to the back buffer. + m_d2dDeviceContext->SetTarget(m_d2dRenderTargets[m_swapChain->GetCurrentBackBufferIndex()].Get()); + m_d2dDeviceContext->BeginDraw(); + m_d2dDeviceContext->SetTransform(D2D1::Matrix3x2F::Identity()); + m_d2dDeviceContext->DrawTextW( + duration.c_str(), + duration.size(), + m_textFormat.Get(), + &D2D1::RectF(0, 0, rtSize.width, rtSize.height), + m_textBrush.Get() + ); + m_d2dDeviceContext->DrawTextW( + count.c_str(), + count.size(), + m_textFormat.Get(), + &D2D1::RectF(0, 14, rtSize.width, rtSize.height), + m_textBrush.Get() + ); + m_d2dDeviceContext->EndDraw(); + + // Release our wrapped render target resource. Releasing + // transitions the back buffer resource to the state specified + // as the OutState when the wrapped resource was created. + m_d3d11On12Device->ReleaseWrappedResources(m_wrappedBackBuffers[m_swapChain->GetCurrentBackBufferIndex()].GetAddressOf(), 1); + + // Flush to submit the 11 command list to the shared command queue. + m_d3d11DeviceContext->Flush(); +} + +#endif \ No newline at end of file diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index 4d592cf2638e..cbcc67f9564a 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -365,7 +365,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) wxDialog diag(this, wxID_ANY, "Settings", wxDefaultPosition); static const u32 width = 458; - static const u32 height = 520; + static const u32 height = 580; // Settings panels wxNotebook* nb_config = new wxNotebook(&diag, wxID_ANY, wxPoint(6,6), wxSize(width, height)); @@ -455,6 +455,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) wxCheckBox* chbox_gs_vsync = new wxCheckBox(p_graphics, wxID_ANY, "VSync"); wxCheckBox* chbox_gs_debug_output = new wxCheckBox(p_graphics, wxID_ANY, "Debug Output"); wxCheckBox* chbox_gs_3dmonitor = new wxCheckBox(p_graphics, wxID_ANY, "3D Monitor"); + wxCheckBox* chbox_gs_overlay = new wxCheckBox(p_graphics, wxID_ANY, "Debug overlay"); wxCheckBox* chbox_audio_dump = new wxCheckBox(p_audio, wxID_ANY, "Dump to file"); wxCheckBox* chbox_audio_conv = new wxCheckBox(p_audio, wxID_ANY, "Convert to 16 bit"); wxCheckBox* chbox_hle_logging = new wxCheckBox(p_misc, wxID_ANY, "Log everything"); @@ -628,6 +629,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) chbox_gs_vsync ->SetValue(Ini.GSVSyncEnable.GetValue()); chbox_gs_debug_output ->SetValue(Ini.GSDebugOutputEnable.GetValue()); chbox_gs_3dmonitor ->SetValue(Ini.GS3DTV.GetValue()); + chbox_gs_overlay ->SetValue(Ini.GSOverlay.GetValue()); chbox_audio_dump ->SetValue(Ini.AudioDumpToFile.GetValue()); chbox_audio_conv ->SetValue(Ini.AudioConvertToU16.GetValue()); chbox_hle_logging ->SetValue(Ini.HLELogging.GetValue()); @@ -721,6 +723,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) s_subpanel_graphics->Add(chbox_gs_vsync, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics->Add(chbox_gs_debug_output, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics->Add(chbox_gs_3dmonitor, wxSizerFlags().Border(wxALL, 5).Expand()); + s_subpanel_graphics->Add(chbox_gs_overlay, wxSizerFlags().Border(wxALL, 5).Expand()); // Input - Output s_subpanel_io->Add(s_round_io_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand()); @@ -801,6 +804,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) Ini.GSVSyncEnable.SetValue(chbox_gs_vsync->GetValue()); Ini.GSDebugOutputEnable.SetValue(chbox_gs_debug_output->GetValue()); Ini.GS3DTV.SetValue(chbox_gs_3dmonitor->GetValue()); + Ini.GSOverlay.SetValue(chbox_gs_overlay->GetValue()); Ini.PadHandlerMode.SetValue(cbox_pad_handler->GetSelection()); Ini.KeyboardHandlerMode.SetValue(cbox_keyboard_handler->GetSelection()); Ini.MouseHandlerMode.SetValue(cbox_mouse_handler->GetSelection()); diff --git a/rpcs3/Ini.h b/rpcs3/Ini.h index a274ace4440d..edc8f57f9982 100644 --- a/rpcs3/Ini.h +++ b/rpcs3/Ini.h @@ -113,6 +113,7 @@ class Inis IniEntry GSVSyncEnable; IniEntry GS3DTV; IniEntry GSDebugOutputEnable; + IniEntry GSOverlay; // Audio IniEntry AudioOutMode; @@ -203,6 +204,7 @@ class Inis GSVSyncEnable.Init("GS_VSyncEnable", path); GSDebugOutputEnable.Init("GS_DebugOutputEnable", path); GS3DTV.Init("GS_3DTV", path); + GSOverlay.Init("GS_Overlay", path); // Audio AudioOutMode.Init("Audio_AudioOutMode", path); @@ -289,6 +291,7 @@ class Inis GSVSyncEnable.Load(false); GSDebugOutputEnable.Load(false); GS3DTV.Load(false); + GSOverlay.Load(false); // Audio AudioOutMode.Load(1); @@ -375,6 +378,7 @@ class Inis GSVSyncEnable.Save(); GSDebugOutputEnable.Save(); GS3DTV.Save(); + GSOverlay.Save(); // Audio AudioOutMode.Save(); diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index a5b402b01252..d9be1e590890 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -60,6 +60,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index ee8cda35ba9f..ba0980eb2e8b 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -995,6 +995,9 @@ Emu\GPU\RSX\D3D12 + + Emu\GPU\RSX\D3D12 +