diff --git a/README.md b/README.md
index 5cd0c006c5..625dd40c3a 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ repositories {
}
dependencies {
- implementation 'com.google.android.filament:filament-android:1.56.6'
+ implementation 'com.google.android.filament:filament-android:1.56.7'
}
```
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
iOS projects can use CocoaPods to install the latest release:
```shell
-pod 'Filament', '~> 1.56.6'
+pod 'Filament', '~> 1.56.7'
```
## Documentation
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index ffccaa339a..09643b5d20 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -7,6 +7,9 @@ A new header is inserted each time a *tag* is created.
Instead, if you are authoring a PR for the main branch, add your release note to
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
+## v1.56.8
+
+
## v1.56.7
diff --git a/android/filament-android/src/main/cpp/Engine.cpp b/android/filament-android/src/main/cpp/Engine.cpp
index 56aecc66dd..d6e941209b 100644
--- a/android/filament-android/src/main/cpp/Engine.cpp
+++ b/android/filament-android/src/main/cpp/Engine.cpp
@@ -392,11 +392,11 @@ Java_com_google_android_filament_Engine_nIsValidSwapChain(JNIEnv*, jclass,
return (jboolean)engine->isValid((SwapChain*)nativeSwapChain);
}
-extern "C" JNIEXPORT void JNICALL
+extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nFlushAndWait(JNIEnv*, jclass,
- jlong nativeEngine) {
+ jlong nativeEngine, jlong timeout) {
Engine* engine = (Engine*) nativeEngine;
- engine->flushAndWait();
+ return engine->flushAndWait((uint64_t)timeout);
}
extern "C" JNIEXPORT void JNICALL
diff --git a/android/filament-android/src/main/java/com/google/android/filament/Engine.java b/android/filament-android/src/main/java/com/google/android/filament/Engine.java
index 1e49bf54a3..e73e82944c 100644
--- a/android/filament-android/src/main/java/com/google/android/filament/Engine.java
+++ b/android/filament-android/src/main/java/com/google/android/filament/Engine.java
@@ -1271,7 +1271,28 @@ public class Engine {
* {@link android.view.SurfaceHolder.Callback#surfaceDestroyed surfaceDestroyed}.
*/
public void flushAndWait() {
- nFlushAndWait(getNativeObject());
+ flushAndWait(Fence.WAIT_FOR_EVER);
+ }
+
+ /**
+ * Kicks the hardware thread (e.g. the OpenGL, Vulkan or Metal thread) and blocks until
+ * all commands to this point are executed. Note that does guarantee that the
+ * hardware is actually finished.
+ *
+ * A timeout can be specified, if for some reason this flushAndWait doesn't complete before the timeout, it will
+ * return false, true otherwise.
+ *
+ * This is typically used right after destroying the SwapChain,
+ * in cases where a guarantee about the SwapChain destruction is needed in a
+ * timely fashion, such as when responding to Android's
+ * android.view.SurfaceHolder.Callback.surfaceDestroyed
+ *
+ * @param timeout A timeout in nanoseconds
+ * @return true if successful, false if flushAndWait timed out, in which case it wasn't successful and commands
+ * might still be executing on both the CPU and GPU sides.
+ */
+ public boolean flushAndWait(long timeout) {
+ return nFlushAndWait(getNativeObject(), timeout);
}
/**
@@ -1437,7 +1458,7 @@ public class Engine {
private static native boolean nIsValidRenderTarget(long nativeEngine, long nativeTarget);
private static native boolean nIsValidSwapChain(long nativeEngine, long nativeSwapChain);
private static native void nDestroyEntity(long nativeEngine, int entity);
- private static native void nFlushAndWait(long nativeEngine);
+ private static native boolean nFlushAndWait(long nativeEngine, long timeout);
private static native void nFlush(long nativeEngine);
private static native boolean nIsPaused(long nativeEngine);
private static native void nSetPaused(long nativeEngine, boolean paused);
diff --git a/android/filament-android/src/main/java/com/google/android/filament/View.java b/android/filament-android/src/main/java/com/google/android/filament/View.java
index 0bcd1299b7..bcf6f5378f 100644
--- a/android/filament-android/src/main/java/com/google/android/filament/View.java
+++ b/android/filament-android/src/main/java/com/google/android/filament/View.java
@@ -1420,10 +1420,10 @@ public class View {
/**
* Upscaling quality
* LOW: bilinear filtered blit. Fastest, poor quality
- * MEDIUM: AMD FidelityFX FSR1 w/ mobile optimizations
+ * MEDIUM: Qualcomm Snapdragon Game Super Resolution (SGSR) 1.0
* HIGH: AMD FidelityFX FSR1 w/ mobile optimizations
* ULTRA: AMD FidelityFX FSR1
- * FSR1 require a well anti-aliased (MSAA or TAA), noise free scene.
+ * FSR1 and SGSR require a well anti-aliased (MSAA or TAA), noise free scene. Avoid FXAA and dithering.
*
* The default upscaling quality is set to LOW.
*/
diff --git a/android/gradle.properties b/android/gradle.properties
index e4f778ef79..d1baf95447 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
-VERSION_NAME=1.56.6
+VERSION_NAME=1.56.7
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
diff --git a/filament/CMakeLists.txt b/filament/CMakeLists.txt
index d218a39170..9f0364f94e 100644
--- a/filament/CMakeLists.txt
+++ b/filament/CMakeLists.txt
@@ -252,6 +252,7 @@ set(MATERIAL_SRCS
src/materials/fsr/fsr_easu_mobile.mat
src/materials/fsr/fsr_easu_mobileF.mat
src/materials/fsr/fsr_rcas.mat
+ src/materials/sgsr/sgsr1.mat
src/materials/resolveDepth.mat
src/materials/separableGaussianBlur.mat
src/materials/skybox.mat
@@ -504,6 +505,12 @@ add_custom_command(
APPEND
)
+add_custom_command(
+ OUTPUT "${MATERIAL_DIR}/sgsr1.filamat"
+ DEPENDS src/materials/sgsr/sgsr1_shader_mobile.fs
+ APPEND
+)
+
add_custom_command(
OUTPUT "${MATERIAL_DIR}/separableGaussianBlur.filamat"
DEPENDS src/materials/separableGaussianBlur.vs
diff --git a/filament/include/filament/Engine.h b/filament/include/filament/Engine.h
index 8fb44af5dc..5092e16c38 100644
--- a/filament/include/filament/Engine.h
+++ b/filament/include/filament/Engine.h
@@ -970,6 +970,25 @@ public:
*/
void flushAndWait();
+ /**
+ * Kicks the hardware thread (e.g. the OpenGL, Vulkan or Metal thread) and blocks until
+ * all commands to this point are executed. Note that does guarantee that the
+ * hardware is actually finished.
+ *
+ * A timeout can be specified, if for some reason this flushAndWait doesn't complete before the timeout, it will
+ * return false, true otherwise.
+ *
+ * This is typically used right after destroying the SwapChain,
+ * in cases where a guarantee about the SwapChain destruction is needed in a
+ * timely fashion, such as when responding to Android's
+ * android.view.SurfaceHolder.Callback.surfaceDestroyed
+ *
+ * @param timeout A timeout in nanoseconds
+ * @return true if successful, false if flushAndWait timed out, in which case it wasn't successful and commands
+ * might still be executing on both the CPU and GPU sides.
+ */
+ bool flushAndWait(uint64_t timeout);
+
/**
* Kicks the hardware thread (e.g. the OpenGL, Vulkan or Metal thread) but does not wait
* for commands to be either executed or the hardware finished.
diff --git a/filament/include/filament/Options.h b/filament/include/filament/Options.h
index 93bba80cd8..dc06143dd4 100644
--- a/filament/include/filament/Options.h
+++ b/filament/include/filament/Options.h
@@ -86,10 +86,10 @@ struct DynamicResolutionOptions {
/**
* Upscaling quality
* LOW: bilinear filtered blit. Fastest, poor quality
- * MEDIUM: AMD FidelityFX FSR1 w/ mobile optimizations
+ * MEDIUM: Qualcomm Snapdragon Game Super Resolution (SGSR) 1.0
* HIGH: AMD FidelityFX FSR1 w/ mobile optimizations
* ULTRA: AMD FidelityFX FSR1
- * FSR1 require a well anti-aliased (MSAA or TAA), noise free scene.
+ * FSR1 and SGSR require a well anti-aliased (MSAA or TAA), noise free scene. Avoid FXAA and dithering.
*
* The default upscaling quality is set to LOW.
*/
diff --git a/filament/src/Engine.cpp b/filament/src/Engine.cpp
index 5f1af80aaf..455067739c 100644
--- a/filament/src/Engine.cpp
+++ b/filament/src/Engine.cpp
@@ -338,6 +338,10 @@ void Engine::flushAndWait() {
downcast(this)->flushAndWait();
}
+bool Engine::flushAndWait(uint64_t timeout) {
+ return downcast(this)->flushAndWait(timeout);
+}
+
void Engine::flush() {
downcast(this)->flush();
}
diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp
index b7a51aae0b..d9ab8b0c16 100644
--- a/filament/src/PostProcessManager.cpp
+++ b/filament/src/PostProcessManager.cpp
@@ -311,6 +311,7 @@ static const PostProcessManager::StaticMaterialInfo sMaterialList[] = {
{ "fsr_easu_mobile", MATERIAL(FSR_EASU_MOBILE) },
{ "fsr_easu_mobileF", MATERIAL(FSR_EASU_MOBILEF) },
{ "fsr_rcas", MATERIAL(FSR_RCAS) },
+ { "sgsr1", MATERIAL(SGSR1) },
{ "debugShadowCascades", MATERIAL(DEBUGSHADOWCASCADES) },
{ "resolveDepth", MATERIAL(RESOLVEDEPTH) },
{ "shadowmap", MATERIAL(SHADOWMAP) },
@@ -2328,7 +2329,7 @@ void PostProcessManager::colorGradingPrepareSubpass(DriverApi& driver,
mi->setParameter("vignette", vignetteParameters);
mi->setParameter("vignetteColor", vignetteOptions.color);
mi->setParameter("dithering", colorGradingConfig.dithering);
- mi->setParameter("fxaa", colorGradingConfig.fxaa);
+ mi->setParameter("outputLuminance", colorGradingConfig.outputLuminance);
mi->setParameter("temporalNoise", temporalNoise);
mi->commit(driver);
@@ -2544,7 +2545,7 @@ FrameGraphId PostProcessManager::colorGrading(FrameGraph& fg,
mi->setParameter("bloom", bloomParameters);
mi->setParameter("vignette", vignetteParameters);
mi->setParameter("vignetteColor", vignetteOptions.color);
- mi->setParameter("fxaa", colorGradingConfig.fxaa);
+ mi->setParameter("outputLuminance", colorGradingConfig.outputLuminance);
mi->setParameter("temporalNoise", temporalNoise);
mi->setParameter("viewport", float4{
float(vp.left) / input.width,
@@ -2562,7 +2563,7 @@ FrameGraphId PostProcessManager::colorGrading(FrameGraph& fg,
FrameGraphId PostProcessManager::fxaa(FrameGraph& fg,
FrameGraphId const input, filament::Viewport const& vp,
- TextureFormat const outFormat, bool const translucent) noexcept {
+ TextureFormat const outFormat, bool const preserveAlphaChannel) noexcept {
struct PostProcessFXAA {
FrameGraphId input;
@@ -2587,7 +2588,7 @@ FrameGraphId PostProcessManager::fxaa(FrameGraph& fg,
auto const& material = getPostProcessMaterial("fxaa");
- PostProcessVariant const variant = translucent ?
+ PostProcessVariant const variant = preserveAlphaChannel ?
PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE;
FMaterialInstance* const mi =
@@ -2920,20 +2921,171 @@ FrameGraphId PostProcessManager::rcas(
}
FrameGraphId PostProcessManager::upscale(FrameGraph& fg, bool translucent,
- DynamicResolutionOptions dsrOptions, FrameGraphId const input,
- filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc,
- SamplerMagFilter filter) noexcept {
-
+ bool sourceHasLuminance, DynamicResolutionOptions dsrOptions,
+ FrameGraphId const input, filament::Viewport const& vp,
+ FrameGraphTexture::Descriptor const& outDesc, SamplerMagFilter filter) noexcept {
// The code below cannot handle sub-resources
assert_invariant(fg.getSubResourceDescriptor(input).layer == 0);
assert_invariant(fg.getSubResourceDescriptor(input).level == 0);
- const bool lowQualityFallback = translucent && dsrOptions.quality != QualityLevel::LOW;
+ const bool lowQualityFallback = translucent;
if (lowQualityFallback) {
- // FidelityFX-FSR doesn't support the alpha channel currently
+ // FidelityFX-FSR nor SGSR support the source alpha channel currently
dsrOptions.quality = QualityLevel::LOW;
}
+ if (dsrOptions.quality == QualityLevel::LOW) {
+ return upscaleBilinear(fg, translucent, dsrOptions, input, vp, outDesc, filter);
+ }
+ if (dsrOptions.quality == QualityLevel::MEDIUM) {
+ return upscaleSGSR1(fg, sourceHasLuminance, dsrOptions, input, vp, outDesc);
+ }
+ return upscaleFSR1(fg, dsrOptions, input, vp, outDesc);
+}
+
+FrameGraphId PostProcessManager::upscaleBilinear(FrameGraph& fg, bool translucent,
+ DynamicResolutionOptions dsrOptions, FrameGraphId const input,
+ filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc,
+ SamplerMagFilter filter) noexcept {
+
+ struct QuadBlitData {
+ FrameGraphId input;
+ FrameGraphId output;
+ };
+
+ auto const& ppQuadBlit = fg.addPass(dsrOptions.enabled ? "upscaling" : "compositing",
+ [&](FrameGraph::Builder& builder, auto& data) {
+ data.input = builder.sample(input);
+ data.output = builder.createTexture("upscaled output", outDesc);
+ data.output = builder.write(data.output, FrameGraphTexture::Usage::COLOR_ATTACHMENT);
+ builder.declareRenderPass(builder.getName(data.output), {
+ .attachments = { .color = { data.output } },
+ .clearFlags = TargetBufferFlags::DEPTH });
+ },
+ [this, vp, translucent, filter](FrameGraphResources const& resources,
+ auto const& data, DriverApi& driver) {
+ bindPostProcessDescriptorSet(driver);
+
+ // helper to enable blending
+ auto enableTranslucentBlending = [](PipelineState& pipeline) {
+ pipeline.rasterState.blendFunctionSrcRGB = BlendFunction::ONE;
+ pipeline.rasterState.blendFunctionSrcAlpha = BlendFunction::ONE;
+ pipeline.rasterState.blendFunctionDstRGB = BlendFunction::ONE_MINUS_SRC_ALPHA;
+ pipeline.rasterState.blendFunctionDstAlpha = BlendFunction::ONE_MINUS_SRC_ALPHA;
+ };
+
+ auto color = resources.getTexture(data.input);
+ auto const& inputDesc = resources.getDescriptor(data.input);
+
+ // --------------------------------------------------------------------------------
+ // set uniforms
+
+ auto& material = getPostProcessMaterial("blitLow");
+ FMaterialInstance* const mi =
+ PostProcessMaterial::getMaterialInstance(mEngine, material);
+ mi->setParameter("color", color, {
+ .filterMag = filter
+ });
+
+ mi->setParameter("levelOfDetail", 0.0f);
+
+ mi->setParameter("viewport", float4{
+ float(vp.left) / inputDesc.width,
+ float(vp.bottom) / inputDesc.height,
+ float(vp.width) / inputDesc.width,
+ float(vp.height) / inputDesc.height
+ });
+ mi->commit(driver);
+ mi->use(driver);
+
+ auto out = resources.getRenderPassInfo();
+
+ auto pipeline = getPipelineState(material.getMaterial(mEngine));
+ if (translucent) {
+ enableTranslucentBlending(pipeline);
+ }
+ renderFullScreenQuad(out, pipeline, driver);
+ });
+
+ auto output = ppQuadBlit->output;
+
+ // if we had to take the low quality fallback, we still do the "sharpen pass"
+ if (dsrOptions.sharpness > 0.0f) {
+ output = rcas(fg, dsrOptions.sharpness, output, outDesc, translucent);
+ }
+
+ // we rely on automatic culling of unused render passes
+ return output;
+}
+
+FrameGraphId PostProcessManager::upscaleSGSR1(FrameGraph& fg, bool sourceHasLuminance,
+ DynamicResolutionOptions dsrOptions, FrameGraphId const input,
+ filament::Viewport const&, FrameGraphTexture::Descriptor const& outDesc) noexcept {
+
+ struct QuadBlitData {
+ FrameGraphId input;
+ FrameGraphId output;
+ };
+
+ auto const& ppQuadBlit = fg.addPass(dsrOptions.enabled ? "upscaling" : "compositing",
+ [&](FrameGraph::Builder& builder, auto& data) {
+ data.input = builder.sample(input);
+ data.output = builder.createTexture("upscaled output", outDesc);
+ data.output = builder.write(data.output, FrameGraphTexture::Usage::COLOR_ATTACHMENT);
+ builder.declareRenderPass(builder.getName(data.output), {
+ .attachments = { .color = { data.output } },
+ .clearFlags = TargetBufferFlags::DEPTH });
+ },
+ [this, sourceHasLuminance](FrameGraphResources const& resources,
+ auto const& data, DriverApi& driver) {
+ bindPostProcessDescriptorSet(driver);
+
+ auto color = resources.getTexture(data.input);
+ auto const& inputDesc = resources.getDescriptor(data.input);
+
+ // --------------------------------------------------------------------------------
+ // set uniforms
+
+ auto const& material = getPostProcessMaterial("sgsr1");
+
+ PostProcessVariant const variant = sourceHasLuminance ?
+ PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE;
+
+ FMaterialInstance* const mi =
+ PostProcessMaterial::getMaterialInstance(mEngine, material, variant);
+
+ mi->setParameter("color", color, {
+ // The SGSR documentation doesn't clarify if LINEAR or NEAREST should be used. The
+ // sample code uses NEAREST, but that doesn't seem right, since it would mean the
+ // LERP mode would not be a LERP, and the non-edges would be sampled as NEAREST.
+ .filterMag = SamplerMagFilter::LINEAR
+ });
+
+ mi->setParameter("viewport", float4{
+ 1.0f / inputDesc.width,
+ 1.0f / inputDesc.height,
+ float(inputDesc.width),
+ float(inputDesc.height),
+ });
+
+ mi->commit(driver);
+ mi->use(driver);
+
+ auto out = resources.getRenderPassInfo();
+ commitAndRenderFullScreenQuad(driver, out, mi, variant);
+
+ });
+
+ auto output = ppQuadBlit->output;
+
+ // we rely on automatic culling of unused render passes
+ return output;
+}
+
+FrameGraphId PostProcessManager::upscaleFSR1(FrameGraph& fg,
+ DynamicResolutionOptions dsrOptions, FrameGraphId const input,
+ filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc) noexcept {
+
const bool twoPassesEASU = mWorkaroundSplitEasu &&
(dsrOptions.quality == QualityLevel::MEDIUM
|| dsrOptions.quality == QualityLevel::HIGH);
@@ -2964,7 +3116,7 @@ FrameGraphId PostProcessManager::upscale(FrameGraph& fg, bool
.attachments = { .color = { data.output }, .depth = { data.depth }},
.clearFlags = TargetBufferFlags::DEPTH });
},
- [this, twoPassesEASU, dsrOptions, vp, translucent, filter](FrameGraphResources const& resources,
+ [this, twoPassesEASU, dsrOptions, vp](FrameGraphResources const& resources,
auto const& data, DriverApi& driver) {
bindPostProcessDescriptorSet(driver);
@@ -2989,14 +3141,6 @@ FrameGraphId PostProcessManager::upscale(FrameGraph& fg, bool
float2{ inputDesc.width, inputDesc.height });
};
- // helper to enable blending
- auto enableTranslucentBlending = [](PipelineState& pipeline) {
- pipeline.rasterState.blendFunctionSrcRGB = BlendFunction::ONE;
- pipeline.rasterState.blendFunctionSrcAlpha = BlendFunction::ONE;
- pipeline.rasterState.blendFunctionDstRGB = BlendFunction::ONE_MINUS_SRC_ALPHA;
- pipeline.rasterState.blendFunctionDstAlpha = BlendFunction::ONE_MINUS_SRC_ALPHA;
- };
-
auto color = resources.getTexture(data.input);
auto const& inputDesc = resources.getDescriptor(data.input);
auto const& outputDesc = resources.getDescriptor(data.output);
@@ -3023,29 +3167,21 @@ FrameGraphId PostProcessManager::upscale(FrameGraph& fg, bool
}
{ // just a scope to not leak local variables
- const std::string_view blitterNames[4] = {
- "blitLow", "fsr_easu_mobile", "fsr_easu_mobile", "fsr_easu" };
- unsigned const index = std::min(3u, unsigned(dsrOptions.quality));
+ const std::string_view blitterNames[2] = { "fsr_easu_mobile", "fsr_easu" };
+ unsigned const index = std::min(1u, unsigned(dsrOptions.quality) - 2);
easuMaterial = &getPostProcessMaterial(blitterNames[index]);
FMaterialInstance* const mi =
PostProcessMaterial::getMaterialInstance(mEngine, *easuMaterial);
- if (dsrOptions.quality != QualityLevel::LOW) {
- setEasuUniforms(mi, inputDesc, outputDesc);
- }
+
+ setEasuUniforms(mi, inputDesc, outputDesc);
+
mi->setParameter("color", color, {
- .filterMag = (dsrOptions.quality == QualityLevel::LOW) ?
- filter : SamplerMagFilter::LINEAR
+ .filterMag = SamplerMagFilter::LINEAR
});
- if (blitterNames[index] != "blitLow") {
- mi->setParameter("resolution",
- float4{outputDesc.width, outputDesc.height, 1.0f / outputDesc.width,
- 1.0f / outputDesc.height});
- }
-
- if (blitterNames[index] == "blitLow") {
- mi->setParameter("levelOfDetail", 0.0f);
- }
+ mi->setParameter("resolution",
+ float4{outputDesc.width, outputDesc.height, 1.0f / outputDesc.width,
+ 1.0f / outputDesc.height});
mi->setParameter("viewport", float4{
float(vp.left) / inputDesc.width,
@@ -3066,29 +3202,19 @@ FrameGraphId PostProcessManager::upscale(FrameGraph& fg, bool
auto pipeline0 = getPipelineState(splitEasuMaterial->getMaterial(mEngine));
auto pipeline1 = getPipelineState(easuMaterial->getMaterial(mEngine));
pipeline1.rasterState.depthFunc = SamplerCompareFunc::NE;
- if (translucent) {
- enableTranslucentBlending(pipeline0);
- enableTranslucentBlending(pipeline1);
- }
driver.beginRenderPass(out.target, out.params);
driver.draw(pipeline0, mFullScreenQuadRph, 0, 3, 1);
driver.draw(pipeline1, mFullScreenQuadRph, 0, 3, 1);
driver.endRenderPass();
} else {
auto pipeline = getPipelineState(easuMaterial->getMaterial(mEngine));
- if (translucent) {
- enableTranslucentBlending(pipeline);
- }
renderFullScreenQuad(out, pipeline, driver);
}
});
auto output = ppQuadBlit->output;
-
- // if we had to take the low quality fallback, we still do the "sharpen pass"
- if (dsrOptions.sharpness > 0.0f &&
- (dsrOptions.quality != QualityLevel::LOW || lowQualityFallback)) {
- output = rcas(fg, dsrOptions.sharpness, output, outDesc, translucent);
+ if (dsrOptions.sharpness > 0.0f) {
+ output = rcas(fg, dsrOptions.sharpness, output, outDesc, false);
}
// we rely on automatic culling of unused render passes
diff --git a/filament/src/PostProcessManager.h b/filament/src/PostProcessManager.h
index c435cdccd9..677cec30cb 100644
--- a/filament/src/PostProcessManager.h
+++ b/filament/src/PostProcessManager.h
@@ -89,7 +89,7 @@ public:
bool asSubpass{};
bool customResolve{};
bool translucent{};
- bool fxaa{};
+ bool outputLuminance{}; // Whether to output luminance in the alpha channel. Ignored by the TRANSLUCENT variant.
bool dithering{};
backend::TextureFormat ldrFormat{};
};
@@ -227,7 +227,7 @@ public:
// Anti-aliasing
FrameGraphId fxaa(FrameGraph& fg,
FrameGraphId input, Viewport const& vp,
- backend::TextureFormat outFormat, bool translucent) noexcept;
+ backend::TextureFormat outFormat, bool preserveAlphaChannel) noexcept;
// Temporal Anti-aliasing
void TaaJitterCamera(
@@ -251,12 +251,25 @@ public:
// high quality upscaler
// - when translucent, reverts to LINEAR
- // - doens't handle sub-resouces
+ // - doesn't handle sub-resouces
FrameGraphId upscale(FrameGraph& fg, bool translucent,
+ bool sourceHasLuminance, DynamicResolutionOptions dsrOptions,
+ FrameGraphId input, Viewport const& vp,
+ FrameGraphTexture::Descriptor const& outDesc, backend::SamplerMagFilter filter) noexcept;
+
+ FrameGraphId upscaleBilinear(FrameGraph& fg, bool translucent,
DynamicResolutionOptions dsrOptions, FrameGraphId input,
Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc,
backend::SamplerMagFilter filter) noexcept;
+ FrameGraphId upscaleFSR1(FrameGraph& fg,
+ DynamicResolutionOptions dsrOptions, FrameGraphId input,
+ filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc) noexcept;
+
+ FrameGraphId upscaleSGSR1(FrameGraph& fg, bool sourceHasLuminance,
+ DynamicResolutionOptions dsrOptions, FrameGraphId input,
+ filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc) noexcept;
+
FrameGraphId rcas(
FrameGraph& fg,
float sharpness,
diff --git a/filament/src/ShadowMapManager.h b/filament/src/ShadowMapManager.h
index a6dc21cab3..ba606c6eb4 100644
--- a/filament/src/ShadowMapManager.h
+++ b/filament/src/ShadowMapManager.h
@@ -230,7 +230,7 @@ private:
// Inline storage for all our ShadowMap objects, we can't easily use a std::array<> directly.
// Because ShadowMap doesn't have a default ctor, and we avoid out-of-line allocations.
// Each ShadowMap is currently 88 bytes (total of ~12KB for 128 shadow maps)
- using ShadowMapStorage = std::aligned_storage::type;
+ using ShadowMapStorage = std::aligned_storage_t;
using ShadowMapCacheContainer = std::array;
ShadowMapCacheContainer mShadowMapCache;
uint32_t mDirectionalShadowMapCount = 0;
diff --git a/filament/src/details/Engine.cpp b/filament/src/details/Engine.cpp
index 1cc9a951be..2116fae4c1 100644
--- a/filament/src/details/Engine.cpp
+++ b/filament/src/details/Engine.cpp
@@ -665,50 +665,28 @@ void FEngine::flush() {
}
void FEngine::flushAndWait() {
- FILAMENT_CHECK_PRECONDITION(!mCommandBufferQueue.isPaused())
- << "Cannot call flushAndWait() when rendering thread is paused!";
+ flushAndWait(FENCE_WAIT_FOR_EVER);
+}
-#if defined(__ANDROID__)
+bool FEngine::flushAndWait(uint64_t timeout) {
+ FILAMENT_CHECK_PRECONDITION(!mCommandBufferQueue.isPaused())
+ << "Cannot call Engine::flushAndWait() when rendering thread is paused!";
// first make sure we've not terminated filament
FILAMENT_CHECK_PRECONDITION(!mCommandBufferQueue.isExitRequested())
- << "calling Engine::flushAndWait() after Engine::shutdown()!";
-
-#endif
+ << "Calling Engine::flushAndWait() after Engine::shutdown()!";
// enqueue finish command -- this will stall in the driver until the GPU is done
getDriverApi().finish();
-#if defined(__ANDROID__) && !defined(NDEBUG)
-
- // then create a fence that will trigger when we're past the finish() above
- size_t tryCount = 8;
- FFence* fence = FEngine::createFence();
- UTILS_NOUNROLL
- do {
- FenceStatus status = fence->wait(FFence::Mode::FLUSH,250000000u);
- // if the fence didn't trigger after 250ms, check that the command queue thread is still
- // running (otherwise indicating a precondition violation).
- if (UTILS_UNLIKELY(status == FenceStatus::TIMEOUT_EXPIRED)) {
- FILAMENT_CHECK_PRECONDITION(!mCommandBufferQueue.isExitRequested())
- << "called Engine::shutdown() WHILE in Engine::flushAndWait()!";
- tryCount--;
- FILAMENT_CHECK_POSTCONDITION(tryCount) << "flushAndWait() failed inexplicably after 2s";
- // if the thread is still running, maybe we just need to give it more time
- continue;
- }
- break;
- } while (true);
+ FFence* fence = createFence();
+ FenceStatus const status = fence->wait(FFence::Mode::FLUSH, timeout);
destroy(fence);
-#else
-
- FFence::waitAndDestroy(createFence(), FFence::Mode::FLUSH);
-
-#endif
-
// finally, execute callbacks that might have been scheduled
getDriver().purge();
+
+ return status == FenceStatus::CONDITION_SATISFIED;
}
// -----------------------------------------------------------------------------------------------
diff --git a/filament/src/details/Engine.h b/filament/src/details/Engine.h
index da83a726a6..28376a5b6b 100644
--- a/filament/src/details/Engine.h
+++ b/filament/src/details/Engine.h
@@ -394,6 +394,7 @@ public:
void setPaused(bool paused);
void flushAndWait();
+ bool flushAndWait(uint64_t timeout);
// flush the current buffer
void flush();
@@ -716,7 +717,7 @@ public:
&features.backend.opengl.assert_native_window_is_valid, true },
{ "engine.shadows.use_shadow_atlas",
"Uses an array of atlases to store shadow maps.",
- &features.engine.shadows.use_shadow_atlas, true },
+ &features.engine.shadows.use_shadow_atlas, false },
{ "features.engine.debug.assert_material_instance_in_use",
"Assert when a MaterialInstance is destroyed while it is in use by RenderableManager.",
&features.engine.debug.assert_material_instance_in_use, false }
diff --git a/filament/src/details/Renderer.cpp b/filament/src/details/Renderer.cpp
index 6057c92a52..186c6249c7 100644
--- a/filament/src/details/Renderer.cpp
+++ b/filament/src/details/Renderer.cpp
@@ -681,6 +681,9 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
hasColorGrading &&
!bloomOptions.enabled && !dofOptions.enabled && !taaOptions.enabled;
+ // whether we're scaled at all
+ bool scaled = any(notEqual(scale, float2(1.0f)));
+
// asSubpass is disabled with TAA (although it's supported) because performance was degraded
// on qualcomm hardware -- we might need a backend dependent toggle at some point
const PostProcessManager::ColorGradingConfig colorGradingConfig{
@@ -695,18 +698,15 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
hasColorGrading &&
!engine.debug.renderer.disable_subpasses,
.translucent = needsAlphaChannel,
- .fxaa = hasFXAA,
+ .outputLuminance = hasFXAA || scaled, // ignored by translucent variants (false)
.dithering = hasDithering,
- .ldrFormat = (hasColorGrading && hasFXAA) ?
+ .ldrFormat = (hasColorGrading && (hasFXAA || scaled)) ?
TextureFormat::RGBA8 : getLdrFormat(needsAlphaChannel)
};
// by construction (msaaSampleCount) both asSubpass and customResolve can't be true
assert_invariant(colorGradingConfig.asSubpass + colorGradingConfig.customResolve < 2);
- // whether we're scaled at all
- bool scaled = any(notEqual(scale, float2(1.0f)));
-
// vp is the user defined viewport within the View
filament::Viewport const& vp = view.getViewport();
@@ -1351,8 +1351,9 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
}
if (hasFXAA) {
- input = ppm.fxaa(fg, input, xvp, colorGradingConfig.ldrFormat,
- !hasColorGrading || needsAlphaChannel);
+ bool const preserveAlphaChannel = needsAlphaChannel ||
+ (hasColorGrading && colorGradingConfig.outputLuminance);
+ input = ppm.fxaa(fg, input, xvp, colorGradingConfig.ldrFormat, preserveAlphaChannel);
// the padded buffer is resolved now
xvp.left = xvp.bottom = 0;
svp = xvp;
@@ -1360,9 +1361,11 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
if (scaled) {
mightNeedFinalBlit = false;
auto viewport = DEBUG_DYNAMIC_SCALING ? xvp : vp;
- input = ppm.upscale(fg, needsAlphaChannel, dsrOptions, input, xvp, {
- .width = viewport.width, .height = viewport.height,
- .format = colorGradingConfig.ldrFormat }, SamplerMagFilter::LINEAR);
+ bool const sourceHasLuminance = !needsAlphaChannel &&
+ (hasColorGrading && colorGradingConfig.outputLuminance);
+ input = ppm.upscale(fg, needsAlphaChannel, sourceHasLuminance, dsrOptions, input, xvp, {
+ .width = viewport.width, .height = viewport.height,
+ .format = colorGradingConfig.ldrFormat }, SamplerMagFilter::LINEAR);
xvp.left = xvp.bottom = 0;
svp = xvp;
}
diff --git a/filament/src/materials/colorGrading/colorGrading.mat b/filament/src/materials/colorGrading/colorGrading.mat
index 7667b42d9b..83712beafe 100644
--- a/filament/src/materials/colorGrading/colorGrading.mat
+++ b/filament/src/materials/colorGrading/colorGrading.mat
@@ -41,7 +41,7 @@ material {
},
{
type : int,
- name : fxaa
+ name : outputLuminance
},
{
type : float,
@@ -166,10 +166,10 @@ void postProcess(inout PostProcessInputs postProcess) {
color = dither(color, materialParams.temporalNoise);
}
- // kill alpha computations when opaque / fxaa luminance
+ // kill alpha computations when opaque / luminance
#if POST_PROCESS_OPAQUE
color.a = 1.0;
- if (materialParams.fxaa > 0) {
+ if (materialParams.outputLuminance > 0) {
color.a = luminance(color.rgb);
}
#endif
diff --git a/filament/src/materials/sgsr/LICENSE.txt b/filament/src/materials/sgsr/LICENSE.txt
new file mode 100644
index 0000000000..d9d513c758
--- /dev/null
+++ b/filament/src/materials/sgsr/LICENSE.txt
@@ -0,0 +1,29 @@
+Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+SPDX-License-Identifier: BSD-3-Clause
\ No newline at end of file
diff --git a/filament/src/materials/sgsr/sgsr1.mat b/filament/src/materials/sgsr/sgsr1.mat
new file mode 100644
index 0000000000..38fe23fc02
--- /dev/null
+++ b/filament/src/materials/sgsr/sgsr1.mat
@@ -0,0 +1,80 @@
+material {
+ name : sgsr1,
+ parameters : [
+ {
+ type : sampler2d,
+ name : color,
+ precision: medium
+ },
+ {
+ type : float4,
+ name : viewport,
+ precision: high
+ }
+ ],
+ variables : [
+ vertex
+ ],
+ depthWrite : false,
+ depthCulling : false,
+ domain: postprocess
+}
+
+vertex {
+ void postProcessVertex(inout PostProcessVertexInputs postProcess) {
+ postProcess.normalizedUV = uvToRenderTargetUV(postProcess.normalizedUV);
+ postProcess.vertex.xy = postProcess.normalizedUV;
+ }
+}
+
+fragment {
+
+ void dummy(){}
+
+ precision mediump float;
+ precision highp int;
+
+#if defined(FILAMENT_HAS_FEATURE_TEXTURE_GATHER)
+ #define gather textureGather
+#else
+ vec4 gather(const mediump sampler2D color, highp vec2 p, const int comp) {
+ highp ivec2 i = ivec2(p * materialParams.viewport.zw - 0.5);
+ vec4 d;
+ d[0] = texelFetchOffset(color, i, 0, ivec2(0, 1))[comp];
+ d[1] = texelFetchOffset(color, i, 0, ivec2(1, 1))[comp];
+ d[2] = texelFetchOffset(color, i, 0, ivec2(1, 0))[comp];
+ d[3] = texelFetchOffset(color, i, 0, ivec2(0, 0))[comp];
+ return d;
+ }
+#endif
+
+/*
+* Operation modes:
+* RGBA -> 1
+* RGBY -> 3
+* LERP -> 4
+*/
+
+// SGSR cannot support translucency;
+// So we hijack the POST_PROCESS variant to select whether a luminance channel is present
+#if POST_PROCESS_OPAQUE
+# define OperationMode 1
+#else
+# define OperationMode 3
+#endif
+
+/*
+* If set, will use edge direction to improve visual quality
+* Expect a minimal cost increase
+*/
+#define UseEdgeDirection
+#define EdgeThreshold 8.0 / 255.0
+#define EdgeSharpness 2.0
+
+#include "sgsr1_shader_mobile.fs"
+
+ void postProcess(inout PostProcessInputs postProcess) {
+ highp vec4 vp[1] = vec4[1]( materialParams.viewport );
+ postProcess.color = sgsr(materialParams_color, variable_vertex.xy, vp);
+ }
+}
diff --git a/filament/src/materials/sgsr/sgsr1_shader_mobile.fs b/filament/src/materials/sgsr/sgsr1_shader_mobile.fs
new file mode 100644
index 0000000000..edc937f4ad
--- /dev/null
+++ b/filament/src/materials/sgsr/sgsr1_shader_mobile.fs
@@ -0,0 +1,132 @@
+//============================================================================================================
+//
+//
+// Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
+// SPDX-License-Identifier: BSD-3-Clause
+//
+//============================================================================================================
+
+////////////////////////
+// USER CONFIGURATION //
+////////////////////////
+
+float fastLanczos2(float x)
+{
+ float wA = x-4.0;
+ float wB = x*wA-wA;
+ wA *= wA;
+ return wB*wA;
+}
+
+#if defined(UseEdgeDirection)
+vec2 weightY(float dx, float dy, float c, vec3 data)
+#else
+vec2 weightY(float dx, float dy, float c, float data)
+#endif
+{
+#if defined(UseEdgeDirection)
+ float std = data.x;
+ vec2 dir = data.yz;
+
+ float edgeDis = ((dx*dir.y)+(dy*dir.x));
+ float x = (((dx*dx)+(dy*dy))+((edgeDis*edgeDis)*((clamp(((c*c)*std),0.0,1.0)*0.7)+-1.0)));
+#else
+ float std = data;
+ float x = ((dx*dx)+(dy*dy))* 0.55 + clamp(abs(c)*std, 0.0, 1.0);
+#endif
+
+ float w = fastLanczos2(x);
+ return vec2(w, w * c);
+}
+
+vec2 edgeDirection(vec4 left, vec4 right)
+{
+ vec2 dir;
+ float RxLz = (right.x + (-left.z));
+ float RwLy = (right.w + (-left.y));
+ vec2 delta;
+ delta.x = (RxLz + RwLy);
+ delta.y = (RxLz + (-RwLy));
+ float lengthInv = inversesqrt((delta.x * delta.x+ 3.075740e-05) + (delta.y * delta.y));
+ dir.x = (delta.x * lengthInv);
+ dir.y = (delta.y * lengthInv);
+ return dir;
+}
+
+vec4 sgsr(mediump sampler2D ps0, highp vec2 in_TEXCOORD0, highp vec4 ViewportInfo[1])
+{
+ vec4 color;
+ if(OperationMode == 1)
+ color.xyz = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyz;
+ else
+ color.xyzw = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyzw;
+
+#if OperationMode != 4
+ if (OperationMode!=4)
+ {
+ highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo[0].zw)+vec2(-0.5,0.5));
+ highp vec2 imgCoordPixel = floor(imgCoord);
+ highp vec2 coord = (imgCoordPixel*ViewportInfo[0].xy);
+ vec2 pl = (imgCoord+(-imgCoordPixel));
+ vec4 left = gather(ps0,coord, OperationMode);
+
+ float edgeVote = abs(left.z - left.y) + abs(color[OperationMode] - left.y) + abs(color[OperationMode] - left.z) ;
+ if(edgeVote > EdgeThreshold)
+ {
+ coord.x += ViewportInfo[0].x;
+
+ vec4 right = gather(ps0,coord + vec2(ViewportInfo[0].x, 0.0), OperationMode);
+ vec4 upDown;
+ upDown.xy = gather(ps0,coord + vec2(0.0, -ViewportInfo[0].y),OperationMode).wz;
+ upDown.zw = gather(ps0,coord+ vec2(0.0, ViewportInfo[0].y), OperationMode).yx;
+
+ float mean = (left.y+left.z+right.x+right.w)*0.25;
+ left = left - vec4(mean);
+ right = right - vec4(mean);
+ upDown = upDown - vec4(mean);
+ color.w = color[OperationMode] - mean;
+
+ float sum = (((((abs(left.x)+abs(left.y))+abs(left.z))+abs(left.w)) +
+ (((abs(right.x)+abs(right.y))+abs(right.z))+abs(right.w))) +
+ (((abs(upDown.x)+abs(upDown.y))+abs(upDown.z))+abs(upDown.w)));
+
+#if defined(UseEdgeDirection)
+ float sumMean = 1.014185e+01 / sum;
+ float std = (sumMean * sumMean);
+ vec3 data = vec3(std, edgeDirection(left, right));
+#else
+ // taken from sgsr sample
+ float data = 2.181818 / sum;
+#endif
+
+ vec2 aWY = weightY(pl.x, pl.y+1.0, upDown.x,data);
+ aWY += weightY(pl.x-1.0, pl.y+1.0, upDown.y,data);
+ aWY += weightY(pl.x-1.0, pl.y-2.0, upDown.z,data);
+ aWY += weightY(pl.x, pl.y-2.0, upDown.w,data);
+ aWY += weightY(pl.x+1.0, pl.y-1.0, left.x,data);
+ aWY += weightY(pl.x, pl.y-1.0, left.y,data);
+ aWY += weightY(pl.x, pl.y, left.z,data);
+ aWY += weightY(pl.x+1.0, pl.y, left.w,data);
+ aWY += weightY(pl.x-1.0, pl.y-1.0, right.x,data);
+ aWY += weightY(pl.x-2.0, pl.y-1.0, right.y,data);
+ aWY += weightY(pl.x-2.0, pl.y, right.z,data);
+ aWY += weightY(pl.x-1.0, pl.y, right.w,data);
+
+ float finalY = aWY.y/aWY.x;
+ float maxY = max(max(left.y,left.z),max(right.x,right.w));
+ float minY = min(min(left.y,left.z),min(right.x,right.w));
+ float deltaY = clamp(EdgeSharpness*finalY, minY, maxY) -color.w;
+
+ //smooth high contrast input
+ deltaY = clamp(deltaY, -23.0 / 255.0, 23.0 / 255.0);
+
+ color.x = clamp(color.x+deltaY, 0.0, 1.0);
+ color.y = clamp(color.y+deltaY, 0.0, 1.0);
+ color.z = clamp(color.z+deltaY, 0.0, 1.0);
+ }
+ }
+#endif
+
+ color.w = 1.0; //assume alpha channel is not used
+ return color;
+}
\ No newline at end of file
diff --git a/ios/CocoaPods/Filament.podspec b/ios/CocoaPods/Filament.podspec
index 1133525c5a..e5e319aab0 100644
--- a/ios/CocoaPods/Filament.podspec
+++ b/ios/CocoaPods/Filament.podspec
@@ -1,12 +1,12 @@
Pod::Spec.new do |spec|
spec.name = "Filament"
- spec.version = "1.56.6"
+ spec.version = "1.56.7"
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
spec.homepage = "https://google.github.io/filament"
spec.authors = "Google LLC."
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
spec.platform = :ios, "11.0"
- spec.source = { :http => "https://github.com/google/filament/releases/download/v1.56.6/filament-v1.56.6-ios.tgz" }
+ spec.source = { :http => "https://github.com/google/filament/releases/download/v1.56.7/filament-v1.56.7-ios.tgz" }
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
spec.pod_target_xcconfig = {
diff --git a/libs/imageio/include/imageio/ImageDecoder.h b/libs/imageio/include/imageio/ImageDecoder.h
index cd341c49d8..4573e0b2c8 100644
--- a/libs/imageio/include/imageio/ImageDecoder.h
+++ b/libs/imageio/include/imageio/ImageDecoder.h
@@ -33,7 +33,7 @@ public:
SRGB
};
- // Returns linear floating-point data, or a non-valid image if an error occured.
+ // Returns linear floating-point data, or a non-valid image if an error occurred.
static LinearImage decode(std::istream& stream, const std::string& sourceName,
ColorSpace sourceSpace = ColorSpace::SRGB);
diff --git a/libs/matdbg/src/SourceFormatter.cpp b/libs/matdbg/src/SourceFormatter.cpp
index c068a34f4b..fe7c3f88ed 100644
--- a/libs/matdbg/src/SourceFormatter.cpp
+++ b/libs/matdbg/src/SourceFormatter.cpp
@@ -25,14 +25,32 @@ namespace filament::matdbg {
#if defined(__linux__) || defined(__APPLE__)
std::string SourceFormatter::format(char const* source) {
- std::string const TMP_FILENAME = "/tmp/matdbg-tmp-src.cpp";
+ char output[1024];
- std::string original(source);
- FILE* fp;
- fp = fopen(TMP_FILENAME.c_str(), "w");
- if (!fp) {
- return original;
+ // First check if clang-format is available.
+ FILE* fp = popen("clang-format -version", "r");
+
+ // Need to drain the output
+ while (fgets(output, 1024, fp) != NULL) {}
+
+ int status = pclose(fp);
+ if (!fp || !WEXITSTATUS(status)) {
+ std::call_once(mClangWarningFlag, []() {
+ utils::slog.w << "[matdbg] unable to run clang-format to format shader file. "
+ << "Please make sure it's installed." << utils::io::endl;
+ });
+ return source;
}
+
+ // Write the source to a temp file for formatting
+ char const* TMP_FILENAME = "/tmp/matdbg-tmp-src.cpp";
+ fp = fopen(TMP_FILENAME, "w");
+ if (!fp) {
+ return source;
+ }
+
+ // Unknown if the input is 0-terminated so we put it in a string first.
+ std::string original(source);
fputs(original.c_str(), fp);
fflush(fp);
pclose(fp);
@@ -45,22 +63,16 @@ std::string SourceFormatter::format(char const* source) {
"}'";
fp = popen(("clang-format " + CLANG_FORMAT_OPTIONS + "< " + TMP_FILENAME).c_str(), "r");
-
if (!fp) {
- std::call_once(mClangWarningFlag, []() {
- utils::slog.w << "[matdbg] unable to run clang-format to format shader file. "
- << "Please make sure it's installed.";
- });
return original;
}
- char output[1024];
std::stringstream outStream;
while (fgets(output, 1024, fp) != NULL) {
outStream << output;
}
- int status = pclose(fp);
+ status = pclose(fp);
if (WEXITSTATUS(status)) {
utils::slog.w << "[matdbg] clang-format failed with code=" << WEXITSTATUS(status)
<< utils::io::endl;
@@ -69,11 +81,11 @@ std::string SourceFormatter::format(char const* source) {
}
#else
std::string SourceFormatter::format(char const* source) {
- std::call_once(mClangWarningFlag, []() {
+ std::call_once(mClangWarningFlag, []() {
utils::slog.w <<"[matdbg]: source formatting is not available on this platform" <<
utils::io::endl;
});
- return "";
+ return source;
}
#endif
diff --git a/libs/utils/src/Panic.cpp b/libs/utils/src/Panic.cpp
index 1b8921ac06..e0aec064fa 100644
--- a/libs/utils/src/Panic.cpp
+++ b/libs/utils/src/Panic.cpp
@@ -43,7 +43,7 @@ class UserPanicHandler {
struct CallBack {
Panic::PanicHandlerCallback handler = nullptr;
void* user = nullptr;
- void call(Panic const& panic) const noexcept {
+ void call(Panic const& panic) const {
if (UTILS_UNLIKELY(handler)) {
handler(user, panic);
}
@@ -64,7 +64,7 @@ public:
return data;
}
- void call(Panic const& panic) const noexcept {
+ void call(Panic const& panic) const {
getCallback().call(panic);
}
diff --git a/web/filament-js/package.json b/web/filament-js/package.json
index 3a8340976c..36a97d6c37 100644
--- a/web/filament-js/package.json
+++ b/web/filament-js/package.json
@@ -1,6 +1,6 @@
{
"name": "filament",
- "version": "1.56.6",
+ "version": "1.56.7",
"description": "Real-time physically based rendering engine",
"main": "filament.js",
"module": "filament.js",