mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-20 06:00:58 +00:00
Replacer: Perform the padding to pow2 size during CopyLevelTo, not during load. Saves memory.
This commit is contained in:
parent
df41a5cebd
commit
79f4e73110
@ -250,7 +250,7 @@ void *AllocateAlignedMemory(size_t size, size_t alignment) {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
_assert_msg_(ptr != nullptr, "Failed to allocate aligned memory");
|
||||
_assert_msg_(ptr != nullptr, "Failed to allocate aligned memory of size %llu", size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
@ -256,6 +256,12 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the level dimensions.
|
||||
for (auto &level : levels_) {
|
||||
level.fullW = (level.w * desc_.w) / desc_.newW;
|
||||
level.fullH = (level.h * desc_.h) / desc_.newH;
|
||||
}
|
||||
|
||||
SetState(ReplacementState::ACTIVE);
|
||||
|
||||
if (threadWaitable_)
|
||||
@ -390,7 +396,6 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference
|
||||
ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format %s", filename.c_str(), magic.c_str());
|
||||
}
|
||||
|
||||
|
||||
// Already populated from cache. TODO: Move this above the first read, and take level.w/h from the cache.
|
||||
if (!data_[mipLevel].empty()) {
|
||||
vfs_->CloseFile(openFile);
|
||||
@ -398,13 +403,10 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference
|
||||
return LoadLevelResult::DONE;
|
||||
}
|
||||
|
||||
// Is this really the right place to do it?
|
||||
level.w = (level.w * desc_.w) / desc_.newW;
|
||||
level.h = (level.h * desc_.h) / desc_.newH;
|
||||
|
||||
if (good && mipLevel != 0) {
|
||||
// Check that the mipmap size is correct. Can't load mips of the wrong size.
|
||||
if (level.w != (levels_[0].w >> mipLevel) || level.h != (levels_[0].h >> mipLevel)) {
|
||||
// If loading a low mip directly (through png most likely), check that the mipmap size is correct.
|
||||
// Can't load mips of the wrong size.
|
||||
if (level.w != std::max(1, (levels_[0].w >> mipLevel)) || level.h != std::max(1, (levels_[0].h >> mipLevel))) {
|
||||
WARN_LOG(G3D, "Replacement mipmap invalid: size=%dx%d, expected=%dx%d (level %d)",
|
||||
level.w, level.h, levels_[0].w >> mipLevel, levels_[0].h >> mipLevel, mipLevel);
|
||||
good = false;
|
||||
@ -668,6 +670,13 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We pad the images right here during the copy.
|
||||
// TODO: Add support for the texture cache to scale texture coordinates instead.
|
||||
// It already supports this for render target textures that aren't powers of 2.
|
||||
|
||||
int outW = levels_[level].fullW;
|
||||
int outH = levels_[level].fullH;
|
||||
|
||||
// We probably could avoid this lock, but better to play it safe.
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
|
||||
@ -683,7 +692,7 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) {
|
||||
|
||||
if (fmt == Draw::DataFormat::R8G8B8A8_UNORM) {
|
||||
if (rowPitch < info.w * 4) {
|
||||
ERROR_LOG(G3D, "Replacement rowPitch=%d, but w=%d (level=%d)", rowPitch, info.w * 4, level);
|
||||
ERROR_LOG(G3D, "Replacement rowPitch=%d, but w=%d (level=%d) (too small)", rowPitch, info.w * 4, level);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -699,10 +708,18 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) {
|
||||
#ifdef PARALLEL_COPY
|
||||
const int MIN_LINES_PER_THREAD = 4;
|
||||
ParallelRangeLoop(&g_threadManager, [&](int l, int h) {
|
||||
int extraPixels = outW - info.w;
|
||||
for (int y = l; y < h; ++y) {
|
||||
memcpy((uint8_t *)out + rowPitch * y, data.data() + info.w * 4 * y, info.w * 4);
|
||||
// Fill the rest of the line with black.
|
||||
memset((uint8_t *)out + rowPitch * y + info.w * 4, 0, extraPixels * 4);
|
||||
}
|
||||
}, 0, info.h, MIN_LINES_PER_THREAD);
|
||||
// Memset the rest of the padding.
|
||||
for (int y = info.h; y < outH; y++) {
|
||||
uint8_t *dest = (uint8_t *)out + rowPitch * y;
|
||||
memset(dest, 0, outW * 4);
|
||||
}
|
||||
#else
|
||||
for (int y = 0; y < info.h; ++y) {
|
||||
memcpy((uint8_t *)out + rowPitch * y, data.data() + info.w * 4 * y, info.w * 4);
|
||||
|
@ -93,8 +93,12 @@ struct ReplacedTextureRef {
|
||||
|
||||
// Metadata about a given texture level.
|
||||
struct ReplacedTextureLevel {
|
||||
// Data dimensions
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
// PSP texture dimensions
|
||||
int fullW = 0;
|
||||
int fullH = 0;
|
||||
|
||||
// To be able to reload, we need to be able to reopen, unfortunate we can't use zip_file_t.
|
||||
// TODO: This really belongs on the level in the cache, not in the individual ReplacedTextureLevel objects.
|
||||
@ -121,8 +125,8 @@ public:
|
||||
void GetSize(int level, int *w, int *h) const {
|
||||
_dbg_assert_(State() == ReplacementState::ACTIVE);
|
||||
_dbg_assert_(level < levels_.size());
|
||||
*w = levels_[level].w;
|
||||
*h = levels_[level].h;
|
||||
*w = levels_[level].fullW;
|
||||
*h = levels_[level].fullH;
|
||||
}
|
||||
|
||||
int GetLevelDataSize(int level) const {
|
||||
|
Loading…
x
Reference in New Issue
Block a user