macos: enable Metal shader logging

This enables the compile options and Xcode configuration so that logging
in Metal shaders shows up in our Xcode debug console. This doesn't add
any log messages, but makes it so that when we iterate on the shaders in
the future, we can add and see logs to help us out.
This commit is contained in:
Mitchell Hashimoto
2024-11-19 18:41:55 -08:00
parent 14f603e691
commit aad101565a
5 changed files with 86 additions and 47 deletions

View File

@ -196,6 +196,9 @@ jobs:
name: ghostty
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
- name: XCode Select
run: sudo xcode-select -s /Applications/Xcode_16.0.app
- name: Test All
run: |
# OpenGL
@ -352,6 +355,9 @@ jobs:
name: ghostty
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
- name: XCode Select
run: sudo xcode-select -s /Applications/Xcode_16.0.app
- name: test
run: nix develop -c zig build test

View File

@ -1384,10 +1384,21 @@ fn addMetallib(
b: *std.Build,
step: *std.Build.Step.Compile,
) !void {
const optimize = step.root_module.optimize.?;
const metal_step = MetallibStep.create(b, .{
.name = "Ghostty",
.target = step.root_module.resolved_target.?,
.sources = &.{b.path("src/renderer/shaders/cell.metal")},
.logging = switch (optimize) {
.Debug,
=> true,
.ReleaseFast,
.ReleaseSmall,
.ReleaseSafe,
=> false,
},
});
metal_step.output.addStepDependencies(&step.step);

View File

@ -55,6 +55,23 @@
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
<EnvironmentVariables>
<EnvironmentVariable
key = "MTL_LOG_BUFFER_SIZE"
value = "4096"
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable
key = "MTL_LOG_LEVEL"
value = "MTLLogLevelDebug"
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable
key = "MTL_LOG_TO_STDERR"
value = "1"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
<AdditionalOptions>
<AdditionalOption
key = "NSZombieEnabled"

View File

@ -16,6 +16,9 @@ pub const Options = struct {
/// The Metal source files.
sources: []const LazyPath,
/// Whether to enable Metal shader logging.
logging: bool = false,
};
step: *Step,
@ -42,7 +45,20 @@ pub fn create(b: *std.Build, opts: Options) *MetallibStep {
b,
b.fmt("metal {s}", .{opts.name}),
);
run_ir.addArgs(&.{ "xcrun", "-sdk", sdk, "metal", "-o" });
run_ir.addArgs(&.{
"xcrun",
"-sdk",
sdk,
"metal",
"-std=metal3.2",
});
if (opts.logging) run_ir.addArgs(&.{
// https://developer.apple.com/documentation/metal/logging_shader_debug_messages
"-fmetal-enable-logging",
});
run_ir.addArgs(&.{"-o"});
const output_ir = run_ir.addOutputFileArg(b.fmt("{s}.ir", .{opts.name}));
run_ir.addArgs(&.{"-c"});
for (opts.sources) |source| run_ir.addFileArg(source);

View File

@ -2,6 +2,8 @@
using namespace metal;
constant os_log logger("com.mitchellh.ghostty", "cell");
enum Padding : uint8_t {
EXTEND_LEFT = 1u,
EXTEND_RIGHT = 2u,
@ -79,9 +81,7 @@ struct FullScreenVertexOut {
float4 position [[position]];
};
vertex FullScreenVertexOut full_screen_vertex(
uint vid [[vertex_id]]
) {
vertex FullScreenVertexOut full_screen_vertex(uint vid [[vertex_id]]) {
FullScreenVertexOut out;
float4 position;
@ -112,12 +112,11 @@ vertex FullScreenVertexOut full_screen_vertex(
//-------------------------------------------------------------------
#pragma mark - Cell BG Shader
fragment float4 cell_bg_fragment(
FullScreenVertexOut in [[stage_in]],
constant uchar4 *cells [[buffer(0)]],
constant Uniforms& uniforms [[buffer(1)]]
) {
int2 grid_pos = int2(floor((in.position.xy - uniforms.grid_padding.wx) / uniforms.cell_size));
fragment float4 cell_bg_fragment(FullScreenVertexOut in [[stage_in]],
constant uchar4* cells [[buffer(0)]],
constant Uniforms& uniforms [[buffer(1)]]) {
int2 grid_pos = int2(
floor((in.position.xy - uniforms.grid_padding.wx) / uniforms.cell_size));
// Clamp x position, extends edge bg colors in to padding on sides.
if (grid_pos.x < 0) {
@ -197,12 +196,12 @@ struct CellTextVertexOut {
float2 tex_coord;
};
vertex CellTextVertexOut cell_text_vertex(
uint vid [[vertex_id]],
CellTextVertexIn in [[stage_in]],
constant Uniforms& uniforms [[buffer(1)]],
constant uchar4 *bg_colors [[buffer(2)]]
) {
vertex CellTextVertexOut cell_text_vertex(uint vid [[vertex_id]],
CellTextVertexIn in [[stage_in]],
constant Uniforms& uniforms
[[buffer(1)]],
constant uchar4* bg_colors
[[buffer(2)]]) {
// Convert the grid x, y into world space x, y by accounting for cell size
float2 cell_pos = uniforms.cell_size * float2(in.grid_pos);
@ -287,36 +286,31 @@ vertex CellTextVertexOut cell_text_vertex(
// and Powerline glyphs to be unaffected (else parts of the line would
// have different colors as some parts are displayed via background colors).
if (uniforms.min_contrast > 1.0f && in.mode == MODE_TEXT) {
float4 bg_color = float4(bg_colors[in.grid_pos.y * uniforms.grid_size.x + in.grid_pos.x]) / 255.0f;
float4 bg_color =
float4(
bg_colors[in.grid_pos.y * uniforms.grid_size.x + in.grid_pos.x]) /
255.0f;
out.color = contrasted_color(uniforms.min_contrast, out.color, bg_color);
}
// If this cell is the cursor cell, then we need to change the color.
if (
in.mode != MODE_TEXT_CURSOR &&
(
in.grid_pos.x == uniforms.cursor_pos.x ||
uniforms.cursor_wide &&
in.grid_pos.x == uniforms.cursor_pos.x + 1
) &&
in.grid_pos.y == uniforms.cursor_pos.y
) {
if (in.mode != MODE_TEXT_CURSOR &&
(in.grid_pos.x == uniforms.cursor_pos.x ||
uniforms.cursor_wide && in.grid_pos.x == uniforms.cursor_pos.x + 1) &&
in.grid_pos.y == uniforms.cursor_pos.y) {
out.color = float4(uniforms.cursor_color) / 255.0f;
}
return out;
}
fragment float4 cell_text_fragment(
CellTextVertexOut in [[stage_in]],
texture2d<float> textureGrayscale [[texture(0)]],
texture2d<float> textureColor [[texture(1)]]
) {
constexpr sampler textureSampler(
coord::pixel,
address::clamp_to_edge,
filter::nearest
);
fragment float4 cell_text_fragment(CellTextVertexOut in [[stage_in]],
texture2d<float> textureGrayscale
[[texture(0)]],
texture2d<float> textureColor
[[texture(1)]]) {
constexpr sampler textureSampler(coord::pixel, address::clamp_to_edge,
filter::nearest);
switch (in.mode) {
default:
@ -367,12 +361,10 @@ struct ImageVertexOut {
float2 tex_coord;
};
vertex ImageVertexOut image_vertex(
uint vid [[vertex_id]],
ImageVertexIn in [[stage_in]],
texture2d<uint> image [[texture(0)]],
constant Uniforms& uniforms [[buffer(1)]]
) {
vertex ImageVertexOut image_vertex(uint vid [[vertex_id]],
ImageVertexIn in [[stage_in]],
texture2d<uint> image [[texture(0)]],
constant Uniforms& uniforms [[buffer(1)]]) {
// The size of the image in pixels
float2 image_size = float2(image.get_width(), image.get_height());
@ -409,10 +401,8 @@ vertex ImageVertexOut image_vertex(
return out;
}
fragment float4 image_fragment(
ImageVertexOut in [[stage_in]],
texture2d<uint> image [[texture(0)]]
) {
fragment float4 image_fragment(ImageVertexOut in [[stage_in]],
texture2d<uint> image [[texture(0)]]) {
constexpr sampler textureSampler(address::clamp_to_edge, filter::linear);
// Ehhhhh our texture is in RGBA8Uint but our color attachment is
@ -426,4 +416,3 @@ fragment float4 image_fragment(
result.rgb *= result.a;
return result;
}