diff --git a/Source/Core/VideoBackends/D3D/TextureCache.cpp b/Source/Core/VideoBackends/D3D/TextureCache.cpp index d6369f290f..de22a2c04f 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/TextureCache.cpp @@ -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); } diff --git a/Source/Core/VideoBackends/D3D/TextureCache.h b/Source/Core/VideoBackends/D3D/TextureCache.h index 01b229cf72..78450eefdd 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.h +++ b/Source/Core/VideoBackends/D3D/TextureCache.h @@ -30,7 +30,8 @@ private: const MathUtil::Rectangle& srcrect, const MathUtil::Rectangle& 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; diff --git a/Source/Core/VideoBackends/D3D12/TextureCache.cpp b/Source/Core/VideoBackends/D3D12/TextureCache.cpp index d626cb7732..77009112cd 100644 --- a/Source/Core/VideoBackends/D3D12/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D12/TextureCache.cpp @@ -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()); } diff --git a/Source/Core/VideoBackends/D3D12/TextureCache.h b/Source/Core/VideoBackends/D3D12/TextureCache.h index f6921afe5b..fb8cdf3385 100644 --- a/Source/Core/VideoBackends/D3D12/TextureCache.h +++ b/Source/Core/VideoBackends/D3D12/TextureCache.h @@ -39,7 +39,8 @@ private: const MathUtil::Rectangle& src_rect, const MathUtil::Rectangle& 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; diff --git a/Source/Core/VideoBackends/Null/NullBackend.cpp b/Source/Core/VideoBackends/Null/NullBackend.cpp index 7892b86927..bcbbd1aaab 100644 --- a/Source/Core/VideoBackends/Null/NullBackend.cpp +++ b/Source/Core/VideoBackends/Null/NullBackend.cpp @@ -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(); diff --git a/Source/Core/VideoBackends/Null/TextureCache.h b/Source/Core/VideoBackends/Null/TextureCache.h index 48d111dce6..399af04764 100644 --- a/Source/Core/VideoBackends/Null/TextureCache.h +++ b/Source/Core/VideoBackends/Null/TextureCache.h @@ -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 { diff --git a/Source/Core/VideoBackends/OGL/TextureCache.cpp b/Source/Core/VideoBackends/OGL/TextureCache.cpp index 3bf1342809..e49483a593 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/TextureCache.cpp @@ -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(); diff --git a/Source/Core/VideoBackends/OGL/TextureCache.h b/Source/Core/VideoBackends/OGL/TextureCache.h index aece35cd6c..de0de485f5 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.h +++ b/Source/Core/VideoBackends/OGL/TextureCache.h @@ -45,7 +45,8 @@ private: const MathUtil::Rectangle& srcrect, const MathUtil::Rectangle& 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; diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index 1b26f1d40a..e004a0cac3 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -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 { diff --git a/Source/Core/VideoBackends/Vulkan/TextureCache.cpp b/Source/Core/VideoBackends/Vulkan/TextureCache.cpp index 08c370b48f..62c0228010 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureCache.cpp +++ b/Source/Core/VideoBackends/Vulkan/TextureCache.cpp @@ -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(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) { diff --git a/Source/Core/VideoBackends/Vulkan/TextureCache.h b/Source/Core/VideoBackends/Vulkan/TextureCache.h index 5fd25c23d8..884d82ddf4 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureCache.h +++ b/Source/Core/VideoBackends/Vulkan/TextureCache.h @@ -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, diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 89d473cfec..e3a9daa69d 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -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(texformat), width, height, expandedWidth, expandedHeight, row_stride, tlut, static_cast(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; diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 4c9582079b..f621f7d92a 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -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 { 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::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& srcrect, const MathUtil::Rectangle& 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;