Skip to content

Commit

Permalink
Shaders use GLSL3 instead of GLSL1 by default.
Browse files Browse the repository at this point in the history
Remove support for GLSL1.
Deprecate use of 'texture' uniform variable names and 'texture2D' function calls in shader code. They aren't supported in modern GLSL.
  • Loading branch information
slime73 committed Jun 20, 2024
1 parent 54a31ec commit ad0af74
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 143 deletions.
246 changes: 111 additions & 135 deletions src/modules/graphics/Shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,40 +46,19 @@ namespace glsl
{

static const char global_syntax[] = R"(
#if !defined(GL_ES) && __VERSION__ < 140
#define lowp
#define mediump
#define highp
#endif
#define LOVE_HIGHP_OR_MEDIUMP highp
#if __VERSION__ >= 300
#define LOVE_IO_LOCATION(x) layout (location = x)
#else
#define LOVE_IO_LOCATION(x)
#endif
#define number float
#define Image sampler2D
#define ArrayImage sampler2DArray
#define CubeImage samplerCube
#define VolumeImage sampler3D
#if __VERSION__ >= 300 && !defined(LOVE_GLSL1_ON_GLSL3)
#define DepthImage sampler2DShadow
#define DepthArrayImage sampler2DArrayShadow
#define DepthCubeImage samplerCubeShadow
#endif
#define DepthImage sampler2DShadow
#define DepthArrayImage sampler2DArrayShadow
#define DepthCubeImage samplerCubeShadow
#define extern uniform
#if defined(GL_EXT_texture_array) && (!defined(GL_ES) || __VERSION__ > 100 || defined(GL_OES_gpu_shader5))
// Only used when !GLSLES1 to work around Ouya driver bug. But we still want it
// enabled for glslang validation when glsl 1-on-3 is used, so also enable it if
// OES_gpu_shader5 exists.
#define LOVE_EXT_TEXTURE_ARRAY_ENABLED
#extension GL_EXT_texture_array : enable
#endif
#ifdef GL_OES_texture_3D
#extension GL_OES_texture_3D : enable
#endif
#ifdef GL_OES_standard_derivatives
#extension GL_OES_standard_derivatives : enable
#if __VERSION__ >= 430 || (defined(GL_ES) && __VERSION__ >= 310)
layout (std430) buffer;
#endif
)";

Expand All @@ -106,62 +85,80 @@ uniform highp vec4 love_UniformsPerDraw[12];
static const char global_functions[] = R"(
#ifdef GL_ES
precision mediump sampler2D;
#if __VERSION__ >= 300 || defined(LOVE_EXT_TEXTURE_ARRAY_ENABLED)
precision mediump sampler2DArray;
#endif
#if __VERSION__ >= 300 || defined(GL_OES_texture_3D)
precision mediump sampler3D;
#endif
#if __VERSION__ >= 300 && !defined(LOVE_GLSL1_ON_GLSL3)
precision mediump sampler2DShadow;
precision mediump samplerCubeShadow;
precision mediump sampler2DArrayShadow;
#endif
precision mediump sampler2DArray;
precision mediump sampler3D;
precision mediump samplerCube;
precision mediump sampler2DShadow;
precision mediump samplerCubeShadow;
precision mediump sampler2DArrayShadow;
precision highp isampler2D;
precision highp isampler2DArray;
precision highp isampler3D;
precision highp isamplerCube;
precision highp usampler2D;
precision highp usampler2DArray;
precision highp usampler3D;
precision highp usamplerCube;
#endif
#if __VERSION__ >= 430 || (defined(GL_ES) && __VERSION__ >= 310)
layout (std430) buffer;
// Avoid #define so legacy code that uses 'texture' as a variable can work...
// Unfortunately it means these can't have variable precision.
vec4 Texel(sampler2D s, highp vec2 c) { return texture(s, c); }
ivec4 Texel(isampler2D s, highp vec2 c) { return texture(s, c); }
uvec4 Texel(usampler2D s, highp vec2 c) { return texture(s, c); }
vec4 Texel(sampler3D s, highp vec3 c) { return texture(s, c); }
ivec4 Texel(isampler3D s, highp vec3 c) { return texture(s, c); }
uvec4 Texel(usampler3D s, highp vec3 c) { return texture(s, c); }
vec4 Texel(samplerCube s, highp vec3 c) { return texture(s, c); }
ivec4 Texel(isamplerCube s, highp vec3 c) { return texture(s, c); }
uvec4 Texel(usamplerCube s, highp vec3 c) { return texture(s, c); }
vec4 Texel(sampler2DArray s, highp vec3 c) { return texture(s, c); }
ivec4 Texel(isampler2DArray s, highp vec3 c) { return texture(s, c); }
uvec4 Texel(usampler2DArray s, highp vec3 c) { return texture(s, c); }
float Texel(sampler2DShadow s, highp vec3 c) { return texture(s, c); }
float Texel(samplerCubeShadow s, highp vec4 c) { return texture(s, c); }
float Texel(sampler2DArrayShadow s, highp vec4 c) { return texture(s, c); }
#ifdef PIXEL
vec4 Texel(sampler2D s, highp vec2 c, float b) { return texture(s, c, b); }
ivec4 Texel(isampler2D s, highp vec2 c, float b) { return texture(s, c, b); }
uvec4 Texel(usampler2D s, highp vec2 c, float b) { return texture(s, c, b); }
vec4 Texel(sampler3D s, highp vec3 c, float b) { return texture(s, c, b); }
ivec4 Texel(isampler3D s, highp vec3 c, float b) { return texture(s, c, b); }
uvec4 Texel(usampler3D s, highp vec3 c, float b) { return texture(s, c, b); }
vec4 Texel(samplerCube s, highp vec3 c, float b) { return texture(s, c, b); }
ivec4 Texel(isamplerCube s, highp vec3 c, float b) { return texture(s, c, b); }
uvec4 Texel(usamplerCube s, highp vec3 c, float b) { return texture(s, c, b); }
vec4 Texel(sampler2DArray s, highp vec3 c, float b) { return texture(s, c, b); }
ivec4 Texel(isampler2DArray s, highp vec3 c, float b) { return texture(s, c, b); }
uvec4 Texel(usampler2DArray s, highp vec3 c, float b) { return texture(s, c, b); }
float Texel(sampler2DShadow s, highp vec3 c, float b) { return texture(s, c, b); }
float Texel(samplerCubeShadow s, highp vec4 c, float b) { return texture(s, c, b); }
#endif
#if __VERSION__ >= 130 && !defined(LOVE_GLSL1_ON_GLSL3)
#define Texel texture
#else
#if __VERSION__ >= 130
#define texture2D Texel
#define texture3D Texel
#define textureCube Texel
#define texture2DArray Texel
#define love_texture2D texture
#define love_texture3D texture
#define love_textureCube texture
#define love_texture2DArray texture
#else
#define love_texture2D texture2D
#define love_texture3D texture3D
#define love_textureCube textureCube
#define love_texture2DArray texture2DArray
#endif
vec4 Texel(sampler2D s, vec2 c) { return love_texture2D(s, c); }
vec4 Texel(samplerCube s, vec3 c) { return love_textureCube(s, c); }
#if __VERSION__ > 100 || defined(GL_OES_texture_3D)
vec4 Texel(sampler3D s, vec3 c) { return love_texture3D(s, c); }
#endif
#if __VERSION__ >= 130 || defined(LOVE_EXT_TEXTURE_ARRAY_ENABLED)
vec4 Texel(sampler2DArray s, vec3 c) { return love_texture2DArray(s, c); }
#endif
#ifdef PIXEL
vec4 Texel(sampler2D s, vec2 c, float b) { return love_texture2D(s, c, b); }
vec4 Texel(samplerCube s, vec3 c, float b) { return love_textureCube(s, c, b); }
#if __VERSION__ > 100 || defined(GL_OES_texture_3D)
vec4 Texel(sampler3D s, vec3 c, float b) { return love_texture3D(s, c, b); }
#endif
#if __VERSION__ >= 130 || defined(LOVE_EXT_TEXTURE_ARRAY_ENABLED)
vec4 Texel(sampler2DArray s, vec3 c, float b) { return love_texture2DArray(s, c, b); }
#endif
#endif
#define texture love_texture
uniform mediump float deprecatedTextureCall;
vec4 texture2DDeprecated(sampler2D s, vec2 c) { return texture(s, c) + deprecatedTextureCall; }
vec4 textureCubeDeprecated(samplerCube s, vec3 c) { return texture(s, c) + deprecatedTextureCall; }
#ifdef PIXEL
vec4 texture2DDeprecated(sampler2D s, vec2 c, float b) { return texture(s, c, b) + deprecatedTextureCall; }
vec4 textureCubeDeprecated(samplerCube s, vec3 c, float b) { return texture(s, c, b) + deprecatedTextureCall; }
#endif
#define texture2D texture2DDeprecated
#define textureCube textureCubeDeprecated
float gammaToLinearPrecise(float c) {
return c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4);
}
Expand Down Expand Up @@ -219,14 +216,10 @@ static const char vertex_header[] = R"(
#define love_Position gl_Position
#define love_PointSize gl_PointSize
#if __VERSION__ >= 130
#define attribute in
#define varying out
#ifndef LOVE_GLSL1_ON_GLSL3
#define love_VertexID gl_VertexID
#define love_InstanceID gl_InstanceID
#endif
#endif
#define attribute in
#define varying out
#define love_VertexID gl_VertexID
#define love_InstanceID gl_InstanceID
)";

static const char vertex_functions[] = R"(
Expand All @@ -238,12 +231,12 @@ vec4 love_clipSpaceTransform(vec4 clipPosition) {
)";

static const char vertex_main[] = R"(
LOVE_IO_LOCATION(0) attribute vec4 VertexPosition;
LOVE_IO_LOCATION(1) attribute vec4 VertexTexCoord;
LOVE_IO_LOCATION(2) attribute vec4 VertexColor;
layout (location = 0) in vec4 VertexPosition;
layout (location = 1) in vec4 VertexTexCoord;
layout (location = 2) in vec4 VertexColor;
varying vec4 VaryingTexCoord;
varying vec4 VaryingColor;
out vec4 VaryingTexCoord;
out vec4 VaryingColor;
vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition);
Expand Down Expand Up @@ -271,9 +264,7 @@ static const char pixel_header[] = R"(
#define love_MaxRenderTargets gl_MaxDrawBuffers
#if __VERSION__ >= 130
#define varying in
#endif
#define varying in
// Legacy
#define love_MaxCanvases love_MaxRenderTargets
Expand Down Expand Up @@ -305,15 +296,11 @@ vec4 VideoTexel(vec2 texcoords) {
)";

static const char pixel_main[] = R"(
#if __VERSION__ >= 130
LOVE_IO_LOCATION(0) out vec4 love_PixelColor;
#else
#define love_PixelColor gl_FragColor
#endif
layout (location = 0) out vec4 love_PixelColor;
uniform sampler2D MainTex;
varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord;
varying mediump vec4 VaryingColor;
in highp vec4 VaryingTexCoord;
in mediump vec4 VaryingColor;
vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord);
Expand All @@ -323,22 +310,15 @@ void main() {
)";

