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

This commit is contained in:
slime
2022-08-25 19:25:01 -03:00
parent 96820749ad
commit db1bf4707c
4 changed files with 56 additions and 11 deletions
+23 -7
View File
@@ -89,7 +89,12 @@ static const char render_uniforms[] = R"(
// 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...
// 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];
#endif
// Older GLSL doesn't support preprocessor line continuations...
#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 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
#define ViewSpaceFromLocal TransformMatrix
@@ -538,6 +548,11 @@ std::string Shader::createShaderStageCode(Graphics *gfx, ShaderStageType stage,
if (info.usesMRT)
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)
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[] =
{
{ "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));
+4 -1
View File
@@ -64,6 +64,7 @@ public:
BUILTIN_TEXTURE_VIDEO_CB,
BUILTIN_TEXTURE_VIDEO_CR,
BUILTIN_UNIFORMS_PER_DRAW,
BUILTIN_UNIFORMS_PER_DRAW_2,
BUILTIN_MAX_ENUM
};
@@ -176,8 +177,10 @@ public:
Matrix4 transformMatrix;
Matrix4 projectionMatrix;
Vector4 normalMatrix[3]; // 3x3 matrix padded to an array of 3 vector4s.
Vector4 screenSizeParams;
Colorf constantColor;
// Pixel shader-centric variables past this point.
Vector4 screenSizeParams;
};
// Pointer to currently active Shader.
+27 -3
View File
@@ -46,6 +46,7 @@ static bool isBuffer(Shader::UniformType utype)
Shader::Shader(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM])
: love::graphics::Shader(stages)
, program(0)
, splitUniformsPerDraw(false)
, builtinUniforms()
, builtinUniformInfo()
{
@@ -486,6 +487,11 @@ bool Shader::loadVolatile()
{
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
textureUnits.clear();
textureUnits.push_back(TextureUnit());
@@ -1014,9 +1020,27 @@ void Shader::updateBuiltinUniforms(love::graphics::Graphics *gfx, int viewportW,
data.constantColor = gfx->getColor();
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
+2
View File
@@ -112,6 +112,8 @@ private:
// volatile
GLuint program;
bool splitUniformsPerDraw;
// Location values for any built-in uniform variables.
GLint builtinUniforms[BUILTIN_MAX_ENUM];
UniformInfo *builtinUniformInfo[BUILTIN_MAX_ENUM];