mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-07 20:39:04 +03:00
WIP
This commit is contained in:
parent
764bfba2e2
commit
247afa1666
@ -1,28 +1,31 @@
|
||||
use std::{collections::HashMap, ffi::c_void, mem};
|
||||
|
||||
use self::shaders::ToUchar4;
|
||||
|
||||
use super::window::RenderContext;
|
||||
use crate::{color::ColorU, scene::Layer, Scene};
|
||||
use super::{sprite_cache::SpriteCache, window::RenderContext};
|
||||
use crate::{
|
||||
color::ColorU,
|
||||
geometry::vector::{vec2i, Vector2I},
|
||||
scene::Layer,
|
||||
Scene,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use metal::{MTLResourceOptions, NSRange};
|
||||
use shaders::ToFloat2 as _;
|
||||
use shaders::{ToFloat2 as _, ToUchar4 as _, ToUint2 as _};
|
||||
use std::{collections::HashMap, ffi::c_void, mem};
|
||||
|
||||
const SHADERS_METALLIB: &'static [u8] =
|
||||
include_bytes!(concat!(env!("OUT_DIR"), "/shaders.metallib"));
|
||||
const INSTANCE_BUFFER_SIZE: usize = 1024 * 1024; // This is an arbitrary decision. There's probably a more optimal value.
|
||||
const ATLAS_SIZE: Vector2I = vec2i(1024, 768);
|
||||
|
||||
pub struct Renderer {
|
||||
sprite_cache: SpriteCache,
|
||||
quad_pipeline_state: metal::RenderPipelineState,
|
||||
shadow_pipeline_state: metal::RenderPipelineState,
|
||||
sprite_pipeline_state: metal::RenderPipelineState,
|
||||
unit_vertices: metal::Buffer,
|
||||
instances: metal::Buffer,
|
||||
sprite_cache: SpriteCache,
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
pub fn new(device: &metal::DeviceRef, pixel_format: metal::MTLPixelFormat) -> Result<Self> {
|
||||
pub fn new(device: metal::Device, pixel_format: metal::MTLPixelFormat) -> Result<Self> {
|
||||
let library = device
|
||||
.new_library_with_data(SHADERS_METALLIB)
|
||||
.map_err(|message| anyhow!("error building metal library: {}", message))?;
|
||||
@ -46,8 +49,9 @@ impl Renderer {
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
sprite_cache: SpriteCache::new(device, ATLAS_SIZE),
|
||||
quad_pipeline_state: build_pipeline_state(
|
||||
device,
|
||||
&device,
|
||||
&library,
|
||||
"quad",
|
||||
"quad_vertex",
|
||||
@ -55,7 +59,7 @@ impl Renderer {
|
||||
pixel_format,
|
||||
)?,
|
||||
shadow_pipeline_state: build_pipeline_state(
|
||||
device,
|
||||
&device,
|
||||
&library,
|
||||
"shadow",
|
||||
"shadow_vertex",
|
||||
@ -63,7 +67,7 @@ impl Renderer {
|
||||
pixel_format,
|
||||
)?,
|
||||
sprite_pipeline_state: build_pipeline_state(
|
||||
device,
|
||||
&device,
|
||||
&library,
|
||||
"sprite",
|
||||
"sprite_vertex",
|
||||
@ -268,14 +272,14 @@ impl Renderer {
|
||||
for glyph in layer.glyphs() {
|
||||
let (atlas, bounds) =
|
||||
self.sprite_cache
|
||||
.rasterize_glyph(glyph.font_id, glyph.font_size, glyph.glyph_id);
|
||||
.render_glyph(glyph.font_id, glyph.font_size, glyph.glyph_id);
|
||||
sprites
|
||||
.entry(atlas)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(shaders::GPUISprite {
|
||||
origin: glyph.origin.to_float2(),
|
||||
size: bounds.size().to_float2(),
|
||||
atlas_origin: bounds.origin().to_float2(),
|
||||
size: bounds.size().to_uint2(),
|
||||
atlas_origin: bounds.origin().to_uint2(),
|
||||
color: glyph.color.to_uchar4(),
|
||||
});
|
||||
}
|
||||
@ -358,6 +362,8 @@ mod shaders {
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use pathfinder_geometry::vector::Vector2I;
|
||||
|
||||
use crate::{color::ColorU, geometry::vector::Vector2F};
|
||||
use std::mem;
|
||||
|
||||
@ -371,6 +377,10 @@ mod shaders {
|
||||
fn to_uchar4(&self) -> vector_uchar4;
|
||||
}
|
||||
|
||||
pub trait ToUint2 {
|
||||
fn to_uint2(&self) -> vector_uint2;
|
||||
}
|
||||
|
||||
impl ToFloat2 for (f32, f32) {
|
||||
fn to_float2(&self) -> vector_float2 {
|
||||
unsafe {
|
||||
@ -405,4 +415,13 @@ mod shaders {
|
||||
vec
|
||||
}
|
||||
}
|
||||
|
||||
impl ToUint2 for Vector2I {
|
||||
fn to_uint2(&self) -> vector_uint2 {
|
||||
let mut output = self.y() as vector_uint2;
|
||||
output <<= 32;
|
||||
output |= self.x() as vector_uint2;
|
||||
output
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ typedef enum {
|
||||
|
||||
typedef struct {
|
||||
vector_float2 origin;
|
||||
vector_float2 size;
|
||||
vector_float2 atlas_origin;
|
||||
vector_uint2 size;
|
||||
vector_uint2 atlas_origin;
|
||||
vector_uchar4 color;
|
||||
} GPUISprite;
|
||||
|
@ -1,19 +1,75 @@
|
||||
use crate::geometry::vector::Vector2I;
|
||||
use etagere::BucketedAtlasAllocator;
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
struct SpriteCache {
|
||||
atlasses: Vec<etagere::BucketedAtlasAllocator>,
|
||||
use crate::{
|
||||
fonts::{FontId, GlyphId},
|
||||
geometry::{rect::RectI, vector::Vector2I},
|
||||
FontCache,
|
||||
};
|
||||
use etagere::BucketedAtlasAllocator;
|
||||
use metal::{MTLPixelFormat, TextureDescriptor};
|
||||
use ordered_float::OrderedFloat;
|
||||
|
||||
#[derive(Hash, Eq, PartialEq)]
|
||||
struct GlyphDescriptor {
|
||||
font_id: FontId,
|
||||
font_size: OrderedFloat<f32>,
|
||||
glyph_id: GlyphId,
|
||||
}
|
||||
|
||||
pub struct SpriteCache {
|
||||
font_cache: Arc<FontCache>,
|
||||
device: metal::Device,
|
||||
size: Vector2I,
|
||||
atlasses: Vec<Atlas>,
|
||||
glyphs: HashMap<GlyphDescriptor, (usize, RectI)>,
|
||||
}
|
||||
|
||||
impl SpriteCache {
|
||||
fn new(size: Vector2I) -> Self {
|
||||
let size = etagere::Size::new(size.x(), size.y());
|
||||
pub fn new(device: metal::Device, size: Vector2I) -> Self {
|
||||
Self {
|
||||
atlasses: vec![BucketedAtlasAllocator::new(size)],
|
||||
device,
|
||||
size,
|
||||
atlasses: vec![Atlas::new(&device, size)],
|
||||
glyphs: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn render_glyph(&mut self) {
|
||||
self.atlasses.last().unwrap()
|
||||
pub fn render_glyph(
|
||||
&mut self,
|
||||
font_id: FontId,
|
||||
font_size: f32,
|
||||
glyph_id: GlyphId,
|
||||
) -> (usize, RectI) {
|
||||
self.glyphs
|
||||
.entry(GlyphDescriptor {
|
||||
font_id,
|
||||
font_size: OrderedFloat(font_size),
|
||||
glyph_id,
|
||||
})
|
||||
.or_insert_with(|| {
|
||||
let rendered_glyph = self.font_cache.render_glyph(font_id, font_size, glyph_id);
|
||||
// let atlas = self.atlasses.last_mut().unwrap();
|
||||
todo!()
|
||||
})
|
||||
.clone()
|
||||
}
|
||||
}
|
||||
|
||||
struct Atlas {
|
||||
allocator: BucketedAtlasAllocator,
|
||||
texture: metal::Texture,
|
||||
}
|
||||
|
||||
impl Atlas {
|
||||
fn new(device: &metal::DeviceRef, size: Vector2I) -> Self {
|
||||
let descriptor = TextureDescriptor::new();
|
||||
descriptor.set_pixel_format(MTLPixelFormat::A8Unorm);
|
||||
descriptor.set_width(size.x() as u64);
|
||||
descriptor.set_height(size.y() as u64);
|
||||
|
||||
Self {
|
||||
allocator: BucketedAtlasAllocator::new(etagere::Size::new(size.x(), size.y())),
|
||||
texture: device.new_texture(&descriptor),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ impl Window {
|
||||
synthetic_drag_counter: 0,
|
||||
executor,
|
||||
scene_to_render: Default::default(),
|
||||
renderer: Renderer::new(&device, PIXEL_FORMAT)?,
|
||||
renderer: Renderer::new(device, PIXEL_FORMAT)?,
|
||||
command_queue: device.new_command_queue(),
|
||||
device,
|
||||
layer,
|
||||
|
Loading…
Reference in New Issue
Block a user