diff --git a/filament/src/materials/blitLow.mat b/filament/src/materials/blitLow.mat index 1614857765..d504ec0c4c 100644 --- a/filament/src/materials/blitLow.mat +++ b/filament/src/materials/blitLow.mat @@ -34,8 +34,8 @@ vertex { fragment { void postProcess(inout PostProcessInputs postProcess) { -#if FILAMENT_EFFECTIVE_VERSION == 100 - postProcess.color = texture2D(materialParams_color, variable_vertex.xy); +#if MATERIAL_FEATURE_LEVEL == 0 + postProcess.color = texture(materialParams_color, variable_vertex.xy); #else postProcess.color = textureLod(materialParams_color, variable_vertex.xy, materialParams.levelOfDetail); #endif diff --git a/filament/src/materials/skybox.mat b/filament/src/materials/skybox.mat index 2f0bd3581d..db39f9f7bd 100644 --- a/filament/src/materials/skybox.mat +++ b/filament/src/materials/skybox.mat @@ -37,7 +37,7 @@ fragment { sky = materialParams.color; } else { #if MATERIAL_FEATURE_LEVEL == 0 - sky = vec4(textureCube(materialParams_skybox, variable_eyeDirection.xyz).rgb, 1.0); + sky = vec4(texture(materialParams_skybox, variable_eyeDirection.xyz).rgb, 1.0); #else sky = vec4(textureLod(materialParams_skybox, variable_eyeDirection.xyz, 0.0).rgb, 1.0); sky.rgb *= frameUniforms.iblLuminance; diff --git a/libs/filagui/src/materials/uiBlit.mat b/libs/filagui/src/materials/uiBlit.mat index 774113fbd3..9696de83c6 100644 --- a/libs/filagui/src/materials/uiBlit.mat +++ b/libs/filagui/src/materials/uiBlit.mat @@ -22,7 +22,7 @@ fragment { prepareMaterial(material); vec2 uv = getUV0(); uv.y = 1.0 - uv.y; - vec4 albedo = texture2D(materialParams_albedo, uv); + vec4 albedo = texture(materialParams_albedo, uv); material.baseColor = getColor() * albedo; material.baseColor.rgb *= material.baseColor.a; } diff --git a/libs/filagui/src/materials/uiBlitExternal.mat b/libs/filagui/src/materials/uiBlitExternal.mat index f07187837d..999b075ad3 100644 --- a/libs/filagui/src/materials/uiBlitExternal.mat +++ b/libs/filagui/src/materials/uiBlitExternal.mat @@ -22,7 +22,7 @@ fragment { prepareMaterial(material); vec2 uv = getUV0(); uv.y = 1.0 - uv.y; - vec4 albedo = texture2D(materialParams_albedo, uv); + vec4 albedo = texture(materialParams_albedo, uv); material.baseColor = getColor() * albedo; material.baseColor.rgb *= material.baseColor.a; } diff --git a/libs/filamat/src/GLSLPostProcessor.cpp b/libs/filamat/src/GLSLPostProcessor.cpp index c887967b41..6848e29652 100644 --- a/libs/filamat/src/GLSLPostProcessor.cpp +++ b/libs/filamat/src/GLSLPostProcessor.cpp @@ -950,6 +950,38 @@ bool GLSLPostProcessor::fullOptimization(const TShader& tShader, if (found != std::string::npos) { str.replace(found, clipDistanceDefinition.length(), ""); } + + // Validate the transpiled ESSL1 shader dynamically before considering it successful. + // This proactively catches unsupported SPIR-V -> ESSL1 translation quirks (like textureLod) + // at compile-time since we can't easily test all variants on physical GLES 2.0 devices. + if (config.featureLevel == 0) { + // preampitively forbid spirv-cross from cheating and polyfilling disabled features + auto const& exts = glslCompiler.get_required_extensions(); + for (auto const& ext : exts) { + if (ext != "GL_OES_standard_derivatives" && + ext != "GL_OES_EGL_image_external" && + ext != "GL_EXT_shader_framebuffer_fetch" && + ext != "GL_EXT_shader_framebuffer_fetch_non_coherent") { + slog.e << "ERROR: Feature Level 0 shaders cannot require: " << ext << ". " + << "spirv-cross attempted to unilaterally inject it." << io::endl; + return false; + } + } + + TShader validateShader(internalConfig.shLang); + // The cleaner must be declared after the TShader to manage the glslang memory pool + // teardown order correctly and safely destroy the AST. + GLSLangCleaner const validateCleaner; + + const char* shaderCString = str.c_str(); + validateShader.setStrings(&shaderCString, 1); + + bool const validateOk = validateShader.parse(&DefaultTBuiltInResource, glslOptions.version, false, EShMsgDefault); + if (!validateOk) { + slog.e << "ESSL1 Validation failed:\n" << validateShader.getInfoLog() << io::endl; + return false; + } + } } return true; } diff --git a/libs/filamat/src/MaterialBuilder.cpp b/libs/filamat/src/MaterialBuilder.cpp index ebeafda643..c71e6fceee 100644 --- a/libs/filamat/src/MaterialBuilder.cpp +++ b/libs/filamat/src/MaterialBuilder.cpp @@ -131,7 +131,7 @@ void MaterialBuilderBase::prepare(bool const vulkanSemantics, // OpenGL is a special case. If we're doing any optimization, then we need to go to Spir-V. TargetLanguage glTargetLanguage = mOptimization > Optimization::PREPROCESSOR ? TargetLanguage::SPIRV : TargetLanguage::GLSL; - if (vulkanSemantics) { + if (vulkanSemantics || featureLevel == backend::FeatureLevel::FEATURE_LEVEL_0) { // Currently GLSLPostProcessor.cpp is incapable of compiling SPIRV to GLSL without // running the optimizer. For now we just activate the optimizer in that case. mOptimization = Optimization::PERFORMANCE; @@ -167,7 +167,7 @@ void MaterialBuilderBase::prepare(bool const vulkanSemantics, && featureLevel == backend::FeatureLevel::FEATURE_LEVEL_0 && shaderModel == ShaderModel::MOBILE) { mCodeGenPermutations.push_back({ - shaderModel, + ShaderModel::MOBILE, TargetApi::OPENGL, glTargetLanguage, backend::FeatureLevel::FEATURE_LEVEL_0 @@ -938,6 +938,15 @@ bool MaterialBuilder::generateShaders(JobSystem& jobSystem, const std::vector= FeatureLevel::FEATURE_LEVEL_1) { - effective_version = "300"; - } else { - effective_version = "100"; - } - break; - case ShaderModel::DESKTOP: - if (mFeatureLevel >= FeatureLevel::FEATURE_LEVEL_2) { - effective_version = "450"; - } else { - effective_version = "410"; - } - break; - default: - assert(false); - } - } - generateDefine(out, "FILAMENT_EFFECTIVE_VERSION", effective_version); - switch (material.stereoscopicType) { case StereoscopicType::INSTANCED: generateDefine(out, "FILAMENT_STEREO_INSTANCED", true); @@ -253,17 +223,11 @@ utils::io::sstream& CodeGenerator::generateCommonProlog(utils::io::sstream& out, generateDefine(out, "MATERIAL_HAS_CUSTOM_DEPTH", material.userMaterialHasCustomDepth); } - if (mTargetLanguage == TargetLanguage::SPIRV || - mFeatureLevel >= FeatureLevel::FEATURE_LEVEL_1) { - if (stage == ShaderStage::VERTEX) { - generateDefine(out, "VARYING", "out"); - generateDefine(out, "ATTRIBUTE", "in"); - } else if (stage == ShaderStage::FRAGMENT) { - generateDefine(out, "VARYING", "in"); - } - } else { - generateDefine(out, "VARYING", "varying"); - generateDefine(out, "ATTRIBUTE", "attribute"); + if (stage == ShaderStage::VERTEX) { + generateDefine(out, "VARYING", "out"); + generateDefine(out, "ATTRIBUTE", "in"); + } else if (stage == ShaderStage::FRAGMENT) { + generateDefine(out, "VARYING", "in"); } auto getShadingDefine = [](Shading shading) -> const char* { @@ -361,31 +325,6 @@ utils::io::sstream& CodeGenerator::generateCommonProlog(utils::io::sstream& out, out << '\n'; out << SHADERS_COMMON_DEFINES_GLSL_DATA; - if (material.featureLevel == FeatureLevel::FEATURE_LEVEL_0 && - (mFeatureLevel > FeatureLevel::FEATURE_LEVEL_0 - || mTargetLanguage == TargetLanguage::SPIRV)) { - // Insert compatibility definitions for ESSL 1.0 functions which were removed in ESSL 3.0. - - // This is the minimum required value according to the OpenGL ES Shading Language Version - // 1.00 document. glslang forbids defining symbols beginning with gl_ as const, hence the - // #define. - generateDefine(out, "gl_MaxVaryingVectors", "8"); - - generateDefine(out, "texture2D", "texture"); - generateDefine(out, "texture2DProj", "textureProj"); - generateDefine(out, "texture3D", "texture"); - generateDefine(out, "texture3DProj", "textureProj"); - generateDefine(out, "textureCube", "texture"); - - if (stage == ShaderStage::VERTEX) { - generateDefine(out, "texture2DLod", "textureLod"); - generateDefine(out, "texture2DProjLod", "textureProjLod"); - generateDefine(out, "texture3DLod", "textureLod"); - generateDefine(out, "texture3DProjLod", "textureProjLod"); - generateDefine(out, "textureCubeLod", "textureLod"); - } - } - // Api level enforcement. generateDefine(out, "CLIENT_MATERIAL_API_LEVEL", apiLevel); generateDefine(out, "UNSTABLE_MATERIAL_API_LEVEL", filament::UNSTABLE_MATERIAL_API_LEVEL); diff --git a/libs/filamat/src/shaders/ShaderGenerator.cpp b/libs/filamat/src/shaders/ShaderGenerator.cpp index 81390ff1e8..43b5a44b0e 100644 --- a/libs/filamat/src/shaders/ShaderGenerator.cpp +++ b/libs/filamat/src/shaders/ShaderGenerator.cpp @@ -689,6 +689,8 @@ std::string ShaderGenerator::createSurfaceComputeProgram(ShaderModel const shade generateUserSpecConstants(cg, s, mConstants); + CodeGenerator::generateDefine(s, "MATERIAL_FEATURE_LEVEL", uint32_t(featureLevel)); + CodeGenerator::generateSurfaceTypes(s, ShaderStage::COMPUTE); cg.generateUniforms(s, ShaderStage::COMPUTE, diff --git a/libs/filamat/tests/test_filamat.cpp b/libs/filamat/tests/test_filamat.cpp index c130ef7ff5..2caac4a78c 100644 --- a/libs/filamat/tests/test_filamat.cpp +++ b/libs/filamat/tests/test_filamat.cpp @@ -923,7 +923,7 @@ TEST_F(MaterialCompiler, FeatureLevel0Sampler2D) { std::string shaderCode(R"( void material(inout MaterialInputs material) { prepareMaterial(material); - material.baseColor = texture2D(materialParams_sampler, vec2(0.0, 0.0)); + material.baseColor = texture(materialParams_sampler, vec2(0.0, 0.0)); } )"); filamat::MaterialBuilder builder; @@ -941,7 +941,7 @@ TEST_F(MaterialCompiler, SamplerTransformName) { void material(inout MaterialInputs material) { prepareMaterial(material); vec3 uvw = materialParams.sampler_transform * vec3(0.0, 0.0, 0.0); - material.baseColor = texture2D(materialParams_sampler, uvw.xy); + material.baseColor = texture(materialParams_sampler, uvw.xy); } )"); filamat::MaterialBuilder builder; @@ -960,7 +960,7 @@ TEST_F(MaterialCompiler, SamplerMissingTransformName) { void material(inout MaterialInputs material) { prepareMaterial(material); vec3 uvw = materialParams.sampler_transform * vec3(0.0, 0.0, 0.0); - material.baseColor = texture2D(materialParams_sampler, uvw.xy); + material.baseColor = texture(materialParams_sampler, uvw.xy); } )"); filamat::MaterialBuilder builder; diff --git a/shaders/src/common_getters.glsl b/shaders/src/common_getters.glsl index 856ed5a639..059a066ed4 100644 --- a/shaders/src/common_getters.glsl +++ b/shaders/src/common_getters.glsl @@ -46,7 +46,7 @@ highp mat4 getViewFromClipMatrix() { return frameUniforms.viewFromClipMatrix; } -#if FILAMENT_EFFECTIVE_VERSION > 100 +#if MATERIAL_FEATURE_LEVEL > 0 /** @public-api */ highp mat4 getEyeFromViewMatrix() { return frameUniforms.eyeFromViewMatrix[getEyeIndex()]; diff --git a/shaders/src/surface_depth_main.fs b/shaders/src/surface_depth_main.fs index 261608ae4f..d568da5baf 100644 --- a/shaders/src/surface_depth_main.fs +++ b/shaders/src/surface_depth_main.fs @@ -1,14 +1,10 @@ #if defined(VARIANT_HAS_VSM) layout(location = 0) out highp vec4 fragColor; #elif defined(VARIANT_HAS_PICKING) -# if __VERSION__ == 100 -highp vec4 outPicking; -# else -# if MATERIAL_FEATURE_LEVEL == 0 +# if MATERIAL_FEATURE_LEVEL == 0 layout(location = 0) out highp vec4 outPicking; -# else +# else layout(location = 0) out highp uvec2 outPicking; -# endif # endif #else // not color output @@ -55,7 +51,7 @@ void main() { highp float depth = vertex_worldPosition.w; fragColor = computeDepthMomentsVSM(depth); #elif defined(VARIANT_HAS_PICKING) -#if FILAMENT_EFFECTIVE_VERSION == 100 +#if MATERIAL_FEATURE_LEVEL == 0 outPicking.a = mod(float(object_uniforms_objectId / 65536), 256.0) / 255.0; outPicking.b = mod(float(object_uniforms_objectId / 256), 256.0) / 255.0; outPicking.g = mod(float(object_uniforms_objectId) , 256.0) / 255.0; @@ -64,9 +60,7 @@ void main() { outPicking.x = uint(object_uniforms_objectId); outPicking.y = floatBitsToUint(vertex_position.z / vertex_position.w); #endif -#if __VERSION__ == 100 - gl_FragData[0] = outPicking; -#endif + #else // that's it #endif diff --git a/shaders/src/surface_getters.vs b/shaders/src/surface_getters.vs index 1a71a06fa6..e65972c7e6 100644 --- a/shaders/src/surface_getters.vs +++ b/shaders/src/surface_getters.vs @@ -23,7 +23,7 @@ float getObjectUserData() { // Attributes access //------------------------------------------------------------------------------ -#if __VERSION__ >= 300 +#if MATERIAL_FEATURE_LEVEL > 0 /** @public-api */ int getVertexIndex() { #if defined(TARGET_METAL_ENVIRONMENT) || defined(TARGET_VULKAN_ENVIRONMENT) || defined(TARGET_WEBGPU_ENVIRONMENT) diff --git a/shaders/src/surface_main.fs b/shaders/src/surface_main.fs index 92c1185826..c36e9a7b4b 100644 --- a/shaders/src/surface_main.fs +++ b/shaders/src/surface_main.fs @@ -1,8 +1,4 @@ -#if __VERSION__ == 100 -vec4 fragColor; -#else layout(location = 0) out vec4 fragColor; -#endif #if defined(MATERIAL_HAS_POST_LIGHTING_COLOR) void blendPostLightingColor(const MaterialInputs material, inout vec4 color) { @@ -119,7 +115,5 @@ void main() { } #endif -#if __VERSION__ == 100 - gl_FragData[0] = fragColor; -#endif + }