summaryrefslogtreecommitdiffstats
path: root/src/video_core/texture_cache/texture_cache.h
diff options
context:
space:
mode:
authorFernando Sahmkow <fsahmkow27@gmail.com>2019-12-08 18:13:18 +0100
committerFernandoS27 <fsahmkow27@gmail.com>2019-12-22 17:24:34 +0100
commit51c9e98677395564a4fafeaba718cbd2263541bb (patch)
tree7546b488cf1753f227ba9e409a96ff247bc5ae73 /src/video_core/texture_cache/texture_cache.h
parentMerge pull request #3230 from ReinUsesLisp/vk-emu-shaders (diff)
downloadyuzu-51c9e98677395564a4fafeaba718cbd2263541bb.tar
yuzu-51c9e98677395564a4fafeaba718cbd2263541bb.tar.gz
yuzu-51c9e98677395564a4fafeaba718cbd2263541bb.tar.bz2
yuzu-51c9e98677395564a4fafeaba718cbd2263541bb.tar.lz
yuzu-51c9e98677395564a4fafeaba718cbd2263541bb.tar.xz
yuzu-51c9e98677395564a4fafeaba718cbd2263541bb.tar.zst
yuzu-51c9e98677395564a4fafeaba718cbd2263541bb.zip
Diffstat (limited to '')
-rw-r--r--src/video_core/texture_cache/texture_cache.h88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 02d2e9136..5416eee3b 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -616,6 +616,85 @@ private:
}
/**
+ * Takes care of managing 3D textures and its slices. Does some HLE methods when possible.
+ * Fallsback to LLE when it isn't possible.
+ *
+ * @param overlaps The overlapping surfaces registered in the cache.
+ * @param params The parameters on the new surface.
+ * @param gpu_addr The starting address of the new surface.
+ * @param cache_addr The starting address of the new surface on physical memory.
+ * @param preserve_contents Indicates that the new surface should be loaded from memory or
+ * left blank.
+ */
+ std::optional<std::pair<TSurface, TView>> Manage3DSurfaces(std::vector<TSurface>& overlaps,
+ const SurfaceParams& params,
+ const GPUVAddr gpu_addr,
+ const CacheAddr cache_addr,
+ bool preserve_contents) {
+ if (params.target == SurfaceTarget::Texture3D) {
+ bool failed = false;
+ if (params.num_levels > 1) {
+ // We can't handle mipmaps in 3D textures yet, better fallback to LLE approach
+ return std::nullopt;
+ }
+ TSurface new_surface = GetUncachedSurface(gpu_addr, params);
+ bool modified = false;
+ for (auto& surface : overlaps) {
+ const SurfaceParams& src_params = surface->GetSurfaceParams();
+ if (src_params.target != SurfaceTarget::Texture2D) {
+ failed = true;
+ break;
+ }
+ if (src_params.height != params.height) {
+ failed = true;
+ break;
+ }
+ if (src_params.block_depth != params.block_depth ||
+ src_params.block_height != params.block_height) {
+ failed = true;
+ break;
+ }
+ const u32 offset = static_cast<u32>(surface->GetCacheAddr() - cache_addr);
+ const auto [x, y, z] = params.GetBlockOffsetXYZ(offset);
+ modified |= surface->IsModified();
+ const CopyParams copy_params(0, 0, 0, 0, 0, z, 0, 0, params.width, params.height,
+ 1);
+ ImageCopy(surface, new_surface, copy_params);
+ }
+ if (failed) {
+ return std::nullopt;
+ }
+ for (const auto& surface : overlaps) {
+ Unregister(surface);
+ }
+ new_surface->MarkAsModified(modified, Tick());
+ Register(new_surface);
+ return {{new_surface, new_surface->GetMainView()}};
+ } else {
+ for (const auto& surface : overlaps) {
+ if (!surface->MatchTarget(params.target)) {
+ if (overlaps.size() == 1 && surface->GetCacheAddr() == cache_addr) {
+ if (Settings::values.use_accurate_gpu_emulation) {
+ return std::nullopt;
+ }
+ Unregister(surface);
+ return InitializeSurface(gpu_addr, params, preserve_contents);
+ }
+ return std::nullopt;
+ }
+ if (surface->GetCacheAddr() != cache_addr) {
+ continue;
+ }
+ const auto struct_result = surface->MatchesStructure(params);
+ if (struct_result == MatchStructureResult::FullMatch) {
+ return {{surface, surface->GetMainView()}};
+ }
+ }
+ return InitializeSurface(gpu_addr, params, preserve_contents);
+ }
+ }
+
+ /**
* Gets the starting address and parameters of a candidate surface and tries
* to find a matching surface within the cache. This is done in 3 big steps:
*
@@ -687,6 +766,15 @@ private:
}
}
+ // Look if it's a 3D texture
+ if (params.block_depth > 0) {
+ std::optional<std::pair<TSurface, TView>> surface =
+ Manage3DSurfaces(overlaps, params, gpu_addr, cache_addr, preserve_contents);
+ if (surface) {
+ return *surface;
+ }
+ }
+
// Split cases between 1 overlap or many.
if (overlaps.size() == 1) {
TSurface current_surface = overlaps[0];