gl_texture_cache: Add copy from multiple overlaps into a single surface
This commit is contained in:
parent
84139586c9
commit
0cefb7bcb4
|
@ -518,16 +518,14 @@ TextureCacheOpenGL::TextureCacheOpenGL(Core::System& system,
|
||||||
TextureCacheOpenGL::~TextureCacheOpenGL() = default;
|
TextureCacheOpenGL::~TextureCacheOpenGL() = default;
|
||||||
|
|
||||||
CachedSurfaceView* TextureCacheOpenGL::TryFastGetSurfaceView(
|
CachedSurfaceView* TextureCacheOpenGL::TryFastGetSurfaceView(
|
||||||
VAddr cpu_addr, u8* host_ptr, const SurfaceParams& params, bool preserve_contents,
|
VAddr cpu_addr, u8* host_ptr, const SurfaceParams& new_params, bool preserve_contents,
|
||||||
const std::vector<CachedSurface*>& overlaps) {
|
const std::vector<CachedSurface*>& overlaps) {
|
||||||
if (overlaps.size() > 1) {
|
if (overlaps.size() > 1) {
|
||||||
return nullptr;
|
return TryCopyAsViews(cpu_addr, host_ptr, new_params, overlaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& old_surface{overlaps[0]};
|
const auto& old_surface{overlaps[0]};
|
||||||
const auto& old_params{old_surface->GetSurfaceParams()};
|
const auto& old_params{old_surface->GetSurfaceParams()};
|
||||||
const auto& new_params{params};
|
|
||||||
|
|
||||||
if (old_params.GetTarget() == new_params.GetTarget() &&
|
if (old_params.GetTarget() == new_params.GetTarget() &&
|
||||||
old_params.GetDepth() == new_params.GetDepth() && old_params.GetDepth() == 1 &&
|
old_params.GetDepth() == new_params.GetDepth() && old_params.GetDepth() == 1 &&
|
||||||
old_params.GetNumLevels() == new_params.GetNumLevels() &&
|
old_params.GetNumLevels() == new_params.GetNumLevels() &&
|
||||||
|
@ -567,6 +565,54 @@ CachedSurfaceView* TextureCacheOpenGL::SurfaceCopy(VAddr cpu_addr, u8* host_ptr,
|
||||||
return new_surface->GetView(cpu_addr, new_params);
|
return new_surface->GetView(cpu_addr, new_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CachedSurfaceView* TextureCacheOpenGL::TryCopyAsViews(VAddr cpu_addr, u8* host_ptr,
|
||||||
|
const SurfaceParams& new_params,
|
||||||
|
const std::vector<CachedSurface*>& overlaps) {
|
||||||
|
if (new_params.GetTarget() == SurfaceTarget::Texture1D ||
|
||||||
|
new_params.GetTarget() == SurfaceTarget::Texture1DArray ||
|
||||||
|
new_params.GetTarget() == SurfaceTarget::Texture3D) {
|
||||||
|
// Non-2D textures are not handled at the moment in this fast path.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CachedSurface* const new_surface{GetUncachedSurface(new_params)};
|
||||||
|
// TODO(Rodrigo): Move this down
|
||||||
|
Register(new_surface, cpu_addr, host_ptr);
|
||||||
|
|
||||||
|
// TODO(Rodrigo): Find a way to avoid heap allocations here.
|
||||||
|
std::vector<CachedSurfaceView*> views;
|
||||||
|
views.reserve(overlaps.size());
|
||||||
|
for (const auto& overlap : overlaps) {
|
||||||
|
const auto view{
|
||||||
|
new_surface->TryGetView(overlap->GetCpuAddr(), overlap->GetSurfaceParams())};
|
||||||
|
if (!view) {
|
||||||
|
// TODO(Rodrigo): Remove this
|
||||||
|
Unregister(new_surface);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
views.push_back(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(Rodrigo): It's possible that these method leaves some unloaded textures if the data has
|
||||||
|
// been uploaded to guest memory but not used as a surface previously.
|
||||||
|
for (std::size_t i = 0; i < overlaps.size(); ++i) {
|
||||||
|
const auto& overlap{overlaps[i]};
|
||||||
|
const auto& view{views[i]};
|
||||||
|
for (u32 overlap_level = 0; overlap_level < view->GetNumLevels(); ++overlap_level) {
|
||||||
|
const u32 super_level{view->GetBaseLevel() + overlap_level};
|
||||||
|
glCopyImageSubData(overlap->GetTexture(), overlap->GetTarget(), overlap_level, 0, 0, 0,
|
||||||
|
new_surface->GetTexture(), new_surface->GetTarget(), super_level, 0,
|
||||||
|
0, view->GetBaseLayer(), view->GetWidth(), view->GetHeight(),
|
||||||
|
view->GetNumLayers());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new_surface->MarkAsModified(true);
|
||||||
|
|
||||||
|
// TODO(Rodrigo): Add an entry to directly get the superview
|
||||||
|
return new_surface->GetView(cpu_addr, new_params);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<CachedSurface> TextureCacheOpenGL::CreateSurface(const SurfaceParams& params) {
|
std::unique_ptr<CachedSurface> TextureCacheOpenGL::CreateSurface(const SurfaceParams& params) {
|
||||||
return std::make_unique<CachedSurface>(params);
|
return std::make_unique<CachedSurface>(params);
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,34 @@ public:
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 GetWidth() const {
|
||||||
|
return params.GetMipWidth(GetBaseLevel());
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GetHeight() const {
|
||||||
|
return params.GetMipHeight(GetBaseLevel());
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GetDepth() const {
|
||||||
|
return params.GetMipDepth(GetBaseLevel());
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GetBaseLayer() const {
|
||||||
|
return key.base_layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GetNumLayers() const {
|
||||||
|
return key.num_layers;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GetBaseLevel() const {
|
||||||
|
return key.base_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GetNumLevels() const {
|
||||||
|
return key.num_levels;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct TextureView {
|
struct TextureView {
|
||||||
OGLTexture texture;
|
OGLTexture texture;
|
||||||
|
@ -128,7 +156,8 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CachedSurfaceView* TryFastGetSurfaceView(VAddr cpu_addr, u8* host_ptr,
|
CachedSurfaceView* TryFastGetSurfaceView(VAddr cpu_addr, u8* host_ptr,
|
||||||
const SurfaceParams& params, bool preserve_contents,
|
const SurfaceParams& new_params,
|
||||||
|
bool preserve_contents,
|
||||||
const std::vector<CachedSurface*>& overlaps);
|
const std::vector<CachedSurface*>& overlaps);
|
||||||
|
|
||||||
std::unique_ptr<CachedSurface> CreateSurface(const SurfaceParams& params);
|
std::unique_ptr<CachedSurface> CreateSurface(const SurfaceParams& params);
|
||||||
|
@ -136,6 +165,9 @@ protected:
|
||||||
private:
|
private:
|
||||||
CachedSurfaceView* SurfaceCopy(VAddr cpu_addr, u8* host_ptr, const SurfaceParams& new_params,
|
CachedSurfaceView* SurfaceCopy(VAddr cpu_addr, u8* host_ptr, const SurfaceParams& new_params,
|
||||||
CachedSurface* old_surface, const SurfaceParams& old_params);
|
CachedSurface* old_surface, const SurfaceParams& old_params);
|
||||||
|
|
||||||
|
CachedSurfaceView* TryCopyAsViews(VAddr cpu_addr, u8* host_ptr, const SurfaceParams& new_params,
|
||||||
|
const std::vector<CachedSurface*>& overlaps);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace OpenGL
|
} // namespace OpenGL
|
||||||
|
|
|
@ -316,7 +316,7 @@ std::size_t SurfaceParams::GetInnerMemorySize(bool as_host_size, bool layer_only
|
||||||
size += GetInnerMipmapMemorySize(level, as_host_size, layer_only, uncompressed);
|
size += GetInnerMipmapMemorySize(level, as_host_size, layer_only, uncompressed);
|
||||||
}
|
}
|
||||||
if (is_tiled && !as_host_size) {
|
if (is_tiled && !as_host_size) {
|
||||||
//size = Common::AlignUp(size, Tegra::Texture::GetGOBSize() * block_height * block_depth);
|
size = Common::AlignUp(size, Tegra::Texture::GetGOBSize() * block_height * block_depth);
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue