texture_cache: Flush 3D textures in the order they are drawn
This commit is contained in:
		| @@ -235,8 +235,9 @@ void SwizzleFunc(MortonSwizzleMode mode, u8* memory, const SurfaceParams& params | ||||
|  | ||||
| } // Anonymous namespace | ||||
|  | ||||
| CachedSurface::CachedSurface(const SurfaceParams& params) | ||||
|     : VideoCommon::SurfaceBaseContextless<CachedSurfaceView>{params} { | ||||
| CachedSurface::CachedSurface(TextureCacheOpenGL& texture_cache, const SurfaceParams& params) | ||||
|     : VideoCommon::SurfaceBaseContextless<TextureCacheOpenGL, CachedSurfaceView>{texture_cache, | ||||
|                                                                                  params} { | ||||
|     const auto& tuple{GetFormatTuple(params.GetPixelFormat(), params.GetComponentType())}; | ||||
|     internal_format = tuple.internal_format; | ||||
|     format = tuple.format; | ||||
|   | ||||
| @@ -26,15 +26,17 @@ using VideoCore::Surface::SurfaceType; | ||||
|  | ||||
| class CachedSurfaceView; | ||||
| class CachedSurface; | ||||
| class TextureCacheOpenGL; | ||||
|  | ||||
| using Surface = std::shared_ptr<CachedSurface>; | ||||
| using TextureCacheBase = VideoCommon::TextureCacheContextless<CachedSurface, CachedSurfaceView>; | ||||
|  | ||||
| class CachedSurface final : public VideoCommon::SurfaceBaseContextless<CachedSurfaceView> { | ||||
| class CachedSurface final | ||||
|     : public VideoCommon::SurfaceBaseContextless<TextureCacheOpenGL, CachedSurfaceView> { | ||||
|     friend CachedSurfaceView; | ||||
|  | ||||
| public: | ||||
|     explicit CachedSurface(const SurfaceParams& params); | ||||
|     explicit CachedSurface(TextureCacheOpenGL& texture_cache, const SurfaceParams& params); | ||||
|     ~CachedSurface(); | ||||
|  | ||||
|     void LoadBuffer(); | ||||
|   | ||||
| @@ -460,7 +460,6 @@ static void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum | ||||
|     switch (severity) { | ||||
|     case GL_DEBUG_SEVERITY_HIGH: | ||||
|         LOG_CRITICAL(Render_OpenGL, format, str_source, str_type, id, message); | ||||
|         __debugbreak(); | ||||
|         break; | ||||
|     case GL_DEBUG_SEVERITY_MEDIUM: | ||||
|         LOG_WARNING(Render_OpenGL, format, str_source, str_type, id, message); | ||||
|   | ||||
| @@ -154,8 +154,8 @@ bool SurfaceParams::IsLayered() const { | ||||
|     switch (target) { | ||||
|     case SurfaceTarget::Texture1DArray: | ||||
|     case SurfaceTarget::Texture2DArray: | ||||
|     case SurfaceTarget::TextureCubeArray: | ||||
|     case SurfaceTarget::TextureCubemap: | ||||
|     case SurfaceTarget::TextureCubeArray: | ||||
|         return true; | ||||
|     default: | ||||
|         return false; | ||||
| @@ -192,9 +192,11 @@ u32 SurfaceParams::GetMipBlockDepth(u32 level) const { | ||||
|     while (block_depth > 1 && depth * 2 <= block_depth) { | ||||
|         block_depth >>= 1; | ||||
|     } | ||||
|  | ||||
|     if (block_depth == 32 && GetMipBlockHeight(level) >= 4) { | ||||
|         return 16; | ||||
|     } | ||||
|  | ||||
|     return block_depth; | ||||
| } | ||||
|  | ||||
| @@ -227,7 +229,7 @@ std::size_t SurfaceParams::GetLayerSize(bool as_host_size, bool uncompressed) co | ||||
|     for (u32 level = 0; level < num_levels; ++level) { | ||||
|         size += GetInnerMipmapMemorySize(level, as_host_size, uncompressed); | ||||
|     } | ||||
|     if (is_tiled && IsLayered()) { | ||||
|     if (is_tiled && (IsLayered() || target == SurfaceTarget::Texture3D)) { | ||||
|         return Common::AlignUp(size, Tegra::Texture::GetGOBSize() * block_height * block_depth); | ||||
|     } | ||||
|     return size; | ||||
| @@ -312,9 +314,10 @@ void SurfaceParams::CalculateCachedValues() { | ||||
|  | ||||
|     guest_size_in_bytes = GetInnerMemorySize(false, false, false); | ||||
|  | ||||
|     // ASTC is uncompressed in software, in emulated as RGBA8 | ||||
|     if (IsPixelFormatASTC(pixel_format)) { | ||||
|         host_size_in_bytes = static_cast<std::size_t>(width * height * depth * 4U); | ||||
|         // ASTC is uncompressed in software, in emulated as RGBA8 | ||||
|         host_size_in_bytes = static_cast<std::size_t>(width) * static_cast<std::size_t>(height) * | ||||
|                              static_cast<std::size_t>(depth) * 4ULL; | ||||
|     } else { | ||||
|         host_size_in_bytes = GetInnerMemorySize(true, false, false); | ||||
|     } | ||||
|   | ||||
| @@ -273,7 +273,7 @@ struct hash<VideoCommon::ViewKey> { | ||||
|  | ||||
| namespace VideoCommon { | ||||
|  | ||||
| template <typename TView, typename TExecutionContext> | ||||
| template <typename TTextureCache, typename TView, typename TExecutionContext> | ||||
| class SurfaceBase { | ||||
|     static_assert(std::is_trivially_copyable_v<TExecutionContext>); | ||||
|  | ||||
| @@ -331,6 +331,9 @@ public: | ||||
|  | ||||
|     void MarkAsModified(bool is_modified_) { | ||||
|         is_modified = is_modified_; | ||||
|         if (is_modified_) { | ||||
|             modification_tick = texture_cache.Tick(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     const SurfaceParams& GetSurfaceParams() const { | ||||
| @@ -358,13 +361,18 @@ public: | ||||
|         is_registered = false; | ||||
|     } | ||||
|  | ||||
|     u64 GetModificationTick() const { | ||||
|         return modification_tick; | ||||
|     } | ||||
|  | ||||
|     bool IsRegistered() const { | ||||
|         return is_registered; | ||||
|     } | ||||
|  | ||||
| protected: | ||||
|     explicit SurfaceBase(const SurfaceParams& params) | ||||
|         : params{params}, view_offset_map{params.CreateViewOffsetMap()} {} | ||||
|     explicit SurfaceBase(TTextureCache& texture_cache, const SurfaceParams& params) | ||||
|         : params{params}, texture_cache{texture_cache}, view_offset_map{ | ||||
|                                                             params.CreateViewOffsetMap()} {} | ||||
|  | ||||
|     ~SurfaceBase() = default; | ||||
|  | ||||
| @@ -389,12 +397,14 @@ private: | ||||
|         return view.get(); | ||||
|     } | ||||
|  | ||||
|     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{}; | ||||
|     std::unordered_map<ViewKey, std::unique_ptr<TView>> views; | ||||
| @@ -475,6 +485,10 @@ public: | ||||
|         return it != registered_surfaces.end() ? *it->second.begin() : nullptr; | ||||
|     } | ||||
|  | ||||
|     u64 Tick() { | ||||
|         return ++ticks; | ||||
|     } | ||||
|  | ||||
| protected: | ||||
|     TextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer) | ||||
|         : system{system}, rasterizer{rasterizer} {} | ||||
| @@ -521,7 +535,7 @@ private: | ||||
|  | ||||
|         const auto host_ptr{memory_manager.GetPointer(gpu_addr)}; | ||||
|         const auto cache_addr{ToCacheAddr(host_ptr)}; | ||||
|         const auto overlaps{GetSurfacesInRegion(cache_addr, params.GetGuestSizeInBytes())}; | ||||
|         auto overlaps{GetSurfacesInRegion(cache_addr, params.GetGuestSizeInBytes())}; | ||||
|         if (overlaps.empty()) { | ||||
|             return LoadSurfaceView(exctx, gpu_addr, *cpu_addr, host_ptr, params, preserve_contents); | ||||
|         } | ||||
| @@ -544,8 +558,8 @@ private: | ||||
|  | ||||
|         for (const auto& surface : overlaps) { | ||||
|             if (!fast_view) { | ||||
|                 // Flush even when we don't care about the contents, to preserve memory not written | ||||
|                 // by the new surface. | ||||
|                 // Flush even when we don't care about the contents, to preserve memory not | ||||
|                 // written by the new surface. | ||||
|                 exctx = surface->FlushBuffer(exctx); | ||||
|             } | ||||
|             Unregister(surface); | ||||
| @@ -614,6 +628,8 @@ private: | ||||
|  | ||||
|     VideoCore::RasterizerInterface& rasterizer; | ||||
|  | ||||
|     u64 ticks{}; | ||||
|  | ||||
|     IntervalMap registered_surfaces; | ||||
|  | ||||
|     /// The surface reserve is a "backup" cache, this is where we put unique surfaces that have | ||||
| @@ -653,6 +669,10 @@ public: | ||||
|         return Base::TryFindFramebufferSurface(host_ptr); | ||||
|     } | ||||
|  | ||||
|     u64 Tick() { | ||||
|         return Base::Tick(); | ||||
|     } | ||||
|  | ||||
| protected: | ||||
|     explicit TextureCacheContextless(Core::System& system, | ||||
|                                      VideoCore::RasterizerInterface& rasterizer) | ||||
| @@ -678,8 +698,8 @@ private: | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template <typename TView> | ||||
| class SurfaceBaseContextless : public SurfaceBase<TView, DummyExecutionContext> { | ||||
| template <typename TTextureCache, typename TView> | ||||
| class SurfaceBaseContextless : public SurfaceBase<TTextureCache, TView, DummyExecutionContext> { | ||||
| public: | ||||
|     DummyExecutionContext FlushBuffer(DummyExecutionContext) { | ||||
|         FlushBufferImpl(); | ||||
| @@ -692,8 +712,8 @@ public: | ||||
|     } | ||||
|  | ||||
| protected: | ||||
|     explicit SurfaceBaseContextless(const SurfaceParams& params) | ||||
|         : SurfaceBase<TView, DummyExecutionContext>{params} {} | ||||
|     explicit SurfaceBaseContextless(TTextureCache& texture_cache, const SurfaceParams& params) | ||||
|         : SurfaceBase<TTextureCache, TView, DummyExecutionContext>{texture_cache, params} {} | ||||
|  | ||||
|     virtual void FlushBufferImpl() = 0; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 ReinUsesLisp
					ReinUsesLisp