mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Remove fake-mipmap logic from LoadTextureLevel
This commit is contained in:
parent
8b398bbbb7
commit
f728faffdc
7 changed files with 161 additions and 172 deletions
|
@ -54,6 +54,20 @@ static const D3D11_INPUT_ELEMENT_DESC g_QuadVertexElements[] = {
|
|||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12,},
|
||||
};
|
||||
|
||||
// NOTE: In the D3D backends, we flip R and B in the shaders, so while these look wrong, they're OK.
|
||||
|
||||
Draw::DataFormat FromD3D11Format(u32 fmt) {
|
||||
switch (fmt) {
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM: default: return Draw::DataFormat::R8G8B8A8_UNORM;
|
||||
}
|
||||
}
|
||||
|
||||
DXGI_FORMAT ToDXGIFormat(Draw::DataFormat fmt) {
|
||||
switch (fmt) {
|
||||
case Draw::DataFormat::R8G8B8A8_UNORM: default: return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
}
|
||||
}
|
||||
|
||||
SamplerCacheD3D11::~SamplerCacheD3D11() {
|
||||
for (auto &iter : cache_) {
|
||||
iter.second->Release();
|
||||
|
@ -518,14 +532,49 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) {
|
|||
maxLevel = 0;
|
||||
}
|
||||
|
||||
int level = 0;
|
||||
int srcLevel = 0;
|
||||
if (IsFakeMipmapChange()) {
|
||||
// NOTE: Since the level is not part of the cache key, we assume it never changes.
|
||||
level = std::max(0, gstate.getTexLevelOffset16() / 16);
|
||||
srcLevel = std::max(0, gstate.getTexLevelOffset16() / 16);
|
||||
}
|
||||
|
||||
DXGI_FORMAT dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat());
|
||||
LoadTextureLevel(*entry, replaced, level, maxLevel, scaleFactor, dstFmt);
|
||||
|
||||
ID3D11Texture2D *texture = DxTex(entry);
|
||||
_assert_(texture == nullptr);
|
||||
|
||||
// Create texture
|
||||
int levels = scaleFactor == 1 ? maxLevel + 1 : 1;
|
||||
int tw = w, th = h;
|
||||
DXGI_FORMAT tfmt = dstFmt;
|
||||
if (replaced.GetSize(srcLevel, tw, th)) {
|
||||
tfmt = ToDXGIFormat(replaced.Format(srcLevel));
|
||||
} else {
|
||||
tw *= scaleFactor;
|
||||
th *= scaleFactor;
|
||||
if (scaleFactor > 1) {
|
||||
tfmt = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
}
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc{};
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.ArraySize = 1;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.Width = tw;
|
||||
desc.Height = th;
|
||||
desc.Format = tfmt;
|
||||
desc.MipLevels = IsFakeMipmapChange() ? 1 : levels;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
|
||||
ASSERT_SUCCESS(device_->CreateTexture2D(&desc, nullptr, &texture));
|
||||
ID3D11ShaderResourceView *view;
|
||||
ASSERT_SUCCESS(device_->CreateShaderResourceView(texture, nullptr, &view));
|
||||
entry->texturePtr = texture;
|
||||
entry->textureView = view;
|
||||
|
||||
LoadTextureLevel(*entry, replaced, srcLevel, 0, maxLevel, scaleFactor, dstFmt);
|
||||
|
||||
ID3D11ShaderResourceView *textureView = DxView(entry);
|
||||
if (!textureView) {
|
||||
|
@ -535,7 +584,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) {
|
|||
// Mipmapping is only enabled when texture scaling is disabled.
|
||||
if (maxLevel > 0 && scaleFactor == 1) {
|
||||
for (int i = 1; i <= maxLevel; i++) {
|
||||
LoadTextureLevel(*entry, replaced, i, maxLevel, scaleFactor, dstFmt);
|
||||
LoadTextureLevel(*entry, replaced, i, i, maxLevel, scaleFactor, dstFmt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -604,75 +653,28 @@ CheckAlphaResult TextureCacheD3D11::CheckAlpha(const u32 *pixelData, u32 dstFmt,
|
|||
}
|
||||
}
|
||||
|
||||
// NOTE: In the D3D backends, we flip R and B in the shaders, so while these look wrong, they're OK.
|
||||
|
||||
Draw::DataFormat FromD3D11Format(u32 fmt) {
|
||||
switch (fmt) {
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM: default: return Draw::DataFormat::R8G8B8A8_UNORM;
|
||||
}
|
||||
}
|
||||
|
||||
DXGI_FORMAT ToDXGIFormat(Draw::DataFormat fmt) {
|
||||
switch (fmt) {
|
||||
case Draw::DataFormat::R8G8B8A8_UNORM: default: return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, int scaleFactor, DXGI_FORMAT dstFmt) {
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int srcLevel, int dstLevel, int maxLevel, int scaleFactor, DXGI_FORMAT dstFmt) {
|
||||
int w = gstate.getTextureWidth(srcLevel);
|
||||
int h = gstate.getTextureHeight(srcLevel);
|
||||
|
||||
ID3D11Texture2D *texture = DxTex(&entry);
|
||||
if ((level == 0 || IsFakeMipmapChange()) && texture == nullptr) {
|
||||
// Create texture
|
||||
int levels = scaleFactor == 1 ? maxLevel + 1 : 1;
|
||||
int tw = w, th = h;
|
||||
DXGI_FORMAT tfmt = dstFmt;
|
||||
if (replaced.GetSize(level, tw, th)) {
|
||||
tfmt = ToDXGIFormat(replaced.Format(level));
|
||||
} else {
|
||||
tw *= scaleFactor;
|
||||
th *= scaleFactor;
|
||||
if (scaleFactor > 1) {
|
||||
tfmt = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
}
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc{};
|
||||
// TODO: Make it DEFAULT or immutable, required for multiple mip levels. Will require some code restructuring though.
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.ArraySize = 1;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.Width = tw;
|
||||
desc.Height = th;
|
||||
desc.Format = tfmt;
|
||||
desc.MipLevels = IsFakeMipmapChange() ? 1 : levels;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
|
||||
ASSERT_SUCCESS(device_->CreateTexture2D(&desc, nullptr, &texture));
|
||||
ID3D11ShaderResourceView *view;
|
||||
ASSERT_SUCCESS(device_->CreateShaderResourceView(texture, nullptr, &view));
|
||||
entry.texturePtr = texture;
|
||||
entry.textureView = view;
|
||||
}
|
||||
|
||||
gpuStats.numTexturesDecoded++;
|
||||
// For UpdateSubresource, we can't decode directly into the texture so we allocate a buffer :(
|
||||
u32 *mapData = nullptr;
|
||||
int mapRowPitch = 0;
|
||||
if (replaced.GetSize(level, w, h)) {
|
||||
if (replaced.GetSize(srcLevel, w, h)) {
|
||||
mapData = (u32 *)AllocateAlignedMemory(w * h * sizeof(u32), 16);
|
||||
mapRowPitch = w * 4;
|
||||
double replaceStart = time_now_d();
|
||||
replaced.Load(level, mapData, mapRowPitch);
|
||||
replaced.Load(srcLevel, mapData, mapRowPitch);
|
||||
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||
dstFmt = ToDXGIFormat(replaced.Format(level));
|
||||
dstFmt = ToDXGIFormat(replaced.Format(srcLevel));
|
||||
} else {
|
||||
GETextureFormat tfmt = (GETextureFormat)entry.format;
|
||||
GEPaletteFormat clutformat = gstate.getClutPaletteFormat();
|
||||
u32 texaddr = gstate.getTextureAddress(level);
|
||||
int bufw = GetTextureBufw(level, texaddr, tfmt);
|
||||
u32 texaddr = gstate.getTextureAddress(srcLevel);
|
||||
int bufw = GetTextureBufw(srcLevel, texaddr, tfmt);
|
||||
int bpp = dstFmt == DXGI_FORMAT_B8G8R8A8_UNORM ? 4 : 2;
|
||||
u32 *pixelData;
|
||||
int decPitch;
|
||||
|
@ -697,8 +699,8 @@ void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &
|
|||
|
||||
bool expand32 = !gstate_c.Supports(GPU_SUPPORTS_16BIT_FORMATS);
|
||||
|
||||
CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, expand32);
|
||||
entry.SetAlphaStatus(alphaResult, level);
|
||||
CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, srcLevel, bufw, false, expand32);
|
||||
entry.SetAlphaStatus(alphaResult, srcLevel);
|
||||
|
||||
if (scaleFactor > 1) {
|
||||
u32 scaleFmt = (u32)dstFmt;
|
||||
|
@ -732,14 +734,11 @@ void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &
|
|||
replacedInfo.fmt = FromD3D11Format(dstFmt);
|
||||
|
||||
// NOTE: Reading the decoded texture here may be very slow, if we just wrote it to write-combined memory.
|
||||
replacer_.NotifyTextureDecoded(replacedInfo, pixelData, decPitch, level, w, h);
|
||||
replacer_.NotifyTextureDecoded(replacedInfo, pixelData, decPitch, srcLevel, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsFakeMipmapChange())
|
||||
context_->UpdateSubresource(texture, 0, nullptr, mapData, mapRowPitch, 0);
|
||||
else
|
||||
context_->UpdateSubresource(texture, level, nullptr, mapData, mapRowPitch, 0);
|
||||
context_->UpdateSubresource(texture, dstLevel, nullptr, mapData, mapRowPitch, 0);
|
||||
FreeAlignedMemory(mapData);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ protected:
|
|||
void ReleaseTexture(TexCacheEntry *entry, bool delete_them) override;
|
||||
|
||||
private:
|
||||
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, int scaleFactor, DXGI_FORMAT dstFmt);
|
||||
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int srcLevel, int dstLevel, int maxLevel, int scaleFactor, DXGI_FORMAT dstFmt);
|
||||
DXGI_FORMAT GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const;
|
||||
static CheckAlphaResult CheckAlpha(const u32 *pixelData, u32 dstFmt, int w);
|
||||
void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override;
|
||||
|
|
|
@ -37,6 +37,19 @@
|
|||
#include "ext/xxhash.h"
|
||||
#include "Common/Math/math_util.h"
|
||||
|
||||
// NOTE: In the D3D backends, we flip R and B in the shaders, so while these look wrong, they're OK.
|
||||
|
||||
Draw::DataFormat FromD3D9Format(u32 fmt) {
|
||||
switch (fmt) {
|
||||
case D3DFMT_A8R8G8B8: default: return Draw::DataFormat::R8G8B8A8_UNORM;
|
||||
}
|
||||
}
|
||||
|
||||
D3DFORMAT ToD3D9Format(Draw::DataFormat fmt) {
|
||||
switch (fmt) {
|
||||
case Draw::DataFormat::R8G8B8A8_UNORM: default: return D3DFMT_A8R8G8B8;
|
||||
}
|
||||
}
|
||||
|
||||
namespace DX9 {
|
||||
|
||||
|
@ -480,9 +493,38 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) {
|
|||
level = std::max(0, gstate.getTexLevelOffset16() / 16);
|
||||
}
|
||||
|
||||
LoadTextureLevel(*entry, replaced, level, maxLevel, scaleFactor, dstFmt);
|
||||
|
||||
LPDIRECT3DTEXTURE9 &texture = DxTex(entry);
|
||||
// Create texture
|
||||
D3DPOOL pool = D3DPOOL_MANAGED;
|
||||
int usage = 0;
|
||||
pool = D3DPOOL_DEFAULT;
|
||||
usage = D3DUSAGE_DYNAMIC; // TODO: Switch to using a staging texture?
|
||||
int levels = scaleFactor == 1 ? maxLevel + 1 : 1;
|
||||
int tw = w, th = h;
|
||||
D3DFORMAT tfmt = (D3DFORMAT)(dstFmt);
|
||||
if (replaced.GetSize(level, tw, th)) {
|
||||
tfmt = ToD3D9Format(replaced.Format(level));
|
||||
} else {
|
||||
tw *= scaleFactor;
|
||||
th *= scaleFactor;
|
||||
if (scaleFactor > 1) {
|
||||
tfmt = D3DFMT_A8R8G8B8;
|
||||
}
|
||||
}
|
||||
HRESULT hr;
|
||||
if (IsFakeMipmapChange())
|
||||
hr = device_->CreateTexture(tw, th, 1, usage, tfmt, pool, &texture, NULL);
|
||||
else
|
||||
hr = device_->CreateTexture(tw, th, levels, usage, tfmt, pool, &texture, NULL);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
INFO_LOG(G3D, "Failed to create D3D texture: %dx%d", tw, th);
|
||||
ReleaseTexture(entry, true);
|
||||
return;
|
||||
}
|
||||
|
||||
LoadTextureLevel(*entry, replaced, level, 0, maxLevel, scaleFactor, dstFmt);
|
||||
|
||||
if (!texture) {
|
||||
return;
|
||||
}
|
||||
|
@ -490,7 +532,7 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) {
|
|||
// Mipmapping is only enabled when texture scaling is disabled.
|
||||
if (maxLevel > 0 && scaleFactor == 1) {
|
||||
for (int i = 1; i <= maxLevel; i++) {
|
||||
LoadTextureLevel(*entry, replaced, i, maxLevel, scaleFactor, dstFmt);
|
||||
LoadTextureLevel(*entry, replaced, i, i, maxLevel, scaleFactor, dstFmt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -540,79 +582,32 @@ CheckAlphaResult TextureCacheDX9::CheckAlpha(const u32 *pixelData, u32 dstFmt, i
|
|||
}
|
||||
}
|
||||
|
||||
// NOTE: In the D3D backends, we flip R and B in the shaders, so while these look wrong, they're OK.
|
||||
|
||||
Draw::DataFormat FromD3D9Format(u32 fmt) {
|
||||
switch (fmt) {
|
||||
case D3DFMT_A8R8G8B8: default: return Draw::DataFormat::R8G8B8A8_UNORM;
|
||||
}
|
||||
}
|
||||
|
||||
D3DFORMAT ToD3D9Format(Draw::DataFormat fmt) {
|
||||
switch (fmt) {
|
||||
case Draw::DataFormat::R8G8B8A8_UNORM: default: return D3DFMT_A8R8G8B8;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, int scaleFactor, u32 dstFmt) {
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int srcLevel, int dstLevel, int maxLevel, int scaleFactor, u32 dstFmt) {
|
||||
int w = gstate.getTextureWidth(srcLevel);
|
||||
int h = gstate.getTextureHeight(srcLevel);
|
||||
|
||||
LPDIRECT3DTEXTURE9 &texture = DxTex(&entry);
|
||||
if ((level == 0 || IsFakeMipmapChange()) && texture == nullptr) {
|
||||
// Create texture
|
||||
D3DPOOL pool = D3DPOOL_MANAGED;
|
||||
int usage = 0;
|
||||
pool = D3DPOOL_DEFAULT;
|
||||
usage = D3DUSAGE_DYNAMIC; // TODO: Switch to using a staging texture?
|
||||
int levels = scaleFactor == 1 ? maxLevel + 1 : 1;
|
||||
int tw = w, th = h;
|
||||
D3DFORMAT tfmt = (D3DFORMAT)(dstFmt);
|
||||
if (replaced.GetSize(level, tw, th)) {
|
||||
tfmt = ToD3D9Format(replaced.Format(level));
|
||||
} else {
|
||||
tw *= scaleFactor;
|
||||
th *= scaleFactor;
|
||||
if (scaleFactor > 1) {
|
||||
tfmt = D3DFMT_A8R8G8B8;
|
||||
}
|
||||
}
|
||||
HRESULT hr;
|
||||
if (IsFakeMipmapChange())
|
||||
hr = device_->CreateTexture(tw, th, 1, usage, tfmt, pool, &texture, NULL);
|
||||
else
|
||||
hr = device_->CreateTexture(tw, th, levels, usage, tfmt, pool, &texture, NULL);
|
||||
if (FAILED(hr)) {
|
||||
INFO_LOG(G3D, "Failed to create D3D texture: %dx%d", tw, th);
|
||||
ReleaseTexture(&entry, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
D3DLOCKED_RECT rect;
|
||||
|
||||
HRESULT result;
|
||||
uint32_t lockFlag = level == 0 ? D3DLOCK_DISCARD : 0; // Can only discard the top level
|
||||
if (IsFakeMipmapChange())
|
||||
result = texture->LockRect(0, &rect, NULL, lockFlag);
|
||||
else
|
||||
result = texture->LockRect(level, &rect, NULL, lockFlag);
|
||||
uint32_t lockFlag = dstLevel == 0 ? D3DLOCK_DISCARD : 0; // Can only discard the top level
|
||||
result = texture->LockRect(dstLevel, &rect, NULL, lockFlag);
|
||||
if (FAILED(result)) {
|
||||
ERROR_LOG(G3D, "Failed to lock D3D texture: %dx%d", w, h);
|
||||
return;
|
||||
}
|
||||
|
||||
gpuStats.numTexturesDecoded++;
|
||||
if (replaced.GetSize(level, w, h)) {
|
||||
if (replaced.GetSize(srcLevel, w, h)) {
|
||||
double replaceStart = time_now_d();
|
||||
replaced.Load(level, rect.pBits, rect.Pitch);
|
||||
replaced.Load(srcLevel, rect.pBits, rect.Pitch);
|
||||
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||
dstFmt = ToD3D9Format(replaced.Format(level));
|
||||
dstFmt = ToD3D9Format(replaced.Format(srcLevel));
|
||||
} else {
|
||||
GETextureFormat tfmt = (GETextureFormat)entry.format;
|
||||
GEPaletteFormat clutformat = gstate.getClutPaletteFormat();
|
||||
u32 texaddr = gstate.getTextureAddress(level);
|
||||
int bufw = GetTextureBufw(level, texaddr, tfmt);
|
||||
u32 texaddr = gstate.getTextureAddress(srcLevel);
|
||||
int bufw = GetTextureBufw(srcLevel, texaddr, tfmt);
|
||||
int bpp = dstFmt == D3DFMT_A8R8G8B8 ? 4 : 2;
|
||||
|
||||
u32 *pixelData = (u32 *)rect.pBits;
|
||||
|
@ -624,8 +619,8 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re
|
|||
decPitch = w * bpp;
|
||||
}
|
||||
|
||||
CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, false);
|
||||
entry.SetAlphaStatus(alphaResult, level);
|
||||
CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, srcLevel, bufw, false, false);
|
||||
entry.SetAlphaStatus(alphaResult, srcLevel);
|
||||
|
||||
if (scaleFactor > 1) {
|
||||
scaler.ScaleAlways((u32 *)rect.pBits, pixelData, dstFmt, w, h, scaleFactor);
|
||||
|
@ -656,14 +651,11 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re
|
|||
replacedInfo.scaleFactor = scaleFactor;
|
||||
replacedInfo.fmt = FromD3D9Format(dstFmt);
|
||||
|
||||
replacer_.NotifyTextureDecoded(replacedInfo, pixelData, decPitch, level, w, h);
|
||||
replacer_.NotifyTextureDecoded(replacedInfo, pixelData, decPitch, srcLevel, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsFakeMipmapChange())
|
||||
texture->UnlockRect(0);
|
||||
else
|
||||
texture->UnlockRect(level);
|
||||
texture->UnlockRect(0);
|
||||
}
|
||||
|
||||
bool TextureCacheDX9::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) {
|
||||
|
|
|
@ -62,7 +62,7 @@ protected:
|
|||
private:
|
||||
void ApplySamplingParams(const SamplerCacheKey &key);
|
||||
|
||||
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, int scaleFactor, u32 dstFmt);
|
||||
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int srcLevel, int dstLevel, int maxLevel, int scaleFactor, u32 dstFmt);
|
||||
D3DFORMAT GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const;
|
||||
static CheckAlphaResult CheckAlpha(const u32 *pixelData, u32 dstFmt, int w);
|
||||
void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override;
|
||||
|
|
|
@ -521,13 +521,21 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) {
|
|||
// be as good quality as the game's own (might even be better in some cases though).
|
||||
|
||||
// Always load base level texture here
|
||||
int level = 0;
|
||||
int srcLevel = 0;
|
||||
if (IsFakeMipmapChange()) {
|
||||
// NOTE: Since the level is not part of the cache key, we assume it never changes.
|
||||
level = std::max(0, gstate.getTexLevelOffset16() / 16);
|
||||
srcLevel = std::max(0, gstate.getTexLevelOffset16() / 16);
|
||||
}
|
||||
|
||||
LoadTextureLevel(*entry, replaced, level, scaleFactor, dstFmt);
|
||||
_assert_(!entry->textureName);
|
||||
|
||||
// TODO: Actually pass in correct size here. The size here is (in GL) not yet used for anything else
|
||||
// than determining if we can wrap this texture size, that is, it's pow2 or not on very old hardware, else true.
|
||||
// This will be easy after .. well, yet another refactoring, where I hoist the size calculation out of LoadTextureLevel
|
||||
// and unify BuildTexture.
|
||||
entry->textureName = render_->CreateTexture(GL_TEXTURE_2D, 16, 16, 1);
|
||||
|
||||
LoadTextureLevel(*entry, replaced, srcLevel, 0, scaleFactor, dstFmt);
|
||||
|
||||
// Mipmapping is only enabled when texture scaling is disabled.
|
||||
int texMaxLevel = 0;
|
||||
|
@ -544,7 +552,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) {
|
|||
}
|
||||
} else {
|
||||
for (int i = 1; i <= maxLevel; i++) {
|
||||
LoadTextureLevel(*entry, replaced, i, scaleFactor, dstFmt);
|
||||
LoadTextureLevel(*entry, replaced, i, i, scaleFactor, dstFmt);
|
||||
}
|
||||
texMaxLevel = maxLevel;
|
||||
}
|
||||
|
@ -609,40 +617,32 @@ CheckAlphaResult TextureCacheGLES::CheckAlpha(const uint8_t *pixelData, Draw::Da
|
|||
}
|
||||
}
|
||||
|
||||
void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int scaleFactor, Draw::DataFormat dstFmt) {
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int srcLevel, int dstLevel, int scaleFactor, Draw::DataFormat dstFmt) {
|
||||
int w = gstate.getTextureWidth(srcLevel);
|
||||
int h = gstate.getTextureHeight(srcLevel);
|
||||
uint8_t *pixelData;
|
||||
int decPitch = 0;
|
||||
|
||||
gpuStats.numTexturesDecoded++;
|
||||
|
||||
if (!entry.textureName) {
|
||||
// TODO: Actually pass in correct size here. The size here is not yet used for anything else
|
||||
// than determining if we can wrap this texture size, that is, it's pow2 or not on very old hardware, else true.
|
||||
// This will be easy after .. well, yet another refactoring, where I hoist the size calculation out of LoadTextureLevel
|
||||
// and unify BuildTexture.
|
||||
entry.textureName = render_->CreateTexture(GL_TEXTURE_2D, 16, 16, 1);
|
||||
}
|
||||
|
||||
if (replaced.GetSize(level, w, h)) {
|
||||
if (replaced.GetSize(srcLevel, w, h)) {
|
||||
PROFILE_THIS_SCOPE("replacetex");
|
||||
|
||||
int bpp = (int)DataFormatSizeInBytes(replaced.Format(level));
|
||||
int bpp = (int)DataFormatSizeInBytes(replaced.Format(srcLevel));
|
||||
decPitch = w * bpp;
|
||||
uint8_t *rearrange = (uint8_t *)AllocateAlignedMemory(decPitch * h, 16);
|
||||
double replaceStart = time_now_d();
|
||||
replaced.Load(level, rearrange, decPitch);
|
||||
replaced.Load(srcLevel, rearrange, decPitch);
|
||||
replacementTimeThisFrame_ += time_now_d() - replaceStart;
|
||||
pixelData = rearrange;
|
||||
|
||||
dstFmt = replaced.Format(level);
|
||||
dstFmt = replaced.Format(srcLevel);
|
||||
} else {
|
||||
PROFILE_THIS_SCOPE("decodetex");
|
||||
|
||||
GEPaletteFormat clutformat = gstate.getClutPaletteFormat();
|
||||
u32 texaddr = gstate.getTextureAddress(level);
|
||||
int bufw = GetTextureBufw(level, texaddr, GETextureFormat(entry.format));
|
||||
u32 texaddr = gstate.getTextureAddress(srcLevel);
|
||||
int bufw = GetTextureBufw(srcLevel, texaddr, GETextureFormat(entry.format));
|
||||
|
||||
int pixelSize = dstFmt == Draw::DataFormat::R8G8B8A8_UNORM ? 4 : 2;
|
||||
// We leave GL_UNPACK_ALIGNMENT at 4, so this must be at least 4.
|
||||
|
@ -650,8 +650,8 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r
|
|||
|
||||
pixelData = (uint8_t *)AllocateAlignedMemory(decPitch * h * pixelSize, 16);
|
||||
|
||||
CheckAlphaResult alphaStatus = DecodeTextureLevel(pixelData, decPitch, GETextureFormat(entry.format), clutformat, texaddr, level, bufw, true, false);
|
||||
entry.SetAlphaStatus(alphaStatus, level);
|
||||
CheckAlphaResult alphaStatus = DecodeTextureLevel(pixelData, decPitch, GETextureFormat(entry.format), clutformat, texaddr, srcLevel, bufw, true, false);
|
||||
entry.SetAlphaStatus(alphaStatus, srcLevel);
|
||||
|
||||
if (scaleFactor > 1) {
|
||||
uint8_t *rearrange = (uint8_t *)AllocateAlignedMemory(w * scaleFactor * h * scaleFactor * 4, 16);
|
||||
|
@ -673,15 +673,12 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r
|
|||
replacedInfo.scaleFactor = scaleFactor;
|
||||
replacedInfo.fmt = dstFmt;
|
||||
|
||||
replacer_.NotifyTextureDecoded(replacedInfo, pixelData, decPitch, level, w, h);
|
||||
replacer_.NotifyTextureDecoded(replacedInfo, pixelData, decPitch, srcLevel, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
PROFILE_THIS_SCOPE("loadtex");
|
||||
if (IsFakeMipmapChange())
|
||||
render_->TextureImage(entry.textureName, 0, w, h, dstFmt, pixelData, GLRAllocType::ALIGNED);
|
||||
else
|
||||
render_->TextureImage(entry.textureName, level, w, h, dstFmt, pixelData, GLRAllocType::ALIGNED);
|
||||
render_->TextureImage(entry.textureName, dstLevel, w, h, dstFmt, pixelData, GLRAllocType::ALIGNED);
|
||||
}
|
||||
|
||||
bool TextureCacheGLES::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) {
|
||||
|
|
|
@ -70,7 +70,7 @@ protected:
|
|||
|
||||
private:
|
||||
void ApplySamplingParams(const SamplerCacheKey &key);
|
||||
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int scaleFactor, Draw::DataFormat dstFmt);
|
||||
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int srcLevel, int dstLevel, int scaleFactor, Draw::DataFormat dstFmt);
|
||||
Draw::DataFormat GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const;
|
||||
|
||||
static CheckAlphaResult CheckAlpha(const uint8_t *pixelData, Draw::DataFormat dstFmt, int w);
|
||||
|
|
|
@ -916,7 +916,8 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
|||
prevStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
}
|
||||
entry->vkTex->EndCreate(cmdInit, false, computeUpload ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
entry->vkTex->EndCreate(cmdInit, false, prevStage, computeUpload ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
|
||||
|
||||
if (maxLevel == 0) {
|
||||
|
@ -969,9 +970,9 @@ CheckAlphaResult TextureCacheVulkan::CheckAlpha(const u32 *pixelData, VkFormat d
|
|||
}
|
||||
}
|
||||
|
||||
void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePtr, int rowPitch, int level, int scaleFactor, VkFormat dstFmt) {
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePtr, int rowPitch, int srcLevel, int scaleFactor, VkFormat dstFmt) {
|
||||
int w = gstate.getTextureWidth(srcLevel);
|
||||
int h = gstate.getTextureHeight(srcLevel);
|
||||
|
||||
gpuStats.numTexturesDecoded++;
|
||||
|
||||
|
@ -980,11 +981,11 @@ void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePt
|
|||
|
||||
GETextureFormat tfmt = (GETextureFormat)entry.format;
|
||||
GEPaletteFormat clutformat = gstate.getClutPaletteFormat();
|
||||
u32 texaddr = gstate.getTextureAddress(level);
|
||||
u32 texaddr = gstate.getTextureAddress(srcLevel);
|
||||
|
||||
_assert_msg_(texaddr != 0, "Can't load a texture from address null")
|
||||
|
||||
int bufw = GetTextureBufw(level, texaddr, tfmt);
|
||||
int bufw = GetTextureBufw(srcLevel, texaddr, tfmt);
|
||||
int bpp = dstFmt == VULKAN_8888_FORMAT ? 4 : 2;
|
||||
|
||||
u32 *pixelData = (u32 *)writePtr;
|
||||
|
@ -999,10 +1000,10 @@ void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePt
|
|||
|
||||
bool expand32 = !gstate_c.Supports(GPU_SUPPORTS_16BIT_FORMATS) || dstFmt == VK_FORMAT_R8G8B8A8_UNORM;
|
||||
|
||||
CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, expand32);
|
||||
CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, srcLevel, bufw, false, expand32);
|
||||
|
||||
// WARN_LOG(G3D, "Alpha: full=%d w=%d h=%d level=%d %s/%s", (int)(alphaResult == CHECKALPHA_FULL), w, h, level, GeTextureFormatToString(tfmt), GEPaletteFormatToString(clutformat));
|
||||
entry.SetAlphaStatus(alphaResult, level);
|
||||
entry.SetAlphaStatus(alphaResult, srcLevel);
|
||||
|
||||
if (scaleFactor > 1) {
|
||||
u32 fmt = dstFmt;
|
||||
|
|
Loading…
Add table
Reference in a new issue