diff --git a/src/duckstation-qt/CMakeLists.txt b/src/duckstation-qt/CMakeLists.txt index 87ee6c030..7726bb868 100644 --- a/src/duckstation-qt/CMakeLists.txt +++ b/src/duckstation-qt/CMakeLists.txt @@ -40,3 +40,11 @@ add_executable(duckstation-qt ) target_link_libraries(duckstation-qt PRIVATE YBaseLib core common imgui glad Qt5::Core Qt5::Gui Qt5::Widgets) + +if(WIN32) + target_sources(duckstation-qt PRIVATE + d3d11displaywindow.cpp + d3d11displaywindow.h + ) + target_link_libraries(duckstation PRIVATE d3d11.lib) +endif() diff --git a/src/duckstation-qt/d3d11displaywindow.cpp b/src/duckstation-qt/d3d11displaywindow.cpp index 9dbe21b99..38daea050 100644 --- a/src/duckstation-qt/d3d11displaywindow.cpp +++ b/src/duckstation-qt/d3d11displaywindow.cpp @@ -12,8 +12,8 @@ public: template using ComPtr = Microsoft::WRL::ComPtr; - D3D11DisplayWindowTexture(ComPtr texture, ComPtr srv, u32 width, u32 height, - bool dynamic) + D3D11DisplayWindowTexture(ComPtr texture, ComPtr srv, u32 width, + u32 height, bool dynamic) : m_texture(std::move(texture)), m_srv(std::move(srv)), m_width(width), m_height(height), m_dynamic(dynamic) { } @@ -27,8 +27,8 @@ public: ID3D11ShaderResourceView* GetD3DSRV() const { return m_srv.Get(); } bool IsDynamic() const { return m_dynamic; } - static std::unique_ptr Create(ID3D11Device* device, u32 width, u32 height, const void* data, - u32 data_stride, bool dynamic) + static std::unique_ptr Create(ID3D11Device* device, u32 width, u32 height, + const void* data, u32 data_stride, bool dynamic) { const CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, width, height, 1, 1, D3D11_BIND_SHADER_RESOURCE, dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT, @@ -60,11 +60,15 @@ private: D3D11DisplayWindow::D3D11DisplayWindow(QtHostInterface* host_interface, QWindow* parent) : QtDisplayWindow(host_interface, parent) { - } D3D11DisplayWindow::~D3D11DisplayWindow() = default; +HostDisplay* D3D11DisplayWindow::getHostDisplayInterface() +{ + return this; +} + HostDisplay::RenderAPI D3D11DisplayWindow::GetRenderAPI() const { return HostDisplay::RenderAPI::D3D11; @@ -91,13 +95,13 @@ void D3D11DisplayWindow::ChangeRenderWindow(void* new_window) } std::unique_ptr D3D11DisplayWindow::CreateTexture(u32 width, u32 height, const void* data, - u32 data_stride, bool dynamic) + u32 data_stride, bool dynamic) { return D3D11DisplayWindowTexture::Create(m_device.Get(), width, height, data, data_stride, dynamic); } -void D3D11DisplayWindow::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data, - u32 data_stride) +void D3D11DisplayWindow::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, + const void* data, u32 data_stride) { D3D11DisplayWindowTexture* d3d11_texture = static_cast(texture); if (!d3d11_texture->IsDynamic()) @@ -133,7 +137,7 @@ void D3D11DisplayWindow::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y } void D3D11DisplayWindow::SetDisplayTexture(void* texture, s32 offset_x, s32 offset_y, s32 width, s32 height, - u32 texture_width, u32 texture_height, float aspect_ratio) + u32 texture_width, u32 texture_height, float aspect_ratio) { m_display_srv = static_cast(texture); m_display_offset_x = offset_x; @@ -167,14 +171,15 @@ std::tuple D3D11DisplayWindow::GetWindowSize() const return std::make_tuple(static_cast(s.width()), static_cast(s.height())); } -void D3D11DisplayWindow::WindowResized() -{ -} +void D3D11DisplayWindow::WindowResized() {} void D3D11DisplayWindow::onWindowResized(int width, int height) { QtDisplayWindow::onWindowResized(width, height); + if (!m_swap_chain) + return; + m_swap_chain_rtv.Reset(); HRESULT hr = m_swap_chain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0); @@ -200,7 +205,7 @@ bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread) swap_chain_desc.SampleDesc.Count = 1; swap_chain_desc.BufferCount = 3; swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swap_chain_desc.OutputWindow = syswm.info.win.window; + swap_chain_desc.OutputWindow = reinterpret_cast(winId()); swap_chain_desc.Windowed = TRUE; swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; @@ -220,7 +225,7 @@ bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread) return false; } -#if 0 +#if 1 ComPtr info; hr = m_device.As(&info); if (SUCCEEDED(hr)) @@ -230,10 +235,36 @@ bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread) } #endif + if (!QtDisplayWindow::createDeviceContext(worker_thread)) + { + m_swap_chain.Reset(); + m_context.Reset(); + m_device.Reset(); + } + return true; } -bool D3D11DisplayWindow::CreateSwapChainRTV() +bool D3D11DisplayWindow::initializeDeviceContext() +{ + if (!createSwapChainRTV()) + return false; + + if (!QtDisplayWindow::initializeDeviceContext()) + return false; + + return true; +} + +void D3D11DisplayWindow::destroyDeviceContext() +{ + QtDisplayWindow::destroyDeviceContext(); + m_swap_chain.Reset(); + m_context.Reset(); + m_device.Reset(); +} + +bool D3D11DisplayWindow::createSwapChainRTV() { ComPtr backbuffer; HRESULT hr = m_swap_chain->GetBuffer(0, IID_PPV_ARGS(backbuffer.GetAddressOf())); @@ -258,7 +289,7 @@ bool D3D11DisplayWindow::CreateSwapChainRTV() return true; } -bool D3D11DisplayWindow::CreateD3DResources() +bool D3D11DisplayWindow::createDeviceResources() { static constexpr char fullscreen_quad_vertex_shader[] = R"( cbuffer UBOBlock : register(b0) @@ -331,26 +362,36 @@ void main(in float2 v_tex0 : TEXCOORD0, return true; } -bool D3D11DisplayWindow::CreateImGuiContext() +void D3D11DisplayWindow::destroyDeviceResources() { - if (!ImGui_ImplSDL2_InitForD3D(m_window) || !ImGui_ImplDX11_Init(m_device.Get(), m_context.Get())) + QtDisplayWindow::destroyDeviceResources(); + + m_linear_sampler.Reset(); + m_point_sampler.Reset(); + m_display_pixel_shader.Reset(); + m_display_vertex_shader.Reset(); + m_display_blend_state.Reset(); + m_display_depth_stencil_state.Reset(); + m_display_rasterizer_state.Reset(); +} + +bool D3D11DisplayWindow::createImGuiContext() +{ + if (!QtDisplayWindow::createImGuiContext()) + return false; + + if (!ImGui_ImplDX11_Init(m_device.Get(), m_context.Get())) return false; ImGui_ImplDX11_NewFrame(); - ImGui_ImplSDL2_NewFrame(m_window); + ImGui::NewFrame(); return true; } -std::unique_ptr D3D11DisplayWindow::Create(SDL_Window* window) +void D3D11DisplayWindow::destroyImGuiContext() { - std::unique_ptr display = std::make_unique(window); - if (!display->CreateD3DDevice() || !display->CreateSwapChainRTV() || !display->CreateD3DResources() || - !display->CreateImGuiContext()) - { - return nullptr; - } - - return display; + ImGui_ImplDX11_Shutdown(); + QtDisplayWindow::destroyImGuiContext(); } void D3D11DisplayWindow::Render() @@ -359,17 +400,18 @@ void D3D11DisplayWindow::Render() m_context->ClearRenderTargetView(m_swap_chain_rtv.Get(), clear_color.data()); m_context->OMSetRenderTargets(1, m_swap_chain_rtv.GetAddressOf(), nullptr); - RenderDisplay(); + renderDisplay(); + ImGui::Render(); ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); m_swap_chain->Present(BoolToUInt32(m_vsync), 0); - ImGui_ImplSDL2_NewFrame(m_window); + ImGui::NewFrame(); ImGui_ImplDX11_NewFrame(); } -void D3D11DisplayWindow::RenderDisplay() +void D3D11DisplayWindow::renderDisplay() { if (!m_display_srv) return; @@ -404,3 +446,5 @@ void D3D11DisplayWindow::RenderDisplay() m_context->Draw(3, 0); } + + diff --git a/src/duckstation-qt/duckstation-qt.vcxproj b/src/duckstation-qt/duckstation-qt.vcxproj index 16d862f4d..8f86201a0 100644 --- a/src/duckstation-qt/duckstation-qt.vcxproj +++ b/src/duckstation-qt/duckstation-qt.vcxproj @@ -36,6 +36,7 @@ + @@ -58,6 +59,7 @@ + @@ -108,6 +110,7 @@ + @@ -283,7 +286,7 @@ Console true $(SolutionDir)dep\msvc\lib32-debug;$(SolutionDir)dep\msvc\qt5-x86\lib;%(AdditionalLibraryDirectories) - Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5Multimediad.lib;%(AdditionalDependencies) + Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5Multimediad.lib;d3d11.lib;%(AdditionalDependencies) @@ -304,7 +307,7 @@ Console true $(SolutionDir)dep\msvc\lib64-debug;$(SolutionDir)dep\msvc\qt5-x64\lib;%(AdditionalLibraryDirectories) - Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5Multimediad.lib;%(AdditionalDependencies) + Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5Multimediad.lib;d3d11.lib;%(AdditionalDependencies) @@ -327,7 +330,7 @@ Console true $(SolutionDir)dep\msvc\lib32-debug;$(SolutionDir)dep\msvc\qt5-x86\lib;%(AdditionalLibraryDirectories) - Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5Multimediad.lib;%(AdditionalDependencies) + Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5Multimediad.lib;d3d11.lib;%(AdditionalDependencies) @@ -350,7 +353,7 @@ Console true $(SolutionDir)dep\msvc\lib64-debug;$(SolutionDir)dep\msvc\qt5-x64\lib;%(AdditionalLibraryDirectories) - Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5Multimediad.lib;%(AdditionalDependencies) + Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5Multimediad.lib;d3d11.lib;%(AdditionalDependencies) @@ -372,7 +375,7 @@ true true $(SolutionDir)dep\msvc\lib32;$(SolutionDir)dep\msvc\qt5-x86\lib;%(AdditionalLibraryDirectories) - Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5Multimedia.lib;%(AdditionalDependencies) + Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5Multimedia.lib;d3d11.lib;%(AdditionalDependencies) @@ -395,7 +398,7 @@ true true $(SolutionDir)dep\msvc\lib32;$(SolutionDir)dep\msvc\qt5-x86\lib;%(AdditionalLibraryDirectories) - Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5Multimedia.lib;%(AdditionalDependencies) + Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5Multimedia.lib;d3d11.lib;%(AdditionalDependencies) UseLinkTimeCodeGeneration @@ -418,7 +421,7 @@ true true $(SolutionDir)dep\msvc\lib64;$(SolutionDir)dep\msvc\qt5-x64\lib;%(AdditionalLibraryDirectories) - Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5Multimedia.lib;%(AdditionalDependencies) + Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5Multimedia.lib;d3d11.lib;%(AdditionalDependencies) @@ -441,7 +444,7 @@ true true $(SolutionDir)dep\msvc\lib64;$(SolutionDir)dep\msvc\qt5-x64\lib;%(AdditionalLibraryDirectories) - Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5Multimedia.lib;%(AdditionalDependencies) + Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5Multimedia.lib;d3d11.lib;%(AdditionalDependencies) UseLinkTimeCodeGeneration diff --git a/src/duckstation-qt/duckstation-qt.vcxproj.filters b/src/duckstation-qt/duckstation-qt.vcxproj.filters index 64fd7d469..2252a61f2 100644 --- a/src/duckstation-qt/duckstation-qt.vcxproj.filters +++ b/src/duckstation-qt/duckstation-qt.vcxproj.filters @@ -30,12 +30,14 @@ + + diff --git a/src/duckstation-qt/qthostinterface.cpp b/src/duckstation-qt/qthostinterface.cpp index 1255ed2ad..55015c8f1 100644 --- a/src/duckstation-qt/qthostinterface.cpp +++ b/src/duckstation-qt/qthostinterface.cpp @@ -15,6 +15,10 @@ #include Log_SetChannel(QtHostInterface); +#ifdef WIN32 +#include "d3d11displaywindow.h" +#endif + QtHostInterface::QtHostInterface(QObject* parent) : QObject(parent), m_qsettings("duckstation-qt.ini", QSettings::IniFormat) { @@ -132,7 +136,11 @@ void QtHostInterface::refreshGameList(bool invalidate_cache /*= false*/) QWidget* QtHostInterface::createDisplayWidget(QWidget* parent) { +#ifdef WIN32 + m_display_window = new D3D11DisplayWindow(this, nullptr); +#else m_display_window = new OpenGLDisplayWindow(this, nullptr); +#endif connect(m_display_window, &QtDisplayWindow::windowResizedEvent, this, &QtHostInterface::onDisplayWindowResized); m_display.release();