mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 22:59:47 -06:00
VideoCommon: Changes to TextureCache to support decoding in backend
This commit is contained in:
@ -110,7 +110,8 @@ void TextureCacheBase::OnConfigChanged(VideoConfig& config)
|
|||||||
if (config.iSafeTextureCache_ColorSamples != backup_config.color_samples ||
|
if (config.iSafeTextureCache_ColorSamples != backup_config.color_samples ||
|
||||||
config.bTexFmtOverlayEnable != backup_config.texfmt_overlay ||
|
config.bTexFmtOverlayEnable != backup_config.texfmt_overlay ||
|
||||||
config.bTexFmtOverlayCenter != backup_config.texfmt_overlay_center ||
|
config.bTexFmtOverlayCenter != backup_config.texfmt_overlay_center ||
|
||||||
config.bHiresTextures != backup_config.hires_textures)
|
config.bHiresTextures != backup_config.hires_textures ||
|
||||||
|
config.bEnableGPUTextureDecoding != backup_config.gpu_texture_decoding)
|
||||||
{
|
{
|
||||||
Invalidate();
|
Invalidate();
|
||||||
|
|
||||||
@ -209,6 +210,7 @@ void TextureCacheBase::SetBackupConfig(const VideoConfig& config)
|
|||||||
backup_config.cache_hires_textures = config.bCacheHiresTextures;
|
backup_config.cache_hires_textures = config.bCacheHiresTextures;
|
||||||
backup_config.stereo_3d = config.iStereoMode > 0;
|
backup_config.stereo_3d = config.iStereoMode > 0;
|
||||||
backup_config.efb_mono_depth = config.bStereoEFBMonoDepth;
|
backup_config.efb_mono_depth = config.bStereoEFBMonoDepth;
|
||||||
|
backup_config.gpu_texture_decoding = config.bEnableGPUTextureDecoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureCacheBase::TCacheEntryBase* TextureCacheBase::ApplyPaletteToEntry(TCacheEntryBase* entry,
|
TextureCacheBase::TCacheEntryBase* TextureCacheBase::ApplyPaletteToEntry(TCacheEntryBase* entry,
|
||||||
@ -526,6 +528,7 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
|
|||||||
|
|
||||||
const u32 texture_size =
|
const u32 texture_size =
|
||||||
TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat);
|
TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat);
|
||||||
|
u32 bytes_per_block = (bsw * bsh * TexDecoder_GetTexelSizeInNibbles(texformat)) / 2;
|
||||||
u32 additional_mips_size = 0; // not including level 0, which is texture_size
|
u32 additional_mips_size = 0; // not including level 0, which is texture_size
|
||||||
|
|
||||||
// GPUs don't like when the specified mipmap count would require more than one 1x1-sized LOD in
|
// GPUs don't like when the specified mipmap count would require more than one 1x1-sized LOD in
|
||||||
@ -755,6 +758,17 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
|
|||||||
// how many levels the allocated texture shall have
|
// how many levels the allocated texture shall have
|
||||||
const u32 texLevels = hires_tex ? (u32)hires_tex->m_levels.size() : tex_levels;
|
const u32 texLevels = hires_tex ? (u32)hires_tex->m_levels.size() : tex_levels;
|
||||||
|
|
||||||
|
// We can decode on the GPU if it is a supported format and the flag is enabled.
|
||||||
|
// Currently we don't decode RGBA8 textures from Tmem, as that would require copying from both
|
||||||
|
// banks, and if we're doing an copy we may as well just do the whole thing on the CPU, since
|
||||||
|
// there's no conversion between formats. In the future this could be extended with a separate
|
||||||
|
// shader, however.
|
||||||
|
bool decode_on_gpu =
|
||||||
|
!hires_tex && g_ActiveConfig.UseGPUTextureDecoding() &&
|
||||||
|
g_texture_cache->SupportsGPUTextureDecode(static_cast<TextureFormat>(texformat),
|
||||||
|
static_cast<TlutFormat>(tlutfmt)) &&
|
||||||
|
!(from_tmem && texformat == GX_TF_RGBA8);
|
||||||
|
|
||||||
// create the entry/texture
|
// create the entry/texture
|
||||||
TCacheEntryConfig config;
|
TCacheEntryConfig config;
|
||||||
config.width = width;
|
config.width = width;
|
||||||
@ -769,17 +783,29 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
|
|||||||
|
|
||||||
if (!hires_tex)
|
if (!hires_tex)
|
||||||
{
|
{
|
||||||
if (!(texformat == GX_TF_RGBA8 && from_tmem))
|
const u8* tlut = &texMem[tlutaddr];
|
||||||
|
if (decode_on_gpu)
|
||||||
{
|
{
|
||||||
const u8* tlut = &texMem[tlutaddr];
|
u32 row_stride = bytes_per_block * (expandedWidth / bsw);
|
||||||
TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlut,
|
g_texture_cache->DecodeTextureOnGPU(
|
||||||
(TlutFormat)tlutfmt);
|
entry, 0, src_data, texture_size, static_cast<TextureFormat>(texformat), width, height,
|
||||||
|
expandedWidth, expandedHeight, row_stride, tlut, static_cast<TlutFormat>(tlutfmt));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u8* src_data_gb =
|
if (!(texformat == GX_TF_RGBA8 && from_tmem))
|
||||||
&texMem[bpmem.tex[stage / 4].texImage2[stage % 4].tmem_odd * TMEM_LINE_SIZE];
|
{
|
||||||
TexDecoder_DecodeRGBA8FromTmem(temp, src_data, src_data_gb, expandedWidth, expandedHeight);
|
TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlut,
|
||||||
|
(TlutFormat)tlutfmt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u8* src_data_gb =
|
||||||
|
&texMem[bpmem.tex[stage / 4].texImage2[stage % 4].tmem_odd * TMEM_LINE_SIZE];
|
||||||
|
TexDecoder_DecodeRGBA8FromTmem(temp, src_data, src_data_gb, expandedWidth, expandedHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->Load(temp, width, height, expandedWidth, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -797,9 +823,6 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
|
|||||||
entry->is_efb_copy = false;
|
entry->is_efb_copy = false;
|
||||||
entry->is_custom_tex = hires_tex != nullptr;
|
entry->is_custom_tex = hires_tex != nullptr;
|
||||||
|
|
||||||
// load texture
|
|
||||||
entry->Load(temp, width, height, expandedWidth, 0);
|
|
||||||
|
|
||||||
std::string basename = "";
|
std::string basename = "";
|
||||||
if (g_ActiveConfig.bDumpTextures && !hires_tex)
|
if (g_ActiveConfig.bDumpTextures && !hires_tex)
|
||||||
{
|
{
|
||||||
@ -840,13 +863,26 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
|
|||||||
const u32 expanded_mip_height = Common::AlignUp(mip_height, bsh);
|
const u32 expanded_mip_height = Common::AlignUp(mip_height, bsh);
|
||||||
|
|
||||||
const u8*& mip_src_data = from_tmem ? ((level % 2) ? ptr_odd : ptr_even) : src_data;
|
const u8*& mip_src_data = from_tmem ? ((level % 2) ? ptr_odd : ptr_even) : src_data;
|
||||||
const u8* tlut = &texMem[tlutaddr];
|
size_t mip_size =
|
||||||
TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat,
|
|
||||||
tlut, (TlutFormat)tlutfmt);
|
|
||||||
mip_src_data +=
|
|
||||||
TexDecoder_GetTextureSizeInBytes(expanded_mip_width, expanded_mip_height, texformat);
|
TexDecoder_GetTextureSizeInBytes(expanded_mip_width, expanded_mip_height, texformat);
|
||||||
|
const u8* tlut = &texMem[tlutaddr];
|
||||||
|
|
||||||
entry->Load(temp, mip_width, mip_height, expanded_mip_width, level);
|
if (decode_on_gpu)
|
||||||
|
{
|
||||||
|
u32 row_stride = bytes_per_block * (mip_width / bsw);
|
||||||
|
g_texture_cache->DecodeTextureOnGPU(entry, level, mip_src_data, mip_size,
|
||||||
|
static_cast<TextureFormat>(texformat), mip_width,
|
||||||
|
mip_height, expanded_mip_width, expanded_mip_height,
|
||||||
|
row_stride, tlut, static_cast<TlutFormat>(tlutfmt));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat,
|
||||||
|
tlut, (TlutFormat)tlutfmt);
|
||||||
|
entry->Load(temp, mip_width, mip_height, expanded_mip_width, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
mip_src_data += mip_size;
|
||||||
|
|
||||||
if (g_ActiveConfig.bDumpTextures)
|
if (g_ActiveConfig.bDumpTextures)
|
||||||
DumpTexture(entry, basename, level);
|
DumpTexture(entry, basename, level);
|
||||||
|
@ -171,6 +171,23 @@ public:
|
|||||||
virtual void ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette,
|
virtual void ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette,
|
||||||
TlutFormat format) = 0;
|
TlutFormat format) = 0;
|
||||||
|
|
||||||
|
// Returns true if the texture data and palette formats are supported by the GPU decoder.
|
||||||
|
virtual bool SupportsGPUTextureDecode(TextureFormat format, TlutFormat palette_format)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decodes the specified data to the GPU texture specified by entry.
|
||||||
|
// width, height are the size of the image in pixels.
|
||||||
|
// aligned_width, aligned_height are the size of the image in pixels, aligned to the block size.
|
||||||
|
// row_stride is the number of bytes for a row of blocks, not pixels.
|
||||||
|
virtual void DecodeTextureOnGPU(TCacheEntryBase* entry, u32 dst_level, const u8* data,
|
||||||
|
size_t data_size, TextureFormat format, u32 width, u32 height,
|
||||||
|
u32 aligned_width, u32 aligned_height, u32 row_stride,
|
||||||
|
const u8* palette, TlutFormat palette_format)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TextureCacheBase();
|
TextureCacheBase();
|
||||||
|
|
||||||
@ -225,6 +242,7 @@ private:
|
|||||||
bool copy_cache_enable;
|
bool copy_cache_enable;
|
||||||
bool stereo_3d;
|
bool stereo_3d;
|
||||||
bool efb_mono_depth;
|
bool efb_mono_depth;
|
||||||
|
bool gpu_texture_decoding;
|
||||||
};
|
};
|
||||||
BackupConfig backup_config = {};
|
BackupConfig backup_config = {};
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user