TextureCache: Support compressed textures and pass pitch/size to upload
This also removes an extra copy of the image for custom textures.
This commit is contained in:
parent
bc8a96d713
commit
f4b848949c
|
@ -129,10 +129,10 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase*
|
|||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(const u8* buffer, u32 width, u32 height, u32 expanded_width,
|
||||
u32 level)
|
||||
void TextureCache::TCacheEntry::Load(u32 level, u32 width, u32 height, u32 row_length,
|
||||
const u8* buffer, size_t buffer_size)
|
||||
{
|
||||
unsigned int src_pitch = 4 * expanded_width;
|
||||
u32 src_pitch = row_length * 4;
|
||||
D3D::context->UpdateSubresource(texture->GetTex(), level, nullptr, buffer, src_pitch, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,8 @@ private:
|
|||
const MathUtil::Rectangle<int>& srcrect,
|
||||
const MathUtil::Rectangle<int>& dstrect) override;
|
||||
|
||||
void Load(const u8* buffer, u32 width, u32 height, u32 expanded_width, u32 levels) override;
|
||||
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size) override;
|
||||
|
||||
void FromRenderTarget(bool is_depth_copy, const EFBRectangle& srcRect, bool scaleByHalf,
|
||||
unsigned int cbufid, const float* colmat) override;
|
||||
|
|
|
@ -175,10 +175,10 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase*
|
|||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(const u8* buffer, u32 width, u32 height, u32 expanded_width,
|
||||
u32 level)
|
||||
void TextureCache::TCacheEntry::Load(u32 level, u32 width, u32 height, u32 row_length,
|
||||
const u8* buffer, size_t buffer_size)
|
||||
{
|
||||
unsigned int src_pitch = 4 * expanded_width;
|
||||
u32 src_pitch = 4 * row_length;
|
||||
D3D::ReplaceRGBATexture2D(m_texture->GetTex12(), buffer, width, height, src_pitch, level,
|
||||
m_texture->GetResourceUsageState());
|
||||
}
|
||||
|
|
|
@ -39,7 +39,8 @@ private:
|
|||
const MathUtil::Rectangle<int>& src_rect,
|
||||
const MathUtil::Rectangle<int>& dst_rect) override;
|
||||
|
||||
void Load(const u8* buffer, u32 width, u32 height, u32 expanded_width, u32 levels) override;
|
||||
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size) override;
|
||||
|
||||
void FromRenderTarget(bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half,
|
||||
unsigned int cbuf_id, const float* colmat) override;
|
||||
|
|
|
@ -45,6 +45,7 @@ void VideoBackend::InitBackendInfo()
|
|||
g_Config.backend_info.bSupportsMultithreading = false;
|
||||
g_Config.backend_info.bSupportsInternalResolutionFrameDumps = false;
|
||||
g_Config.backend_info.bSupportsGPUTextureDecoding = false;
|
||||
g_Config.backend_info.bSupportsST3CTextures = false;
|
||||
|
||||
// aamodes: We only support 1 sample, so no MSAA
|
||||
g_Config.backend_info.Adapters.clear();
|
||||
|
|
|
@ -31,7 +31,10 @@ private:
|
|||
{
|
||||
TCacheEntry(const TCacheEntryConfig& _config) : TCacheEntryBase(_config) {}
|
||||
~TCacheEntry() {}
|
||||
void Load(const u8* buffer, u32 width, u32 height, u32 expanded_width, u32 level) override {}
|
||||
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size) override
|
||||
{
|
||||
}
|
||||
void FromRenderTarget(bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half,
|
||||
unsigned int cbufid, const float* colmat) override
|
||||
{
|
||||
|
|
|
@ -202,8 +202,8 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase*
|
|||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(const u8* buffer, u32 width, u32 height, u32 expanded_width,
|
||||
u32 level)
|
||||
void TextureCache::TCacheEntry::Load(u32 level, u32 width, u32 height, u32 row_length,
|
||||
const u8* buffer, size_t buffer_size)
|
||||
{
|
||||
if (level >= config.levels)
|
||||
PanicAlert("Texture only has %d levels, can't update level %d", config.levels, level);
|
||||
|
@ -216,8 +216,8 @@ void TextureCache::TCacheEntry::Load(const u8* buffer, u32 width, u32 height, u3
|
|||
glActiveTexture(GL_TEXTURE9);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
|
||||
|
||||
if (expanded_width != width)
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width);
|
||||
if (row_length != width)
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
|
||||
|
||||
if (g_ogl_config.bSupportsTextureStorage)
|
||||
{
|
||||
|
@ -230,7 +230,7 @@ void TextureCache::TCacheEntry::Load(const u8* buffer, u32 width, u32 height, u3
|
|||
GL_UNSIGNED_BYTE, buffer);
|
||||
}
|
||||
|
||||
if (expanded_width != width)
|
||||
if (row_length != width)
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
|
||||
TextureCache::SetStage();
|
||||
|
|
|
@ -45,7 +45,8 @@ private:
|
|||
const MathUtil::Rectangle<int>& srcrect,
|
||||
const MathUtil::Rectangle<int>& dstrect) override;
|
||||
|
||||
void Load(const u8* buffer, u32 width, u32 height, u32 expanded_width, u32 level) override;
|
||||
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size) override;
|
||||
|
||||
void FromRenderTarget(bool is_depth_copy, const EFBRectangle& srcRect, bool scaleByHalf,
|
||||
unsigned int cbufid, const float* colmat) override;
|
||||
|
|
|
@ -65,7 +65,10 @@ private:
|
|||
{
|
||||
TCacheEntry(const TCacheEntryConfig& _config) : TCacheEntryBase(_config) {}
|
||||
~TCacheEntry() {}
|
||||
void Load(const u8* buffer, u32 width, u32 height, u32 expanded_width, u32 level) override {}
|
||||
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size) override
|
||||
{
|
||||
}
|
||||
void FromRenderTarget(bool is_depth_copy, const EFBRectangle& srcRect, bool scaleByHalf,
|
||||
unsigned int cbufid, const float* colmat) override
|
||||
{
|
||||
|
|
|
@ -341,8 +341,8 @@ TextureCache::TCacheEntry::~TCacheEntry()
|
|||
g_command_buffer_mgr->DeferFramebufferDestruction(m_framebuffer);
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(const u8* buffer, unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level)
|
||||
void TextureCache::TCacheEntry::Load(u32 level, u32 width, u32 height, u32 row_length,
|
||||
const u8* buffer, size_t buffer_size)
|
||||
{
|
||||
// Can't copy data larger than the texture extents.
|
||||
width = std::max(1u, std::min(width, m_texture->GetWidth() >> level));
|
||||
|
@ -371,7 +371,7 @@ void TextureCache::TCacheEntry::Load(const u8* buffer, unsigned int width, unsig
|
|||
u32 upload_pitch = upload_width * sizeof(u32);
|
||||
u32 upload_size = upload_pitch * height;
|
||||
u32 upload_alignment = static_cast<u32>(g_vulkan_context->GetBufferImageGranularity());
|
||||
u32 source_pitch = expanded_width * 4;
|
||||
u32 source_pitch = row_length * 4;
|
||||
if ((upload_size + upload_alignment) <= STAGING_TEXTURE_UPLOAD_THRESHOLD &&
|
||||
(upload_size + upload_alignment) <= MAXIMUM_TEXTURE_UPLOAD_BUFFER_SIZE)
|
||||
{
|
||||
|
|
|
@ -27,8 +27,8 @@ public:
|
|||
|
||||
Texture2D* GetTexture() const { return m_texture.get(); }
|
||||
VkFramebuffer GetFramebuffer() const { return m_framebuffer; }
|
||||
void Load(const u8* buffer, unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level) override;
|
||||
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size) override;
|
||||
void FromRenderTarget(bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half,
|
||||
unsigned int cbufid, const float* colmat) override;
|
||||
void CopyRectangleFromTexture(const TCacheEntryBase* source,
|
||||
|
|
|
@ -750,8 +750,6 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
|
|||
}
|
||||
expandedWidth = level.width;
|
||||
expandedHeight = level.height;
|
||||
CheckTempSize(level.data_size);
|
||||
memcpy(temp, level.data.get(), level.data_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -774,6 +772,7 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
|
|||
config.width = width;
|
||||
config.height = height;
|
||||
config.levels = texLevels;
|
||||
config.format = hires_tex ? hires_tex->GetFormat() : HostTextureFormat::RGBA8;
|
||||
|
||||
TCacheEntryBase* entry = AllocateTexture(config);
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true);
|
||||
|
@ -784,17 +783,20 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
|
|||
const u8* tlut = &texMem[tlutaddr];
|
||||
if (hires_tex)
|
||||
{
|
||||
entry->Load(temp, width, height, expandedWidth, 0);
|
||||
const auto& level = hires_tex->m_levels[0];
|
||||
entry->Load(0, level.width, level.height, level.row_length, level.data.get(), level.data_size);
|
||||
}
|
||||
else if (decode_on_gpu)
|
||||
if (!hires_tex && decode_on_gpu)
|
||||
{
|
||||
u32 row_stride = bytes_per_block * (expandedWidth / bsw);
|
||||
g_texture_cache->DecodeTextureOnGPU(
|
||||
entry, 0, src_data, texture_size, static_cast<TextureFormat>(texformat), width, height,
|
||||
expandedWidth, expandedHeight, row_stride, tlut, static_cast<TlutFormat>(tlutfmt));
|
||||
}
|
||||
else
|
||||
else if (!hires_tex)
|
||||
{
|
||||
size_t decoded_texture_size = expandedWidth * sizeof(u32) * expandedHeight;
|
||||
CheckTempSize(decoded_texture_size);
|
||||
if (!(texformat == GX_TF_RGBA8 && from_tmem))
|
||||
{
|
||||
TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlut,
|
||||
|
@ -807,7 +809,7 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
|
|||
TexDecoder_DecodeRGBA8FromTmem(temp, src_data, src_data_gb, expandedWidth, expandedHeight);
|
||||
}
|
||||
|
||||
entry->Load(temp, width, height, expandedWidth, 0);
|
||||
entry->Load(0, width, height, expandedWidth, temp, decoded_texture_size);
|
||||
}
|
||||
|
||||
iter = textures_by_address.emplace(address, entry);
|
||||
|
@ -837,9 +839,8 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
|
|||
for (u32 level_index = 1; level_index != texLevels; ++level_index)
|
||||
{
|
||||
const auto& level = hires_tex->m_levels[level_index];
|
||||
CheckTempSize(level.data_size);
|
||||
memcpy(temp, level.data.get(), level.data_size);
|
||||
entry->Load(temp, level.width, level.height, level.width, level_index);
|
||||
entry->Load(level_index, level.width, level.height, level.row_length, level.data.get(),
|
||||
level.data_size);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -877,9 +878,11 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
|
|||
}
|
||||
else
|
||||
{
|
||||
// No need to call CheckTempSize here, as mips will always be smaller than the base level.
|
||||
size_t decoded_mip_size = expanded_mip_width * sizeof(u32) * expanded_mip_height;
|
||||
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);
|
||||
entry->Load(level, mip_width, mip_height, expanded_mip_width, temp, decoded_mip_size);
|
||||
}
|
||||
|
||||
mip_src_data += mip_size;
|
||||
|
|
|
@ -27,16 +27,16 @@ public:
|
|||
|
||||
bool operator==(const TCacheEntryConfig& o) const
|
||||
{
|
||||
return std::tie(width, height, levels, layers, rendertarget) ==
|
||||
std::tie(o.width, o.height, o.levels, o.layers, o.rendertarget);
|
||||
return std::tie(width, height, levels, layers, format, rendertarget) ==
|
||||
std::tie(o.width, o.height, o.levels, o.layers, o.format, o.rendertarget);
|
||||
}
|
||||
|
||||
struct Hasher : std::hash<u64>
|
||||
{
|
||||
size_t operator()(const TCacheEntryConfig& c) const
|
||||
{
|
||||
u64 id = (u64)c.rendertarget << 63 | (u64)c.layers << 48 | (u64)c.levels << 32 |
|
||||
(u64)c.height << 16 | (u64)c.width;
|
||||
u64 id = (u64)c.rendertarget << 63 | (u64)c.format << 50 | (u64)c.layers << 48 |
|
||||
(u64)c.levels << 32 | (u64)c.height << 16 | (u64)c.width;
|
||||
return std::hash<u64>::operator()(id);
|
||||
}
|
||||
};
|
||||
|
@ -45,6 +45,7 @@ public:
|
|||
u32 height = 0;
|
||||
u32 levels = 1;
|
||||
u32 layers = 1;
|
||||
HostTextureFormat format = HostTextureFormat::RGBA8;
|
||||
bool rendertarget = false;
|
||||
};
|
||||
|
||||
|
@ -129,7 +130,8 @@ public:
|
|||
const MathUtil::Rectangle<int>& srcrect,
|
||||
const MathUtil::Rectangle<int>& dstrect) = 0;
|
||||
|
||||
virtual void Load(const u8* buffer, u32 width, u32 height, u32 expanded_width, u32 level) = 0;
|
||||
virtual void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size) = 0;
|
||||
virtual void FromRenderTarget(bool is_depth_copy, const EFBRectangle& srcRect, bool scaleByHalf,
|
||||
unsigned int cbufid, const float* colmat) = 0;
|
||||
|
||||
|
|
Loading…
Reference in New Issue