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;