Change the 2D matrix generation to query the coordinate convention from the draw context

This commit is contained in:
Henrik Rydgård 2024-10-30 23:27:38 +01:00
parent 8f8598c347
commit d37c04079d
9 changed files with 56 additions and 34 deletions

View File

@ -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;

View File

@ -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:

View File

@ -2,6 +2,9 @@
#include "Common/Common.h"
#include <functional>
#include <cstdint>
// 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,
};

View File

@ -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;

View File

@ -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;

View File

@ -586,6 +586,7 @@ struct DeviceCaps {
GPUVendor vendor;
uint32_t deviceID; // use caution!
CoordConvention coordConvention;
DataFormat preferredDepthBufferFormat;
DataFormat preferredShadowMapFormatLow;
DataFormat preferredShadowMapFormatHigh;

View File

@ -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;
}

View File

@ -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<float> &rect, float rtWidth, float rtHeight);
void RotateRectToDisplay(DisplayRect<int> &rect, int rtWidth, int rtHeight);
Lin::Matrix4x4 ComputeOrthoMatrix(float xres, float yres, CoordConvention coordConvention);

View File

@ -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)