Optimized feather (#11625) 72f05121ea
* Convert to Float16

* Clang

* Update render_context_vulkan_impl.cpp

* Updated GMS

* Update render_context_gl_impl.cpp

* Update

* Update gpu_namespace_test.cpp

* Update gpu_namespace_test.cpp

* clang

* Comments

* clang

* Update common.glsl

* Update Shaders

* Add non conversion filtering path

* Update draw_path_common.glsl

* Remove gather and use a R16 texture for atlas

* Update draw_path_common.glsl

* Update draw_path_common.glsl

* Update draw_path_common.glsl

* Update draw_path_common.glsl

* Revert back to R32

* Update render_context_d3d_impl.cpp

* Update draw_path_common.glsl

* Update draw_path_common.glsl

* Update draw_path_common.glsl

* Update draw_path_common.glsl

* Update render_context_metal_impl.mm

* remove r16

* Update pipeline_manager_vulkan.cpp

* Update pipeline_manager_vulkan.cpp

* Change metal to R16F

* Moved filter_feather into a inline function

* Rebase GMs

* Restore 16 bit

* Fixes

* Update pipeline_manager_vulkan.cpp

* Clang

* Update GMs

* Update GMS

* Remove setting feather texture

* clang

* Update Gms

* GMS

* Update GMs

* Update pr_platform_tests.yaml

* GMS

* Change min to clamp

* Rebase GMs

* GMS

* GMS

* GMS

* GMS

* GMS

* gms

* GMS

* GMs

* GMs

* GMS

Co-authored-by: John White <aliasbinman@gmail.com>
diff --git a/.rive_head b/.rive_head
index fe93c07..206c857 100644
--- a/.rive_head
+++ b/.rive_head
@@ -1 +1 @@
-a03a19071f550263c1bed327923a1e0d32975618
+72f05121ea61a82c2bdb3a4d7cdb56c629af77e0
diff --git a/renderer/src/gl/render_context_gl_impl.cpp b/renderer/src/gl/render_context_gl_impl.cpp
index 464a4bb..e38d775 100644
--- a/renderer/src/gl/render_context_gl_impl.cpp
+++ b/renderer/src/gl/render_context_gl_impl.cpp
@@ -1461,9 +1461,7 @@
     {
         glutils::Uniform1iByName(m_id, GLSL_gradTexture, GRAD_TEXTURE_IDX);
     }
-    if ((isTessellationDraw &&
-         (shaderFeatures & ShaderFeatures::ENABLE_FEATHER)) ||
-        drawType == gpu::DrawType::atlasBlit)
+    if (isTessellationDraw && (shaderFeatures & ShaderFeatures::ENABLE_FEATHER))
     {
         assert(isPaintDraw || interlockMode == gpu::InterlockMode::atomics);
         glutils::Uniform1iByName(m_id,
diff --git a/renderer/src/shaders/draw_path_common.glsl b/renderer/src/shaders/draw_path_common.glsl
index 80992e5..63f2923 100644
--- a/renderer/src/shaders/draw_path_common.glsl
+++ b/renderer/src/shaders/draw_path_common.glsl
@@ -265,6 +265,20 @@
 #endif // @ENABLE_FEATHER
 
 #if defined(@FRAGMENT) && defined(@ATLAS_BLIT)
+
+INLINE half filter_feather(half4 coverages,
+                           float2 atlasCoord,
+                           float2 atlasQuadCenter)
+{
+    coverages.xw = mix(coverages.xw,
+                       coverages.yz,
+                       make_half(atlasCoord.x + .5 - atlasQuadCenter.x));
+    coverages.x = mix(coverages.w,
+                      coverages.x,
+                      make_half(atlasCoord.y + .5 - atlasQuadCenter.y));
+    return clamp(coverages.x, make_half(0.0), make_half(1.0));
+}
+
 // Upscales a pre-rendered feather from the atlas, converting from gaussian
 // space to linear before doing a bilerp.
 INLINE half
@@ -274,19 +288,23 @@
     // Gather the quad of pixels we need to filter.
     // Gather from the exact center of the quad to make sure there are no
     // rounding differences between us and the texture unit.
-    float2 atlasQuadCenter = round(atlasCoord);
+
     half4 coverages;
+    float2 atlasQuadCenter = round(atlasCoord);
+
 #ifdef @ATLAS_TEXTURE_R32UI_FLOAT_BITS
     coverages = uintBitsToFloat(uint4(TEXTURE_GATHER(@atlasTexture,
                                                      atlasSampler,
                                                      atlasQuadCenter,
                                                      atlasTextureInverseSize)));
+    return filter_feather(coverages, atlasCoord, atlasQuadCenter);
 #elif defined(@ATLAS_TEXTURE_R32I_FIXED_POINT)
     int4 coverages_i32 = int4(TEXTURE_GATHER(@atlasTexture,
                                              atlasSampler,
                                              atlasQuadCenter,
                                              atlasTextureInverseSize));
     coverages = float4(coverages_i32) * (1. / ATLAS_R32I_FIXED_POINT_FACTOR);
+    return filter_feather(coverages, atlasCoord, atlasQuadCenter);
 #elif defined(@ATLAS_TEXTURE_RGBA8_UNORM)
     int2 coord = int2(atlasQuadCenter);
     half4x4 coverages_u8x4 =
@@ -301,27 +319,17 @@
                            255.,
                            -255.) *
                 coverages_u8x4;
+    return filter_feather(coverages, atlasCoord, atlasQuadCenter);
 #else
-    coverages = make_half4(TEXTURE_GATHER(@atlasTexture,
-                                          atlasSampler,
-                                          atlasQuadCenter,
-                                          atlasTextureInverseSize));
+    half cov = TEXTURE_SAMPLE_LOD(@atlasTexture,
+                                  atlasSampler,
+                                  atlasCoord * atlasTextureInverseSize,
+                                  .0)
+                   .r;
+    return clamp(cov, make_half(0.0), make_half(1.0));
 #endif
-    // Convert each pixel from gaussian space back to linear.
-    coverages = make_half4(INVERSE_FEATHER(coverages.x),
-                           INVERSE_FEATHER(coverages.y),
-                           INVERSE_FEATHER(coverages.z),
-                           INVERSE_FEATHER(coverages.w));
-    // Bilerp in linear space.
-    coverages.xw = mix(coverages.xw,
-                       coverages.yz,
-                       make_half(atlasCoord.x + .5 - atlasQuadCenter.x));
-    coverages.x = mix(coverages.w,
-                      coverages.x,
-                      make_half(atlasCoord.y + .5 - atlasQuadCenter.y));
-    // Go back to gaussian now that the bilerp is finished.
-    return FEATHER(coverages.x);
 }
+
 #endif // @FRAGMENT && @ATLAS_BLIT
 
 #if defined(@VERTEX) && defined(@DRAW_PATH)