Settings: Add option for creating a debug GPU device

This commit is contained in:
Connor McLaughlin 2020-01-19 14:53:49 +10:00
parent 8378e5ed0d
commit b9538a55f5
14 changed files with 62 additions and 82 deletions

View file

@ -17,6 +17,7 @@ void Settings::SetDefaults()
gpu_true_color = true;
gpu_texture_filtering = false;
gpu_force_progressive_scan = true;
gpu_use_debug_device = false;
display_linear_filtering = true;
display_fullscreen = false;
video_sync_enabled = true;
@ -51,6 +52,7 @@ void Settings::Load(SettingsInterface& si)
gpu_resolution_scale = static_cast<u32>(si.GetIntValue("GPU", "ResolutionScale", 1));
gpu_true_color = si.GetBoolValue("GPU", "TrueColor", false);
gpu_texture_filtering = si.GetBoolValue("GPU", "TextureFiltering", false);
gpu_use_debug_device = si.GetBoolValue("GPU", "UseDebugDevice", false);
display_linear_filtering = si.GetBoolValue("Display", "LinearFiltering", true);
display_fullscreen = si.GetBoolValue("Display", "Fullscreen", false);
@ -86,6 +88,7 @@ void Settings::Save(SettingsInterface& si) const
si.SetIntValue("GPU", "ResolutionScale", static_cast<long>(gpu_resolution_scale));
si.SetBoolValue("GPU", "TrueColor", gpu_true_color);
si.SetBoolValue("GPU", "TextureFiltering", gpu_texture_filtering);
si.SetBoolValue("GPU", "UseDebugDevice", gpu_use_debug_device);
si.SetBoolValue("Display", "LinearFiltering", display_linear_filtering);
si.SetBoolValue("Display", "Fullscreen", display_fullscreen);

View file

@ -44,6 +44,7 @@ struct Settings
bool gpu_true_color = false;
bool gpu_texture_filtering = false;
bool gpu_force_progressive_scan = false;
bool gpu_use_debug_device = false;
bool display_linear_filtering = true;
bool display_fullscreen = false;
bool video_sync_enabled = true;

View file

