Merge branch 'google:main' into main
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1271,7 +1271,28 @@ public class Engine {
|
||||
* {@link android.view.SurfaceHolder.Callback#surfaceDestroyed surfaceDestroyed}.</p>
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* <p>This is typically used right after destroying the <code>SwapChain</code>,
|
||||
* in cases where a guarantee about the <code>SwapChain</code> destruction is needed in a
|
||||
* timely fashion, such as when responding to Android's
|
||||
* <code>android.view.SurfaceHolder.Callback.surfaceDestroyed</code></p>
|
||||
*
|
||||
* @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);
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* <p>This is typically used right after destroying the <code>SwapChain</code>,
|
||||
* in cases where a guarantee about the <code>SwapChain</code> destruction is needed in a
|
||||
* timely fashion, such as when responding to Android's
|
||||
* <code>android.view.SurfaceHolder.Callback.surfaceDestroyed</code></p>
|
||||
*
|
||||
* @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.
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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<FrameGraphTexture> 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<FrameGraphTexture> PostProcessManager::colorGrading(FrameGraph& fg,
|
||||
|
||||
FrameGraphId<FrameGraphTexture> PostProcessManager::fxaa(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> const input, filament::Viewport const& vp,
|
||||
TextureFormat const outFormat, bool const translucent) noexcept {
|
||||
TextureFormat const outFormat, bool const preserveAlphaChannel) noexcept {
|
||||
|
||||
struct PostProcessFXAA {
|
||||
FrameGraphId<FrameGraphTexture> input;
|
||||
@@ -2587,7 +2588,7 @@ FrameGraphId<FrameGraphTexture> 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<FrameGraphTexture> PostProcessManager::rcas(
|
||||
}
|
||||
|
||||
FrameGraphId<FrameGraphTexture> PostProcessManager::upscale(FrameGraph& fg, bool translucent,
|
||||
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> const input,
|
||||
filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc,
|
||||
SamplerMagFilter filter) noexcept {
|
||||
|
||||
bool sourceHasLuminance, DynamicResolutionOptions dsrOptions,
|
||||
FrameGraphId<FrameGraphTexture> 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<FrameGraphTexture> PostProcessManager::upscaleBilinear(FrameGraph& fg, bool translucent,
|
||||
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> const input,
|
||||
filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc,
|
||||
SamplerMagFilter filter) noexcept {
|
||||
|
||||
struct QuadBlitData {
|
||||
FrameGraphId<FrameGraphTexture> input;
|
||||
FrameGraphId<FrameGraphTexture> output;
|
||||
};
|
||||
|
||||
auto const& ppQuadBlit = fg.addPass<QuadBlitData>(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<FrameGraphTexture> PostProcessManager::upscaleSGSR1(FrameGraph& fg, bool sourceHasLuminance,
|
||||
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> const input,
|
||||
filament::Viewport const&, FrameGraphTexture::Descriptor const& outDesc) noexcept {
|
||||
|
||||
struct QuadBlitData {
|
||||
FrameGraphId<FrameGraphTexture> input;
|
||||
FrameGraphId<FrameGraphTexture> output;
|
||||
};
|
||||
|
||||
auto const& ppQuadBlit = fg.addPass<QuadBlitData>(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<FrameGraphTexture> PostProcessManager::upscaleFSR1(FrameGraph& fg,
|
||||
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> 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<FrameGraphTexture> 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<FrameGraphTexture> 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<FrameGraphTexture> 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<FrameGraphTexture> 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
|
||||
|
||||
@@ -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<FrameGraphTexture> fxaa(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> 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<FrameGraphTexture> upscale(FrameGraph& fg, bool translucent,
|
||||
bool sourceHasLuminance, DynamicResolutionOptions dsrOptions,
|
||||
FrameGraphId<FrameGraphTexture> input, Viewport const& vp,
|
||||
FrameGraphTexture::Descriptor const& outDesc, backend::SamplerMagFilter filter) noexcept;
|
||||
|
||||
FrameGraphId<FrameGraphTexture> upscaleBilinear(FrameGraph& fg, bool translucent,
|
||||
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> input,
|
||||
Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc,
|
||||
backend::SamplerMagFilter filter) noexcept;
|
||||
|
||||
FrameGraphId<FrameGraphTexture> upscaleFSR1(FrameGraph& fg,
|
||||
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> input,
|
||||
filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc) noexcept;
|
||||
|
||||
FrameGraphId<FrameGraphTexture> upscaleSGSR1(FrameGraph& fg, bool sourceHasLuminance,
|
||||
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> input,
|
||||
filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc) noexcept;
|
||||
|
||||
FrameGraphId<FrameGraphTexture> rcas(
|
||||
FrameGraph& fg,
|
||||
float sharpness,
|
||||
|
||||
@@ -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<sizeof(ShadowMap)>::type;
|
||||
using ShadowMapStorage = std::aligned_storage_t<sizeof(ShadowMap), alignof(ShadowMap)>;
|
||||
using ShadowMapCacheContainer = std::array<ShadowMapStorage, CONFIG_MAX_SHADOWMAPS>;
|
||||
ShadowMapCacheContainer mShadowMapCache;
|
||||
uint32_t mDirectionalShadowMapCount = 0;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user