diff --git a/docs/Materials.md.html b/docs/Materials.md.html
index 0148faed18..e5d6a33829 100644
--- a/docs/Materials.md.html
+++ b/docs/Materials.md.html
@@ -1920,6 +1920,7 @@ The following APIs are only available from the vertex block:
**getCustom0()** to **getCustom7()** | float4 | Custom vertex attribute
**getWorldFromModelMatrix()** | float4x4 | Matrix that converts from model (object) space to world space
**getWorldFromModelNormalMatrix()** | float3x3 | Matrix that converts normals from model (object) space to world space
+**getVertexIndex()** | int | Index of the current vertex
### Fragment only
diff --git a/libs/filamat/src/GLSLPostProcessor.cpp b/libs/filamat/src/GLSLPostProcessor.cpp
index 07ec121a2c..5b2f8f897b 100644
--- a/libs/filamat/src/GLSLPostProcessor.cpp
+++ b/libs/filamat/src/GLSLPostProcessor.cpp
@@ -158,8 +158,11 @@ bool GLSLPostProcessor::process(const std::string& inputShader, Config const& co
std::string* outputGlsl, SpirvBlob* outputSpirv, std::string* outputMsl) {
// If TargetApi is Vulkan, then we need post-processing even if there's no optimization.
+ // If we're using framebuffer fetch, we also need to force our compilation target to Vulkan, as
+ // it is only supported in GLSL for Vulkan.
using TargetApi = MaterialBuilder::TargetApi;
- const TargetApi targetApi = outputSpirv ? TargetApi::VULKAN : TargetApi::OPENGL;
+ const TargetApi targetApi = (outputSpirv || config.hasFramebufferFetch) ? TargetApi::VULKAN :
+ TargetApi::OPENGL;
if (targetApi == TargetApi::OPENGL && mOptimization == MaterialBuilder::Optimization::NONE) {
*outputGlsl = inputShader;
if (mPrintShaders) {
@@ -190,7 +193,8 @@ bool GLSLPostProcessor::process(const std::string& inputShader, Config const& co
tShader.setStrings(&shaderCString, 1);
internalConfig.langVersion = GLSLTools::glslangVersionFromShaderModel(config.shaderModel);
- GLSLTools::prepareShaderParser(tShader, internalConfig.shLang, internalConfig.langVersion, mOptimization);
+ GLSLTools::prepareShaderParser(targetApi, tShader, internalConfig.shLang,
+ internalConfig.langVersion, mOptimization);
EShMessages msg = GLSLTools::glslangFlagsFromTargetApi(targetApi);
bool ok = tShader.parse(&DefaultTBuiltInResource, internalConfig.langVersion, false, msg);
if (!ok) {
@@ -277,7 +281,7 @@ void GLSLPostProcessor::preprocessOptimization(glslang::TShader& tShader,
const char* shaderCString = glsl.c_str();
spirvShader.setStrings(&shaderCString, 1);
- GLSLTools::prepareShaderParser(spirvShader,
+ GLSLTools::prepareShaderParser(targetApi, spirvShader,
internalConfig.shLang, internalConfig.langVersion, mOptimization);
ok = spirvShader.parse(&DefaultTBuiltInResource, internalConfig.langVersion, false, msg);
program.addShader(&spirvShader);
diff --git a/libs/filamat/src/GLSLPostProcessor.h b/libs/filamat/src/GLSLPostProcessor.h
index 78bc529a3b..8096e8a098 100644
--- a/libs/filamat/src/GLSLPostProcessor.h
+++ b/libs/filamat/src/GLSLPostProcessor.h
@@ -50,6 +50,7 @@ public:
struct Config {
filament::backend::ShaderType shaderType;
filament::backend::ShaderModel shaderModel;
+ bool hasFramebufferFetch;
struct {
std::vector> subpassInputToColorLocation;
} glsl;
diff --git a/libs/filamat/src/MaterialBuilder.cpp b/libs/filamat/src/MaterialBuilder.cpp
index 18379bc74e..e636b25810 100644
--- a/libs/filamat/src/MaterialBuilder.cpp
+++ b/libs/filamat/src/MaterialBuilder.cpp
@@ -712,6 +712,8 @@ bool MaterialBuilder::generateShaders(JobSystem& jobSystem, const std::vector