Просмотр исходного кода

gl_texture_cache: Add fast copy path

ReinUsesLisp 7 лет назад
Родитель
Сommit
fb94871791

+ 48 - 3
src/video_core/renderer_opengl/gl_texture_cache.cpp

@@ -177,9 +177,9 @@ void ApplyTextureDefaults(const SurfaceParams& params, GLuint texture) {
     }
     }
 }
 }
 
 
-OGLTexture CreateTexture(const SurfaceParams& params, GLenum internal_format) {
+OGLTexture CreateTexture(const SurfaceParams& params, GLenum target, GLenum internal_format) {
     OGLTexture texture;
     OGLTexture texture;
-    texture.Create(GetTextureTarget(params));
+    texture.Create(target);
 
 
     switch (params.GetTarget()) {
     switch (params.GetTarget()) {
     case SurfaceTarget::Texture1D:
     case SurfaceTarget::Texture1D:
@@ -241,7 +241,8 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
     format = tuple.format;
     format = tuple.format;
     type = tuple.type;
     type = tuple.type;
     is_compressed = tuple.compressed;
     is_compressed = tuple.compressed;
-    texture = CreateTexture(params, internal_format);
+    target = GetTextureTarget(params);
+    texture = CreateTexture(params, target, internal_format);
     staging_buffer.resize(params.GetHostSizeInBytes());
     staging_buffer.resize(params.GetHostSizeInBytes());
 }
 }
 
 
@@ -504,9 +505,53 @@ 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& params, bool preserve_contents,
     const std::vector<CachedSurface*>& overlaps) {
     const std::vector<CachedSurface*>& overlaps) {
+    if (overlaps.size() > 1) {
+        return nullptr;
+    }
+
+    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() &&
+        old_params.GetPixelFormat() == new_params.GetPixelFormat()) {
+        return SurfaceCopy(cpu_addr, host_ptr, new_params, old_surface, old_params);
+    }
+
     return nullptr;
     return nullptr;
 }
 }
 
 
+CachedSurfaceView* TextureCacheOpenGL::SurfaceCopy(VAddr cpu_addr, u8* host_ptr,
+                                                   const SurfaceParams& new_params,
+                                                   CachedSurface* old_surface,
+                                                   const SurfaceParams& old_params) {
+    CachedSurface* const new_surface{GetUncachedSurface(new_params)};
+    Register(new_surface, cpu_addr, host_ptr);
+
+    const u32 min_width{
+        std::max(old_params.GetDefaultBlockWidth(), new_params.GetDefaultBlockWidth())};
+    const u32 min_height{
+        std::max(old_params.GetDefaultBlockHeight(), new_params.GetDefaultBlockHeight())};
+    for (u32 level = 0; level < old_params.GetNumLevels(); ++level) {
+        const u32 width{std::min(old_params.GetMipWidth(level), new_params.GetMipWidth(level))};
+        const u32 height{std::min(old_params.GetMipHeight(level), new_params.GetMipHeight(level))};
+        if (width < min_width || height < min_height) {
+            // Avoid copies that are too small to be handled in OpenGL
+            break;
+        }
+        glCopyImageSubData(old_surface->GetTexture(), old_surface->GetTarget(), level, 0, 0, 0,
+                           new_surface->GetTexture(), new_surface->GetTarget(), level, 0, 0, 0,
+                           width, height, 1);
+    }
+
+    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);
 }
 }

+ 9 - 0
src/video_core/renderer_opengl/gl_texture_cache.h

@@ -38,6 +38,10 @@ public:
 
 
     void LoadBuffer();
     void LoadBuffer();
 
 
+    GLenum GetTarget() const {
+        return target;
+    }
+
     GLuint GetTexture() const {
     GLuint GetTexture() const {
         return texture.handle;
         return texture.handle;
     }
     }
@@ -56,6 +60,7 @@ private:
     GLenum format{};
     GLenum format{};
     GLenum type{};
     GLenum type{};
     bool is_compressed{};
     bool is_compressed{};
+    GLenum target{};
 
 
     OGLTexture texture;
     OGLTexture texture;
 
 
@@ -126,6 +131,10 @@ protected:
                                              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);
+
+private:
+    CachedSurfaceView* SurfaceCopy(VAddr cpu_addr, u8* host_ptr, const SurfaceParams& new_params,
+                                   CachedSurface* old_surface, const SurfaceParams& old_params);
 };
 };
 
 
 } // namespace OpenGL
 } // namespace OpenGL

+ 2 - 2
src/video_core/texture_cache.cpp

@@ -160,7 +160,7 @@ u32 SurfaceParams::GetMipBlockHeight(u32 level) const {
     // Auto block resizing algorithm from:
     // Auto block resizing algorithm from:
     // https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nv50/nv50_miptree.c
     // https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nv50/nv50_miptree.c
     if (level == 0) {
     if (level == 0) {
-        return block_height;
+        return this->block_height;
     }
     }
     const u32 height{GetMipHeight(level)};
     const u32 height{GetMipHeight(level)};
     const u32 default_block_height{GetDefaultBlockHeight()};
     const u32 default_block_height{GetDefaultBlockHeight()};
@@ -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;
 }
 }

+ 1 - 2
src/video_core/textures/decoders.cpp

@@ -359,8 +359,7 @@ std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height
         const u32 aligned_width = Common::AlignUp(width * bytes_per_pixel, gob_size_x);
         const u32 aligned_width = Common::AlignUp(width * bytes_per_pixel, gob_size_x);
         const u32 aligned_height = Common::AlignUp(height, gob_size_y * block_height);
         const u32 aligned_height = Common::AlignUp(height, gob_size_y * block_height);
         const u32 aligned_depth = Common::AlignUp(depth, gob_size_z * block_depth);
         const u32 aligned_depth = Common::AlignUp(depth, gob_size_z * block_depth);
-        const u32 size = aligned_width * aligned_height * aligned_depth;
-        return size;
+        return aligned_width * aligned_height * aligned_depth;
     } else {
     } else {
         return width * height * depth * bytes_per_pixel;
         return width * height * depth * bytes_per_pixel;
     }
     }