Detailed changes
@@ -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();
@@ -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()
}
}
@@ -39,7 +39,8 @@ typedef struct {
typedef enum {
GPUISpriteVertexInputIndexVertices = 0,
GPUISpriteVertexInputIndexSprites = 1,
- GPUISpriteVertexInputIndexUniforms = 2,
+ GPUISpriteVertexInputIndexViewportSize = 2,
+ GPUISpriteVertexInputIndexAtlasSize = 3,
} GPUISpriteVertexInputIndex;
typedef enum {
@@ -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;
}
@@ -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()