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) {
|
bool ReplacedTexture::Load(int level, void *out, int rowPitch) {
|
||||||
_assert_msg_((size_t)level < levels_.size(), "Invalid miplevel");
|
_assert_msg_((size_t)level < levels_.size(), "Invalid miplevel");
|
||||||
_assert_msg_(out != nullptr && rowPitch > 0, "Invalid out/pitch");
|
_assert_msg_(out != nullptr && rowPitch > 0, "Invalid out/pitch");
|
||||||
|
|
|
@ -153,6 +153,8 @@ struct ReplacedTexture {
|
||||||
return (u8)alphaStatus_;
|
return (u8)alphaStatus_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsReady(double budget);
|
||||||
|
|
||||||
bool Load(int level, void *out, int rowPitch);
|
bool Load(int level, void *out, int rowPitch);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -472,6 +472,10 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
|
||||||
reason = "scaling";
|
reason = "scaling";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (match && (entry->status & TexCacheEntry::STATUS_TO_REPLACE) && replacementTimeThisFrame_ <= replacementFrameBudget_) {
|
||||||
|
match = false;
|
||||||
|
reason = "replacing";
|
||||||
|
}
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
// got one!
|
// got one!
|
||||||
|
|
|
@ -123,16 +123,17 @@ struct TexCacheEntry {
|
||||||
STATUS_CLUT_RECHECK = 0x20, // Another texture with same addr had a hashfail.
|
STATUS_CLUT_RECHECK = 0x20, // Another texture with same addr had a hashfail.
|
||||||
STATUS_TO_SCALE = 0x80, // Pending texture scaling in a later frame.
|
STATUS_TO_SCALE = 0x80, // Pending texture scaling in a later frame.
|
||||||
STATUS_IS_SCALED = 0x100, // Has been scaled (can't be replaceImages'd.)
|
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
|
// 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
|
// 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.
|
// 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.
|
// Status, but int so we can zero initialize.
|
||||||
|
@ -334,6 +335,9 @@ protected:
|
||||||
int decimationCounter_;
|
int decimationCounter_;
|
||||||
int texelsScaledThisFrame_ = 0;
|
int texelsScaledThisFrame_ = 0;
|
||||||
int timesInvalidatedAllThisFrame_ = 0;
|
int timesInvalidatedAllThisFrame_ = 0;
|
||||||
|
double replacementTimeThisFrame_ = 0;
|
||||||
|
// TODO: Maybe vary by FPS...
|
||||||
|
double replacementFrameBudget_ = 0.75 / 60.0;
|
||||||
|
|
||||||
TexCache cache_;
|
TexCache cache_;
|
||||||
u32 cacheSizeEstimate_ = 0;
|
u32 cacheSizeEstimate_ = 0;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include <d3d11.h>
|
#include <d3d11.h>
|
||||||
|
|
||||||
|
#include "Common/TimeUtil.h"
|
||||||
#include "Core/MemMap.h"
|
#include "Core/MemMap.h"
|
||||||
#include "Core/Reporting.h"
|
#include "Core/Reporting.h"
|
||||||
#include "GPU/ge_constants.h"
|
#include "GPU/ge_constants.h"
|
||||||
|
@ -169,6 +170,7 @@ void TextureCacheD3D11::InvalidateLastTexture() {
|
||||||
void TextureCacheD3D11::StartFrame() {
|
void TextureCacheD3D11::StartFrame() {
|
||||||
InvalidateLastTexture();
|
InvalidateLastTexture();
|
||||||
timesInvalidatedAllThisFrame_ = 0;
|
timesInvalidatedAllThisFrame_ = 0;
|
||||||
|
replacementTimeThisFrame_ = 0.0;
|
||||||
|
|
||||||
if (texelsScaledThisFrame_) {
|
if (texelsScaledThisFrame_) {
|
||||||
// INFO_LOG(G3D, "Scaled %i texels", 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;
|
u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0;
|
||||||
int w = gstate.getTextureWidth(0);
|
int w = gstate.getTextureWidth(0);
|
||||||
int h = gstate.getTextureHeight(0);
|
int h = gstate.getTextureHeight(0);
|
||||||
|
double replaceStart = time_now_d();
|
||||||
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
|
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
|
||||||
if (replaced.GetSize(0, w, h)) {
|
if (replaced.IsReady(replacementFrameBudget_ - replacementTimeThisFrame_)) {
|
||||||
// We're replacing, so we won't scale.
|
if (replaced.GetSize(0, w, h)) {
|
||||||
scaleFactor = 1;
|
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||||
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
|
|
||||||
maxLevel = replaced.MaxLevel();
|
// We're replacing, so we won't scale.
|
||||||
badMipSizes = false;
|
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.
|
// Don't scale the PPGe texture.
|
||||||
|
@ -678,7 +688,9 @@ void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &
|
||||||
if (replaced.GetSize(level, w, h)) {
|
if (replaced.GetSize(level, w, h)) {
|
||||||
mapData = (u32 *)AllocateAlignedMemory(w * h * sizeof(u32), 16);
|
mapData = (u32 *)AllocateAlignedMemory(w * h * sizeof(u32), 16);
|
||||||
mapRowPitch = w * 4;
|
mapRowPitch = w * 4;
|
||||||
|
double replaceStart = time_now_d();
|
||||||
replaced.Load(level, mapData, mapRowPitch);
|
replaced.Load(level, mapData, mapRowPitch);
|
||||||
|
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||||
dstFmt = ToDXGIFormat(replaced.Format(level));
|
dstFmt = ToDXGIFormat(replaced.Format(level));
|
||||||
} else {
|
} else {
|
||||||
GETextureFormat tfmt = (GETextureFormat)entry.format;
|
GETextureFormat tfmt = (GETextureFormat)entry.format;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "Common/TimeUtil.h"
|
||||||
#include "Core/MemMap.h"
|
#include "Core/MemMap.h"
|
||||||
#include "Core/Reporting.h"
|
#include "Core/Reporting.h"
|
||||||
#include "GPU/ge_constants.h"
|
#include "GPU/ge_constants.h"
|
||||||
|
@ -134,6 +135,7 @@ void TextureCacheDX9::ApplySamplingParams(const SamplerCacheKey &key) {
|
||||||
void TextureCacheDX9::StartFrame() {
|
void TextureCacheDX9::StartFrame() {
|
||||||
InvalidateLastTexture();
|
InvalidateLastTexture();
|
||||||
timesInvalidatedAllThisFrame_ = 0;
|
timesInvalidatedAllThisFrame_ = 0;
|
||||||
|
replacementTimeThisFrame_ = 0.0;
|
||||||
|
|
||||||
if (texelsScaledThisFrame_) {
|
if (texelsScaledThisFrame_) {
|
||||||
VERBOSE_LOG(G3D, "Scaled %i texels", 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;
|
u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0;
|
||||||
int w = gstate.getTextureWidth(0);
|
int w = gstate.getTextureWidth(0);
|
||||||
int h = gstate.getTextureHeight(0);
|
int h = gstate.getTextureHeight(0);
|
||||||
|
double replaceStart = time_now_d();
|
||||||
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
|
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
|
||||||
if (replaced.GetSize(0, w, h)) {
|
if (replaced.IsReady(replacementFrameBudget_ - replacementTimeThisFrame_)) {
|
||||||
// We're replacing, so we won't scale.
|
if (replaced.GetSize(0, w, h)) {
|
||||||
scaleFactor = 1;
|
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||||
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
|
|
||||||
maxLevel = replaced.MaxLevel();
|
// We're replacing, so we won't scale.
|
||||||
badMipSizes = false;
|
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.
|
// Don't scale the PPGe texture.
|
||||||
|
@ -615,7 +625,9 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re
|
||||||
|
|
||||||
gpuStats.numTexturesDecoded++;
|
gpuStats.numTexturesDecoded++;
|
||||||
if (replaced.GetSize(level, w, h)) {
|
if (replaced.GetSize(level, w, h)) {
|
||||||
|
double replaceStart = time_now_d();
|
||||||
replaced.Load(level, rect.pBits, rect.Pitch);
|
replaced.Load(level, rect.pBits, rect.Pitch);
|
||||||
|
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||||
dstFmt = ToD3D9Format(replaced.Format(level));
|
dstFmt = ToD3D9Format(replaced.Format(level));
|
||||||
} else {
|
} else {
|
||||||
GETextureFormat tfmt = (GETextureFormat)entry.format;
|
GETextureFormat tfmt = (GETextureFormat)entry.format;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "Common/Math/math_util.h"
|
#include "Common/Math/math_util.h"
|
||||||
#include "Common/Profiler/Profiler.h"
|
#include "Common/Profiler/Profiler.h"
|
||||||
#include "Common/GPU/OpenGL/GLRenderManager.h"
|
#include "Common/GPU/OpenGL/GLRenderManager.h"
|
||||||
|
#include "Common/TimeUtil.h"
|
||||||
|
|
||||||
#include "Core/Config.h"
|
#include "Core/Config.h"
|
||||||
#include "Core/Host.h"
|
#include "Core/Host.h"
|
||||||
|
@ -152,6 +153,7 @@ static void ConvertColors(void *dstBuf, const void *srcBuf, Draw::DataFormat dst
|
||||||
void TextureCacheGLES::StartFrame() {
|
void TextureCacheGLES::StartFrame() {
|
||||||
InvalidateLastTexture();
|
InvalidateLastTexture();
|
||||||
timesInvalidatedAllThisFrame_ = 0;
|
timesInvalidatedAllThisFrame_ = 0;
|
||||||
|
replacementTimeThisFrame_ = 0.0;
|
||||||
|
|
||||||
GLRenderManager *renderManager = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
GLRenderManager *renderManager = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||||
if (!lowMemoryMode_ && renderManager->SawOutOfMemory()) {
|
if (!lowMemoryMode_ && renderManager->SawOutOfMemory()) {
|
||||||
|
@ -505,13 +507,21 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) {
|
||||||
u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0;
|
u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0;
|
||||||
int w = gstate.getTextureWidth(0);
|
int w = gstate.getTextureWidth(0);
|
||||||
int h = gstate.getTextureHeight(0);
|
int h = gstate.getTextureHeight(0);
|
||||||
|
double replaceStart = time_now_d();
|
||||||
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
|
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
|
||||||
if (replaced.GetSize(0, w, h)) {
|
if (replaced.IsReady(replacementFrameBudget_ - replacementTimeThisFrame_)) {
|
||||||
// We're replacing, so we won't scale.
|
if (replaced.GetSize(0, w, h)) {
|
||||||
scaleFactor = 1;
|
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||||
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
|
|
||||||
maxLevel = replaced.MaxLevel();
|
// We're replacing, so we won't scale.
|
||||||
badMipSizes = false;
|
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.
|
// 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;
|
int bpp = replaced.Format(level) == ReplacedTextureFormat::F_8888 ? 4 : 2;
|
||||||
decPitch = w * bpp;
|
decPitch = w * bpp;
|
||||||
uint8_t *rearrange = (uint8_t *)AllocateAlignedMemory(decPitch * h, 16);
|
uint8_t *rearrange = (uint8_t *)AllocateAlignedMemory(decPitch * h, 16);
|
||||||
|
double replaceStart = time_now_d();
|
||||||
replaced.Load(level, rearrange, decPitch);
|
replaced.Load(level, rearrange, decPitch);
|
||||||
|
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||||
pixelData = rearrange;
|
pixelData = rearrange;
|
||||||
|
|
||||||
dstFmt = ToDataFormat(replaced.Format(level));
|
dstFmt = ToDataFormat(replaced.Format(level));
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include "Common/Data/Convert/ColorConv.h"
|
#include "Common/Data/Convert/ColorConv.h"
|
||||||
#include "Common/StringUtils.h"
|
#include "Common/StringUtils.h"
|
||||||
|
#include "Common/TimeUtil.h"
|
||||||
#include "Core/Config.h"
|
#include "Core/Config.h"
|
||||||
#include "Core/Host.h"
|
#include "Core/Host.h"
|
||||||
#include "Core/MemMap.h"
|
#include "Core/MemMap.h"
|
||||||
|
@ -442,6 +443,7 @@ void TextureCacheVulkan::StartFrame() {
|
||||||
|
|
||||||
timesInvalidatedAllThisFrame_ = 0;
|
timesInvalidatedAllThisFrame_ = 0;
|
||||||
texelsScaledThisFrame_ = 0;
|
texelsScaledThisFrame_ = 0;
|
||||||
|
replacementTimeThisFrame_ = 0.0;
|
||||||
|
|
||||||
if (clearCacheNextFrame_) {
|
if (clearCacheNextFrame_) {
|
||||||
Clear(true);
|
Clear(true);
|
||||||
|
@ -776,13 +778,21 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
||||||
u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0;
|
u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0;
|
||||||
int w = gstate.getTextureWidth(0);
|
int w = gstate.getTextureWidth(0);
|
||||||
int h = gstate.getTextureHeight(0);
|
int h = gstate.getTextureHeight(0);
|
||||||
|
double replaceStart = time_now_d();
|
||||||
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
|
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
|
||||||
if (replaced.GetSize(0, w, h)) {
|
if (replaced.IsReady(replacementFrameBudget_ - replacementTimeThisFrame_)) {
|
||||||
// We're replacing, so we won't scale.
|
if (replaced.GetSize(0, w, h)) {
|
||||||
scaleFactor = 1;
|
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||||
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
|
|
||||||
maxLevel = replaced.MaxLevel();
|
// We're replacing, so we won't scale.
|
||||||
badMipSizes = false;
|
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);
|
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()) {
|
if (replaced.Valid()) {
|
||||||
// Directly load the replaced image.
|
// Directly load the replaced image.
|
||||||
data = drawEngine_->GetPushBufferForTextureData()->PushAligned(size, &bufferOffset, &texBuf, pushAlignment);
|
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.
|
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);
|
entry->vkTex->UploadMip(cmdInit, i, mipWidth, mipHeight, texBuf, bufferOffset, stride / bpp);
|
||||||
} else {
|
} else {
|
||||||
auto dispatchCompute = [&](VkDescriptorSet descSet) {
|
auto dispatchCompute = [&](VkDescriptorSet descSet) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue