FL0 materials are always compile via spirv-cross
This commit is contained in:
committed by
Mathias Agopian
parent
62ac2950c9
commit
8ec732dadc
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<Va
|
||||
JobSystem::Job* parent = jobSystem.createJob();
|
||||
|
||||
for (const auto& v : variants) {
|
||||
if (params.featureLevel == FeatureLevel::FEATURE_LEVEL_0) {
|
||||
assert_invariant(params.shaderModel == ShaderModel::MOBILE);
|
||||
assert_invariant(params.targetApi == TargetApi::OPENGL);
|
||||
if (filament::Variant::isStereoVariant(v.variant)) {
|
||||
// the stereo variant can never be used at feature level 0
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
JobSystem::Job* job = jobs::createJob(jobSystem, parent, [&]() {
|
||||
if (cancelJobs.load()) {
|
||||
return;
|
||||
@@ -1319,8 +1328,7 @@ error:
|
||||
CodeGenParams const semanticCodeGenParams = {
|
||||
.shaderModel = ShaderModel::MOBILE,
|
||||
.targetApi = TargetApi::OPENGL,
|
||||
.targetLanguage = (info.featureLevel == FeatureLevel::FEATURE_LEVEL_0) ?
|
||||
TargetLanguage::GLSL : TargetLanguage::SPIRV,
|
||||
.targetLanguage = TargetLanguage::SPIRV,
|
||||
.featureLevel = info.featureLevel,
|
||||
};
|
||||
|
||||
|
||||
@@ -202,36 +202,6 @@ utils::io::sstream& CodeGenerator::generateCommonProlog(utils::io::sstream& out,
|
||||
out << "#define FILAMENT_HAS_FEATURE_INSTANCING\n";
|
||||
}
|
||||
|
||||
// During compilation and optimization, __VERSION__ reflects the shader language version of the
|
||||
// intermediate code, not the version of the final code. spirv-cross automatically adapts
|
||||
// certain language features (e.g. fragment output) but leaves others untouched (e.g. sampler
|
||||
// functions, bit shift operations). Client code may have to make decisions based on this
|
||||
// information, so define a FILAMENT_EFFECTIVE_VERSION constant.
|
||||
const char *effective_version;
|
||||
if (mTargetLanguage == TargetLanguage::GLSL) {
|
||||
effective_version = "__VERSION__";
|
||||
} else {
|
||||
switch (mShaderModel) {
|
||||
case ShaderModel::MOBILE:
|
||||
if (mFeatureLevel >= 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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()];
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user