Merge pull request #22734 from hrydgard/vulkan-stale-extent-workaround

Android Vulkan: Bring back the stale surface extent workaround
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2026-10-22 21:52:20 +02:00
commit 79cedbc13f
3 files changed
+27

No files matched your search

+15
View File
@@ -1556,6 +1556,21 @@ bool VulkanContext::InitSwapchain(VkPresentModeKHR desiredPresentMode) {
}
}
#if PPSSPP_PLATFORM(ANDROID)
// After an in-place rotation, the surface can report the new transform together with the previous
// orientation's extent. A Redmi 9A (PowerVR, Android 11) keeps doing it after surfaceChanged has given us the
// new size, so the swapchain stays wrong until the next rotation. The latest window size from surfaceChanged
// is current (g_display can lag behind it, until the render thread applies the resize), so if the extent is
// exactly that transposed, it's stale.
const VkExtent2D windowSize = cbGetDrawSize_ ? cbGetDrawSize_() : VkExtent2D{};
if (windowSize.width > 0 && windowSize.height > 0 && windowSize.width != windowSize.height &&
currentExtent.width == windowSize.height && currentExtent.height == windowSize.width) {
WARN_LOG(Log::G3D, "Surface extent %dx%d is the window transposed, probably stale after a rotation. Using %dx%d.",
currentExtent.width, currentExtent.height, windowSize.width, windowSize.height);
std::swap(currentExtent.width, currentExtent.height);
}
#endif
swapChainExtent_.width = clamp(currentExtent.width, surfCapabilities_.minImageExtent.width, surfCapabilities_.maxImageExtent.width);
swapChainExtent_.height = clamp(currentExtent.height, surfCapabilities_.minImageExtent.height, surfCapabilities_.maxImageExtent.height);
+1
View File
@@ -524,6 +524,7 @@ private:
// that we really don't want in everything that uses VulkanContext.
void *winsysData1_ = nullptr;
void *winsysData2_ = nullptr;
// The window's current size in pixels, from the platform. Optional.
std::function<VkExtent2D()> cbGetDrawSize_;
VkInstance instance_ = VK_NULL_HANDLE;
+11
View File
@@ -89,6 +89,7 @@ struct JNIEnv {};
#include "Common/VR/PPSSPPVR.h"
#include "Common/GPU/Vulkan/VulkanLoader.h"
#include "Common/GPU/GraphicsContext.h"
#include "Common/GPU/Vulkan/VulkanContext.h"
#include "Common/GPU/Vulkan/VulkanGraphicsContext.h"
#include "android/jni/AndroidEGLGraphicsContext.h"
#include "Common/StringUtils.h"
@@ -202,6 +203,10 @@ static void SetPermissionStatusFromJava(std::string_view name, PermissionStatus
static GraphicsContext *graphicsContext;
// The latest surface size from backbufferResize, width in the high half, for Vulkan to check the surface's extent
// against. Atomic rather than under g_pendingResizeLock (below), since a resize applied directly can recreate the swapchain.
static std::atomic<uint64_t> g_surfaceSize;
#if PPSSPP_ARCH(ARMV7)
// Old Android workaround
extern "C" {
@@ -730,6 +735,10 @@ retry:
delete ctx;
goto retry;
}
((VulkanContext *)ctx->GetAPIContext())->SetCbGetDrawSize([]() {
const uint64_t size = g_surfaceSize;
return VkExtent2D{ (uint32_t)(size >> 32), (uint32_t)size };
});
graphicsContext = ctx;
// Now, we wait until we get a surface to continue initializing Vulkan.
break;
@@ -908,6 +917,8 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv
const bool rotated = lastRotation != -1 && rotation != lastRotation;
lastRotation = rotation;
g_surfaceSize = ((uint64_t)(uint32_t)pixel_xres << 32) | (uint32_t)pixel_yres;
// pixel_*res is the backbuffer resolution.
if (IsVREnabled()) {
GetVRResolutionPerEye(&pixel_xres, &pixel_yres);