gl_texture_cache: Add copy from multiple overlaps into a single surface
This commit is contained in:
		| @@ -518,16 +518,14 @@ TextureCacheOpenGL::TextureCacheOpenGL(Core::System& system, | ||||
| TextureCacheOpenGL::~TextureCacheOpenGL() = default; | ||||
|  | ||||
| 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) { | ||||
|     if (overlaps.size() > 1) { | ||||
|         return nullptr; | ||||
|         return TryCopyAsViews(cpu_addr, host_ptr, new_params, overlaps); | ||||
|     } | ||||
|  | ||||
|     const auto& old_surface{overlaps[0]}; | ||||
|     const auto& old_params{old_surface->GetSurfaceParams()}; | ||||
|     const auto& new_params{params}; | ||||
|  | ||||
|     if (old_params.GetTarget() == new_params.GetTarget() && | ||||
|         old_params.GetDepth() == new_params.GetDepth() && old_params.GetDepth() == 1 && | ||||
|         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); | ||||
| } | ||||
|  | ||||
| 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) { | ||||
|     return std::make_unique<CachedSurface>(params); | ||||
| } | ||||
|   | ||||
| @@ -90,6 +90,34 @@ public: | ||||
|         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: | ||||
|     struct TextureView { | ||||
|         OGLTexture texture; | ||||
| @@ -128,7 +156,8 @@ public: | ||||
|  | ||||
| protected: | ||||
|     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); | ||||
|  | ||||
|     std::unique_ptr<CachedSurface> CreateSurface(const SurfaceParams& params); | ||||
| @@ -136,6 +165,9 @@ protected: | ||||
| private: | ||||
|     CachedSurfaceView* SurfaceCopy(VAddr cpu_addr, u8* host_ptr, const SurfaceParams& new_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 | ||||
|   | ||||
| @@ -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); | ||||
|     } | ||||
|     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; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 ReinUsesLisp
					ReinUsesLisp