From e427d0962849c2e2ed4db4c7bddd277619db9264 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 3 Jan 2016 23:06:15 -0800 Subject: [PATCH] Determine scaleFactor once per frame. This way, for auto, we can properly treat it like scaleFactor = 1 when the resolution is small. --- GPU/Common/TextureCacheCommon.cpp | 41 +++++++++++++++++++++++++++++++ GPU/Common/TextureCacheCommon.h | 2 ++ GPU/Directx9/GPU_DX9.cpp | 2 ++ GPU/Directx9/TextureCacheDX9.cpp | 22 +++-------------- GPU/GLES/GLES_GPU.cpp | 4 ++- GPU/GLES/TextureCache.cpp | 26 +++----------------- 6 files changed, 55 insertions(+), 42 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 30207f1c90..215730f6c6 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -19,6 +19,7 @@ #include "Common/MemoryUtil.h" #include "Core/Config.h" #include "Core/Reporting.h" +#include "Core/System.h" #include "GPU/Common/FramebufferCommon.h" #include "GPU/Common/TextureCacheCommon.h" #include "GPU/Common/TextureDecoder.h" @@ -164,6 +165,46 @@ void TextureCacheCommon::NotifyFramebuffer(u32 address, VirtualFramebuffer *fram } } +void TextureCacheCommon::NotifyConfigChanged() { + int scaleFactor; + + // 0 means automatic texture scaling, up to 5x, based on resolution. + if (g_Config.iTexScalingLevel == 0) { + scaleFactor = g_Config.iInternalResolution; + // Automatic resolution too? Okay. + if (scaleFactor == 0) { + if (!g_Config.IsPortrait()) { + scaleFactor = (PSP_CoreParameter().pixelWidth + 479) / 480; + } else { + scaleFactor = (PSP_CoreParameter().pixelHeight + 479) / 480; + } + } + + // Mobile devices don't get the higher scale factors, too expensive. Very rough way to decide though... + if (!gstate_c.Supports(GPU_IS_MOBILE)) { + scaleFactor = std::min(5, scaleFactor); + } else { + scaleFactor = std::min(3, scaleFactor); + } + } else { + scaleFactor = g_Config.iTexScalingLevel; + } + + if (!gstate_c.Supports(GPU_SUPPORTS_OES_TEXTURE_NPOT)) { + // Reduce the scale factor to a power of two (e.g. 2 or 4) if textures must be a power of two. + while ((scaleFactor & (scaleFactor - 1)) != 0) { + --scaleFactor; + } + } + + // Just in case, small display with auto resolution or something. + if (scaleFactor <= 0) { + scaleFactor = 1; + } + + standardScaleFactor_ = scaleFactor; +} + void TextureCacheCommon::LoadClut(u32 clutAddr, u32 loadBytes) { clutTotalBytes_ = loadBytes; clutRenderAddress_ = 0xFFFFFFFF; diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 847a1c2917..8376093561 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -45,6 +45,7 @@ public: // FramebufferManager keeps TextureCache updated about what regions of memory are being rendered to. void NotifyFramebuffer(u32 address, VirtualFramebuffer *framebuffer, FramebufferNotification msg); + void NotifyConfigChanged(); int AttachedDrawingHeight(); @@ -154,6 +155,7 @@ protected: u32 clutTotalBytes_; u32 clutMaxBytes_; u32 clutRenderAddress_; + int standardScaleFactor_; }; inline bool TextureCacheCommon::TexCacheEntry::Matches(u16 dim2, u8 format2, u8 maxLevel2) { diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index e0a230bc08..46bb33e3d9 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -444,6 +444,7 @@ DIRECTX9_GPU::DIRECTX9_GPU() // Some of our defaults are different from hw defaults, let's assert them. // We restore each frame anyway, but here is convenient for tests. dxstate.Restore(); + textureCache_.NotifyConfigChanged(); } void DIRECTX9_GPU::UpdateCmdInfo() { @@ -537,6 +538,7 @@ void DIRECTX9_GPU::BeginFrameInternal() { if (resized_) { UpdateCmdInfo(); transformDraw_.Resized(); + textureCache_.NotifyConfigChanged(); resized_ = false; } diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 5354f7c271..c9b2fa5643 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -1145,7 +1145,7 @@ void TextureCacheDX9::SetTexture(bool force) { } } - if (match && (entry->status & TexCacheEntry::STATUS_TO_SCALE) && g_Config.iTexScalingLevel != 1 && texelsScaledThisFrame_ < TEXCACHE_MAX_TEXELS_SCALED) { + if (match && (entry->status & TexCacheEntry::STATUS_TO_SCALE) && standardScaleFactor_ != 1 && texelsScaledThisFrame_ < TEXCACHE_MAX_TEXELS_SCALED) { if ((entry->status & TexCacheEntry::STATUS_CHANGE_FREQUENT) == 0) { // INFO_LOG(G3D, "Reloading texture to do the scaling we skipped.."); match = false; @@ -1172,7 +1172,7 @@ void TextureCacheDX9::SetTexture(bool force) { gpuStats.numTextureInvalidations++; DEBUG_LOG(G3D, "Texture different or overwritten, reloading at %08x: %s", texaddr, reason); if (doDelete) { - if (entry->maxLevel == maxLevel && entry->dim == gstate.getTextureDimension(0) && entry->format == format && g_Config.iTexScalingLevel == 1) { + if (entry->maxLevel == maxLevel && entry->dim == gstate.getTextureDimension(0) && entry->format == format && standardScaleFactor_ == 1) { // Actually, if size and number of levels match, let's try to avoid deleting and recreating. // Instead, let's use glTexSubImage to replace the images. replaceImages = true; @@ -1291,21 +1291,7 @@ void TextureCacheDX9::SetTexture(bool force) { // If GLES3 is available, we can preallocate the storage, which makes texture loading more efficient. D3DFORMAT dstFmt = GetDestFormat(format, gstate.getClutPaletteFormat()); - int scaleFactor; - // Auto-texture scale upto 5x rendering resolution - if (g_Config.iTexScalingLevel == 0) { - scaleFactor = g_Config.iInternalResolution; - if (scaleFactor == 0) { - scaleFactor = (PSP_CoreParameter().renderWidth + 479) / 480; - } - - scaleFactor = std::min(4, scaleFactor); - if (scaleFactor == 3) { - scaleFactor = 2; - } - } else { - scaleFactor = g_Config.iTexScalingLevel; - } + int scaleFactor = standardScaleFactor_; // Rachet down scale factor in low-memory mode. if (lowMemoryMode_) { @@ -1585,7 +1571,7 @@ void *TextureCacheDX9::DecodeTextureLevel(GETextureFormat format, GEPaletteForma ERROR_LOG_REPORT(G3D, "NO finalbuf! Will crash!"); } - if (!(g_Config.iTexScalingLevel == 1 && gstate_c.Supports(GPU_SUPPORTS_UNPACK_SUBIMAGE)) && w != bufw) { + if (!(standardScaleFactor_ == 1 && gstate_c.Supports(GPU_SUPPORTS_UNPACK_SUBIMAGE)) && w != bufw) { int pixelSize; switch (dstFmt) { case D3DFMT_A4R4G4B4: diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index 152d14a6be..e849dc9ef9 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -454,8 +454,9 @@ GLES_GPU::GLES_GPU(GraphicsContext *ctx) // Some of our defaults are different from hw defaults, let's assert them. // We restore each frame anyway, but here is convenient for tests. - transformDraw_.RestoreVAO(); glstate.Restore(); + transformDraw_.RestoreVAO(); + textureCache_.NotifyConfigChanged(); } GLES_GPU::~GLES_GPU() { @@ -715,6 +716,7 @@ void GLES_GPU::BeginFrameInternal() { CheckGPUFeatures(); UpdateCmdInfo(); transformDraw_.Resized(); + textureCache_.NotifyConfigChanged(); } UpdateVsyncInterval(resized_); resized_ = false; diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index 16b0b39f56..ae52e06a85 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -1230,7 +1230,7 @@ void TextureCache::SetTexture(bool force) { } } - if (match && (entry->status & TexCacheEntry::STATUS_TO_SCALE) && g_Config.iTexScalingLevel != 1 && texelsScaledThisFrame_ < TEXCACHE_MAX_TEXELS_SCALED) { + if (match && (entry->status & TexCacheEntry::STATUS_TO_SCALE) && standardScaleFactor_ != 1 && texelsScaledThisFrame_ < TEXCACHE_MAX_TEXELS_SCALED) { if ((entry->status & TexCacheEntry::STATUS_CHANGE_FREQUENT) == 0) { // INFO_LOG(G3D, "Reloading texture to do the scaling we skipped.."); match = false; @@ -1255,7 +1255,7 @@ void TextureCache::SetTexture(bool force) { gpuStats.numTextureInvalidations++; DEBUG_LOG(G3D, "Texture different or overwritten, reloading at %08x: %s", texaddr, reason); if (doDelete) { - if (entry->maxLevel == maxLevel && entry->dim == gstate.getTextureDimension(0) && entry->format == format && g_Config.iTexScalingLevel == 1) { + if (entry->maxLevel == maxLevel && entry->dim == gstate.getTextureDimension(0) && entry->format == format && standardScaleFactor_ == 1) { // Actually, if size and number of levels match, let's try to avoid deleting and recreating. // Instead, let's use glTexSubImage to replace the images. replaceImages = true; @@ -1380,27 +1380,7 @@ void TextureCache::SetTexture(bool force) { // If GLES3 is available, we can preallocate the storage, which makes texture loading more efficient. GLenum dstFmt = GetDestFormat(format, gstate.getClutPaletteFormat()); - int scaleFactor; - // Auto-texture scale upto 5x rendering resolution - if (g_Config.iTexScalingLevel == 0) { - scaleFactor = g_Config.iInternalResolution; - if (scaleFactor == 0) { - scaleFactor = (PSP_CoreParameter().renderWidth + 479) / 480; - } - - // Mobile devices don't get the higher scale factors, too expensive. Very rough way to decide though... - if (!gstate_c.Supports(GPU_IS_MOBILE)) { - bool supportNpot = gstate_c.Supports(GPU_SUPPORTS_OES_TEXTURE_NPOT); - scaleFactor = std::min(supportNpot ? 5 : 4, scaleFactor); - if (!supportNpot && scaleFactor == 3) { - scaleFactor = 2; - } - } else { - scaleFactor = std::min(gstate_c.Supports(GPU_SUPPORTS_OES_TEXTURE_NPOT) ? 3 : 2, scaleFactor); - } - } else { - scaleFactor = g_Config.iTexScalingLevel; - } + int scaleFactor = standardScaleFactor_; // Rachet down scale factor in low-memory mode. if (lowMemoryMode_) {