From c32bec071cc4328ab51444b32b960226e5a590c3 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Wed, 10 Aug 2022 15:39:37 +0100 Subject: [PATCH] Adjust blit src{X,Y} to account for centred sampling before calling into helper shader Since the blit engine itself samples from pixel corners and the helper shader from pixel centres teh src coordinates need to be adjusted to avoid the helper shader wrapping round on the final column. --- .../main/cpp/skyline/gpu/interconnect/fermi_2d.cpp | 12 ++++++++---- .../main/cpp/skyline/gpu/interconnect/fermi_2d.h | 4 +++- .../cpp/skyline/soc/gm20b/engines/fermi/types.h | 10 ++++++++++ .../cpp/skyline/soc/gm20b/engines/fermi_2d.cpp | 7 ++++--- .../main/cpp/skyline/soc/gm20b/engines/fermi_2d.h | 14 ++------------ 5 files changed, 27 insertions(+), 20 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/interconnect/fermi_2d.cpp b/app/src/main/cpp/skyline/gpu/interconnect/fermi_2d.cpp index 8fac1a4f..7222cd3f 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/fermi_2d.cpp +++ b/app/src/main/cpp/skyline/gpu/interconnect/fermi_2d.cpp @@ -108,7 +108,7 @@ namespace skyline::gpu::interconnect { Fermi2D::Fermi2D(GPU &gpu, soc::gm20b::ChannelContext &channelCtx, gpu::interconnect::CommandExecutor &executor) : gpu(gpu), channelCtx(channelCtx), executor(executor) {} - void Fermi2D::Blit(const Surface &srcSurface, const Surface &dstSurface, float srcRectX, float srcRectY, u32 dstRectWidth, u32 dstRectHeight, u32 dstRectX, u32 dstRectY, float duDx, float dvDy, bool resolve, bool bilinearFilter) { + void Fermi2D::Blit(const Surface &srcSurface, const Surface &dstSurface, float srcRectX, float srcRectY, u32 dstRectWidth, u32 dstRectHeight, u32 dstRectX, u32 dstRectY, float duDx, float dvDy, SampleModeOrigin sampleOrigin, bool resolve, SampleModeFilter filter) { // TODO: When we support MSAA perform a resolve operation rather than blit when the `resolve` flag is set. auto srcGuestTexture{GetGuestTexture(srcSurface)}; auto dstGuestTexture{GetGuestTexture(dstSurface)}; @@ -120,13 +120,17 @@ namespace skyline::gpu::interconnect { auto dstTextureView{textureManager.FindOrCreate(dstGuestTexture, executor.tag)}; executor.AttachTexture(dstTextureView.get()); + // Blit shader always samples from centre so adjust if necessary + float centredSrcRectX{sampleOrigin == SampleModeOrigin::Corner ? srcRectX - 0.5f : srcRectX}; + float centredSrcRectY{sampleOrigin == SampleModeOrigin::Corner ? srcRectY - 0.5f : srcRectY}; + gpu.helperShaders.blitHelperShader.Blit( gpu, { .width = duDx * dstRectWidth, .height = dvDy * dstRectHeight, - .x = srcRectX, - .y = srcRectY, + .x = centredSrcRectX, + .y = centredSrcRectY, }, { .width = static_cast(dstRectWidth), @@ -136,7 +140,7 @@ namespace skyline::gpu::interconnect { }, srcGuestTexture.dimensions, dstGuestTexture.dimensions, duDx, dvDy, - bilinearFilter, + filter == SampleModeFilter::Bilinear, srcTextureView.get(), dstTextureView.get(), [=](auto &&executionCallback) { auto dst{dstTextureView.get()}; diff --git a/app/src/main/cpp/skyline/gpu/interconnect/fermi_2d.h b/app/src/main/cpp/skyline/gpu/interconnect/fermi_2d.h index 5dc82923..3aaf4260 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/fermi_2d.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/fermi_2d.h @@ -26,6 +26,8 @@ namespace skyline::gpu::interconnect { private: using IOVA = soc::gm20b::IOVA; using Surface = skyline::soc::gm20b::engine::fermi2d::type::Surface; + using SampleModeOrigin = skyline::soc::gm20b::engine::fermi2d::type::SampleModeOrigin; + using SampleModeFilter = skyline::soc::gm20b::engine::fermi2d::type::SampleModeFilter; GPU &gpu; soc::gm20b::ChannelContext &channelCtx; @@ -36,6 +38,6 @@ namespace skyline::gpu::interconnect { public: Fermi2D(GPU &gpu, soc::gm20b::ChannelContext &channelCtx, gpu::interconnect::CommandExecutor &executor); - void Blit(const Surface &srcSurface, const Surface &dstSurface, float srcRectX, float srcRectY, u32 dstRectWidth, u32 dstRectHeight, u32 dstRectX, u32 dstRectY, float duDx, float dvDy, bool resolve, bool bilinearFilter); + void Blit(const Surface &srcSurface, const Surface &dstSurface, float srcRectX, float srcRectY, u32 dstRectWidth, u32 dstRectHeight, u32 dstRectX, u32 dstRectY, float duDx, float dvDy, SampleModeOrigin sampleOrigin, bool resolve, SampleModeFilter filter); }; } diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/fermi/types.h b/app/src/main/cpp/skyline/soc/gm20b/engines/fermi/types.h index 5fd5c285..6524d7db 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/fermi/types.h +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/fermi/types.h @@ -89,5 +89,15 @@ namespace skyline::soc::gm20b::engine::fermi2d::type { Address address; }; + enum class SampleModeOrigin : u8 { + Center = 0, + Corner = 1 + }; + + enum class SampleModeFilter : u8 { + Point = 0, + Bilinear = 1 + }; + #pragma pack(pop) } diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/fermi_2d.cpp b/app/src/main/cpp/skyline/soc/gm20b/engines/fermi_2d.cpp index 75c9b816..69edceb9 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/fermi_2d.cpp +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/fermi_2d.cpp @@ -41,7 +41,7 @@ namespace skyline::soc::gm20b::engine::fermi2d { float duDx{fixedToFloating(pixelsFromMemory.duDx)}; float dvDy{fixedToFloating(pixelsFromMemory.dvDy)}; - if (registers.pixelsFromMemory->sampleMode.origin == Registers::PixelsFromMemory::SampleModeOrigin::Center) { + if (registers.pixelsFromMemory->sampleMode.origin == type::SampleModeOrigin::Center) { // This is an MSAA resolve operation, sampling from the center of each pixel in order to resolve the final image from the MSAA samples // MSAA images are stored in memory like regular images but each pixels dimensions are scaled: e.g for 2x2 MSAA /* 112233 @@ -61,8 +61,9 @@ namespace skyline::soc::gm20b::engine::fermi2d { pixelsFromMemory.dstWidth, pixelsFromMemory.dstHeight, pixelsFromMemory.dstX0, pixelsFromMemory.dstY0, duDx, dvDy, - registers.pixelsFromMemory->sampleMode.origin == Registers::PixelsFromMemory::SampleModeOrigin::Center, - pixelsFromMemory.sampleMode.filter == Registers::PixelsFromMemory::SampleModeFilter::Bilinear); + registers.pixelsFromMemory->sampleMode.origin, + registers.pixelsFromMemory->sampleMode.origin == type::SampleModeOrigin::Center, + pixelsFromMemory.sampleMode.filter); } } diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/fermi_2d.h b/app/src/main/cpp/skyline/soc/gm20b/engines/fermi_2d.h index def16b12..14b8c94c 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/fermi_2d.h +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/fermi_2d.h @@ -46,16 +46,6 @@ namespace skyline::soc::gm20b::engine::fermi2d { Shape16x4 = 2 }; - enum class SampleModeOrigin : u8 { - Center = 0, - Corner = 1 - }; - - enum class SampleModeFilter : u8 { - Point = 0, - Bilinear = 1 - }; - BlockShapeV blockShape : 3; u32 _pad0_ : 29; u16 corralSize : 10; @@ -63,9 +53,9 @@ namespace skyline::soc::gm20b::engine::fermi2d { bool safeOverlap : 1; u32 _pad2_ : 31; struct { - SampleModeOrigin origin : 1; + type::SampleModeOrigin origin : 1; u8 _pad0_ : 3; - SampleModeFilter filter : 1; + type::SampleModeFilter filter : 1; u32 _pad1_ : 27; } sampleMode;