mirror of
https://github.com/love2d/love.git
synced 2026-08-12 08:30:56 +02:00
Workaround for built-in shaders on some ES2 devices which don't support highp in pixel shaders.
This commit is contained in:
@@ -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));
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user