mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #17143 from hrydgard/refactor-force-filtering
Refactor the replacement "force filtering" feature
This commit is contained in:
commit
e6ceaa541c
10 changed files with 81 additions and 50 deletions
|
@ -145,7 +145,7 @@ void ReplacedTexture::PurgeIfNotUsedSinceTime(double t) {
|
|||
}
|
||||
|
||||
// This can only return true if ACTIVE or NOT_FOUND.
|
||||
bool ReplacedTexture::IsReady(double budget) {
|
||||
bool ReplacedTexture::Poll(double budget) {
|
||||
_assert_(vfs_ != nullptr);
|
||||
|
||||
double now = time_now_d();
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "Common/File/VFS/VFS.h"
|
||||
#include "Common/GPU/thin3d.h"
|
||||
#include "Common/Log.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
|
||||
class TextureReplacer;
|
||||
class LimitedWaitable;
|
||||
|
@ -75,6 +76,7 @@ struct ReplacementDesc {
|
|||
uint32_t hash;
|
||||
int w;
|
||||
int h;
|
||||
TextureFiltering forceFiltering;
|
||||
std::string hashfiles;
|
||||
Path basePath;
|
||||
std::vector<std::string> filenames;
|
||||
|
@ -147,6 +149,15 @@ public:
|
|||
return sz;
|
||||
}
|
||||
|
||||
bool ForceFiltering(TextureFiltering *forceFiltering) const {
|
||||
if (desc_.forceFiltering != (TextureFiltering)0) {
|
||||
*forceFiltering = desc_.forceFiltering;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int NumLevels() const {
|
||||
_dbg_assert_(State() == ReplacementState::ACTIVE);
|
||||
return (int)levels_.size();
|
||||
|
@ -161,7 +172,7 @@ public:
|
|||
return (u8)alphaStatus_;
|
||||
}
|
||||
|
||||
bool IsReady(double budget);
|
||||
bool Poll(double budget);
|
||||
bool CopyLevelTo(int level, uint8_t *out, size_t outDataSize, int rowPitch);
|
||||
|
||||
std::string logId_;
|
||||
|
|
|
@ -252,8 +252,8 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, const TexCac
|
|||
|
||||
// Filtering overrides from replacements or settings.
|
||||
TextureFiltering forceFiltering = TEX_FILTER_AUTO;
|
||||
u64 cachekey = replacer_.Enabled() ? (entry ? entry->CacheKey() : 0) : 0;
|
||||
if (!replacer_.Enabled() || entry == nullptr || !replacer_.FindFiltering(cachekey, entry->fullhash, &forceFiltering)) {
|
||||
bool useReplacerFiltering = entry && replacer_.Enabled() && entry->replacedTexture && entry->replacedTexture->ForceFiltering(&forceFiltering);
|
||||
if (!useReplacerFiltering) {
|
||||
switch (g_Config.iTexFiltering) {
|
||||
case TEX_FILTER_AUTO:
|
||||
// Follow what the game wants. We just do a single heuristic change to avoid bleeding of wacky color test colors
|
||||
|
@ -328,7 +328,7 @@ SamplerCacheKey TextureCacheCommon::GetFramebufferSamplingParams(u16 bufferWidth
|
|||
// Kill any mipmapping settings.
|
||||
key.mipEnable = false;
|
||||
key.mipFilt = false;
|
||||
key.aniso = 0.0;
|
||||
key.aniso = 0.0f;
|
||||
key.maxLevel = 0.0f;
|
||||
key.lodBias = 0.0f;
|
||||
|
||||
|
@ -531,11 +531,11 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
|
|||
int w0 = gstate.getTextureWidth(0);
|
||||
int h0 = gstate.getTextureHeight(0);
|
||||
int d0 = 1;
|
||||
ReplacedTexture *replaced = FindReplacement(entry, w0, h0, d0);
|
||||
if (replaced) {
|
||||
if (entry->replacedTexture) {
|
||||
PollReplacement(entry, &w0, &h0, &d0);
|
||||
// This texture is pending a replacement load.
|
||||
// So check the replacer if it's reached a conclusion.
|
||||
switch (replaced->State()) {
|
||||
switch (entry->replacedTexture->State()) {
|
||||
case ReplacementState::NOT_FOUND:
|
||||
// Didn't find a replacement, so stop looking.
|
||||
// DEBUG_LOG(G3D, "No replacement for texture %dx%d", w0, h0);
|
||||
|
@ -858,7 +858,7 @@ void TextureCacheCommon::HandleTextureChange(TexCacheEntry *const entry, const c
|
|||
if (doDelete) {
|
||||
ForgetLastTexture();
|
||||
ReleaseTexture(entry, true);
|
||||
entry->status &= ~TexCacheEntry::STATUS_IS_SCALED;
|
||||
entry->status &= ~(TexCacheEntry::STATUS_IS_SCALED_OR_REPLACED | TexCacheEntry::STATUS_TO_REPLACE);
|
||||
}
|
||||
|
||||
// Mark as hashing, if marked as reliable.
|
||||
|
@ -1502,8 +1502,8 @@ u32 TextureCacheCommon::EstimateTexMemoryUsage(const TexCacheEntry *entry) {
|
|||
return pixelSize << (dimW + dimH);
|
||||
}
|
||||
|
||||
ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int &w, int &h, int &d) {
|
||||
if (d != 1) {
|
||||
ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int *w, int *h, int *d) {
|
||||
if (*d != 1) {
|
||||
// We don't yet support replacing 3D textures.
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1519,32 +1519,40 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int &
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Allow some delay to reduce pop-in.
|
||||
constexpr double MAX_BUDGET_PER_TEX = 0.25 / 60.0;
|
||||
|
||||
double replaceStart = time_now_d();
|
||||
u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0;
|
||||
ReplacedTexture *replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
|
||||
ReplacedTexture *replaced = replacer_.FindReplacement(cachekey, entry->fullhash, *w, *h);
|
||||
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||
if (!replaced) {
|
||||
// TODO: Remove the flag here?
|
||||
// entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE;
|
||||
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||
return nullptr;
|
||||
}
|
||||
entry->replacedTexture = replaced; // we know it's non-null here.
|
||||
PollReplacement(entry, w, h, d);
|
||||
return replaced;
|
||||
}
|
||||
|
||||
void TextureCacheCommon::PollReplacement(TexCacheEntry *entry, int *w, int *h, int *d) {
|
||||
// Allow some delay to reduce pop-in.
|
||||
constexpr double MAX_BUDGET_PER_TEX = 0.25 / 60.0;
|
||||
|
||||
double budget = std::min(MAX_BUDGET_PER_TEX, replacementFrameBudget_ - replacementTimeThisFrame_);
|
||||
if (replaced->IsReady(budget)) {
|
||||
if (replaced->State() == ReplacementState::ACTIVE) {
|
||||
replaced->GetSize(0, &w, &h);
|
||||
|
||||
double replaceStart = time_now_d();
|
||||
if (entry->replacedTexture->Poll(budget)) {
|
||||
if (entry->replacedTexture->State() == ReplacementState::ACTIVE) {
|
||||
entry->replacedTexture->GetSize(0, w, h);
|
||||
// Consider it already "scaled.".
|
||||
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
|
||||
entry->status |= TexCacheEntry::STATUS_IS_SCALED_OR_REPLACED;
|
||||
}
|
||||
|
||||
// Remove the flag, even if it was invalid.
|
||||
entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE;
|
||||
}
|
||||
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||
|
||||
switch (replaced->State()) {
|
||||
switch (entry->replacedTexture->State()) {
|
||||
case ReplacementState::UNLOADED:
|
||||
case ReplacementState::PENDING:
|
||||
// Make sure we keep polling.
|
||||
|
@ -1553,8 +1561,6 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int &
|
|||
default:
|
||||
break;
|
||||
}
|
||||
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||
return replaced;
|
||||
}
|
||||
|
||||
// This is only used in the GLES backend, where we don't point these to video memory.
|
||||
|
@ -2073,6 +2079,8 @@ void TextureCacheCommon::ApplyTexture() {
|
|||
// This prevents temporary scaling perf hits on the first second of video.
|
||||
if (IsVideo(entry->addr)) {
|
||||
entry->status |= TexCacheEntry::STATUS_CHANGE_FREQUENT | TexCacheEntry::STATUS_VIDEO;
|
||||
} else {
|
||||
entry->status &= ~TexCacheEntry::STATUS_VIDEO;
|
||||
}
|
||||
|
||||
if (nextNeedsRehash_) {
|
||||
|
@ -2782,7 +2790,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt
|
|||
plan.scaleFactor = 1;
|
||||
} else {
|
||||
entry->status &= ~TexCacheEntry::STATUS_TO_SCALE;
|
||||
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
|
||||
entry->status |= TexCacheEntry::STATUS_IS_SCALED_OR_REPLACED;
|
||||
texelsScaledThisFrame_ += plan.w * plan.h;
|
||||
}
|
||||
}
|
||||
|
@ -2819,17 +2827,18 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt
|
|||
}
|
||||
|
||||
if (canReplace) {
|
||||
plan.replaced = FindReplacement(entry, plan.w, plan.h, plan.depth);
|
||||
plan.replaceValid = plan.replaced ? plan.replaced->State() == ReplacementState::ACTIVE : false;
|
||||
// This is the "trigger point" for replacement.
|
||||
plan.replaced = FindReplacement(entry, &plan.w, &plan.h, &plan.depth);
|
||||
plan.doReplace = plan.replaced ? plan.replaced->State() == ReplacementState::ACTIVE : false;
|
||||
} else {
|
||||
plan.replaced = nullptr;
|
||||
plan.replaceValid = false;
|
||||
plan.doReplace = false;
|
||||
}
|
||||
|
||||
// NOTE! Last chance to change scale factor here!
|
||||
|
||||
plan.saveTexture = false;
|
||||
if (plan.replaceValid) {
|
||||
if (plan.doReplace) {
|
||||
// We're replacing, so we won't scale.
|
||||
plan.scaleFactor = 1;
|
||||
// We're ignoring how many levels were specified - instead we just load all available from the replacer.
|
||||
|
@ -2839,7 +2848,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt
|
|||
// But, we still need to create the texture at a larger size.
|
||||
plan.replaced->GetSize(0, &plan.createW, &plan.createH);
|
||||
} else {
|
||||
if (replacer_.Enabled() && !plan.replaceValid && plan.depth == 1 && canReplace) {
|
||||
if (replacer_.Enabled() && !plan.doReplace && plan.depth == 1 && canReplace) {
|
||||
ReplacedTextureDecodeInfo replacedInfo;
|
||||
// TODO: Do we handle the race where a replacement becomes valid AFTER this but before we save?
|
||||
replacedInfo.cachekey = entry->CacheKey();
|
||||
|
@ -2889,7 +2898,7 @@ void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, s
|
|||
|
||||
PROFILE_THIS_SCOPE("decodetex");
|
||||
|
||||
if (plan.replaceValid) {
|
||||
if (plan.doReplace) {
|
||||
plan.replaced->GetSize(srcLevel, &w, &h);
|
||||
double replaceStart = time_now_d();
|
||||
plan.replaced->CopyLevelTo(srcLevel, data, dataSize, stride);
|
||||
|
|
|
@ -105,12 +105,18 @@ struct TextureDefinition {
|
|||
GETextureFormat format;
|
||||
};
|
||||
|
||||
// TODO: Shrink this struct. There is some fluff.
|
||||
// Texture replacement state machine:
|
||||
// Call FindReplacement during PrepareBuild.
|
||||
// If replacedTexture gets set: If not found, -> STATUS_TO_REPLACE, otherwise directly -> STATUS_IS_SCALED.
|
||||
// If replacedTexture is null, leave it at null.
|
||||
// If replacedTexture is set in SetTexture and STATUS_IS_SCALED is not set, query status. If ready rebuild texture, which will set STATUS_IS_SCALED.
|
||||
|
||||
// NOTE: These only handle textures loaded directly from PSP memory contents.
|
||||
// Framebuffer textures do not have entries, we bind the framebuffers directly.
|
||||
// At one point we might merge the concepts of framebuffers and textures, but that
|
||||
// moment is far away.
|
||||
|
||||
// TODO: Shrink this struct. There is some fluff.
|
||||
struct TexCacheEntry {
|
||||
~TexCacheEntry() {
|
||||
if (texturePtr || textureName || vkTex)
|
||||
|
@ -133,7 +139,7 @@ struct TexCacheEntry {
|
|||
STATUS_CHANGE_FREQUENT = 0x10, // Changes often (less than 6 frames in between.)
|
||||
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_IS_SCALED_OR_REPLACED = 0x100, // Has been scaled already (ignored for replacement checks).
|
||||
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
|
||||
|
@ -287,14 +293,14 @@ struct BuildTexturePlan {
|
|||
// The replacement for the texture.
|
||||
ReplacedTexture *replaced;
|
||||
// Need to only check once since it can change during the load!
|
||||
bool replaceValid;
|
||||
bool doReplace;
|
||||
bool saveTexture;
|
||||
|
||||
// TODO: Expand32 should probably also be decided in PrepareBuildTexture.
|
||||
bool decodeToClut8;
|
||||
|
||||
void GetMipSize(int level, int *w, int *h) const {
|
||||
if (replaceValid) {
|
||||
if (doReplace) {
|
||||
replaced->GetSize(level, w, h);
|
||||
return;
|
||||
}
|
||||
|
@ -383,7 +389,8 @@ protected:
|
|||
CheckAlphaResult DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, TexDecodeFlags flags);
|
||||
void UnswizzleFromMem(u32 *dest, u32 destPitch, const u8 *texptr, u32 bufw, u32 height, u32 bytesPerPixel);
|
||||
CheckAlphaResult ReadIndexedTex(u8 *out, int outPitch, int level, const u8 *texptr, int bytesPerIndex, int bufw, bool reverseColors, bool expandTo32Bit);
|
||||
ReplacedTexture *FindReplacement(TexCacheEntry *entry, int &w, int &h, int &d);
|
||||
ReplacedTexture *FindReplacement(TexCacheEntry *entry, int *w, int *h, int *d);
|
||||
void PollReplacement(TexCacheEntry *entry, int *w, int *h, int *d);
|
||||
|
||||
// Return value is mapData normally, but could be another buffer allocated with AllocateAlignedMemory.
|
||||
void LoadTextureLevel(TexCacheEntry &entry, uint8_t *mapData, size_t dataSize, int mapRowPitch, BuildTexturePlan &plan, int srcLevel, Draw::DataFormat dstFmt, TexDecodeFlags texDecFlags);
|
||||
|
|
|
@ -501,6 +501,9 @@ ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
desc.forceFiltering = (TextureFiltering)0; // invalid value
|
||||
FindFiltering(cachekey, hash, &desc.forceFiltering);
|
||||
|
||||
if (!foundAlias) {
|
||||
// We'll just need to generate the names for each level.
|
||||
// By default, we look for png since that's also what's dumped.
|
||||
|
|
|
@ -106,7 +106,6 @@ public:
|
|||
|
||||
// Returns nullptr if not found.
|
||||
ReplacedTexture *FindReplacement(u64 cachekey, u32 hash, int w, int h);
|
||||
bool FindFiltering(u64 cachekey, u32 hash, TextureFiltering *forceFiltering);
|
||||
|
||||
// Check if a NotifyTextureDecoded for this texture is desired (used to avoid reads from write-combined memory.)
|
||||
bool WillSave(const ReplacedTextureDecodeInfo &replacedInfo);
|
||||
|
@ -125,6 +124,8 @@ public:
|
|||
static std::string HashName(u64 cachekey, u32 hash, int level);
|
||||
|
||||
protected:
|
||||
bool FindFiltering(u64 cachekey, u32 hash, TextureFiltering *forceFiltering);
|
||||
|
||||
bool LoadIni();
|
||||
bool LoadIniValues(IniFile &ini, bool isOverride = false);
|
||||
void ParseHashRange(const std::string &key, const std::string &value);
|
||||
|
|
|
@ -261,7 +261,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) {
|
|||
}
|
||||
|
||||
DXGI_FORMAT dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat());
|
||||
if (plan.replaceValid) {
|
||||
if (plan.doReplace) {
|
||||
dstFmt = ToDXGIFormat(plan.replaced->Format());
|
||||
} else if (plan.scaleFactor > 1 || plan.saveTexture) {
|
||||
dstFmt = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
|
@ -298,7 +298,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) {
|
|||
int stride = 0;
|
||||
|
||||
int dataSize;
|
||||
if (plan.replaceValid) {
|
||||
if (plan.doReplace) {
|
||||
int blockSize = 0;
|
||||
if (Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), &blockSize)) {
|
||||
stride = ((mipWidth + 3) & ~3) * blockSize / 4; // Number of blocks * 4 * Size of a block / 4
|
||||
|
@ -404,7 +404,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) {
|
|||
entry->status &= ~TexCacheEntry::STATUS_NO_MIPS;
|
||||
}
|
||||
|
||||
if (plan.replaceValid) {
|
||||
if (plan.doReplace) {
|
||||
entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus()));
|
||||
|
||||
if (!Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), nullptr)) {
|
||||
|
|
|
@ -230,7 +230,7 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) {
|
|||
}
|
||||
|
||||
D3DFORMAT dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat());
|
||||
if (plan.replaceValid) {
|
||||
if (plan.doReplace) {
|
||||
dstFmt = ToD3D9Format(plan.replaced->Format());
|
||||
} else if (plan.scaleFactor > 1 || plan.saveTexture) {
|
||||
dstFmt = D3DFMT_A8R8G8B8;
|
||||
|
@ -316,7 +316,7 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) {
|
|||
entry->status |= TexCacheEntry::STATUS_3D;
|
||||
}
|
||||
|
||||
if (plan.replaceValid) {
|
||||
if (plan.doReplace) {
|
||||
entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus()));
|
||||
|
||||
if (!Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), nullptr)) {
|
||||
|
|
|
@ -246,7 +246,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) {
|
|||
int th = plan.createH;
|
||||
|
||||
Draw::DataFormat dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat());
|
||||
if (plan.replaceValid) {
|
||||
if (plan.doReplace) {
|
||||
plan.replaced->GetSize(plan.baseLevelSrc, &tw, &th);
|
||||
dstFmt = plan.replaced->Format();
|
||||
} else if (plan.scaleFactor > 1 || plan.saveTexture) {
|
||||
|
@ -296,7 +296,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) {
|
|||
|
||||
bool bc = false;
|
||||
|
||||
if (plan.replaceValid) {
|
||||
if (plan.doReplace) {
|
||||
int blockSize = 0;
|
||||
if (Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), &blockSize)) {
|
||||
stride = mipWidth * 4;
|
||||
|
@ -357,7 +357,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) {
|
|||
render_->FinalizeTexture(entry->textureName, 1, false);
|
||||
}
|
||||
|
||||
if (plan.replaceValid) {
|
||||
if (plan.doReplace) {
|
||||
entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -435,7 +435,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
|||
VkFormat dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat());
|
||||
|
||||
if (plan.scaleFactor > 1) {
|
||||
_dbg_assert_(!plan.replaceValid);
|
||||
_dbg_assert_(!plan.doReplace);
|
||||
// Whether hardware or software scaling, this is the dest format.
|
||||
dstFmt = VULKAN_8888_FORMAT;
|
||||
} else if (plan.decodeToClut8) {
|
||||
|
@ -445,7 +445,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
|||
// We don't generate mipmaps for 512x512 textures because they're almost exclusively used for menu backgrounds
|
||||
// and similar, which don't really need it.
|
||||
// Also, if using replacements, check that we really can generate mips for this format - that's not possible for compressed ones.
|
||||
if (g_Config.iTexFiltering == TEX_FILTER_AUTO_MAX_QUALITY && plan.w <= 256 && plan.h <= 256 && (!plan.replaceValid || plan.replaced->Format() == Draw::DataFormat::R8G8B8A8_UNORM)) {
|
||||
if (g_Config.iTexFiltering == TEX_FILTER_AUTO_MAX_QUALITY && plan.w <= 256 && plan.h <= 256 && (!plan.doReplace || plan.replaced->Format() == Draw::DataFormat::R8G8B8A8_UNORM)) {
|
||||
// Boost the number of mipmaps.
|
||||
if (plan.maxPossibleLevels > plan.levelsToCreate) { // TODO: Should check against levelsToLoad, no?
|
||||
// We have to generate mips with a shader. This requires decoding to R8G8B8A8_UNORM format to avoid extra complications.
|
||||
|
@ -458,7 +458,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
|||
VkFormat actualFmt = plan.scaleFactor > 1 ? VULKAN_8888_FORMAT : dstFmt;
|
||||
bool bcFormat = false;
|
||||
int bcAlign = 0;
|
||||
if (plan.replaceValid) {
|
||||
if (plan.doReplace) {
|
||||
Draw::DataFormat fmt = plan.replaced->Format();
|
||||
bcFormat = Draw::DataFormatIsBlockCompressed(fmt, &bcAlign);
|
||||
actualFmt = ToVulkanFormat(fmt);
|
||||
|
@ -591,7 +591,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
|||
};
|
||||
|
||||
bool dataScaled = true;
|
||||
if (plan.replaceValid) {
|
||||
if (plan.doReplace) {
|
||||
int rowLength = pixelStride;
|
||||
if (bcFormat) {
|
||||
// For block compressed formats, we just set the upload size to the data size..
|
||||
|
@ -601,7 +601,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
|||
// Directly load the replaced image.
|
||||
data = pushBuffer->Allocate(uploadSize, pushAlignment, &texBuf, &bufferOffset);
|
||||
double replaceStart = time_now_d();
|
||||
if (!plan.replaced->CopyLevelTo(plan.baseLevelSrc + i, (uint8_t *)data, uploadSize, byteStride)) { // If plan.replaceValid, this shouldn't fail.
|
||||
if (!plan.replaced->CopyLevelTo(plan.baseLevelSrc + i, (uint8_t *)data, uploadSize, byteStride)) { // If plan.doReplace, this shouldn't fail.
|
||||
WARN_LOG(G3D, "Failed to copy replaced texture level");
|
||||
// TODO: Fill with some pattern?
|
||||
}
|
||||
|
@ -681,7 +681,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
|||
entry->status |= TexCacheEntry::STATUS_3D;
|
||||
}
|
||||
|
||||
if (plan.replaceValid) {
|
||||
if (plan.doReplace) {
|
||||
entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus()));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue