add "real-time texture scaling" option.

This commit is contained in:
aliaspider committed 2018-03-27 23:53:21 +01:00
1 parent 29de4b5a18
commit 45830d7cdc
18 files changed
+412 -54

No files matched your search

+1
View File
@@ -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),
+1
View File
@@ -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;
+3 -1
View File
@@ -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,
+8
View File
@@ -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) {
+4 -1
View File
@@ -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
+29 -23
View File
@@ -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();
+3
View File
@@ -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;
+1 -1
View File
@@ -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;
+291 -17
View File
@@ -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<range+2.0 ;j++){\n"
" pos.y = offset.y - j;\n"
" c=tex_sample_direct(coord - pos * u_texSize.zw).rgba;\n"
" tempColor+=c*KERNEL(pos.x,sharpness)*KERNEL(pos.y,sharpness);\n"
" }\n"
" }\n"
" tempColor=clamp(tempColor,0.0,1.0);\n"
" return tempColor;\n"
"};\n";
static const char* sampler_cosine =
"#define sharpness 1.0\n"
"#define pi 3.14159265358\n"
"#define a(x) abs(x)\n"
"#define d(x,b) (pi*b*min(a(x)+0.5,1.0/b))\n"
"#define e(x,b) (pi*b*min(max(a(x)-0.5,-1.0/b),1.0/b))\n"
"#define KERNEL(x,b) ((d(x,b)+sin(d(x,b))-e(x,b)-sin(e(x,b)))/(2.0*pi))\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<range+2.0 ;j++){\n"
" pos.y = offset.y - j;\n"
" c=tex_sample_direct(coord - pos * u_texSize.zw).rgba;\n"
" tempColor+=c*KERNEL(pos.x,sharpness)*KERNEL(pos.y,sharpness);\n"
" }\n"
" }\n"
" tempColor=clamp(tempColor,0.0,1.0);\n"
" return tempColor;\n"
"};\n";
static const char* sampler_xbrz =
"float c_df(float4 c1, float4 c2) {\n"
" float4 df = abs(c1 - c2);\n"
" return df.r + df.g + df.b + df.a;\n"
"}\n"
"\n"
"static const float coef = 2.0;\n"
"\n"
"static const float4 rgbw = float4(14.352, 28.176, 5.472, 15.0);\n"
"static const float4 eq_threshold = float4(15.0, 15.0, 15.0, 15.0);\n"
"\n"
"static const float4 delta = float4(1.0/4., 1.0/4., 1.0/4., 1.0/4.);\n"
"static const float4 delta_l = float4(0.5/4., 1.0/4., 0.5/4., 1.0/4.);\n"
"static const float4 delta_u = delta_l.yxwz;\n"
"\n"
"static const float4 Ao = float4( 1.0, -1.0, -1.0, 1.0 );\n"
"static const float4 Bo = float4( 1.0, 1.0, -1.0,-1.0 );\n"
"static const float4 Co = float4( 1.5, 0.5, -0.5, 0.5 );\n"
"static const float4 Ax = float4( 1.0, -1.0, -1.0, 1.0 );\n"
"static const float4 Bx = float4( 0.5, 2.0, -0.5,-2.0 );\n"
"static const float4 Cx = float4( 1.0, 1.0, -0.5, 0.0 );\n"
"static const float4 Ay = float4( 1.0, -1.0, -1.0, 1.0 );\n"
"static const float4 By = float4( 2.0, 0.5, -2.0,-0.5 );\n"
"static const float4 Cy = float4( 2.0, 0.0, -1.0, 0.5 );\n"
"static const float4 Ci = float4(0.25, 0.25, 0.25, 0.25);\n"
"\n"
"// Difference between vector components.\n"
"float4 df(float4 A, float4 B)\n"
"{\n"
" return float4(abs(A-B));\n"
"}\n"
"\n"
"// Compare two vectors and return their components are different.\n"
"float4 diff(float4 A, float4 B)\n"
"{\n"
" return step(0.001, df(A, B));\n"
"}\n"
"\n"
"// Determine if two vector components are equal based on a threshold.\n"
"float4 eq(float4 A, float4 B)\n"
"{\n"
" return step(df(A, B), 15.);\n"
"}\n"
"\n"
"// Determine if two vector components are NOT equal based on a threshold.\n"
"float4 neq(float4 A, float4 B)\n"
"{\n"
" return (float4(1.0, 1.0, 1.0, 1.0) - eq(A, B));\n"
"}\n"
"\n"
"// Weighted distance.\n"
"float4 wd(float4 a, float4 b, float4 c, float4 d, float4 e, float4 f, float4 g, float4 h)\n"
"{\n"
" return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h));\n"
"}\n"
"\n"
"float4 tex_sample(float2 coord)\n"
"{\n"
" float2 tc = coord * u_texSize.xy;\n"
" float2 fp = frac(tc);\n"
" tc = floor(tc) + 0.5;\n"
"\n"
" float4 xyp_1_2_3 = tc.xxxy + float4(-1., 0., 1., -2.);\n"
" float4 xyp_6_7_8 = tc.xxxy + float4(-1., 0., 1., -1.);\n"
" float4 xyp_11_12_13 = tc.xxxy + float4(-1., 0., 1., 0.);\n"
" float4 xyp_16_17_18 = tc.xxxy + float4(-1., 0., 1., 1.);\n"
" float4 xyp_21_22_23 = tc.xxxy + float4(-1., 0., 1., 2.);\n"
" float4 xyp_5_10_15 = tc.xyyy + float4(-2., -1., 0., 1.);\n"
" float4 xyp_9_14_9 = tc.xyyy + float4( 2., -1., 0., 1.);\n"
"\n"
" float4 edri;\n"
" float4 edr;\n"
" float4 edr_l;\n"
" float4 edr_u;\n"
" float4 px; // px = pixel, edr = edge detection rule\n"
" float4 irlv0;\n"
" float4 irlv1;\n"
" float4 irlv2l;\n"
" float4 irlv2u;\n"
" float4 block_3d;\n"
" float4 fx;\n"
" float4 fx_l;\n"
" float4 fx_u; // inequations of straight lines.\n"
"\n"
"\n"
" float4 A1 = tex_sample_direct(u_texSize.zw * xyp_1_2_3.xw );\n"
" float4 B1 = tex_sample_direct(u_texSize.zw * xyp_1_2_3.yw );\n"
" float4 C1 = tex_sample_direct(u_texSize.zw * xyp_1_2_3.zw );\n"
" float4 A = tex_sample_direct(u_texSize.zw * xyp_6_7_8.xw );\n"
" float4 B = tex_sample_direct(u_texSize.zw * xyp_6_7_8.yw );\n"
" float4 C = tex_sample_direct(u_texSize.zw * xyp_6_7_8.zw );\n"
" float4 D = tex_sample_direct(u_texSize.zw * xyp_11_12_13.xw );\n"
" float4 E = tex_sample_direct(u_texSize.zw * xyp_11_12_13.yw );\n"
" float4 F = tex_sample_direct(u_texSize.zw * xyp_11_12_13.zw );\n"
" float4 G = tex_sample_direct(u_texSize.zw * xyp_16_17_18.xw );\n"
" float4 H = tex_sample_direct(u_texSize.zw * xyp_16_17_18.yw );\n"
" float4 I = tex_sample_direct(u_texSize.zw * xyp_16_17_18.zw );\n"
" float4 G5 = tex_sample_direct(u_texSize.zw * xyp_21_22_23.xw );\n"
" float4 H5 = tex_sample_direct(u_texSize.zw * xyp_21_22_23.yw );\n"
" float4 I5 = tex_sample_direct(u_texSize.zw * xyp_21_22_23.zw );\n"
" float4 A0 = tex_sample_direct(u_texSize.zw * xyp_5_10_15.xy );\n"
" float4 D0 = tex_sample_direct(u_texSize.zw * xyp_5_10_15.xz );\n"
" float4 G0 = tex_sample_direct(u_texSize.zw * xyp_5_10_15.xw );\n"
" float4 C4 = tex_sample_direct(u_texSize.zw * xyp_9_14_9.xy );\n"
" float4 F4 = tex_sample_direct(u_texSize.zw * xyp_9_14_9.xz );\n"
" float4 I4 = tex_sample_direct(u_texSize.zw * xyp_9_14_9.xw );\n"
"\n"
" float4 b = float4(dot(B ,rgbw), dot(D ,rgbw), dot(H ,rgbw), dot(F ,rgbw));\n"
" float4 c = float4(dot(C ,rgbw), dot(A ,rgbw), dot(G ,rgbw), dot(I ,rgbw));\n"
" float4 d = b.yzwx;\n"
" float4 e = dot(E,rgbw).xxxx;\n"
" float4 f = b.wxyz;\n"
" float4 g = c.zwxy;\n"
" float4 h = b.zwxy;\n"
" float4 i = c.wxyz;\n"
" float4 i4 = float4(dot(I4,rgbw), dot(C1,rgbw), dot(A0,rgbw), dot(G5,rgbw));\n"
" float4 i5 = float4(dot(I5,rgbw), dot(C4,rgbw), dot(A1,rgbw), dot(G0,rgbw));\n"
" float4 h5 = float4(dot(H5,rgbw), dot(F4,rgbw), dot(B1,rgbw), dot(D0,rgbw));\n"
" float4 f4 = h5.yzwx;\n"
"\n"
" // These inequations define the line below which interpolation occurs.\n"
" fx = (Ao*fp.y+Bo*fp.x);\n"
" fx_l = (Ax*fp.y+Bx*fp.x);\n"
" fx_u = (Ay*fp.y+By*fp.x);\n"
"\n"
" irlv1 = irlv0 = diff(e,f) * diff(e,h);\n"
"\n"
" irlv1 = (irlv0 * ( neq(f,b) * neq(f,c) + neq(h,d) * neq(h,g) + eq(e,i) * (neq(f,f4) * neq(f,i4) + neq(h,h5) * neq(h,i5)) + eq(e,g) + eq(e,c)) );\n"
"\n"
" irlv2l = diff(e,g) * diff(d,g);\n"
" irlv2u = diff(e,c) * diff(b,c);\n"
"\n"
" float4 fx45i = clamp((fx + delta -Co - Ci)/(2.0*delta ), 0.0, 1.0);\n"
" float4 fx45 = clamp((fx + delta -Co )/(2.0*delta ), 0.0, 1.0);\n"
" float4 fx30 = clamp((fx_l + delta_l -Cx )/(2.0*delta_l), 0.0, 1.0);\n"
" float4 fx60 = clamp((fx_u + delta_u -Cy )/(2.0*delta_u), 0.0, 1.0);\n"
"\n"
" float4 wd1 = wd( e, c, g, i, h5, f4, h, f);\n"
" float4 wd2 = wd( h, d, i5, f, i4, b, e, i);\n"
"\n"
" edri = step(wd1, wd2) * irlv0;\n"
" edr = step(wd1 + float4(0.1, 0.1, 0.1, 0.1), wd2) * step(float4(0.5, 0.5, 0.5, 0.5), irlv1);\n"
" edr_l = step( 2.*df(f,g), df(h,c) ) * irlv2l * edr;\n"
" edr_u = step( 2.*df(h,c), df(f,g) ) * irlv2u * edr;\n"
"\n"
" fx45 = edr * fx45;\n"
" fx30 = edr_l * fx30;\n"
" fx60 = edr_u * fx60;\n"
" fx45i = edri * fx45i;\n"
"\n"
" px = step(df(e,f), df(e,h));\n"
"\n"
" float4 maximos = max(max(fx30, fx60), max(fx45, fx45i));\n"
"\n"
" float4 res1 = E;\n"
" res1 = lerp(res1, lerp(H, F, px.x), maximos.x);\n"
" res1 = lerp(res1, lerp(B, D, px.z), maximos.z);\n"
"\n"
" float4 res2 = E;\n"
" res2 = lerp(res2, lerp(F, B, px.y), maximos.y);\n"
" res2 = lerp(res2, lerp(D, H, px.w), maximos.w);\n"
"\n"
" float4 res = lerp(res1, res2, step(c_df(E, res1), c_df(E, res2)));\n"
" return res;\n"
// " float texel_alpha = tex_sample_direct(tc * u_texSize.zw).a;\n"
// "\n"
// " return float4(E, texel_alpha);\n"
// " return tex_sample_direct(coord);\n"
// " return tex_sample_direct(coord * u_texSize.xy * u_texSize.zw);\n"
// " return float4(res2, texel_alpha);\n"
// " return float4(res.r, 0.0f, 0.0f, texel_alpha);\n"
// " return float4(res, texel_alpha);\n"
"}\n";
// Missing: Z depth range
// Also, logic ops etc, of course, as they are not supported in DX9.
bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguage lang) {
@@ -69,8 +313,10 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag
StencilValueType replaceAlphaWithStencilType = (StencilValueType)id.Bits(FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE, 4);
if (lang == HLSL_DX9) {
if (doTexture)
if (doTexture) {
WRITE(p, "sampler tex : register(s0);\n");
WRITE(p, "float4 u_texSize : register(c%i);\n", CONST_PS_TEXSIZE);
}
if (!isModeClear && replaceBlend > 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
+2
View File
@@ -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
};
+11 -1
View File
@@ -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 |
+2 -1
View File
@@ -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);
}
}
+10 -1
View File
@@ -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()));
+6
View File
@@ -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");
+24 -2
View File
@@ -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));
+3
View File
@@ -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
+4
View File
@@ -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
+9 -6
View File
@@ -175,7 +175,8 @@ static RetroOption<int> ppsspp_button_preference("ppsspp_button_preference", "Co
static RetroOption<bool> ppsspp_fast_memory("ppsspp_fast_memory", "Fast Memory (Speedhack)", true);
static RetroOption<bool> ppsspp_block_transfer_gpu("ppsspp_block_transfer_gpu", "Block Transfer GPU", true);
static RetroOption<int> 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<int> 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<int> 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<bool> ppsspp_texture_scaling_realtime("ppsspp_texture_scaling_realtime", "Realtime Texture Scaling", false);
static RetroOption<int> ppsspp_texture_anisotropic_filtering("ppsspp_texture_anisotropic_filtering", "Anisotropic Filtering", { "off", "1x", "2x", "4x", "8x", "16x" });
static RetroOption<bool> ppsspp_texture_deposterize("ppsspp_texture_deposterize", "Texture Deposterize", false);
static RetroOption<bool> 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();
}
}