mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Prevent creating texture with invalid mipmap levels
Fixes crash during loading in Jak with Metal renderer, and UB with Vulkan.
This commit is contained in:
parent
b4b2f3a0b6
commit
ed57355948
|
@ -74,11 +74,6 @@ const char* shaderName(PresentShader value)
|
|||
}
|
||||
}
|
||||
|
||||
static int MipmapLevelsForSize(int width, int height)
|
||||
{
|
||||
return std::min(static_cast<int>(std::log2(std::max(width, height))) + 1, MAXIMUM_TEXTURE_MIPMAP_LEVELS);
|
||||
}
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
|
||||
enum class TextureLabel
|
||||
|
@ -285,6 +280,11 @@ std::optional<std::string> GSDevice::ReadShaderSource(const char* filename)
|
|||
return FileSystem::ReadFileToString(Path::Combine(EmuFolders::Resources, filename).c_str());
|
||||
}
|
||||
|
||||
int GSDevice::GetMipmapLevelsForSize(int width, int height)
|
||||
{
|
||||
return std::min(static_cast<int>(std::log2(std::max(width, height))) + 1, MAXIMUM_TEXTURE_MIPMAP_LEVELS);
|
||||
}
|
||||
|
||||
bool GSDevice::Create()
|
||||
{
|
||||
m_vsync_mode = Host::GetEffectiveVSyncMode();
|
||||
|
@ -546,7 +546,8 @@ GSTexture* GSDevice::CreateDepthStencil(int w, int h, GSTexture::Format format,
|
|||
|
||||
GSTexture* GSDevice::CreateTexture(int w, int h, int mipmap_levels, GSTexture::Format format, bool prefer_reuse /* = false */)
|
||||
{
|
||||
const int levels = mipmap_levels < 0 ? MipmapLevelsForSize(w, h) : mipmap_levels;
|
||||
pxAssert(mipmap_levels != 0 && (mipmap_levels < 0 || mipmap_levels <= GetMipmapLevelsForSize(w, h)));
|
||||
const int levels = mipmap_levels < 0 ? GetMipmapLevelsForSize(w, h) : mipmap_levels;
|
||||
return FetchSurface(GSTexture::Type::Texture, w, h, levels, format, false, m_features.prefer_new_textures && !prefer_reuse);
|
||||
}
|
||||
|
||||
|
|
|
@ -815,6 +815,9 @@ public:
|
|||
/// Reads the specified shader source file.
|
||||
static std::optional<std::string> ReadShaderSource(const char* filename);
|
||||
|
||||
/// Returns the maximum number of mipmap levels for a given texture size.
|
||||
static int GetMipmapLevelsForSize(int width, int height);
|
||||
|
||||
__fi u64 GetPoolMemoryUsage() const { return m_pool_memory_usage; }
|
||||
|
||||
__fi FeatureSupport Features() const { return m_features; }
|
||||
|
|
|
@ -4166,7 +4166,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
|||
{
|
||||
// lod won't contain the full range when using basic mipmapping, only that
|
||||
// which is hashed, so we just allocate the full thing.
|
||||
tlevels = (GSConfig.HWMipmap != HWMipmapLevel::Full) ? -1 : (lod->y - lod->x + 1);
|
||||
tlevels = (GSConfig.HWMipmap != HWMipmapLevel::Full) ? -1 : std::min(lod->y - lod->x + 1, GSDevice::GetMipmapLevelsForSize(tw, th));
|
||||
src->m_lod = *lod;
|
||||
}
|
||||
|
||||
|
@ -5069,7 +5069,7 @@ GSTextureCache::HashCacheEntry* GSTextureCache::LookupHashCache(const GIFRegTEX0
|
|||
// expand/upload texture
|
||||
const int tw = region.HasX() ? region.GetWidth() : (1 << TEX0.TW);
|
||||
const int th = region.HasY() ? region.GetHeight() : (1 << TEX0.TH);
|
||||
const int tlevels = lod ? ((GSConfig.HWMipmap != HWMipmapLevel::Full) ? -1 : (lod->y - lod->x + 1)) : 1;
|
||||
const int tlevels = lod ? ((GSConfig.HWMipmap != HWMipmapLevel::Full) ? -1 : std::min(lod->y - lod->x + 1, GSDevice::GetMipmapLevelsForSize(tw, th))) : 1;
|
||||
GSTexture* tex = g_gs_device->CreateTexture(tw, th, tlevels, paltex ? GSTexture::Format::UNorm8 : GSTexture::Format::Color);
|
||||
if (!tex)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue