mali love incoming. start with detecting mali devices set default settings

This commit is contained in:
izzy2lost
2025-11-28 11:51:50 -05:00
parent 3fe07e4652
commit 2692830038
5 changed files with 302 additions and 10 deletions
+113
View File
@@ -0,0 +1,113 @@
// SPDX-FileCopyrightText: 2025 PCSX2 Dev Team
// SPDX-License-Identifier: GPL-3.0+
#ifdef __ANDROID__
#include "AndroidDeviceDetection.h"
#include "common/Console.h"
#include <sys/system_properties.h>
#include <cstring>
namespace AndroidDeviceDetection
{
static std::string GetSystemProperty(const char* key)
{
char value[PROP_VALUE_MAX] = {};
if (__system_property_get(key, value) > 0)
return std::string(value);
return "";
}
std::string GetManufacturer()
{
return GetSystemProperty("ro.product.manufacturer");
}
std::string GetModel()
{
return GetSystemProperty("ro.product.model");
}
std::string GetGPURenderer()
{
// This would need to be called from GL/Vulkan context
// For now, we rely on hardware detection
return GetSystemProperty("ro.hardware");
}
bool IsMediatek()
{
std::string hardware = GetSystemProperty("ro.hardware");
std::string board = GetSystemProperty("ro.product.board");
std::string platform = GetSystemProperty("ro.board.platform");
// Convert to lowercase for comparison
auto toLower = [](std::string str) {
for (char& c : str) c = std::tolower(c);
return str;
};
hardware = toLower(hardware);
board = toLower(board);
platform = toLower(platform);
// Check for Mediatek identifiers
return (hardware.find("mt") == 0 ||
hardware.find("mediatek") != std::string::npos ||
board.find("mt") == 0 ||
platform.find("mt") == 0 ||
platform.find("mediatek") != std::string::npos);
}
bool IsSnapdragon()
{
std::string hardware = GetSystemProperty("ro.hardware");
std::string board = GetSystemProperty("ro.product.board");
std::string platform = GetSystemProperty("ro.board.platform");
auto toLower = [](std::string str) {
for (char& c : str) c = std::tolower(c);
return str;
};
hardware = toLower(hardware);
board = toLower(board);
platform = toLower(platform);
// Check for Qualcomm/Snapdragon identifiers
return (hardware.find("qcom") != std::string::npos ||
hardware.find("qualcomm") != std::string::npos ||
platform.find("msm") == 0 ||
platform.find("sdm") == 0 ||
platform.find("sm") == 0 ||
platform.find("qcom") != std::string::npos);
}
GPUVendor DetectGPUVendor()
{
if (IsSnapdragon())
{
Console.WriteLn("Detected Qualcomm Snapdragon (Adreno GPU)");
return GPUVendor::Qualcomm;
}
if (IsMediatek())
{
Console.WriteLn("Detected Mediatek (Mali GPU)");
return GPUVendor::ARM;
}
// Check for other vendors via hardware string
std::string hardware = GetSystemProperty("ro.hardware");
if (hardware.find("exynos") != std::string::npos)
{
Console.WriteLn("Detected Samsung Exynos (Mali GPU)");
return GPUVendor::ARM;
}
Console.WriteLn("Unknown GPU vendor, hardware: %s", hardware.c_str());
return GPUVendor::Unknown;
}
}
#endif // __ANDROID__
+40
View File
@@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: 2025 PCSX2 Dev Team
// SPDX-License-Identifier: GPL-3.0+
#pragma once
#ifdef __ANDROID__
#include <string>
namespace AndroidDeviceDetection
{
enum class GPUVendor
{
Unknown,
Qualcomm, // Adreno (Snapdragon)
ARM, // Mali (Mediatek, Exynos, etc.)
Imagination, // PowerVR
Other
};
// Detect GPU vendor from system properties and GL/Vulkan strings
GPUVendor DetectGPUVendor();
// Check if device is Mediatek (Mali GPU)
bool IsMediatek();
// Check if device is Snapdragon (Adreno GPU)
bool IsSnapdragon();
// Get device manufacturer
std::string GetManufacturer();
// Get device model
std::string GetModel();
// Get GPU renderer string (requires GL context or Vulkan device)
std::string GetGPURenderer();
}
#endif // __ANDROID__
+1
View File
@@ -1127,6 +1127,7 @@ if(ANDROID)
../AchievementsJNI.cpp
../AchievementsAndroid.cpp
../AchievementsNativeMethods.cpp
../AndroidDeviceDetection.cpp
)
elseif(LINUX)
target_sources(PCSX2 PRIVATE
+57
View File
@@ -6,6 +6,7 @@
#include "GS/GSUtil.h"
#include "MultiISA.h"
#include "common/StringUtil.h"
#include "common/Console.h"
#include <array>
@@ -22,6 +23,10 @@
#include <wil/com.h>
#endif
#ifdef __ANDROID__
#include "AndroidDeviceDetection.h"
#endif
namespace {
struct GSUtilMaps
{
@@ -213,6 +218,58 @@ GSRendererType GSUtil::GetPreferredRenderer()
#elif defined(_WIN32)
// Use D3D device info to select renderer.
preferred_renderer = D3D::GetPreferredRenderer();
#elif defined(__ANDROID__)
// Android: Detect GPU vendor and choose appropriate renderer
using namespace AndroidDeviceDetection;
GPUVendor vendor = DetectGPUVendor();
if (vendor == GPUVendor::ARM)
{
// Mediatek/Mali GPUs: Prefer OpenGL over Vulkan
// Vulkan drivers on Mali are often buggy, especially on Mediatek
// OpenGL works but may have 2D graphics issues that need workarounds
Console.Warning("Mediatek/Mali GPU detected: Using OpenGL renderer (Vulkan has known issues)");
#if defined(ENABLE_OPENGL)
preferred_renderer = GSRendererType::OGL;
#elif defined(ENABLE_VULKAN)
// Fallback to Vulkan if OpenGL not available (but warn user)
Console.Error("OpenGL not available, falling back to Vulkan (may have issues on Mali)");
preferred_renderer = GSRendererType::VK;
#else
preferred_renderer = GSRendererType::SW;
#endif
}
else if (vendor == GPUVendor::Qualcomm)
{
// Snapdragon/Adreno GPUs: Prefer Vulkan (good driver support)
Console.WriteLn("Qualcomm/Adreno GPU detected: Using Vulkan renderer");
#if defined(ENABLE_VULKAN)
preferred_renderer = GSRendererType::VK;
#elif defined(ENABLE_OPENGL)
preferred_renderer = GSRendererType::OGL;
#else
preferred_renderer = GSRendererType::SW;
#endif
}
else
{
// Unknown vendor: Try Vulkan first, then OpenGL
Console.WriteLn("Unknown GPU vendor: Trying Vulkan renderer");
#if defined(ENABLE_VULKAN)
if (GSDeviceVK::IsSuitableDefaultRenderer())
preferred_renderer = GSRendererType::VK;
#endif
if (preferred_renderer == GSRendererType::Auto)
{
#if defined(ENABLE_OPENGL)
preferred_renderer = GSRendererType::OGL;
#elif defined(ENABLE_VULKAN)
preferred_renderer = GSRendererType::VK;
#else
preferred_renderer = GSRendererType::SW;
#endif
}
}
#else
// Linux: Prefer Vulkan if the driver isn't buggy.
#if defined(ENABLE_VULKAN)
@@ -18,9 +18,18 @@
#include "IconsFontAwesome5.h"
#include <cinttypes>
#include <cctype>
#include <fstream>
#include <sstream>
// Some texture barrier extension macros may not be generated by GLAD for GLES builds.
#ifndef GLAD_GL_EXT_texture_barrier
#define GLAD_GL_EXT_texture_barrier 0
#endif
#ifndef GLAD_GL_OES_texture_barrier
#define GLAD_GL_OES_texture_barrier 0
#endif
static constexpr u32 g_vs_cb_index = 1;
static constexpr u32 g_ps_cb_index = 0;
@@ -626,24 +635,42 @@ bool GSDeviceOGL::CheckFeatures(bool& buggy_pbo)
//bool vendor_id_amd = false;
bool vendor_id_nvidia = false;
//bool vendor_id_intel = false;
bool vendor_id_arm_mali = false;
const char* vendor = (const char*)glGetString(GL_VENDOR);
if (std::strstr(vendor, "Advanced Micro Devices") || std::strstr(vendor, "ATI Technologies Inc.") ||
std::strstr(vendor, "ATI"))
const char* renderer = (const char*)glGetString(GL_RENDERER);
const std::string vendor_str = vendor ? vendor : "";
const std::string renderer_str = renderer ? renderer : "";
const auto to_lower = [](std::string s) {
for (char& c : s)
c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
return s;
};
const std::string vendor_lower = to_lower(vendor_str);
const std::string renderer_lower = to_lower(renderer_str);
if (vendor_lower.find("advanced micro devices") != std::string::npos ||
vendor_lower.find("ati technologies inc.") != std::string::npos ||
vendor_lower.find("ati") != std::string::npos)
{
Console.WriteLn(Color_StrongRed, "GL: AMD GPU detected.");
//vendor_id_amd = true;
}
else if (std::strstr(vendor, "NVIDIA Corporation"))
else if (vendor_lower.find("nvidia corporation") != std::string::npos || vendor_lower.find("nvidia") != std::string::npos)
{
Console.WriteLn(Color_StrongGreen, "GL: NVIDIA GPU detected.");
vendor_id_nvidia = true;
}
else if (std::strstr(vendor, "Intel"))
else if (vendor_lower.find("intel") != std::string::npos)
{
Console.WriteLn(Color_StrongBlue, "GL: Intel GPU detected.");
//vendor_id_intel = true;
}
else if (vendor_lower.find("arm") != std::string::npos || renderer_lower.find("mali") != std::string::npos)
{
Console.Warning("GL: ARM Mali GPU detected - applying workarounds for 2D graphics issues.");
vendor_id_arm_mali = true;
}
GLint major_gl = 0;
GLint minor_gl = 0;
@@ -724,7 +751,7 @@ bool GSDeviceOGL::CheckFeatures(bool& buggy_pbo)
if (!m_is_gles) {
buggy_pbo = !GLAD_GL_VERSION_4_4 && !GLAD_GL_ARB_buffer_storage && !GLAD_GL_EXT_buffer_storage;
} else {
buggy_pbo = GLAD_GL_EXT_buffer_storage;
buggy_pbo = !GLAD_GL_EXT_buffer_storage;
}
if (buggy_pbo)
Console.Warning("GL: Not using PBOs for texture uploads because buffer_storage is unavailable.");
@@ -747,12 +774,14 @@ bool GSDeviceOGL::CheckFeatures(bool& buggy_pbo)
m_features.framebuffer_fetch = false;
}
const bool has_texture_barrier =
GLAD_GL_ARB_texture_barrier || GLAD_GL_EXT_texture_barrier || GLAD_GL_OES_texture_barrier;
if (GSConfig.OverrideTextureBarriers == 0)
m_features.texture_barrier = m_features.framebuffer_fetch; // Force Disabled
else if (GSConfig.OverrideTextureBarriers == 1)
m_features.texture_barrier = true; // Force Enabled
else
m_features.texture_barrier = m_features.framebuffer_fetch || GLAD_GL_ARB_texture_barrier;
m_features.texture_barrier = m_features.framebuffer_fetch || has_texture_barrier;
if (!m_features.texture_barrier)
{
// OSD message disabled: GL_ARB_texture_barrier warning
@@ -801,6 +830,54 @@ bool GSDeviceOGL::CheckFeatures(bool& buggy_pbo)
m_features.line_expand ? "hardware" : (m_features.vs_expand ? "vertex expanding" : "UNSUPPORTED"),
m_features.vs_expand ? "vertex expanding" : "CPU");
// Mali GPU workarounds for missing 2D graphics
if (vendor_id_arm_mali)
{
Console.Warning("GL: Applying Mali GPU workarounds:");
// Mali has issues with framebuffer fetch - disable it
if (m_features.framebuffer_fetch)
{
Console.Warning(" - Disabling framebuffer fetch (causes 2D graphics issues on Mali)");
m_features.framebuffer_fetch = false;
}
// Force texture barriers on Mali
if (!m_features.texture_barrier && has_texture_barrier)
{
Console.Warning(" - Enabling texture barriers (required for proper blending on Mali)");
m_features.texture_barrier = true;
}
else if (!has_texture_barrier)
{
// Keep barriers disabled so we fall back to safe RT copies instead of no-op barriers.
m_features.texture_barrier = false;
}
// Disable vertex shader expansion on Mali (can cause rendering issues)
if (m_features.vs_expand)
{
Console.Warning(" - Disabling vertex shader expansion (unstable on Mali)");
m_features.vs_expand = false;
}
// Force PBO usage off on Mali (can cause texture corruption)
if (!buggy_pbo)
{
Console.Warning(" - Disabling PBO for texture uploads (causes corruption on Mali)");
buggy_pbo = true;
}
// Disable download PBO as well
if (!m_disable_download_pbo)
{
Console.Warning(" - Disabling PBO for texture downloads (causes corruption on Mali)");
m_disable_download_pbo = true;
}
Console.Warning("GL: Mali workarounds applied. If 2D graphics still missing, try Software renderer.");
}
return true;
}
@@ -1368,10 +1445,14 @@ std::string GSDeviceOGL::GenGlslHeader(const std::string_view entry, GLenum type
else
header += "#define HAS_FRAMEBUFFER_FETCH 0\n";
if (GLAD_GL_ARB_clip_control)
header += "#define HAS_CLIP_CONTROL 1\n";
else
header += "#define HAS_CLIP_CONTROL 0\n";
if (GLAD_GL_ARB_clip_control)
{
header += "#define HAS_CLIP_CONTROL 1\n";
}
else
{
header += "#define HAS_CLIP_CONTROL 0\n";
}
// Allow to puts several shader in 1 files
switch (type)