From 923ac98ea85bb2accf5ad8f92ea03dd4c4d6a979 Mon Sep 17 00:00:00 2001 From: Sungun Park Date: Mon, 3 Feb 2025 17:44:44 -0800 Subject: [PATCH] Add multiview_data for multiview information Add a varying variable `multiview_data` for both surface and post-processing shaders. Currently this only works as intended in surface shader, and additional implementation to facilitate it for post-processing will be following. The `multiview_data` contains multiview information like whether multiview is enabled for the current material and what the eye index is in that case. This variable is globally available including fragment shaders so that it can be referenced in user shaders in .material files. Also this allows us to indirectly reference the constant variables such as `gl_ViewID_OVR` and `gl_ViewIndex` in a platform-agnostic way. Make the preprocessor `MATERIAL_FEATURE_LEVEL` available for both surface and post-processing shaders, it used to be only available for surface shader, and this will be referenced in post-processing shaders later to support multiview for post-processing. --- libs/filamat/src/shaders/CodeGenerator.cpp | 6 +++++- libs/filamat/src/shaders/CodeGenerator.h | 2 +- libs/filamat/src/shaders/ShaderGenerator.cpp | 5 ++--- shaders/CMakeLists.txt | 1 + shaders/src/common_getters.glsl | 8 +------- shaders/src/common_varyings.glsl | 13 +++++++++++++ shaders/src/surface_getters.vs | 9 +-------- shaders/src/surface_main.vs | 11 +++++++++++ shaders/src/surface_varyings.glsl | 2 +- 9 files changed, 36 insertions(+), 21 deletions(-) create mode 100644 shaders/src/common_varyings.glsl diff --git a/libs/filamat/src/shaders/CodeGenerator.cpp b/libs/filamat/src/shaders/CodeGenerator.cpp index 4b41e7974d..e4478057d1 100644 --- a/libs/filamat/src/shaders/CodeGenerator.cpp +++ b/libs/filamat/src/shaders/CodeGenerator.cpp @@ -365,6 +365,8 @@ utils::io::sstream& CodeGenerator::generateCommonProlog(utils::io::sstream& out, out << '\n'; out << SHADERS_COMMON_DEFINES_GLSL_DATA; + CodeGenerator::generateDefine(out, "MATERIAL_FEATURE_LEVEL", uint32_t(mFeatureLevel)); + if (material.featureLevel == FeatureLevel::FEATURE_LEVEL_0 && (mFeatureLevel > FeatureLevel::FEATURE_LEVEL_0 || mTargetLanguage == TargetLanguage::SPIRV)) { @@ -485,7 +487,7 @@ io::sstream& CodeGenerator::generateCommonVariable(io::sstream& out, ShaderStage return out; } -io::sstream& CodeGenerator::generateSurfaceShaderInputs(io::sstream& out, ShaderStage stage, +io::sstream& CodeGenerator::generateSurfaceInputs(io::sstream& out, ShaderStage stage, const AttributeBitset& attributes, Interpolation interpolation, MaterialBuilder::PushConstantList const& pushConstants) const { auto const& attributeDatabase = MaterialBuilder::getAttributeDatabase(); @@ -517,6 +519,7 @@ io::sstream& CodeGenerator::generateSurfaceShaderInputs(io::sstream& out, Shader } out << "\n"; + out << SHADERS_COMMON_VARYINGS_GLSL_DATA; out << SHADERS_SURFACE_VARYINGS_GLSL_DATA; return out; } @@ -1073,6 +1076,7 @@ io::sstream& CodeGenerator::generateSurfaceMaterial(io::sstream& out, ShaderStag } io::sstream& CodeGenerator::generatePostProcessInputs(io::sstream& out, ShaderStage stage) { + out << SHADERS_COMMON_VARYINGS_GLSL_DATA; if (stage == ShaderStage::VERTEX) { out << SHADERS_POST_PROCESS_INPUTS_VS_DATA; } else if (stage == ShaderStage::FRAGMENT) { diff --git a/libs/filamat/src/shaders/CodeGenerator.h b/libs/filamat/src/shaders/CodeGenerator.h index 4bc7bc8f29..0ab019b9d4 100644 --- a/libs/filamat/src/shaders/CodeGenerator.h +++ b/libs/filamat/src/shaders/CodeGenerator.h @@ -109,7 +109,7 @@ public: const MaterialBuilder::CustomVariable& variable, size_t index); // generate declarations for non-custom "in" variables - utils::io::sstream& generateSurfaceShaderInputs(utils::io::sstream& out, ShaderStage stage, + utils::io::sstream& generateSurfaceInputs(utils::io::sstream& out, ShaderStage stage, const filament::AttributeBitset& attributes, filament::Interpolation interpolation, MaterialBuilder::PushConstantList const& pushConstants) const; static utils::io::sstream& generatePostProcessInputs(utils::io::sstream& out, ShaderStage stage); diff --git a/libs/filamat/src/shaders/ShaderGenerator.cpp b/libs/filamat/src/shaders/ShaderGenerator.cpp index 8b011598c7..afe337ea54 100644 --- a/libs/filamat/src/shaders/ShaderGenerator.cpp +++ b/libs/filamat/src/shaders/ShaderGenerator.cpp @@ -81,7 +81,6 @@ void ShaderGenerator::generateSurfaceMaterialVariantDefines(utils::io::sstream& } out << '\n'; - CodeGenerator::generateDefine(out, "MATERIAL_FEATURE_LEVEL", uint32_t(featureLevel)); CodeGenerator::generateDefine(out, "MATERIAL_HAS_SHADOW_MULTIPLIER", material.hasShadowMultiplier); @@ -436,7 +435,7 @@ std::string ShaderGenerator::createSurfaceVertexProgram(ShaderModel shaderModel, [](MaterialBuilder::PushConstant const& constant) { return constant.stage == ShaderStage::VERTEX; }); - cg.generateSurfaceShaderInputs(vs, ShaderStage::VERTEX, attributes, interpolation, + cg.generateSurfaceInputs(vs, ShaderStage::VERTEX, attributes, interpolation, vertexPushConstants); CodeGenerator::generateSurfaceTypes(vs, ShaderStage::VERTEX); @@ -546,7 +545,7 @@ std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel shaderMode [](MaterialBuilder::PushConstant const& constant) { return constant.stage == ShaderStage::FRAGMENT; }); - cg.generateSurfaceShaderInputs(fs, ShaderStage::FRAGMENT, material.requiredAttributes, interpolation, + cg.generateSurfaceInputs(fs, ShaderStage::FRAGMENT, material.requiredAttributes, interpolation, fragmentPushConstants); CodeGenerator::generateSurfaceTypes(fs, ShaderStage::FRAGMENT); diff --git a/shaders/CMakeLists.txt b/shaders/CMakeLists.txt index 7109c239c2..ba5cc1ef27 100644 --- a/shaders/CMakeLists.txt +++ b/shaders/CMakeLists.txt @@ -21,6 +21,7 @@ set(SHADERS src/surface_material.fs src/common_math.glsl src/common_shading.fs + src/common_varyings.glsl src/surface_shadowing.glsl src/surface_types.glsl src/surface_depth_main.fs diff --git a/shaders/src/common_getters.glsl b/shaders/src/common_getters.glsl index 95ea0799f2..40ecc81d2f 100644 --- a/shaders/src/common_getters.glsl +++ b/shaders/src/common_getters.glsl @@ -28,13 +28,7 @@ highp mat4 getClipFromWorldMatrix() { int eye = instance_index % CONFIG_STEREO_EYE_COUNT; return frameUniforms.clipFromWorldMatrix[eye]; #elif defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_MULTIVIEW) - -#if defined(TARGET_VULKAN_ENVIRONMENT) - return frameUniforms.clipFromWorldMatrix[gl_ViewIndex]; -#else - return frameUniforms.clipFromWorldMatrix[gl_ViewID_OVR]; -#endif // TARGET_VULKAN_ENVIRONMENT - + return frameUniforms.clipFromWorldMatrix[multiview_data.y]; #else return frameUniforms.clipFromWorldMatrix[0]; #endif diff --git a/shaders/src/common_varyings.glsl b/shaders/src/common_varyings.glsl new file mode 100644 index 0000000000..8a1a69cb26 --- /dev/null +++ b/shaders/src/common_varyings.glsl @@ -0,0 +1,13 @@ +//------------------------------------------------------------------------------ +// Common Varyings +//------------------------------------------------------------------------------ + +// The `multiview_data` variable is to pass the current state of multiview set in the vertex shader +// to the fragment shader. `x` means whether multiview is used, `y` means the current view index. +// Neither the multiview feature nor the `flat` keyword is supported in FL0. So, for FL0, declare +// it as a non-flat and non-varying variable and set it to zeros as a placeholder. +#if MATERIAL_FEATURE_LEVEL > 0 +LAYOUT_LOCATION(99) flat VARYING ivec2 multiview_data; +#else +ivec2 multiview_data = ivec2(0, 0); +#endif diff --git a/shaders/src/surface_getters.vs b/shaders/src/surface_getters.vs index a9b8c293ac..5dd35687b3 100644 --- a/shaders/src/surface_getters.vs +++ b/shaders/src/surface_getters.vs @@ -284,14 +284,7 @@ int getEyeIndex() { #if defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_INSTANCED) return instance_index % CONFIG_STEREO_EYE_COUNT; #elif defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_MULTIVIEW) - -#if defined(TARGET_VULKAN_ENVIRONMENT) - return int(gl_ViewIndex); -#else - // gl_ViewID_OVR is of uint type, which needs an explicit conversion. - return int(gl_ViewID_OVR); -#endif // TARGET_VULKAN_ENVIRONMENT - + return int(multiview_data.y); #endif return 0; } diff --git a/shaders/src/surface_main.vs b/shaders/src/surface_main.vs index c8882de005..3078dead9a 100644 --- a/shaders/src/surface_main.vs +++ b/shaders/src/surface_main.vs @@ -31,6 +31,17 @@ void main() { logical_instance_index = instance_index / CONFIG_STEREO_EYE_COUNT; #endif +#if defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_MULTIVIEW) +# if defined(TARGET_VULKAN_ENVIRONMENT) + int multiview_view_index = int(gl_ViewIndex); +# else + int multiview_view_index = int(gl_ViewID_OVR); +# endif // TARGET_VULKAN_ENVIRONMENT + multiview_data = ivec2(1, int(multiview_view_index)); +#else + multiview_data = ivec2(0, 0); +#endif + initObjectUniforms(); // Initialize the inputs to sensible default values, see surface_material_inputs.vs diff --git a/shaders/src/surface_varyings.glsl b/shaders/src/surface_varyings.glsl index 7c1432ef98..7de7b1e275 100644 --- a/shaders/src/surface_varyings.glsl +++ b/shaders/src/surface_varyings.glsl @@ -1,5 +1,5 @@ //------------------------------------------------------------------------------ -// Varyings +// Surface Varyings //------------------------------------------------------------------------------ LAYOUT_LOCATION(4) VARYING highp vec4 vertex_worldPosition;