diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 98c61022804f..3b9aeb99e4b2 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -15,16 +15,13 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#ifdef USING_QT_UI -#include -#else #include -#endif #include -#include "Common/Data/Text/I18n.h" #include "ext/xxhash.h" + +#include "Common/Data/Text/I18n.h" #include "Common/Data/Format/IniFile.h" #include "Common/Data/Text/Parsers.h" #include "Common/ColorConv.h" @@ -333,16 +330,6 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *result, u64 cachekey, level.fmt = ReplacedTextureFormat::F_8888; level.file = filename; -#ifdef USING_QT_UI - QImage image(filename.c_str(), "PNG"); - if (image.isNull()) { - ERROR_LOG(G3D, "Could not load texture replacement info: %s", filename.c_str()); - } else { - level.w = (image.width() * w) / newW; - level.h = (image.height() * h) / newH; - good = true; - } -#else png_image png = {}; png.version = PNG_IMAGE_VERSION; FILE *fp = File::OpenCFile(filename, "rb"); @@ -357,7 +344,6 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *result, u64 cachekey, fclose(fp); png_image_free(&png); -#endif if (good && i != 0) { // Check that the mipmap size is correct. Can't load mips of the wrong size. @@ -377,7 +363,6 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *result, u64 cachekey, result->alphaStatus_ = ReplacedTextureAlpha::UNKNOWN; } -#ifndef USING_QT_UI static bool WriteTextureToPNG(png_imagep image, const std::string &filename, int convert_to_8bit, const void *buffer, png_int_32 row_stride, const void *colormap) { FILE *fp = File::OpenCFile(filename, "wb"); if (!fp) { @@ -395,7 +380,6 @@ static bool WriteTextureToPNG(png_imagep image, const std::string &filename, int return false; } } -#endif void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &replacedInfo, const void *data, int pitch, int level, int w, int h) { _assert_msg_(enabled_, "Replacement not enabled"); @@ -459,9 +443,6 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl h = lookupH * replacedInfo.scaleFactor; } -#ifdef USING_QT_UI - ERROR_LOG(G3D, "Replacement texture saving not implemented for Qt"); -#else if (replacedInfo.fmt != ReplacedTextureFormat::F_8888) { saveBuf.resize((pitch * h) / sizeof(u16)); switch (replacedInfo.fmt) { @@ -512,7 +493,6 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl } else if (success) { NOTICE_LOG(G3D, "Saving texture for replacement: %08x / %dx%d", replacedInfo.hash, w, h); } -#endif // Remember that we've saved this for next time. ReplacedTextureLevel saved; @@ -600,34 +580,6 @@ void ReplacedTexture::Load(int level, void *out, int rowPitch) { const ReplacedTextureLevel &info = levels_[level]; -#ifdef USING_QT_UI - QImage image(info.file.c_str(), "PNG"); - if (image.isNull()) { - ERROR_LOG(G3D, "Could not load texture replacement info: %s", info.file.c_str()); - return; - } - - image = image.convertToFormat(QImage::Format_ARGB32); - bool alphaFull = true; - for (int y = 0; y < image.height(); ++y) { - const QRgb *src = (const QRgb *)image.constScanLine(y); - uint8_t *outLine = (uint8_t *)out + y * rowPitch; - for (int x = 0; x < image.width(); ++x) { - outLine[x * 4 + 0] = qRed(src[x]); - outLine[x * 4 + 1] = qGreen(src[x]); - outLine[x * 4 + 2] = qBlue(src[x]); - outLine[x * 4 + 3] = qAlpha(src[x]); - // We're already scanning each pixel... - if (qAlpha(src[x]) != 255) { - alphaFull = false; - } - } - } - - if (level == 0 || !alphaFull) { - alphaStatus_ = alphaFull ? ReplacedTextureAlpha::FULL : ReplacedTextureAlpha::UNKNOWN; - } -#else png_image png = {}; png.version = PNG_IMAGE_VERSION; @@ -662,7 +614,6 @@ void ReplacedTexture::Load(int level, void *out, int rowPitch) { fclose(fp); png_image_free(&png); -#endif } bool TextureReplacer::GenerateIni(const std::string &gameID, std::string *generatedFilename) { diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 43ff63089b0b..db328b43496d 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -710,7 +710,10 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { // Adjust maxLevel to actually present levels.. bool badMipSizes = false; + + // maxLevel here is the max level to upload. Not the count. int maxLevel = entry->maxLevel; + for (int i = 0; i <= maxLevel; i++) { // If encountering levels pointing to nothing, adjust max level. u32 levelTexaddr = gstate.getTextureAddress(i); @@ -740,6 +743,10 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { maxLevel = 0; } + // We generate missing mipmaps from maxLevel+1 up to this level. maxLevel can get overwritten below + // such as when using replacement textures - but let's keep the same amount of levels. + int maxLevelToGenerate = maxLevel; + // If GLES3 is available, we can preallocate the storage, which makes texture loading more efficient. VkFormat dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); @@ -824,8 +831,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { } VkImageLayout imageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - // If we want to use the GE debugger, we should add VK_IMAGE_USAGE_TRANSFER_SRC_BIT too... + VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; // Compute experiment if (actualFmt == VULKAN_8888_FORMAT && scaleFactor > 1 && hardwareScaling) { @@ -845,7 +851,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { snprintf(texName, sizeof(texName), "texture_%08x_%s", entry->addr, GeTextureFormatToString((GETextureFormat)entry->format)); image->SetTag(texName); - bool allocSuccess = image->CreateDirect(cmdInit, allocator_, w * scaleFactor, h * scaleFactor, maxLevel + 1, actualFmt, imageLayout, usage, mapping); + bool allocSuccess = image->CreateDirect(cmdInit, allocator_, w * scaleFactor, h * scaleFactor, maxLevelToGenerate + 1, actualFmt, imageLayout, usage, mapping); if (!allocSuccess && !lowMemoryMode_) { WARN_LOG_REPORT(G3D, "Texture cache ran out of GPU memory; switching to low memory mode"); lowMemoryMode_ = true; @@ -864,7 +870,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { scaleFactor = 1; actualFmt = dstFmt; - allocSuccess = image->CreateDirect(cmdInit, allocator_, w * scaleFactor, h * scaleFactor, maxLevel + 1, actualFmt, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, mapping); + allocSuccess = image->CreateDirect(cmdInit, allocator_, w * scaleFactor, h * scaleFactor, maxLevelToGenerate + 1, actualFmt, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, mapping); } if (!allocSuccess) { @@ -987,6 +993,11 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { } } + // Generate any additional mipmap levels. + for (int level = maxLevel + 1; level <= maxLevelToGenerate; level++) { + entry->vkTex->GenerateMip(cmdInit, level); + } + if (maxLevel == 0) { entry->status |= TexCacheEntry::STATUS_BAD_MIPS; } else {