diff --git a/Core/Config.cpp b/Core/Config.cpp index 623637999a..3e9b4d26d9 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -551,6 +551,7 @@ static ConfigSetting graphicsSettings[] = { ReportedConfigSetting("TexScalingLevel", &g_Config.iTexScalingLevel, 1, true, true), ReportedConfigSetting("TexScalingType", &g_Config.iTexScalingType, 0, true, true), ReportedConfigSetting("TexDeposterize", &g_Config.bTexDeposterize, false, true, true), + ReportedConfigSetting("TexRealtime", &g_Config.bRealtimeTexScaling, false, true, true), ConfigSetting("VSyncInterval", &g_Config.bVSync, false, true, true), ReportedConfigSetting("DisableStencilTest", &g_Config.bDisableStencilTest, false, true, true), ReportedConfigSetting("BloomHack", &g_Config.iBloomHack, 0, true, true), diff --git a/Core/Config.h b/Core/Config.h index edc88e4a19..b9f800c1fb 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -193,6 +193,7 @@ public: bool bSaveNewTextures; int iTexScalingLevel; // 1 = off, 2 = 2x, ..., 5 = 5x int iTexScalingType; // 0 = xBRZ, 1 = Hybrid + bool bRealtimeTexScaling; bool bTexDeposterize; int iFpsLimit; int iForceMaxEmulatedFPS; diff --git a/GPU/Common/ShaderCommon.h b/GPU/Common/ShaderCommon.h index 8de756237c..93e4464ea9 100644 --- a/GPU/Common/ShaderCommon.h +++ b/GPU/Common/ShaderCommon.h @@ -83,7 +83,9 @@ enum : uint64_t { DIRTY_BEZIERSPLINE = 1ULL << 32, DIRTY_TEXCLAMP = 1ULL << 33, - // space for 7 more uniforms. + DIRTY_TEXSIZE = 1ULL << 33, + + // space for 6 more uniforms. DIRTY_ALL_UNIFORMS = 0x3FFFFFFFFULL, DIRTY_ALL_LIGHTS = DIRTY_LIGHT0 | DIRTY_LIGHT1 | DIRTY_LIGHT2 | DIRTY_LIGHT3, diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index 5e0927410d..9d66faee5d 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -203,6 +203,14 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView ub->spline_type_u = gstate_c.spline_type_u; ub->spline_type_v = gstate_c.spline_type_v; } + + if (dirtyUniforms & DIRTY_TEXSIZE) { + ub->texSize[0] = (float)gstate_c.curTextureWidth; + ub->texSize[1] = (float)gstate_c.curTextureHeight; + ub->texSize[2] = 1.0f / (float)gstate_c.curTextureWidth; + ub->texSize[3] = 1.0f / (float)gstate_c.curTextureHeight; + } + } void LightUpdateUniforms(UB_VS_Lights *ub, uint64_t dirtyUniforms) { diff --git a/GPU/Common/ShaderUniforms.h b/GPU/Common/ShaderUniforms.h index 9e7d028c7a..e46abac0c9 100644 --- a/GPU/Common/ShaderUniforms.h +++ b/GPU/Common/ShaderUniforms.h @@ -11,7 +11,7 @@ enum : uint64_t { DIRTY_WORLDMATRIX | DIRTY_PROJTHROUGHMATRIX | DIRTY_VIEWMATRIX | DIRTY_TEXMATRIX | DIRTY_ALPHACOLORREF | DIRTY_PROJMATRIX | DIRTY_FOGCOLOR | DIRTY_FOGCOEF | DIRTY_TEXENV | DIRTY_STENCILREPLACEVALUE | DIRTY_ALPHACOLORMASK | DIRTY_SHADERBLEND | DIRTY_UVSCALEOFFSET | DIRTY_TEXCLAMP | DIRTY_DEPTHRANGE | DIRTY_MATAMBIENTALPHA | - DIRTY_BEZIERSPLINE, + DIRTY_BEZIERSPLINE | DIRTY_TEXSIZE, DIRTY_LIGHT_UNIFORMS = DIRTY_LIGHT0 | DIRTY_LIGHT1 | DIRTY_LIGHT2 | DIRTY_LIGHT3 | DIRTY_MATDIFFUSE | DIRTY_MATSPECULAR | DIRTY_MATEMISSIVE | DIRTY_AMBIENT, @@ -40,6 +40,7 @@ struct UB_VS_FS_Base { float blendFixB[4]; float texClamp[4]; float texClampOffset[4]; + float texSize[4]; }; static const char *ub_baseStr = @@ -65,6 +66,7 @@ R"( mat4 proj_mtx; vec3 blendFixB; vec4 texclamp; vec2 texclampoff; + vec4 texsize; )"; // HLSL code is shared so these names are changed to match those in DX9. @@ -91,6 +93,7 @@ R"( float4x4 u_proj; float3 u_blendFixB; float4 u_texclamp; float2 u_texclampoff; + float4 u_texSize; )"; // 512 bytes. Would like to shrink more. Some colors only have 8-bit precision and we expand diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 47bc10e9b8..aaf5cec2de 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -423,6 +423,7 @@ void TextureCacheCommon::SetTexture(bool force) { //got one! gstate_c.curTextureWidth = w; gstate_c.curTextureHeight = h; + gstate_c.Dirty(DIRTY_TEXSIZE); if (rehash) { // Update in case any of these changed. entry->sizeInRAM = (textureBitsPerPixel[format] * bufw * h / 2) / 8; @@ -842,6 +843,7 @@ void TextureCacheCommon::SetTextureFramebuffer(TexCacheEntry *entry, VirtualFram // We need to force it, since we may have set it on a texture before attaching. gstate_c.curTextureWidth = framebuffer->bufferWidth; gstate_c.curTextureHeight = framebuffer->bufferHeight; + gstate_c.Dirty(DIRTY_TEXSIZE); if (gstate_c.bgraTexture) { gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE); } else if ((gstate_c.curTextureXOffset == 0) != (fbInfo.xOffset == 0) || (gstate_c.curTextureYOffset == 0) != (fbInfo.yOffset == 0)) { @@ -909,35 +911,39 @@ bool TextureCacheCommon::SetOffsetTexture(u32 offset) { void TextureCacheCommon::NotifyConfigChanged() { int scaleFactor; - // 0 means automatic texture scaling, up to 5x, based on resolution. - if (g_Config.iTexScalingLevel == 0) { - scaleFactor = g_Config.iInternalResolution; - // Automatic resolution too? Okay. - if (scaleFactor == 0) { - if (!g_Config.IsPortrait()) { - scaleFactor = (PSP_CoreParameter().pixelWidth + 479) / 480; - } else { - scaleFactor = (PSP_CoreParameter().pixelHeight + 479) / 480; + if (g_Config.bRealtimeTexScaling) { + scaleFactor = 1; + } else { + // 0 means automatic texture scaling, up to 5x, based on resolution. + if (g_Config.iTexScalingLevel == 0) { + scaleFactor = g_Config.iInternalResolution; + // Automatic resolution too? Okay. + if (scaleFactor == 0) { + if (!g_Config.IsPortrait()) { + scaleFactor = (PSP_CoreParameter().pixelWidth + 479) / 480; + } else { + scaleFactor = (PSP_CoreParameter().pixelHeight + 479) / 480; + } + } + + scaleFactor = std::min(5, scaleFactor); + } else { + scaleFactor = g_Config.iTexScalingLevel; + } + + if (!gstate_c.Supports(GPU_SUPPORTS_OES_TEXTURE_NPOT)) { + // Reduce the scale factor to a power of two (e.g. 2 or 4) if textures must be a power of two. + while ((scaleFactor & (scaleFactor - 1)) != 0) { + --scaleFactor; } } - scaleFactor = std::min(5, scaleFactor); - } else { - scaleFactor = g_Config.iTexScalingLevel; - } - - if (!gstate_c.Supports(GPU_SUPPORTS_OES_TEXTURE_NPOT)) { - // Reduce the scale factor to a power of two (e.g. 2 or 4) if textures must be a power of two. - while ((scaleFactor & (scaleFactor - 1)) != 0) { - --scaleFactor; + // Just in case, small display with auto resolution or something. + if (scaleFactor <= 0) { + scaleFactor = 1; } } - // Just in case, small display with auto resolution or something. - if (scaleFactor <= 0) { - scaleFactor = 1; - } - standardScaleFactor_ = scaleFactor; replacer_.NotifyConfigChanged(); diff --git a/GPU/Common/TextureScalerCommon.cpp b/GPU/Common/TextureScalerCommon.cpp index 4299d8a7ff..b77dfad9cb 100644 --- a/GPU/Common/TextureScalerCommon.cpp +++ b/GPU/Common/TextureScalerCommon.cpp @@ -561,6 +561,9 @@ bool TextureScalerCommon::ScaleInto(u32 *outputBuf, u32 *src, u32 &dstFmt, int & case HYBRID: ScaleHybrid(factor, inputBuf, outputBuf, width, height); break; + case GAUSSIAN: + case COSINE: + // no cpu implementation for those, so fall back to bicubic case BICUBIC: ScaleBicubicMitchell(factor, inputBuf, outputBuf, width, height); break; diff --git a/GPU/Common/TextureScalerCommon.h b/GPU/Common/TextureScalerCommon.h index cf34381305..8074956811 100644 --- a/GPU/Common/TextureScalerCommon.h +++ b/GPU/Common/TextureScalerCommon.h @@ -31,7 +31,7 @@ public: bool Scale(u32 *&data, u32 &dstfmt, int &width, int &height, int factor); bool ScaleInto(u32 *out, u32 *src, u32 &dstfmt, int &width, int &height, int factor); - enum { XBRZ = 0, HYBRID = 1, BICUBIC = 2, HYBRID_BICUBIC = 3 }; + enum { XBRZ = 0, HYBRID = 1, BICUBIC = 2, HYBRID_BICUBIC = 3, GAUSSIAN = 4, COSINE = 5 }; protected: virtual void ConvertTo8888(u32 format, u32 *source, u32 *&dest, int width, int height) = 0; diff --git a/GPU/Directx9/PixelShaderGeneratorDX9.cpp b/GPU/Directx9/PixelShaderGeneratorDX9.cpp index 73bd6165e4..0caf177e74 100644 --- a/GPU/Directx9/PixelShaderGeneratorDX9.cpp +++ b/GPU/Directx9/PixelShaderGeneratorDX9.cpp @@ -22,6 +22,7 @@ #include "GPU/Directx9/PixelShaderGeneratorDX9.h" #include "GPU/ge_constants.h" #include "GPU/Common/GPUStateUtils.h" +#include "GPU/Common/TextureScalerCommon.h" #include "GPU/GPUState.h" #include "GPU/Common/ShaderUniforms.h" @@ -31,6 +32,249 @@ namespace DX9 { +static const char* sampler_default = + "float4 tex_sample(float2 coord) {\n" + " return tex_sample_direct(coord);\n" + "};\n"; + +static const char* sampler_hybrid = sampler_default; +static const char* sampler_bicubic = sampler_default; +static const char* sampler_hybrid_bicubic = sampler_default; +static const char* sampler_gaussian = + "#define sharpness 1.0\n" + "#define pi 3.14159265358\n" + "#define normalGauss(x) ((exp(-(x)*(x)*0.5))/sqrt(2.0*pi))\n" + "float normalGaussIntegral(float x)\n" + "{\n" + " float a1 = 0.4361836;\n" + " float a2 = -0.1201676;\n" + " float a3 = 0.9372980;\n" + " float p = 0.3326700;\n" + " float t = 1.0 / (1.0 + p*abs(x));\n" + "\n" + " return (0.5-normalGauss(x) * (t*(a1 + t*(a2 + a3*t))))*sign(x);\n" + "}\n" + "#define KERNEL(x,b) (normalGaussIntegral(sqrt(2*pi)*b*(x - 0.5)) - normalGaussIntegral(sqrt(2*pi)*b*(x + 0.5)))\n" + "\n" + "float4 tex_sample(float2 coord) {\n" + " float2 offset = frac(coord * u_texSize.xy) - 0.5;\n" + " float4 tempColor = 0.0;\n" + " float4 c;\n" + " float range = 2.0f;\n" + " float i,j;\n" + " float2 pos;\n" + " for (i = -range; i < range + 2.0; i++){\n" + " pos.x = offset.x - i;\n" + " for (j = -range; j REPLACE_BLEND_STANDARD) { if (replaceBlend == REPLACE_BLEND_COPY_FBO) { WRITE(p, "float2 u_fbotexSize : register(c%i);\n", CONST_PS_FBOTEXSIZE); @@ -147,6 +393,45 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag } WRITE(p, "};\n"); + if (doTexture) { + WRITE(p, "float4 tex_sample_direct(float2 coord) {\n"); + + if (lang == HLSL_D3D11 || lang == HLSL_D3D11_LEVEL9) { + WRITE(p, " return tex.Sample(samp, coord)%s;\n", bgraTexture ? ".bgra" : ""); + } else { + WRITE(p, " return tex2D(tex, coord)%s;\n", bgraTexture ? ".bgra" : ""); + } + WRITE(p, "};\n"); + + if(g_Config.bRealtimeTexScaling && g_Config.iTexScalingLevel != 1) { + switch (g_Config.iTexScalingType) { + case TextureScalerCommon::XBRZ: + WRITE(p, sampler_xbrz); + break; + case TextureScalerCommon::HYBRID: + WRITE(p, sampler_hybrid); + break; + case TextureScalerCommon::BICUBIC: + WRITE(p, sampler_bicubic); + break; + case TextureScalerCommon::HYBRID_BICUBIC: + WRITE(p, sampler_hybrid_bicubic); + break; + case TextureScalerCommon::GAUSSIAN: + WRITE(p, sampler_gaussian); + break; + case TextureScalerCommon::COSINE: + WRITE(p, sampler_cosine); + break; + default: + ERROR_LOG(G3D, "Unknown scaling type: %d", g_Config.iTexScalingType); + break; + } + } else { + WRITE(p, sampler_default); + } + } + if (lang == HLSL_DX9) { WRITE(p, "float4 main( PS_IN In ) : COLOR {\n"); } else { @@ -180,7 +465,10 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag } if (doTexture) { - const char *texcoord = "In.v_texcoord"; + const char *texcoord = "In.v_texcoord.xy"; + if (doTextureProjection) { + texcoord = "In.v_texcoord.xy / In.v_texcoord.z"; + } // TODO: Not sure the right way to do this for projection. if (needShaderTexClamp) { // We may be clamping inside a larger surface (tex = 64x64, buffer=480x272). @@ -210,23 +498,9 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag WRITE(p, " float2 fixedcoord = float2(%s, %s);\n", ucoord.c_str(), vcoord.c_str()); texcoord = "fixedcoord"; - // We already projected it. - doTextureProjection = false; } - if (lang == HLSL_D3D11 || lang == HLSL_D3D11_LEVEL9) { - if (doTextureProjection) { - WRITE(p, " float4 t = tex.Sample(samp, In.v_texcoord.xy / In.v_texcoord.z)%s;\n", bgraTexture ? ".bgra" : ""); - } else { - WRITE(p, " float4 t = tex.Sample(samp, %s.xy)%s;\n", texcoord, bgraTexture ? ".bgra" : ""); - } - } else { - if (doTextureProjection) { - WRITE(p, " float4 t = tex2Dproj(tex, float4(In.v_texcoord.x, In.v_texcoord.y, 0, In.v_texcoord.z))%s;\n", bgraTexture ? ".bgra" : ""); - } else { - WRITE(p, " float4 t = tex2D(tex, %s.xy)%s;\n", texcoord, bgraTexture ? ".bgra" : ""); - } - } + WRITE(p, " float4 t = tex_sample(%s);\n", texcoord); WRITE(p, " float4 p = In.v_color0;\n"); if (doTextureAlpha) { // texfmt == RGBA diff --git a/GPU/Directx9/PixelShaderGeneratorDX9.h b/GPU/Directx9/PixelShaderGeneratorDX9.h index 15623439ff..f845f5dcf8 100644 --- a/GPU/Directx9/PixelShaderGeneratorDX9.h +++ b/GPU/Directx9/PixelShaderGeneratorDX9.h @@ -38,4 +38,6 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag // For stencil upload #define CONST_PS_STENCILVALUE 10 +// For scaling filters +#define CONST_PS_TEXSIZE 11 }; diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index 10e128d620..b0a99e93dc 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -258,7 +258,7 @@ static void ConvertProjMatrixToD3DThrough(Matrix4x4 &in) { in.translateAndScale(Vec3(xoff, yoff, 0.5f), Vec3(1.0f, 1.0f, 0.5f)); } -const uint64_t psUniforms = DIRTY_TEXENV | DIRTY_ALPHACOLORREF | DIRTY_ALPHACOLORMASK | DIRTY_FOGCOLOR | DIRTY_STENCILREPLACEVALUE | DIRTY_SHADERBLEND | DIRTY_TEXCLAMP; +const uint64_t psUniforms = DIRTY_TEXENV | DIRTY_ALPHACOLORREF | DIRTY_ALPHACOLORMASK | DIRTY_FOGCOLOR | DIRTY_STENCILREPLACEVALUE | DIRTY_SHADERBLEND | DIRTY_TEXCLAMP | DIRTY_TEXSIZE; void ShaderManagerDX9::PSUpdateUniforms(u64 dirtyUniforms) { if (dirtyUniforms & DIRTY_TEXENV) { @@ -310,6 +310,16 @@ void ShaderManagerDX9::PSUpdateUniforms(u64 dirtyUniforms) { PSSetFloatArray(CONST_PS_TEXCLAMP, texclamp, 4); PSSetFloatArray(CONST_PS_TEXCLAMPOFF, texclampoff, 2); } + + if (dirtyUniforms & DIRTY_TEXSIZE) { + const float texSize[4] = { + (float)gstate_c.curTextureWidth, + (float)gstate_c.curTextureHeight, + 1.0f / (float)gstate_c.curTextureWidth, + 1.0f / (float)gstate_c.curTextureHeight, + }; + PSSetFloatArray(CONST_PS_TEXSIZE, texSize, 4); + } } const uint64_t vsUniforms = DIRTY_PROJMATRIX | DIRTY_PROJTHROUGHMATRIX | DIRTY_WORLDMATRIX | DIRTY_VIEWMATRIX | DIRTY_TEXMATRIX | diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 60eace01ac..8a03e53297 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1407,10 +1407,11 @@ void GPUCommon::Execute_TexSize0(u32 op, u32 diff) { // Don't reset it unless the size is different / the texture has changed. if (diff || gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS)) { gstate_c.curTextureWidth = gstate.getTextureWidth(0); - gstate_c.curTextureHeight = gstate.getTextureHeight(0); + gstate_c.curTextureHeight = gstate.getTextureHeight(0); gstate_c.Dirty(DIRTY_UVSCALEOFFSET); // We will need to reset the texture now. gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); + gstate_c.Dirty(DIRTY_TEXSIZE); } } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 8d803f913b..3fb3e8643f 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -378,7 +378,7 @@ void GameSettingsScreen::CreateViews() { }); texScalingChoice->SetDisabledPtr(&g_Config.bSoftwareRendering); - static const char *texScaleAlgos[] = { "xBRZ", "Hybrid", "Bicubic", "Hybrid + Bicubic", }; + static const char *texScaleAlgos[] = { "xBRZ", "Hybrid", "Bicubic", "Hybrid + Bicubic", "Gaussian", "Cosine"}; PopupMultiChoice *texScalingType = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iTexScalingType, gr->T("Upscale Type"), texScaleAlgos, 0, ARRAY_SIZE(texScaleAlgos), gr->GetName(), screenManager())); texScalingType->SetDisabledPtr(&g_Config.bSoftwareRendering); @@ -391,6 +391,15 @@ void GameSettingsScreen::CreateViews() { }); deposterize->SetDisabledPtr(&g_Config.bSoftwareRendering); + CheckBox *realtimeScaling = graphicsSettings->Add(new CheckBox(&g_Config.bRealtimeTexScaling, gr->T("Realtime Scaling"))); + realtimeScaling->OnClick.Add([=](EventParams &e) { + if (g_Config.bRealtimeTexScaling == true) { + settingInfo_->Show(gr->T("Realtime Scaling Tip", "GPU heavy - apply texture scaling filters with shaders during rendering"), e.v); + } + return UI::EVENT_CONTINUE; + }); + realtimeScaling->SetDisabledPtr(&g_Config.bSoftwareRendering); + graphicsSettings->Add(new ItemHeader(gr->T("Texture Filtering"))); static const char *anisoLevels[] = { "Off", "2x", "4x", "8x", "16x" }; PopupMultiChoice *anisoFiltering = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iAnisotropyLevel, gr->T("Anisotropic Filtering"), anisoLevels, 0, ARRAY_SIZE(anisoLevels), gr->GetName(), screenManager())); diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 6f5dcf48b6..c8cb04fa5a 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -927,6 +927,12 @@ void HandleGlobalMessage(const std::string &msg, const std::string &value) { } Reporting::UpdateConfig(); } + if (msg == "gpu_clearShaderCache") { + if (gpu) { + gpu->ClearShaderCache(); + } + Reporting::UpdateConfig(); + } if (msg == "core_powerSaving") { if (value != "false") { I18NCategory *sy = GetI18NCategory("System"); diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index caa5ae5511..f0fb114c1c 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -346,7 +346,10 @@ namespace MainWindow { TranslateMenuItem(menu, ID_TEXTURESCALING_HYBRID); TranslateMenuItem(menu, ID_TEXTURESCALING_BICUBIC); TranslateMenuItem(menu, ID_TEXTURESCALING_HYBRID_BICUBIC); + TranslateMenuItem(menu, ID_TEXTURESCALING_GAUSSIAN); + TranslateMenuItem(menu, ID_TEXTURESCALING_COSINE); TranslateMenuItem(menu, ID_TEXTURESCALING_DEPOSTERIZE); + TranslateMenuItem(menu, ID_TEXTURESCALING_REALTIME); TranslateMenuItem(menu, ID_OPTIONS_HARDWARETRANSFORM); TranslateMenuItem(menu, ID_OPTIONS_VERTEXCACHE); TranslateMenuItem(menu, ID_OPTIONS_SHOWFPS); @@ -481,6 +484,10 @@ namespace MainWindow { void setTexScalingMultiplier(int level) { g_Config.iTexScalingLevel = level; NativeMessageReceived("gpu_clearCache", ""); + + if(g_Config.bRealtimeTexScaling) { + NativeMessageReceived("gpu_clearShaderCache", ""); + } } static void setTexFiltering(int type) { @@ -494,6 +501,10 @@ namespace MainWindow { static void setTexScalingType(int type) { g_Config.iTexScalingType = type; NativeMessageReceived("gpu_clearCache", ""); + + if(g_Config.bRealtimeTexScaling) { + NativeMessageReceived("gpu_clearShaderCache", ""); + } } static void setRenderingMode(int mode) { @@ -759,6 +770,14 @@ namespace MainWindow { case ID_TEXTURESCALING_HYBRID: setTexScalingType(TextureScalerCommon::HYBRID); break; case ID_TEXTURESCALING_BICUBIC: setTexScalingType(TextureScalerCommon::BICUBIC); break; case ID_TEXTURESCALING_HYBRID_BICUBIC: setTexScalingType(TextureScalerCommon::HYBRID_BICUBIC); break; + case ID_TEXTURESCALING_GAUSSIAN: setTexScalingType(TextureScalerCommon::GAUSSIAN); break; + case ID_TEXTURESCALING_COSINE: setTexScalingType(TextureScalerCommon::COSINE); break; + + case ID_TEXTURESCALING_REALTIME: + g_Config.bRealtimeTexScaling = !g_Config.bRealtimeTexScaling; + NativeMessageReceived("gpu_clearShaderCache", ""); + NativeMessageReceived("gpu_clearCache", ""); + break; case ID_TEXTURESCALING_DEPOSTERIZE: g_Config.bTexDeposterize = !g_Config.bTexDeposterize; @@ -1065,6 +1084,7 @@ namespace MainWindow { CHECKITEM(ID_OPTIONS_PAUSE_FOCUS, g_Config.bPauseOnLostFocus); CHECKITEM(ID_EMULATION_SOUND, g_Config.bEnableSound); CHECKITEM(ID_TEXTURESCALING_DEPOSTERIZE, g_Config.bTexDeposterize); + CHECKITEM(ID_TEXTURESCALING_REALTIME, g_Config.bRealtimeTexScaling); CHECKITEM(ID_EMULATION_CHEATS, g_Config.bEnableCheats); CHECKITEM(ID_OPTIONS_IGNOREWINKEY, g_Config.bIgnoreWindowsKey); CHECKITEM(ID_FILE_DUMPFRAMES, g_Config.bDumpFrames); @@ -1172,12 +1192,14 @@ namespace MainWindow { ID_TEXTURESCALING_HYBRID, ID_TEXTURESCALING_BICUBIC, ID_TEXTURESCALING_HYBRID_BICUBIC, + ID_TEXTURESCALING_GAUSSIAN, + ID_TEXTURESCALING_COSINE, }; if (g_Config.iTexScalingType < TextureScalerCommon::XBRZ) g_Config.iTexScalingType = TextureScalerCommon::XBRZ; - else if (g_Config.iTexScalingType > TextureScalerCommon::HYBRID_BICUBIC) - g_Config.iTexScalingType = TextureScalerCommon::HYBRID_BICUBIC; + else if (g_Config.iTexScalingType > TextureScalerCommon::COSINE) + g_Config.iTexScalingType = TextureScalerCommon::COSINE; for (int i = 0; i < ARRAY_SIZE(texscalingtypeitems); i++) { CheckMenuItem(menu, texscalingtypeitems[i], MF_BYCOMMAND | ((i == g_Config.iTexScalingType) ? MF_CHECKED : MF_UNCHECKED)); diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 466752e4df..2ebd3889e7 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -612,8 +612,11 @@ BEGIN MENUITEM "Hybrid", ID_TEXTURESCALING_HYBRID MENUITEM "Bicubic", ID_TEXTURESCALING_BICUBIC MENUITEM "Hybrid + Bicubic", ID_TEXTURESCALING_HYBRID_BICUBIC + MENUITEM "Gaussian", ID_TEXTURESCALING_GAUSSIAN + MENUITEM "Cosine", ID_TEXTURESCALING_COSINE MENUITEM SEPARATOR MENUITEM "Deposterize", ID_TEXTURESCALING_DEPOSTERIZE + MENUITEM "Realtime Scaling", ID_TEXTURESCALING_REALTIME END MENUITEM "Hardware Transform", ID_OPTIONS_HARDWARETRANSFORM MENUITEM "Vertex Cache", ID_OPTIONS_VERTEXCACHE diff --git a/Windows/resource.h b/Windows/resource.h index ca52341e45..576580b64d 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -340,6 +340,10 @@ #define ID_OPTIONS_WINDOW9X 40175 #define ID_OPTIONS_WINDOW10X 40176 +#define ID_TEXTURESCALING_REALTIME 40177 +#define ID_TEXTURESCALING_GAUSSIAN 40178 +#define ID_TEXTURESCALING_COSINE 40179 + // Dummy option to let the buffered rendering hotkey cycle through all the options. #define ID_OPTIONS_BUFFEREDRENDERINGDUMMY 40500 #define IDC_STEPOUT 40501 diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 0759ffbd97..9d6d179da8 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -175,7 +175,8 @@ static RetroOption ppsspp_button_preference("ppsspp_button_preference", "Co static RetroOption ppsspp_fast_memory("ppsspp_fast_memory", "Fast Memory (Speedhack)", true); static RetroOption ppsspp_block_transfer_gpu("ppsspp_block_transfer_gpu", "Block Transfer GPU", true); static RetroOption ppsspp_texture_scaling_level("ppsspp_texture_scaling_level", "Texture Scaling Level", { { "1", 1 }, { "2", 2 }, { "3", 3 }, { "4", 4 }, { "5", 5 }, { "0", 0 } }); -static RetroOption ppsspp_texture_scaling_type("ppsspp_texture_scaling_type", "Texture Scaling Type", { { "xbrz", TextureScalerCommon::XBRZ }, { "hybrid", TextureScalerCommon::HYBRID }, { "bicubic", TextureScalerCommon::BICUBIC }, { "hybrid_bicubic", TextureScalerCommon::HYBRID_BICUBIC } }); +static RetroOption ppsspp_texture_scaling_type("ppsspp_texture_scaling_type", "Texture Scaling Type", { { "xbrz", TextureScalerCommon::XBRZ }, { "hybrid", TextureScalerCommon::HYBRID }, { "bicubic", TextureScalerCommon::BICUBIC }, { "hybrid_bicubic", TextureScalerCommon::HYBRID_BICUBIC }, { "gaussian", TextureScalerCommon::GAUSSIAN }, { "cosine", TextureScalerCommon::COSINE } }); +static RetroOption ppsspp_texture_scaling_realtime("ppsspp_texture_scaling_realtime", "Realtime Texture Scaling", false); static RetroOption ppsspp_texture_anisotropic_filtering("ppsspp_texture_anisotropic_filtering", "Anisotropic Filtering", { "off", "1x", "2x", "4x", "8x", "16x" }); static RetroOption ppsspp_texture_deposterize("ppsspp_texture_deposterize", "Texture Deposterize", false); static RetroOption ppsspp_gpu_hardware_transform("ppsspp_gpu_hardware_transform", "GPU Hardware T&L", true); @@ -204,6 +205,7 @@ void retro_set_environment(retro_environment_t cb) { vars.push_back(ppsspp_texture_scaling_type.GetOptions()); vars.push_back(ppsspp_texture_anisotropic_filtering.GetOptions()); vars.push_back(ppsspp_texture_deposterize.GetOptions()); + vars.push_back(ppsspp_texture_scaling_realtime.GetOptions()); vars.push_back(ppsspp_gpu_hardware_transform.GetOptions()); vars.push_back(ppsspp_vertex_cache.GetOptions()); vars.push_back(ppsspp_separate_io_thread.GetOptions()); @@ -293,12 +295,13 @@ static void check_variables(CoreParameter &coreParam) { } } - if (ppsspp_texture_scaling_type.Update(&g_Config.iTexScalingType) && gpu) { - gpu->ClearCacheNextFrame(); - } - - if (ppsspp_texture_scaling_level.Update(&g_Config.iTexScalingLevel) && gpu) { + bool clear_cache = ppsspp_texture_scaling_type.Update(&g_Config.iTexScalingType); + clear_cache |= ppsspp_texture_scaling_level.Update(&g_Config.iTexScalingLevel); + clear_cache |= ppsspp_texture_scaling_realtime.Update(&g_Config.bRealtimeTexScaling); + if (clear_cache && gpu) { gpu->ClearCacheNextFrame(); + gpu->ClearShaderCache(); + gpu->Resized(); } }