Match mip layers and array layers in texture manager

This commit is contained in:
Billy Laws 2022-11-03 22:36:03 +00:00
parent d502adb309
commit 3ae1e78544

View File

@ -25,7 +25,19 @@ namespace skyline::gpu {
std::shared_ptr<Texture> match{}; std::shared_ptr<Texture> match{};
boost::container::small_vector<std::shared_ptr<Texture>, 4> matches{}; boost::container::small_vector<std::shared_ptr<Texture>, 4> matches{};
auto mappingEnd{std::upper_bound(textures.begin(), textures.end(), guestMapping)}, hostMapping{mappingEnd}; auto mappingEnd{std::upper_bound(textures.begin(), textures.end(), guestMapping, [](const auto &value, const auto &element) {
return value.end() < element.end();
})}, hostMapping{mappingEnd};
while (hostMapping != textures.end() && guestMapping.begin() < hostMapping->end())
hostMapping++;
std::shared_ptr<Texture> fullMatch{};
std::shared_ptr<Texture> layerMipMatch{};
u32 matchLevel{};
u32 matchLayer{};
while (hostMapping != textures.begin() && (--hostMapping)->end() > guestMapping.begin()) { while (hostMapping != textures.begin() && (--hostMapping)->end() > guestMapping.begin()) {
auto &hostMappings{hostMapping->texture->guest->mappings}; auto &hostMappings{hostMapping->texture->guest->mappings};
if (!hostMapping->contains(guestMapping)) if (!hostMapping->contains(guestMapping))
@ -47,34 +59,67 @@ namespace skyline::gpu {
auto &matchGuestTexture{*hostMapping->texture->guest}; auto &matchGuestTexture{*hostMapping->texture->guest};
if (matchGuestTexture.format->IsCompatible(*guestTexture.format) && if (matchGuestTexture.format->IsCompatible(*guestTexture.format) &&
((((matchGuestTexture.dimensions.width == guestTexture.dimensions.width && ((((matchGuestTexture.dimensions.width == guestTexture.dimensions.width &&
matchGuestTexture.dimensions.height == guestTexture.dimensions.height) || matchGuestTexture.CalculateLayerSize() == guestTexture.CalculateLayerSize()) && matchGuestTexture.dimensions.height == guestTexture.dimensions.height) || matchGuestTexture.CalculateLayerSize() == guestTexture.CalculateLayerSize()) &&
matchGuestTexture.GetViewDepth() <= guestTexture.GetViewDepth()) matchGuestTexture.GetViewDepth() <= guestTexture.GetViewDepth())
|| matchGuestTexture.viewMipBase > 0) || matchGuestTexture.viewMipBase > 0)
&& matchGuestTexture.tileConfig == guestTexture.tileConfig) { && matchGuestTexture.tileConfig == guestTexture.tileConfig) {
auto &texture{hostMapping->texture}; fullMatch = hostMapping->texture;
ContextLock textureLock{tag, *texture};
return texture->GetView(guestTexture.viewType, vk::ImageSubresourceRange{
.aspectMask = guestTexture.aspect,
.baseMipLevel = guestTexture.viewMipBase,
.levelCount = guestTexture.viewMipCount,
.baseArrayLayer = guestTexture.baseArrayLayer,
.layerCount = guestTexture.GetViewLayerCount(),
}, guestTexture.format, guestTexture.swizzle);
} else { } else {
matches.push_back(hostMapping->texture); matches.push_back(hostMapping->texture);
} }
} /* else if (mappingMatch) { } else {
// We've gotten a partial match with a certain subset of contiguous mappings matching, we need to check if this is a meaningful overlap auto &matchGuestTexture{*hostMapping->texture->guest};
if (MeaningfulOverlap) { if (matchGuestTexture.format->IsCompatible(*guestTexture.format) && matchGuestTexture.tileConfig == guestTexture.tileConfig &&
// TODO: Layout Checks + Check match against Base Layer in TIC (!layerMipMatch || (matchGuestTexture.GetViewLayerCount() >= layerMipMatch->guest->GetViewLayerCount() && matchGuestTexture.mipLevelCount >= layerMipMatch->guest->mipLevelCount))) {
auto &texture{hostMapping->texture}; size_t memOffset{static_cast<size_t>(guestMapping.data() - hostMapping->texture->guest->mappings.front().data())};
return TextureView(texture, static_cast<vk::ImageViewType>(guestTexture.type), vk::ImageSubresourceRange{ size_t layerMemOffset{};
.aspectMask = guestTexture.format->vkAspect, bool matched{};
.levelCount = texture->mipLevels, for (u32 layer{}; layer < hostMapping->texture->layerCount; layer++) {
.layerCount = texture->layerCount, u32 level{};
}, guestTexture.format); size_t levelMemOffset{};
for (auto &mipLevel : hostMapping->texture->mipLayouts) {
if (layerMemOffset + levelMemOffset == memOffset) {
if (mipLevel.blockLinearSize == guestTexture.CalculateLayerSize()) {
matched = true;
matchLayer = layer;
matchLevel = level;
break;
}
level++;
levelMemOffset += mipLevel.blockLinearSize;
}
}
if (matched)
break;
layerMemOffset += matchGuestTexture.GetLayerStride();
}
if (matched)
layerMipMatch = hostMapping->texture;
} }
} */ }
}
if (layerMipMatch) {
ContextLock textureLock{tag, *layerMipMatch};
return layerMipMatch->GetView(guestTexture.viewType, vk::ImageSubresourceRange{
.aspectMask = guestTexture.aspect,
.baseMipLevel = guestTexture.viewMipBase + matchLevel,
.levelCount = guestTexture.viewMipCount,
.baseArrayLayer = guestTexture.baseArrayLayer + matchLayer,
.layerCount = guestTexture.GetViewLayerCount(),
}, guestTexture.format, guestTexture.swizzle);
} else if (fullMatch) {
ContextLock textureLock{tag, *fullMatch};
return fullMatch->GetView(guestTexture.viewType, vk::ImageSubresourceRange{
.aspectMask = guestTexture.aspect,
.baseMipLevel = guestTexture.viewMipBase,
.levelCount = guestTexture.viewMipCount,
.baseArrayLayer = guestTexture.baseArrayLayer,
.layerCount = guestTexture.GetViewLayerCount(),
}, guestTexture.format, guestTexture.swizzle);
} }
for (auto &texture : matches) for (auto &texture : matches)