summaryrefslogtreecommitdiffstats
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/texture_cache/surface_params.cpp2
-rw-r--r--src/video_core/texture_cache/texture_cache.h49
2 files changed, 35 insertions, 16 deletions
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp
index 6fe7c85ac..0b2b2b8c4 100644
--- a/src/video_core/texture_cache/surface_params.cpp
+++ b/src/video_core/texture_cache/surface_params.cpp
@@ -247,7 +247,7 @@ SurfaceParams SurfaceParams::CreateForFermiCopySurface(
params.height = config.height;
params.pitch = config.pitch;
// TODO(Rodrigo): Try to guess texture arrays from parameters
- params.target = params.block_depth > 0 ? SurfaceTarget::Texture3D : SurfaceTarget::Texture2D;
+ params.target = SurfaceTarget::Texture2D;
params.depth = 1;
params.num_levels = 1;
params.emulated_levels = 1;
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index b19eeed66..b543fc8c0 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -724,10 +724,35 @@ private:
* @param params The parameters on the new surface.
* @param gpu_addr The starting address of the new surface.
* @param cpu_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(VectorSurface& overlaps,
const SurfaceParams& params,
- GPUVAddr gpu_addr, VAddr cpu_addr) {
+ GPUVAddr gpu_addr, VAddr cpu_addr,
+ bool preserve_contents) {
+ if (params.target != SurfaceTarget::Texture3D) {
+ for (const auto& surface : overlaps) {
+ if (!surface->MatchTarget(params.target)) {
+ if (overlaps.size() == 1 && surface->GetCpuAddr() == cpu_addr) {
+ if (Settings::IsGPULevelExtreme()) {
+ return std::nullopt;
+ }
+ Unregister(surface);
+ return InitializeSurface(gpu_addr, params, preserve_contents);
+ }
+ return std::nullopt;
+ }
+ if (surface->GetCpuAddr() != cpu_addr) {
+ continue;
+ }
+ if (surface->MatchesStructure(params) == MatchStructureResult::FullMatch) {
+ return std::make_pair(surface, surface->GetMainView());
+ }
+ }
+ return InitializeSurface(gpu_addr, params, preserve_contents);
+ }
+
if (params.num_levels > 1) {
// We can't handle mipmaps in 3D textures yet, better fallback to LLE approach
return std::nullopt;
@@ -748,25 +773,18 @@ private:
}
}
- if (params.depth == 1) {
- return std::nullopt;
- }
-
TSurface new_surface = GetUncachedSurface(gpu_addr, params);
- LoadSurface(new_surface);
-
bool modified = false;
+
for (auto& surface : overlaps) {
const SurfaceParams& src_params = surface->GetSurfaceParams();
- if (src_params.height != params.height ||
+ if (src_params.target != SurfaceTarget::Texture2D ||
+ src_params.height != params.height ||
src_params.block_depth != params.block_depth ||
src_params.block_height != params.block_height) {
return std::nullopt;
}
- if (!surface->IsModified()) {
- continue;
- }
- modified = true;
+ modified |= surface->IsModified();
const u32 offset = static_cast<u32>(surface->GetCpuAddr() - cpu_addr);
const u32 slice = std::get<2>(params.GetBlockOffsetXYZ(offset));
@@ -781,7 +799,7 @@ private:
new_surface->MarkAsModified(modified, Tick());
Register(new_surface);
- auto view = new_surface->GetMainView();
+ TView view = new_surface->GetMainView();
return std::make_pair(std::move(new_surface), std::move(view));
}
@@ -861,8 +879,9 @@ private:
}
// Manage 3D textures
- if (params.target == SurfaceTarget::Texture3D) {
- auto surface = Manage3DSurfaces(overlaps, params, gpu_addr, cpu_addr);
+ if (params.block_depth > 0) {
+ auto surface =
+ Manage3DSurfaces(overlaps, params, gpu_addr, cpu_addr, preserve_contents);
if (surface) {
return *surface;
}