diff --git a/CMakeLists.txt b/CMakeLists.txt index 1686bc77c..73c7f4d87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -930,7 +930,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) + list(APPEND DEPENDENCIES_LIBRARIES d3d11 dxgi) message(STATUS "UI render backend: DirectX 11") endif() else() diff --git a/extern/imgui_software_renderer/imgui_sw.cpp b/extern/imgui_software_renderer/imgui_sw.cpp index b13a94c21..7721fffe1 100644 --- a/extern/imgui_software_renderer/imgui_sw.cpp +++ b/extern/imgui_software_renderer/imgui_sw.cpp @@ -46,10 +46,14 @@ namespace { // ---------------------------------------------------------------------------- #pragma pack(push, 1) - struct ColorInt + union ColorInt { - uint8_t r, g, b, a = 0; - ColorInt(const std::string &) {} + struct { + uint8_t r, g, b, a; + }; + uint32_t u32; + ColorInt(): + u32(0) {} ColorInt &operator*=(const ColorInt &other) diff --git a/src/gui/gui.h b/src/gui/gui.h index 41cc28128..f885b7d2b 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1460,6 +1460,12 @@ class FurnaceGUIRender { virtual bool supportsDrawOsc(); virtual bool getOutputSize(int& w, int& h); virtual int getWindowFlags(); + virtual int getMaxTextureWidth(); + virtual int getMaxTextureHeight(); + virtual const char* getBackendName(); + virtual const char* getVendorName(); + virtual const char* getDeviceName(); + virtual const char* getAPIVersion(); virtual void setSwapInterval(int swapInterval); virtual void preInit(); virtual bool init(SDL_Window* win, int swapInterval); diff --git a/src/gui/render.cpp b/src/gui/render.cpp index 60e0c83c6..6e0b58246 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -36,6 +36,8 @@ bool FurnaceGUI::initRender() { if (rend!=NULL) return false; + logV("requested backend: %s",settings.renderBackend); + if (safeMode) { renderBackend=GUI_BACKEND_SDL; } else if (settings.renderBackend=="OpenGL" || settings.renderBackend=="OpenGL 3.0" || settings.renderBackend=="OpenGL ES 2.0") { diff --git a/src/gui/render/abstract.cpp b/src/gui/render/abstract.cpp index 8a3ebcc82..c8d9be046 100644 --- a/src/gui/render/abstract.cpp +++ b/src/gui/render/abstract.cpp @@ -101,6 +101,30 @@ int FurnaceGUIRender::getWindowFlags() { return 0; } +int FurnaceGUIRender::getMaxTextureWidth() { + return 0; +} + +int FurnaceGUIRender::getMaxTextureHeight() { + return 0; +} + +const char* FurnaceGUIRender::getBackendName() { + return "Dummy"; +} + +const char* FurnaceGUIRender::getVendorName() { + return "N/A"; +} + +const char* FurnaceGUIRender::getDeviceName() { + return "N/A"; +} + +const char* FurnaceGUIRender::getAPIVersion() { + return "N/A"; +} + void FurnaceGUIRender::setSwapInterval(int swapInterval) { } diff --git a/src/gui/render/renderDX11.cpp b/src/gui/render/renderDX11.cpp index f103d5041..83ef53520 100644 --- a/src/gui/render/renderDX11.cpp +++ b/src/gui/render/renderDX11.cpp @@ -22,6 +22,7 @@ #include #include "backends/imgui_impl_dx11.h" #include "../../ta-log.h" +#include "../../utfutils.h" typedef HRESULT (__stdcall *D3DCompile_t)(LPCVOID,SIZE_T,LPCSTR,D3D_SHADER_MACRO*,ID3DInclude*,LPCSTR,LPCSTR,UINT,UINT,ID3DBlob**,ID3DBlob*); @@ -368,6 +369,30 @@ int FurnaceGUIRenderDX11::getWindowFlags() { return 0; } +int FurnaceGUIRenderDX11::getMaxTextureWidth() { + return maxWidth; +} + +int FurnaceGUIRenderDX11::getMaxTextureHeight() { + return maxHeight; +} + +const char* FurnaceGUIRenderDX11::getBackendName() { + return "DirectX 11"; +} + +const char* FurnaceGUIRenderDX11::getVendorName() { + return vendorName.c_str(); +} + +const char* FurnaceGUIRenderDX11::getDeviceName() { + return deviceName.c_str(); +} + +const char* FurnaceGUIRenderDX11::getAPIVersion() { + return apiVersion.c_str(); +} + void FurnaceGUIRenderDX11::setSwapInterval(int swapInt) { swapInterval=swapInt; } @@ -393,6 +418,7 @@ bool FurnaceGUIRenderDX11::init(SDL_Window* win, int swapInt) { } HWND window=(HWND)sysWindow.info.win.window; + // prepare swapchain swapInterval=swapInt; DXGI_SWAP_CHAIN_DESC chainDesc; @@ -411,12 +437,51 @@ bool FurnaceGUIRenderDX11::init(SDL_Window* win, int swapInt) { chainDesc.SwapEffect=DXGI_SWAP_EFFECT_DISCARD; chainDesc.Flags=DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + // initialize 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; } + IDXGIDevice* giDevice=NULL; + IDXGIAdapter* adapter=NULL; + + result=device->QueryInterface(__uuidof(IDXGIDevice),(void**)&giDevice); + if (result==S_OK) { + result=giDevice->GetAdapter(&adapter); + if (result==S_OK) { + DXGI_ADAPTER_DESC adapterDesc; + + result=adapter->GetDesc(&adapterDesc); + if (result!=S_OK) { + logE("could not get adapter info! %.8x",result); + } else { + deviceName=utf16To8(adapterDesc.Description); + vendorName=fmt::sprintf("%.4x:%.4x",adapterDesc.VendorId,adapterDesc.DeviceId); + logV("device: %s",deviceName); + } + } else { + logE("could not get adapter! %.8x",result); + logE("won't be able to get adapter info..."); + } + } else { + logE("could not query interface! %.8x",result); + logE("won't be able to get adapter info..."); + } + + if (featureLevel>=0xb000) { + maxWidth=16384; + maxHeight=16384; + } else if (featureLevel>=0xa000) { + maxWidth=8192; + maxHeight=8192; + } else { + maxWidth=4096; + maxHeight=4096; + } + apiVersion=fmt::sprintf("%d.%d",((int)featureLevel)>>12,((int)featureLevel)>>8); + // https://github.com/ocornut/imgui/pull/638 D3DCompile_t D3DCompile=NULL; char dllBuffer[20]; diff --git a/src/gui/render/renderDX11.h b/src/gui/render/renderDX11.h index eda263ed5..eba32218c 100644 --- a/src/gui/render/renderDX11.h +++ b/src/gui/render/renderDX11.h @@ -56,6 +56,9 @@ class FurnaceGUIRenderDX11: public FurnaceGUIRender { float padding[7]; }; + int maxWidth, maxHeight; + String vendorName, deviceName, apiVersion; + bool destroyRenderTarget(); bool createRenderTarget(); @@ -79,6 +82,12 @@ class FurnaceGUIRenderDX11: public FurnaceGUIRender { void present(); bool getOutputSize(int& w, int& h); int getWindowFlags(); + int getMaxTextureWidth(); + int getMaxTextureHeight(); + const char* getBackendName(); + const char* getVendorName(); + const char* getDeviceName(); + const char* getAPIVersion(); void setSwapInterval(int swapInterval); void preInit(); bool init(SDL_Window* win, int swapInterval); @@ -101,6 +110,8 @@ class FurnaceGUIRenderDX11: public FurnaceGUIRender { sh_wipe_vertex(NULL), sh_wipe_fragment(NULL), sh_wipe_inputLayout(NULL), - sh_wipe_uniform(NULL) { + sh_wipe_uniform(NULL), + maxWidth(8192), + maxHeight(8192) { } }; diff --git a/src/gui/render/renderGL.cpp b/src/gui/render/renderGL.cpp index f83380a1e..a2986aef7 100644 --- a/src/gui/render/renderGL.cpp +++ b/src/gui/render/renderGL.cpp @@ -546,6 +546,30 @@ int FurnaceGUIRenderGL::getWindowFlags() { return SDL_WINDOW_OPENGL; } +int FurnaceGUIRenderGL::getMaxTextureWidth() { + return maxWidth; +} + +int FurnaceGUIRenderGL::getMaxTextureHeight() { + return maxHeight; +} + +const char* FurnaceGUIRenderGL::getBackendName() { + return backendName.c_str(); +} + +const char* FurnaceGUIRenderGL::getVendorName() { + return vendorName.c_str(); +} + +const char* FurnaceGUIRenderGL::getDeviceName() { + return deviceName.c_str(); +} + +const char* FurnaceGUIRenderGL::getAPIVersion() { + return apiVersion.c_str(); +} + void FurnaceGUIRenderGL::setSwapInterval(int swapInterval) { SDL_GL_SetSwapInterval(swapInterval); if (swapInterval>0 && SDL_GL_GetSwapInterval()==0) { @@ -640,8 +664,36 @@ bool FurnaceGUIRenderGL::init(SDL_Window* win, int swapInterval) { #ifndef USE_GLES LOAD_PROC_OPTIONAL(furGetGraphicsResetStatusARB,PFNGLGETGRAPHICSRESETSTATUSARBPROC,"glGetGraphicsResetStatusARB"); +#else + backendName="OpenGL ES 2.0"; #endif + // information + const char* next=(const char*)glGetString(GL_VENDOR); + if (next==NULL) { + vendorName="???"; + } else { + vendorName=next; + } + next=(const char*)glGetString(GL_RENDERER); + if (next==NULL) { + deviceName="???"; + } else { + deviceName=next; + } + next=(const char*)glGetString(GL_VERSION); + if (next==NULL) { + apiVersion="???"; + } else { + apiVersion=next; + } + + int maxSize=1024; + glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxSize); + + maxWidth=maxSize; + maxHeight=maxSize; + // texture for osc renderer if (glVer==3) { C(glGenTextures(1,&oscDataTex)); @@ -725,4 +777,11 @@ bool FurnaceGUIRenderGL::isDead() { void FurnaceGUIRenderGL::setVersion(unsigned char ver) { glVer=ver; + if (glVer==3) { + backendName="OpenGL 3.0"; + } else if (glVer==2) { + backendName="OpenGL 2.0"; + } else { + backendName="OpenGL BUG.REPORT"; + } } diff --git a/src/gui/render/renderGL.h b/src/gui/render/renderGL.h index 7c0179a9d..eb452eb9a 100644 --- a/src/gui/render/renderGL.h +++ b/src/gui/render/renderGL.h @@ -49,6 +49,9 @@ class FurnaceGUIRenderGL: public FurnaceGUIRender { bool swapIntervalSet; unsigned char glVer; + int maxWidth, maxHeight; + String backendName, vendorName, deviceName, apiVersion; + bool createShader(const char* vertexS, const char* fragmentS, int& vertex, int& fragment, int& program, const char** attribNames); public: @@ -72,6 +75,12 @@ class FurnaceGUIRenderGL: public FurnaceGUIRender { bool getOutputSize(int& w, int& h); bool supportsDrawOsc(); int getWindowFlags(); + int getMaxTextureWidth(); + int getMaxTextureHeight(); + const char* getBackendName(); + const char* getVendorName(); + const char* getDeviceName(); + const char* getAPIVersion(); void setSwapInterval(int swapInterval); void preInit(); bool init(SDL_Window* win, int swapInterval); @@ -83,7 +92,11 @@ class FurnaceGUIRenderGL: public FurnaceGUIRender { FurnaceGUIRenderGL(): context(NULL), sdlWin(NULL), - swapIntervalSet(true) { + swapIntervalSet(true), + glVer(3), + maxWidth(0), + maxHeight(0), + backendName("What?") { memset(quadVertex,0,4*3*sizeof(float)); memset(oscVertex,0,4*5*sizeof(float)); memset(oscData,0,2048*sizeof(float)); diff --git a/src/gui/render/renderGL1.cpp b/src/gui/render/renderGL1.cpp index 71c52f389..1ce8e054f 100644 --- a/src/gui/render/renderGL1.cpp +++ b/src/gui/render/renderGL1.cpp @@ -211,6 +211,30 @@ int FurnaceGUIRenderGL1::getWindowFlags() { return SDL_WINDOW_OPENGL; } +int FurnaceGUIRenderGL1::getMaxTextureWidth() { + return maxWidth; +} + +int FurnaceGUIRenderGL1::getMaxTextureHeight() { + return maxHeight; +} + +const char* FurnaceGUIRenderGL1::getBackendName() { + return "OpenGL 1.1"; +} + +const char* FurnaceGUIRenderGL1::getVendorName() { + return vendorName.c_str(); +} + +const char* FurnaceGUIRenderGL1::getDeviceName() { + return deviceName.c_str(); +} + +const char* FurnaceGUIRenderGL1::getAPIVersion() { + return apiVersion.c_str(); +} + void FurnaceGUIRenderGL1::setSwapInterval(int swapInterval) { SDL_GL_SetSwapInterval(swapInterval); if (swapInterval>0 && SDL_GL_GetSwapInterval()==0) { @@ -263,6 +287,31 @@ bool FurnaceGUIRenderGL1::init(SDL_Window* win, int swapInterval) { swapIntervalSet=true; } + const char* next=(const char*)glGetString(GL_VENDOR); + if (next==NULL) { + vendorName="???"; + } else { + vendorName=next; + } + next=(const char*)glGetString(GL_RENDERER); + if (next==NULL) { + deviceName="???"; + } else { + deviceName=next; + } + next=(const char*)glGetString(GL_VERSION); + if (next==NULL) { + apiVersion="???"; + } else { + apiVersion=next; + } + + int maxSize=1024; + glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxSize); + + maxWidth=maxSize; + maxHeight=maxSize; + return true; } diff --git a/src/gui/render/renderGL1.h b/src/gui/render/renderGL1.h index 29d9837fe..d80ca073b 100644 --- a/src/gui/render/renderGL1.h +++ b/src/gui/render/renderGL1.h @@ -24,7 +24,9 @@ class FurnaceGUIRenderGL1: public FurnaceGUIRender { SDL_Window* sdlWin; bool swapIntervalSet; - unsigned char glVer; + + int maxWidth, maxHeight; + String vendorName, deviceName, apiVersion; public: ImTextureID getTextureID(FurnaceGUITexture* which); @@ -47,6 +49,12 @@ class FurnaceGUIRenderGL1: public FurnaceGUIRender { void present(); bool getOutputSize(int& w, int& h); int getWindowFlags(); + int getMaxTextureWidth(); + int getMaxTextureHeight(); + const char* getBackendName(); + const char* getVendorName(); + const char* getDeviceName(); + const char* getAPIVersion(); void setSwapInterval(int swapInterval); void preInit(); bool init(SDL_Window* win, int swapInterval); @@ -57,6 +65,8 @@ class FurnaceGUIRenderGL1: public FurnaceGUIRender { FurnaceGUIRenderGL1(): context(NULL), sdlWin(NULL), - swapIntervalSet(true) { + swapIntervalSet(true), + maxWidth(0), + maxHeight(0) { } }; diff --git a/src/gui/render/renderSDL.cpp b/src/gui/render/renderSDL.cpp index dca54c3b6..7adfe62e5 100644 --- a/src/gui/render/renderSDL.cpp +++ b/src/gui/render/renderSDL.cpp @@ -146,6 +146,33 @@ int FurnaceGUIRenderSDL::getWindowFlags() { return 0; } +int FurnaceGUIRenderSDL::getMaxTextureWidth() { + if (!hasInfo) return 2048; + return renderInfo.max_texture_width; +} + +int FurnaceGUIRenderSDL::getMaxTextureHeight() { + if (!hasInfo) return 2048; + return renderInfo.max_texture_height; +} + +const char* FurnaceGUIRenderSDL::getBackendName() { + return "SDL Renderer"; +} + +const char* FurnaceGUIRenderSDL::getVendorName() { + return "SDL"; +} + +const char* FurnaceGUIRenderSDL::getDeviceName() { + if (!hasInfo) return "???"; + return renderInfo.name; +} + +const char* FurnaceGUIRenderSDL::getAPIVersion() { + return "N/A"; +} + void FurnaceGUIRenderSDL::setSwapInterval(int swapInterval) { if (SDL_RenderSetVSync(sdlRend,(swapInterval>=0)?1:0)!=0) { swapIntervalSet=false; @@ -161,6 +188,13 @@ void FurnaceGUIRenderSDL::preInit() { bool FurnaceGUIRenderSDL::init(SDL_Window* win, int swapInterval) { logV("creating SDL renderer..."); sdlRend=SDL_CreateRenderer(win,-1,SDL_RENDERER_ACCELERATED|((swapInterval>0)?SDL_RENDERER_PRESENTVSYNC:0)|SDL_RENDERER_TARGETTEXTURE); + if (sdlRend==NULL) return false; + if (SDL_GetRendererInfo(sdlRend,&renderInfo)==0) { + hasInfo=true; + } else { + logE("could not get renderer info! %s",SDL_GetError()); + hasInfo=false; + } if (SDL_RenderSetVSync(sdlRend,(swapInterval>=0)?1:0)!=0) { swapIntervalSet=false; logW("tried to enable VSync but couldn't!"); diff --git a/src/gui/render/renderSDL.h b/src/gui/render/renderSDL.h index 898638ebf..370b11289 100644 --- a/src/gui/render/renderSDL.h +++ b/src/gui/render/renderSDL.h @@ -21,6 +21,8 @@ class FurnaceGUIRenderSDL: public FurnaceGUIRender { SDL_Renderer* sdlRend; + SDL_RendererInfo renderInfo; + bool hasInfo; bool swapIntervalSet; public: ImTextureID getTextureID(FurnaceGUITexture* which); @@ -41,6 +43,12 @@ class FurnaceGUIRenderSDL: public FurnaceGUIRender { void present(); bool getOutputSize(int& w, int& h); int getWindowFlags(); + int getMaxTextureWidth(); + int getMaxTextureHeight(); + const char* getBackendName(); + const char* getVendorName(); + const char* getDeviceName(); + const char* getAPIVersion(); void setSwapInterval(int swapInterval); void preInit(); bool init(SDL_Window* win, int swapInterval); @@ -49,5 +57,6 @@ class FurnaceGUIRenderSDL: public FurnaceGUIRender { bool quit(); FurnaceGUIRenderSDL(): sdlRend(NULL), + hasInfo(false), swapIntervalSet(true) {} }; diff --git a/src/gui/render/renderSoftware.cpp b/src/gui/render/renderSoftware.cpp index 161903a92..d3078e8b5 100644 --- a/src/gui/render/renderSoftware.cpp +++ b/src/gui/render/renderSoftware.cpp @@ -118,6 +118,30 @@ int FurnaceGUIRenderSoftware::getWindowFlags() { return 0; } +int FurnaceGUIRenderSoftware::getMaxTextureWidth() { + return 16384; +} + +int FurnaceGUIRenderSoftware::getMaxTextureHeight() { + return 16384; +} + +const char* FurnaceGUIRenderSoftware::getBackendName() { + return "Software"; +} + +const char* FurnaceGUIRenderSoftware::getVendorName() { + return "emilk, JesusKrists and tildearrow"; +} + +const char* FurnaceGUIRenderSoftware::getDeviceName() { + return "imgui_sw Software Renderer"; +} + +const char* FurnaceGUIRenderSoftware::getAPIVersion() { + return "N/A"; +} + void FurnaceGUIRenderSoftware::setSwapInterval(int swapInterval) { } diff --git a/src/gui/render/renderSoftware.h b/src/gui/render/renderSoftware.h index 7d96883e7..498dec69a 100644 --- a/src/gui/render/renderSoftware.h +++ b/src/gui/render/renderSoftware.h @@ -40,6 +40,12 @@ class FurnaceGUIRenderSoftware: public FurnaceGUIRender { void present(); bool getOutputSize(int& w, int& h); int getWindowFlags(); + int getMaxTextureWidth(); + int getMaxTextureHeight(); + const char* getBackendName(); + const char* getVendorName(); + const char* getDeviceName(); + const char* getAPIVersion(); void setSwapInterval(int swapInterval); void preInit(); bool init(SDL_Window* win, int swapInterval); diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index ad9cc45fa..4a01c8513 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -456,6 +456,8 @@ void FurnaceGUI::drawSettings() { } } + ImGui::TextWrapped("current backend: %s\n%s\n%s\n%s",rend->getBackendName(),rend->getVendorName(),rend->getDeviceName(),rend->getAPIVersion()); + bool vsyncB=settings.vsync; if (ImGui::Checkbox("VSync",&vsyncB)) { settings.vsync=vsyncB;