From f605ae9f6524d3179f0003d85a33e21212cb5e31 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 12 Jun 2023 16:47:54 -0500 Subject: [PATCH 01/13] GUI: prepare for DirectX 11 render backend --- CMakeLists.txt | 20 ++++++- src/gui/gui.cpp | 4 +- src/gui/gui.h | 8 ++- src/gui/render.cpp | 11 ++++ src/gui/render/renderDX11.cpp | 100 ++++++++++++++++++++++++++++++++++ src/gui/render/renderDX11.h | 64 ++++++++++++++++++++++ src/gui/settings.cpp | 5 ++ 7 files changed, 208 insertions(+), 4 deletions(-) create mode 100644 src/gui/render/renderDX11.cpp create mode 100644 src/gui/render/renderDX11.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b55f514f..da3256a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,11 @@ if (APPLE) else() set(WITH_RENDER_OPENGL_DEFAULT ON) endif() +if (WIN32) + set(WITH_RENDER_DX11_DEFAULT ON) +else() + set(WITH_RENDER_DX11_DEFAULT OFF) +endif() if (ANDROID) set(USE_GLES_DEFAULT ON) @@ -75,6 +80,7 @@ option(USE_BACKWARD "Use backward-cpp to print a backtrace on crash/abort." ${US option(WITH_JACK "Whether to build with JACK support. Auto-detects if JACK is available" ${WITH_JACK_DEFAULT}) option(WITH_RENDER_SDL "Whether to build with the SDL_Renderer render backend." ${WITH_RENDER_SDL_DEFAULT}) option(WITH_RENDER_OPENGL "Whether to build with the OpenGL render backend." ${WITH_RENDER_OPENGL_DEFAULT}) +option(WITH_RENDER_DX11 "Whether to build with the DirectX 11 render backend." ${WITH_RENDER_DX11_DEFAULT}) option(USE_GLES "Use OpenGL ES for the OpenGL render backend." ${USE_GLES_DEFAULT}) option(SYSTEM_FFTW "Use a system-installed version of FFTW instead of the vendored one" OFF) option(SYSTEM_FMT "Use a system-installed version of fmt instead of the vendored one" OFF) @@ -302,7 +308,7 @@ else() endif() if (BUILD_GUI) - if (NOT WITH_RENDER_SDL AND NOT WITH_RENDER_OPENGL) + if (NOT WITH_RENDER_SDL AND NOT WITH_RENDER_OPENGL AND NOT WITH_RENDER_DX11) message(FATAL_ERROR "No render backends selected!") endif() endif() @@ -731,6 +737,18 @@ if (WITH_RENDER_OPENGL) message(STATUS "UI render backend: OpenGL") endif() +if (WITH_RENDER_DX11) + if (WIN32) + list(APPEND GUI_SOURCES src/gui/render/renderDX11.cpp) + list(APPEND GUI_SOURCES extern/imgui_patched/backends/imgui_impl_dx11.cpp) + list(APPEND DEPENDENCIES_DEFINES HAVE_RENDER_DX11) + list(APPEND DEPENDENCIES_LIBRARIES D3D11 d3dcompiler) + message(STATUS "UI render backend: DirectX 11") + else() + message(FATAL_ERROR "DirectX 11 render backend only for Windows!") + endif() +endif() + if (NOT WIN32 AND NOT APPLE) CHECK_INCLUDE_FILE(sys/io.h SYS_IO_FOUND) CHECK_INCLUDE_FILE(linux/input.h LINUX_INPUT_FOUND) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index edc71376..732ce551 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -6148,7 +6148,7 @@ bool FurnaceGUI::init() { logV("window size: %dx%d",scrW,scrH); if (!initRender()) { - if (settings.renderBackend=="OpenGL") { + if (settings.renderBackend!="SDL" && !settings.renderBackend.empty()) { settings.renderBackend=""; e->setConf("renderBackend",""); e->saveConf(); @@ -6234,7 +6234,7 @@ bool FurnaceGUI::init() { logD("starting render backend..."); if (!rend->init(sdlWin)) { - if (settings.renderBackend=="OpenGL") { + if (settings.renderBackend!="SDL" && !settings.renderBackend.empty()) { settings.renderBackend=""; e->setConf("renderBackend",""); e->saveConf(); diff --git a/src/gui/gui.h b/src/gui/gui.h index 77bcab26..19fdb281 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -71,16 +71,22 @@ enum FurnaceGUIRenderBackend { GUI_BACKEND_SDL=0, - GUI_BACKEND_GL + GUI_BACKEND_GL, + GUI_BACKEND_DX11 }; #ifdef HAVE_RENDER_SDL #define GUI_BACKEND_DEFAULT GUI_BACKEND_SDL #define GUI_BACKEND_DEFAULT_NAME "SDL" #else +#ifdef HAVE_RENDER_DX11 +#define GUI_BACKEND_DEFAULT GUI_BACKEND_DX11 +#define GUI_BACKEND_DEFAULT_NAME "DirectX 11" +#else #define GUI_BACKEND_DEFAULT GUI_BACKEND_GL #define GUI_BACKEND_DEFAULT_NAME "OpenGL" #endif +#endif // TODO: // - add colors for FM envelope and waveform diff --git a/src/gui/render.cpp b/src/gui/render.cpp index 908fd57d..5ad753c2 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -25,12 +25,17 @@ #ifdef HAVE_RENDER_GL #include "render/renderGL.h" #endif +#ifdef HAVE_RENDER_DX11 +#include "render/renderDX11.h" +#endif bool FurnaceGUI::initRender() { if (rend!=NULL) return false; if (settings.renderBackend=="OpenGL") { renderBackend=GUI_BACKEND_GL; + } else if (settings.renderBackend=="DirectX 11") { + renderBackend=GUI_BACKEND_DX11; } else if (settings.renderBackend=="SDL") { renderBackend=GUI_BACKEND_SDL; } else { @@ -44,6 +49,12 @@ bool FurnaceGUI::initRender() { rend=new FurnaceGUIRenderGL; break; #endif +#ifdef HAVE_RENDER_DX11 + case GUI_BACKEND_DX11: + logI("render backend: DirectX 11"); + rend=new FurnaceGUIRenderDX11; + break; +#endif #ifdef HAVE_RENDER_SDL case GUI_BACKEND_SDL: logI("render backend: SDL_Renderer"); diff --git a/src/gui/render/renderDX11.cpp b/src/gui/render/renderDX11.cpp new file mode 100644 index 00000000..6e7bdb6b --- /dev/null +++ b/src/gui/render/renderDX11.cpp @@ -0,0 +1,100 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2023 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "renderDX11.h" + +ImTextureID FurnaceGUIRenderDX11::getTextureID(void* which) { + return NULL; +} + +bool FurnaceGUIRenderDX11::lockTexture(void* which, void** data, int* pitch) { + return false; +} + +bool FurnaceGUIRenderDX11::unlockTexture(void* which) { + return false; +} + +bool FurnaceGUIRenderDX11::updateTexture(void* which, void* data, int pitch) { + return false; +} + +void* FurnaceGUIRenderDX11::createTexture(bool dynamic, int width, int height) { + return NULL; +} + +bool FurnaceGUIRenderDX11::destroyTexture(void* which) { + return false; +} + +void FurnaceGUIRenderDX11::setTextureBlendMode(void* which, FurnaceGUIBlendMode mode) { +} + +void FurnaceGUIRenderDX11::setBlendMode(FurnaceGUIBlendMode mode) { +} + +void FurnaceGUIRenderDX11::clear(ImVec4 color) { +} + +bool FurnaceGUIRenderDX11::newFrame() { + return true; +} + +void FurnaceGUIRenderDX11::createFontsTexture() { +} + +void FurnaceGUIRenderDX11::destroyFontsTexture() { +} + +void FurnaceGUIRenderDX11::renderGUI() { +} + +void FurnaceGUIRenderDX11::wipe(float alpha) { +} + +void FurnaceGUIRenderDX11::present() { +} + +bool FurnaceGUIRenderDX11::getOutputSize(int& w, int& h) { + return false; +} + +int FurnaceGUIRenderDX11::getWindowFlags() { + return 0; +} + +void FurnaceGUIRenderDX11::preInit() { +} + +bool FurnaceGUIRenderDX11::init(SDL_Window* win) { + return false; +} + +void FurnaceGUIRenderDX11::initGUI(SDL_Window* win) { +} + +bool FurnaceGUIRenderDX11::quit() { + return false; +} + +void FurnaceGUIRenderDX11::quitGUI() { +} + +FurnaceGUIRenderDX11::~FurnaceGUIRenderDX11() { +} diff --git a/src/gui/render/renderDX11.h b/src/gui/render/renderDX11.h new file mode 100644 index 00000000..6900848f --- /dev/null +++ b/src/gui/render/renderDX11.h @@ -0,0 +1,64 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2023 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "../gui.h" + +class FurnaceGUIRenderDX11: public FurnaceGUIRender { + ID3D11Device* device; + ID3D11DeviceContext* context; + ID3D11RenderTargetView* renderTarget; + SDL_Window* sdlWin; + IDXGISwapChain* swapchain; + float quadVertex[4][3]; + unsigned int quadBuf; + + void createRenderTarget(); + + public: + ImTextureID getTextureID(void* which); + bool lockTexture(void* which, void** data, int* pitch); + bool unlockTexture(void* which); + bool updateTexture(void* which, void* data, int pitch); + void* createTexture(bool dynamic, int width, int height); + bool destroyTexture(void* which); + void setTextureBlendMode(void* which, FurnaceGUIBlendMode mode); + void setBlendMode(FurnaceGUIBlendMode mode); + void clear(ImVec4 color); + bool newFrame(); + void createFontsTexture(); + void destroyFontsTexture(); + void renderGUI(); + void wipe(float alpha); + void present(); + bool getOutputSize(int& w, int& h); + int getWindowFlags(); + void preInit(); + bool init(SDL_Window* win); + void initGUI(SDL_Window* win); + void quitGUI(); + bool quit(); + FurnaceGUIRenderDX11(): + device(NULL), + context(NULL), + renderTarget(NULL), + sdlWin(NULL), + swapchain(NULL) { + memset(quadVertex,0,4*3*sizeof(float)); + } +}; diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index 9648de12..5e57640d 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -1303,6 +1303,11 @@ void FurnaceGUI::drawSettings() { settings.renderBackend="SDL"; } #endif +#ifdef HAVE_RENDER_DX11 + if (ImGui::Selectable("DirectX 11",curRenderBackend=="DirectX 11")) { + settings.renderBackend="DirectX 11"; + } +#endif #ifdef HAVE_RENDER_GL if (ImGui::Selectable("OpenGL",curRenderBackend=="OpenGL")) { settings.renderBackend="OpenGL"; From 2c912da89af3182cd52216342e96ec75504e2ed5 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 12 Jun 2023 19:17:46 -0500 Subject: [PATCH 02/13] GUI: DirectX 11 render backend, part 1 --- CMakeLists.txt | 2 +- src/gui/render/renderDX11.cpp | 129 ++++++++++++++++++++++++++++++++-- src/gui/render/renderDX11.h | 12 +++- 3 files changed, 134 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index da3256a1..30174880 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -742,7 +742,7 @@ if (WITH_RENDER_DX11) list(APPEND GUI_SOURCES src/gui/render/renderDX11.cpp) list(APPEND GUI_SOURCES extern/imgui_patched/backends/imgui_impl_dx11.cpp) list(APPEND DEPENDENCIES_DEFINES HAVE_RENDER_DX11) - list(APPEND DEPENDENCIES_LIBRARIES D3D11 d3dcompiler) + list(APPEND DEPENDENCIES_LIBRARIES d3d11 d3dcompiler) message(STATUS "UI render backend: DirectX 11") else() message(FATAL_ERROR "DirectX 11 render backend only for Windows!") diff --git a/src/gui/render/renderDX11.cpp b/src/gui/render/renderDX11.cpp index 6e7bdb6b..dcfb0998 100644 --- a/src/gui/render/renderDX11.cpp +++ b/src/gui/render/renderDX11.cpp @@ -17,7 +17,61 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#define INCLUDE_D3D11 #include "renderDX11.h" +#include +#include "backends/imgui_impl_dx11.h" +#include "../../ta-log.h" + +const D3D_FEATURE_LEVEL possibleFeatureLevels[2]={ + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_0 +}; + +bool FurnaceGUIRenderDX11::destroyRenderTarget() { + if (renderTarget!=NULL) { + renderTarget->Release(); + renderTarget=NULL; + return true; + } + return false; +} + +bool FurnaceGUIRenderDX11::createRenderTarget() { + ID3D11Texture2D* screen=NULL; + HRESULT result; + + destroyRenderTarget(); + + if (swapchain==NULL || device==NULL) { + logW("createRenderTarget: swapchain or device are NULL!"); + return false; + } + + result=swapchain->GetBuffer(0,IID_PPV_ARGS(&screen)); + if (result!=S_OK) { + logW("createRenderTarget: could not get buffer! %.8x",result); + return false; + } + if (screen==NULL) { + logW("createRenderTarget: screen is null!"); + return false; + } + + result=device->CreateRenderTargetView(screen,NULL,&renderTarget); + if (result!=S_OK) { + logW("createRenderTarget: could not create render target view! %.8x",result); + screen->Release(); + return false; + } + if (renderTarget==NULL) { + logW("createRenderTarget: what the hell the render target is null?"); + screen->Release(); + return false; + } + + return true; +} ImTextureID FurnaceGUIRenderDX11::getTextureID(void* which) { return NULL; @@ -50,25 +104,40 @@ void FurnaceGUIRenderDX11::setBlendMode(FurnaceGUIBlendMode mode) { } void FurnaceGUIRenderDX11::clear(ImVec4 color) { + float floatColor[4]={ + color.x*color.w, + color.y*color.w, + color.z*color.w, + color.w, + }; + + context->OMSetRenderTargets(1,&renderTarget,NULL); + context->ClearRenderTargetView(renderTarget,floatColor); } bool FurnaceGUIRenderDX11::newFrame() { + ImGui_ImplDX11_NewFrame(); return true; } void FurnaceGUIRenderDX11::createFontsTexture() { + ImGui_ImplDX11_CreateDeviceObjects(); } void FurnaceGUIRenderDX11::destroyFontsTexture() { + ImGui_ImplDX11_InvalidateDeviceObjects(); } void FurnaceGUIRenderDX11::renderGUI() { + ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); } void FurnaceGUIRenderDX11::wipe(float alpha) { + // TODO } void FurnaceGUIRenderDX11::present() { + swapchain->Present(1,0); } bool FurnaceGUIRenderDX11::getOutputSize(int& w, int& h) { @@ -83,18 +152,68 @@ void FurnaceGUIRenderDX11::preInit() { } bool FurnaceGUIRenderDX11::init(SDL_Window* win) { - return false; + SDL_SysWMinfo sysWindow; + D3D_FEATURE_LEVEL featureLevel; + + SDL_VERSION(&sysWindow.version); + if (SDL_GetWindowWMInfo(win,&sysWindow)==SDL_FALSE) { + logE("could not get window WM info! %s",SDL_GetError()); + return false; + } + HWND window=(HWND)sysWindow.info.win.window; + + DXGI_SWAP_CHAIN_DESC chainDesc; + memset(&chainDesc,0,sizeof(chainDesc)); + chainDesc.BufferDesc.Width=0; + chainDesc.BufferDesc.Height=0; + chainDesc.BufferDesc.Format=DXGI_FORMAT_R8G8B8A8_UNORM; + chainDesc.BufferDesc.RefreshRate.Numerator=60; + chainDesc.BufferDesc.RefreshRate.Denominator=1; + chainDesc.SampleDesc.Count=1; + chainDesc.SampleDesc.Quality=0; + chainDesc.BufferUsage=DXGI_USAGE_RENDER_TARGET_OUTPUT; + chainDesc.BufferCount=2; + chainDesc.OutputWindow=window; + chainDesc.Windowed=TRUE; // TODO: what if we're in full screen mode? + chainDesc.SwapEffect=DXGI_SWAP_EFFECT_DISCARD; + chainDesc.Flags=DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + + HRESULT result=D3D11CreateDeviceAndSwapChain(NULL,D3D_DRIVER_TYPE_HARDWARE,NULL,0,possibleFeatureLevels,2,D3D11_SDK_VERSION,&chainDesc,&swapchain,&device,&featureLevel,&context); + if (result!=S_OK) { + logE("could not create device and/or swap chain! %.8x",result); + return false; + } + + createRenderTarget(); + return true; } void FurnaceGUIRenderDX11::initGUI(SDL_Window* win) { + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + + ImGui_ImplSDL2_InitForD3D(win); + ImGui_ImplDX11_Init(device,context); } bool FurnaceGUIRenderDX11::quit() { - return false; + destroyRenderTarget(); + + if (swapchain!=NULL) { + swapchain->Release(); + swapchain=NULL; + } + if (context!=NULL) { + context->Release(); + context=NULL; + } + if (device!=NULL) { + device->Release(); + device=NULL; + } + return true; } void FurnaceGUIRenderDX11::quitGUI() { -} - -FurnaceGUIRenderDX11::~FurnaceGUIRenderDX11() { + ImGui_ImplDX11_Shutdown(); } diff --git a/src/gui/render/renderDX11.h b/src/gui/render/renderDX11.h index 6900848f..9db29851 100644 --- a/src/gui/render/renderDX11.h +++ b/src/gui/render/renderDX11.h @@ -18,17 +18,24 @@ */ #include "../gui.h" +#ifdef INCLUDE_D3D11 +#include +#else +typedef void ID3D11DeviceContext; +typedef void ID3D11RenderTargetView; +typedef void IDXGISwapChain; +#endif class FurnaceGUIRenderDX11: public FurnaceGUIRender { ID3D11Device* device; ID3D11DeviceContext* context; ID3D11RenderTargetView* renderTarget; - SDL_Window* sdlWin; IDXGISwapChain* swapchain; float quadVertex[4][3]; unsigned int quadBuf; - void createRenderTarget(); + bool destroyRenderTarget(); + bool createRenderTarget(); public: ImTextureID getTextureID(void* which); @@ -57,7 +64,6 @@ class FurnaceGUIRenderDX11: public FurnaceGUIRender { device(NULL), context(NULL), renderTarget(NULL), - sdlWin(NULL), swapchain(NULL) { memset(quadVertex,0,4*3*sizeof(float)); } From cf144f4fe9e24dbfbe89c2067ddf909968fde588 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 12 Jun 2023 19:43:26 -0500 Subject: [PATCH 03/13] GUI: DirectX 11 render backend, part 2 --- src/gui/gui.cpp | 3 ++- src/gui/gui.h | 1 + src/gui/render/abstract.cpp | 5 ++++- src/gui/render/renderDX11.cpp | 22 +++++++++++++++++++++- src/gui/render/renderDX11.h | 7 +++++-- 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 732ce551..6ea8a941 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -3420,6 +3420,7 @@ bool FurnaceGUI::loop() { logV("portrait: %d (%dx%d)",portrait,scrW,scrH); logD("window resized to %dx%d",scrW,scrH); updateWindow=true; + rend->resized(ev); break; case SDL_WINDOWEVENT_MOVED: scrX=ev.window.data1; @@ -5824,8 +5825,8 @@ bool FurnaceGUI::loop() { } } } - rend->present(); drawTimeEnd=SDL_GetPerformanceCounter(); + rend->present(); if (settings.renderClearPos) { rend->clear(uiColors[GUI_COLOR_BACKGROUND]); } diff --git a/src/gui/gui.h b/src/gui/gui.h index 19fdb281..81266e43 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1248,6 +1248,7 @@ class FurnaceGUIRender { virtual bool destroyTexture(void* which); virtual void setTextureBlendMode(void* which, FurnaceGUIBlendMode mode); virtual void setBlendMode(FurnaceGUIBlendMode mode); + virtual void resized(const SDL_Event& ev); virtual void clear(ImVec4 color); virtual bool newFrame(); virtual void createFontsTexture(); diff --git a/src/gui/render/abstract.cpp b/src/gui/render/abstract.cpp index 996cf4e8..a45c4ecd 100644 --- a/src/gui/render/abstract.cpp +++ b/src/gui/render/abstract.cpp @@ -49,6 +49,9 @@ void FurnaceGUIRender::setTextureBlendMode(void* which, FurnaceGUIBlendMode mode void FurnaceGUIRender::setBlendMode(FurnaceGUIBlendMode mode) { } +void FurnaceGUIRender::resized(const SDL_Event& ev) { +} + void FurnaceGUIRender::clear(ImVec4 color) { } @@ -97,4 +100,4 @@ void FurnaceGUIRender::quitGUI() { } FurnaceGUIRender::~FurnaceGUIRender() { -} \ No newline at end of file +} diff --git a/src/gui/render/renderDX11.cpp b/src/gui/render/renderDX11.cpp index dcfb0998..767878ce 100644 --- a/src/gui/render/renderDX11.cpp +++ b/src/gui/render/renderDX11.cpp @@ -48,6 +48,15 @@ bool FurnaceGUIRenderDX11::createRenderTarget() { return false; } + DXGI_SWAP_CHAIN_DESC chainDesc; + memset(&chainDesc,0,sizeof(chainDesc)); + if (swapchain->GetDesc(&chainDesc)!=S_OK) { + logW("createRenderTarget: could not get swapchain desc!"); + } else { + outW=chainDesc.BufferDesc.Width; + outH=chainDesc.BufferDesc.Height; + } + result=swapchain->GetBuffer(0,IID_PPV_ARGS(&screen)); if (result!=S_OK) { logW("createRenderTarget: could not get buffer! %.8x",result); @@ -103,6 +112,15 @@ void FurnaceGUIRenderDX11::setTextureBlendMode(void* which, FurnaceGUIBlendMode void FurnaceGUIRenderDX11::setBlendMode(FurnaceGUIBlendMode mode) { } +void FurnaceGUIRenderDX11::resized(const SDL_Event& ev) { + destroyRenderTarget(); + swapchain->ResizeBuffers(0,0,0,DXGI_FORMAT_UNKNOWN,0); + + + + createRenderTarget(); +} + void FurnaceGUIRenderDX11::clear(ImVec4 color) { float floatColor[4]={ color.x*color.w, @@ -141,7 +159,9 @@ void FurnaceGUIRenderDX11::present() { } bool FurnaceGUIRenderDX11::getOutputSize(int& w, int& h) { - return false; + w=outW; + h=outH; + return true; } int FurnaceGUIRenderDX11::getWindowFlags() { diff --git a/src/gui/render/renderDX11.h b/src/gui/render/renderDX11.h index 9db29851..1a3d7dca 100644 --- a/src/gui/render/renderDX11.h +++ b/src/gui/render/renderDX11.h @@ -31,8 +31,8 @@ class FurnaceGUIRenderDX11: public FurnaceGUIRender { ID3D11DeviceContext* context; ID3D11RenderTargetView* renderTarget; IDXGISwapChain* swapchain; + int outW, outH; float quadVertex[4][3]; - unsigned int quadBuf; bool destroyRenderTarget(); bool createRenderTarget(); @@ -46,6 +46,7 @@ class FurnaceGUIRenderDX11: public FurnaceGUIRender { bool destroyTexture(void* which); void setTextureBlendMode(void* which, FurnaceGUIBlendMode mode); void setBlendMode(FurnaceGUIBlendMode mode); + void resized(const SDL_Event& ev); void clear(ImVec4 color); bool newFrame(); void createFontsTexture(); @@ -64,7 +65,9 @@ class FurnaceGUIRenderDX11: public FurnaceGUIRender { device(NULL), context(NULL), renderTarget(NULL), - swapchain(NULL) { + swapchain(NULL), + outW(0), + outH(0) { memset(quadVertex,0,4*3*sizeof(float)); } }; From 686a6844908dc9a4eb6b7c8733268dce61f6a257 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 12 Jun 2023 22:36:27 -0500 Subject: [PATCH 04/13] add demos/msx/OPLL_High_and_Rising.fur see ticket #1084 --- demos/msx/OPLL_High_and_Rising.fur | Bin 0 -> 6187 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 demos/msx/OPLL_High_and_Rising.fur diff --git a/demos/msx/OPLL_High_and_Rising.fur b/demos/msx/OPLL_High_and_Rising.fur new file mode 100644 index 0000000000000000000000000000000000000000..2ecab85bb1de2b9cb2b1a402f457701802cf269b GIT binary patch literal 6187 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 literal 0 HcmV?d00001 From 852f61b7fcacc64516935ee7c34ae250803ba215 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 12 Jun 2023 23:43:15 -0500 Subject: [PATCH 05/13] GUI: DirectX 11 render backend, part 3 --- src/gui/render/renderDX11.cpp | 112 +++++++++++++++++++++++++++++++--- src/gui/render/renderDX11.h | 4 ++ 2 files changed, 107 insertions(+), 9 deletions(-) diff --git a/src/gui/render/renderDX11.cpp b/src/gui/render/renderDX11.cpp index 767878ce..1133f842 100644 --- a/src/gui/render/renderDX11.cpp +++ b/src/gui/render/renderDX11.cpp @@ -28,6 +28,19 @@ const D3D_FEATURE_LEVEL possibleFeatureLevels[2]={ D3D_FEATURE_LEVEL_10_0 }; +struct FurnaceDXTexture { + ID3D11Texture2D* tex; + ID3D11ShaderResourceView* view; + int width, height; + unsigned char* lockedData; + FurnaceDXTexture(): + tex(NULL), + view(NULL), + width(0), + height(0), + lockedData(NULL) {} +}; + bool FurnaceGUIRenderDX11::destroyRenderTarget() { if (renderTarget!=NULL) { renderTarget->Release(); @@ -83,27 +96,104 @@ bool FurnaceGUIRenderDX11::createRenderTarget() { } ImTextureID FurnaceGUIRenderDX11::getTextureID(void* which) { - return NULL; + FurnaceDXTexture* t=(FurnaceDXTexture*)which; + return (ImTextureID)t->view; } bool FurnaceGUIRenderDX11::lockTexture(void* which, void** data, int* pitch) { - return false; + FurnaceDXTexture* t=(FurnaceDXTexture*)which; + if (t->lockedData!=NULL) return false; + + D3D11_MAPPED_SUBRESOURCE mappedRes; + memset(&mappedRes,0,sizeof(mappedRes)); + + HRESULT result=context->Map(t->tex,D3D11CalcSubresource(0,0,1),D3D11_MAP_WRITE,0,&mappedRes); + if (result!=S_OK) { + logW("could not map texture!"); + return false; + } + t->lockedData=(unsigned char*)mappedRes.pData; + *data=mappedRes.pData; + *pitch=mappedRes.RowPitch; + return true; } bool FurnaceGUIRenderDX11::unlockTexture(void* which) { - return false; + FurnaceDXTexture* t=(FurnaceDXTexture*)which; + if (t->lockedData==NULL) return false; + context->Unmap(t->tex,D3D11CalcSubresource(0,0,1)); + t->lockedData=NULL; + return true; } bool FurnaceGUIRenderDX11::updateTexture(void* which, void* data, int pitch) { - return false; + FurnaceDXTexture* t=(FurnaceDXTexture*)which; + context->UpdateSubresource(t->tex,D3D11CalcSubresource(0,0,1),NULL,data,pitch,pitch*t->height); + return true; } void* FurnaceGUIRenderDX11::createTexture(bool dynamic, int width, int height) { - return NULL; + D3D11_TEXTURE2D_DESC texDesc; + D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc; + ID3D11Texture2D* tex=NULL; + ID3D11ShaderResourceView* view=NULL; + HRESULT result; + + memset(&texDesc,0,sizeof(texDesc)); + memset(&viewDesc,0,sizeof(viewDesc)); + + texDesc.Width=width; + texDesc.Height=height; + texDesc.MipLevels=1; + texDesc.ArraySize=1; + texDesc.Format=DXGI_FORMAT_R8G8B8A8_UNORM; // ??? + texDesc.SampleDesc.Count=1; + texDesc.SampleDesc.Quality=0; + texDesc.Usage=dynamic?D3D11_USAGE_DYNAMIC:D3D11_USAGE_DEFAULT; + texDesc.BindFlags=D3D11_BIND_SHADER_RESOURCE; + texDesc.CPUAccessFlags=dynamic?D3D11_CPU_ACCESS_WRITE:0; + texDesc.MiscFlags=0; + + result=device->CreateTexture2D(&texDesc,NULL,&tex); + if (result!=S_OK) { + logW("could not create texture! %.8x",result); + return NULL; + } + + viewDesc.Format=texDesc.Format=texDesc.Format; + viewDesc.ViewDimension=D3D11_SRV_DIMENSION_TEXTURE2D; + viewDesc.Texture2D.MostDetailedMip=0; + viewDesc.Texture2D.MipLevels=texDesc.MipLevels; + + result=device->CreateShaderResourceView(tex,&viewDesc,&view); + if (result!=S_OK) { + logW("could not create texture view! %.8x",result); + tex->Release(); + return NULL; + } + + FurnaceDXTexture* ret=new FurnaceDXTexture; + ret->width=width; + ret->height=height; + ret->tex=tex; + ret->view=view; + textures.push_back(ret); + return ret; } bool FurnaceGUIRenderDX11::destroyTexture(void* which) { - return false; + FurnaceDXTexture* t=(FurnaceDXTexture*)which; + t->view->Release(); + t->tex->Release(); + delete t; + + for (size_t i=0; iResizeBuffers(0,0,0,DXGI_FORMAT_UNKNOWN,0); - - - createRenderTarget(); } @@ -219,6 +306,13 @@ void FurnaceGUIRenderDX11::initGUI(SDL_Window* win) { bool FurnaceGUIRenderDX11::quit() { destroyRenderTarget(); + for (FurnaceDXTexture* i: textures) { + i->view->Release(); + i->tex->Release(); + delete i; + } + textures.clear(); + if (swapchain!=NULL) { swapchain->Release(); swapchain=NULL; diff --git a/src/gui/render/renderDX11.h b/src/gui/render/renderDX11.h index 1a3d7dca..19cfb6f0 100644 --- a/src/gui/render/renderDX11.h +++ b/src/gui/render/renderDX11.h @@ -26,6 +26,8 @@ typedef void ID3D11RenderTargetView; typedef void IDXGISwapChain; #endif +struct FurnaceDXTexture; + class FurnaceGUIRenderDX11: public FurnaceGUIRender { ID3D11Device* device; ID3D11DeviceContext* context; @@ -37,6 +39,8 @@ class FurnaceGUIRenderDX11: public FurnaceGUIRender { bool destroyRenderTarget(); bool createRenderTarget(); + std::vector textures; + public: ImTextureID getTextureID(void* which); bool lockTexture(void* which, void** data, int* pitch); From ad8082a9210c7f7d275dcf2468febe03ddaa605a Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 13 Jun 2023 03:12:12 -0500 Subject: [PATCH 06/13] GUI: DirectX 11 render backend, part 4 ready to merge? --- CMakeLists.txt | 14 +- .../backends/imgui_impl_dx11.cpp | 27 ++- src/gui/gui.cpp | 6 +- src/gui/render/renderDX11.cpp | 210 +++++++++++++++++- src/gui/render/renderDX11.h | 32 ++- 5 files changed, 269 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 30174880..a5e91fb0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -739,11 +739,15 @@ endif() if (WITH_RENDER_DX11) if (WIN32) - list(APPEND GUI_SOURCES src/gui/render/renderDX11.cpp) - list(APPEND GUI_SOURCES extern/imgui_patched/backends/imgui_impl_dx11.cpp) - list(APPEND DEPENDENCIES_DEFINES HAVE_RENDER_DX11) - list(APPEND DEPENDENCIES_LIBRARIES d3d11 d3dcompiler) - message(STATUS "UI render backend: DirectX 11") + if (SUPPORT_XP) + message(FATAL_ERROR "SUPPORT_XP is on. cannot enable DirectX 11 backend.") + else() + list(APPEND GUI_SOURCES src/gui/render/renderDX11.cpp) + list(APPEND GUI_SOURCES extern/imgui_patched/backends/imgui_impl_dx11.cpp) + list(APPEND DEPENDENCIES_DEFINES HAVE_RENDER_DX11) + list(APPEND DEPENDENCIES_LIBRARIES d3d11) + message(STATUS "UI render backend: DirectX 11") + endif() else() message(FATAL_ERROR "DirectX 11 render backend only for Windows!") endif() diff --git a/extern/imgui_patched/backends/imgui_impl_dx11.cpp b/extern/imgui_patched/backends/imgui_impl_dx11.cpp index fa60d9eb..86276968 100644 --- a/extern/imgui_patched/backends/imgui_impl_dx11.cpp +++ b/extern/imgui_patched/backends/imgui_impl_dx11.cpp @@ -32,16 +32,16 @@ // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2016-05-07: DirectX11: Disabling depth-write. +// DISCLAIMER: modified with d3dcompiler patch (see https://github.com/ocornut/imgui/pull/638). + #include "imgui.h" #include "imgui_impl_dx11.h" // DirectX #include #include -#include -#ifdef _MSC_VER -#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below. -#endif + +typedef HRESULT (__stdcall *D3DCompile_t)(LPCVOID, SIZE_T, LPCSTR, D3D_SHADER_MACRO*, ID3DInclude*, LPCSTR, LPCSTR, UINT, UINT, ID3DBlob**, ID3DBlob*); // DirectX11 data struct ImGui_ImplDX11_Data @@ -380,11 +380,22 @@ bool ImGui_ImplDX11_CreateDeviceObjects() if (bd->pFontSampler) ImGui_ImplDX11_InvalidateDeviceObjects(); - // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) - // If you would like to use this DX11 sample code but remove this dependency you can: - // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution] - // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. // See https://github.com/ocornut/imgui/pull/638 for sources and details. + // Detect which d3dcompiler_XX.dll is present in the system and grab a pointer to D3DCompile. + // Without this, you must link d3dcompiler.lib with the project. + D3DCompile_t D3DCompile = NULL; + { + char dllBuffer[20]; + for (int i = 47; i > 30 && !D3DCompile; i--) + { + sprintf(dllBuffer, "d3dcompiler_%d.dll", i); + HMODULE hDll = LoadLibraryA(dllBuffer); + if (hDll) + D3DCompile = (D3DCompile_t)GetProcAddress(hDll, "D3DCompile"); + } + if (!D3DCompile) + return false; + } // Create the vertex shader { diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 6ea8a941..620ad36a 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -6237,9 +6237,9 @@ bool FurnaceGUI::init() { if (!rend->init(sdlWin)) { if (settings.renderBackend!="SDL" && !settings.renderBackend.empty()) { settings.renderBackend=""; - e->setConf("renderBackend",""); - e->saveConf(); - lastError=fmt::sprintf("\r\nthe render backend has been set to a safe value. please restart Furnace."); + //e->setConf("renderBackend",""); + //e->saveConf(); + //lastError=fmt::sprintf("\r\nthe render backend has been set to a safe value. please restart Furnace."); } else { lastError=fmt::sprintf("could not init renderer! %s",SDL_GetError()); if (!settings.renderDriver.empty()) { diff --git a/src/gui/render/renderDX11.cpp b/src/gui/render/renderDX11.cpp index 1133f842..1ed6c9cc 100644 --- a/src/gui/render/renderDX11.cpp +++ b/src/gui/render/renderDX11.cpp @@ -23,6 +23,47 @@ #include "backends/imgui_impl_dx11.h" #include "../../ta-log.h" +typedef HRESULT (__stdcall *D3DCompile_t)(LPCVOID,SIZE_T,LPCSTR,D3D_SHADER_MACRO*,ID3DInclude*,LPCSTR,LPCSTR,UINT,UINT,ID3DBlob**,ID3DBlob*); + +const char* shD3D11_wipe_srcV= + "cbuffer WipeUniform: register(b0) {\n" + " float alpha;\n" + " float padding1;\n" + " float padding2;\n" + " float padding3;\n" + " float4 padding4;\n" + "};\n" + "\n" + "struct vsInput {\n" + " float4 pos: POSITION;\n" + "};\n" + "\n" + "struct fsInput {\n" + " float4 pos: SV_POSITION;\n" + " float4 color: COLOR0;\n" + "};\n" + "\n" + "fsInput main(vsInput input) {\n" + " fsInput output;\n" + " output.pos=input.pos;\n" + " output.color=float4(0.0f,0.0f,0.0f,alpha);\n" + " return output;\n" + "}"; + +const char* shD3D11_wipe_srcF= + "struct fsInput {\n" + " float4 pos: SV_POSITION;\n" + " float4 color: COLOR0;\n" + "};\n" + "\n" + "float4 main(fsInput input): SV_Target {\n" + " return input.color;\n" + "}"; + +const D3D11_INPUT_ELEMENT_DESC shD3D11_wipe_inputLayout={ + "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 +}; + const D3D_FEATURE_LEVEL possibleFeatureLevels[2]={ D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0 @@ -237,8 +278,43 @@ void FurnaceGUIRenderDX11::renderGUI() { ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); } +const float blendFactor[4]={ + 1.0f, 1.0f, 1.0f, 1.0f +}; + void FurnaceGUIRenderDX11::wipe(float alpha) { - // TODO + D3D11_VIEWPORT viewPort; + unsigned int strides=4*sizeof(float); + unsigned int offsets=0; + + memset(&viewPort,0,sizeof(viewPort)); + viewPort.TopLeftX=0.0f; + viewPort.TopLeftY=0.0f; + viewPort.Width=outW; + viewPort.Height=outH; + viewPort.MinDepth=0.0f; + viewPort.MaxDepth=1.0f; + + D3D11_MAPPED_SUBRESOURCE mappedUniform; + if (context->Map(sh_wipe_uniform,0,D3D11_MAP_WRITE_DISCARD,0,&mappedUniform)!=S_OK) { + logW("could not map constant"); + } + WipeUniform* sh_wipe_uniformState=(WipeUniform*)mappedUniform.pData; + sh_wipe_uniformState->alpha=alpha; + context->Unmap(sh_wipe_uniform,0); + + context->RSSetViewports(1,&viewPort); + context->RSSetState(rsState); + + context->OMSetBlendState(omBlendState,blendFactor,0xffffffff); + context->IASetInputLayout(sh_wipe_inputLayout); + context->IASetVertexBuffers(0,1,&quadVertex,&strides,&offsets); + context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + context->VSSetShader(sh_wipe_vertex,NULL,0); + context->VSSetConstantBuffers(0,1,&sh_wipe_uniform); + context->PSSetShader(sh_wipe_fragment,NULL,0); + + context->Draw(4,0); } void FurnaceGUIRenderDX11::present() { @@ -258,6 +334,13 @@ int FurnaceGUIRenderDX11::getWindowFlags() { void FurnaceGUIRenderDX11::preInit() { } +const float wipeVertices[4][4]={ + -1.0, -1.0, 0.0, 1.0, + 1.0, -1.0, 0.0, 1.0, + -1.0, 1.0, 0.0, 1.0, + 1.0, 1.0, 0.0, 1.0 +}; + bool FurnaceGUIRenderDX11::init(SDL_Window* win) { SDL_SysWMinfo sysWindow; D3D_FEATURE_LEVEL featureLevel; @@ -291,6 +374,131 @@ bool FurnaceGUIRenderDX11::init(SDL_Window* win) { return false; } + // https://github.com/ocornut/imgui/pull/638 + D3DCompile_t D3DCompile=NULL; + char dllBuffer[20]; + for (int i=47; (i>30 && !D3DCompile); i--) { + snprintf(dllBuffer,20,"d3dcompiler_%d.dll",i); + HMODULE hDll=LoadLibraryA(dllBuffer); + if (hDll) { + D3DCompile=(D3DCompile_t)GetProcAddress(hDll,"D3DCompile"); + } + } + if (!D3DCompile) { + logE("could not find D3DCompile!"); + return false; + } + + // create wipe shader + ID3DBlob* wipeBlobV=NULL; + ID3DBlob* wipeBlobF=NULL; + D3D11_BUFFER_DESC wipeConstantDesc; + + result=D3DCompile(shD3D11_wipe_srcV,strlen(shD3D11_wipe_srcV),NULL,NULL,NULL,"main","vs_4_0",0,0,&wipeBlobV,NULL); + if (result!=S_OK) { + logE("could not compile vertex shader! %.8x",result); + return false; + } + result=D3DCompile(shD3D11_wipe_srcF,strlen(shD3D11_wipe_srcF),NULL,NULL,NULL,"main","ps_4_0",0,0,&wipeBlobF,NULL); + if (result!=S_OK) { + logE("could not compile pixel shader! %.8x",result); + return false; + } + + result=device->CreateVertexShader(wipeBlobV->GetBufferPointer(),wipeBlobV->GetBufferSize(),NULL,&sh_wipe_vertex); + if (result!=S_OK) { + logE("could not create vertex shader! %.8x",result); + return false; + } + result=device->CreatePixelShader(wipeBlobF->GetBufferPointer(),wipeBlobF->GetBufferSize(),NULL,&sh_wipe_fragment); + if (result!=S_OK) { + logE("could not create pixel shader! %.8x",result); + return false; + } + + result=device->CreateInputLayout(&shD3D11_wipe_inputLayout,1,wipeBlobV->GetBufferPointer(),wipeBlobV->GetBufferSize(),&sh_wipe_inputLayout); + if (result!=S_OK) { + logE("could not create input layout! %.8x",result); + return false; + } + + memset(&wipeConstantDesc,0,sizeof(wipeConstantDesc)); + wipeConstantDesc.ByteWidth=sizeof(WipeUniform); + wipeConstantDesc.Usage=D3D11_USAGE_DYNAMIC; + wipeConstantDesc.BindFlags=D3D11_BIND_CONSTANT_BUFFER; + wipeConstantDesc.CPUAccessFlags=D3D11_CPU_ACCESS_WRITE; + wipeConstantDesc.MiscFlags=0; + wipeConstantDesc.StructureByteStride=0; + + result=device->CreateBuffer(&wipeConstantDesc,NULL,&sh_wipe_uniform); + if (result!=S_OK) { + logE("could not create constant buffer! %.8x",result); + return false; + } + + // create wipe vertices + D3D11_BUFFER_DESC vertexDesc; + D3D11_SUBRESOURCE_DATA vertexRes; + + memset(&vertexDesc,0,sizeof(vertexDesc)); + memset(&vertexRes,0,sizeof(vertexRes)); + + vertexDesc.ByteWidth=4*4*sizeof(float); + vertexDesc.Usage=D3D11_USAGE_DEFAULT; + vertexDesc.BindFlags=D3D11_BIND_VERTEX_BUFFER; + vertexDesc.CPUAccessFlags=0; + vertexDesc.MiscFlags=0; + vertexDesc.StructureByteStride=0; + + vertexRes.pSysMem=wipeVertices; + vertexRes.SysMemPitch=0; + vertexRes.SysMemSlicePitch=0; + + result=device->CreateBuffer(&vertexDesc,&vertexRes,&quadVertex); + if (result!=S_OK) { + logE("could not create vertex buffer! %.8x",result); + return false; + } + + // initialize the rest + D3D11_RASTERIZER_DESC rasterDesc; + D3D11_BLEND_DESC blendDesc; + + memset(&rasterDesc,0,sizeof(rasterDesc)); + memset(&blendDesc,0,sizeof(blendDesc)); + + rasterDesc.FillMode=D3D11_FILL_SOLID; + rasterDesc.CullMode=D3D11_CULL_NONE; + rasterDesc.FrontCounterClockwise=false; + rasterDesc.DepthBias=0; + rasterDesc.DepthBiasClamp=0.0f; + rasterDesc.SlopeScaledDepthBias=0.0f; + rasterDesc.DepthClipEnable=false; + rasterDesc.ScissorEnable=false; + rasterDesc.MultisampleEnable=false; + rasterDesc.AntialiasedLineEnable=false; + result=device->CreateRasterizerState(&rasterDesc,&rsState); + if (result!=S_OK) { + logE("could not create rasterizer state! %.8x",result); + return false; + } + + blendDesc.AlphaToCoverageEnable=false; + blendDesc.IndependentBlendEnable=false; + blendDesc.RenderTarget[0].BlendEnable=true; + blendDesc.RenderTarget[0].SrcBlend=D3D11_BLEND_SRC_ALPHA; + blendDesc.RenderTarget[0].DestBlend=D3D11_BLEND_INV_SRC_ALPHA; + blendDesc.RenderTarget[0].BlendOp=D3D11_BLEND_OP_ADD; + blendDesc.RenderTarget[0].SrcBlendAlpha=D3D11_BLEND_ONE; + blendDesc.RenderTarget[0].DestBlendAlpha=D3D11_BLEND_INV_SRC_ALPHA; + blendDesc.RenderTarget[0].BlendOpAlpha=D3D11_BLEND_OP_ADD; + blendDesc.RenderTarget[0].RenderTargetWriteMask=D3D11_COLOR_WRITE_ENABLE_ALL; + result=device->CreateBlendState(&blendDesc,&omBlendState); + if (result!=S_OK) { + logE("could not create blend state! %.8x",result); + return false; + } + createRenderTarget(); return true; } diff --git a/src/gui/render/renderDX11.h b/src/gui/render/renderDX11.h index 19cfb6f0..18d8673d 100644 --- a/src/gui/render/renderDX11.h +++ b/src/gui/render/renderDX11.h @@ -23,6 +23,12 @@ #else typedef void ID3D11DeviceContext; typedef void ID3D11RenderTargetView; +typedef void ID3D11Buffer; +typedef void ID3D11RasterizerState; +typedef void ID3D11BlendState; +typedef void ID3D11VertexShader; +typedef void ID3D11PixelShader; +typedef void ID3D11InputLayout; typedef void IDXGISwapChain; #endif @@ -33,8 +39,22 @@ class FurnaceGUIRenderDX11: public FurnaceGUIRender { ID3D11DeviceContext* context; ID3D11RenderTargetView* renderTarget; IDXGISwapChain* swapchain; + ID3D11RasterizerState* rsState; + ID3D11BlendState* omBlendState; + + ID3D11Buffer* quadVertex; int outW, outH; - float quadVertex[4][3]; + + // SHADERS // + // -> wipe + ID3D11VertexShader* sh_wipe_vertex; + ID3D11PixelShader* sh_wipe_fragment; + ID3D11InputLayout* sh_wipe_inputLayout; + ID3D11Buffer* sh_wipe_uniform; + struct WipeUniform { + float alpha; + float padding[7]; + }; bool destroyRenderTarget(); bool createRenderTarget(); @@ -70,8 +90,14 @@ class FurnaceGUIRenderDX11: public FurnaceGUIRender { context(NULL), renderTarget(NULL), swapchain(NULL), + rsState(NULL), + omBlendState(NULL), + quadVertex(NULL), outW(0), - outH(0) { - memset(quadVertex,0,4*3*sizeof(float)); + outH(0), + sh_wipe_vertex(NULL), + sh_wipe_fragment(NULL), + sh_wipe_inputLayout(NULL), + sh_wipe_uniform(NULL) { } }; From 4f39e6ee31830f5346e577aed4b9525b9b0ee96e Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 13 Jun 2023 03:54:55 -0500 Subject: [PATCH 07/13] GUI: DirectX 11 render backend, part 5 nope, not yet --- src/gui/render/renderDX11.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/render/renderDX11.cpp b/src/gui/render/renderDX11.cpp index 1ed6c9cc..5b2cbb36 100644 --- a/src/gui/render/renderDX11.cpp +++ b/src/gui/render/renderDX11.cpp @@ -245,7 +245,7 @@ void FurnaceGUIRenderDX11::setBlendMode(FurnaceGUIBlendMode mode) { void FurnaceGUIRenderDX11::resized(const SDL_Event& ev) { destroyRenderTarget(); - swapchain->ResizeBuffers(0,0,0,DXGI_FORMAT_UNKNOWN,0); + swapchain->ResizeBuffers(0,(unsigned int)ev.window.data1,(unsigned int)ev.window.data2,DXGI_FORMAT_UNKNOWN,DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH); createRenderTarget(); } From d85dd7071a5472410a636b190ee7f60411f3d9ff Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 13 Jun 2023 04:06:03 -0500 Subject: [PATCH 08/13] GUI: DirectX 11 render backend, part 6 nice I probably found a new DXVK bug --- src/gui/render/renderDX11.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/gui/render/renderDX11.cpp b/src/gui/render/renderDX11.cpp index 5b2cbb36..5f7e70d6 100644 --- a/src/gui/render/renderDX11.cpp +++ b/src/gui/render/renderDX11.cpp @@ -109,6 +109,7 @@ bool FurnaceGUIRenderDX11::createRenderTarget() { } else { outW=chainDesc.BufferDesc.Width; outH=chainDesc.BufferDesc.Height; + logI("DX11: buffer desc sizes: %d, %d",chainDesc.BufferDesc.Width,chainDesc.BufferDesc.Height); } result=swapchain->GetBuffer(0,IID_PPV_ARGS(&screen)); @@ -133,6 +134,7 @@ bool FurnaceGUIRenderDX11::createRenderTarget() { return false; } + screen->Release(); return true; } @@ -245,7 +247,11 @@ void FurnaceGUIRenderDX11::setBlendMode(FurnaceGUIBlendMode mode) { void FurnaceGUIRenderDX11::resized(const SDL_Event& ev) { destroyRenderTarget(); - swapchain->ResizeBuffers(0,(unsigned int)ev.window.data1,(unsigned int)ev.window.data2,DXGI_FORMAT_UNKNOWN,DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH); + logI("DX11: resizing buffers"); + HRESULT result=swapchain->ResizeBuffers(0,(unsigned int)ev.window.data1,(unsigned int)ev.window.data2,DXGI_FORMAT_UNKNOWN,DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH); + if (result!=S_OK) { + logW("error while resizing swapchain buffers! %.8x",result); + } createRenderTarget(); } From db14ce602d1901642b940730727edce62ae87306 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 13 Jun 2023 04:16:19 -0500 Subject: [PATCH 09/13] why are you not showing me the return value I want to see what's going on --- src/gui/render/renderDX11.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/render/renderDX11.cpp b/src/gui/render/renderDX11.cpp index 5f7e70d6..452b8180 100644 --- a/src/gui/render/renderDX11.cpp +++ b/src/gui/render/renderDX11.cpp @@ -152,7 +152,7 @@ bool FurnaceGUIRenderDX11::lockTexture(void* which, void** data, int* pitch) { HRESULT result=context->Map(t->tex,D3D11CalcSubresource(0,0,1),D3D11_MAP_WRITE,0,&mappedRes); if (result!=S_OK) { - logW("could not map texture!"); + logW("could not map texture! %.8x",result); return false; } t->lockedData=(unsigned char*)mappedRes.pData; From 8ee4734eabaef61223f434a02919d31351893d82 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 13 Jun 2023 04:24:34 -0500 Subject: [PATCH 10/13] DISCARD --- src/gui/render/renderDX11.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/render/renderDX11.cpp b/src/gui/render/renderDX11.cpp index 452b8180..ea6aac78 100644 --- a/src/gui/render/renderDX11.cpp +++ b/src/gui/render/renderDX11.cpp @@ -150,7 +150,7 @@ bool FurnaceGUIRenderDX11::lockTexture(void* which, void** data, int* pitch) { D3D11_MAPPED_SUBRESOURCE mappedRes; memset(&mappedRes,0,sizeof(mappedRes)); - HRESULT result=context->Map(t->tex,D3D11CalcSubresource(0,0,1),D3D11_MAP_WRITE,0,&mappedRes); + HRESULT result=context->Map(t->tex,D3D11CalcSubresource(0,0,1),D3D11_MAP_WRITE_DISCARD,0,&mappedRes); if (result!=S_OK) { logW("could not map texture! %.8x",result); return false; From 1ffa80e84594092540c02563cfa5f74a070d6f6d Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 13 Jun 2023 04:38:13 -0500 Subject: [PATCH 11/13] and one more piece of code --- src/gui/render/renderDX11.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/render/renderDX11.cpp b/src/gui/render/renderDX11.cpp index ea6aac78..e7ea0910 100644 --- a/src/gui/render/renderDX11.cpp +++ b/src/gui/render/renderDX11.cpp @@ -158,6 +158,8 @@ bool FurnaceGUIRenderDX11::lockTexture(void* which, void** data, int* pitch) { t->lockedData=(unsigned char*)mappedRes.pData; *data=mappedRes.pData; *pitch=mappedRes.RowPitch; + + logV("texture locked... pitch: %d",mappedRes.RowPitch); return true; } From 6933446d8a5d69d6f2470b10798c71c568ca512f Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 13 Jun 2023 05:45:36 -0500 Subject: [PATCH 12/13] GUI: DirectX 11 render backend, part 7 now with texture workaround --- src/gui/sampleEdit.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/gui/sampleEdit.cpp b/src/gui/sampleEdit.cpp index 8f5a9843..5d2e1d9f 100644 --- a/src/gui/sampleEdit.cpp +++ b/src/gui/sampleEdit.cpp @@ -1231,7 +1231,17 @@ void FurnaceGUI::drawSampleEdit() { } } - memcpy(dataT,data,sampleTexW*sampleTexH*sizeof(unsigned int)); + if ((pitch>>2)==sampleTexW) { + memcpy(dataT,data,sampleTexW*sampleTexH*sizeof(unsigned int)); + } else { + int srcY=0; + int destY=0; + for (int i=0; i>2; + } + } rend->unlockTexture(sampleTex); delete[] data; } From 83ad6e08941b556410d590ab06029ddf16fd3e62 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 14 Jun 2023 14:50:39 -0500 Subject: [PATCH 13/13] GUI: DirectX 11 render backend, part 8 updateTexture for dynamic textures --- src/gui/render/renderDX11.cpp | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/gui/render/renderDX11.cpp b/src/gui/render/renderDX11.cpp index e7ea0910..b860890f 100644 --- a/src/gui/render/renderDX11.cpp +++ b/src/gui/render/renderDX11.cpp @@ -74,12 +74,14 @@ struct FurnaceDXTexture { ID3D11ShaderResourceView* view; int width, height; unsigned char* lockedData; + bool dynamic; FurnaceDXTexture(): tex(NULL), view(NULL), width(0), height(0), - lockedData(NULL) {} + lockedData(NULL), + dynamic(false) {} }; bool FurnaceGUIRenderDX11::destroyRenderTarget() { @@ -173,7 +175,26 @@ bool FurnaceGUIRenderDX11::unlockTexture(void* which) { bool FurnaceGUIRenderDX11::updateTexture(void* which, void* data, int pitch) { FurnaceDXTexture* t=(FurnaceDXTexture*)which; - context->UpdateSubresource(t->tex,D3D11CalcSubresource(0,0,1),NULL,data,pitch,pitch*t->height); + if (t->dynamic) { + unsigned char* d=NULL; + int p=0; + if (!lockTexture(t,&d,&p)) return false; + if (p==pitch) { + memcpy(d,data,p*t->height); + } else { + unsigned char* ucData=(unsigned char*)data; + int srcPos=0; + int destPos=0; + for (int i=0; iheight; i++) { + memcpy(&d[destPos],&ucData[srcPos],pitch); + srcPos+=pitch; + destPos+=p; + } + } + unlockTexture(t); + } else { + context->UpdateSubresource(t->tex,D3D11CalcSubresource(0,0,1),NULL,data,pitch,pitch*t->height); + } return true; } @@ -222,6 +243,7 @@ void* FurnaceGUIRenderDX11::createTexture(bool dynamic, int width, int height) { ret->height=height; ret->tex=tex; ret->view=view; + ret->dynamic=dynamic; textures.push_back(ret); return ret; }