diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index 3b8a42f8a..b4d764d56 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -1683,13 +1683,13 @@ bool GPU::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_sm case DisplayScalingMode::BilinearSmooth: case DisplayScalingMode::BilinearInteger: - fs = shadergen.GenerateDisplayFragmentShader(true); + fs = shadergen.GenerateDisplayFragmentShader(true, false); break; case DisplayScalingMode::Nearest: case DisplayScalingMode::NearestInteger: default: - fs = shadergen.GenerateDisplayFragmentShader(false); + fs = shadergen.GenerateDisplayFragmentShader(false, true); break; } diff --git a/src/core/gpu_shadergen.cpp b/src/core/gpu_shadergen.cpp index 6c9400c7f..dfe544d2e 100644 --- a/src/core/gpu_shadergen.cpp +++ b/src/core/gpu_shadergen.cpp @@ -48,17 +48,27 @@ std::string GPUShaderGen::GenerateDisplayVertexShader() return ss.str(); } -std::string GPUShaderGen::GenerateDisplayFragmentShader(bool clamp_uv) +std::string GPUShaderGen::GenerateDisplayFragmentShader(bool clamp_uv, bool nearest) { std::stringstream ss; WriteHeader(ss); WriteDisplayUniformBuffer(ss); DeclareTexture(ss, "samp0", 0); DeclareFragmentEntryPoint(ss, 0, 1); + ss << "{\n"; + if (clamp_uv) - ss << "{\n o_col0 = float4(SAMPLE_TEXTURE(samp0, ClampUV(v_tex0)).rgb, 1.0f);\n }"; + ss << " float2 uv = ClampUV(v_tex0);\n"; else - ss << "{\n o_col0 = float4(SAMPLE_TEXTURE(samp0, v_tex0).rgb, 1.0f);\n }"; + ss << " float2 uv = v_tex0;\n"; + + // Work around nearest sampling precision issues on AMD graphics cards by adding 1/128 to UVs. + if (nearest) + ss << " o_col0 = float4(LOAD_TEXTURE(samp0, int2((uv * u_src_size.xy) + (1.0 / 128.0)), 0).rgb, 1.0f);\n"; + else + ss << " o_col0 = float4(SAMPLE_TEXTURE(samp0, ClampUV(v_tex0)).rgb, 1.0f);\n"; + + ss << "}\n"; return ss.str(); } diff --git a/src/core/gpu_shadergen.h b/src/core/gpu_shadergen.h index f3be9832a..525de29c2 100644 --- a/src/core/gpu_shadergen.h +++ b/src/core/gpu_shadergen.h @@ -12,7 +12,7 @@ public: ~GPUShaderGen(); std::string GenerateDisplayVertexShader(); - std::string GenerateDisplayFragmentShader(bool clamp_uv); + std::string GenerateDisplayFragmentShader(bool clamp_uv, bool nearest); std::string GenerateDisplaySharpBilinearFragmentShader(); std::string GenerateInterleavedFieldExtractFragmentShader();