diff --git a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h index ccb45487..0aeab963 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h @@ -1951,22 +1951,17 @@ namespace skyline::gpu::interconnect { #undef TIC_FORMAT_CASE_NORM_INT_FLOAT } - /** - * @tparam ConvGR Converts all green component - * @tparam SwapBR Swaps blue and red components - */ - template - vk::ComponentMapping ConvertTicSwizzleMapping(TextureImageControl::FormatWord format) { - auto convertComponentSwizzle{[](TextureImageControl::ImageSwizzle swizzle) { + vk::ComponentMapping ConvertTicSwizzleMapping(TextureImageControl::FormatWord format, vk::ComponentMapping swizzleMapping) { + auto convertComponentSwizzle{[swizzleMapping](TextureImageControl::ImageSwizzle swizzle) { switch (swizzle) { case TextureImageControl::ImageSwizzle::R: - return SwapBR ? vk::ComponentSwizzle::eB : vk::ComponentSwizzle::eR; + return swizzleMapping.r; case TextureImageControl::ImageSwizzle::G: - return ConvGR ? vk::ComponentSwizzle::eR : vk::ComponentSwizzle::eG; + return swizzleMapping.g; case TextureImageControl::ImageSwizzle::B: - return SwapBR ? vk::ComponentSwizzle::eR : vk::ComponentSwizzle::eB; + return swizzleMapping.b; case TextureImageControl::ImageSwizzle::A: - return vk::ComponentSwizzle::eA; + return swizzleMapping.a; case TextureImageControl::ImageSwizzle::Zero: return vk::ComponentSwizzle::eZero; case TextureImageControl::ImageSwizzle::OneFloat: @@ -2006,13 +2001,7 @@ namespace skyline::gpu::interconnect { auto &guest{poolTexture.guest}; guest.format = ConvertTicFormat(textureControl.formatWord, textureControl.isSrgb); guest.aspect = guest.format->Aspect(textureControl.formatWord.swizzleX == TextureImageControl::ImageSwizzle::R); - - if (guest.format->IsDepthOrStencil()) // G/R are equivalent for depth/stencil - guest.swizzle = ConvertTicSwizzleMapping(textureControl.formatWord); - else if (guest.format->swapRedBlue) - guest.swizzle = ConvertTicSwizzleMapping(textureControl.formatWord); - else - guest.swizzle = ConvertTicSwizzleMapping(textureControl.formatWord); + guest.swizzle = ConvertTicSwizzleMapping(textureControl.formatWord, guest.format->swizzleMapping); constexpr size_t CubeFaceCount{6}; //!< The amount of faces of a cube diff --git a/app/src/main/cpp/skyline/gpu/presentation_engine.cpp b/app/src/main/cpp/skyline/gpu/presentation_engine.cpp index 2d5b4290..233f1716 100644 --- a/app/src/main/cpp/skyline/gpu/presentation_engine.cpp +++ b/app/src/main/cpp/skyline/gpu/presentation_engine.cpp @@ -121,7 +121,7 @@ namespace skyline::gpu { throw exception("Cannot update swapchain to accomodate image extent: {}x{} ({}x{}-{}x{})", extent.width, extent.height, capabilities.minImageExtent.width, capabilities.minImageExtent.height, capabilities.maxImageExtent.width, capabilities.maxImageExtent.height); vk::Format vkFormat{*format}; - if (vkFormat == vk::Format::eB5G6R5UnormPack16 && format->swapRedBlue) + if (format == gpu::format::R5G6B5Unorm) // B5G6R5 isn't generally supported by the swapchain and the format is used for R5G6B5 with swapped R/B channels to avoid aliasing so we reverse that by using R5G6B5 as the underlying Vulkan format for the swapchain which should be automatically handled by the driver for any copies from B5G6R5 textures and the data representation should be the same as B5G6R5 with swapped R/B channels so not reporting the correct texture::Format should be fine vkFormat = vk::Format::eR5G6B5UnormPack16; diff --git a/app/src/main/cpp/skyline/gpu/texture/format.h b/app/src/main/cpp/skyline/gpu/texture/format.h index b30d3013..819e679f 100644 --- a/app/src/main/cpp/skyline/gpu/texture/format.h +++ b/app/src/main/cpp/skyline/gpu/texture/format.h @@ -64,10 +64,21 @@ namespace skyline::gpu::format { FORMAT_NORM_INT_FLOAT(R16, 16, eR16); FORMAT_NORM_INT_SRGB(R8G8, 16, eR8G8); FORMAT(B5G6R5Unorm, 16, eB5G6R5UnormPack16); - FORMAT(R5G6B5Unorm, 16, eB5G6R5UnormPack16, .swapRedBlue = true); // Used by SurfaceFlinger - FORMAT(R4G4B4A4Unorm, 16, eR4G4B4A4UnormPack16); + FORMAT(R5G6B5Unorm, 16, eB5G6R5UnormPack16, .swizzleMapping = { + .r = vk::ComponentSwizzle::eB, + .b = vk::ComponentSwizzle::eR + }); // Used by SurfaceFlinger + FORMAT(R4G4B4A4Unorm, 16, eR4G4B4A4UnormPack16, .swizzleMapping = { + .r = vk::ComponentSwizzle::eA, + .g = vk::ComponentSwizzle::eB, + .b = vk::ComponentSwizzle::eG, + .a = vk::ComponentSwizzle::eR + }); FORMAT(B5G5R5A1Unorm, 16, eB5G5R5A1UnormPack16); - FORMAT(A1B5G5R5Unorm, 16, eA1R5G5B5UnormPack16, .swapRedBlue = true); + FORMAT(A1B5G5R5Unorm, 16, eA1R5G5B5UnormPack16, .swizzleMapping = { + .r = vk::ComponentSwizzle::eB, + .b = vk::ComponentSwizzle::eR + }); FORMAT_INT_FLOAT(R32, 32, eR32); FORMAT_NORM_INT_FLOAT(R16G16, 32, eR16G16); @@ -132,18 +143,29 @@ namespace skyline::gpu::format { ); // Depth/Stencil Formats - FORMAT(D16Unorm, 16, eD16Unorm, vka::eDepth); + // All of these have a G->R swizzle + FORMAT(D16Unorm, 16, eD16Unorm, vka::eDepth, .swizzleMapping = { + .g = vk::ComponentSwizzle::eR + }); - FORMAT(D32Float, 32, eD32Sfloat, vka::eDepth); + FORMAT(D32Float, 32, eD32Sfloat, vka::eDepth, .swizzleMapping = { + .g = vk::ComponentSwizzle::eR + }); FORMAT(D24UnormS8Uint, 32, eD24UnormS8Uint, .vkAspect = { vka::eStencil | vka::eDepth + }, .swizzleMapping = { + .g = vk::ComponentSwizzle::eR }); FORMAT(D32FloatS8Uint, 32, eD32SfloatS8Uint, .vkAspect = { vka::eStencil | vka::eDepth + }, .swizzleMapping = { + .g = vk::ComponentSwizzle::eR }); FORMAT(S8UintD24Unorm, 32, eD24UnormS8Uint, .vkAspect = { vka::eStencil | vka::eDepth - }, .stencilFirst = true); // TODO: Swizzle Depth/Stencil + }, .swizzleMapping = { + .g = vk::ComponentSwizzle::eR + }); #undef FORMAT diff --git a/app/src/main/cpp/skyline/gpu/texture/texture.h b/app/src/main/cpp/skyline/gpu/texture/texture.h index ec2ede2f..a06845bf 100644 --- a/app/src/main/cpp/skyline/gpu/texture/texture.h +++ b/app/src/main/cpp/skyline/gpu/texture/texture.h @@ -68,7 +68,12 @@ namespace skyline::gpu { vk::ImageAspectFlags vkAspect{vk::ImageAspectFlagBits::eColor}; u16 blockHeight{1}; //!< The height of a block in pixels u16 blockWidth{1}; //!< The width of a block in pixels - bool swapRedBlue{}; //!< Swap the red and blue channels, ignored on depth formats + vk::ComponentMapping swizzleMapping{ + .r = vk::ComponentSwizzle::eR, + .g = vk::ComponentSwizzle::eG, + .b = vk::ComponentSwizzle::eB, + .a = vk::ComponentSwizzle::eA + }; bool stencilFirst{}; //!< If the stencil channel is the first channel in the format constexpr bool IsCompressed() const { @@ -115,10 +120,6 @@ namespace skyline::gpu { return bpb == other.bpb && blockHeight == other.blockHeight && blockWidth == other.blockWidth; } - constexpr bool IsDepthOrStencil() const { - return bool{vkAspect & (vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil)}; - } - /** * @brief Determines the image aspect to use based off of the format and the first swizzle component */