WIP

Antonio Scandurra created

Change summary

crates/gpui3/src/platform.rs                    |   4 
crates/gpui3/src/platform/mac/metal_renderer.rs | 107 ++++++++++++++++--
crates/gpui3/src/scene.rs                       |   6 
3 files changed, 98 insertions(+), 19 deletions(-)

Detailed changes

crates/gpui3/src/platform.rs 🔗

@@ -245,7 +245,7 @@ pub struct AtlasTile {
     pub(crate) bounds: Bounds<DevicePixels>,
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 #[repr(C)]
 pub(crate) struct AtlasTextureId {
     // We use u32 instead of usize for Metal Shader Language compatibility
@@ -253,7 +253,7 @@ pub(crate) struct AtlasTextureId {
     pub(crate) kind: AtlasTextureKind,
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 #[repr(C)]
 pub(crate) enum AtlasTextureKind {
     Monochrome = 0,

crates/gpui3/src/platform/mac/metal_renderer.rs 🔗

@@ -1,7 +1,7 @@
 use crate::{
-    point, size, AtlasTextureId, AtlasTextureKind, AtlasTile, DevicePixels, MetalAtlas,
-    MonochromeSprite, PathId, PolychromeSprite, PrimitiveBatch, Quad, Scene, Shadow, Size,
-    Underline,
+    point, size, AtlasTextureId, AtlasTextureKind, AtlasTile, Bounds, ContentMask, DevicePixels,
+    MetalAtlas, MonochromeSprite, Path, PathId, PathVertex, PolychromeSprite, PrimitiveBatch, Quad,
+    ScaledPixels, Scene, Shadow, Size, Underline,
 };
 use cocoa::{
     base::{NO, YES},
@@ -170,6 +170,9 @@ impl MetalRenderer {
         };
         let command_queue = self.command_queue.clone();
         let command_buffer = command_queue.new_command_buffer();
+        let mut instance_offset = 0;
+
+        let path_tiles = self.rasterize_paths(scene.paths(), &mut instance_offset, &command_buffer);
 
         let render_pass_descriptor = metal::RenderPassDescriptor::new();
         let color_attachment = render_pass_descriptor
@@ -192,17 +195,6 @@ impl MetalRenderer {
             znear: 0.0,
             zfar: 1.0,
         });
-
-        let mut instance_offset = 0;
-
-        let mut path_tiles: HashMap<PathId, AtlasTile> = HashMap::default();
-        for path in scene.paths() {
-            let tile = self
-                .sprite_atlas
-                .allocate(path.bounds.size.map(Into::into), AtlasTextureKind::Path);
-            path_tiles.insert(path.id, tile);
-        }
-
         for batch in scene.batches() {
             match batch {
                 PrimitiveBatch::Shadows(shadows) => {
@@ -266,6 +258,93 @@ impl MetalRenderer {
         drawable.present();
     }
 
+    fn rasterize_paths(
+        &mut self,
+        paths: &[Path<ScaledPixels>],
+        offset: &mut usize,
+        command_buffer: &metal::CommandBufferRef,
+    ) -> HashMap<PathId, AtlasTile> {
+        let mut tiles = HashMap::default();
+        let mut vertices_by_texture_id = HashMap::default();
+        for path in paths {
+            let tile = self
+                .sprite_atlas
+                .allocate(path.bounds.size.map(Into::into), AtlasTextureKind::Path);
+            vertices_by_texture_id
+                .entry(tile.texture_id)
+                .or_insert(Vec::new())
+                .extend(path.vertices.iter().map(|vertex| PathVertex {
+                    xy_position: vertex.xy_position - path.bounds.origin
+                        + tile.bounds.origin.map(Into::into),
+                    st_position: vertex.st_position,
+                    content_mask: ContentMask {
+                        bounds: Bounds {
+                            origin: vertex.xy_position - path.bounds.origin
+                                + tile.bounds.origin.map(Into::into),
+                            size: vertex.content_mask.bounds.size,
+                        },
+                    },
+                }));
+            tiles.insert(path.id, tile);
+        }
+
+        for (texture_id, vertices) in vertices_by_texture_id {
+            todo!();
+            // align_offset(offset);
+            // let next_offset = *offset + vertices.len() * mem::size_of::<PathVertex<ScaledPixels>>();
+            // assert!(
+            //     next_offset <= INSTANCE_BUFFER_SIZE,
+            //     "instance buffer exhausted"
+            // );
+
+            // let render_pass_descriptor = metal::RenderPassDescriptor::new();
+            // let color_attachment = render_pass_descriptor
+            //     .color_attachments()
+            //     .object_at(0)
+            //     .unwrap();
+
+            // let texture = self.sprite_atlas.metal_texture(texture_id);
+            // color_attachment.set_texture(Some(&texture));
+            // color_attachment.set_load_action(metal::MTLLoadAction::Clear);
+            // color_attachment.set_store_action(metal::MTLStoreAction::Store);
+            // color_attachment.set_clear_color(metal::MTLClearColor::new(0., 0., 0., 1.));
+            // let command_encoder = command_buffer.new_render_command_encoder(render_pass_descriptor);
+            // command_encoder.set_render_pipeline_state(&self.path_atlas_pipeline_state);
+            // command_encoder.set_vertex_buffer(
+            //     shaders::GPUIPathAtlasVertexInputIndex_GPUIPathAtlasVertexInputIndexVertices as u64,
+            //     Some(&self.instances),
+            //     *offset as u64,
+            // );
+            // command_encoder.set_vertex_bytes(
+            //     shaders::GPUIPathAtlasVertexInputIndex_GPUIPathAtlasVertexInputIndexAtlasSize
+            //         as u64,
+            //     mem::size_of::<shaders::vector_float2>() as u64,
+            //     [vec2i(texture.width() as i32, texture.height() as i32).to_float2()].as_ptr()
+            //         as *const c_void,
+            // );
+
+            // let buffer_contents = unsafe {
+            //     (self.instances.contents() as *mut u8).add(*offset) as *mut shaders::GPUIPathVertex
+            // };
+
+            // for (ix, vertex) in vertices.iter().enumerate() {
+            //     unsafe {
+            //         *buffer_contents.add(ix) = *vertex;
+            //     }
+            // }
+
+            // command_encoder.draw_primitives(
+            //     metal::MTLPrimitiveType::Triangle,
+            //     0,
+            //     vertices.len() as u64,
+            // );
+            // command_encoder.end_encoding();
+            // *offset = next_offset;
+        }
+
+        tiles
+    }
+
     fn draw_shadows(
         &mut self,
         shadows: &[Shadow],

crates/gpui3/src/scene.rs 🔗

@@ -180,8 +180,8 @@ pub(crate) struct Scene {
 }
 
 impl Scene {
-    pub fn paths(&self) -> impl Iterator<Item = &Path<ScaledPixels>> {
-        self.paths.iter()
+    pub fn paths(&self) -> &[Path<ScaledPixels>] {
+        &self.paths
     }
 
     pub fn batches(&self) -> impl Iterator<Item = PrimitiveBatch> {
@@ -678,7 +678,7 @@ impl From<Path<ScaledPixels>> for Primitive {
     }
 }
 
-#[derive(Debug)]
+#[derive(Clone, Debug)]
 #[repr(C)]
 pub struct PathVertex<P: Clone + Debug> {
     pub(crate) xy_position: Point<P>,