diff options
| author | 2019-05-18 04:57:49 -0400 | |
|---|---|---|
| committer | 2019-06-20 21:38:33 -0300 | |
| commit | 175aa343ff1c9f931b266caf2d19b8df943dab0d (patch) | |
| tree | c9cdf1f449232c7fc0728be6bbc86d8537ff44aa /src/video_core/texture_cache | |
| parent | gl_shader_decompiler: Implement image binding settings (diff) | |
| download | yuzu-175aa343ff1c9f931b266caf2d19b8df943dab0d.tar.gz yuzu-175aa343ff1c9f931b266caf2d19b8df943dab0d.tar.xz yuzu-175aa343ff1c9f931b266caf2d19b8df943dab0d.zip | |
texture_cache: Fermi2D reform and implement View Mirage
This also does some fixes on compressed textures reinterpret and on the
Fermi2D engine in general.
Diffstat (limited to 'src/video_core/texture_cache')
| -rw-r--r-- | src/video_core/texture_cache/surface_base.h | 15 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_params.h | 14 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 40 |
3 files changed, 49 insertions, 20 deletions
diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index cb7f22706..a3dd1c607 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h | |||
| @@ -126,14 +126,19 @@ public: | |||
| 126 | return MatchStructureResult::None; | 126 | return MatchStructureResult::None; |
| 127 | } | 127 | } |
| 128 | // Tiled surface | 128 | // Tiled surface |
| 129 | if (std::tie(params.height, params.depth, params.block_width, params.block_height, | 129 | if (std::tie(params.depth, params.block_width, params.block_height, params.block_depth, |
| 130 | params.block_depth, params.tile_width_spacing, params.num_levels) == | 130 | params.tile_width_spacing, params.num_levels) == |
| 131 | std::tie(rhs.height, rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, | 131 | std::tie(rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, |
| 132 | rhs.tile_width_spacing, rhs.num_levels)) { | 132 | rhs.tile_width_spacing, rhs.num_levels)) { |
| 133 | if (params.width == rhs.width) { | 133 | if (std::tie(params.width, params.height) == std::tie(rhs.width, rhs.height)) { |
| 134 | return MatchStructureResult::FullMatch; | 134 | return MatchStructureResult::FullMatch; |
| 135 | } | 135 | } |
| 136 | if (params.GetBlockAlignedWidth() == rhs.GetBlockAlignedWidth()) { | 136 | const u32 ws = SurfaceParams::ConvertWidth(rhs.GetBlockAlignedWidth(), |
| 137 | params.pixel_format, rhs.pixel_format); | ||
| 138 | const u32 hs = | ||
| 139 | SurfaceParams::ConvertHeight(rhs.height, params.pixel_format, rhs.pixel_format); | ||
| 140 | const u32 w1 = params.GetBlockAlignedWidth(); | ||
| 141 | if (std::tie(w1, params.height) == std::tie(ws, hs)) { | ||
| 137 | return MatchStructureResult::SemiMatch; | 142 | return MatchStructureResult::SemiMatch; |
| 138 | } | 143 | } |
| 139 | } | 144 | } |
diff --git a/src/video_core/texture_cache/surface_params.h b/src/video_core/texture_cache/surface_params.h index b3082173f..13a08a60f 100644 --- a/src/video_core/texture_cache/surface_params.h +++ b/src/video_core/texture_cache/surface_params.h | |||
| @@ -126,6 +126,20 @@ public: | |||
| 126 | /// Returns the size of a layer in bytes in host memory for a given mipmap level. | 126 | /// Returns the size of a layer in bytes in host memory for a given mipmap level. |
| 127 | std::size_t GetHostLayerSize(u32 level) const; | 127 | std::size_t GetHostLayerSize(u32 level) const; |
| 128 | 128 | ||
| 129 | static u32 ConvertWidth(u32 width, VideoCore::Surface::PixelFormat pixel_format_from, | ||
| 130 | VideoCore::Surface::PixelFormat pixel_format_to) { | ||
| 131 | const u32 bw1 = VideoCore::Surface::GetDefaultBlockWidth(pixel_format_from); | ||
| 132 | const u32 bw2 = VideoCore::Surface::GetDefaultBlockWidth(pixel_format_to); | ||
| 133 | return (width * bw2 + bw1 - 1) / bw1; | ||
| 134 | } | ||
| 135 | |||
| 136 | static u32 ConvertHeight(u32 height, VideoCore::Surface::PixelFormat pixel_format_from, | ||
| 137 | VideoCore::Surface::PixelFormat pixel_format_to) { | ||
| 138 | const u32 bh1 = VideoCore::Surface::GetDefaultBlockHeight(pixel_format_from); | ||
| 139 | const u32 bh2 = VideoCore::Surface::GetDefaultBlockHeight(pixel_format_to); | ||
| 140 | return (height * bh2 + bh1 - 1) / bh1; | ||
| 141 | } | ||
| 142 | |||
| 129 | /// Returns the default block width. | 143 | /// Returns the default block width. |
| 130 | u32 GetDefaultBlockWidth() const { | 144 | u32 GetDefaultBlockWidth() const { |
| 131 | return VideoCore::Surface::GetDefaultBlockWidth(pixel_format); | 145 | return VideoCore::Surface::GetDefaultBlockWidth(pixel_format); |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 85c9160e0..593ceeaf6 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -141,11 +141,6 @@ public: | |||
| 141 | return {}; | 141 | return {}; |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | if (regs.color_mask[index].raw == 0) { | ||
| 145 | SetEmptyColorBuffer(index); | ||
| 146 | return {}; | ||
| 147 | } | ||
| 148 | |||
| 149 | const auto& config{regs.rt[index]}; | 144 | const auto& config{regs.rt[index]}; |
| 150 | const auto gpu_addr{config.Address()}; | 145 | const auto gpu_addr{config.Address()}; |
| 151 | if (!gpu_addr) { | 146 | if (!gpu_addr) { |
| @@ -192,11 +187,11 @@ public: | |||
| 192 | 187 | ||
| 193 | void DoFermiCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src_config, | 188 | void DoFermiCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src_config, |
| 194 | const Tegra::Engines::Fermi2D::Regs::Surface& dst_config, | 189 | const Tegra::Engines::Fermi2D::Regs::Surface& dst_config, |
| 195 | const Common::Rectangle<u32>& src_rect, | 190 | const Tegra::Engines::Fermi2D::Config& copy_config) { |
| 196 | const Common::Rectangle<u32>& dst_rect) { | 191 | std::pair<TSurface, TView> dst_surface = GetFermiSurface(dst_config); |
| 197 | TSurface dst_surface = GetFermiSurface(dst_config); | 192 | std::pair<TSurface, TView> src_surface = GetFermiSurface(src_config); |
| 198 | ImageBlit(GetFermiSurface(src_config), dst_surface, src_rect, dst_rect); | 193 | ImageBlit(src_surface.second, dst_surface.second, copy_config); |
| 199 | dst_surface->MarkAsModified(true, Tick()); | 194 | dst_surface.first->MarkAsModified(true, Tick()); |
| 200 | } | 195 | } |
| 201 | 196 | ||
| 202 | TSurface TryFindFramebufferSurface(const u8* host_ptr) { | 197 | TSurface TryFindFramebufferSurface(const u8* host_ptr) { |
| @@ -234,8 +229,8 @@ protected: | |||
| 234 | virtual void ImageCopy(TSurface src_surface, TSurface dst_surface, | 229 | virtual void ImageCopy(TSurface src_surface, TSurface dst_surface, |
| 235 | const CopyParams& copy_params) = 0; | 230 | const CopyParams& copy_params) = 0; |
| 236 | 231 | ||
| 237 | virtual void ImageBlit(TSurface src, TSurface dst, const Common::Rectangle<u32>& src_rect, | 232 | virtual void ImageBlit(TView src_view, TView dst_view, |
| 238 | const Common::Rectangle<u32>& dst_rect) = 0; | 233 | const Tegra::Engines::Fermi2D::Config& copy_config) = 0; |
| 239 | 234 | ||
| 240 | void Register(TSurface surface) { | 235 | void Register(TSurface surface) { |
| 241 | std::lock_guard lock{mutex}; | 236 | std::lock_guard lock{mutex}; |
| @@ -282,10 +277,11 @@ protected: | |||
| 282 | return new_surface; | 277 | return new_surface; |
| 283 | } | 278 | } |
| 284 | 279 | ||
| 285 | TSurface GetFermiSurface(const Tegra::Engines::Fermi2D::Regs::Surface& config) { | 280 | std::pair<TSurface, TView> GetFermiSurface( |
| 281 | const Tegra::Engines::Fermi2D::Regs::Surface& config) { | ||
| 286 | SurfaceParams params = SurfaceParams::CreateForFermiCopySurface(config); | 282 | SurfaceParams params = SurfaceParams::CreateForFermiCopySurface(config); |
| 287 | const GPUVAddr gpu_addr = config.Address(); | 283 | const GPUVAddr gpu_addr = config.Address(); |
| 288 | return GetSurface(gpu_addr, params, true).first; | 284 | return GetSurface(gpu_addr, params, true); |
| 289 | } | 285 | } |
| 290 | 286 | ||
| 291 | Core::System& system; | 287 | Core::System& system; |
| @@ -551,7 +547,21 @@ private: | |||
| 551 | if (view.has_value()) { | 547 | if (view.has_value()) { |
| 552 | const bool is_mirage = !current_surface->MatchFormat(params.pixel_format); | 548 | const bool is_mirage = !current_surface->MatchFormat(params.pixel_format); |
| 553 | if (is_mirage) { | 549 | if (is_mirage) { |
| 554 | LOG_CRITICAL(HW_GPU, "Mirage View Unsupported"); | 550 | // On a mirage view, we need to recreate the surface under this new view |
| 551 | // and then obtain a view again. | ||
| 552 | SurfaceParams new_params = current_surface->GetSurfaceParams(); | ||
| 553 | const u32 wh = SurfaceParams::ConvertWidth( | ||
| 554 | new_params.width, new_params.pixel_format, params.pixel_format); | ||
| 555 | const u32 hh = SurfaceParams::ConvertHeight( | ||
| 556 | new_params.height, new_params.pixel_format, params.pixel_format); | ||
| 557 | new_params.width = wh; | ||
| 558 | new_params.height = hh; | ||
| 559 | new_params.pixel_format = params.pixel_format; | ||
| 560 | std::pair<TSurface, TView> pair = RebuildSurface(current_surface, new_params); | ||
| 561 | std::optional<TView> mirage_view = | ||
| 562 | pair.first->EmplaceView(params, gpu_addr, candidate_size); | ||
| 563 | if (mirage_view) | ||
| 564 | return {pair.first, *mirage_view}; | ||
| 555 | return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, false); | 565 | return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, false); |
| 556 | } | 566 | } |
| 557 | return {current_surface, *view}; | 567 | return {current_surface, *view}; |