diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index da606a8045..e3e266735c 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -7,6 +7,8 @@ A new header is inserted each time a *tag* is created. ## v1.12.2 +- engine: Support AMD FidelityFX Super Resolution for dynamic resolution scaling + ## v1.12.1 - engine: `double` precision translation support in TransformManager. Disabled by default. diff --git a/android/filament-android/src/main/cpp/View.cpp b/android/filament-android/src/main/cpp/View.cpp index 6b132978d6..8e8caabbaf 100644 --- a/android/filament-android/src/main/cpp/View.cpp +++ b/android/filament-android/src/main/cpp/View.cpp @@ -119,13 +119,14 @@ Java_com_google_android_filament_View_nGetDithering(JNIEnv*, jclass, extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_View_nSetDynamicResolutionOptions(JNIEnv*, jclass, jlong nativeView, jboolean enabled, jboolean homogeneousScaling, - jfloat minScale, jfloat maxScale, jint quality) { + jfloat minScale, jfloat maxScale, jfloat sharpness, jint quality) { View* view = (View*)nativeView; View::DynamicResolutionOptions options; options.enabled = enabled; options.homogeneousScaling = homogeneousScaling; options.minScale = filament::math::float2{ minScale }; options.maxScale = filament::math::float2{ maxScale }; + options.sharpness = sharpness; options.quality = (View::QualityLevel)quality; view->setDynamicResolutionOptions(options); } 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 21c774e168..7380b437fe 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 @@ -131,8 +131,20 @@ public class View { public float maxScale = 1.0f; /** - * Upscaling quality. LOW: 1 bilinear tap, MEDIUM: 4 bilinear taps, HIGH: 9 bilinear taps. - * If minScale needs to be very low, it might help to use MEDIUM or HIGH here. + * Sharpness when QualityLevel.ULTRA is used [0, 2]. + * 0 is the sharpest setting, 2 is the smoothest setting. + * The default is set to 0.2 + */ + public float sharpness = 0.2f; + + /** + * Upscaling quality + * LOW: bilinear filtered blit. Fastest, poor quality + * MEDIUM: 16-tap optimized tent filter. + * HIGH: 36-tap optimized tent filter. + * ULTRA: AMD FidelityFX FSR1. Slowest, very high quality. + * Requires a well anti-aliased (MSAA or TAA), noise free scene. + * * The default upscaling quality is set to LOW. */ @NonNull @@ -1188,6 +1200,7 @@ public class View { options.homogeneousScaling, options.minScale, options.maxScale, + options.sharpness, options.quality.ordinal()); } @@ -1560,7 +1573,7 @@ public class View { private static native int nGetAntiAliasing(long nativeView); private static native void nSetDithering(long nativeView, int dithering); private static native int nGetDithering(long nativeView); - private static native void nSetDynamicResolutionOptions(long nativeView, boolean enabled, boolean homogeneousScaling, float minScale, float maxScale, int quality); + private static native void nSetDynamicResolutionOptions(long nativeView, boolean enabled, boolean homogeneousScaling, float minScale, float maxScale, float sharpness, int quality); private static native void nSetRenderQuality(long nativeView, int hdrColorBufferQuality); private static native void nSetDynamicLightingOptions(long nativeView, float zLightNear, float zLightFar); private static native void nSetShadowType(long nativeView, int type); diff --git a/android/samples/sample-gltf-viewer/src/main/java/com/google/android/filament/gltf/MainActivity.kt b/android/samples/sample-gltf-viewer/src/main/java/com/google/android/filament/gltf/MainActivity.kt index cf8d4e80cb..b1060c7fd4 100644 --- a/android/samples/sample-gltf-viewer/src/main/java/com/google/android/filament/gltf/MainActivity.kt +++ b/android/samples/sample-gltf-viewer/src/main/java/com/google/android/filament/gltf/MainActivity.kt @@ -27,6 +27,7 @@ import android.widget.Toast import com.google.android.filament.Fence import com.google.android.filament.IndirectLight import com.google.android.filament.Skybox +import com.google.android.filament.View import com.google.android.filament.utils.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -97,6 +98,10 @@ class MainActivity : Activity() { val view = modelViewer.view view.dynamicResolutionOptions = view.dynamicResolutionOptions.apply { enabled = true + quality = View.QualityLevel.ULTRA + homogeneousScaling = true + minScale = 0.5f + maxScale = 0.5f } view.ambientOcclusionOptions = view.ambientOcclusionOptions.apply { diff --git a/filament/CMakeLists.txt b/filament/CMakeLists.txt index 45fdfcac62..45dbd33278 100644 --- a/filament/CMakeLists.txt +++ b/filament/CMakeLists.txt @@ -63,6 +63,7 @@ set(SRCS src/FrameSkipper.cpp src/Froxelizer.cpp src/Frustum.cpp + src/fsr.cpp src/IndexBuffer.cpp src/IndirectLight.cpp src/Material.cpp @@ -161,10 +162,15 @@ set(PRIVATE_HDRS src/fg2/details/Resource.h src/fg2/details/ResourceNode.h src/fg2/details/Utilities.h + src/fsr.h + src/materials/fsr/ffx_a.h + src/materials/fsr/ffx_fsr1.h src/upcast.h ) set(MATERIAL_SRCS + src/materials/fsr/fsr_easu.mat + src/materials/fsr/fsr_rcas.mat src/materials/colorGrading/colorGrading.mat src/materials/colorGrading/colorGradingAsSubpass.mat src/materials/defaultMaterial.mat @@ -352,6 +358,20 @@ add_custom_command( APPEND ) +add_custom_command( + OUTPUT "${MATERIAL_DIR}/fsr_easu.filamat" + DEPENDS src/materials/fsr/ffx_a.h + DEPENDS src/materials/fsr/ffx_fsr1.h + APPEND +) + +add_custom_command( + OUTPUT "${MATERIAL_DIR}/fsr_rcas.filamat" + DEPENDS src/materials/fsr/ffx_a.h + DEPENDS src/materials/fsr/ffx_fsr1.h + APPEND +) + add_custom_command( OUTPUT ${RESGEN_OUTPUTS} COMMAND resgen ${RESGEN_FLAGS} ${MATERIAL_BINS} diff --git a/filament/backend/src/opengl/OpenGLProgram.cpp b/filament/backend/src/opengl/OpenGLProgram.cpp index 885a93f434..3e051fbf68 100644 --- a/filament/backend/src/opengl/OpenGLProgram.cpp +++ b/filament/backend/src/opengl/OpenGLProgram.cpp @@ -81,8 +81,8 @@ OpenGLProgram::OpenGLProgram(OpenGLDriver* gl, const Program& programBuilder) no std::string unpackHalf2x16{ R"( +// these don't handle denormals, NaNs or inf float u16tofp32(highp uint v) { - // this doesn't handle denormals, NaNs or inf v <<= 16u; highp uint s = v & 0x80000000u; highp uint n = v & 0x7FFFFFFFu; @@ -92,7 +92,28 @@ float u16tofp32(highp uint v) { vec2 unpackHalf2x16(highp uint v) { return vec2(u16tofp32(v&0xFFFFu), u16tofp32(v>>16u)); } - +uint fp32tou16(float val) { + uint f32 = floatBitsToUint(val); + uint f16 = 0u; + uint sign = (f32 >> 16) & 0x8000u; + int exponent = int((f32 >> 23) & 0xFFu) - 127; + uint mantissa = f32 & 0x007FFFFFu; + if (exponent > 15) { + f16 = sign | (0x1Fu << 10); + } else if (exponent > -15) { + exponent += 15; + mantissa >>= 13; + f16 = sign | uint(exponent << 10) | mantissa; + } else { + f16 = sign; + } + return f16; +} +highp uint packHalf2x16(vec2 v) { + highp uint x = fp32tou16(v.x); + highp uint y = fp32tou16(v.y); + return (y << 16) | x; +} )"}; // a good point for insertion is just before the first occurrence of an uniform block auto pos = temp.find("layout(std140)"); diff --git a/filament/include/filament/Options.h b/filament/include/filament/Options.h index a27aa71d62..b630effcc7 100644 --- a/filament/include/filament/Options.h +++ b/filament/include/filament/Options.h @@ -71,9 +71,21 @@ enum class BlendMode : uint8_t { struct DynamicResolutionOptions { math::float2 minScale = math::float2(0.5f); //!< minimum scale factors in x and y math::float2 maxScale = math::float2(1.0f); //!< maximum scale factors in x and y + float sharpness = 0.2f; //!< sharpness when QualityLevel::ULTRA is used [0 (sharpest), 2 (smoothest)] bool enabled = false; //!< enable or disable dynamic resolution bool homogeneousScaling = false; //!< set to true to force homogeneous scaling - QualityLevel quality = QualityLevel::LOW; //!< Upscaling quality + + /** + * Upscaling quality + * LOW: bilinear filtered blit. Fastest, poor quality + * MEDIUM: 16-tap optimized tent filter. + * HIGH: 36-tap optimized tent filter. + * ULTRA: AMD FidelityFX FSR1. Slowest, very high quality. + * Requires a well anti-aliased (MSAA or TAA), noise free scene. + * + * The default upscaling quality is set to LOW. + */ + QualityLevel quality = QualityLevel::LOW; }; /** diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp index 9eac8468e5..d70e723db6 100644 --- a/filament/src/PostProcessManager.cpp +++ b/filament/src/PostProcessManager.cpp @@ -29,6 +29,7 @@ #include "fg2/FrameGraph.h" #include "fg2/FrameGraphResources.h" +#include "fsr.h" #include "RenderPass.h" #include "details/Camera.h" @@ -226,6 +227,8 @@ static const MaterialInfo sMaterialList[] = { { "separableGaussianBlur", MATERIAL(SEPARABLEGAUSSIANBLUR) }, { "taa", MATERIAL(TAA) }, { "vsmMipmap", MATERIAL(VSMMIPMAP) }, + { "fsr_easu", MATERIAL(FSR_EASU) }, + { "fsr_rcas", MATERIAL(FSR_RCAS) }, }; void PostProcessManager::init() noexcept { @@ -2267,12 +2270,17 @@ FrameGraphId PostProcessManager::opaqueBlit(FrameGraph& fg, } FrameGraphId PostProcessManager::blendBlit( - FrameGraph& fg, bool translucent, QualityLevel quality, + FrameGraph& fg, bool translucent, DynamicResolutionOptions dsrOptions, FrameGraphId input, FrameGraphTexture::Descriptor const& outDesc) noexcept { Handle fullScreenRenderPrimitive = mEngine.getFullScreenRenderPrimitive(); + if (translucent && dsrOptions.quality == QualityLevel::ULTRA) { + // FidelityFX-FSR doesn't support the alpha channel currently + dsrOptions.quality = QualityLevel::MEDIUM; + } + struct QuadBlitData { FrameGraphId input; FrameGraphId output; @@ -2289,23 +2297,41 @@ FrameGraphId PostProcessManager::blendBlit( auto color = resources.getTexture(data.input); auto out = resources.getRenderPassInfo(); - auto const& desc = resources.getDescriptor(data.input); + auto const& inputDesc = resources.getDescriptor(data.input); + auto const& outputDesc = resources.getDescriptor(data.output); - const StaticString blitterNames[3] = { "blitLow", "blitMedium", "blitHigh" }; - unsigned index = std::min(2u, (unsigned)quality); + const StaticString blitterNames[4] = { "blitLow", "blitMedium", "blitHigh", "fsr_easu" }; + unsigned index = std::min(3u, (unsigned)dsrOptions.quality); auto& material = getPostProcessMaterial(blitterNames[index]); FMaterialInstance* const mi = material.getMaterialInstance(); + + if (dsrOptions.quality == QualityLevel::ULTRA) { + FSRUniforms uniforms; + FSR_ScalingSetup(&uniforms, { + .inputWidth = inputDesc.width, + .inputHeight = inputDesc.height, + .outputWidth = outputDesc.width, + .outputHeight = outputDesc.height, + }); + mi->setParameter("EasuCon0", uniforms.EasuCon0); + mi->setParameter("EasuCon1", uniforms.EasuCon1); + mi->setParameter("EasuCon2", uniforms.EasuCon2); + mi->setParameter("EasuCon3", uniforms.EasuCon3); + } + mi->setParameter("color", color, { - .filterMag = SamplerMagFilter::LINEAR, - .filterMin = SamplerMinFilter::LINEAR + .filterMag = SamplerMagFilter::LINEAR, + .filterMin = SamplerMinFilter::LINEAR }); mi->setParameter("resolution", - float4{ desc.width, desc.height, 1.0f / desc.width, 1.0f / desc.height }); + float4{ outputDesc.width, outputDesc.height, + 1.0f / outputDesc.width, 1.0f / outputDesc.height }); mi->commit(driver); mi->use(driver); PipelineState pipeline(material.getPipelineState()); if (translucent) { + assert_invariant(dsrOptions.quality != QualityLevel::ULTRA); pipeline.rasterState.blendFunctionSrcRGB = BlendFunction::ONE; pipeline.rasterState.blendFunctionSrcAlpha = BlendFunction::ONE; pipeline.rasterState.blendFunctionDstRGB = BlendFunction::ONE_MINUS_SRC_ALPHA; @@ -2316,8 +2342,48 @@ FrameGraphId PostProcessManager::blendBlit( driver.endRenderPass(); }); + auto output = ppQuadBlit->output; + + if (dsrOptions.quality == QualityLevel::ULTRA) { + + auto& ppFsrRcas = fg.addPass("FidelityFX FSR1 Rcas", + [&](FrameGraph::Builder& builder, auto& data) { + data.input = builder.sample(output); + data.output = builder.createTexture("FFX FSR1 Rcas output", outDesc); + data.output = builder.declareRenderPass(data.output); + }, + [=](FrameGraphResources const& resources, + auto const& data, DriverApi& driver) { + + auto color = resources.getTexture(data.input); + auto out = resources.getRenderPassInfo(); + auto const& outputDesc = resources.getDescriptor(data.output); + + auto& material = getPostProcessMaterial("fsr_rcas"); + FMaterialInstance* const mi = material.getMaterialInstance(); + + FSRUniforms uniforms; + FSR_SharpeningSetup(&uniforms, { .sharpness = dsrOptions.sharpness }); + mi->setParameter("RcasCon", uniforms.RcasCon); + mi->setParameter("color", color, { }); // uses texelFetch + mi->setParameter("resolution", float4{ + outputDesc.width, outputDesc.height, + 1.0f / outputDesc.width, 1.0f / outputDesc.height }); + mi->commit(driver); + mi->use(driver); + + PipelineState pipeline(material.getPipelineState()); + assert_invariant(!translucent); + driver.beginRenderPass(out.target, out.params); + driver.draw(pipeline, fullScreenRenderPrimitive); + driver.endRenderPass(); + }); + + output = ppFsrRcas->output; + } + // we rely on automatic culling of unused render passes - return ppQuadBlit->output; + return output; } FrameGraphId PostProcessManager::resolve(FrameGraph& fg, diff --git a/filament/src/PostProcessManager.h b/filament/src/PostProcessManager.h index 6c1d6cb8e9..ef928584db 100644 --- a/filament/src/PostProcessManager.h +++ b/filament/src/PostProcessManager.h @@ -122,7 +122,7 @@ public: backend::SamplerMagFilter filter = backend::SamplerMagFilter::LINEAR) noexcept; FrameGraphId blendBlit( - FrameGraph& fg, bool translucent, QualityLevel quality, + FrameGraph& fg, bool translucent, DynamicResolutionOptions dsrOptions, FrameGraphId input, FrameGraphTexture::Descriptor const& outDesc) noexcept; diff --git a/filament/src/Renderer.cpp b/filament/src/Renderer.cpp index e708daefb2..71b7112c6c 100644 --- a/filament/src/Renderer.cpp +++ b/filament/src/Renderer.cpp @@ -231,7 +231,7 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { bool hasFXAA = view.getAntiAliasing() == AntiAliasing::FXAA; uint8_t msaaSampleCount = view.getSampleCount(); float2 scale = view.updateScale(mFrameInfoManager.getLastFrameInfo()); - const QualityLevel upscalingQuality = view.getDynamicResolutionOptions().quality; + auto dsrOptions = view.getDynamicResolutionOptions(); auto bloomOptions = view.getBloomOptions(); auto dofOptions = view.getDepthOfFieldOptions(); auto aoOptions = view.getAmbientOcclusionOptions(); @@ -550,11 +550,14 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { } if (scaled) { mightNeedFinalBlit = false; - if (UTILS_LIKELY(!blending && upscalingQuality == QualityLevel::LOW)) { - input = ppm.opaqueBlit(fg, input, { .format = colorGradingConfig.ldrFormat }); + if (UTILS_LIKELY(!blending && dsrOptions.quality == QualityLevel::LOW)) { + input = ppm.opaqueBlit(fg, input, { + .width = vp.width, .height = vp.height, + .format = colorGradingConfig.ldrFormat }, SamplerMagFilter::LINEAR); } else { - input = ppm.blendBlit(fg, true, upscalingQuality, input, - { .format = colorGradingConfig.ldrFormat }); + input = ppm.blendBlit(fg, blending, dsrOptions, input, { + .width = vp.width, .height = vp.height, + .format = colorGradingConfig.ldrFormat }); } } } @@ -574,11 +577,14 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { if (mightNeedFinalBlit && ((outputIsSwapChain && (msaaSampleCount > 1 || colorGradingConfig.asSubpass)) || blending)) { - if (UTILS_LIKELY(!blending && upscalingQuality == QualityLevel::LOW)) { - input = ppm.opaqueBlit(fg, input, { .format = colorGradingConfig.ldrFormat }); + if (UTILS_LIKELY(!blending && dsrOptions.quality == QualityLevel::LOW)) { + input = ppm.opaqueBlit(fg, input, { + .width = vp.width, .height = vp.height, + .format = colorGradingConfig.ldrFormat }, SamplerMagFilter::LINEAR); } else { - input = ppm.blendBlit(fg, true, upscalingQuality, input, - { .format = colorGradingConfig.ldrFormat }); + input = ppm.blendBlit(fg, blending, dsrOptions, input, { + .width = vp.width, .height = vp.height, + .format = colorGradingConfig.ldrFormat }); } } diff --git a/filament/src/View.cpp b/filament/src/View.cpp index 32f5fdd47d..eb8bee85a8 100644 --- a/filament/src/View.cpp +++ b/filament/src/View.cpp @@ -115,6 +115,8 @@ void FView::setDynamicResolutionOptions(DynamicResolutionOptions const& options) // clamp maxScale to 2x because we're doing bilinear filtering, so super-sampling // is not useful above that. dynamicResolution.maxScale = min(dynamicResolution.maxScale, float2(2.0f)); + + dynamicResolution.sharpness = clamp(dynamicResolution.sharpness, 0.0f, 2.0f); } } diff --git a/filament/src/fsr.cpp b/filament/src/fsr.cpp new file mode 100644 index 0000000000..9344394559 --- /dev/null +++ b/filament/src/fsr.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fsr.h" + +#include + +#include +#include +#include + +namespace filament { + +using namespace math; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +#pragma clang diagnostic ignored "-Wignored-qualifiers" + +#define A_CPU 1 +#include "materials/fsr/ffx_a.h" +#define FSR_EASU_F 1 +#define FSR_RCAS_F 1 +#include "materials/fsr/ffx_fsr1.h" + +#pragma clang diagnostic pop + +void FSR_ScalingSetup(FSRUniforms* outUniforms, FSRScalingConfig config) noexcept { + FsrEasuCon( outUniforms->EasuCon0.v, outUniforms->EasuCon1.v, + outUniforms->EasuCon2.v, outUniforms->EasuCon3.v, + // Viewport size (top left aligned) in the input image which is to be scaled. + config.inputWidth, config.inputHeight, + // The size of the input image. + config.inputWidth, config.inputHeight, + // The output resolution. + config.outputWidth, config.outputHeight); +} + +void FSR_SharpeningSetup(FSRUniforms* outUniforms, FSRSharpeningConfig config) noexcept { + FsrRcasCon(outUniforms->RcasCon.v, config.sharpness); +} + +} // namespace filament + + diff --git a/filament/src/fsr.h b/filament/src/fsr.h new file mode 100644 index 0000000000..187ab9d7d0 --- /dev/null +++ b/filament/src/fsr.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TNT_FILAMENT_FSR_H +#define TNT_FILAMENT_FSR_H + +#include + +#include + +namespace filament { + +struct FSRScalingConfig { + uint32_t inputWidth; + uint32_t inputHeight; + uint32_t outputWidth; + uint32_t outputHeight; +}; + +struct FSRSharpeningConfig { + // The scale is {0.0 := maximum sharpness, to N>0, where N is the number of stops (halving) + // of the reduction of sharpness}. + float sharpness; +}; + +struct FSRUniforms { + math::uint4 EasuCon0; + math::uint4 EasuCon1; + math::uint4 EasuCon2; + math::uint4 EasuCon3; + math::uint4 RcasCon; +}; + +void FSR_ScalingSetup(FSRUniforms* inoutUniforms, FSRScalingConfig config) noexcept; +void FSR_SharpeningSetup(FSRUniforms* inoutUniforms, FSRSharpeningConfig config) noexcept; + +} // namespace filament + +#endif // TNT_FILAMENT_FSR_H diff --git a/filament/src/materials/fsr/ffx_fsr1.h b/filament/src/materials/fsr/ffx_fsr1.h index 15ecfde5c2..b7c69df620 100644 --- a/filament/src/materials/fsr/ffx_fsr1.h +++ b/filament/src/materials/fsr/ffx_fsr1.h @@ -199,7 +199,7 @@ AF1 outputSizeInPixelsY){ con2[3]=AU1_AF1(AF1_( 2.0)*ARcpF1(inputSizeInPixelsY)); con3[0]=AU1_AF1(AF1_( 0.0)*ARcpF1(inputSizeInPixelsX)); con3[1]=AU1_AF1(AF1_( 4.0)*ARcpF1(inputSizeInPixelsY)); - con3[2]=con3[3]=0;} + con3[2]=con3[3]=AU1(0);} //If the an offset into the input image resource A_STATIC void FsrEasuConOffset( @@ -434,7 +434,8 @@ A_STATIC void FsrEasuConOffset( FsrEasuTapF(aC,aW,AF2( 0.0, 2.0)-pp,dir,len2,lob,clp,AF3(zzonR.w,zzonG.w,zzonB.w)); // n //------------------------------------------------------------------------------------------------------------------------------ // Normalize and dering. - pix=min(max4,max(min4,aC*AF3_(ARcpF1(aW))));} + pix=min(max4,max(min4,aC*AF3_(ARcpF1(aW)))); +} #endif //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -668,8 +669,8 @@ AF1 sharpness){ varAF2(hSharp)=initAF2(sharpness,sharpness); con[0]=AU1_AF1(sharpness); con[1]=AU1_AH2_AF2(hSharp); - con[2]=0; - con[3]=0;} + con[2]=AU1(0); + con[3]=AU1(0);} //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //_____________________________________________________________/\_______________________________________________________________ diff --git a/filament/src/materials/fsr/fsr_easu.mat b/filament/src/materials/fsr/fsr_easu.mat new file mode 100644 index 0000000000..dfa4d1bc8b --- /dev/null +++ b/filament/src/materials/fsr/fsr_easu.mat @@ -0,0 +1,114 @@ +material { + name : fsr_easu, + parameters : [ + { + type : sampler2d, + name : color, + precision: medium + }, + { + type : float4, + name : resolution, + precision: high + }, + { + type : uint4, + name : EasuCon0, + precision: high + }, + { + type : uint4, + name : EasuCon1, + precision: high + }, + { + type : uint4, + name : EasuCon2, + precision: high + }, + { + type : uint4, + name : EasuCon3, + precision: high + } + ], + variables : [ + vertex + ], + depthWrite : false, + depthCulling : false, + domain: postprocess +} + +vertex { + void postProcessVertex(inout PostProcessVertexInputs postProcess) { + postProcess.vertex.xy = postProcess.normalizedUV * materialParams.resolution.xy; + } +} + +fragment { + + precision mediump float; + precision highp int; + + #define A_GPU 1 + #define A_GLSL 1 + #include "ffx_a.h" + #define FSR_EASU_F 1 + #include "ffx_fsr1.h" + +#if defined(FILAMENT_HAS_FEATURE_TEXTURE_GATHER) + AF4 FsrEasuRF(AF2 p) { + return textureGather(materialParams_color, p, 0); + } + + AF4 FsrEasuGF(AF2 p) { + return textureGather(materialParams_color, p, 1); + } + + AF4 FsrEasuBF(AF2 p) { + return textureGather(materialParams_color, p, 2); + } +#else + AF4 FsrEasuRF(AF2 p) { + vec4 d; + d[0] = textureLodOffset(materialParams_color, p, 0.0, ivec2(0, 1)).r; + d[1] = textureLodOffset(materialParams_color, p, 0.0, ivec2(1, 1)).r; + d[2] = textureLodOffset(materialParams_color, p, 0.0, ivec2(1, 0)).r; + d[3] = textureLodOffset(materialParams_color, p, 0.0, ivec2(0, 0)).r; + return AF4(d); + } + + AF4 FsrEasuGF(AF2 p) { + vec4 d; + d[0] = textureLodOffset(materialParams_color, p, 0.0, ivec2(0, 1)).g; + d[1] = textureLodOffset(materialParams_color, p, 0.0, ivec2(1, 1)).g; + d[2] = textureLodOffset(materialParams_color, p, 0.0, ivec2(1, 0)).g; + d[3] = textureLodOffset(materialParams_color, p, 0.0, ivec2(0, 0)).g; + return AF4(d); + } + + AF4 FsrEasuBF(AF2 p) { + vec4 d; + d[0] = textureLodOffset(materialParams_color, p, 0.0, ivec2(0, 1)).b; + d[1] = textureLodOffset(materialParams_color, p, 0.0, ivec2(1, 1)).b; + d[2] = textureLodOffset(materialParams_color, p, 0.0, ivec2(1, 0)).b; + d[3] = textureLodOffset(materialParams_color, p, 0.0, ivec2(0, 0)).b; + return AF4(d); + } +#endif + + void postProcess(inout PostProcessInputs postProcess) { + highp uvec2 p = uvec2(variable_vertex.xy); + + AF3 pix; + FsrEasuF(pix, p, + materialParams.EasuCon0, + materialParams.EasuCon1, + materialParams.EasuCon2, + materialParams.EasuCon3); + + postProcess.color.rgb = pix; + postProcess.color.a = 1.0; // TODO: FSR doesn't support transparency. + } +} diff --git a/filament/src/materials/fsr/fsr_rcas.mat b/filament/src/materials/fsr/fsr_rcas.mat new file mode 100644 index 0000000000..56fc4fa475 --- /dev/null +++ b/filament/src/materials/fsr/fsr_rcas.mat @@ -0,0 +1,59 @@ +material { + name : fsr_rcas, + parameters : [ + { + type : sampler2d, + name : color, + precision: medium + }, + { + type : float4, + name : resolution, + precision: high + }, + { + type : uint4, + name : RcasCon, + precision: high + } + ], + variables : [ + vertex + ], + depthWrite : false, + depthCulling : false, + domain: postprocess +} + +vertex { + void postProcessVertex(inout PostProcessVertexInputs postProcess) { + postProcess.vertex.xy = postProcess.normalizedUV * materialParams.resolution.xy; + } +} + +fragment { + + precision mediump float; + precision highp int; + + #define A_GPU 1 + #define A_GLSL 1 + #include "ffx_a.h" + #define FSR_RCAS_F 1 + #include "ffx_fsr1.h" + + AF4 FsrRcasLoadF(ASU2 p) { + return texelFetch(materialParams_color, p, 0); + } + + void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) { } + + void postProcess(inout PostProcessInputs postProcess) { + highp uvec2 p = uvec2(variable_vertex.xy); + + FsrRcasF(postProcess.color.r, postProcess.color.g, postProcess.color.b, + p, materialParams.RcasCon); + + postProcess.color.a = 1.0; // TODO: FSR doesn't support transparency. + } +} diff --git a/samples/gltf_viewer.cpp b/samples/gltf_viewer.cpp index 05287b9319..14896afcbe 100644 --- a/samples/gltf_viewer.cpp +++ b/samples/gltf_viewer.cpp @@ -345,6 +345,8 @@ static void createGroundPlane(Engine* engine, Scene* scene, App& app) { static float sGlobalScale = 1.0f; static float sGlobalScaleAnamorphism = 0.0f; +static int sGlobalScaleQuality = 0; +static float sGlobalScaleSharpness = 0.2f; int main(int argc, char** argv) { App app; @@ -575,6 +577,9 @@ int main(int argc, char** argv) { } ImGui::SliderFloat("scale", &sGlobalScale, 0.25f, 1.0f); ImGui::SliderFloat("anamorphism", &sGlobalScaleAnamorphism, -1.0f, 1.0f); + ImGui::SliderInt("quality", &sGlobalScaleQuality, 0, 3); + ImGui::SliderFloat("sharpness", &sGlobalScaleSharpness, 0.0f, 2.0f); + } if (ImGui::BeginPopupModal("MessageBox", NULL, ImGuiWindowFlags_AlwaysAutoResize)) { @@ -700,7 +705,9 @@ int main(int argc, char** argv) { lerp(sGlobalScale, 1.0f, sGlobalScaleAnamorphism <= 0.0f ? -sGlobalScaleAnamorphism : 0.0f), }, + .sharpness = sGlobalScaleSharpness, .enabled = sGlobalScale != 1.0f, + .quality = (QualityLevel)sGlobalScaleQuality }); };