HiresTextures: Do not load compressed textures with unaligned dimensions
D3D11 cannot handle block compressed textures where the first mip level is not a multiple of the block size. The simple fix for texture pack authors: leave these textures uncompressed. You can still use a .dds container.
This commit is contained in:
parent
7eaba154a4
commit
f7a0cae7f4
|
@ -335,7 +335,7 @@ std::unique_ptr<HiresTexture> HiresTexture::Load(const std::string& base_filenam
|
||||||
// Try loading DDS textures first, that way we maintain compression of DXT formats.
|
// Try loading DDS textures first, that way we maintain compression of DXT formats.
|
||||||
// TODO: Reduce the number of open() calls here. We could use one fd.
|
// TODO: Reduce the number of open() calls here. We could use one fd.
|
||||||
Level level;
|
Level level;
|
||||||
if (!LoadDDSTexture(level, filename_iter->second.path))
|
if (!LoadDDSTexture(level, filename_iter->second.path, mip_level))
|
||||||
{
|
{
|
||||||
File::IOFile file;
|
File::IOFile file;
|
||||||
file.Open(filename_iter->second.path, "rb");
|
file.Open(filename_iter->second.path, "rb");
|
||||||
|
|
|
@ -49,7 +49,7 @@ private:
|
||||||
static std::unique_ptr<HiresTexture> Load(const std::string& base_filename, u32 width,
|
static std::unique_ptr<HiresTexture> Load(const std::string& base_filename, u32 width,
|
||||||
u32 height);
|
u32 height);
|
||||||
static bool LoadDDSTexture(HiresTexture* tex, const std::string& filename);
|
static bool LoadDDSTexture(HiresTexture* tex, const std::string& filename);
|
||||||
static bool LoadDDSTexture(Level& level, const std::string& filename);
|
static bool LoadDDSTexture(Level& level, const std::string& filename, u32 mip_level);
|
||||||
static bool LoadTexture(Level& level, const std::vector<u8>& buffer);
|
static bool LoadTexture(Level& level, const std::vector<u8>& buffer);
|
||||||
static void Prefetch();
|
static void Prefetch();
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "Common/Align.h"
|
#include "Common/Align.h"
|
||||||
#include "Common/File.h"
|
#include "Common/File.h"
|
||||||
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/Swap.h"
|
#include "Common/Swap.h"
|
||||||
#include "VideoCommon/VideoConfig.h"
|
#include "VideoCommon/VideoConfig.h"
|
||||||
|
|
||||||
|
@ -400,9 +401,22 @@ bool ParseDDSHeader(File::IOFile& file, DDSLoadInfo* info)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadMipLevel(HiresTexture::Level* level, File::IOFile& file, const DDSLoadInfo& info,
|
bool ReadMipLevel(HiresTexture::Level* level, File::IOFile& file, const std::string& filename,
|
||||||
u32 width, u32 height, u32 row_length, size_t size)
|
u32 mip_level, const DDSLoadInfo& info, u32 width, u32 height, u32 row_length,
|
||||||
|
size_t size)
|
||||||
{
|
{
|
||||||
|
// D3D11 cannot handle block compressed textures where the first mip level is
|
||||||
|
// not a multiple of the block size.
|
||||||
|
if (mip_level == 0 && info.block_size > 1 &&
|
||||||
|
((width % info.block_size) != 0 || (height % info.block_size) != 0))
|
||||||
|
{
|
||||||
|
ERROR_LOG(VIDEO,
|
||||||
|
"Invalid dimensions for DDS texture %s. For compressed textures of this format, "
|
||||||
|
"the width/height of the first mip level must be a multiple of %u.",
|
||||||
|
filename.c_str(), info.block_size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Copy to the final storage location.
|
// Copy to the final storage location.
|
||||||
level->width = width;
|
level->width = width;
|
||||||
level->height = height;
|
level->height = height;
|
||||||
|
@ -435,8 +449,8 @@ bool HiresTexture::LoadDDSTexture(HiresTexture* tex, const std::string& filename
|
||||||
// Read first mip level, as it may have a custom pitch.
|
// Read first mip level, as it may have a custom pitch.
|
||||||
Level first_level;
|
Level first_level;
|
||||||
if (!file.Seek(info.first_mip_offset, SEEK_SET) ||
|
if (!file.Seek(info.first_mip_offset, SEEK_SET) ||
|
||||||
!ReadMipLevel(&first_level, file, info, info.width, info.height, info.first_mip_row_length,
|
!ReadMipLevel(&first_level, file, filename, 0, info, info.width, info.height,
|
||||||
info.first_mip_size))
|
info.first_mip_row_length, info.first_mip_size))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -458,7 +472,8 @@ bool HiresTexture::LoadDDSTexture(HiresTexture* tex, const std::string& filename
|
||||||
u32 mip_row_length = blocks_wide * info.block_size;
|
u32 mip_row_length = blocks_wide * info.block_size;
|
||||||
size_t mip_size = blocks_wide * static_cast<size_t>(info.bytes_per_block) * blocks_high;
|
size_t mip_size = blocks_wide * static_cast<size_t>(info.bytes_per_block) * blocks_high;
|
||||||
Level level;
|
Level level;
|
||||||
if (!ReadMipLevel(&level, file, info, mip_width, mip_height, mip_row_length, mip_size))
|
if (!ReadMipLevel(&level, file, filename, i, info, mip_width, mip_height, mip_row_length,
|
||||||
|
mip_size))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
tex->m_levels.push_back(std::move(level));
|
tex->m_levels.push_back(std::move(level));
|
||||||
|
@ -467,7 +482,7 @@ bool HiresTexture::LoadDDSTexture(HiresTexture* tex, const std::string& filename
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HiresTexture::LoadDDSTexture(Level& level, const std::string& filename)
|
bool HiresTexture::LoadDDSTexture(Level& level, const std::string& filename, u32 mip_level)
|
||||||
{
|
{
|
||||||
// Only loading a single mip level.
|
// Only loading a single mip level.
|
||||||
File::IOFile file;
|
File::IOFile file;
|
||||||
|
@ -479,6 +494,6 @@ bool HiresTexture::LoadDDSTexture(Level& level, const std::string& filename)
|
||||||
if (!ParseDDSHeader(file, &info))
|
if (!ParseDDSHeader(file, &info))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return ReadMipLevel(&level, file, info, info.width, info.height, info.first_mip_row_length,
|
return ReadMipLevel(&level, file, filename, mip_level, info, info.width, info.height,
|
||||||
info.first_mip_size);
|
info.first_mip_row_length, info.first_mip_size);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue