From d37c04079db6241201ad7ee96a7f24e938e98e9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 30 Oct 2024 23:27:38 +0100 Subject: [PATCH] Change the 2D matrix generation to query the coordinate convention from the draw context --- Common/GPU/D3D11/thin3d_d3d11.cpp | 2 ++ Common/GPU/D3D9/thin3d_d3d9.cpp | 3 +++ Common/GPU/MiscTypes.h | 11 +++++++++ Common/GPU/OpenGL/thin3d_gl.cpp | 1 + Common/GPU/Vulkan/thin3d_vulkan.cpp | 1 + Common/GPU/thin3d.h | 1 + Common/System/Display.cpp | 33 +++++++++++++++++++++++++++ Common/System/Display.h | 3 +++ UI/NativeApp.cpp | 35 +---------------------------- 9 files changed, 56 insertions(+), 34 deletions(-) diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index b4304d1226..52a510dc5c 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -259,6 +259,8 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de // We no longer support Windows Phone. _assert_(featureLevel_ >= D3D_FEATURE_LEVEL_9_3); + caps_.coordConvention = CoordConvention::Direct3D11; + // Seems like a fair approximation... caps_.dualSourceBlend = featureLevel_ >= D3D_FEATURE_LEVEL_10_0; caps_.depthClampSupported = featureLevel_ >= D3D_FEATURE_LEVEL_10_0; diff --git a/Common/GPU/D3D9/thin3d_d3d9.cpp b/Common/GPU/D3D9/thin3d_d3d9.cpp index 3072ed2f50..a7d5d0dc37 100644 --- a/Common/GPU/D3D9/thin3d_d3d9.cpp +++ b/Common/GPU/D3D9/thin3d_d3d9.cpp @@ -717,6 +717,9 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID if (FAILED(d3d->GetAdapterIdentifier(adapterId, 0, &identifier_))) { ERROR_LOG(Log::G3D, "Failed to get adapter identifier: %d", adapterId); } + + caps_.coordConvention = CoordConvention::Direct3D9; + switch (identifier_.VendorId) { case 0x10DE: caps_.vendor = GPUVendor::VENDOR_NVIDIA; break; case 0x1002: diff --git a/Common/GPU/MiscTypes.h b/Common/GPU/MiscTypes.h index 834db32f19..a249145d2e 100644 --- a/Common/GPU/MiscTypes.h +++ b/Common/GPU/MiscTypes.h @@ -2,6 +2,9 @@ #include "Common/Common.h" +#include +#include + // Flags and structs shared between backends that haven't found a good home. enum class InvalidationFlags { @@ -35,3 +38,11 @@ struct FrameTimeData { double presentMargin; }; constexpr size_t FRAME_TIME_HISTORY_LENGTH = 32; + +// Different APIs use different coordinate conventions +enum class CoordConvention { + Direct3D9, + Direct3D11, + Vulkan, + OpenGL, +}; diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 3b149699fe..c9fb9eda47 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -573,6 +573,7 @@ OpenGLContext::OpenGLContext(bool canChangeSwapInterval) : renderManager_(frameT caps_.textureDepthSupported = true; } + caps_.coordConvention = CoordConvention::OpenGL; caps_.setMaxFrameLatencySupported = true; caps_.dualSourceBlend = gl_extensions.ARB_blend_func_extended || gl_extensions.EXT_blend_func_extended; caps_.anisoSupported = gl_extensions.EXT_texture_filter_anisotropic; diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index 5943c197f3..5538d78e54 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -880,6 +880,7 @@ VKContext::VKContext(VulkanContext *vulkan, bool useRenderThread) INFO_LOG(Log::G3D, "Determining Vulkan device caps"); + caps_.coordConvention = CoordConvention::Vulkan; caps_.setMaxFrameLatencySupported = true; caps_.anisoSupported = vulkan->GetDeviceFeatures().enabled.standard.samplerAnisotropy != 0; caps_.geometryShaderSupported = vulkan->GetDeviceFeatures().enabled.standard.geometryShader != 0; diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h index 02241df43a..6dd2a7a3b1 100644 --- a/Common/GPU/thin3d.h +++ b/Common/GPU/thin3d.h @@ -586,6 +586,7 @@ struct DeviceCaps { GPUVendor vendor; uint32_t deviceID; // use caution! + CoordConvention coordConvention; DataFormat preferredDepthBufferFormat; DataFormat preferredShadowMapFormatLow; DataFormat preferredShadowMapFormatHigh; diff --git a/Common/System/Display.cpp b/Common/System/Display.cpp index 15af7de4e3..bc73b466e2 100644 --- a/Common/System/Display.cpp +++ b/Common/System/Display.cpp @@ -2,6 +2,7 @@ #include "Common/System/Display.h" #include "Common/Math/math_util.h" +#include "Common/GPU/MiscTypes.h" DisplayProperties g_display; @@ -66,3 +67,35 @@ void DisplayProperties::Print() { printf("rotation: %d\n", (int)rotation); rot_matrix.print(); } + +Lin::Matrix4x4 ComputeOrthoMatrix(float xres, float yres, CoordConvention coordConvention) { + using namespace Lin; + // TODO: Should be able to share the y-flip logic here with the one in postprocessing/presentation, for example. + Matrix4x4 ortho; + switch (coordConvention) { + case CoordConvention::Vulkan: + ortho.setOrthoD3D(0.0f, xres, 0, yres, -1.0f, 1.0f); + break; + case CoordConvention::Direct3D9: + ortho.setOrthoD3D(0.0f, xres, yres, 0.0f, -1.0f, 1.0f); + Matrix4x4 translation; + // Account for the small window adjustment. + translation.setTranslation(Vec3( + -0.5f * g_display.dpi_scale_x / g_display.dpi_scale_real_x, + -0.5f * g_display.dpi_scale_y / g_display.dpi_scale_real_y, 0.0f)); + ortho = translation * ortho; + break; + case CoordConvention::Direct3D11: + ortho.setOrthoD3D(0.0f, xres, yres, 0.0f, -1.0f, 1.0f); + break; + case CoordConvention::OpenGL: + default: + ortho.setOrtho(0.0f, xres, yres, 0.0f, -1.0f, 1.0f); + break; + } + // Compensate for rotated display if needed. + if (g_display.rotation != DisplayRotation::ROTATE_0) { + ortho = ortho * g_display.rot_matrix; + } + return ortho; +} diff --git a/Common/System/Display.h b/Common/System/Display.h index 0bea49542a..7f61a13dfd 100644 --- a/Common/System/Display.h +++ b/Common/System/Display.h @@ -1,6 +1,7 @@ #pragma once #include "Common/Math/lin/matrix4x4.h" +#include "Common/GPU/MiscTypes.h" // This is meant to be a framework for handling DPI scaling etc. // For now, it just consists of these ugly globals. @@ -50,3 +51,5 @@ struct DisplayRect { void RotateRectToDisplay(DisplayRect &rect, float rtWidth, float rtHeight); void RotateRectToDisplay(DisplayRect &rect, int rtWidth, int rtHeight); + +Lin::Matrix4x4 ComputeOrthoMatrix(float xres, float yres, CoordConvention coordConvention); diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 4c035ca6b6..0c365de049 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1016,38 +1016,6 @@ void CallbackPostRender(UIContext *dc, void *userdata) { } } -static Matrix4x4 ComputeOrthoMatrix(float xres, float yres) { - // TODO: Should be able to share the y-flip logic here with the one in postprocessing/presentation, for example. - Matrix4x4 ortho; - switch (GetGPUBackend()) { - case GPUBackend::VULKAN: - ortho.setOrthoD3D(0.0f, xres, 0, yres, -1.0f, 1.0f); - break; - case GPUBackend::DIRECT3D9: - ortho.setOrthoD3D(0.0f, xres, yres, 0.0f, -1.0f, 1.0f); - Matrix4x4 translation; - // Account for the small window adjustment. - translation.setTranslation(Vec3( - -0.5f * g_display.dpi_scale_x / g_display.dpi_scale_real_x, - -0.5f * g_display.dpi_scale_y / g_display.dpi_scale_real_y, 0.0f)); - ortho = translation * ortho; - break; - case GPUBackend::DIRECT3D11: - ortho.setOrthoD3D(0.0f, xres, yres, 0.0f, -1.0f, 1.0f); - break; - case GPUBackend::OPENGL: - default: - ortho.setOrtho(0.0f, xres, yres, 0.0f, -1.0f, 1.0f); - break; - } - - // Compensate for rotated display if needed. - if (g_display.rotation != DisplayRotation::ROTATE_0) { - ortho = ortho * g_display.rot_matrix; - } - return ortho; -} - static void SendMouseDeltaAxis(); void NativeFrame(GraphicsContext *graphicsContext) { @@ -1115,8 +1083,7 @@ void NativeFrame(GraphicsContext *graphicsContext) { g_requestManager.ProcessRequests(); // Apply the UIContext bounds as a 2D transformation matrix. - // TODO: This should be moved into the draw context... - Matrix4x4 ortho = ComputeOrthoMatrix(g_display.dp_xres, g_display.dp_yres); + Matrix4x4 ortho = ComputeOrthoMatrix(g_display.dp_xres, g_display.dp_yres, graphicsContext->GetDrawContext()->GetDeviceCaps().coordConvention); Draw::DebugFlags debugFlags = Draw::DebugFlags::NONE; if ((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::GPU_PROFILE)