Merge pull request #9258 from hrydgard/avoid-unnecessary-projection

Avoid unnecessary projection. Should fix "low-res look" in some games on older PowerVR
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2017-01-30 19:58:24 +01:00
commit e7b044c449
9 files changed
+62 -75

No files matched your search

+9 -5
View File
@@ -22,7 +22,7 @@ std::string VertexShaderDesc(const ShaderID &id) {
if (id.Bit(VS_BIT_ENABLE_FOG)) desc << "Fog ";
if (id.Bit(VS_BIT_NORM_REVERSE)) desc << "RevN ";
if (id.Bit(VS_BIT_DO_TEXTURE)) desc << "Tex ";
if (id.Bit(VS_BIT_DO_TEXTURE_PROJ)) desc << "TexProj ";
if (id.Bit(VS_BIT_DO_TEXTURE_TRANSFORM)) desc << "TexProj ";
int uvgMode = id.Bits(VS_BIT_UVGEN_MODE, 2);
const char *uvgModes[4] = { "UV ", "UVMtx ", "UVEnv ", "UVUnk " };
int ls0 = id.Bits(VS_BIT_LS0, 2);
@@ -58,7 +58,7 @@ std::string VertexShaderDesc(const ShaderID &id) {
void ComputeVertexShaderID(ShaderID *id_out, u32 vertType, bool useHWTransform) {
bool doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
bool doTextureTransform = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
bool doShadeMapping = doTexture && (gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP);
bool doFlatShading = gstate.getShadeMode() == GE_SHADE_FLAT && !gstate.isModeClear();
@@ -83,7 +83,7 @@ void ComputeVertexShaderID(ShaderID *id_out, u32 vertType, bool useHWTransform)
if (doTexture) {
id.SetBit(VS_BIT_DO_TEXTURE);
id.SetBit(VS_BIT_DO_TEXTURE_PROJ, doTextureProjection);
id.SetBit(VS_BIT_DO_TEXTURE_TRANSFORM, doTextureTransform);
}
if (useHWTransform) {
@@ -94,7 +94,7 @@ void ComputeVertexShaderID(ShaderID *id_out, u32 vertType, bool useHWTransform)
id.SetBits(VS_BIT_UVGEN_MODE, 2, gstate.getUVGenMode());
// The next bits are used differently depending on UVgen mode
if (doTextureProjection) {
if (doTextureTransform) {
id.SetBits(VS_BIT_UVPROJ_MODE, 2, gstate.getUVProjMode());
} else if (doShadeMapping) {
id.SetBits(VS_BIT_LS0, 2, gstate.getUVLS0());
@@ -149,6 +149,10 @@ void ComputeVertexShaderID(ShaderID *id_out, u32 vertType, bool useHWTransform)
static const char *alphaTestFuncs[] = { "NEVER", "ALWAYS", "==", "!=", "<", "<=", ">", ">=" };
static bool MatrixNeedsProjection(const float m[12]) {
return m[2] != 0.0f || m[5] != 0.0f || m[8] != 0.0f || m[11] != 1.0f;
}
std::string FragmentShaderDesc(const ShaderID &id) {
std::stringstream desc;
desc << StringFromFormat("%08x:%08x ", id.d[1], id.d[0]);
@@ -224,7 +228,7 @@ void ComputeFragmentShaderID(ShaderID *id_out) {
bool enableAlphaTest = gstate.isAlphaTestEnabled() && !IsAlphaTestTriviallyTrue() && !g_Config.bDisableAlphaTest;
bool enableColorTest = gstate.isColorTestEnabled() && !IsColorTestTriviallyTrue();
bool enableColorDoubling = gstate.isColorDoublingEnabled() && gstate.isTextureMapEnabled();
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
bool doTextureProjection = (gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX && MatrixNeedsProjection(gstate.tgenMatrix));
bool doTextureAlpha = gstate.isTextureAlphaUsed();
bool doFlatShading = gstate.getShadeMode() == GE_SHADE_FLAT;
+1 -1
View File
@@ -11,7 +11,7 @@ enum {
VS_BIT_ENABLE_FOG = 2,
VS_BIT_HAS_COLOR = 3,
VS_BIT_DO_TEXTURE = 4,
VS_BIT_DO_TEXTURE_PROJ = 6,
VS_BIT_DO_TEXTURE_TRANSFORM = 6,
VS_BIT_USE_HW_TRANSFORM = 8,
VS_BIT_HAS_NORMAL = 9, // conditioned on hw transform
VS_BIT_NORM_REVERSE = 10,
+1 -4
View File
@@ -112,10 +112,7 @@ bool GenerateFragmentShaderDX9(const ShaderID &id, char *buffer) {
WRITE(p, "struct PS_IN {\n");
if (doTexture) {
if (doTextureProjection)
WRITE(p, " float3 v_texcoord: TEXCOORD0;\n");
else
WRITE(p, " float2 v_texcoord: TEXCOORD0;\n");
WRITE(p, " float3 v_texcoord: TEXCOORD0;\n");
}
WRITE(p, " float4 v_color0: COLOR0;\n");
if (lmode) {
+15 -19
View File
@@ -61,7 +61,7 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) {
bool isModeThrough = id.Bit(VS_BIT_IS_THROUGH);
bool lmode = id.Bit(VS_BIT_LMODE) && !isModeThrough; // TODO: Different expression than in shaderIDgen
bool doTexture = id.Bit(VS_BIT_DO_TEXTURE);
bool doTextureProjection = id.Bit(VS_BIT_DO_TEXTURE_PROJ);
bool doTextureTransform = id.Bit(VS_BIT_DO_TEXTURE_TRANSFORM);
GETexMapMode uvGenMode = static_cast<GETexMapMode>(id.Bits(VS_BIT_UVGEN_MODE, 2));
@@ -122,7 +122,7 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) {
// When transforming by hardware, we need a great deal more uniforms...
WRITE(p, "float4x3 u_world : register(c%i);\n", CONST_VS_WORLD);
WRITE(p, "float4x3 u_view : register(c%i);\n", CONST_VS_VIEW);
if (doTextureProjection)
if (doTextureTransform)
WRITE(p, "float4x3 u_texmtx : register(c%i);\n", CONST_VS_TEXMTX);
if (enableBones) {
#ifdef USE_BONE_ARRAY
@@ -176,6 +176,7 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) {
}
// And the "varyings".
bool texCoordInVec3 = false;
if (useHWTransform) {
WRITE(p, "struct VS_IN { \n");
if (enableBones) {
@@ -197,8 +198,10 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) {
WRITE(p, "struct VS_IN {\n");
WRITE(p, " float4 position : POSITION;\n");
if (doTexture && hasTexcoord) {
if (doTextureProjection && !throughmode)
if (doTextureTransform && !throughmode) {
texCoordInVec3 = true;
WRITE(p, " float3 texcoord : TEXCOORD0;\n");
}
else
WRITE(p, " float2 texcoord : TEXCOORD0;\n");
}
@@ -215,10 +218,7 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) {
WRITE(p, "struct VS_OUT {\n");
WRITE(p, " float4 gl_Position : POSITION;\n");
if (doTexture) {
if (doTextureProjection)
WRITE(p, " float3 v_texcoord: TEXCOORD0;\n");
else
WRITE(p, " float2 v_texcoord: TEXCOORD0;\n");
WRITE(p, " float3 v_texcoord : TEXCOORD0;\n");
}
WRITE(p, " float4 v_color0 : COLOR0;\n");
if (lmode)
@@ -248,14 +248,10 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) {
if (!useHWTransform) {
// Simple pass-through of vertex data to fragment shader
if (doTexture) {
if (doTextureProjection) {
if (throughmode) {
WRITE(p, " Out.v_texcoord = float3(In.texcoord.x, In.texcoord.y, 1.0);\n");
} else {
WRITE(p, " Out.v_texcoord = In.texcoord;\n");
}
if (texCoordInVec3) {
WRITE(p, " Out.v_texcoord = In.texcoord;\n");
} else {
WRITE(p, " Out.v_texcoord = In.texcoord.xy;\n");
WRITE(p, " Out.v_texcoord = float3(In.texcoord, 1.0);\n");
}
}
if (hasColor) {
@@ -505,15 +501,15 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) {
case GE_TEXMAP_UNKNOWN: // Not sure what this is, but Riviera uses it. Treating as coords works.
if (scaleUV) {
if (hasTexcoord) {
WRITE(p, " Out.v_texcoord = In.texcoord * u_uvscaleoffset.xy;\n");
WRITE(p, " Out.v_texcoord = float3(In.texcoord.xy * u_uvscaleoffset.xy, 0.0);\n");
} else {
WRITE(p, " Out.v_texcoord = float2(0.0, 0.0);\n");
WRITE(p, " Out.v_texcoord = float3(0.0, 0.0, 0.0);\n");
}
} else {
if (hasTexcoord) {
WRITE(p, " Out.v_texcoord = In.texcoord * u_uvscaleoffset.xy + u_uvscaleoffset.zw;\n");
WRITE(p, " Out.v_texcoord = float3(In.texcoord.xy * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n");
} else {
WRITE(p, " Out.v_texcoord = u_uvscaleoffset.zw;\n");
WRITE(p, " Out.v_texcoord = float3(u_uvscaleoffset.zw, 0.0);\n");
}
}
break;
@@ -553,7 +549,7 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) {
break;
case GE_TEXMAP_ENVIRONMENT_MAP: // Shade mapping - use dots from light sources.
WRITE(p, " Out.v_texcoord.xy = u_uvscaleoffset.xy * float2(1.0 + dot(normalize(u_lightpos%i), worldnormal), 1.0 + dot(normalize(u_lightpos%i), worldnormal)) * 0.5;\n", ls0, ls1);
WRITE(p, " Out.v_texcoord = float3(u_uvscaleoffset.xy * float2(1.0 + dot(normalize(u_lightpos%i), worldnormal), 1.0 + dot(normalize(u_lightpos%i), worldnormal)) * 0.5, 1.0);\n", ls0, ls1);
break;
default:
+2 -5
View File
@@ -227,10 +227,7 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer) {
WRITE(p, "%s %s float v_fogdepth;\n", varying, highpFog ? "highp" : "mediump");
}
if (doTexture) {
if (doTextureProjection)
WRITE(p, "%s %s vec3 v_texcoord;\n", varying, highpTexcoord ? "highp" : "mediump");
else
WRITE(p, "%s %s vec2 v_texcoord;\n", varying, highpTexcoord ? "highp" : "mediump");
WRITE(p, "%s %s vec3 v_texcoord;\n", varying, highpTexcoord ? "highp" : "mediump");
}
if (!g_Config.bFragmentTestCache) {
@@ -329,7 +326,7 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer) {
if (doTextureProjection) {
WRITE(p, " vec4 t = %sProj(tex, %s);\n", texture, texcoord);
} else {
WRITE(p, " vec4 t = %s(tex, %s);\n", texture, texcoord);
WRITE(p, " vec4 t = %s(tex, %s.xy);\n", texture, texcoord);
}
WRITE(p, " vec4 p = v_color0;\n");
+1 -3
View File
@@ -15,8 +15,6 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
// #define SHADERLOG
#if defined(_WIN32) && defined(SHADERLOG)
#include "Common/CommonWindows.h"
#endif
@@ -991,7 +989,7 @@ std::string ShaderManagerGLES::DebugGetShaderString(std::string id, DebugShaderT
// as sometimes these features might have an effect on the ID bits.
#define CACHE_HEADER_MAGIC 0x83277592
#define CACHE_VERSION 2
#define CACHE_VERSION 3
struct CacheHeader {
uint32_t magic;
uint32_t version;
+17 -18
View File
@@ -166,7 +166,7 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
bool isModeThrough = id.Bit(VS_BIT_IS_THROUGH);
bool lmode = id.Bit(VS_BIT_LMODE) && !isModeThrough; // TODO: Different expression than in shaderIDgen
bool doTexture = id.Bit(VS_BIT_DO_TEXTURE);
bool doTextureProjection = id.Bit(VS_BIT_DO_TEXTURE_PROJ);
bool doTextureProjection = id.Bit(VS_BIT_DO_TEXTURE_TRANSFORM);
GETexMapMode uvGenMode = static_cast<GETexMapMode>(id.Bits(VS_BIT_UVGEN_MODE, 2));
@@ -225,11 +225,14 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
if (useHWTransform && hasNormal)
WRITE(p, "%s mediump vec3 normal;\n", attribute);
bool texcoordVec3In = false;
if (doTexture && hasTexcoord) {
if (!useHWTransform && doTextureProjection && !throughmode)
if (!useHWTransform && doTextureProjection && !throughmode) {
WRITE(p, "%s vec3 texcoord;\n", attribute);
else
texcoordVec3In = true;
} else {
WRITE(p, "%s vec2 texcoord;\n", attribute);
}
}
if (hasColor) {
WRITE(p, "%s lowp vec4 color0;\n", attribute);
@@ -315,11 +318,7 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
}
if (doTexture) {
if (doTextureProjection) {
WRITE(p, "%s %s vec3 v_texcoord;\n", varying, highpTexcoord ? "highp" : "mediump");
} else {
WRITE(p, "%s %s vec2 v_texcoord;\n", varying, highpTexcoord ? "highp" : "mediump");
}
WRITE(p, "%s %s vec3 v_texcoord;\n", varying, highpTexcoord ? "highp" : "mediump");
}
if (enableFog) {
@@ -430,10 +429,10 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
if (!useHWTransform) {
// Simple pass-through of vertex data to fragment shader
if (doTexture) {
if (throughmode && doTextureProjection) {
WRITE(p, " v_texcoord = vec3(texcoord, 1.0);\n");
} else {
if (texcoordVec3In) {
WRITE(p, " v_texcoord = texcoord;\n");
} else {
WRITE(p, " v_texcoord = vec3(texcoord, 1.0);\n");
}
}
if (hasColor) {
@@ -803,20 +802,20 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
if (doBezier || doSpline)
// TODO: Need fix?
// Fix to avoid temporarily texture animation bug with hardware tessellation.
WRITE(p, " v_texcoord = tex * u_uvscaleoffset.xy + u_uvscaleoffset.zw;\n");
WRITE(p, " v_texcoord = vec3(tex * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n");
else
WRITE(p, " v_texcoord = texcoord * u_uvscaleoffset.xy;\n");
WRITE(p, " v_texcoord = vec3(texcoord.xy * u_uvscaleoffset.xy, 0.0);\n");
} else {
WRITE(p, " v_texcoord = vec2(0.0);\n");
WRITE(p, " v_texcoord = vec3(0.0);\n");
}
} else {
if (hasTexcoord) {
if (doBezier || doSpline)
WRITE(p, " v_texcoord = tex * u_uvscaleoffset.xy + u_uvscaleoffset.zw;\n");
WRITE(p, " v_texcoord = vec3(tex * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n");
else
WRITE(p, " v_texcoord = texcoord * u_uvscaleoffset.xy + u_uvscaleoffset.zw;\n");
WRITE(p, " v_texcoord = vec3(texcoord.xy * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n");
} else {
WRITE(p, " v_texcoord = u_uvscaleoffset.zw;\n");
WRITE(p, " v_texcoord = vec3(u_uvscaleoffset.zw, 0.0);\n");
}
}
break;
@@ -857,7 +856,7 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
break;
case GE_TEXMAP_ENVIRONMENT_MAP: // Shade mapping - use dots from light sources.
WRITE(p, " v_texcoord = u_uvscaleoffset.xy * vec2(1.0 + dot(normalize(u_lightpos%i), worldnormal), 1.0 + dot(normalize(u_lightpos%i), worldnormal)) * 0.5;\n", ls0, ls1);
WRITE(p, " v_texcoord = vec3(u_uvscaleoffset.xy * vec2(1.0 + dot(normalize(u_lightpos%i), worldnormal), 1.0 + dot(normalize(u_lightpos%i), worldnormal)) * 0.5, 1.0);\n", ls0, ls1);
break;
default:
+2 -5
View File
@@ -98,10 +98,7 @@ bool GenerateVulkanGLSLFragmentShader(const ShaderID &id, char *buffer) {
WRITE(p, "layout (location = 3) in float v_fogdepth;\n");
}
if (doTexture) {
if (doTextureProjection)
WRITE(p, "layout (location = 0) in vec3 v_texcoord;\n");
else
WRITE(p, "layout (location = 0) in vec2 v_texcoord;\n");
WRITE(p, "layout (location = 0) in vec3 v_texcoord;\n");
}
if (enableAlphaTest && !alphaTestAgainstZero) {
@@ -176,7 +173,7 @@ bool GenerateVulkanGLSLFragmentShader(const ShaderID &id, char *buffer) {
if (doTextureProjection) {
WRITE(p, " vec4 t = textureProj(tex, %s);\n", texcoord);
} else {
WRITE(p, " vec4 t = texture(tex, %s);\n", texcoord);
WRITE(p, " vec4 t = texture(tex, %s.xy);\n", texcoord);
}
WRITE(p, " vec4 p = v_color0;\n");
+14 -15
View File
@@ -108,7 +108,7 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer, bool *uses
bool isModeThrough = id.Bit(VS_BIT_IS_THROUGH);
bool lmode = id.Bit(VS_BIT_LMODE) && !isModeThrough; // TODO: Different expression than in shaderIDgen
bool doTexture = id.Bit(VS_BIT_DO_TEXTURE);
bool doTextureProjection = id.Bit(VS_BIT_DO_TEXTURE_PROJ);
bool doTextureTransform = id.Bit(VS_BIT_DO_TEXTURE_TRANSFORM);
GETexMapMode uvGenMode = static_cast<GETexMapMode>(id.Bits(VS_BIT_UVGEN_MODE, 2));
@@ -171,9 +171,12 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer, bool *uses
if (useHWTransform && hasNormal)
WRITE(p, "layout (location = %d) in vec3 normal;\n", PspAttributeLocation::NORMAL);
bool texcoordInVec3 = false;
if (doTexture && hasTexcoord) {
if (!useHWTransform && doTextureProjection && !throughmode)
if (!useHWTransform && doTextureTransform && !throughmode) {
WRITE(p, "layout (location = %d) in vec3 texcoord;\n", PspAttributeLocation::TEXCOORD);
texcoordInVec3 = true;
}
else
WRITE(p, "layout (location = %d) in vec2 texcoord;\n", PspAttributeLocation::TEXCOORD);
}
@@ -189,11 +192,7 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer, bool *uses
}
if (doTexture) {
if (doTextureProjection) {
WRITE(p, "layout (location = 0) out vec3 v_texcoord;\n");
} else {
WRITE(p, "layout (location = 0) out vec2 v_texcoord;\n");
}
WRITE(p, "layout (location = 0) out vec3 v_texcoord;\n");
}
if (enableFog) {
@@ -218,10 +217,10 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer, bool *uses
if (!useHWTransform) {
// Simple pass-through of vertex data to fragment shader
if (doTexture) {
if (throughmode && doTextureProjection) {
WRITE(p, " v_texcoord = vec3(texcoord, 1.0);\n");
} else {
if (texcoordInVec3) {
WRITE(p, " v_texcoord = texcoord;\n");
} else {
WRITE(p, " v_texcoord = vec3(texcoord, 1.0);\n");
}
}
if (hasColor) {
@@ -435,15 +434,15 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer, bool *uses
case GE_TEXMAP_UNKNOWN: // Not sure what this is, but Riviera uses it. Treating as coords works.
if (scaleUV) {
if (hasTexcoord) {
WRITE(p, " v_texcoord = texcoord;\n");
WRITE(p, " v_texcoord = vec3(texcoord.xy, 0.0);\n");
} else {
WRITE(p, " v_texcoord = vec2(0.0);\n");
WRITE(p, " v_texcoord = vec3(0.0);\n");
}
} else {
if (hasTexcoord) {
WRITE(p, " v_texcoord = texcoord * base.uvscaleoffset.xy + base.uvscaleoffset.zw;\n");
WRITE(p, " v_texcoord = vec3(texcoord.xy * base.uvscaleoffset.xy + base.uvscaleoffset.zw, 0.0);\n");
} else {
WRITE(p, " v_texcoord = base.uvscaleoffset.zw;\n");
WRITE(p, " v_texcoord = vec3(base.uvscaleoffset.zw, 0.0);\n");
}
}
break;
@@ -484,7 +483,7 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer, bool *uses
break;
case GE_TEXMAP_ENVIRONMENT_MAP: // Shade mapping - use dots from light sources.
WRITE(p, " v_texcoord = base.uvscaleoffset.xy * vec2(1.0 + dot(normalize(light.pos[%i]), worldnormal), 1.0 + dot(normalize(light.pos[%i]), worldnormal)) * 0.5;\n", ls0, ls1);
WRITE(p, " v_texcoord = vec3(base.uvscaleoffset.xy * vec2(1.0 + dot(normalize(light.pos[%i]), worldnormal), 1.0 + dot(normalize(light.pos[%i]), worldnormal)) * 0.5, 1.0);\n", ls0, ls1);
break;
default: