diff --git a/src/modules/graphics/Shader.cpp b/src/modules/graphics/Shader.cpp index 9b2659030..14fb6f63d 100644 --- a/src/modules/graphics/Shader.cpp +++ b/src/modules/graphics/Shader.cpp @@ -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 )"; @@ -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); } @@ -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"( @@ -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); @@ -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 @@ -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); @@ -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 @@ -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(); @@ -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" }, }; @@ -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; @@ -607,14 +586,9 @@ 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; @@ -622,26 +596,17 @@ std::string Shader::createShaderStageCode(Graphics *gfx, ShaderStageType stage, 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"; @@ -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(); @@ -909,6 +874,18 @@ const std::vector *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 stages[], std::string& err) { Reflection reflection; @@ -1693,7 +1670,6 @@ const std::string &Shader::getDefaultCode(StandardShader shader, ShaderStageType static StringMap::Entry languageEntries[] = { - { "glsl1", Shader::LANGUAGE_GLSL1 }, { "glsl3", Shader::LANGUAGE_GLSL3 }, { "glsl4", Shader::LANGUAGE_GLSL4 }, }; diff --git a/src/modules/graphics/Shader.h b/src/modules/graphics/Shader.h index 7c90031fd..760d6c9e1 100644 --- a/src/modules/graphics/Shader.h +++ b/src/modules/graphics/Shader.h @@ -51,7 +51,6 @@ class Shader : public Object, public Resource enum Language { - LANGUAGE_GLSL1, LANGUAGE_GLSL3, LANGUAGE_GLSL4, LANGUAGE_MAX_ENUM @@ -269,6 +268,9 @@ class Shader : public Object, public Resource const std::vector *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); diff --git a/src/modules/graphics/ShaderStage.cpp b/src/modules/graphics/ShaderStage.cpp index d079cfa96..ea628a7c2 100644 --- a/src/modules/graphics/ShaderStage.cpp +++ b/src/modules/graphics/ShaderStage.cpp @@ -48,19 +48,15 @@ ShaderStage::ShaderStage(Graphics *gfx, ShaderStageType stage, const std::string auto glslangShader = new glslang::TShader(glslangStage); - bool supportsGLSL3 = gfx->getCapabilities().features[Graphics::FEATURE_GLSL3]; - int defaultversion = gles ? 100 : 120; - EProfile defaultprofile = ENoProfile; + int defaultversion = gles ? 300 : 330; + EProfile defaultprofile = gles ? EEsProfile : ECoreProfile; const char *csrc = glsl.c_str(); int srclen = (int) glsl.length(); glslangShader->setStringsWithLengths(&csrc, &srclen, 1); bool forcedefault = false; - if (source.find("#define LOVE_GLSL1_ON_GLSL3") != std::string::npos) - forcedefault = true; - - bool forwardcompat = supportsGLSL3 && !forcedefault; + bool forwardcompat = true; if (!glslangShader->parse(GetResources(), defaultversion, defaultprofile, forcedefault, forwardcompat, EShMsgSuppressWarnings)) { diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 851c4770d..ba8faff05 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -1595,6 +1595,10 @@ int w_newShader(lua_State *L) try { Shader *shader = instance()->newShader(stages, options); + if (shader->isUsingDeprecatedTextureFunctions()) + luax_markdeprecated(L, 1, "texture2D() or textureCube() function calls in shader code", API_CUSTOM, DEPRECATED_REPLACED, "texture() function calls"); + if (shader->isUsingDeprecatedTextureUniform()) + luax_markdeprecated(L, 1, "'texture' uniform variable name in shader code", API_CUSTOM, DEPRECATED_NO_REPLACEMENT, ""); luax_pushtype(L, shader); shader->release(); } @@ -1624,6 +1628,10 @@ int w_newComputeShader(lua_State* L) try { Shader *shader = instance()->newComputeShader(stages[0], options); + if (shader->isUsingDeprecatedTextureFunctions()) + luax_markdeprecated(L, 1, "texture2D() or textureCube() function calls in shader code", API_CUSTOM, DEPRECATED_REPLACED, "texture() function calls"); + if (shader->isUsingDeprecatedTextureUniform()) + luax_markdeprecated(L, 1, "'texture' uniform variable name in shader code", API_CUSTOM, DEPRECATED_NO_REPLACEMENT, ""); luax_pushtype(L, shader); shader->release(); }