diff options
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.cpp | 114 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.h | 7 | ||||
| -rw-r--r-- | src/video_core/texture_cache.cpp | 110 | ||||
| -rw-r--r-- | src/video_core/texture_cache.h | 161 | 
4 files changed, 211 insertions, 181 deletions
| diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 362f4019c..3e2a1f53c 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -15,7 +15,6 @@  namespace OpenGL { -using Tegra::Texture::ConvertFromGuestToHost;  using Tegra::Texture::SwizzleSource;  using VideoCore::MortonSwizzleMode; @@ -207,32 +206,6 @@ OGLTexture CreateTexture(const SurfaceParams& params, GLenum target, GLenum inte      return texture;  } -void SwizzleFunc(MortonSwizzleMode mode, u8* memory, const SurfaceParams& params, u8* buffer, -                 u32 level) { -    const u32 width{params.GetMipWidth(level)}; -    const u32 height{params.GetMipHeight(level)}; -    const u32 block_height{params.GetMipBlockHeight(level)}; -    const u32 block_depth{params.GetMipBlockDepth(level)}; - -    std::size_t guest_offset{params.GetGuestMipmapLevelOffset(level)}; -    if (params.IsLayered()) { -        std::size_t host_offset{0}; -        const std::size_t guest_stride = params.GetGuestLayerSize(); -        const std::size_t host_stride = params.GetHostLayerSize(level); -        for (u32 layer = 0; layer < params.GetNumLayers(); layer++) { -            MortonSwizzle(mode, params.GetPixelFormat(), width, block_height, height, block_depth, -                          1, params.GetTileWidthSpacing(), buffer + host_offset, -                          memory + guest_offset); -            guest_offset += guest_stride; -            host_offset += host_stride; -        } -    } else { -        MortonSwizzle(mode, params.GetPixelFormat(), width, block_height, height, block_depth, -                      params.GetMipDepth(level), params.GetTileWidthSpacing(), buffer, -                      memory + guest_offset); -    } -} -  } // Anonymous namespace  CachedSurface::CachedSurface(TextureCacheOpenGL& texture_cache, const SurfaceParams& params) @@ -245,54 +218,11 @@ CachedSurface::CachedSurface(TextureCacheOpenGL& texture_cache, const SurfacePar      is_compressed = tuple.compressed;      target = GetTextureTarget(params);      texture = CreateTexture(params, target, internal_format); -    staging_buffer.resize(params.GetHostSizeInBytes());  }  CachedSurface::~CachedSurface() = default; -void CachedSurface::LoadBuffer() { -    if (params.IsTiled()) { -        ASSERT_MSG(params.GetBlockWidth() == 1, "Block width is defined as {} on texture target {}", -                   params.GetBlockWidth(), static_cast<u32>(params.GetTarget())); -        for (u32 level = 0; level < params.GetNumLevels(); ++level) { -            u8* const buffer{staging_buffer.data() + params.GetHostMipmapLevelOffset(level)}; -            SwizzleFunc(MortonSwizzleMode::MortonToLinear, GetHostPtr(), params, buffer, level); -        } -    } else { -        ASSERT_MSG(params.GetNumLevels() == 1, "Linear mipmap loading is not implemented"); -        const u32 bpp{GetFormatBpp(params.GetPixelFormat()) / CHAR_BIT}; -        const u32 block_width{VideoCore::Surface::GetDefaultBlockWidth(params.GetPixelFormat())}; -        const u32 block_height{VideoCore::Surface::GetDefaultBlockHeight(params.GetPixelFormat())}; -        const u32 width{(params.GetWidth() + block_width - 1) / block_width}; -        const u32 height{(params.GetHeight() + block_height - 1) / block_height}; -        const u32 copy_size{width * bpp}; -        if (params.GetPitch() == copy_size) { -            std::memcpy(staging_buffer.data(), GetHostPtr(), params.GetHostSizeInBytes()); -        } else { -            const u8* start{GetHostPtr()}; -            u8* write_to{staging_buffer.data()}; -            for (u32 h = height; h > 0; --h) { -                std::memcpy(write_to, start, copy_size); -                start += params.GetPitch(); -                write_to += copy_size; -            } -        } -    } - -    for (u32 level = 0; level < params.GetNumLevels(); ++level) { -        ConvertFromGuestToHost(staging_buffer.data() + params.GetHostMipmapLevelOffset(level), -                               params.GetPixelFormat(), params.GetMipWidth(level), -                               params.GetMipHeight(level), params.GetMipDepth(level), true, true); -    } -} - -void CachedSurface::FlushBufferImpl() { -    LOG_CRITICAL(Render_OpenGL, "Flushing"); - -    if (!IsModified()) { -        return; -    } - +void CachedSurface::DownloadTextureImpl() {      // TODO(Rodrigo): Optimize alignment      glPixelStorei(GL_PACK_ALIGNMENT, 1);      SCOPE_EXIT({ glPixelStorei(GL_PACK_ROW_LENGTH, 0); }); @@ -300,60 +230,30 @@ void CachedSurface::FlushBufferImpl() {      for (u32 level = 0; level < params.GetNumLevels(); ++level) {          glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(params.GetMipWidth(level)));          if (is_compressed) { -            glGetCompressedTextureImage( -                texture.handle, level, static_cast<GLsizei>(params.GetHostMipmapSize(level)), -                staging_buffer.data() + params.GetHostMipmapLevelOffset(level)); +            glGetCompressedTextureImage(texture.handle, level, +                                        static_cast<GLsizei>(params.GetHostMipmapSize(level)), +                                        GetStagingBufferLevelData(level));          } else {              glGetTextureImage(texture.handle, level, format, type,                                static_cast<GLsizei>(params.GetHostMipmapSize(level)), -                              staging_buffer.data() + params.GetHostMipmapLevelOffset(level)); +                              GetStagingBufferLevelData(level));          }      } - -    if (params.IsTiled()) { -        ASSERT_MSG(params.GetBlockWidth() == 1, "Block width is defined as {}", -                   params.GetBlockWidth()); -        for (u32 level = 0; level < params.GetNumLevels(); ++level) { -            u8* const buffer = staging_buffer.data() + params.GetHostMipmapLevelOffset(level); -            SwizzleFunc(MortonSwizzleMode::LinearToMorton, GetHostPtr(), params, buffer, level); -        } -    } else { -        UNIMPLEMENTED(); -        /* -        ASSERT(params.GetTarget() == SurfaceTarget::Texture2D); -        ASSERT(params.GetNumLevels() == 1); - -        const u32 bpp{params.GetFormatBpp() / 8}; -        const u32 copy_size{params.GetWidth() * bpp}; -        if (params.GetPitch() == copy_size) { -            std::memcpy(host_ptr, staging_buffer.data(), GetSizeInBytes()); -        } else { -            u8* start{host_ptr}; -            const u8* read_to{staging_buffer.data()}; -            for (u32 h = params.GetHeight(); h > 0; --h) { -                std::memcpy(start, read_to, copy_size); -                start += params.GetPitch(); -                read_to += copy_size; -            } -        } -        */ -    }  }  void CachedSurface::UploadTextureImpl() { +    SCOPE_EXIT({ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); });      for (u32 level = 0; level < params.GetNumLevels(); ++level) {          UploadTextureMipmap(level);      }  }  void CachedSurface::UploadTextureMipmap(u32 level) { -    u8* buffer{staging_buffer.data() + params.GetHostMipmapLevelOffset(level)}; -      // TODO(Rodrigo): Optimize alignment      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);      glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.GetMipWidth(level))); -    SCOPE_EXIT({ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); }); +    u8* buffer{GetStagingBufferLevelData(level)};      if (is_compressed) {          const auto image_size{static_cast<GLsizei>(params.GetHostMipmapSize(level))};          switch (params.GetTarget()) { diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index e6448c6f8..0a69be233 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h @@ -39,8 +39,6 @@ public:      explicit CachedSurface(TextureCacheOpenGL& texture_cache, const SurfaceParams& params);      ~CachedSurface(); -    void LoadBuffer(); -      GLenum GetTarget() const {          return target;      } @@ -54,9 +52,8 @@ protected:      std::unique_ptr<CachedSurfaceView> CreateView(const ViewKey& view_key); -    void FlushBufferImpl(); -      void UploadTextureImpl(); +    void DownloadTextureImpl();  private:      void UploadTextureMipmap(u32 level); @@ -68,8 +65,6 @@ private:      GLenum target{};      OGLTexture texture; - -    std::vector<u8> staging_buffer;  };  class CachedSurfaceView final { diff --git a/src/video_core/texture_cache.cpp b/src/video_core/texture_cache.cpp index b78a7d951..146e8ed9b 100644 --- a/src/video_core/texture_cache.cpp +++ b/src/video_core/texture_cache.cpp @@ -7,14 +7,16 @@  #include "common/cityhash.h"  #include "common/common_types.h"  #include "core/core.h" +#include "video_core/morton.h"  #include "video_core/surface.h"  #include "video_core/texture_cache.h" +#include "video_core/textures/convert.h"  #include "video_core/textures/decoders.h"  #include "video_core/textures/texture.h"  namespace VideoCommon { -using VideoCore::Surface::SurfaceTarget; +using VideoCore::MortonSwizzleMode;  using VideoCore::Surface::ComponentTypeFromDepthFormat;  using VideoCore::Surface::ComponentTypeFromRenderTarget; @@ -22,12 +24,118 @@ using VideoCore::Surface::ComponentTypeFromTexture;  using VideoCore::Surface::PixelFormatFromDepthFormat;  using VideoCore::Surface::PixelFormatFromRenderTargetFormat;  using VideoCore::Surface::PixelFormatFromTextureFormat; +using VideoCore::Surface::SurfaceTarget;  using VideoCore::Surface::SurfaceTargetFromTextureType; +using Tegra::Texture::ConvertFromGuestToHost; + +namespace { +  constexpr u32 GetMipmapSize(bool uncompressed, u32 mip_size, u32 tile) {      return uncompressed ? mip_size : std::max(1U, (mip_size + tile - 1) / tile);  } +void SwizzleFunc(MortonSwizzleMode mode, u8* memory, const SurfaceParams& params, u8* buffer, +                 u32 level) { +    const u32 width{params.GetMipWidth(level)}; +    const u32 height{params.GetMipHeight(level)}; +    const u32 block_height{params.GetMipBlockHeight(level)}; +    const u32 block_depth{params.GetMipBlockDepth(level)}; + +    std::size_t guest_offset{params.GetGuestMipmapLevelOffset(level)}; +    if (params.IsLayered()) { +        std::size_t host_offset{0}; +        const std::size_t guest_stride = params.GetGuestLayerSize(); +        const std::size_t host_stride = params.GetHostLayerSize(level); +        for (u32 layer = 0; layer < params.GetNumLayers(); layer++) { +            MortonSwizzle(mode, params.GetPixelFormat(), width, block_height, height, block_depth, +                          1, params.GetTileWidthSpacing(), buffer + host_offset, +                          memory + guest_offset); +            guest_offset += guest_stride; +            host_offset += host_stride; +        } +    } else { +        MortonSwizzle(mode, params.GetPixelFormat(), width, block_height, height, block_depth, +                      params.GetMipDepth(level), params.GetTileWidthSpacing(), buffer, +                      memory + guest_offset); +    } +} + +} // Anonymous namespace + +SurfaceBaseImpl::SurfaceBaseImpl(const SurfaceParams& params) : params{params} { +    staging_buffer.resize(params.GetHostSizeInBytes()); +} + +SurfaceBaseImpl::~SurfaceBaseImpl() = default; + +void SurfaceBaseImpl::LoadBuffer() { +    if (params.IsTiled()) { +        ASSERT_MSG(params.GetBlockWidth() == 1, "Block width is defined as {} on texture target {}", +                   params.GetBlockWidth(), static_cast<u32>(params.GetTarget())); +        for (u32 level = 0; level < params.GetNumLevels(); ++level) { +            u8* const buffer{GetStagingBufferLevelData(level)}; +            SwizzleFunc(MortonSwizzleMode::MortonToLinear, host_ptr, params, buffer, level); +        } +    } else { +        ASSERT_MSG(params.GetNumLevels() == 1, "Linear mipmap loading is not implemented"); +        const u32 bpp{GetFormatBpp(params.GetPixelFormat()) / CHAR_BIT}; +        const u32 block_width{params.GetDefaultBlockWidth()}; +        const u32 block_height{params.GetDefaultBlockHeight()}; +        const u32 width{(params.GetWidth() + block_width - 1) / block_width}; +        const u32 height{(params.GetHeight() + block_height - 1) / block_height}; +        const u32 copy_size{width * bpp}; +        if (params.GetPitch() == copy_size) { +            std::memcpy(staging_buffer.data(), host_ptr, params.GetHostSizeInBytes()); +        } else { +            const u8* start{host_ptr}; +            u8* write_to{staging_buffer.data()}; +            for (u32 h = height; h > 0; --h) { +                std::memcpy(write_to, start, copy_size); +                start += params.GetPitch(); +                write_to += copy_size; +            } +        } +    } + +    for (u32 level = 0; level < params.GetNumLevels(); ++level) { +        ConvertFromGuestToHost(GetStagingBufferLevelData(level), params.GetPixelFormat(), +                               params.GetMipWidth(level), params.GetMipHeight(level), +                               params.GetMipDepth(level), true, true); +    } +} + +void SurfaceBaseImpl::FlushBuffer() { +    if (params.IsTiled()) { +        ASSERT_MSG(params.GetBlockWidth() == 1, "Block width is defined as {}", +                   params.GetBlockWidth()); +        for (u32 level = 0; level < params.GetNumLevels(); ++level) { +            u8* const buffer = GetStagingBufferLevelData(level); +            SwizzleFunc(MortonSwizzleMode::LinearToMorton, GetHostPtr(), params, buffer, level); +        } +    } else { +        UNIMPLEMENTED(); +        /* +        ASSERT(params.GetTarget() == SurfaceTarget::Texture2D); +        ASSERT(params.GetNumLevels() == 1); + +        const u32 bpp{params.GetFormatBpp() / 8}; +        const u32 copy_size{params.GetWidth() * bpp}; +        if (params.GetPitch() == copy_size) { +            std::memcpy(host_ptr, staging_buffer.data(), GetSizeInBytes()); +        } else { +            u8* start{host_ptr}; +            const u8* read_to{staging_buffer.data()}; +            for (u32 h = params.GetHeight(); h > 0; --h) { +                std::memcpy(start, read_to, copy_size); +                start += params.GetPitch(); +                read_to += copy_size; +            } +        } +        */ +    } +} +  SurfaceParams SurfaceParams::CreateForTexture(Core::System& system,                                                const Tegra::Texture::FullTextureInfo& config) {      SurfaceParams params; diff --git a/src/video_core/texture_cache.h b/src/video_core/texture_cache.h index f22e8e776..90c72cb15 100644 --- a/src/video_core/texture_cache.h +++ b/src/video_core/texture_cache.h @@ -273,37 +273,11 @@ struct hash<VideoCommon::ViewKey> {  namespace VideoCommon { -template <typename TTextureCache, typename TView, typename TExecutionContext> -class SurfaceBase { -    static_assert(std::is_trivially_copyable_v<TExecutionContext>); - +class SurfaceBaseImpl {  public: -    virtual void LoadBuffer() = 0; - -    virtual TExecutionContext FlushBuffer(TExecutionContext exctx) = 0; - -    virtual TExecutionContext UploadTexture(TExecutionContext exctx) = 0; - -    TView* TryGetView(GPUVAddr view_addr, const SurfaceParams& view_params) { -        if (view_addr < gpu_addr || !params.IsFamiliar(view_params)) { -            // It can't be a view if it's in a prior address. -            return {}; -        } - -        const auto relative_offset{static_cast<u64>(view_addr - gpu_addr)}; -        const auto it{view_offset_map.find(relative_offset)}; -        if (it == view_offset_map.end()) { -            // Couldn't find an aligned view. -            return {}; -        } -        const auto [layer, level] = it->second; - -        if (!params.IsViewValid(view_params, layer, level)) { -            return {}; -        } +    void LoadBuffer(); -        return GetView(layer, view_params.GetNumLayers(), level, view_params.GetNumLevels()); -    } +    void FlushBuffer();      GPUVAddr GetGpuAddr() const {          ASSERT(is_registered); @@ -325,27 +299,10 @@ public:          return cache_addr;      } -    std::size_t GetSizeInBytes() const { -        return params.GetGuestSizeInBytes(); -    } - -    void MarkAsModified(bool is_modified_) { -        is_modified = is_modified_; -        if (is_modified_) { -            modification_tick = texture_cache.Tick(); -        } -    } -      const SurfaceParams& GetSurfaceParams() const {          return params;      } -    TView* GetView(GPUVAddr view_addr, const SurfaceParams& view_params) { -        TView* view{TryGetView(view_addr, view_params)}; -        ASSERT(view != nullptr); -        return view; -    } -      void Register(GPUVAddr gpu_addr_, VAddr cpu_addr_, u8* host_ptr_) {          ASSERT(!is_registered);          is_registered = true; @@ -361,30 +318,95 @@ public:          is_registered = false;      } -    u64 GetModificationTick() const { -        return modification_tick; -    } -      bool IsRegistered() const {          return is_registered;      } -protected: -    explicit SurfaceBase(TTextureCache& texture_cache, const SurfaceParams& params) -        : params{params}, texture_cache{texture_cache}, view_offset_map{ -                                                            params.CreateViewOffsetMap()} {} +    std::size_t GetSizeInBytes() const { +        return params.GetGuestSizeInBytes(); +    } -    ~SurfaceBase() = default; +    u8* GetStagingBufferLevelData(u32 level) { +        return staging_buffer.data() + params.GetHostMipmapLevelOffset(level); +    } + +protected: +    explicit SurfaceBaseImpl(const SurfaceParams& params); +    ~SurfaceBaseImpl(); // non-virtual is intended      virtual void DecorateSurfaceName() = 0; -    virtual std::unique_ptr<TView> CreateView(const ViewKey& view_key) = 0; +    const SurfaceParams params; + +private: +    GPUVAddr gpu_addr{}; +    VAddr cpu_addr{}; +    u8* host_ptr{}; +    CacheAddr cache_addr{}; +    bool is_registered{}; + +    std::vector<u8> staging_buffer; +}; + +template <typename TTextureCache, typename TView, typename TExecutionContext> +class SurfaceBase : public SurfaceBaseImpl { +    static_assert(std::is_trivially_copyable_v<TExecutionContext>); + +public: +    virtual TExecutionContext UploadTexture(TExecutionContext exctx) = 0; + +    virtual TExecutionContext DownloadTexture(TExecutionContext exctx) = 0; + +    TView* TryGetView(GPUVAddr view_addr, const SurfaceParams& view_params) { +        if (view_addr < GetGpuAddr() || !params.IsFamiliar(view_params)) { +            // It can't be a view if it's in a prior address. +            return {}; +        } + +        const auto relative_offset{static_cast<u64>(view_addr - GetGpuAddr())}; +        const auto it{view_offset_map.find(relative_offset)}; +        if (it == view_offset_map.end()) { +            // Couldn't find an aligned view. +            return {}; +        } +        const auto [layer, level] = it->second; + +        if (!params.IsViewValid(view_params, layer, level)) { +            return {}; +        } + +        return GetView(layer, view_params.GetNumLayers(), level, view_params.GetNumLevels()); +    } + +    void MarkAsModified(bool is_modified_) { +        is_modified = is_modified_; +        if (is_modified_) { +            modification_tick = texture_cache.Tick(); +        } +    } + +    TView* GetView(GPUVAddr view_addr, const SurfaceParams& view_params) { +        TView* view{TryGetView(view_addr, view_params)}; +        ASSERT(view != nullptr); +        return view; +    }      bool IsModified() const {          return is_modified;      } -    const SurfaceParams params; +    u64 GetModificationTick() const { +        return modification_tick; +    } + +protected: +    explicit SurfaceBase(TTextureCache& texture_cache, const SurfaceParams& params) +        : SurfaceBaseImpl{params}, texture_cache{texture_cache}, +          view_offset_map{params.CreateViewOffsetMap()} {} + +    ~SurfaceBase() = default; + +    virtual std::unique_ptr<TView> CreateView(const ViewKey& view_key) = 0;  private:      TView* GetView(u32 base_layer, u32 num_layers, u32 base_level, u32 num_levels) { @@ -400,13 +422,8 @@ private:      TTextureCache& texture_cache;      const std::map<u64, std::pair<u32, u32>> view_offset_map; -    GPUVAddr gpu_addr{}; -    VAddr cpu_addr{}; -    u8* host_ptr{}; -    CacheAddr cache_addr{}; -    u64 modification_tick{};      bool is_modified{}; -    bool is_registered{}; +    u64 modification_tick{};      std::unordered_map<ViewKey, std::unique_ptr<TView>> views;  }; @@ -560,7 +577,7 @@ private:              if (!fast_view) {                  // Flush even when we don't care about the contents, to preserve memory not                  // written by the new surface. -                exctx = surface->FlushBuffer(exctx); +                exctx = FlushSurface(exctx, surface);              }              Unregister(surface);          } @@ -590,6 +607,16 @@ private:          return exctx;      } +    TExecutionContext FlushSurface(TExecutionContext exctx, +                                   const std::shared_ptr<TSurface>& surface) { +        if (!surface->IsModified()) { +            return exctx; +        } +        exctx = surface->DownloadTexture(exctx); +        surface->FlushBuffer(); +        return exctx; +    } +      std::vector<std::shared_ptr<TSurface>> GetSurfacesInRegion(CacheAddr cache_addr,                                                                 std::size_t size) const {          if (size == 0) { @@ -701,8 +728,8 @@ private:  template <typename TTextureCache, typename TView>  class SurfaceBaseContextless : public SurfaceBase<TTextureCache, TView, DummyExecutionContext> {  public: -    DummyExecutionContext FlushBuffer(DummyExecutionContext) { -        FlushBufferImpl(); +    DummyExecutionContext DownloadTexture(DummyExecutionContext) { +        DownloadTextureImpl();          return {};      } @@ -715,7 +742,7 @@ protected:      explicit SurfaceBaseContextless(TTextureCache& texture_cache, const SurfaceParams& params)          : SurfaceBase<TTextureCache, TView, DummyExecutionContext>{texture_cache, params} {} -    virtual void FlushBufferImpl() = 0; +    virtual void DownloadTextureImpl() = 0;      virtual void UploadTextureImpl() = 0;  }; | 
