gpu: update example to latest mach/gpu API

Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
Stephen Gutekanst 2022-07-31 09:15:47 -07:00 committed by Stephen Gutekanst
parent 03c348d2bf
commit 9568bff8ab
4 changed files with 131 additions and 200 deletions

View file

@ -13,20 +13,18 @@ pub fn build(b: *std.build.Builder) void {
const test_step = b.step("test", "Run library tests"); const test_step = b.step("test", "Run library tests");
test_step.dependOn(&testStep(b, mode, target, .{ .gpu_dawn_options = gpu_dawn_options }).step); test_step.dependOn(&testStep(b, mode, target, .{ .gpu_dawn_options = gpu_dawn_options }).step);
// const example = b.addExecutable("gpu-hello-triangle", "examples/main.zig"); const example = b.addExecutable("gpu-hello-triangle", "examples/main.zig");
// example.setBuildMode(mode); example.setBuildMode(mode);
//example.setTarget(target); example.setTarget(target);
// example.linkLibC(); example.addPackage(pkg);
// example.addPackagePath("gpu", "src/main.zig"); example.addPackage(glfw.pkg);
// example.addPackagePath("glfw", "libs/mach-glfw/src/main.zig"); link(b, example, .{ .gpu_dawn_options = gpu_dawn_options });
// link(b, example, .{ .gpu_dawn_options = gpu_dawn_options }); example.install();
// example.install(); const example_run_cmd = example.run();
example_run_cmd.step.dependOn(b.getInstallStep());
// const example_run_cmd = example.run(); const example_run_step = b.step("run-example", "Run the example");
// example_run_cmd.step.dependOn(b.getInstallStep()); example_run_step.dependOn(&example_run_cmd.step);
// const example_run_step = b.step("run-example", "Run the example");
// example_run_step.dependOn(&example_run_cmd.step);
} }
pub fn testStep(b: *std.build.Builder, mode: std.builtin.Mode, target: std.zig.CrossTarget, options: Options) *std.build.RunStep { pub fn testStep(b: *std.build.Builder, mode: std.builtin.Mode, target: std.zig.CrossTarget, options: Options) *std.build.RunStep {

View file

@ -1,4 +1,3 @@
pub const c = @cImport({ pub const c = @cImport({
@cInclude("dawn/webgpu.h"); @cInclude("dawn/webgpu.h");
@cInclude("dawn/dawn_proc.h");
}); });

View file

@ -4,16 +4,19 @@ const c = @import("c.zig").c;
const glfw = @import("glfw"); const glfw = @import("glfw");
const gpu = @import("gpu"); const gpu = @import("gpu");
pub const GPUInterface = gpu.dawn.Interface;
pub fn main() !void { pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; var gpa = std.heap.GeneralPurposeAllocator(.{}){};
var allocator = gpa.allocator(); var allocator = gpa.allocator();
gpu.Impl.init();
const setup = try sample_utils.setup(allocator); const setup = try sample_utils.setup(allocator);
const framebuffer_size = try setup.window.getFramebufferSize(); const framebuffer_size = try setup.window.getFramebufferSize();
const window_data = try allocator.create(WindowData); const window_data = try allocator.create(WindowData);
window_data.* = .{ window_data.* = .{
.surface = null, .surface = setup.surface,
.swap_chain = null, .swap_chain = null,
.swap_chain_format = undefined, .swap_chain_format = undefined,
.current_desc = undefined, .current_desc = undefined,
@ -21,43 +24,16 @@ pub fn main() !void {
}; };
setup.window.setUserPointer(window_data); setup.window.setUserPointer(window_data);
// If targeting OpenGL, we can't use the newer WGPUSurface API. Instead, we need to use the window_data.swap_chain_format = .bgra8_unorm;
// older Dawn-specific API. https://bugs.chromium.org/p/dawn/issues/detail?id=269&q=surface&can=2 const descriptor = gpu.SwapChain.Descriptor{
const use_legacy_api = setup.backend_type == .opengl or setup.backend_type == .opengles; .label = "basic swap chain",
var descriptor: gpu.SwapChain.Descriptor = undefined; .usage = .{ .render_attachment = true },
if (!use_legacy_api) { .format = window_data.swap_chain_format,
window_data.swap_chain_format = .bgra8_unorm; .width = framebuffer_size.width,
descriptor = .{ .height = framebuffer_size.height,
.label = "basic swap chain", .present_mode = .fifo,
.usage = .{ .render_attachment = true }, };
.format = window_data.swap_chain_format,
.width = framebuffer_size.width,
.height = framebuffer_size.height,
.present_mode = .fifo,
.implementation = 0,
};
window_data.surface = sample_utils.createSurfaceForWindow(
&setup.native_instance,
setup.window,
comptime sample_utils.detectGLFWOptions(),
);
} else {
const binding = c.machUtilsCreateBinding(@enumToInt(setup.backend_type), @ptrCast(*c.GLFWwindow, setup.window.handle), @ptrCast(c.WGPUDevice, setup.device.ptr));
if (binding == null) {
@panic("failed to create Dawn backend binding");
}
descriptor = std.mem.zeroes(gpu.SwapChain.Descriptor);
descriptor.implementation = c.machUtilsBackendBinding_getSwapChainImplementation(binding);
window_data.swap_chain = setup.device.nativeCreateSwapChain(null, &descriptor);
window_data.swap_chain_format = @intToEnum(gpu.Texture.Format, @intCast(u32, c.machUtilsBackendBinding_getPreferredSwapChainTextureFormat(binding)));
window_data.swap_chain.?.configure(
window_data.swap_chain_format,
.{ .render_attachment = true },
framebuffer_size.width,
framebuffer_size.height,
);
}
window_data.current_desc = descriptor; window_data.current_desc = descriptor;
window_data.target_desc = descriptor; window_data.target_desc = descriptor;
@ -74,8 +50,11 @@ pub fn main() !void {
\\ } \\ }
; ;
const vs_module = setup.device.createShaderModule(&.{ const vs_module = setup.device.createShaderModule(&.{
.next_in_chain = @ptrCast(*const gpu.ChainedStruct, &gpu.ShaderModule.WGSLDescriptor{
.chain = .{ .next = null, .s_type = .shader_module_wgsl_descriptor },
.source = vs,
}),
.label = "my vertex shader", .label = "my vertex shader",
.code = .{ .wgsl = vs },
}); });
const fs = const fs =
@ -84,33 +63,32 @@ pub fn main() !void {
\\ } \\ }
; ;
const fs_module = setup.device.createShaderModule(&.{ const fs_module = setup.device.createShaderModule(&.{
.next_in_chain = @ptrCast(*const gpu.ChainedStruct, &gpu.ShaderModule.WGSLDescriptor{
.chain = .{ .next = null, .s_type = .shader_module_wgsl_descriptor },
.source = fs,
}),
.label = "my fragment shader", .label = "my fragment shader",
.code = .{ .wgsl = fs },
}); });
// Fragment state // Fragment state
const blend = gpu.BlendState{ const blend = gpu.BlendState{
.color = .{ .color = .{
.operation = .add,
.src_factor = .one,
.dst_factor = .one, .dst_factor = .one,
}, },
.alpha = .{ .alpha = .{
.operation = .add,
.src_factor = .one,
.dst_factor = .one, .dst_factor = .one,
}, },
}; };
const color_target = gpu.ColorTargetState{ const color_target = gpu.ColorTargetState{
.format = window_data.swap_chain_format, .format = window_data.swap_chain_format,
.blend = &blend, .blend = &blend,
.write_mask = gpu.ColorWriteMask.all, .write_mask = gpu.ColorWriteMaskFlags.all,
}; };
const fragment = gpu.FragmentState{ const fragment = gpu.FragmentState{
.module = fs_module, .module = fs_module,
.entry_point = "main", .entry_point = "main",
.targets = &.{color_target}, .target_count = 1,
.constants = null, .targets = &[_]gpu.ColorTargetState{color_target},
}; };
const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ const pipeline_descriptor = gpu.RenderPipeline.Descriptor{
.fragment = &fragment, .fragment = &fragment,
@ -119,19 +97,9 @@ pub fn main() !void {
.vertex = .{ .vertex = .{
.module = vs_module, .module = vs_module,
.entry_point = "main", .entry_point = "main",
.buffers = null,
},
.multisample = .{
.count = 1,
.mask = 0xFFFFFFFF,
.alpha_to_coverage_enabled = false,
},
.primitive = .{
.front_face = .ccw,
.cull_mode = .none,
.topology = .triangle_list,
.strip_index_format = .none,
}, },
.multisample = .{},
.primitive = .{},
}; };
const pipeline = setup.device.createRenderPipeline(&pipeline_descriptor); const pipeline = setup.device.createRenderPipeline(&pipeline_descriptor);
@ -161,8 +129,8 @@ pub fn main() !void {
} }
const WindowData = struct { const WindowData = struct {
surface: ?gpu.Surface, surface: ?*gpu.Surface,
swap_chain: ?gpu.SwapChain, swap_chain: ?*gpu.SwapChain,
swap_chain_format: gpu.Texture.Format, swap_chain_format: gpu.Texture.Format,
current_desc: gpu.SwapChain.Descriptor, current_desc: gpu.SwapChain.Descriptor,
target_desc: gpu.SwapChain.Descriptor, target_desc: gpu.SwapChain.Descriptor,
@ -170,24 +138,16 @@ const WindowData = struct {
const FrameParams = struct { const FrameParams = struct {
window: glfw.Window, window: glfw.Window,
device: gpu.Device, device: *gpu.Device,
pipeline: gpu.RenderPipeline, pipeline: *gpu.RenderPipeline,
queue: gpu.Queue, queue: *gpu.Queue,
}; };
fn frame(params: FrameParams) !void { fn frame(params: FrameParams) !void {
try glfw.pollEvents(); try glfw.pollEvents();
const pl = params.window.getUserPointer(WindowData).?; const pl = params.window.getUserPointer(WindowData).?;
if (pl.swap_chain == null or !pl.current_desc.equal(&pl.target_desc)) { if (pl.swap_chain == null or !std.meta.eql(pl.current_desc, pl.target_desc)) {
const use_legacy_api = pl.surface == null; pl.swap_chain = params.device.createSwapChain(pl.surface, &pl.target_desc);
if (!use_legacy_api) {
pl.swap_chain = params.device.nativeCreateSwapChain(pl.surface, &pl.target_desc);
} else pl.swap_chain.?.configure(
pl.swap_chain_format,
.{ .render_attachment = true },
pl.target_desc.width,
pl.target_desc.height,
);
pl.current_desc = pl.target_desc; pl.current_desc = pl.target_desc;
} }
@ -201,9 +161,11 @@ fn frame(params: FrameParams) !void {
}; };
const encoder = params.device.createCommandEncoder(null); const encoder = params.device.createCommandEncoder(null);
const render_pass_info = gpu.RenderPassEncoder.Descriptor{ const render_pass_info = gpu.RenderPassDescriptor{
.color_attachments = &.{color_attachment}, .color_attachment_count = 1,
.color_attachments = &[_]gpu.RenderPassColorAttachment{color_attachment},
.depth_stencil_attachment = null, .depth_stencil_attachment = null,
.occlusion_query_set = null,
}; };
const pass = encoder.beginRenderPass(&render_pass_info); const pass = encoder.beginRenderPass(&render_pass_info);
pass.setPipeline(params.pipeline); pass.setPipeline(params.pipeline);
@ -214,7 +176,7 @@ fn frame(params: FrameParams) !void {
var command = encoder.finish(null); var command = encoder.finish(null);
encoder.release(); encoder.release();
params.queue.submit(&.{command}); params.queue.submit(1, &[_]*gpu.CommandBuffer{command});
command.release(); command.release();
pl.swap_chain.?.present(); pl.swap_chain.?.present();
back_buffer_view.release(); back_buffer_view.release();

View file

@ -7,7 +7,7 @@ const objc = @cImport({
@cInclude("objc/message.h"); @cInclude("objc/message.h");
}); });
fn printUnhandledError(_: void, typ: gpu.ErrorType, message: [*:0]const u8) void { fn printUnhandledErrorCallback(typ: gpu.ErrorType, message: [*:0]const u8, _: ?*anyopaque) callconv(.C) void {
switch (typ) { switch (typ) {
.validation => std.debug.print("gpu: validation error: {s}\n", .{message}), .validation => std.debug.print("gpu: validation error: {s}\n", .{message}),
.out_of_memory => std.debug.print("gpu: out of memory: {s}\n", .{message}), .out_of_memory => std.debug.print("gpu: out of memory: {s}\n", .{message}),
@ -15,14 +15,15 @@ fn printUnhandledError(_: void, typ: gpu.ErrorType, message: [*:0]const u8) void
.unknown => std.debug.print("gpu: unknown error: {s}\n", .{message}), .unknown => std.debug.print("gpu: unknown error: {s}\n", .{message}),
else => unreachable, else => unreachable,
} }
std.process.exit(1);
} }
var printUnhandledErrorCallback = gpu.ErrorCallback.init(void, {}, printUnhandledError);
const Setup = struct { const Setup = struct {
native_instance: gpu.NativeInstance, instance: *gpu.Instance,
backend_type: gpu.Adapter.BackendType, adapter: *gpu.Adapter,
device: gpu.Device, device: *gpu.Device,
window: glfw.Window, window: glfw.Window,
surface: *gpu.Surface,
}; };
fn getEnvVarOwned(allocator: std.mem.Allocator, key: []const u8) error{ OutOfMemory, InvalidUtf8 }!?[]u8 { fn getEnvVarOwned(allocator: std.mem.Allocator, key: []const u8) error{ OutOfMemory, InvalidUtf8 }!?[]u8 {
@ -32,17 +33,18 @@ fn getEnvVarOwned(allocator: std.mem.Allocator, key: []const u8) error{ OutOfMem
}; };
} }
fn detectBackendType(allocator: std.mem.Allocator) !gpu.Adapter.BackendType { fn detectBackendType(allocator: std.mem.Allocator) !gpu.BackendType {
const GPU_BACKEND = try getEnvVarOwned(allocator, "GPU_BACKEND"); const GPU_BACKEND = try getEnvVarOwned(allocator, "GPU_BACKEND");
if (GPU_BACKEND) |backend| { if (GPU_BACKEND) |backend| {
defer allocator.free(backend); defer allocator.free(backend);
if (std.ascii.eqlIgnoreCase(backend, "opengl")) return .opengl; if (std.ascii.eqlIgnoreCase(backend, "null")) return .nul;
if (std.ascii.eqlIgnoreCase(backend, "opengles")) return .opengles; if (std.ascii.eqlIgnoreCase(backend, "webgpu")) return .nul;
if (std.ascii.eqlIgnoreCase(backend, "d3d11")) return .d3d11; if (std.ascii.eqlIgnoreCase(backend, "d3d11")) return .d3d11;
if (std.ascii.eqlIgnoreCase(backend, "d3d12")) return .d3d12; if (std.ascii.eqlIgnoreCase(backend, "d3d12")) return .d3d12;
if (std.ascii.eqlIgnoreCase(backend, "metal")) return .metal; if (std.ascii.eqlIgnoreCase(backend, "metal")) return .metal;
if (std.ascii.eqlIgnoreCase(backend, "null")) return .nul;
if (std.ascii.eqlIgnoreCase(backend, "vulkan")) return .vulkan; if (std.ascii.eqlIgnoreCase(backend, "vulkan")) return .vulkan;
if (std.ascii.eqlIgnoreCase(backend, "opengl")) return .opengl;
if (std.ascii.eqlIgnoreCase(backend, "opengles")) return .opengles;
@panic("unknown BACKEND type"); @panic("unknown BACKEND type");
} }
@ -52,6 +54,26 @@ fn detectBackendType(allocator: std.mem.Allocator) !gpu.Adapter.BackendType {
return .vulkan; return .vulkan;
} }
const RequestAdapterResponse = struct {
status: gpu.RequestAdapterStatus,
adapter: *gpu.Adapter,
message: ?[*:0]const u8,
};
fn requestAdapterCallback(
status: gpu.RequestAdapterStatus,
adapter: *gpu.Adapter,
message: ?[*:0]const u8,
userdata: ?*anyopaque,
) callconv(.C) void {
const response = @ptrCast(*?RequestAdapterResponse, @alignCast(@alignOf(*?RequestAdapterResponse), userdata));
response.* = RequestAdapterResponse{
.status = status,
.adapter = adapter,
.message = message,
};
}
pub fn setup(allocator: std.mem.Allocator) !Setup { pub fn setup(allocator: std.mem.Allocator) !Setup {
const backend_type = try detectBackendType(allocator); const backend_type = try detectBackendType(allocator);
@ -61,79 +83,55 @@ pub fn setup(allocator: std.mem.Allocator) !Setup {
var hints = glfwWindowHintsForBackend(backend_type); var hints = glfwWindowHintsForBackend(backend_type);
hints.cocoa_retina_framebuffer = true; hints.cocoa_retina_framebuffer = true;
const window = try glfw.Window.create(640, 480, "mach/gpu window", null, null, hints); const window = try glfw.Window.create(640, 480, "mach/gpu window", null, null, hints);
if (backend_type == .opengl) try glfw.makeContextCurrent(window);
if (backend_type == .opengles) try glfw.makeContextCurrent(window);
const backend_procs = c.machDawnNativeGetProcs(); const instance = gpu.createInstance(null);
c.dawnProcSetProcs(backend_procs); if (instance == null) {
std.debug.print("failed to create GPU instance\n", .{});
const instance = c.machDawnNativeInstance_init();
var native_instance = gpu.NativeInstance.wrap(c.machDawnNativeInstance_get(instance).?);
// Discovers e.g. OpenGL adapters.
try discoverAdapters(instance, window, backend_type);
// Request an adapter.
//
// TODO: It would be nice if we could use gpu_interface.waitForAdapter here, however the webgpu.h
// API does not yet have a way to specify what type of backend you want (vulkan, opengl, etc.)
// In theory, I suppose we shouldn't need to and Dawn should just pick the best adapter - but in
// practice if Vulkan is not supported today waitForAdapter/requestAdapter merely generates an error.
//
// const gpu_interface = native_instance.interface();
// const backend_adapter = switch (gpu_interface.waitForAdapter(&.{
// .power_preference = .high_performance,
// })) {
// .adapter => |v| v,
// .err => |err| {
// std.debug.print("failed to get adapter: error={} {s}\n", .{ err.code, err.message });
// std.process.exit(1);
// },
// };
const adapters = c.machDawnNativeInstance_getAdapters(instance);
var dawn_adapter: ?c.MachDawnNativeAdapter = null;
var i: usize = 0;
while (i < c.machDawnNativeAdapters_length(adapters)) : (i += 1) {
const adapter = c.machDawnNativeAdapters_index(adapters, i);
const properties = c.machDawnNativeAdapter_getProperties(adapter);
const found_backend_type = @intToEnum(gpu.Adapter.BackendType, c.machDawnNativeAdapterProperties_getBackendType(properties));
if (found_backend_type == backend_type) {
dawn_adapter = adapter;
}
}
if (dawn_adapter == null) {
std.debug.print("no matching adapter found for {s}", .{@tagName(backend_type)});
std.debug.print("-> maybe try GPU_BACKEND=opengl ?\n", .{});
std.process.exit(1); std.process.exit(1);
} }
assert(dawn_adapter != null); const surface = createSurfaceForWindow(instance.?, window, comptime detectGLFWOptions());
const backend_adapter = gpu.NativeInstance.fromWGPUAdapter(c.machDawnNativeAdapter_get(dawn_adapter.?).?);
// Print which adapter we are going to use. var response: ?RequestAdapterResponse = null;
const props = backend_adapter.properties; instance.?.requestAdapter(&gpu.RequestAdapterOptions{
.compatible_surface = surface,
.power_preference = .undef,
.force_fallback_adapter = false,
}, requestAdapterCallback, &response);
if (response.?.status != .success) {
std.debug.print("failed to create GPU adapter: {s}\n", .{response.?.message});
std.process.exit(1);
}
// Print which adapter we are using.
var props: gpu.Adapter.Properties = undefined;
response.?.adapter.getProperties(&props);
std.debug.print("found {s} backend on {s} adapter: {s}, {s}\n", .{ std.debug.print("found {s} backend on {s} adapter: {s}, {s}\n", .{
gpu.Adapter.backendTypeName(props.backend_type), props.backend_type.name(),
gpu.Adapter.typeName(props.adapter_type), props.adapter_type.name(),
props.name, props.name,
props.driver_description, props.driver_description,
}); });
const device = switch (backend_adapter.waitForDevice(&.{})) { // Create a device with default limits/features.
.device => |v| v, const device = response.?.adapter.createDevice(null);
.err => |err| { if (device == null) {
std.debug.print("failed to get device: error={} {s}\n", .{ err.code, err.message }); std.debug.print("failed to create GPU device\n", .{});
std.process.exit(1); std.process.exit(1);
}, }
};
device.setUncapturedErrorCallback(&printUnhandledErrorCallback); device.?.setUncapturedErrorCallback(printUnhandledErrorCallback, null);
return Setup{ return Setup{
.native_instance = native_instance, .instance = instance.?,
.backend_type = backend_type, .adapter = response.?.adapter,
.device = device, .device = device.?,
.window = window, .window = window,
.surface = surface,
}; };
} }
fn glfwWindowHintsForBackend(backend: gpu.Adapter.BackendType) glfw.Window.Hints { fn glfwWindowHintsForBackend(backend: gpu.BackendType) glfw.Window.Hints {
return switch (backend) { return switch (backend) {
.opengl => .{ .opengl => .{
// Ask for OpenGL 4.4 which is what the GL backend requires for compute shaders and // Ask for OpenGL 4.4 which is what the GL backend requires for compute shaders and
@ -157,28 +155,6 @@ fn glfwWindowHintsForBackend(backend: gpu.Adapter.BackendType) glfw.Window.Hints
}; };
} }
fn discoverAdapters(instance: c.MachDawnNativeInstance, window: glfw.Window, typ: gpu.Adapter.BackendType) !void {
switch (typ) {
.opengl => {
try glfw.makeContextCurrent(window);
const adapter_options = c.MachDawnNativeAdapterDiscoveryOptions_OpenGL{
.getProc = @ptrCast(fn ([*c]const u8) callconv(.C) ?*anyopaque, glfw.getProcAddress),
};
_ = c.machDawnNativeInstance_discoverAdapters(instance, @enumToInt(typ), &adapter_options);
},
.opengles => {
try glfw.makeContextCurrent(window);
const adapter_options = c.MachDawnNativeAdapterDiscoveryOptions_OpenGLES{
.getProc = @ptrCast(fn ([*c]const u8) callconv(.C) ?*anyopaque, glfw.getProcAddress),
};
_ = c.machDawnNativeInstance_discoverAdapters(instance, @enumToInt(typ), &adapter_options);
},
else => {
c.machDawnNativeInstance_discoverDefaultAdapters(instance);
},
}
}
pub fn detectGLFWOptions() glfw.BackendOptions { pub fn detectGLFWOptions() glfw.BackendOptions {
const target = @import("builtin").target; const target = @import("builtin").target;
if (target.isDarwin()) return .{ .cocoa = true }; if (target.isDarwin()) return .{ .cocoa = true };
@ -190,23 +166,19 @@ pub fn detectGLFWOptions() glfw.BackendOptions {
} }
pub fn createSurfaceForWindow( pub fn createSurfaceForWindow(
native_instance: *const gpu.NativeInstance, instance: *gpu.Instance,
window: glfw.Window, window: glfw.Window,
comptime glfw_options: glfw.BackendOptions, comptime glfw_options: glfw.BackendOptions,
) gpu.Surface { ) *gpu.Surface {
const glfw_native = glfw.Native(glfw_options); const glfw_native = glfw.Native(glfw_options);
const descriptor = if (glfw_options.win32) gpu.Surface.Descriptor{ const descriptor = if (glfw_options.win32) gpu.Surface.DescriptorFromWindowsHWND{
.windows_hwnd = .{ .chain = .{ .s_type = .surface_descriptor_from_windows_hwnd },
.label = "basic surface", .hinstance = std.os.windows.kernel32.GetModuleHandleW(null).?,
.hinstance = std.os.windows.kernel32.GetModuleHandleW(null).?, .hwnd = glfw_native.getWin32Window(window),
.hwnd = glfw_native.getWin32Window(window), } else if (glfw_options.x11) gpu.Surface.DescriptorFromXlibWindow{
}, .chain = .{ .s_type = .surface_descriptor_from_xlib_window },
} else if (glfw_options.x11) gpu.Surface.Descriptor{ .display = glfw_native.getX11Display(),
.xlib = .{ .window = glfw_native.getX11Window(window),
.label = "basic surface",
.display = glfw_native.getX11Display(),
.window = glfw_native.getX11Window(window),
},
} else if (glfw_options.cocoa) blk: { } else if (glfw_options.cocoa) blk: {
const ns_window = glfw_native.getCocoaWindow(window); const ns_window = glfw_native.getCocoaWindow(window);
const ns_view = msgSend(ns_window, "contentView", .{}, *anyopaque); // [nsWindow contentView] const ns_view = msgSend(ns_window, "contentView", .{}, *anyopaque); // [nsWindow contentView]
@ -221,17 +193,17 @@ pub fn createSurfaceForWindow(
const scale_factor = msgSend(ns_window, "backingScaleFactor", .{}, f64); // [ns_window backingScaleFactor] const scale_factor = msgSend(ns_window, "backingScaleFactor", .{}, f64); // [ns_window backingScaleFactor]
msgSend(layer.?, "setContentsScale:", .{scale_factor}, void); // [layer setContentsScale:scale_factor] msgSend(layer.?, "setContentsScale:", .{scale_factor}, void); // [layer setContentsScale:scale_factor]
break :blk gpu.Surface.Descriptor{ break :blk gpu.Surface.DescriptorFromMetalLayer{
.metal_layer = .{ .chain = .{ .s_type = .surface_descriptor_from_metal_layer },
.label = "basic surface", .layer = layer.?,
.layer = layer.?,
},
}; };
} else if (glfw_options.wayland) { } else if (glfw_options.wayland) {
@panic("Dawn does not yet have Wayland support, see https://bugs.chromium.org/p/dawn/issues/detail?id=1246&q=surface&can=2"); @panic("TODO: this example does not support Wayland");
} else unreachable; } else unreachable;
return native_instance.createSurface(&descriptor); return instance.createSurface(&gpu.Surface.Descriptor{
.next_in_chain = @ptrCast(*const gpu.ChainedStruct, &descriptor),
});
} }
// Borrowed from https://github.com/hazeycode/zig-objcrt // Borrowed from https://github.com/hazeycode/zig-objcrt