Skip to content

Commit

Permalink
Vulkan: Be more restrictive about texture upscaling on "slow" devices.
Browse files Browse the repository at this point in the history
Applies the same rules as for software upscaling in this case.

Should fix the stutters seen in #15109
  • Loading branch information
hrydgard committed Dec 16, 2021
1 parent d294b6a commit 80ae4b0
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 5 deletions.
31 changes: 31 additions & 0 deletions Common/GPU/Vulkan/VulkanContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <cstring>
#include <iostream>

#include "Common/System/System.h"
#include "Common/System/Display.h"
#include "Common/Log.h"
#include "Common/GPU/Vulkan/VulkanContext.h"
Expand Down Expand Up @@ -680,6 +681,36 @@ VkResult VulkanContext::CreateDevice() {
allocatorInfo.instance = instance_;
vmaCreateAllocator(&allocatorInfo, &allocator_);

// Examine the physical device to figure out super rough performance grade.
// Basically all we want to do is to identify low performance mobile devices
// so we can make decisions on things like texture scaling strategy.
auto &props = physicalDeviceProperties_[physical_device_].properties;
switch (props.vendorID) {
case VULKAN_VENDOR_AMD:
case VULKAN_VENDOR_NVIDIA:
case VULKAN_VENDOR_INTEL:
devicePerfClass_ = PerfClass::FAST;
break;

case VULKAN_VENDOR_ARM:
case VULKAN_VENDOR_QUALCOMM:
devicePerfClass_ = PerfClass::SLOW;
// I haven't seen the bad compute shader slowdowns on any Android 11 device, so let's do
// a really silly heuristic here, and improve as needed.
#if PPSSPP_PLATFORM(ANDROID)
if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= 30) {
devicePerfClass_ = PerfClass::FAST;
}
#endif
break;

case VULKAN_VENDOR_IMGTEC:
default:
devicePerfClass_ = PerfClass::SLOW;
break;
}


for (int i = 0; i < ARRAY_SIZE(frame_); i++) {
frame_[i].profiler.Init(this);
}
Expand Down
13 changes: 12 additions & 1 deletion Common/GPU/Vulkan/VulkanContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
// other things as well. We also have a nice integrated render pass profiler in the queue
// runner, but this one is more convenient for transient events.

// #define VULKAN_PROFILER_ENABLED
#define VULKAN_PROFILER_ENABLED

#if defined(VULKAN_PROFILER_ENABLED)
#define VK_PROFILE_BEGIN(vulkan, cmd, stage, message) vulkan->GetProfiler()->Begin(cmd, stage, message);
Expand Down Expand Up @@ -80,6 +80,12 @@ struct VulkanPhysicalDeviceInfo {

class VulkanProfiler;

// Extremely rough split of capabilities.
enum class PerfClass {
SLOW,
FAST,
};

// This is a bit repetitive...
class VulkanDeleteList {
struct BufferWithAlloc {
Expand Down Expand Up @@ -323,6 +329,10 @@ class VulkanContext {

const VulkanExtensions &Extensions() { return extensionsLookup_; }

PerfClass DevicePerfClass() const {
return devicePerfClass_;
}

void GetImageMemoryRequirements(VkImage image, VkMemoryRequirements *mem_reqs, bool *dedicatedAllocation);

VmaAllocator Allocator() const {
Expand Down Expand Up @@ -385,6 +395,7 @@ class VulkanContext {
VkExtent2D swapChainExtent_{};

int flags_ = 0;
PerfClass devicePerfClass_ = PerfClass::SLOW;

int inflightFrames_ = MAX_INFLIGHT_FRAMES;

Expand Down
1 change: 1 addition & 0 deletions GPU/Common/TextureCacheCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,7 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
reason = "scaling";
}
}

if (match && (entry->status & TexCacheEntry::STATUS_TO_REPLACE) && replacementTimeThisFrame_ < replacementFrameBudget_) {
int w0 = gstate.getTextureWidth(0);
int h0 = gstate.getTextureHeight(0);
Expand Down
15 changes: 11 additions & 4 deletions GPU/Vulkan/TextureCacheVulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,8 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
return;
}

VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT);

// Adjust maxLevel to actually present levels..
bool badMipSizes = false;

Expand Down Expand Up @@ -659,14 +661,17 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
if (entry->addr > 0x05000000 && entry->addr < PSP_GetKernelMemoryEnd()) {
scaleFactor = 1;
}
if ((entry->status & TexCacheEntry::STATUS_CHANGE_FREQUENT) != 0 && scaleFactor != 1 && !hardwareScaling) {

bool slowScaler = !hardwareScaling || vulkan->DevicePerfClass() == PerfClass::SLOW; // Or the GPU is slow - TODO add check!

if ((entry->status & TexCacheEntry::STATUS_CHANGE_FREQUENT) != 0 && scaleFactor != 1 && slowScaler) {
// Remember for later that we /wanted/ to scale this texture.
entry->status |= TexCacheEntry::STATUS_TO_SCALE;
scaleFactor = 1;
}

if (scaleFactor != 1) {
if (texelsScaledThisFrame_ >= TEXCACHE_MAX_TEXELS_SCALED && !hardwareScaling) {
if (texelsScaledThisFrame_ >= TEXCACHE_MAX_TEXELS_SCALED && slowScaler) {
entry->status |= TexCacheEntry::STATUS_TO_SCALE;
scaleFactor = 1;
} else {
Expand Down Expand Up @@ -715,7 +720,6 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {

bool computeUpload = false;
VkCommandBuffer cmdInit = (VkCommandBuffer)draw_->GetNativeObject(Draw::NativeObject::INIT_COMMANDBUFFER);
VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT);

{
delete entry->vkTex;
Expand Down Expand Up @@ -745,8 +749,11 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;

if (actualFmt == VULKAN_8888_FORMAT && scaleFactor > 1 && hardwareScaling) {
if (uploadCS_ != VK_NULL_HANDLE)
if (uploadCS_ != VK_NULL_HANDLE) {
computeUpload = true;
} else {
WARN_LOG(G3D, "Falling back to software scaling, hardware shader didn't compile");
}
}

if (computeUpload) {
Expand Down

0 comments on commit 80ae4b0

Please sign in to comment.