Get glyphs sort of rendering

Nathan Sobo created

Change summary

gpui/build.rs                               | 11 +++++++
gpui/src/platform/mac/renderer.rs           | 29 ++++++++++------------
gpui/src/platform/mac/shaders/shaders.h     |  3 +
gpui/src/platform/mac/shaders/shaders.metal | 10 ++++---
gpui/src/platform/mac/sprite_cache.rs       |  8 ++++-
5 files changed, 37 insertions(+), 24 deletions(-)

Detailed changes

gpui/build.rs 🔗

@@ -51,7 +51,16 @@ fn compile_metal_shaders() {
     println!("cargo:rerun-if-changed={}", shader_path);
 
     let output = Command::new("xcrun")
-        .args(&["-sdk", "macosx", "metal", "-c", shader_path, "-o"])
+        .args(&[
+            "-sdk",
+            "macosx",
+            "metal",
+            "-gline-tables-only",
+            "-MO",
+            "-c",
+            shader_path,
+            "-o",
+        ])
         .arg(&air_output_path)
         .output()
         .unwrap();

gpui/src/platform/mac/renderer.rs 🔗

@@ -278,7 +278,7 @@ impl Renderer {
                     .or_insert_with(Vec::new)
                     .push(shaders::GPUISprite {
                         origin: (glyph.origin * scene.scale_factor()).to_float2(),
-                        size: (bounds.size().to_f32() * scene.scale_factor()).to_float2(),
+                        size: bounds.size().to_float2(),
                         atlas_origin: bounds.origin().to_float2(),
                         color: glyph.color.to_uchar4(),
                     });
@@ -293,18 +293,15 @@ impl Renderer {
             0,
         );
         ctx.command_encoder.set_vertex_bytes(
-            shaders::GPUISpriteVertexInputIndex_GPUISpriteVertexInputIndexUniforms as u64,
-            mem::size_of::<shaders::GPUIUniforms>() as u64,
-            [shaders::GPUIUniforms {
-                viewport_size: ctx.drawable_size.to_float2(),
-            }]
-            .as_ptr() as *const c_void,
+            shaders::GPUISpriteVertexInputIndex_GPUISpriteVertexInputIndexViewportSize as u64,
+            mem::size_of::<shaders::vector_float2>() as u64,
+            [ctx.drawable_size.to_float2()].as_ptr() as *const c_void,
+        );
+        ctx.command_encoder.set_vertex_bytes(
+            shaders::GPUISpriteVertexInputIndex_GPUISpriteVertexInputIndexAtlasSize as u64,
+            mem::size_of::<shaders::vector_float2>() as u64,
+            [self.sprite_cache.atlas_size().to_float2()].as_ptr() as *const c_void,
         );
-
-        let buffer_contents = unsafe {
-            (self.instances.contents() as *mut u8).offset(*offset as isize)
-                as *mut shaders::GPUISprite
-        };
 
         for (atlas_id, sprites) in sprites_by_atlas {
             align_offset(offset);
@@ -327,6 +324,9 @@ impl Renderer {
             );
 
             unsafe {
+                let buffer_contents = (self.instances.contents() as *mut u8)
+                    .offset(*offset as isize)
+                    as *mut shaders::GPUISprite;
                 std::ptr::copy_nonoverlapping(sprites.as_ptr(), buffer_contents, sprites.len());
             }
             self.instances.did_modify_range(NSRange {
@@ -430,10 +430,7 @@ mod shaders {
 
     impl ToFloat2 for Vector2I {
         fn to_float2(&self) -> vector_float2 {
-            let mut output = self.y() as vector_float2;
-            output <<= 32;
-            output |= self.x() as vector_float2;
-            output
+            self.to_f32().to_float2()
         }
     }
 

gpui/src/platform/mac/shaders/shaders.h 🔗

@@ -39,7 +39,8 @@ typedef struct {
 typedef enum {
     GPUISpriteVertexInputIndexVertices = 0,
     GPUISpriteVertexInputIndexSprites = 1,
-    GPUISpriteVertexInputIndexUniforms = 2,
+    GPUISpriteVertexInputIndexViewportSize = 2,
+    GPUISpriteVertexInputIndexAtlasSize = 3,
 } GPUISpriteVertexInputIndex;
 
 typedef enum {

gpui/src/platform/mac/shaders/shaders.metal 🔗

@@ -151,13 +151,14 @@ vertex SpriteFragmentInput sprite_vertex(
     uint sprite_id [[instance_id]],
     constant float2 *unit_vertices [[buffer(GPUISpriteVertexInputIndexVertices)]],
     constant GPUISprite *sprites [[buffer(GPUISpriteVertexInputIndexSprites)]],
-    constant GPUIUniforms *uniforms [[buffer(GPUISpriteVertexInputIndexUniforms)]]
+    constant float2 *viewport_size [[buffer(GPUISpriteVertexInputIndexViewportSize)]],
+    constant float2 *atlas_size [[buffer(GPUISpriteVertexInputIndexAtlasSize)]]
 ) {
     float2 unit_vertex = unit_vertices[unit_vertex_id];
     GPUISprite sprite = sprites[sprite_id];
     float2 position = unit_vertex * sprite.size + sprite.origin;
-    float2 atlas_position = unit_vertex * sprite.size + sprite.atlas_origin;
-    float4 device_position = to_device_position(position, uniforms->viewport_size);
+    float4 device_position = to_device_position(position, *viewport_size);
+    float2 atlas_position = (unit_vertex * sprite.size + sprite.atlas_origin) / *atlas_size;
 
     return SpriteFragmentInput {
         device_position,
@@ -172,6 +173,7 @@ fragment float4 sprite_fragment(
 ) {
     constexpr sampler atlas_sampler(mag_filter::linear, min_filter::linear);
     float4 color = input.color;
-    color.a *= atlas.sample(atlas_sampler, input.atlas_position).r;
+    float4 mask = atlas.sample(atlas_sampler, input.atlas_position);
+    color.a *= mask.a;
     return color;
 }

gpui/src/platform/mac/sprite_cache.rs 🔗

@@ -39,6 +39,10 @@ impl SpriteCache {
         }
     }
 
+    pub fn atlas_size(&self) -> Vector2I {
+        self.atlas_size
+    }
+
     pub fn render_glyph(
         &mut self,
         font_id: FontId,
@@ -64,12 +68,12 @@ impl SpriteCache {
 
                 let atlas = atlasses.last_mut().unwrap();
                 if let Some(bounds) = atlas.try_insert(size, &mask) {
-                    Some((atlasses.len() - 1, bounds))
+                    Some((atlasses.len() - 1, RectI::new(bounds.origin(), size)))
                 } else {
                     let mut atlas = Atlas::new(device, atlas_size);
                     let bounds = atlas.try_insert(size, &mask).unwrap();
                     atlasses.push(atlas);
-                    Some((atlasses.len() - 1, bounds))
+                    Some((atlasses.len() - 1, RectI::new(bounds.origin(), size)))
                 }
             })
             .clone()