texture_cache: Move staging buffer into a generic implementation
This commit is contained in:
		| @@ -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()) { | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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; | ||||
|     void LoadBuffer(); | ||||
|  | ||||
|     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 {}; | ||||
|         } | ||||
|  | ||||
|         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; | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 ReinUsesLisp
					ReinUsesLisp