mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Centralize texture deindexing more.
This commit is contained in:
parent
0519b3ef79
commit
339f065a5c
8 changed files with 173 additions and 322 deletions
|
@ -46,6 +46,7 @@ TextureCacheCommon::TextureCacheCommon()
|
|||
// Zap so we get consistent behavior if the game fails to load some of the CLUT.
|
||||
memset(clutBufRaw_, 0, 1024 * sizeof(u32));
|
||||
memset(clutBufConverted_, 0, 1024 * sizeof(u32));
|
||||
clutBuf_ = clutBufConverted_;
|
||||
|
||||
// These buffers will grow if necessary, but most won't need more than this.
|
||||
tmpTexBuf32.resize(512 * 512); // 1MB
|
||||
|
@ -465,3 +466,74 @@ u32 TextureCacheCommon::EstimateTexMemoryUsage(const TexCacheEntry *entry) {
|
|||
// This in other words multiplies by w and h.
|
||||
return pixelSize << (dimW + dimH);
|
||||
}
|
||||
|
||||
bool TextureCacheCommon::ReadIndexedTex(u8 *out, int outPitch, int level, const u8 *texptr, int bytesPerIndex, int bufw) {
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
|
||||
if (gstate.isTextureSwizzled()) {
|
||||
tmpTexBuf32.resize(bufw * ((h + 7) & ~7));
|
||||
UnswizzleFromMem(tmpTexBuf32.data(), bufw * bytesPerIndex, texptr, bufw, h, bytesPerIndex);
|
||||
texptr = (u8 *)tmpTexBuf32.data();
|
||||
}
|
||||
|
||||
switch (gstate.getClutPaletteFormat()) {
|
||||
case GE_CMODE_16BIT_BGR5650:
|
||||
case GE_CMODE_16BIT_ABGR5551:
|
||||
case GE_CMODE_16BIT_ABGR4444:
|
||||
{
|
||||
const u16 *clut = GetCurrentClut<u16>();
|
||||
switch (bytesPerIndex) {
|
||||
case 1:
|
||||
for (int y = 0; y < h; ++y) {
|
||||
DeIndexTexture((u16 *)(out + outPitch * y), (const u8 *)texptr + bufw * y, w, clut);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
for (int y = 0; y < h; ++y) {
|
||||
DeIndexTexture((u16 *)(out + outPitch * y), (const u16_le *)texptr + bufw * y, w, clut);
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
for (int y = 0; y < h; ++y) {
|
||||
DeIndexTexture((u16 *)(out + outPitch * y), (const u32_le *)texptr + bufw * y, w, clut);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_CMODE_32BIT_ABGR8888:
|
||||
{
|
||||
const u32 *clut = GetCurrentClut<u32>();
|
||||
switch (bytesPerIndex) {
|
||||
case 1:
|
||||
for (int y = 0; y < h; ++y) {
|
||||
DeIndexTexture((u32 *)(out + outPitch * y), (const u8 *)texptr + bufw * y, w, clut);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
for (int y = 0; y < h; ++y) {
|
||||
DeIndexTexture((u32 *)(out + outPitch * y), (const u16_le *)texptr + bufw * y, w, clut);
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
for (int y = 0; y < h; ++y) {
|
||||
DeIndexTexture((u32 *)(out + outPitch * y), (const u32_le *)texptr + bufw * y, w, clut);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG_REPORT(G3D, "Unhandled clut texture mode %d!!!", gstate.getClutPaletteFormat());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -146,14 +146,29 @@ protected:
|
|||
// Can't be unordered_map, we use lower_bound ... although for some reason that compiles on MSVC.
|
||||
typedef std::map<u64, TexCacheEntry> TexCache;
|
||||
|
||||
// Separate to keep main texture cache size down.
|
||||
struct AttachedFramebufferInfo {
|
||||
u32 xOffset;
|
||||
u32 yOffset;
|
||||
};
|
||||
|
||||
void UnswizzleFromMem(u32 *dest, u32 destPitch, const u8 *texptr, u32 bufw, u32 height, u32 bytesPerPixel);
|
||||
void *RearrangeBuf(void *inBuf, u32 inRowBytes, u32 outRowBytes, int h, bool allowInPlace = true);
|
||||
bool ReadIndexedTex(u8 *out, int outPitch, int level, const u8 *texptr, int bytesPerIndex, int bufw);
|
||||
|
||||
template <typename T>
|
||||
inline const T *GetCurrentClut() {
|
||||
return (const T *)clutBuf_;
|
||||
}
|
||||
|
||||
u32 EstimateTexMemoryUsage(const TexCacheEntry *entry);
|
||||
void GetSamplingParams(int &minFilt, int &magFilt, bool &sClamp, bool &tClamp, float &lodBias, u8 maxLevel, u32 addr);
|
||||
void UpdateMaxSeenV(TexCacheEntry *entry, bool throughMode);
|
||||
|
||||
virtual bool AttachFramebuffer(TexCacheEntry *entry, u32 address, VirtualFramebuffer *framebuffer, u32 texaddrOffset = 0) = 0;
|
||||
void AttachFramebufferValid(TexCacheEntry *entry, VirtualFramebuffer *framebuffer, const AttachedFramebufferInfo &fbInfo);
|
||||
void AttachFramebufferInvalid(TexCacheEntry *entry, VirtualFramebuffer *framebuffer, const AttachedFramebufferInfo &fbInfo);
|
||||
void DetachFramebuffer(TexCacheEntry *entry, u32 address, VirtualFramebuffer *framebuffer);
|
||||
|
||||
virtual void DownloadFramebufferForClut(u32 clutAddr, u32 bytes) = 0;
|
||||
|
||||
|
@ -164,16 +179,8 @@ protected:
|
|||
TexCache cache;
|
||||
u32 cacheSizeEstimate_;
|
||||
|
||||
// Separate to keep main texture cache size down.
|
||||
struct AttachedFramebufferInfo {
|
||||
u32 xOffset;
|
||||
u32 yOffset;
|
||||
};
|
||||
std::vector<VirtualFramebuffer *> fbCache_;
|
||||
std::map<u64, AttachedFramebufferInfo> fbTexInfo_;
|
||||
void AttachFramebufferValid(TexCacheEntry *entry, VirtualFramebuffer *framebuffer, const AttachedFramebufferInfo &fbInfo);
|
||||
void AttachFramebufferInvalid(TexCacheEntry *entry, VirtualFramebuffer *framebuffer, const AttachedFramebufferInfo &fbInfo);
|
||||
void DetachFramebuffer(TexCacheEntry *entry, u32 address, VirtualFramebuffer *framebuffer);
|
||||
|
||||
std::map<u32, int> videos_;
|
||||
|
||||
|
@ -186,6 +193,8 @@ protected:
|
|||
// Raw is where we keep the original bytes. Converted is where we swap colors if necessary.
|
||||
u32 *clutBufRaw_;
|
||||
u32 *clutBufConverted_;
|
||||
// This is the active one.
|
||||
u32 *clutBuf_;
|
||||
u32 clutLastFormat_;
|
||||
u32 clutTotalBytes_;
|
||||
u32 clutMaxBytes_;
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace DX9 {
|
|||
#define TEXCACHE_MIN_PRESSURE 16 * 1024 * 1024 // Total in VRAM
|
||||
#define TEXCACHE_SECOND_MIN_PRESSURE 4 * 1024 * 1024
|
||||
|
||||
TextureCacheDX9::TextureCacheDX9() : secondCacheSizeEstimate_(0), clearCacheNextFrame_(false), lowMemoryMode_(false), clutBuf_(NULL), texelsScaledThisFrame_(0) {
|
||||
TextureCacheDX9::TextureCacheDX9() : secondCacheSizeEstimate_(0), clearCacheNextFrame_(false), lowMemoryMode_(false), texelsScaledThisFrame_(0) {
|
||||
timesInvalidatedAllThisFrame_ = 0;
|
||||
lastBoundTexture = INVALID_TEX;
|
||||
decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL;
|
||||
|
@ -349,108 +349,6 @@ bool TextureCacheDX9::AttachFramebuffer(TexCacheEntry *entry, u32 address, Virtu
|
|||
return false;
|
||||
}
|
||||
|
||||
void *TextureCacheDX9::ReadIndexedTex(int level, const u8 *texptr, int bytesPerIndex, u32 dstFmt, int bufw) {
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
int length = bufw * h;
|
||||
void *buf = NULL;
|
||||
switch (gstate.getClutPaletteFormat()) {
|
||||
case GE_CMODE_16BIT_BGR5650:
|
||||
case GE_CMODE_16BIT_ABGR5551:
|
||||
case GE_CMODE_16BIT_ABGR4444:
|
||||
{
|
||||
tmpTexBuf16.resize(std::max(bufw, w) * h);
|
||||
tmpTexBufRearrange.resize(std::max(bufw, w) * h);
|
||||
const u16 *clut = GetCurrentClut<u16>();
|
||||
if (!gstate.isTextureSwizzled()) {
|
||||
switch (bytesPerIndex) {
|
||||
case 1:
|
||||
DeIndexTexture(tmpTexBuf16.data(), (const u8 *)texptr, length, clut);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
DeIndexTexture(tmpTexBuf16.data(), (const u16_le *)texptr, length, clut);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
DeIndexTexture(tmpTexBuf16.data(), (const u32_le *)texptr, length, clut);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
tmpTexBuf32.resize(std::max(bufw, w) * h);
|
||||
UnswizzleFromMem(tmpTexBuf32.data(), bufw * bytesPerIndex, texptr, bufw, h, bytesPerIndex);
|
||||
switch (bytesPerIndex) {
|
||||
case 1:
|
||||
DeIndexTexture(tmpTexBuf16.data(), (u8 *) tmpTexBuf32.data(), length, clut);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
DeIndexTexture(tmpTexBuf16.data(), (u16 *) tmpTexBuf32.data(), length, clut);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
DeIndexTexture(tmpTexBuf16.data(), (u32 *) tmpTexBuf32.data(), length, clut);
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf = tmpTexBuf16.data();
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_CMODE_32BIT_ABGR8888:
|
||||
{
|
||||
tmpTexBuf32.resize(std::max(bufw, w) * h);
|
||||
tmpTexBufRearrange.resize(std::max(bufw, w) * h);
|
||||
const u32 *clut = GetCurrentClut<u32>();
|
||||
if (!gstate.isTextureSwizzled()) {
|
||||
switch (bytesPerIndex) {
|
||||
case 1:
|
||||
DeIndexTexture(tmpTexBuf32.data(), (const u8 *)texptr, length, clut);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
DeIndexTexture(tmpTexBuf32.data(), (const u16_le *)texptr, length, clut);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
DeIndexTexture(tmpTexBuf32.data(), (const u32_le *)texptr, length, clut);
|
||||
break;
|
||||
}
|
||||
buf = tmpTexBuf32.data();
|
||||
} else {
|
||||
UnswizzleFromMem(tmpTexBuf32.data(), bufw * bytesPerIndex, texptr, bufw, h, bytesPerIndex);
|
||||
// Since we had to unswizzle to tmpTexBuf32, let's output to tmpTexBuf16.
|
||||
tmpTexBuf16.resize(std::max(bufw, w) * h * 2);
|
||||
u32 *dest32 = (u32 *) tmpTexBuf16.data();
|
||||
switch (bytesPerIndex) {
|
||||
case 1:
|
||||
DeIndexTexture(dest32, (u8 *) tmpTexBuf32.data(), length, clut);
|
||||
buf = dest32;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
DeIndexTexture(dest32, (u16 *) tmpTexBuf32.data(), length, clut);
|
||||
buf = dest32;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// TODO: If a game actually uses this mode, check if using dest32 or tmpTexBuf32 is faster.
|
||||
DeIndexTexture(tmpTexBuf32.data(), tmpTexBuf32.data(), length, clut);
|
||||
buf = tmpTexBuf32.data();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG_REPORT(G3D, "Unhandled clut texture mode %d!!!", (gstate.clutformat & 3));
|
||||
break;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
D3DFORMAT getClutDestFormat(GEPaletteFormat format) {
|
||||
switch (format) {
|
||||
case GE_CMODE_16BIT_ABGR4444:
|
||||
|
@ -634,11 +532,6 @@ void TextureCacheDX9::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase
|
|||
clutLastFormat_ = gstate.clutformat;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline const T *TextureCacheDX9::GetCurrentClut() {
|
||||
return (const T *)clutBuf_;
|
||||
}
|
||||
|
||||
inline u32 TextureCacheDX9::GetCurrentClutHash() {
|
||||
return clutHash_;
|
||||
}
|
||||
|
@ -1496,17 +1389,53 @@ void *TextureCacheDX9::DecodeTextureLevel(GETextureFormat format, GEPaletteForma
|
|||
|
||||
case GE_TFMT_CLUT8:
|
||||
texByteAlign = texByteAlignMap[gstate.getClutPaletteFormat()];
|
||||
finalBuf = ReadIndexedTex(level, texptr, 1, dstFmt, bufw);
|
||||
{
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
int length = bufw * h;
|
||||
int bpp = gstate.getClutPaletteFormat() == GE_CMODE_32BIT_ABGR8888 ? 4 : 2;
|
||||
|
||||
tmpTexBuf16.resize(std::max(bufw, w) * h * bpp / 2);
|
||||
tmpTexBufRearrange.resize(std::max(bufw, w) * h * bpp / 2);
|
||||
finalBuf = nullptr;
|
||||
if (ReadIndexedTex((u8 *)tmpTexBuf16.data(), bufw * bpp, level, texptr, 1, bufw)) {
|
||||
finalBuf = tmpTexBuf16.data();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_TFMT_CLUT16:
|
||||
texByteAlign = texByteAlignMap[gstate.getClutPaletteFormat()];
|
||||
finalBuf = ReadIndexedTex(level, texptr, 2, dstFmt, bufw);
|
||||
{
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
int length = bufw * h;
|
||||
int bpp = gstate.getClutPaletteFormat() == GE_CMODE_32BIT_ABGR8888 ? 4 : 2;
|
||||
|
||||
tmpTexBuf16.resize(std::max(bufw, w) * h * bpp / 2);
|
||||
tmpTexBufRearrange.resize(std::max(bufw, w) * h * bpp / 2);
|
||||
finalBuf = nullptr;
|
||||
if (ReadIndexedTex((u8 *)tmpTexBuf16.data(), bufw * bpp, level, texptr, 2, bufw)) {
|
||||
finalBuf = tmpTexBuf16.data();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_TFMT_CLUT32:
|
||||
texByteAlign = texByteAlignMap[gstate.getClutPaletteFormat()];
|
||||
finalBuf = ReadIndexedTex(level, texptr, 4, dstFmt, bufw);
|
||||
{
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
int length = bufw * h;
|
||||
int bpp = gstate.getClutPaletteFormat() == GE_CMODE_32BIT_ABGR8888 ? 4 : 2;
|
||||
|
||||
tmpTexBuf16.resize(std::max(bufw, w) * h * bpp / 2);
|
||||
tmpTexBufRearrange.resize(std::max(bufw, w) * h * bpp / 2);
|
||||
finalBuf = nullptr;
|
||||
if (ReadIndexedTex((u8 *)tmpTexBuf16.data(), bufw * bpp, level, texptr, 4, bufw)) {
|
||||
finalBuf = tmpTexBuf16.data();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_TFMT_4444:
|
||||
|
|
|
@ -78,14 +78,11 @@ protected:
|
|||
private:
|
||||
void Decimate(); // Run this once per frame to get rid of old textures.
|
||||
void DeleteTexture(TexCache::iterator it);
|
||||
void *ReadIndexedTex(int level, const u8 *texptr, int bytesPerIndex, u32 dstFmt, int bufw);
|
||||
void UpdateSamplingParams(TexCacheEntry &entry, bool force);
|
||||
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, bool replaceImages, int scaleFactor, u32 dstFmt);
|
||||
D3DFORMAT GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const;
|
||||
void *DecodeTextureLevel(GETextureFormat format, GEPaletteFormat clutformat, int level, u32 &texByteAlign, u32 &dstFmt, int *bufw = 0);
|
||||
TexCacheEntry::Status CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h);
|
||||
template <typename T>
|
||||
const T *GetCurrentClut();
|
||||
u32 GetCurrentClutHash();
|
||||
void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple);
|
||||
bool AttachFramebuffer(TexCacheEntry *entry, u32 address, VirtualFramebuffer *framebuffer, u32 texaddrOffset = 0) override;
|
||||
|
@ -114,7 +111,6 @@ private:
|
|||
bool lowMemoryMode_;
|
||||
TextureScalerDX9 scaler;
|
||||
|
||||
u32 *clutBuf_;
|
||||
u32 clutHash_;
|
||||
// True if the clut is just alpha values in the same order (RGBA4444-bit only.)
|
||||
bool clutAlphaLinear_;
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
|
||||
#define INVALID_TEX -1
|
||||
|
||||
TextureCache::TextureCache() : secondCacheSizeEstimate_(0), clearCacheNextFrame_(false), lowMemoryMode_(false), clutBuf_(NULL), texelsScaledThisFrame_(0) {
|
||||
TextureCache::TextureCache() : secondCacheSizeEstimate_(0), clearCacheNextFrame_(false), lowMemoryMode_(false), texelsScaledThisFrame_(0) {
|
||||
timesInvalidatedAllThisFrame_ = 0;
|
||||
lastBoundTexture = INVALID_TEX;
|
||||
decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL;
|
||||
|
@ -345,108 +345,6 @@ bool TextureCache::AttachFramebuffer(TexCacheEntry *entry, u32 address, VirtualF
|
|||
return false;
|
||||
}
|
||||
|
||||
void *TextureCache::ReadIndexedTex(int level, const u8 *texptr, int bytesPerIndex, GLuint dstFmt, int bufw) {
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
int length = bufw * h;
|
||||
void *buf = NULL;
|
||||
switch (gstate.getClutPaletteFormat()) {
|
||||
case GE_CMODE_16BIT_BGR5650:
|
||||
case GE_CMODE_16BIT_ABGR5551:
|
||||
case GE_CMODE_16BIT_ABGR4444:
|
||||
{
|
||||
tmpTexBuf16.resize(std::max(bufw, w) * h);
|
||||
tmpTexBufRearrange.resize(std::max(bufw, w) * h);
|
||||
const u16 *clut = GetCurrentClut<u16>();
|
||||
if (!gstate.isTextureSwizzled()) {
|
||||
switch (bytesPerIndex) {
|
||||
case 1:
|
||||
DeIndexTexture(tmpTexBuf16.data(), (const u8 *)texptr, length, clut);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
DeIndexTexture(tmpTexBuf16.data(), (const u16_le *)texptr, length, clut);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
DeIndexTexture(tmpTexBuf16.data(), (const u32_le *)texptr, length, clut);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
tmpTexBuf32.resize(std::max(bufw, w) * h);
|
||||
UnswizzleFromMem(tmpTexBuf32.data(), bufw * bytesPerIndex, texptr, bufw, h, bytesPerIndex);
|
||||
switch (bytesPerIndex) {
|
||||
case 1:
|
||||
DeIndexTexture(tmpTexBuf16.data(), (u8 *) tmpTexBuf32.data(), length, clut);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
DeIndexTexture(tmpTexBuf16.data(), (u16 *) tmpTexBuf32.data(), length, clut);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
DeIndexTexture(tmpTexBuf16.data(), (u32 *) tmpTexBuf32.data(), length, clut);
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf = tmpTexBuf16.data();
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_CMODE_32BIT_ABGR8888:
|
||||
{
|
||||
tmpTexBuf32.resize(std::max(bufw, w) * h);
|
||||
tmpTexBufRearrange.resize(std::max(bufw, w) * h);
|
||||
const u32 *clut = GetCurrentClut<u32>();
|
||||
if (!gstate.isTextureSwizzled()) {
|
||||
switch (bytesPerIndex) {
|
||||
case 1:
|
||||
DeIndexTexture(tmpTexBuf32.data(), (const u8 *)texptr, length, clut);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
DeIndexTexture(tmpTexBuf32.data(), (const u16_le *)texptr, length, clut);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
DeIndexTexture(tmpTexBuf32.data(), (const u32_le *)texptr, length, clut);
|
||||
break;
|
||||
}
|
||||
buf = tmpTexBuf32.data();
|
||||
} else {
|
||||
UnswizzleFromMem(tmpTexBuf32.data(), bufw * bytesPerIndex, texptr, bufw, h, bytesPerIndex);
|
||||
// Since we had to unswizzle to tmpTexBuf32, let's output to tmpTexBuf16.
|
||||
tmpTexBuf16.resize(std::max(bufw, w) * h * 2);
|
||||
u32 *dest32 = (u32 *) tmpTexBuf16.data();
|
||||
switch (bytesPerIndex) {
|
||||
case 1:
|
||||
DeIndexTexture(dest32, (u8 *) tmpTexBuf32.data(), length, clut);
|
||||
buf = dest32;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
DeIndexTexture(dest32, (u16 *) tmpTexBuf32.data(), length, clut);
|
||||
buf = dest32;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// TODO: If a game actually uses this mode, check if using dest32 or tmpTexBuf32 is faster.
|
||||
DeIndexTexture(tmpTexBuf32.data(), tmpTexBuf32.data(), length, clut);
|
||||
buf = tmpTexBuf32.data();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG_REPORT(G3D, "Unhandled clut texture mode %d!!!", (gstate.clutformat & 3));
|
||||
break;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
GLenum getClutDestFormat(GEPaletteFormat format) {
|
||||
switch (format) {
|
||||
case GE_CMODE_16BIT_ABGR4444:
|
||||
|
@ -661,11 +559,6 @@ void TextureCache::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, b
|
|||
clutLastFormat_ = gstate.clutformat;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline const T *TextureCache::GetCurrentClut() {
|
||||
return (const T *)clutBuf_;
|
||||
}
|
||||
|
||||
inline u32 TextureCache::GetCurrentClutHash() {
|
||||
return clutHash_;
|
||||
}
|
||||
|
@ -1660,17 +1553,53 @@ void *TextureCache::DecodeTextureLevel(GETextureFormat format, GEPaletteFormat c
|
|||
|
||||
case GE_TFMT_CLUT8:
|
||||
texByteAlign = texByteAlignMap[gstate.getClutPaletteFormat()];
|
||||
finalBuf = ReadIndexedTex(level, texptr, 1, dstFmt, bufw);
|
||||
{
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
int length = bufw * h;
|
||||
int bpp = gstate.getClutPaletteFormat() == GE_CMODE_32BIT_ABGR8888 ? 4 : 2;
|
||||
|
||||
tmpTexBuf16.resize(std::max(bufw, w) * h * bpp / 2);
|
||||
tmpTexBufRearrange.resize(std::max(bufw, w) * h * bpp / 2);
|
||||
finalBuf = nullptr;
|
||||
if (ReadIndexedTex((u8 *)tmpTexBuf16.data(), bufw * bpp, level, texptr, 1, bufw)) {
|
||||
finalBuf = tmpTexBuf16.data();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_TFMT_CLUT16:
|
||||
texByteAlign = texByteAlignMap[gstate.getClutPaletteFormat()];
|
||||
finalBuf = ReadIndexedTex(level, texptr, 2, dstFmt, bufw);
|
||||
{
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
int length = bufw * h;
|
||||
int bpp = gstate.getClutPaletteFormat() == GE_CMODE_32BIT_ABGR8888 ? 4 : 2;
|
||||
|
||||
tmpTexBuf16.resize(std::max(bufw, w) * h * bpp / 2);
|
||||
tmpTexBufRearrange.resize(std::max(bufw, w) * h * bpp / 2);
|
||||
finalBuf = nullptr;
|
||||
if (ReadIndexedTex((u8 *)tmpTexBuf16.data(), bufw * bpp, level, texptr, 2, bufw)) {
|
||||
finalBuf = tmpTexBuf16.data();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_TFMT_CLUT32:
|
||||
texByteAlign = texByteAlignMap[gstate.getClutPaletteFormat()];
|
||||
finalBuf = ReadIndexedTex(level, texptr, 4, dstFmt, bufw);
|
||||
{
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
int length = bufw * h;
|
||||
int bpp = gstate.getClutPaletteFormat() == GE_CMODE_32BIT_ABGR8888 ? 4 : 2;
|
||||
|
||||
tmpTexBuf16.resize(std::max(bufw, w) * h * bpp / 2);
|
||||
tmpTexBufRearrange.resize(std::max(bufw, w) * h * bpp / 2);
|
||||
finalBuf = nullptr;
|
||||
if (ReadIndexedTex((u8 *)tmpTexBuf16.data(), bufw * bpp, level, texptr, 4, bufw)) {
|
||||
finalBuf = tmpTexBuf16.data();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_TFMT_4444:
|
||||
|
|
|
@ -93,14 +93,11 @@ protected:
|
|||
private:
|
||||
void Decimate(); // Run this once per frame to get rid of old textures.
|
||||
void DeleteTexture(TexCache::iterator it);
|
||||
void *ReadIndexedTex(int level, const u8 *texptr, int bytesPerIndex, GLuint dstFmt, int bufw);
|
||||
void UpdateSamplingParams(TexCacheEntry &entry, bool force);
|
||||
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, bool replaceImages, int scaleFactor, GLenum dstFmt);
|
||||
GLenum GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const;
|
||||
void *DecodeTextureLevel(GETextureFormat format, GEPaletteFormat clutformat, int level, u32 &texByteAlign, GLenum dstFmt, int scaleFactor, int *bufw = 0);
|
||||
TexCacheEntry::Status CheckAlpha(const u32 *pixelData, GLenum dstFmt, int stride, int w, int h);
|
||||
template <typename T>
|
||||
const T *GetCurrentClut();
|
||||
u32 GetCurrentClutHash();
|
||||
void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple);
|
||||
bool AttachFramebuffer(TexCacheEntry *entry, u32 address, VirtualFramebuffer *framebuffer, u32 texaddrOffset = 0) override;
|
||||
|
@ -120,7 +117,6 @@ private:
|
|||
|
||||
TextureScalerGL scaler;
|
||||
|
||||
u32 *clutBuf_;
|
||||
u32 clutHash_;
|
||||
// True if the clut is just alpha values in the same order (RGBA4444-bit only.)
|
||||
bool clutAlphaLinear_;
|
||||
|
|
|
@ -131,7 +131,7 @@ VkSampler SamplerCache::GetOrCreateSampler(const SamplerCacheKey &key) {
|
|||
|
||||
TextureCacheVulkan::TextureCacheVulkan(VulkanContext *vulkan)
|
||||
: vulkan_(vulkan), samplerCache_(vulkan), secondCacheSizeEstimate_(0),
|
||||
clearCacheNextFrame_(false), lowMemoryMode_(false), clutBuf_(NULL), texelsScaledThisFrame_(0),
|
||||
clearCacheNextFrame_(false), lowMemoryMode_(false), texelsScaledThisFrame_(0),
|
||||
clutAlphaLinear_(false) {
|
||||
timesInvalidatedAllThisFrame_ = 0;
|
||||
lastBoundTexture = nullptr;
|
||||
|
@ -412,77 +412,6 @@ bool TextureCacheVulkan::AttachFramebuffer(TexCacheEntry *entry, u32 address, Vi
|
|||
return false;
|
||||
}
|
||||
|
||||
bool TextureCacheVulkan::ReadIndexedTex(u8 *out, int outPitch, int level, const u8 *texptr, int bytesPerIndex, VkFormat dstFmt, int bufw) {
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
|
||||
if (gstate.isTextureSwizzled()) {
|
||||
tmpTexBuf32.resize(bufw * ((h + 7) & ~7));
|
||||
UnswizzleFromMem(tmpTexBuf32.data(), bufw * bytesPerIndex, texptr, bufw, h, bytesPerIndex);
|
||||
texptr = (u8 *)tmpTexBuf32.data();
|
||||
}
|
||||
|
||||
switch (gstate.getClutPaletteFormat()) {
|
||||
case GE_CMODE_16BIT_BGR5650:
|
||||
case GE_CMODE_16BIT_ABGR5551:
|
||||
case GE_CMODE_16BIT_ABGR4444:
|
||||
{
|
||||
const u16 *clut = GetCurrentClut<u16>();
|
||||
switch (bytesPerIndex) {
|
||||
case 1:
|
||||
for (int y = 0; y < h; ++y) {
|
||||
DeIndexTexture((u16 *)(out + outPitch * y), (const u8 *)texptr + bufw * y, w, clut);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
for (int y = 0; y < h; ++y) {
|
||||
DeIndexTexture((u16 *)(out + outPitch * y), (const u16_le *)texptr + bufw * y, w, clut);
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
for (int y = 0; y < h; ++y) {
|
||||
DeIndexTexture((u16 *)(out + outPitch * y), (const u32_le *)texptr + bufw * y, w, clut);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_CMODE_32BIT_ABGR8888:
|
||||
{
|
||||
const u32 *clut = GetCurrentClut<u32>();
|
||||
switch (bytesPerIndex) {
|
||||
case 1:
|
||||
for (int y = 0; y < h; ++y) {
|
||||
DeIndexTexture((u32 *)(out + outPitch * y), (const u8 *)texptr + bufw * y, w, clut);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
for (int y = 0; y < h; ++y) {
|
||||
DeIndexTexture((u32 *)(out + outPitch * y), (const u16_le *)texptr + bufw * y, w, clut);
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
for (int y = 0; y < h; ++y) {
|
||||
DeIndexTexture((u32 *)(out + outPitch * y), (const u32_le *)texptr + bufw * y, w, clut);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG_REPORT(G3D, "Unhandled clut texture mode %d!!!", gstate.getClutPaletteFormat());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
VkFormat getClutDestFormatVulkan(GEPaletteFormat format) {
|
||||
switch (format) {
|
||||
case GE_CMODE_16BIT_ABGR4444:
|
||||
|
@ -643,11 +572,6 @@ void TextureCacheVulkan::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutB
|
|||
clutLastFormat_ = gstate.clutformat;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline const T *TextureCacheVulkan::GetCurrentClut() {
|
||||
return (const T *)clutBuf_;
|
||||
}
|
||||
|
||||
inline u32 TextureCacheVulkan::GetCurrentClutHash() {
|
||||
return clutHash_;
|
||||
}
|
||||
|
@ -1514,19 +1438,19 @@ bool TextureCacheVulkan::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm
|
|||
break;
|
||||
|
||||
case GE_TFMT_CLUT8:
|
||||
if (!ReadIndexedTex(out, outPitch, level, texptr, 1, dstFmt, bufw)) {
|
||||
if (!ReadIndexedTex(out, outPitch, level, texptr, 1, bufw)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_TFMT_CLUT16:
|
||||
if (!ReadIndexedTex(out, outPitch, level, texptr, 2, dstFmt, bufw)) {
|
||||
if (!ReadIndexedTex(out, outPitch, level, texptr, 2, bufw)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_TFMT_CLUT32:
|
||||
if (!ReadIndexedTex(out, outPitch, level, texptr, 4, dstFmt, bufw)) {
|
||||
if (!ReadIndexedTex(out, outPitch, level, texptr, 4, bufw)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -126,14 +126,11 @@ protected:
|
|||
private:
|
||||
void Decimate(); // Run this once per frame to get rid of old textures.
|
||||
void DeleteTexture(TexCache::iterator it);
|
||||
bool ReadIndexedTex(u8 *out, int outPitch, int level, const u8 *texptr, int bytesPerIndex, VkFormat dstFmt, int bufw);
|
||||
void UpdateSamplingParams(TexCacheEntry &entry, SamplerCacheKey &key);
|
||||
void LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePtr, int rowPitch, int level, int scaleFactor, VkFormat dstFmt);
|
||||
VkFormat GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const;
|
||||
bool DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, VkFormat dstFmt, int scaleFactor, int bufw);
|
||||
TexCacheEntry::Status CheckAlpha(const u32 *pixelData, VkFormat dstFmt, int stride, int w, int h);
|
||||
template <typename T>
|
||||
const T *GetCurrentClut();
|
||||
u32 GetCurrentClutHash();
|
||||
void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple);
|
||||
bool AttachFramebuffer(TexCacheEntry *entry, u32 address, VirtualFramebuffer *framebuffer, u32 texaddrOffset = 0) override;
|
||||
|
@ -158,7 +155,6 @@ private:
|
|||
|
||||
TextureScalerVulkan scaler;
|
||||
|
||||
u32 *clutBuf_;
|
||||
u32 clutHash_;
|
||||
// True if the clut is just alpha values in the same order (RGBA4444-bit only.)
|
||||
bool clutAlphaLinear_;
|
||||
|
|
Loading…
Add table
Reference in a new issue