From 57fff3a63695e5fb2f73eefe2ffc7381511d2f5e Mon Sep 17 00:00:00 2001 From: Sungun Park Date: Wed, 28 Feb 2024 14:14:44 -0800 Subject: [PATCH] Add a new material param, stereoscopicType (#7613) * Add a new material param, stereoscopicType This new parameter allows us to specify which implementation of stereoscopic rendering Filament uses for the material. This change just includes material parameter addition and shader code changes, so it doesn't affect the current rendering behavior. These changes will follow as separate commits. - render pipeline changes - material parameter override via matc parameter - material document update --- libs/filamat/include/filamat/MaterialBuilder.h | 5 +++++ libs/filamat/src/MaterialBuilder.cpp | 6 ++++++ libs/filamat/src/shaders/CodeGenerator.cpp | 9 +++++++++ libs/filamat/src/shaders/MaterialInfo.h | 1 + shaders/src/common_getters.glsl | 4 ++++ shaders/src/main.vs | 6 +++--- shaders/src/varyings.glsl | 2 +- tools/matc/src/matc/ParametersProcessor.cpp | 15 +++++++++++++++ 8 files changed, 44 insertions(+), 4 deletions(-) diff --git a/libs/filamat/include/filamat/MaterialBuilder.h b/libs/filamat/include/filamat/MaterialBuilder.h index bd586fe92e..f3e2080df6 100644 --- a/libs/filamat/include/filamat/MaterialBuilder.h +++ b/libs/filamat/include/filamat/MaterialBuilder.h @@ -243,6 +243,7 @@ public: using Precision = filament::backend::Precision; using CullingMode = filament::backend::CullingMode; using FeatureLevel = filament::backend::FeatureLevel; + using StereoscopicType = filament::backend::StereoscopicType; enum class VariableQualifier : uint8_t { OUT @@ -521,6 +522,9 @@ public: //! Specifies how transparent objects should be rendered (default is DEFAULT). MaterialBuilder& transparencyMode(TransparencyMode mode) noexcept; + //! Specify the stereoscopic type (default is INSTANCED) + MaterialBuilder& stereoscopicType(StereoscopicType stereoscopicType) noexcept; + /** * Enable / disable custom surface shading. Custom surface shading requires the LIT * shading model. In addition, the following function must be defined in the fragment @@ -829,6 +833,7 @@ private: Interpolation mInterpolation = Interpolation::SMOOTH; VertexDomain mVertexDomain = VertexDomain::OBJECT; TransparencyMode mTransparencyMode = TransparencyMode::DEFAULT; + StereoscopicType mStereoscopicType = StereoscopicType::INSTANCED; filament::AttributeBitset mRequiredAttributes; diff --git a/libs/filamat/src/MaterialBuilder.cpp b/libs/filamat/src/MaterialBuilder.cpp index 492c898c69..f022c0a983 100644 --- a/libs/filamat/src/MaterialBuilder.cpp +++ b/libs/filamat/src/MaterialBuilder.cpp @@ -498,6 +498,11 @@ MaterialBuilder& MaterialBuilder::transparencyMode(TransparencyMode mode) noexce return *this; } +MaterialBuilder& MaterialBuilder::stereoscopicType(StereoscopicType stereoscopicType) noexcept { + mStereoscopicType = stereoscopicType; + return *this; +} + MaterialBuilder& MaterialBuilder::reflectionMode(ReflectionMode mode) noexcept { mReflectionMode = mode; return *this; @@ -632,6 +637,7 @@ void MaterialBuilder::prepareToBuild(MaterialInfo& info) noexcept { info.vertexDomainDeviceJittered = mVertexDomainDeviceJittered; info.featureLevel = mFeatureLevel; info.groupSize = mGroupSize; + info.stereoscopicType = mStereoscopicType; // This is determined via static analysis of the glsl after prepareToBuild(). info.userMaterialHasCustomDepth = false; diff --git a/libs/filamat/src/shaders/CodeGenerator.cpp b/libs/filamat/src/shaders/CodeGenerator.cpp index a739e726e9..f713411e8b 100644 --- a/libs/filamat/src/shaders/CodeGenerator.cpp +++ b/libs/filamat/src/shaders/CodeGenerator.cpp @@ -181,6 +181,15 @@ utils::io::sstream& CodeGenerator::generateProlog(utils::io::sstream& out, Shade } generateDefine(out, "FILAMENT_EFFECTIVE_VERSION", effective_version); + switch (material.stereoscopicType) { + case StereoscopicType::INSTANCED: + generateDefine(out, "FILAMENT_STEREO_INSTANCED", true); + break; + case StereoscopicType::MULTIVIEW: + generateDefine(out, "FILAMENT_STEREO_MULTIVIEW", true); + break; + } + if (stage == ShaderStage::VERTEX) { CodeGenerator::generateDefine(out, "FLIP_UV_ATTRIBUTE", material.flipUV); CodeGenerator::generateDefine(out, "LEGACY_MORPHING", material.useLegacyMorphing); diff --git a/libs/filamat/src/shaders/MaterialInfo.h b/libs/filamat/src/shaders/MaterialInfo.h index b12863cede..5ede9f8c1f 100644 --- a/libs/filamat/src/shaders/MaterialInfo.h +++ b/libs/filamat/src/shaders/MaterialInfo.h @@ -68,6 +68,7 @@ struct UTILS_PUBLIC MaterialInfo { filament::SamplerBindingMap samplerBindings; filament::ShaderQuality quality; filament::backend::FeatureLevel featureLevel; + filament::backend::StereoscopicType stereoscopicType; filament::math::uint3 groupSize; using BufferContainer = utils::FixedCapacityVector; diff --git a/shaders/src/common_getters.glsl b/shaders/src/common_getters.glsl index eaa2521d85..a2bbebe4f8 100644 --- a/shaders/src/common_getters.glsl +++ b/shaders/src/common_getters.glsl @@ -25,8 +25,12 @@ highp mat4 getViewFromClipMatrix() { /** @public-api */ highp mat4 getClipFromWorldMatrix() { #if defined(VARIANT_HAS_STEREO) +#if defined(FILAMENT_STEREO_INSTANCED) int eye = instance_index % CONFIG_STEREO_EYE_COUNT; return frameUniforms.clipFromWorldMatrix[eye]; +#elif defined(FILAMENT_STEREO_MULTIVIEW) + return frameUniforms.clipFromWorldMatrix[gl_ViewID_OVR]; +#endif #else return frameUniforms.clipFromWorldMatrix[0]; #endif diff --git a/shaders/src/main.vs b/shaders/src/main.vs index 5ef0ebbe20..bbb9230fc8 100644 --- a/shaders/src/main.vs +++ b/shaders/src/main.vs @@ -23,7 +23,7 @@ void main() { logical_instance_index = instance_index; #endif -#if defined(VARIANT_HAS_STEREO) +#if defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_INSTANCED) #if !defined(FILAMENT_HAS_FEATURE_INSTANCING) #error Instanced stereo not supported at this feature level #endif @@ -215,7 +215,7 @@ void main() { // this must happen before we compensate for vulkan below vertex_position = position; -#if defined(VARIANT_HAS_STEREO) +#if defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_INSTANCED) // We're transforming a vertex whose x coordinate is within the range (-w to w). // To move it to the correct portion of the viewport, we need to modify the x coordinate. // It's important to do this after computing vertex_position. @@ -253,7 +253,7 @@ void main() { // some PowerVR drivers crash when gl_Position is written more than once gl_Position = position; -#if defined(VARIANT_HAS_STEREO) +#if defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_INSTANCED) // Fragment shaders filter out the stereo variant, so we need to set instance_index here. instance_index = logical_instance_index; #endif diff --git a/shaders/src/varyings.glsl b/shaders/src/varyings.glsl index a7a48a302f..a0478838de 100644 --- a/shaders/src/varyings.glsl +++ b/shaders/src/varyings.glsl @@ -34,7 +34,7 @@ LAYOUT_LOCATION(11) VARYING highp vec4 vertex_lightSpacePosition; // Note that fragColor is an output and is not declared here; see main.fs and depth_main.fs -#if defined(VARIANT_HAS_STEREO) +#if defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_INSTANCED) #if defined(GL_ES) && defined(FILAMENT_GLSLANG) // On ES, gl_ClipDistance is not a built-in, so we have to rely on EXT_clip_cull_distance // However, this extension is not supported by glslang, so we instead write to diff --git a/tools/matc/src/matc/ParametersProcessor.cpp b/tools/matc/src/matc/ParametersProcessor.cpp index 50d3ab7420..eacf7f24aa 100644 --- a/tools/matc/src/matc/ParametersProcessor.cpp +++ b/tools/matc/src/matc/ParametersProcessor.cpp @@ -796,6 +796,20 @@ static bool processGroupSizes(MaterialBuilder& builder, const JsonishValue& v) { return true; } +static bool processStereoscopicType(MaterialBuilder& builder, const JsonishValue& value) { + static const std::unordered_map strToEnum{ + { "instanced", MaterialBuilder::StereoscopicType::INSTANCED }, + { "multiview", MaterialBuilder::StereoscopicType::MULTIVIEW }, + }; + auto jsonString = value.toJsonString(); + if (!isStringValidEnum(strToEnum, jsonString->getString())) { + return logEnumIssue("stereoscopicType", *jsonString, strToEnum); + } + + builder.stereoscopicType(stringToEnum(strToEnum, jsonString->getString())); + return true; +} + static bool processOutput(MaterialBuilder& builder, const JsonishObject& jsonObject) noexcept { const JsonishValue* nameValue = jsonObject.getValue("name"); @@ -1214,6 +1228,7 @@ ParametersProcessor::ParametersProcessor() { mParameters["customSurfaceShading"] = { &processCustomSurfaceShading, Type::BOOL }; mParameters["featureLevel"] = { &processFeatureLevel, Type::NUMBER }; mParameters["groupSize"] = { &processGroupSizes, Type::ARRAY }; + mParameters["stereoscopicType"] = { &processStereoscopicType, Type::STRING }; } bool ParametersProcessor::process(MaterialBuilder& builder, const JsonishObject& jsonObject) {