static const char pixel_main_custom[] = R"(
#if __VERSION__ >= 130
// Some drivers seem to make the pixel shader do more work when multiple
// pixel shader outputs are defined, even when only one is actually used.
// TODO: We should use reflection or something instead of this, to determine
// how many outputs are actually used in the shader code.
#ifdef LOVE_MULTI_RENDER_TARGETS
LOVE_IO_LOCATION(0) out vec4 love_RenderTargets[love_MaxRenderTargets];
#define love_PixelColor love_RenderTargets[0]
#else
LOVE_IO_LOCATION(0) out vec4 love_PixelColor;
#endif
// Some drivers seem to make the pixel shader do more work when multiple
// pixel shader outputs are defined, even when only one is actually used.
// TODO: We should use reflection or something instead of this, to determine
// how many outputs are actually used in the shader code.
#ifdef LOVE_MULTI_RENDER_TARGETS
layout (location = 0) out vec4 love_RenderTargets[love_MaxRenderTargets];
#define love_PixelColor love_RenderTargets[0]
#else
#ifdef LOVE_MULTI_RENDER_TARGETS
#define love_RenderTargets gl_FragData
#endif
#define love_PixelColor gl_FragColor
layout (location = 0) out vec4 love_PixelColor;
#endif
// Legacy
Expand All @@ -347,8 +327,8 @@ static const char pixel_main_custom[] = R"(
#define LOVE_MULTI_CANVASES 1
#endif
varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord;
varying mediump vec4 VaryingColor;
in highp vec4 VaryingTexCoord;
in mediump vec4 VaryingColor;
void effect();
Expand Down Expand Up @@ -416,7 +396,6 @@ struct Version
// Indexed by Shader::Version
static const Version versions[] =
{
{ "#version 120", "#version 100" },
{ "#version 330 core", "#version 300 es" },
{ "#version 430 core", "#version 320 es" },
};
Expand Down Expand Up @@ -530,7 +509,7 @@ static Shader::Language getTargetLanguage(const std::string &src)
{
std::regex r("^\\s*#pragma language (\\w+)");
std::smatch m;
std::string langstr = std::regex_search(src, m, r) && m.size() > 1 ? m[1] : std::string("glsl1");
std::string langstr = std::regex_search(src, m, r) && m.size() > 1 ? m[1] : std::string("glsl3");
Shader::Language lang = Shader::LANGUAGE_MAX_ENUM;
Shader::getConstant(langstr.c_str(), lang);
return lang;
Expand Down Expand Up @@ -607,41 +586,27 @@ std::string Shader::createShaderStageCode(Graphics *gfx, ShaderStageType stage,
if (info.stages[stage] == ENTRYPOINT_NONE)
throw love::Exception("Cannot find entry point for shader stage.");

if (info.stages[stage] == ENTRYPOINT_RAW && info.language == LANGUAGE_GLSL1)
throw love::Exception("Shaders using a raw entry point (vertexmain or pixelmain) must use GLSL 3 or greater.");

if (stage == SHADERSTAGE_COMPUTE && info.language != LANGUAGE_GLSL4)
throw love::Exception("Compute shaders must use GLSL 4.");

bool glsl1on3 = info.language == LANGUAGE_GLSL1;

if (checksystemfeatures)
{
const auto &features = gfx->getCapabilities().features;

if (stage == SHADERSTAGE_COMPUTE && !features[Graphics::FEATURE_GLSL4])
throw love::Exception("Compute shaders require GLSL 4 which is not supported on this system.");

if (info.language == LANGUAGE_GLSL3 && !features[Graphics::FEATURE_GLSL3])
throw love::Exception("GLSL 3 shaders are not supported on this system.");

if (info.language == LANGUAGE_GLSL4 && !features[Graphics::FEATURE_GLSL4])
throw love::Exception("GLSL 4 shaders are not supported on this system.");

glsl1on3 = info.language == LANGUAGE_GLSL1 && features[Graphics::FEATURE_GLSL3];
}

Language lang = info.language;
if (glsl1on3)
lang = LANGUAGE_GLSL3;

glsl::StageInfo stageinfo = glsl::stageInfo[stage];

std::stringstream ss;

ss << (gles ? glsl::versions[lang].glsles : glsl::versions[lang].glsl) << "\n";
if (glsl1on3)
ss << "#define LOVE_GLSL1_ON_GLSL3 1\n";

if (isGammaCorrect())
ss << "#define LOVE_GAMMA_CORRECT 1\n";
Expand All @@ -666,7 +631,7 @@ std::string Shader::createShaderStageCode(Graphics *gfx, ShaderStageType stage,
ss << stageinfo.main_raw;
else
throw love::Exception("Unknown shader entry point %d", info.stages[stage]);
ss << ((!gles && (lang == Shader::LANGUAGE_GLSL1 || glsl1on3)) ? "#line 0\n" : "#line 1\n");
ss << "#line 1\n";
ss << code;

return ss.str();
Expand Down Expand Up @@ -909,6 +874,18 @@ const std::vector<Buffer::DataDeclaration> *Shader::getBufferFormat(const std::s
return nullptr;
}

bool Shader::isUsingDeprecatedTextureFunctions() const
{
auto it = reflection.localUniforms.find("deprecatedTextureCall");
return it != reflection.localUniforms.end() && it->second.stageMask != 0;
}

bool Shader::isUsingDeprecatedTextureUniform() const
{
auto it = reflection.allUniforms.find("texture");
return it != reflection.allUniforms.end() && it->second->stageMask != 0;
}

bool Shader::validate(StrongRef<ShaderStage> stages[], std::string& err)
{
Reflection reflection;
Expand Down Expand Up @@ -1693,7 +1670,6 @@ const std::string &Shader::getDefaultCode(StandardShader shader, ShaderStageType

static StringMap<Shader::Language, Shader::LANGUAGE_MAX_ENUM>::Entry languageEntries[] =
{
{ "glsl1", Shader::LANGUAGE_GLSL1 },
{ "glsl3", Shader::LANGUAGE_GLSL3 },
{ "glsl4", Shader::LANGUAGE_GLSL4 },
};
Expand Down
4 changes: 3 additions & 1 deletion src/modules/graphics/Shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ class Shader : public Object, public Resource

enum Language
{
LANGUAGE_GLSL1,
LANGUAGE_GLSL3,
LANGUAGE_GLSL4,
LANGUAGE_MAX_ENUM
Expand Down Expand Up @@ -269,6 +268,9 @@ class Shader : public Object, public Resource

const std::vector<Buffer::DataDeclaration> *getBufferFormat(const std::string &name) const;

bool isUsingDeprecatedTextureFunctions() const;
bool isUsingDeprecatedTextureUniform() const;

static SourceInfo getSourceInfo(const std::string &src);
static std::string createShaderStageCode(Graphics *gfx, ShaderStageType stage, const std::string &code, const CompileOptions &options, const SourceInfo &info, bool gles, bool checksystemfeatures);

Expand Down
Loading

0 comments on commit ad0af74

Please sign in to comment.