mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-26 21:54:16 +01:00
Avoid format aliasing warnings on Adreno
Implements an algorithm to determine formats that can be aliased as views without needing `VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT`, this avoids spamming warning logs on view creation when the aliased formats will function in practice.
This commit is contained in:
parent
7206ab4c67
commit
62ea2a6da5
161
app/src/main/cpp/skyline/gpu/texture/adreno_aliasing.h
Normal file
161
app/src/main/cpp/skyline/gpu/texture/adreno_aliasing.h
Normal file
@ -0,0 +1,161 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/container/static_vector.hpp>
|
||||
#include <vulkan/vulkan_enums.hpp>
|
||||
#include <common.h>
|
||||
|
||||
namespace skyline::gpu::texture {
|
||||
/**
|
||||
* @return If a particular format is compatible to alias views of without VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT on Adreno GPUs
|
||||
*/
|
||||
bool IsAdrenoAliasCompatible(vk::Format lhs, vk::Format rhs) {
|
||||
if (lhs <= vk::Format::eUndefined || lhs >= vk::Format::eB10G11R11UfloatPack32 ||
|
||||
rhs <= vk::Format::eUndefined || rhs >= vk::Format::eB10G11R11UfloatPack32)
|
||||
return false; // Any complex (compressed/multi-planar/etc) formats cannot be properly aliased
|
||||
|
||||
constexpr size_t MaxComponentCount{4};
|
||||
using ComponentContainer = boost::container::static_vector<int, MaxComponentCount>;
|
||||
auto GetComponents{[](vk::Format format) -> ComponentContainer {
|
||||
#define FMT(name, ...) case vk::Format::e ## name: return ComponentContainer({__VA_ARGS__})
|
||||
|
||||
switch (format) {
|
||||
FMT(R4G4UnormPack8, 4, 4);
|
||||
FMT(R4G4B4A4UnormPack16, 4, 4, 4, 4);
|
||||
FMT(B4G4R4A4UnormPack16, 4, 4, 4, 4);
|
||||
FMT(R5G6B5UnormPack16, 5, 6, 5);
|
||||
FMT(B5G6R5UnormPack16, 5, 6, 5);
|
||||
FMT(R5G5B5A1UnormPack16, 5, 5, 5, 1);
|
||||
FMT(B5G5R5A1UnormPack16, 5, 5, 5, 1);
|
||||
FMT(A1R5G5B5UnormPack16, 1, 5, 5, 5);
|
||||
FMT(R8Unorm, 8);
|
||||
FMT(R8Snorm, 8);
|
||||
FMT(R8Uscaled, 8);
|
||||
FMT(R8Sscaled, 8);
|
||||
FMT(R8Uint, 8);
|
||||
FMT(R8Sint, 8);
|
||||
FMT(R8Srgb, 8);
|
||||
FMT(R8G8Unorm, 8, 8);
|
||||
FMT(R8G8Snorm, 8, 8);
|
||||
FMT(R8G8Uscaled, 8, 8);
|
||||
FMT(R8G8Sscaled, 8, 8);
|
||||
FMT(R8G8Uint, 8, 8);
|
||||
FMT(R8G8Sint, 8, 8);
|
||||
FMT(R8G8Srgb, 8, 8);
|
||||
FMT(R8G8B8Unorm, 8, 8, 8);
|
||||
FMT(R8G8B8Snorm, 8, 8, 8);
|
||||
FMT(R8G8B8Uscaled, 8, 8, 8);
|
||||
FMT(R8G8B8Sscaled, 8, 8, 8);
|
||||
FMT(R8G8B8Uint, 8, 8, 8);
|
||||
FMT(R8G8B8Sint, 8, 8, 8);
|
||||
FMT(R8G8B8Srgb, 8, 8, 8);
|
||||
FMT(B8G8R8Unorm, 8, 8, 8);
|
||||
FMT(B8G8R8Snorm, 8, 8, 8);
|
||||
FMT(B8G8R8Uscaled, 8, 8, 8);
|
||||
FMT(B8G8R8Sscaled, 8, 8, 8);
|
||||
FMT(B8G8R8Uint, 8, 8, 8);
|
||||
FMT(B8G8R8Sint, 8, 8, 8);
|
||||
FMT(B8G8R8Srgb, 8, 8, 8);
|
||||
FMT(R8G8B8A8Unorm, 8, 8, 8, 8);
|
||||
FMT(R8G8B8A8Snorm, 8, 8, 8, 8);
|
||||
FMT(R8G8B8A8Uscaled, 8, 8, 8, 8);
|
||||
FMT(R8G8B8A8Sscaled, 8, 8, 8, 8);
|
||||
FMT(R8G8B8A8Uint, 8, 8, 8, 8);
|
||||
FMT(R8G8B8A8Sint, 8, 8, 8, 8);
|
||||
FMT(R8G8B8A8Srgb, 8, 8, 8, 8);
|
||||
FMT(B8G8R8A8Unorm, 8, 8, 8, 8);
|
||||
FMT(B8G8R8A8Snorm, 8, 8, 8, 8);
|
||||
FMT(B8G8R8A8Uscaled, 8, 8, 8, 8);
|
||||
FMT(B8G8R8A8Sscaled, 8, 8, 8, 8);
|
||||
FMT(B8G8R8A8Uint, 8, 8, 8, 8);
|
||||
FMT(B8G8R8A8Sint, 8, 8, 8, 8);
|
||||
FMT(B8G8R8A8Srgb, 8, 8, 8, 8);
|
||||
FMT(A8B8G8R8UnormPack32, 8, 8, 8, 8);
|
||||
FMT(A8B8G8R8SnormPack32, 8, 8, 8, 8);
|
||||
FMT(A8B8G8R8UscaledPack32, 8, 8, 8, 8);
|
||||
FMT(A8B8G8R8SscaledPack32, 8, 8, 8, 8);
|
||||
FMT(A8B8G8R8UintPack32, 8, 8, 8, 8);
|
||||
FMT(A8B8G8R8SintPack32, 8, 8, 8, 8);
|
||||
FMT(A8B8G8R8SrgbPack32, 8, 8, 8, 8);
|
||||
FMT(A2R10G10B10UnormPack32, 2, 10, 10, 10);
|
||||
FMT(A2R10G10B10SnormPack32, 2, 10, 10, 10);
|
||||
FMT(A2R10G10B10UscaledPack32, 2, 10, 10, 10);
|
||||
FMT(A2R10G10B10SscaledPack32, 2, 10, 10, 10);
|
||||
FMT(A2R10G10B10UintPack32, 2, 10, 10, 10);
|
||||
FMT(A2R10G10B10SintPack32, 2, 10, 10, 10);
|
||||
FMT(A2B10G10R10UnormPack32, 2, 10, 10, 10);
|
||||
FMT(A2B10G10R10SnormPack32, 2, 10, 10, 10);
|
||||
FMT(A2B10G10R10UscaledPack32, 2, 10, 10, 10);
|
||||
FMT(A2B10G10R10SscaledPack32, 2, 10, 10, 10);
|
||||
FMT(A2B10G10R10UintPack32, 2, 10, 10, 10);
|
||||
FMT(A2B10G10R10SintPack32, 2, 10, 10, 10);
|
||||
FMT(R16Unorm, 16);
|
||||
FMT(R16Snorm, 16);
|
||||
FMT(R16Uscaled, 16);
|
||||
FMT(R16Sscaled, 16);
|
||||
FMT(R16Uint, 16);
|
||||
FMT(R16Sint, 16);
|
||||
FMT(R16Sfloat, 16);
|
||||
FMT(R16G16Unorm, 16, 16);
|
||||
FMT(R16G16Snorm, 16, 16);
|
||||
FMT(R16G16Uscaled, 16, 16);
|
||||
FMT(R16G16Sscaled, 16, 16);
|
||||
FMT(R16G16Uint, 16, 16);
|
||||
FMT(R16G16Sint, 16, 16);
|
||||
FMT(R16G16Sfloat, 16, 16);
|
||||
FMT(R16G16B16Unorm, 16, 16, 16);
|
||||
FMT(R16G16B16Snorm, 16, 16, 16);
|
||||
FMT(R16G16B16Uscaled, 16, 16, 16);
|
||||
FMT(R16G16B16Sscaled, 16, 16, 16);
|
||||
FMT(R16G16B16Uint, 16, 16, 16);
|
||||
FMT(R16G16B16Sint, 16, 16, 16);
|
||||
FMT(R16G16B16Sfloat, 16, 16, 16);
|
||||
FMT(R16G16B16A16Unorm, 16, 16, 16, 16);
|
||||
FMT(R16G16B16A16Snorm, 16, 16, 16, 16);
|
||||
FMT(R16G16B16A16Uscaled, 16, 16, 16, 16);
|
||||
FMT(R16G16B16A16Sscaled, 16, 16, 16, 16);
|
||||
FMT(R16G16B16A16Uint, 16, 16, 16, 16);
|
||||
FMT(R16G16B16A16Sint, 16, 16, 16, 16);
|
||||
FMT(R16G16B16A16Sfloat, 16, 16, 16, 16);
|
||||
FMT(R32Uint, 32);
|
||||
FMT(R32Sint, 32);
|
||||
FMT(R32Sfloat, 32);
|
||||
FMT(R32G32Uint, 32, 32);
|
||||
FMT(R32G32Sint, 32, 32);
|
||||
FMT(R32G32Sfloat, 32, 32);
|
||||
FMT(R32G32B32Uint, 32, 32, 32);
|
||||
FMT(R32G32B32Sint, 32, 32, 32);
|
||||
FMT(R32G32B32Sfloat, 32, 32, 32);
|
||||
FMT(R32G32B32A32Uint, 32, 32, 32, 32);
|
||||
FMT(R32G32B32A32Sint, 32, 32, 32, 32);
|
||||
FMT(R32G32B32A32Sfloat, 32, 32, 32, 32);
|
||||
FMT(R64Uint, 64);
|
||||
FMT(R64Sint, 64);
|
||||
FMT(R64Sfloat, 64);
|
||||
FMT(R64G64Uint, 64, 64);
|
||||
FMT(R64G64Sint, 64, 64);
|
||||
FMT(R64G64Sfloat, 64, 64);
|
||||
FMT(R64G64B64Uint, 64, 64, 64);
|
||||
FMT(R64G64B64Sint, 64, 64, 64);
|
||||
FMT(R64G64B64Sfloat, 64, 64, 64);
|
||||
FMT(R64G64B64A64Uint, 64, 64, 64, 64);
|
||||
FMT(R64G64B64A64Sint, 64, 64, 64, 64);
|
||||
FMT(R64G64B64A64Sfloat, 64, 64, 64, 64);
|
||||
FMT(B10G11R11UfloatPack32, 10, 11, 11);
|
||||
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
|
||||
#undef FMT
|
||||
}};
|
||||
|
||||
// We need to ensure that both formats have corresponding component bits in the same order
|
||||
auto lhsComponents{GetComponents(lhs)}, rhsComponents{GetComponents(rhs)};
|
||||
if (lhsComponents.empty() || rhsComponents.empty())
|
||||
return false;
|
||||
return lhsComponents == rhsComponents;
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@
|
||||
#include <kernel/types/KProcess.h>
|
||||
#include "texture.h"
|
||||
#include "layout.h"
|
||||
#include "adreno_aliasing.h"
|
||||
|
||||
namespace skyline::gpu {
|
||||
u32 GuestTexture::GetLayerSize() {
|
||||
@ -539,8 +540,9 @@ namespace skyline::gpu {
|
||||
if (!pFormat)
|
||||
pFormat = format;
|
||||
|
||||
if (gpu.traits.quirks.vkImageMutableFormatCostly && pFormat->vkFormat != format->vkFormat)
|
||||
Logger::Warn("Creating a view of a texture with a different format without mutable format: {} - {}", vk::to_string(pFormat->vkFormat), vk::to_string(format->vkFormat));
|
||||
auto viewFormat{pFormat->vkFormat}, textureFormat{format->vkFormat};
|
||||
if (gpu.traits.quirks.vkImageMutableFormatCostly && viewFormat != textureFormat && (!gpu.traits.quirks.adrenoRelaxedFormatAliasing || !texture::IsAdrenoAliasCompatible(viewFormat, textureFormat)))
|
||||
Logger::Warn("Creating a view of a texture with a different format without mutable format: {} - {}", vk::to_string(viewFormat), vk::to_string(textureFormat));
|
||||
|
||||
return std::make_shared<TextureView>(shared_from_this(), type, range, pFormat, mapping);
|
||||
}
|
||||
|
@ -149,6 +149,7 @@ namespace skyline::gpu {
|
||||
case vk::DriverId::eQualcommProprietary: {
|
||||
needsIndividualTextureBindingWrites = true;
|
||||
vkImageMutableFormatCostly = true; // Disables UBWC
|
||||
adrenoRelaxedFormatAliasing = true;
|
||||
brokenDescriptorAliasing = true;
|
||||
relaxedRenderPassCompatibility = true; // Adreno drivers support relaxed render pass compatibility rules
|
||||
|
||||
@ -160,6 +161,7 @@ namespace skyline::gpu {
|
||||
|
||||
case vk::DriverId::eMesaTurnip: {
|
||||
vkImageMutableFormatCostly = true; // Disables UBWC and forces linear tiling
|
||||
adrenoRelaxedFormatAliasing = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -185,8 +187,8 @@ namespace skyline::gpu {
|
||||
|
||||
std::string TraitManager::QuirkManager::Summary() {
|
||||
return fmt::format(
|
||||
"\n* Needs Individual Texture Binding Writes: {}\n* VkImage Mutable Format is costly: {}\n* Broken Descriptor Aliasing: {}\n* Relaxed Render Pass Compatibility: {}\n* Max Subpass Count: {}\n* Max Global Queue Priority: {}",
|
||||
needsIndividualTextureBindingWrites, vkImageMutableFormatCostly, brokenDescriptorAliasing, relaxedRenderPassCompatibility, maxSubpassCount, vk::to_string(maxGlobalPriority)
|
||||
"\n* Needs Individual Texture Binding Writes: {}\n* VkImage Mutable Format is costly: {}\n* Adreno Relaxed Format Aliasing: {}\n* Broken Descriptor Aliasing: {}\n* Relaxed Render Pass Compatibility: {}\n* Max Subpass Count: {}\n* Max Global Queue Priority: {}",
|
||||
needsIndividualTextureBindingWrites, vkImageMutableFormatCostly, adrenoRelaxedFormatAliasing, brokenDescriptorAliasing, relaxedRenderPassCompatibility, maxSubpassCount, vk::to_string(maxGlobalPriority)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ namespace skyline::gpu {
|
||||
struct QuirkManager {
|
||||
bool needsIndividualTextureBindingWrites{}; //!< [Adreno Proprietary] A bug that requires descriptor set writes for VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER to be done individually with descriptorCount = 1 rather than batched
|
||||
bool vkImageMutableFormatCostly{}; //!< [Adreno Proprietary/Freedreno] An indication that VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT is costly and should not be enabled unless absolutely necessary (Disables UBWC on Adreno GPUs)
|
||||
bool adrenoRelaxedFormatAliasing{}; //!< [Adreno Proprietary/Freedreno] An indication that the GPU supports a relaxed version of view format aliasing without needing VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, this is designed to work in tandem with 'vkImageMutableFormatCostly'
|
||||
bool brokenDescriptorAliasing{}; //!< [Adreno Proprietary] A bug that causes alised descriptor sets to be incorrectly interpreted by the shader compiler leading to it buggering up LLVM function argument types and crashing
|
||||
bool relaxedRenderPassCompatibility{}; //!< [Adreno Proprietary/Freedreno] A relaxed version of Vulkan specification's render pass compatibility clause which allows for caching pipeline objects for multi-subpass renderpasses, this is intentionally disabled by default as it requires testing prior to enabling
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user