Remove fake-mipmap logic from LoadTextureLevel

This commit is contained in:
Henrik Rydgård 2020-12-10 11:18:43 +01:00
parent 8b398bbbb7
commit f728faffdc
7 changed files with 161 additions and 172 deletions

View file

@ -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);
}

View file

@ -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;

View file

@ -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) {

View file

@ -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;

View file

@ -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) {

View file

@ -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);

View file

@ -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;