texture_cache: Port original code management for 2D vs 3D textures
Handle blits to images as 2D, even when they have block depth. - Fixes rendering issues on Luigi's Mansion 3
This commit is contained in:
parent
c99f5d405b
commit
bd43c05470
2 changed files with 35 additions and 16 deletions
|
@ -247,7 +247,7 @@ SurfaceParams SurfaceParams::CreateForFermiCopySurface(
|
||||||
params.height = config.height;
|
params.height = config.height;
|
||||||
params.pitch = config.pitch;
|
params.pitch = config.pitch;
|
||||||
// TODO(Rodrigo): Try to guess texture arrays from parameters
|
// 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.depth = 1;
|
||||||
params.num_levels = 1;
|
params.num_levels = 1;
|
||||||
params.emulated_levels = 1;
|
params.emulated_levels = 1;
|
||||||
|
|
|
@ -724,10 +724,35 @@ private:
|
||||||
* @param params The parameters on the new surface.
|
* @param params The parameters on the new surface.
|
||||||
* @param gpu_addr The starting address of 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 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,
|
std::optional<std::pair<TSurface, TView>> Manage3DSurfaces(VectorSurface& overlaps,
|
||||||
const SurfaceParams& params,
|
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) {
|
if (params.num_levels > 1) {
|
||||||
// We can't handle mipmaps in 3D textures yet, better fallback to LLE approach
|
// We can't handle mipmaps in 3D textures yet, better fallback to LLE approach
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
@ -748,25 +773,18 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.depth == 1) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
TSurface new_surface = GetUncachedSurface(gpu_addr, params);
|
TSurface new_surface = GetUncachedSurface(gpu_addr, params);
|
||||||
LoadSurface(new_surface);
|
|
||||||
|
|
||||||
bool modified = false;
|
bool modified = false;
|
||||||
|
|
||||||
for (auto& surface : overlaps) {
|
for (auto& surface : overlaps) {
|
||||||
const SurfaceParams& src_params = surface->GetSurfaceParams();
|
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_depth != params.block_depth ||
|
||||||
src_params.block_height != params.block_height) {
|
src_params.block_height != params.block_height) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
if (!surface->IsModified()) {
|
modified |= surface->IsModified();
|
||||||
continue;
|
|
||||||
}
|
|
||||||
modified = true;
|
|
||||||
|
|
||||||
const u32 offset = static_cast<u32>(surface->GetCpuAddr() - cpu_addr);
|
const u32 offset = static_cast<u32>(surface->GetCpuAddr() - cpu_addr);
|
||||||
const u32 slice = std::get<2>(params.GetBlockOffsetXYZ(offset));
|
const u32 slice = std::get<2>(params.GetBlockOffsetXYZ(offset));
|
||||||
|
@ -781,7 +799,7 @@ private:
|
||||||
new_surface->MarkAsModified(modified, Tick());
|
new_surface->MarkAsModified(modified, Tick());
|
||||||
Register(new_surface);
|
Register(new_surface);
|
||||||
|
|
||||||
auto view = new_surface->GetMainView();
|
TView view = new_surface->GetMainView();
|
||||||
return std::make_pair(std::move(new_surface), std::move(view));
|
return std::make_pair(std::move(new_surface), std::move(view));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -861,8 +879,9 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manage 3D textures
|
// Manage 3D textures
|
||||||
if (params.target == SurfaceTarget::Texture3D) {
|
if (params.block_depth > 0) {
|
||||||
auto surface = Manage3DSurfaces(overlaps, params, gpu_addr, cpu_addr);
|
auto surface =
|
||||||
|
Manage3DSurfaces(overlaps, params, gpu_addr, cpu_addr, preserve_contents);
|
||||||
if (surface) {
|
if (surface) {
|
||||||
return *surface;
|
return *surface;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue