From 2c697ec36ae5651e6fc5f029cae482fa8607931f Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Mon, 11 Apr 2022 23:42:36 +0100 Subject: [PATCH] Determine depth/stencil texture aspect based off of image swizzle Required since we can't have a non-rt image with both a depth/stencil aspect at the same time according to vk spec. --- .../gpu/interconnect/graphics_context.h | 7 ++++++ app/src/main/cpp/skyline/gpu/texture/format.h | 2 +- .../main/cpp/skyline/gpu/texture/texture.h | 24 ++++++++++++++++--- .../main/cpp/skyline/gpu/texture_manager.cpp | 4 ++-- 4 files changed, 31 insertions(+), 6 deletions(-) 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 1b7c15ff..ccb45487 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h @@ -268,6 +268,9 @@ namespace skyline::gpu::interconnect { #undef FORMAT_SAME_NORM_INT_FLOAT_CASE }(); + if (renderTarget.guest.format) + renderTarget.guest.aspect = renderTarget.guest.format->vkAspect; + if (renderTarget.guest.tileConfig.mode == texture::TileMode::Linear && renderTarget.guest.format) renderTarget.guest.dimensions.width = renderTarget.widthBytes / renderTarget.guest.format->bpb; @@ -294,6 +297,9 @@ namespace skyline::gpu::interconnect { } }(); + if (depthRenderTarget.guest.format) + depthRenderTarget.guest.aspect = depthRenderTarget.guest.format->vkAspect; + if (depthRenderTarget.guest.tileConfig.mode == texture::TileMode::Linear && depthRenderTarget.guest.format) depthRenderTarget.guest.dimensions.width = depthRenderTarget.widthBytes / depthRenderTarget.guest.format->bpb; @@ -1999,6 +2005,7 @@ namespace skyline::gpu::interconnect { // If the entry didn't exist prior then we need to convert the TIC to a GuestTexture 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); diff --git a/app/src/main/cpp/skyline/gpu/texture/format.h b/app/src/main/cpp/skyline/gpu/texture/format.h index bdf0e70a..b30d3013 100644 --- a/app/src/main/cpp/skyline/gpu/texture/format.h +++ b/app/src/main/cpp/skyline/gpu/texture/format.h @@ -143,7 +143,7 @@ namespace skyline::gpu::format { }); FORMAT(S8UintD24Unorm, 32, eD24UnormS8Uint, .vkAspect = { vka::eStencil | vka::eDepth - }); // TODO: Swizzle Depth/Stencil + }, .stencilFirst = true); // TODO: Swizzle Depth/Stencil #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 7e623408..ec2ede2f 100644 --- a/app/src/main/cpp/skyline/gpu/texture/texture.h +++ b/app/src/main/cpp/skyline/gpu/texture/texture.h @@ -69,6 +69,7 @@ namespace skyline::gpu { 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 + bool stencilFirst{}; //!< If the stencil channel is the first channel in the format constexpr bool IsCompressed() const { return (blockHeight != 1) || (blockWidth != 1); @@ -115,7 +116,21 @@ namespace skyline::gpu { } constexpr bool IsDepthOrStencil() const { - return bool(vkAspect & (vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil)); + 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 + */ + constexpr vk::ImageAspectFlags Aspect(bool first) const { + if (vkAspect & vk::ImageAspectFlagBits::eDepth && vkAspect & vk::ImageAspectFlagBits::eStencil) { + if (first) + return stencilFirst ? vk::ImageAspectFlagBits::eStencil : vk::ImageAspectFlagBits::eDepth; + else + return stencilFirst ? vk::ImageAspectFlagBits::eDepth : vk::ImageAspectFlagBits::eStencil; + } else { + return vkAspect; + } } }; @@ -226,6 +241,7 @@ namespace skyline::gpu { u16 layerCount{}; u32 layerStride{}; //!< An optional hint regarding the size of a single layer, it will be set to 0 when not available, GetLayerSize() should be used to retrieve this value vk::ComponentMapping swizzle{}; //!< Component swizzle derived from format requirements and the guest supplied swizzle + vk::ImageAspectFlags aspect{}; GuestTexture() {} @@ -237,7 +253,8 @@ namespace skyline::gpu { type(type), baseArrayLayer(baseArrayLayer), layerCount(layerCount), - layerStride(layerStride) {} + layerStride(layerStride), + aspect(format->vkAspect) {} GuestTexture(span mapping, texture::Dimensions dimensions, texture::Format format, texture::TileConfig tileConfig, texture::TextureType type, u16 baseArrayLayer = 0, u16 layerCount = 1, u32 layerStride = 0) : mappings(1, mapping), @@ -247,7 +264,8 @@ namespace skyline::gpu { type(type), baseArrayLayer(baseArrayLayer), layerCount(layerCount), - layerStride(layerStride) {} + layerStride(layerStride), + aspect(format->vkAspect) {} /** * @note Requires `dimensions`, `format` and `tileConfig` to be filled in diff --git a/app/src/main/cpp/skyline/gpu/texture_manager.cpp b/app/src/main/cpp/skyline/gpu/texture_manager.cpp index f72e6735..22009397 100644 --- a/app/src/main/cpp/skyline/gpu/texture_manager.cpp +++ b/app/src/main/cpp/skyline/gpu/texture_manager.cpp @@ -48,7 +48,7 @@ namespace skyline::gpu { if (matchGuestTexture.format->IsCompatible(*guestTexture.format) && matchGuestTexture.dimensions == guestTexture.dimensions && matchGuestTexture.tileConfig == guestTexture.tileConfig) { auto &texture{hostMapping->texture}; return texture->GetView(static_cast(guestTexture.type), vk::ImageSubresourceRange{ - .aspectMask = guestTexture.format->vkAspect, + .aspectMask = guestTexture.aspect, .levelCount = texture->mipLevels, .layerCount = texture->layerCount, }, guestTexture.format, guestTexture.swizzle); @@ -80,7 +80,7 @@ namespace skyline::gpu { } return texture->GetView(static_cast(guestTexture.type), vk::ImageSubresourceRange{ - .aspectMask = guestTexture.format->vkAspect, + .aspectMask = guestTexture.aspect, .levelCount = texture->mipLevels, .layerCount = texture->layerCount, }, guestTexture.format, guestTexture.swizzle);