Browse Source

Workaround for built-in shaders on some ES2 devices which don't support highp in pixel shaders.

slime 3 years ago
parent
commit
db1bf4707c

+ 23 - 7
src/modules/graphics/Shader.cpp

@@ -89,7 +89,12 @@ static const char render_uniforms[] = R"(
 // According to the GLSL ES 1.0 spec, uniform precision must match between stages,
 // According to the GLSL ES 1.0 spec, uniform precision must match between stages,
 // but we can't guarantee that highp is always supported in fragment shaders...
 // but we can't guarantee that highp is always supported in fragment shaders...
 // We *really* don't want to use mediump for these in vertex shaders though.
 // We *really* don't want to use mediump for these in vertex shaders though.
+#ifdef LOVE_SPLIT_UNIFORMS_PER_DRAW
+uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw[12];
+uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw2[1];
+#else
 uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw[13];
 uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw[13];
+#endif
 
 
 // Older GLSL doesn't support preprocessor line continuations...
 // Older GLSL doesn't support preprocessor line continuations...
 #define TransformMatrix mat4(love_UniformsPerDraw[0], love_UniformsPerDraw[1], love_UniformsPerDraw[2], love_UniformsPerDraw[3])
 #define TransformMatrix mat4(love_UniformsPerDraw[0], love_UniformsPerDraw[1], love_UniformsPerDraw[2], love_UniformsPerDraw[3])
@@ -100,8 +105,13 @@ uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw[13];
 
 
 #define CurrentDPIScale (love_UniformsPerDraw[8].w)
 #define CurrentDPIScale (love_UniformsPerDraw[8].w)
 #define ConstantPointSize (love_UniformsPerDraw[9].w)
 #define ConstantPointSize (love_UniformsPerDraw[9].w)
-#define ConstantColor (love_UniformsPerDraw[12])
-#define love_ScreenSize (love_UniformsPerDraw[11])
+#define ConstantColor (love_UniformsPerDraw[11])
+
+#ifdef LOVE_SPLIT_UNIFORMS_PER_DRAW
+#define love_ScreenSize (love_UniformsPerDraw2[0])
+#else
+#define love_ScreenSize (love_UniformsPerDraw[12])
+#endif
 
 
 // Alternate names
 // Alternate names
 #define ViewSpaceFromLocal TransformMatrix
 #define ViewSpaceFromLocal TransformMatrix
@@ -538,6 +548,11 @@ std::string Shader::createShaderStageCode(Graphics *gfx, ShaderStageType stage,
 	if (info.usesMRT)
 	if (info.usesMRT)
 		ss << "#define LOVE_MULTI_RENDER_TARGETS 1\n";
 		ss << "#define LOVE_MULTI_RENDER_TARGETS 1\n";
 
 
+	// Note: backends are expected to handle this situation if highp is ever
+	// conditional in that backend.
+	if (!gfx->getCapabilities().features[Graphics::FEATURE_PIXEL_SHADER_HIGHP])
+		ss << "#define LOVE_SPLIT_UNIFORMS_PER_DRAW 1";
+
 	for (const auto &def : options.defines)
 	for (const auto &def : options.defines)
 		ss << "#define " + def.first + " " + def.second + "\n";
 		ss << "#define " + def.first + " " + def.second + "\n";
 
 
@@ -1164,11 +1179,12 @@ static StringMap<Shader::Language, Shader::LANGUAGE_MAX_ENUM> languages(language
 
 
 static StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM>::Entry builtinNameEntries[] =
 static StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM>::Entry builtinNameEntries[] =
 {
 {
-	{ "MainTex",              Shader::BUILTIN_TEXTURE_MAIN      },
-	{ "love_VideoYChannel",   Shader::BUILTIN_TEXTURE_VIDEO_Y   },
-	{ "love_VideoCbChannel",  Shader::BUILTIN_TEXTURE_VIDEO_CB  },
-	{ "love_VideoCrChannel",  Shader::BUILTIN_TEXTURE_VIDEO_CR  },
-	{ "love_UniformsPerDraw", Shader::BUILTIN_UNIFORMS_PER_DRAW },
+	{ "MainTex",               Shader::BUILTIN_TEXTURE_MAIN        },
+	{ "love_VideoYChannel",    Shader::BUILTIN_TEXTURE_VIDEO_Y     },
+	{ "love_VideoCbChannel",   Shader::BUILTIN_TEXTURE_VIDEO_CB    },
+	{ "love_VideoCrChannel",   Shader::BUILTIN_TEXTURE_VIDEO_CR    },
+	{ "love_UniformsPerDraw",  Shader::BUILTIN_UNIFORMS_PER_DRAW   },
+	{ "love_UniformsPerDraw2", Shader::BUILTIN_UNIFORMS_PER_DRAW_2 },
 };
 };
 
 
 static StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM> builtinNames(builtinNameEntries, sizeof(builtinNameEntries));
 static StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM> builtinNames(builtinNameEntries, sizeof(builtinNameEntries));

+ 4 - 1
src/modules/graphics/Shader.h

@@ -64,6 +64,7 @@ public:
 		BUILTIN_TEXTURE_VIDEO_CB,
 		BUILTIN_TEXTURE_VIDEO_CB,
 		BUILTIN_TEXTURE_VIDEO_CR,
 		BUILTIN_TEXTURE_VIDEO_CR,
 		BUILTIN_UNIFORMS_PER_DRAW,
 		BUILTIN_UNIFORMS_PER_DRAW,
+		BUILTIN_UNIFORMS_PER_DRAW_2,
 		BUILTIN_MAX_ENUM
 		BUILTIN_MAX_ENUM
 	};
 	};
 
 
@@ -176,8 +177,10 @@ public:
  		Matrix4 transformMatrix;
  		Matrix4 transformMatrix;
  		Matrix4 projectionMatrix;
  		Matrix4 projectionMatrix;
  		Vector4 normalMatrix[3]; // 3x3 matrix padded to an array of 3 vector4s.
  		Vector4 normalMatrix[3]; // 3x3 matrix padded to an array of 3 vector4s.
- 		Vector4 screenSizeParams;
  		Colorf constantColor;
  		Colorf constantColor;
+
+		// Pixel shader-centric variables past this point.
+		Vector4 screenSizeParams;
  	};
  	};
 
 
 	// Pointer to currently active Shader.
 	// Pointer to currently active Shader.

+ 27 - 3
src/modules/graphics/opengl/Shader.cpp

@@ -46,6 +46,7 @@ static bool isBuffer(Shader::UniformType utype)
 Shader::Shader(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM])
 Shader::Shader(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM])
 	: love::graphics::Shader(stages)
 	: love::graphics::Shader(stages)
 	, program(0)
 	, program(0)
+	, splitUniformsPerDraw(false)
 	, builtinUniforms()
 	, builtinUniforms()
 	, builtinUniformInfo()
 	, builtinUniformInfo()
 {
 {
@@ -486,6 +487,11 @@ bool Shader::loadVolatile()
 {
 {
 	OpenGL::TempDebugGroup debuggroup("Shader load");
 	OpenGL::TempDebugGroup debuggroup("Shader load");
 
 
+	// love::graphics::Shader sets up the shader code-side of this.
+	auto gfx = Module::getInstance<love::graphics::Graphics>(Module::M_GRAPHICS);
+	if (gfx != nullptr)
+		splitUniformsPerDraw = gfx->getCapabilities().features[Graphics::FEATURE_PIXEL_SHADER_HIGHP];
+
 	// zero out active texture list
 	// zero out active texture list
 	textureUnits.clear();
 	textureUnits.clear();
 	textureUnits.push_back(TextureUnit());
 	textureUnits.push_back(TextureUnit());
@@ -1014,9 +1020,27 @@ void Shader::updateBuiltinUniforms(love::graphics::Graphics *gfx, int viewportW,
 	data.constantColor = gfx->getColor();
 	data.constantColor = gfx->getColor();
 	gammaCorrectColor(data.constantColor);
 	gammaCorrectColor(data.constantColor);
 
 
-	GLint location = builtinUniforms[BUILTIN_UNIFORMS_PER_DRAW];
-	if (location >= 0)
-		glUniform4fv(location, 13, (const GLfloat *) &data);
+	// This branch is to avoid always declaring the whole array as highp in the
+	// vertex shader and mediump in the pixel shader for love's default shaders,
+	// on systems that don't support highp in pixel shaders. The default shaders
+	// use the transform matrices in vertex shaders and screen size params in
+	// pixel shaders. If there's a single array containing both and each shader
+	// stage declares a different precision, that's a compile error.
+	if (splitUniformsPerDraw)
+	{
+		GLint location = builtinUniforms[BUILTIN_UNIFORMS_PER_DRAW];
+		if (location >= 0)
+			glUniform4fv(location, 12, (const GLfloat *) &data);
+		GLint location2 = builtinUniforms[BUILTIN_UNIFORMS_PER_DRAW_2];
+		if (location2 >= 0)
+			glUniform4fv(location2, 1, (const GLfloat *) &data.screenSizeParams);
+	}
+	else
+	{
+		GLint location = builtinUniforms[BUILTIN_UNIFORMS_PER_DRAW];
+		if (location >= 0)
+			glUniform4fv(location, 13, (const GLfloat *) &data);
+	}
 }
 }
 
 
 int Shader::getUniformTypeComponents(GLenum type) const
 int Shader::getUniformTypeComponents(GLenum type) const

+ 2 - 0
src/modules/graphics/opengl/Shader.h

@@ -112,6 +112,8 @@ private:
 	// volatile
 	// volatile
 	GLuint program;
 	GLuint program;
 
 
+	bool splitUniformsPerDraw;
+
 	// Location values for any built-in uniform variables.
 	// Location values for any built-in uniform variables.
 	GLint builtinUniforms[BUILTIN_MAX_ENUM];
 	GLint builtinUniforms[BUILTIN_MAX_ENUM];
 	UniformInfo *builtinUniformInfo[BUILTIN_MAX_ENUM];
 	UniformInfo *builtinUniformInfo[BUILTIN_MAX_ENUM];