@ -192,10 +192,8 @@ void D3D11DisplayWindow::onWindowResized(int width, int height)
Panic("Failed to recreate swap chain RTV after resize");
}
bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread)
bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread, bool debug_device)
{
const bool debug = false;
ComPtr<IDXGIFactory> dxgi_factory;
HRESULT hr = CreateDXGIFactory(IID_PPV_ARGS(dxgi_factory.GetAddressOf()));
if (FAILED(hr))
@ -217,7 +215,7 @@ bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread)
}
UINT create_flags = 0;
if (debug)
if (debug_device)
create_flags |= D3D11_CREATE_DEVICE_DEBUG;
hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, create_flags, nullptr, 0, D3D11_SDK_VERSION,
@ -259,7 +257,7 @@ bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread)
}
}
if (debug)
if (debug_device)
{
ComPtr<ID3D11InfoQueue> info;
hr = m_device.As(&info);
@ -270,7 +268,7 @@ bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread)
}
}
if (!QtDisplayWindow::createDeviceContext(worker_thread))
if (!QtDisplayWindow::createDeviceContext(worker_thread, debug_device))
{
m_swap_chain.Reset();
m_context.Reset();
@ -280,12 +278,12 @@ bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread)
return true;
}
bool D3D11DisplayWindow::initializeDeviceContext()
bool D3D11DisplayWindow::initializeDeviceContext(bool debug_device)
{
if (!createSwapChainRTV())
return false;
if (!QtDisplayWindow::initializeDeviceContext())
if (!QtDisplayWindow::initializeDeviceContext(debug_device))
return false;
return true;

View file

@ -21,8 +21,8 @@ public:
HostDisplay* getHostDisplayInterface() override;
bool createDeviceContext(QThread* worker_thread) override;
bool initializeDeviceContext() override;
bool createDeviceContext(QThread* worker_thread, bool debug_device) override;
bool initializeDeviceContext(bool debug_device) override;
void destroyDeviceContext() override;
RenderAPI GetRenderAPI() const override;

View file

@ -234,7 +234,7 @@ static void APIENTRY GLDebugCallback(GLenum source, GLenum type, GLuint id, GLen
}
}
bool OpenGLDisplayWindow::createDeviceContext(QThread* worker_thread)
bool OpenGLDisplayWindow::createDeviceContext(QThread* worker_thread, bool debug_device)
{
m_gl_context = std::make_unique<QOpenGLContext>();
@ -249,9 +249,8 @@ bool OpenGLDisplayWindow::createDeviceContext(QThread* worker_thread)
surface_format.setRenderableType(QSurfaceFormat::OpenGL);
surface_format.setProfile(QSurfaceFormat::CoreProfile);
#ifdef _DEBUG
if (debug_device)
surface_format.setOption(QSurfaceFormat::DebugContext);
#endif
for (const auto [major, minor] : desktop_versions_to_try)
{
@ -269,9 +268,8 @@ bool OpenGLDisplayWindow::createDeviceContext(QThread* worker_thread)
// try es
surface_format.setRenderableType(QSurfaceFormat::OpenGLES);
surface_format.setProfile(QSurfaceFormat::NoProfile);
#ifdef _DEBUG
if (debug_device)
surface_format.setOption(QSurfaceFormat::DebugContext, false);
#endif
for (const auto [major, minor] : es_versions_to_try)
{
@ -300,7 +298,7 @@ bool OpenGLDisplayWindow::createDeviceContext(QThread* worker_thread)
return false;
}
if (!QtDisplayWindow::createDeviceContext(worker_thread))
if (!QtDisplayWindow::createDeviceContext(worker_thread, debug_device))
{
m_gl_context->doneCurrent();
m_gl_context.reset();
@ -312,7 +310,7 @@ bool OpenGLDisplayWindow::createDeviceContext(QThread* worker_thread)
return true;
}
bool OpenGLDisplayWindow::initializeDeviceContext()
bool OpenGLDisplayWindow::initializeDeviceContext(bool debug_device)
{
if (!m_gl_context->makeCurrent(this))
return false;
@ -330,16 +328,14 @@ bool OpenGLDisplayWindow::initializeDeviceContext()
return false;
}
#if 0
if (GLAD_GL_KHR_debug)
if (debug_device && GLAD_GL_KHR_debug)
{
glad_glDebugMessageCallbackKHR(GLDebugCallback, nullptr);
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
}
#endif
if (!QtDisplayWindow::initializeDeviceContext())
if (!QtDisplayWindow::initializeDeviceContext(debug_device))
{
s_thread_gl_context = nullptr;
m_gl_context->doneCurrent();

View file

@ -20,8 +20,8 @@ public:
HostDisplay* getHostDisplayInterface() override;
bool createDeviceContext(QThread* worker_thread) override;
bool initializeDeviceContext() override;
bool createDeviceContext(QThread* worker_thread, bool debug_device) override;
bool initializeDeviceContext(bool debug_device) override;
void destroyDeviceContext() override;
RenderAPI GetRenderAPI() const override;

View file

@ -18,12 +18,12 @@ HostDisplay* QtDisplayWindow::getHostDisplayInterface()
return nullptr;
}
bool QtDisplayWindow::createDeviceContext(QThread* worker_thread)
bool QtDisplayWindow::createDeviceContext(QThread* worker_thread, bool debug_device)
{
return true;
}
bool QtDisplayWindow::initializeDeviceContext()
bool QtDisplayWindow::initializeDeviceContext(bool debug_device)
{
if (!createImGuiContext() || !createDeviceResources())
return false;

View file

@ -18,8 +18,8 @@ public:
virtual HostDisplay* getHostDisplayInterface();
virtual bool createDeviceContext(QThread* worker_thread);
virtual bool initializeDeviceContext();
virtual bool createDeviceContext(QThread* worker_thread, bool debug_device);
virtual bool initializeDeviceContext(bool debug_device);
virtual void destroyDeviceContext();
virtual void Render();

View file

@ -150,7 +150,7 @@ void QtHostInterface::bootSystem(QString initial_filename, QString initial_save_
Assert(!isOnWorkerThread());
emit emulationStarting();
if (!m_display_window->createDeviceContext(m_worker_thread))
if (!m_display_window->createDeviceContext(m_worker_thread, m_settings.gpu_use_debug_device))
{
emit emulationStopped();
return;
@ -420,7 +420,7 @@ QByteArray QtHostInterface::saveStateToMemory()
void QtHostInterface::doBootSystem(QString initial_filename, QString initial_save_state_filename)
{
if (!m_display_window->initializeDeviceContext())
if (!m_display_window->initializeDeviceContext(m_settings.gpu_use_debug_device))
{
emit emulationStopped();
return;

View file

@ -190,10 +190,8 @@ void D3D11HostDisplay::WindowResized()
Panic("Failed to recreate swap chain RTV after resize");
}
bool D3D11HostDisplay::CreateD3DDevice()
bool D3D11HostDisplay::CreateD3DDevice(bool debug_device)
{
const bool debug = false;
SDL_SysWMinfo syswm = {};
if (!SDL_GetWindowWMInfo(m_window, &syswm))
{
@ -222,7 +220,7 @@ bool D3D11HostDisplay::CreateD3DDevice()
}
UINT create_flags = 0;
if (debug)
if (debug_device)
create_flags |= D3D11_CREATE_DEVICE_DEBUG;
hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, create_flags, nullptr, 0, D3D11_SDK_VERSION,
@ -264,7 +262,7 @@ bool D3D11HostDisplay::CreateD3DDevice()
}
}
if (debug)
if (debug_device)
{
ComPtr<ID3D11InfoQueue> info;
hr = m_device.As(&info);
@ -386,10 +384,10 @@ bool D3D11HostDisplay::CreateImGuiContext()
return true;
}
std::unique_ptr<HostDisplay> D3D11HostDisplay::Create(SDL_Window* window)
std::unique_ptr<HostDisplay> D3D11HostDisplay::Create(SDL_Window* window, bool debug_device)
{
std::unique_ptr<D3D11HostDisplay> display = std::make_unique<D3D11HostDisplay>(window);
if (!display->CreateD3DDevice() || !display->CreateSwapChainRTV() || !display->CreateD3DResources() ||
if (!display->CreateD3DDevice(debug_device) || !display->CreateSwapChainRTV() || !display->CreateD3DResources() ||
!display->CreateImGuiContext())
{
return nullptr;

View file

@ -17,7 +17,7 @@ public:
D3D11HostDisplay(SDL_Window* window);
~D3D11HostDisplay();
static std::unique_ptr<HostDisplay> Create(SDL_Window* window);
static std::unique_ptr<HostDisplay> Create(SDL_Window* window, bool debug_device);
RenderAPI GetRenderAPI() const override;
void* GetRenderDevice() const override;
@ -44,7 +44,7 @@ public:
private:
static constexpr u32 DISPLAY_UNIFORM_BUFFER_SIZE = 16;
bool CreateD3DDevice();
bool CreateD3DDevice(bool debug_device);
bool CreateD3DResources();
bool CreateSwapChainRTV();
bool CreateImGuiContext();

View file

@ -203,7 +203,7 @@ static void APIENTRY GLDebugCallback(GLenum source, GLenum type, GLuint id, GLen
}
}
bool OpenGLHostDisplay::CreateGLContext()
bool OpenGLHostDisplay::CreateGLContext(bool debug_device)
{
// Prefer a desktop OpenGL context where possible. If we can't get this, try OpenGL ES.
static constexpr std::array<std::tuple<int, int>, 11> desktop_versions_to_try = {
@ -212,9 +212,8 @@ bool OpenGLHostDisplay::CreateGLContext()
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
#ifdef _DEBUG
if (debug_device)
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
#endif
for (const auto [major, minor] : desktop_versions_to_try)
{
@ -267,16 +266,13 @@ bool OpenGLHostDisplay::CreateGLContext()
return false;
}
#if 0
if (GLAD_GL_KHR_debug)
if (debug_device && GLAD_GL_KHR_debug)
{
glad_glDebugMessageCallbackKHR(GLDebugCallback, nullptr);
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
}
#endif
SDL_GL_SetSwapInterval(0);
return true;
}
@ -350,10 +346,10 @@ void main()
return true;
}
std::unique_ptr<HostDisplay> OpenGLHostDisplay::Create(SDL_Window* window)
std::unique_ptr<HostDisplay> OpenGLHostDisplay::Create(SDL_Window* window, bool debug_device)
{
std::unique_ptr<OpenGLHostDisplay> display = std::make_unique<OpenGLHostDisplay>(window);
if (!display->CreateGLContext() || !display->CreateImGuiContext() || !display->CreateGLResources())
if (!display->CreateGLContext(debug_device) || !display->CreateImGuiContext() || !display->CreateGLResources())
return nullptr;
return display;

View file

@ -12,7 +12,7 @@ public:
OpenGLHostDisplay(SDL_Window* window);
~OpenGLHostDisplay();
static std::unique_ptr<HostDisplay> Create(SDL_Window* window);
static std::unique_ptr<HostDisplay> Create(SDL_Window* window, bool debug_device);
RenderAPI GetRenderAPI() const override;
void* GetRenderDevice() const override;
@ -40,7 +40,7 @@ private:
const char* GetGLSLVersionString() const;
std::string GetGLSLVersionHeader() const;
bool CreateGLContext();
bool CreateGLContext(bool debug_device);
bool CreateImGuiContext();
bool CreateGLResources();

View file

@ -85,10 +85,12 @@ void SDLHostInterface::DestroySDLWindow()
bool SDLHostInterface::CreateDisplay()
{
const bool debug_device = m_settings.gpu_use_debug_device;
#ifdef WIN32
m_display = UseOpenGLRenderer() ? OpenGLHostDisplay::Create(m_window) : D3D11HostDisplay::Create(m_window);
m_display = UseOpenGLRenderer() ? OpenGLHostDisplay::Create(m_window, debug_device) :
D3D11HostDisplay::Create(m_window, debug_device);
#else
m_display = OpenGLHostDisplay::Create(m_window);
m_display = OpenGLHostDisplay::Create(m_window, debug_device);
#endif
if (!m_display)
@ -296,8 +298,7 @@ void SDLHostInterface::HandleSDLEvent(const SDL_Event* event)
switch (event->type)
{
case SDL_WINDOWEVENT:
{
case SDL_WINDOWEVENT: {
if (event->window.event == SDL_WINDOWEVENT_RESIZED)
m_display->WindowResized();
}
@ -308,22 +309,19 @@ void SDLHostInterface::HandleSDLEvent(const SDL_Event* event)
break;
case SDL_KEYDOWN:
case SDL_KEYUP:
{
case SDL_KEYUP: {
if (!ImGui::GetIO().WantCaptureKeyboard)
HandleSDLKeyEvent(event);
}
break;
case SDL_CONTROLLERDEVICEADDED:
{
case SDL_CONTROLLERDEVICEADDED: {
Log_InfoPrintf("Controller %d inserted", event->cdevice.which);
OpenGameController(event->cdevice.which);
}
break;
case SDL_CONTROLLERDEVICEREMOVED:
{
case SDL_CONTROLLERDEVICEREMOVED: {
Log_InfoPrintf("Controller %d removed", event->cdevice.which);
CloseGameController(event->cdevice.which);
}
@ -334,8 +332,7 @@ void SDLHostInterface::HandleSDLEvent(const SDL_Event* event)
break;
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
{
case SDL_CONTROLLERBUTTONUP: {
if (event->type == SDL_CONTROLLERBUTTONDOWN && event->cbutton.button == SDL_CONTROLLER_BUTTON_RIGHTSTICK)
{
// focus the menu bar
@ -346,8 +343,7 @@ void SDLHostInterface::HandleSDLEvent(const SDL_Event* event)
}
break;
case SDL_USEREVENT:
{
case SDL_USEREVENT: {
if (static_cast<u32>(event->user.code) == m_switch_gpu_renderer_event_id)
SwitchGPURenderer();
}
@ -371,8 +367,7 @@ void SDLHostInterface::HandleSDLKeyEvent(const SDL_Event* event)
case SDL_SCANCODE_F5:
case SDL_SCANCODE_F6:
case SDL_SCANCODE_F7:
case SDL_SCANCODE_F8:
{
case SDL_SCANCODE_F8: {
if (!pressed)
{
const u32 index = event->key.keysym.scancode - SDL_SCANCODE_F1 + 1;
@ -384,15 +379,13 @@ void SDLHostInterface::HandleSDLKeyEvent(const SDL_Event* event)
}
break;
case SDL_SCANCODE_F11:
{
case SDL_SCANCODE_F11: {
if (!pressed)
DoToggleFullscreen();
}
break;
case SDL_SCANCODE_TAB:
{
case SDL_SCANCODE_TAB: {
if (!repeat)
{
m_speed_limiter_temp_disabled = pressed;
@ -401,22 +394,19 @@ void SDLHostInterface::HandleSDLKeyEvent(const SDL_Event* event)
}
break;
case SDL_SCANCODE_PAUSE:
{
case SDL_SCANCODE_PAUSE: {
if (pressed)
DoTogglePause();
}
break;
case SDL_SCANCODE_SPACE:
{
case SDL_SCANCODE_SPACE: {
if (pressed)
DoFrameStep();
}
break;
case SDL_SCANCODE_HOME:
{
case SDL_SCANCODE_HOME: {
if (pressed && !repeat && m_system)
{
m_settings.speed_limiter_enabled = !m_settings.speed_limiter_enabled;
@ -427,16 +417,14 @@ void SDLHostInterface::HandleSDLKeyEvent(const SDL_Event* event)
}
break;
case SDL_SCANCODE_END:
{
case SDL_SCANCODE_END: {
if (pressed)
DoToggleSoftwareRendering();
}
break;
case SDL_SCANCODE_PAGEUP:
case SDL_SCANCODE_PAGEDOWN:
{
case SDL_SCANCODE_PAGEDOWN: {
if (pressed)
{
DoModifyInternalResolution(event->key.keysym.scancode == SDL_SCANCODE_PAGEUP ? 1 : -1);