Return null texture on encountering unmapped textures

This commit is contained in:
Billy Laws 2022-12-31 23:06:00 +00:00
parent 97e127153b
commit ec519a7d52

View File

@ -183,6 +183,41 @@ namespace skyline::gpu::interconnect {
}; };
} }
static std::shared_ptr<TextureView> CreateNullTexture(InterconnectContext &ctx) {
constexpr texture::Format NullImageFormat{format::R8G8B8A8Unorm};
constexpr texture::Dimensions NullImageDimensions{1, 1, 1};
constexpr vk::ImageLayout NullImageInitialLayout{vk::ImageLayout::eUndefined};
constexpr vk::ImageTiling NullImageTiling{vk::ImageTiling::eOptimal};
constexpr vk::ImageCreateFlags NullImageFlags{};
constexpr vk::ImageUsageFlags NullImageUsage{vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eSampled};
auto vkImage{ctx.gpu.memory.AllocateImage(
{
.flags = NullImageFlags,
.imageType = vk::ImageType::e2D,
.format = NullImageFormat->vkFormat,
.extent = NullImageDimensions,
.mipLevels = 1,
.arrayLayers = 1,
.samples = vk::SampleCountFlagBits::e1,
.tiling = NullImageTiling,
.usage = NullImageUsage,
.sharingMode = vk::SharingMode::eExclusive,
.queueFamilyIndexCount = 1,
.pQueueFamilyIndices = &ctx.gpu.vkQueueFamilyIndex,
.initialLayout = NullImageInitialLayout
}
)};
auto nullTexture{std::make_shared<Texture>(ctx.gpu, std::move(vkImage), NullImageDimensions, NullImageFormat, NullImageInitialLayout, NullImageTiling, NullImageFlags, NullImageUsage)};
nullTexture->TransitionLayout(vk::ImageLayout::eGeneral);
return nullTexture->GetView(vk::ImageViewType::e2D, vk::ImageSubresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.levelCount = 1,
.layerCount = 1,
});;
}
TextureView *Textures::GetTexture(InterconnectContext &ctx, u32 index, Shader::TextureType shaderType) { TextureView *Textures::GetTexture(InterconnectContext &ctx, u32 index, Shader::TextureType shaderType) {
auto textureHeaders{texturePool.UpdateGet(ctx).textureHeaders}; auto textureHeaders{texturePool.UpdateGet(ctx).textureHeaders};
if (textureHeaderCache.size() != textureHeaders.size()) { if (textureHeaderCache.size() != textureHeaders.size()) {
@ -207,40 +242,8 @@ namespace skyline::gpu::interconnect {
if (auto format{ConvertTicFormat(textureHeader.formatWord, textureHeader.isSrgb)}) { if (auto format{ConvertTicFormat(textureHeader.formatWord, textureHeader.isSrgb)}) {
guest.format = format; guest.format = format;
} else { } else {
if (!nullTextureView) { if (!nullTextureView)
constexpr texture::Format NullImageFormat{format::R8G8B8A8Unorm}; nullTextureView = CreateNullTexture(ctx);
constexpr texture::Dimensions NullImageDimensions{1, 1, 1};
constexpr vk::ImageLayout NullImageInitialLayout{vk::ImageLayout::eUndefined};
constexpr vk::ImageTiling NullImageTiling{vk::ImageTiling::eOptimal};
constexpr vk::ImageCreateFlags NullImageFlags{};
constexpr vk::ImageUsageFlags NullImageUsage{vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eSampled};
auto vkImage{ctx.gpu.memory.AllocateImage(
{
.flags = NullImageFlags,
.imageType = vk::ImageType::e2D,
.format = NullImageFormat->vkFormat,
.extent = NullImageDimensions,
.mipLevels = 1,
.arrayLayers = 1,
.samples = vk::SampleCountFlagBits::e1,
.tiling = NullImageTiling,
.usage = NullImageUsage,
.sharingMode = vk::SharingMode::eExclusive,
.queueFamilyIndexCount = 1,
.pQueueFamilyIndices = &ctx.gpu.vkQueueFamilyIndex,
.initialLayout = NullImageInitialLayout
}
)};
auto nullTexture{std::make_shared<Texture>(ctx.gpu, std::move(vkImage), NullImageDimensions, NullImageFormat, NullImageInitialLayout, NullImageTiling, NullImageFlags, NullImageUsage)};
nullTexture->TransitionLayout(vk::ImageLayout::eGeneral);
nullTextureView = nullTexture->GetView(vk::ImageViewType::e2D, vk::ImageSubresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.levelCount = 1,
.layerCount = 1,
});
}
return nullTextureView.get(); return nullTextureView.get();
} }
@ -317,6 +320,13 @@ namespace skyline::gpu::interconnect {
auto mappings{ctx.channelCtx.asCtx->gmmu.TranslateRange(textureHeader.Iova(), guest.GetSize())}; auto mappings{ctx.channelCtx.asCtx->gmmu.TranslateRange(textureHeader.Iova(), guest.GetSize())};
guest.mappings.assign(mappings.begin(), mappings.end()); guest.mappings.assign(mappings.begin(), mappings.end());
if (guest.mappings.empty() || !guest.mappings.front().valid()) {
Logger::Warn("Unmapped texture in pool: 0x{:X}", textureHeader.Iova());
if (!nullTextureView)
nullTextureView = CreateNullTexture(ctx);
return nullTextureView.get();
}
texture = ctx.gpu.texture.FindOrCreate(guest, ctx.executor.tag); texture = ctx.gpu.texture.FindOrCreate(guest, ctx.executor.tag);
} }