mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Replacement: Add structure for delayed loading.
This commit is contained in:
parent
12215a3c60
commit
2356280a9c
8 changed files with 90 additions and 28 deletions
|
@ -733,6 +733,10 @@ float TextureReplacer::LookupReduceHashRange(int& w, int& h) {
|
|||
}
|
||||
}
|
||||
|
||||
bool ReplacedTexture::IsReady(double budget) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReplacedTexture::Load(int level, void *out, int rowPitch) {
|
||||
_assert_msg_((size_t)level < levels_.size(), "Invalid miplevel");
|
||||
_assert_msg_(out != nullptr && rowPitch > 0, "Invalid out/pitch");
|
||||
|
|
|
@ -153,6 +153,8 @@ struct ReplacedTexture {
|
|||
return (u8)alphaStatus_;
|
||||
}
|
||||
|
||||
bool IsReady(double budget);
|
||||
|
||||
bool Load(int level, void *out, int rowPitch);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -472,6 +472,10 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
|
|||
reason = "scaling";
|
||||
}
|
||||
}
|
||||
if (match && (entry->status & TexCacheEntry::STATUS_TO_REPLACE) && replacementTimeThisFrame_ <= replacementFrameBudget_) {
|
||||
match = false;
|
||||
reason = "replacing";
|
||||
}
|
||||
|
||||
if (match) {
|
||||
// got one!
|
||||
|
|
|
@ -123,16 +123,17 @@ struct TexCacheEntry {
|
|||
STATUS_CLUT_RECHECK = 0x20, // Another texture with same addr had a hashfail.
|
||||
STATUS_TO_SCALE = 0x80, // Pending texture scaling in a later frame.
|
||||
STATUS_IS_SCALED = 0x100, // Has been scaled (can't be replaceImages'd.)
|
||||
STATUS_TO_REPLACE = 0x0200, // Pending texture replacement.
|
||||
// When hashing large textures, we optimize 512x512 down to 512x272 by default, since this
|
||||
// is commonly the only part accessed. If access is made above 272, we hash the entire
|
||||
// texture, and set this flag to allow scaling the texture just once for the new hash.
|
||||
STATUS_FREE_CHANGE = 0x200, // Allow one change before marking "frequent".
|
||||
STATUS_FREE_CHANGE = 0x0400, // Allow one change before marking "frequent".
|
||||
|
||||
STATUS_BAD_MIPS = 0x400, // Has bad or unusable mipmap levels.
|
||||
STATUS_BAD_MIPS = 0x0800, // Has bad or unusable mipmap levels.
|
||||
|
||||
STATUS_FRAMEBUFFER_OVERLAP = 0x800,
|
||||
STATUS_FRAMEBUFFER_OVERLAP = 0x1000,
|
||||
|
||||
STATUS_FORCE_REBUILD = 0x1000,
|
||||
STATUS_FORCE_REBUILD = 0x2000,
|
||||
};
|
||||
|
||||
// Status, but int so we can zero initialize.
|
||||
|
@ -334,6 +335,9 @@ protected:
|
|||
int decimationCounter_;
|
||||
int texelsScaledThisFrame_ = 0;
|
||||
int timesInvalidatedAllThisFrame_ = 0;
|
||||
double replacementTimeThisFrame_ = 0;
|
||||
// TODO: Maybe vary by FPS...
|
||||
double replacementFrameBudget_ = 0.75 / 60.0;
|
||||
|
||||
TexCache cache_;
|
||||
u32 cacheSizeEstimate_ = 0;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <d3d11.h>
|
||||
|
||||
#include "Common/TimeUtil.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "GPU/ge_constants.h"
|
||||
|
@ -169,6 +170,7 @@ void TextureCacheD3D11::InvalidateLastTexture() {
|
|||
void TextureCacheD3D11::StartFrame() {
|
||||
InvalidateLastTexture();
|
||||
timesInvalidatedAllThisFrame_ = 0;
|
||||
replacementTimeThisFrame_ = 0.0;
|
||||
|
||||
if (texelsScaledThisFrame_) {
|
||||
// INFO_LOG(G3D, "Scaled %i texels", texelsScaledThisFrame_);
|
||||
|
@ -486,13 +488,21 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) {
|
|||
u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0;
|
||||
int w = gstate.getTextureWidth(0);
|
||||
int h = gstate.getTextureHeight(0);
|
||||
double replaceStart = time_now_d();
|
||||
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
|
||||
if (replaced.GetSize(0, w, h)) {
|
||||
// We're replacing, so we won't scale.
|
||||
scaleFactor = 1;
|
||||
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
|
||||
maxLevel = replaced.MaxLevel();
|
||||
badMipSizes = false;
|
||||
if (replaced.IsReady(replacementFrameBudget_ - replacementTimeThisFrame_)) {
|
||||
if (replaced.GetSize(0, w, h)) {
|
||||
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||
|
||||
// We're replacing, so we won't scale.
|
||||
scaleFactor = 1;
|
||||
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
|
||||
entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE;
|
||||
maxLevel = replaced.MaxLevel();
|
||||
badMipSizes = false;
|
||||
}
|
||||
} else if (replaced.MaxLevel() >= 0) {
|
||||
entry->status |= TexCacheEntry::STATUS_TO_REPLACE;
|
||||
}
|
||||
|
||||
// Don't scale the PPGe texture.
|
||||
|
@ -678,7 +688,9 @@ void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &
|
|||
if (replaced.GetSize(level, w, h)) {
|
||||
mapData = (u32 *)AllocateAlignedMemory(w * h * sizeof(u32), 16);
|
||||
mapRowPitch = w * 4;
|
||||
double replaceStart = time_now_d();
|
||||
replaced.Load(level, mapData, mapRowPitch);
|
||||
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||
dstFmt = ToDXGIFormat(replaced.Format(level));
|
||||
} else {
|
||||
GETextureFormat tfmt = (GETextureFormat)entry.format;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#include "Common/TimeUtil.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "GPU/ge_constants.h"
|
||||
|
@ -134,6 +135,7 @@ void TextureCacheDX9::ApplySamplingParams(const SamplerCacheKey &key) {
|
|||
void TextureCacheDX9::StartFrame() {
|
||||
InvalidateLastTexture();
|
||||
timesInvalidatedAllThisFrame_ = 0;
|
||||
replacementTimeThisFrame_ = 0.0;
|
||||
|
||||
if (texelsScaledThisFrame_) {
|
||||
VERBOSE_LOG(G3D, "Scaled %i texels", texelsScaledThisFrame_);
|
||||
|
@ -441,13 +443,21 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) {
|
|||
u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0;
|
||||
int w = gstate.getTextureWidth(0);
|
||||
int h = gstate.getTextureHeight(0);
|
||||
double replaceStart = time_now_d();
|
||||
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
|
||||
if (replaced.GetSize(0, w, h)) {
|
||||
// We're replacing, so we won't scale.
|
||||
scaleFactor = 1;
|
||||
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
|
||||
maxLevel = replaced.MaxLevel();
|
||||
badMipSizes = false;
|
||||
if (replaced.IsReady(replacementFrameBudget_ - replacementTimeThisFrame_)) {
|
||||
if (replaced.GetSize(0, w, h)) {
|
||||
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||
|
||||
// We're replacing, so we won't scale.
|
||||
scaleFactor = 1;
|
||||
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
|
||||
entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE;
|
||||
maxLevel = replaced.MaxLevel();
|
||||
badMipSizes = false;
|
||||
}
|
||||
} else if (replaced.MaxLevel() >= 0) {
|
||||
entry->status |= TexCacheEntry::STATUS_TO_REPLACE;
|
||||
}
|
||||
|
||||
// Don't scale the PPGe texture.
|
||||
|
@ -615,7 +625,9 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re
|
|||
|
||||
gpuStats.numTexturesDecoded++;
|
||||
if (replaced.GetSize(level, w, h)) {
|
||||
double replaceStart = time_now_d();
|
||||
replaced.Load(level, rect.pBits, rect.Pitch);
|
||||
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||
dstFmt = ToD3D9Format(replaced.Format(level));
|
||||
} else {
|
||||
GETextureFormat tfmt = (GETextureFormat)entry.format;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "Common/Math/math_util.h"
|
||||
#include "Common/Profiler/Profiler.h"
|
||||
#include "Common/GPU/OpenGL/GLRenderManager.h"
|
||||
#include "Common/TimeUtil.h"
|
||||
|
||||
#include "Core/Config.h"
|
||||
#include "Core/Host.h"
|
||||
|
@ -152,6 +153,7 @@ static void ConvertColors(void *dstBuf, const void *srcBuf, Draw::DataFormat dst
|
|||
void TextureCacheGLES::StartFrame() {
|
||||
InvalidateLastTexture();
|
||||
timesInvalidatedAllThisFrame_ = 0;
|
||||
replacementTimeThisFrame_ = 0.0;
|
||||
|
||||
GLRenderManager *renderManager = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
if (!lowMemoryMode_ && renderManager->SawOutOfMemory()) {
|
||||
|
@ -505,13 +507,21 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) {
|
|||
u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0;
|
||||
int w = gstate.getTextureWidth(0);
|
||||
int h = gstate.getTextureHeight(0);
|
||||
double replaceStart = time_now_d();
|
||||
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
|
||||
if (replaced.GetSize(0, w, h)) {
|
||||
// We're replacing, so we won't scale.
|
||||
scaleFactor = 1;
|
||||
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
|
||||
maxLevel = replaced.MaxLevel();
|
||||
badMipSizes = false;
|
||||
if (replaced.IsReady(replacementFrameBudget_ - replacementTimeThisFrame_)) {
|
||||
if (replaced.GetSize(0, w, h)) {
|
||||
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||
|
||||
// We're replacing, so we won't scale.
|
||||
scaleFactor = 1;
|
||||
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
|
||||
entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE;
|
||||
maxLevel = replaced.MaxLevel();
|
||||
badMipSizes = false;
|
||||
}
|
||||
} else if (replaced.MaxLevel() >= 0) {
|
||||
entry->status |= TexCacheEntry::STATUS_TO_REPLACE;
|
||||
}
|
||||
|
||||
// Don't scale the PPGe texture.
|
||||
|
@ -658,7 +668,9 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r
|
|||
int bpp = replaced.Format(level) == ReplacedTextureFormat::F_8888 ? 4 : 2;
|
||||
decPitch = w * bpp;
|
||||
uint8_t *rearrange = (uint8_t *)AllocateAlignedMemory(decPitch * h, 16);
|
||||
double replaceStart = time_now_d();
|
||||
replaced.Load(level, rearrange, decPitch);
|
||||
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||
pixelData = rearrange;
|
||||
|
||||
dstFmt = ToDataFormat(replaced.Format(level));
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "Common/Data/Convert/ColorConv.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Common/TimeUtil.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/MemMap.h"
|
||||
|
@ -442,6 +443,7 @@ void TextureCacheVulkan::StartFrame() {
|
|||
|
||||
timesInvalidatedAllThisFrame_ = 0;
|
||||
texelsScaledThisFrame_ = 0;
|
||||
replacementTimeThisFrame_ = 0.0;
|
||||
|
||||
if (clearCacheNextFrame_) {
|
||||
Clear(true);
|
||||
|
@ -776,13 +778,21 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
|||
u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0;
|
||||
int w = gstate.getTextureWidth(0);
|
||||
int h = gstate.getTextureHeight(0);
|
||||
double replaceStart = time_now_d();
|
||||
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
|
||||
if (replaced.GetSize(0, w, h)) {
|
||||
// We're replacing, so we won't scale.
|
||||
scaleFactor = 1;
|
||||
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
|
||||
maxLevel = replaced.MaxLevel();
|
||||
badMipSizes = false;
|
||||
if (replaced.IsReady(replacementFrameBudget_ - replacementTimeThisFrame_)) {
|
||||
if (replaced.GetSize(0, w, h)) {
|
||||
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||
|
||||
// We're replacing, so we won't scale.
|
||||
scaleFactor = 1;
|
||||
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
|
||||
entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE;
|
||||
maxLevel = replaced.MaxLevel();
|
||||
badMipSizes = false;
|
||||
}
|
||||
} else if (replaced.MaxLevel() >= 0) {
|
||||
entry->status |= TexCacheEntry::STATUS_TO_REPLACE;
|
||||
}
|
||||
|
||||
bool hardwareScaling = g_Config.bTexHardwareScaling && (uploadCS_ != VK_NULL_HANDLE || copyCS_ != VK_NULL_HANDLE);
|
||||
|
@ -934,7 +944,9 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
|||
if (replaced.Valid()) {
|
||||
// Directly load the replaced image.
|
||||
data = drawEngine_->GetPushBufferForTextureData()->PushAligned(size, &bufferOffset, &texBuf, pushAlignment);
|
||||
replaceStart = time_now_d();
|
||||
replaced.Load(i, data, stride); // if it fails, it'll just be garbage data... OK for now.
|
||||
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||
entry->vkTex->UploadMip(cmdInit, i, mipWidth, mipHeight, texBuf, bufferOffset, stride / bpp);
|
||||
} else {
|
||||
auto dispatchCompute = [&](VkDescriptorSet descSet) {
|
||||
|
|
Loading…
Add table
Reference in a new issue