From ec519a7d52ffa81fd8e7a74b83523802323a75a1 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Sat, 31 Dec 2022 23:06:00 +0000 Subject: [PATCH] Return null texture on encountering unmapped textures --- .../gpu/interconnect/common/textures.cpp | 78 +++++++++++-------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/interconnect/common/textures.cpp b/app/src/main/cpp/skyline/gpu/interconnect/common/textures.cpp index e378faab..79c8669c 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/common/textures.cpp +++ b/app/src/main/cpp/skyline/gpu/interconnect/common/textures.cpp @@ -183,6 +183,41 @@ namespace skyline::gpu::interconnect { }; } + static std::shared_ptr 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(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) { auto textureHeaders{texturePool.UpdateGet(ctx).textureHeaders}; if (textureHeaderCache.size() != textureHeaders.size()) { @@ -207,40 +242,8 @@ namespace skyline::gpu::interconnect { if (auto format{ConvertTicFormat(textureHeader.formatWord, textureHeader.isSrgb)}) { guest.format = format; } else { - if (!nullTextureView) { - 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(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, - }); - } + if (!nullTextureView) + nullTextureView = CreateNullTexture(ctx); return nullTextureView.get(); } @@ -317,6 +320,13 @@ namespace skyline::gpu::interconnect { auto mappings{ctx.channelCtx.asCtx->gmmu.TranslateRange(textureHeader.Iova(), guest.GetSize())}; 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); }