Enforce stronger format and weaker dimension texture compat checks

Rather than using just bpb for format compat, additionally check that the exact component bit layout matches since many games end up reusing RTs for unrelated textures. The texture size requirements have also been weaked to only check the resulting layer size as opposed to width/height - this is somewhat hacky but it gets around the problem of blocklinear alignment.
This commit is contained in:
Billy Laws 2022-10-21 22:03:13 +01:00
parent 14af383238
commit ff57d2fbbf
3 changed files with 16 additions and 7 deletions

View File

@ -3,8 +3,9 @@
#include <gpu.h>
#include <kernel/memory.h>
#include <common/trace.h>
#include <kernel/types/KProcess.h>
#include <common/trace.h>
#include <common/settings.h>
#include "texture.h"
#include "layout.h"
#include "adreno_aliasing.h"
@ -20,7 +21,7 @@ namespace skyline::gpu {
return layerStride;
}
u32 GuestTexture::CalculateLayerSize() {
u32 GuestTexture::CalculateLayerSize() const {
switch (tileConfig.mode) {
case texture::TileMode::Linear:
return static_cast<u32>(format->GetSize(dimensions));

View File

@ -3,6 +3,8 @@
#pragma once
#include <range/v3/view.hpp>
#include <range/v3/algorithm.hpp>
#include <common/spin_lock.h>
#include <common/lockable_shared_ptr.h>
#include <nce.h>
@ -111,7 +113,13 @@ namespace skyline::gpu {
* @return If the supplied format is texel-layout compatible with the current format
*/
constexpr bool IsCompatible(const FormatBase &other) const {
return bpb == other.bpb && blockHeight == other.blockHeight && blockWidth == other.blockWidth;
return vkFormat == other.vkFormat
|| (vkFormat == vk::Format::eD32Sfloat && other.vkFormat == vk::Format::eR32Sfloat)
|| (vkFormat == vk::Format::eR32Sfloat && other.vkFormat == vk::Format::eD32Sfloat)
|| (componentCount(vkFormat) == componentCount(other.vkFormat) &&
ranges::all_of(ranges::views::iota(u8{0}, componentCount(vkFormat)), [this, other](auto i) {
return componentBits(vkFormat, i) == componentBits(other.vkFormat, i);
}) && (vkAspect & other.vkAspect) != vk::ImageAspectFlags{});
}
/**
@ -279,7 +287,7 @@ namespace skyline::gpu {
/**
* @brief Calculates the size of a single layer in bytes, unlike `GetLayerStride` the returned layer size is always calculated and may not be equal to the actual layer stride
*/
u32 CalculateLayerSize();
u32 CalculateLayerSize() const;
/**
* @return The most appropriate backing image type for this texture

View File

@ -46,9 +46,9 @@ namespace skyline::gpu {
// We've gotten a perfect 1:1 match for *all* mappings from the start to end, we just need to check for compatibility aside from this
auto &matchGuestTexture{*hostMapping->texture->guest};
if (matchGuestTexture.format->IsCompatible(*guestTexture.format) &&
((matchGuestTexture.dimensions.width == guestTexture.dimensions.width &&
matchGuestTexture.dimensions.height == guestTexture.dimensions.height &&
matchGuestTexture.GetViewDepth() == guestTexture.GetViewDepth())
((((matchGuestTexture.dimensions.width == guestTexture.dimensions.width &&
matchGuestTexture.dimensions.height == guestTexture.dimensions.height) || matchGuestTexture.CalculateLayerSize() == guestTexture.CalculateLayerSize()) &&
matchGuestTexture.GetViewDepth() <= guestTexture.GetViewDepth())
|| matchGuestTexture.viewMipBase > 0)
&& matchGuestTexture.tileConfig == guestTexture.tileConfig) {
auto &texture{hostMapping->texture};