From 5481eae677e1b306bec4fc7a40881e7e6f72c6c5 Mon Sep 17 00:00:00 2001 From: pizzzza19 Date: Sat, 18 Jul 2026 21:39:13 +0900 Subject: [PATCH 1/2] [GSH_VulkanPresent.cpp] bilinear interpolation in Vulkan Unlike OpenGL, previous builds did not bilinear interpolation but just choose one address per pixel from memory buffer. This caused lack of smoothing of display. Now added bilinear interpolation to Vulkan and look similar to OpenGL. --- Source/gs/GSH_Vulkan/GSH_VulkanPresent.cpp | 88 +++++++++++++++------- 1 file changed, 61 insertions(+), 27 deletions(-) diff --git a/Source/gs/GSH_Vulkan/GSH_VulkanPresent.cpp b/Source/gs/GSH_Vulkan/GSH_VulkanPresent.cpp index d9f2045a71..ba3ed7c254 100644 --- a/Source/gs/GSH_Vulkan/GSH_VulkanPresent.cpp +++ b/Source/gs/GSH_Vulkan/GSH_VulkanPresent.cpp @@ -732,33 +732,67 @@ Framework::Vulkan::CShaderModule CPresent::CreateFragmentShader(const PIPELINE_C auto bufAddress = presentBufParams->x(); auto bufWidth = presentBufParams->y(); auto layerSize = presentRectParams->zw(); - - auto screenPos = ToInt(inputTexCoord->xy() * ToFloat(layerSize)); - - switch(caps.bufPsm) - { - default: - assert(false); - [[fallthrough]]; - case CGSHandler::PSMCT32: - case CGSHandler::PSMCT24: - { - auto address = CMemoryUtils::GetPixelAddress( - b, swizzleTable, bufAddress, bufWidth, screenPos); - auto imageColor = CMemoryUtils::Memory_Read32(b, memoryBuffer, address); - outputColor = CMemoryUtils::PSM32ToVec4(b, imageColor); - } - break; - case CGSHandler::PSMCT16: - case CGSHandler::PSMCT16S: - { - auto address = CMemoryUtils::GetPixelAddress( - b, swizzleTable, bufAddress, bufWidth, screenPos); - auto imageColor = CMemoryUtils::Memory_Read16(b, memoryBuffer, address); - outputColor = CMemoryUtils::PSM16ToVec4(b, imageColor); - } - break; - } + auto maxPos = NewInt2(layerSize->x() - NewInt(b, 1), layerSize->y() - NewInt(b, 1)); + auto ReadTexel = [&](Nuanceur::CInt2Value rawPos) -> Nuanceur::CFloat4Rvalue { + auto pos = NewInt2( + Clamp(rawPos->x(), NewInt(b, 0), maxPos->x()), + Clamp(rawPos->y(), NewInt(b, 0), maxPos->y())); + switch(caps.bufPsm) + { + default: + assert(false); + [[fallthrough]]; + case CGSHandler::PSMCT32: + case CGSHandler::PSMCT24: + { + auto address = CMemoryUtils::GetPixelAddress( + b, swizzleTable, bufAddress, bufWidth, pos); + auto imageColor = CMemoryUtils::Memory_Read32(b, memoryBuffer, address); + return CMemoryUtils::PSM32ToVec4(b, imageColor); + } + case CGSHandler::PSMCT16: + case CGSHandler::PSMCT16S: + { + auto address = CMemoryUtils::GetPixelAddress( + b, swizzleTable, bufAddress, bufWidth, pos); + auto imageColor = CMemoryUtils::Memory_Read16(b, memoryBuffer, address); + return CMemoryUtils::PSM16ToVec4(b, imageColor); + } + } + }; + + auto rawPosF = inputTexCoord->xy() * ToFloat(layerSize); + auto half = NewFloat(b, 0.5f); + auto srcPosF = NewFloat2(rawPosF->x() - half, rawPosF->y() - half); + auto basePos = ToInt(srcPosF); + auto frac = Fract(srcPosF); + auto fx = frac->x(); + auto fy = frac->y(); + + auto posX1Y0 = NewInt2(basePos->x() + NewInt(b, 1), basePos->y()); + auto posX0Y1 = NewInt2(basePos->x(), basePos->y() + NewInt(b, 1)); + auto posX1Y1 = NewInt2(basePos->x() + NewInt(b, 1), basePos->y() + NewInt(b, 1)); + + auto c00 = ReadTexel(basePos); + auto c10 = ReadTexel(posX1Y0); + auto c01 = ReadTexel(posX0Y1); + auto c11 = ReadTexel(posX1Y1); + + auto one = NewFloat(b, 1.0f); + auto oneMinusFx = one - fx; + auto oneMinusFy = one - fy; + + auto w00 = oneMinusFx * oneMinusFy; + auto w10 = fx * oneMinusFy; + auto w01 = oneMinusFx * fy; + auto w11 = fx * fy; + + auto Broadcast4 = [&](Nuanceur::CFloatValue w) -> Nuanceur::CFloat4Rvalue { + return NewFloat4(w, w, w, w); + }; + + outputColor = (c00 * Broadcast4(w00)) + (c10 * Broadcast4(w10)) + + (c01 * Broadcast4(w01)) + (c11 * Broadcast4(w11)); } Framework::CMemStream shaderStream; From 5650e7fa301475f8f55ced7658cf18573b15869b Mon Sep 17 00:00:00 2001 From: pizzzza19 Date: Sat, 18 Jul 2026 21:50:00 +0900 Subject: [PATCH 2/2] [GSHandler.cpp] Correct size CRT_MODE_HDTV_480P 480P display aspect rate should be 4:3 (ITU-R BT.601) and pixel aspect 8:9. For System 246 games display aspect rate was incorrect that can see wider than actual CRT display. --- Source/gs/GSHandler.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/gs/GSHandler.cpp b/Source/gs/GSHandler.cpp index 57e58ba9c2..5a2cd1dc16 100644 --- a/Source/gs/GSHandler.cpp +++ b/Source/gs/GSHandler.cpp @@ -198,6 +198,13 @@ CGSHandler::PRESENTATION_VIEWPORT CGSHandler::GetPresentationViewport() const { PRESENTATION_VIEWPORT viewport; auto sourceSize = std::make_pair(GetCrtWidth(), GetCrtHeight()); + + //720x480(HDTV_480P) should be 4:3 + if(m_crtMode == CRT_MODE_HDTV_480P) + { + sourceSize = std::make_pair(640u, 480u); + } + if(CAppConfig::GetInstance().GetPreferenceBoolean(PREF_CGSHANDLER_WIDESCREEN)) { sourceSize = std::make_pair(1920, 1080);