mach: update to latest mach/gpu API
Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
8bce5bc0a8
commit
85ddeeed5c
6 changed files with 100 additions and 175 deletions
|
|
@ -23,12 +23,12 @@ delta_time: f32 = 0,
|
||||||
delta_time_ns: u64 = 0,
|
delta_time_ns: u64 = 0,
|
||||||
timer: Timer,
|
timer: Timer,
|
||||||
|
|
||||||
device: gpu.Device,
|
device: *gpu.Device,
|
||||||
backend_type: gpu.Adapter.BackendType,
|
backend_type: gpu.BackendType,
|
||||||
swap_chain: ?gpu.SwapChain,
|
swap_chain: ?*gpu.SwapChain,
|
||||||
swap_chain_format: gpu.Texture.Format,
|
swap_chain_format: gpu.Texture.Format,
|
||||||
|
|
||||||
surface: ?gpu.Surface,
|
surface: ?*gpu.Surface,
|
||||||
current_desc: gpu.SwapChain.Descriptor,
|
current_desc: gpu.SwapChain.Descriptor,
|
||||||
target_desc: gpu.SwapChain.Descriptor,
|
target_desc: gpu.SwapChain.Descriptor,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ pub const ecs = @import("ecs");
|
||||||
pub const module = ecs.Module(.{
|
pub const module = ecs.Module(.{
|
||||||
.globals = struct {
|
.globals = struct {
|
||||||
core: *Core,
|
core: *Core,
|
||||||
device: gpu.Device,
|
device: *gpu.Device,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
pub const c = @cImport({
|
|
||||||
@cInclude("dawn/webgpu.h");
|
|
||||||
@cInclude("dawn/dawn_proc.h");
|
|
||||||
@cInclude("dawn_native_mach.h");
|
|
||||||
});
|
|
||||||
|
|
@ -7,7 +7,6 @@ const Core = @import("../Core.zig");
|
||||||
const structs = @import("../structs.zig");
|
const structs = @import("../structs.zig");
|
||||||
const enums = @import("../enums.zig");
|
const enums = @import("../enums.zig");
|
||||||
const util = @import("util.zig");
|
const util = @import("util.zig");
|
||||||
const c = @import("c.zig").c;
|
|
||||||
|
|
||||||
const common = @import("common.zig");
|
const common = @import("common.zig");
|
||||||
comptime {
|
comptime {
|
||||||
|
|
@ -20,7 +19,7 @@ pub const log_level = if (@hasDecl(App, "log_level")) App.log_level else std.log
|
||||||
|
|
||||||
pub const Platform = struct {
|
pub const Platform = struct {
|
||||||
window: glfw.Window,
|
window: glfw.Window,
|
||||||
backend_type: gpu.Adapter.BackendType,
|
backend_type: gpu.BackendType,
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
events: EventQueue = .{},
|
events: EventQueue = .{},
|
||||||
user_ptr: UserPtr = undefined,
|
user_ptr: UserPtr = undefined,
|
||||||
|
|
@ -34,7 +33,9 @@ pub const Platform = struct {
|
||||||
cursors_tried: [@typeInfo(enums.MouseCursor).Enum.fields.len]bool =
|
cursors_tried: [@typeInfo(enums.MouseCursor).Enum.fields.len]bool =
|
||||||
[_]bool{false} ** @typeInfo(enums.MouseCursor).Enum.fields.len,
|
[_]bool{false} ** @typeInfo(enums.MouseCursor).Enum.fields.len,
|
||||||
|
|
||||||
native_instance: gpu.NativeInstance,
|
// TODO: these can be moved to Core
|
||||||
|
instance: *gpu.Instance,
|
||||||
|
adapter: *gpu.Adapter,
|
||||||
|
|
||||||
last_cursor_position: structs.WindowPos,
|
last_cursor_position: structs.WindowPos,
|
||||||
|
|
||||||
|
|
@ -73,131 +74,73 @@ pub const Platform = struct {
|
||||||
null,
|
null,
|
||||||
hints,
|
hints,
|
||||||
);
|
);
|
||||||
|
if (backend_type == .opengl) try glfw.makeContextCurrent(window);
|
||||||
|
if (backend_type == .opengles) try glfw.makeContextCurrent(window);
|
||||||
|
|
||||||
const window_size = try window.getSize();
|
const window_size = try window.getSize();
|
||||||
const framebuffer_size = try window.getFramebufferSize();
|
const framebuffer_size = try window.getFramebufferSize();
|
||||||
|
|
||||||
const backend_procs = c.machDawnNativeGetProcs();
|
const instance = gpu.createInstance(null);
|
||||||
c.dawnProcSetProcs(backend_procs);
|
if (instance == null) {
|
||||||
|
std.debug.print("mach: failed to create GPU instance\n", .{});
|
||||||
const instance = c.machDawnNativeInstance_init();
|
std.process.exit(1);
|
||||||
var native_instance = gpu.NativeInstance.wrap(c.machDawnNativeInstance_get(instance).?);
|
|
||||||
|
|
||||||
// Discover e.g. OpenGL adapters.
|
|
||||||
try util.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("mach: 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;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (dawn_adapter == null) {
|
const surface = util.createSurfaceForWindow(instance.?, window, comptime util.detectGLFWOptions());
|
||||||
std.debug.print("mach: no matching adapter found for {s}", .{@tagName(backend_type)});
|
|
||||||
|
var response: ?util.RequestAdapterResponse = null;
|
||||||
|
instance.?.requestAdapter(&gpu.RequestAdapterOptions{
|
||||||
|
.compatible_surface = surface,
|
||||||
|
.power_preference = options.power_preference,
|
||||||
|
.force_fallback_adapter = false,
|
||||||
|
}, &response, util.requestAdapterCallback);
|
||||||
|
if (response.?.status != .success) {
|
||||||
|
std.debug.print("mach: failed to create GPU adapter: {s}\n", .{response.?.message});
|
||||||
std.debug.print("-> maybe try GPU_BACKEND=opengl ?\n", .{});
|
std.debug.print("-> maybe try GPU_BACKEND=opengl ?\n", .{});
|
||||||
std.process.exit(1);
|
std.process.exit(1);
|
||||||
}
|
}
|
||||||
std.debug.assert(dawn_adapter != null);
|
|
||||||
const backend_adapter = gpu.NativeInstance.fromWGPUAdapter(c.machDawnNativeAdapter_get(dawn_adapter.?).?);
|
|
||||||
|
|
||||||
// Print which adapter we are going to use.
|
// Print which adapter we are going to use.
|
||||||
const props = backend_adapter.properties;
|
var props: gpu.Adapter.Properties = undefined;
|
||||||
|
response.?.adapter.getProperties(&props);
|
||||||
std.debug.print("mach: found {s} backend on {s} adapter: {s}, {s}\n", .{
|
std.debug.print("mach: 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.
|
||||||
.required_features = options.required_features,
|
const device = response.?.adapter.createDevice(&.{
|
||||||
.required_limits = options.required_limits,
|
.required_features_count = if (options.required_features) |v| @intCast(u32, v.len) else 0,
|
||||||
})) {
|
.required_features = if (options.required_features) |v| @as(?[*]gpu.FeatureName, v.ptr) else null,
|
||||||
.device => |v| v,
|
.required_limits = if (options.required_limits) |limits| @as(?*gpu.RequiredLimits, &gpu.RequiredLimits{
|
||||||
.err => |err| {
|
.limits = limits,
|
||||||
// TODO: return a proper error type
|
}) else null,
|
||||||
std.debug.print("mach: failed to get device: error={} {s}\n", .{ err.code, err.message });
|
});
|
||||||
std.process.exit(1);
|
if (device == null) {
|
||||||
},
|
std.debug.print("mach: failed to create GPU device\n", .{});
|
||||||
};
|
std.process.exit(1);
|
||||||
|
|
||||||
// If targeting OpenGL, we can't use the newer WGPUSurface API. Instead, we need to use the
|
|
||||||
// older Dawn-specific API. https://bugs.chromium.org/p/dawn/issues/detail?id=269&q=surface&can=2
|
|
||||||
const use_legacy_api = backend_type == .opengl or backend_type == .opengles;
|
|
||||||
var descriptor: gpu.SwapChain.Descriptor = undefined;
|
|
||||||
var swap_chain: ?gpu.SwapChain = null;
|
|
||||||
var swap_chain_format: gpu.Texture.Format = undefined;
|
|
||||||
var surface: ?gpu.Surface = null;
|
|
||||||
if (!use_legacy_api) {
|
|
||||||
swap_chain_format = .bgra8_unorm;
|
|
||||||
descriptor = .{
|
|
||||||
.label = "basic swap chain",
|
|
||||||
.usage = .{ .render_attachment = true },
|
|
||||||
.format = swap_chain_format,
|
|
||||||
.width = framebuffer_size.width,
|
|
||||||
.height = framebuffer_size.height,
|
|
||||||
.present_mode = switch (options.vsync) {
|
|
||||||
.none => .immediate,
|
|
||||||
.double => .fifo,
|
|
||||||
.triple => .mailbox,
|
|
||||||
},
|
|
||||||
.implementation = 0,
|
|
||||||
};
|
|
||||||
surface = util.createSurfaceForWindow(
|
|
||||||
&native_instance,
|
|
||||||
window,
|
|
||||||
comptime util.detectGLFWOptions(),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const binding = c.machUtilsCreateBinding(@enumToInt(backend_type), @ptrCast(*c.GLFWwindow, window.handle), @ptrCast(c.WGPUDevice, 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);
|
|
||||||
swap_chain = device.nativeCreateSwapChain(null, &descriptor);
|
|
||||||
|
|
||||||
swap_chain_format = @intToEnum(gpu.Texture.Format, @intCast(u32, c.machUtilsBackendBinding_getPreferredSwapChainTextureFormat(binding)));
|
|
||||||
swap_chain.?.configure(
|
|
||||||
swap_chain_format,
|
|
||||||
.{ .render_attachment = true },
|
|
||||||
framebuffer_size.width,
|
|
||||||
framebuffer_size.height,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
device.setUncapturedErrorCallback(&util.printUnhandledErrorCallback);
|
core.swap_chain_format = .bgra8_unorm;
|
||||||
|
const descriptor = gpu.SwapChain.Descriptor{
|
||||||
|
.label = "main swap chain",
|
||||||
|
.usage = .{ .render_attachment = true },
|
||||||
|
.format = core.swap_chain_format,
|
||||||
|
.width = framebuffer_size.width,
|
||||||
|
.height = framebuffer_size.height,
|
||||||
|
.present_mode = .fifo,
|
||||||
|
};
|
||||||
|
|
||||||
core.device = device;
|
device.?.setUncapturedErrorCallback({}, util.printUnhandledErrorCallback);
|
||||||
|
|
||||||
|
core.device = device.?;
|
||||||
core.backend_type = backend_type;
|
core.backend_type = backend_type;
|
||||||
core.surface = surface;
|
core.surface = surface;
|
||||||
core.swap_chain = swap_chain;
|
|
||||||
core.swap_chain_format = swap_chain_format;
|
|
||||||
core.current_desc = descriptor;
|
core.current_desc = descriptor;
|
||||||
core.target_desc = descriptor;
|
core.target_desc = descriptor;
|
||||||
|
core.swap_chain = core.device.createSwapChain(core.surface, &core.target_desc);
|
||||||
|
// TODO: should resize fire on startup here? Might be nice for consistency
|
||||||
|
|
||||||
const cursor_pos = try window.getCursorPos();
|
const cursor_pos = try window.getCursorPos();
|
||||||
|
|
||||||
|
|
@ -212,7 +155,8 @@ pub const Platform = struct {
|
||||||
.x = cursor_pos.xpos,
|
.x = cursor_pos.xpos,
|
||||||
.y = cursor_pos.ypos,
|
.y = cursor_pos.ypos,
|
||||||
},
|
},
|
||||||
.native_instance = native_instance,
|
.instance = instance.?,
|
||||||
|
.adapter = response.?.adapter,
|
||||||
.linux_gamemode_is_active = linux_gamemode_is_active,
|
.linux_gamemode_is_active = linux_gamemode_is_active,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -635,11 +579,15 @@ pub const BackingTimer = std.time.Timer;
|
||||||
|
|
||||||
var app: App = undefined;
|
var app: App = undefined;
|
||||||
|
|
||||||
|
pub const GPUInterface = gpu.dawn.Interface;
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
defer _ = gpa.deinit();
|
defer _ = gpa.deinit();
|
||||||
const allocator = gpa.allocator();
|
const allocator = gpa.allocator();
|
||||||
|
|
||||||
|
gpu.Impl.init();
|
||||||
|
|
||||||
var core = try coreInit(allocator);
|
var core = try coreInit(allocator);
|
||||||
defer coreDeinit(core, allocator);
|
defer coreDeinit(core, allocator);
|
||||||
|
|
||||||
|
|
@ -691,16 +639,8 @@ pub fn coreUpdate(core: *Core, resize: ?CoreResizeCallback) !void {
|
||||||
core.target_desc.width = framebuffer_size.width;
|
core.target_desc.width = framebuffer_size.width;
|
||||||
core.target_desc.height = framebuffer_size.height;
|
core.target_desc.height = framebuffer_size.height;
|
||||||
|
|
||||||
if (core.swap_chain == null or !core.current_desc.equal(&core.target_desc)) {
|
if (core.swap_chain == null or !std.meta.eql(core.current_desc, core.target_desc)) {
|
||||||
const use_legacy_api = core.surface == null;
|
core.swap_chain = core.device.createSwapChain(core.surface, &core.target_desc);
|
||||||
if (!use_legacy_api) {
|
|
||||||
core.swap_chain = core.device.nativeCreateSwapChain(core.surface, &core.target_desc);
|
|
||||||
} else core.swap_chain.?.configure(
|
|
||||||
core.swap_chain_format,
|
|
||||||
.{ .render_attachment = true },
|
|
||||||
core.target_desc.width,
|
|
||||||
core.target_desc.height,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (@hasDecl(App, "resize")) {
|
if (@hasDecl(App, "resize")) {
|
||||||
try app.resize(core, core.target_desc.width, core.target_desc.height);
|
try app.resize(core, core.target_desc.width, core.target_desc.height);
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,11 @@ const std = @import("std");
|
||||||
|
|
||||||
const glfw = @import("glfw");
|
const glfw = @import("glfw");
|
||||||
const gpu = @import("gpu");
|
const gpu = @import("gpu");
|
||||||
const c = @import("c.zig").c;
|
|
||||||
const objc = @cImport({
|
const objc = @cImport({
|
||||||
@cInclude("objc/message.h");
|
@cInclude("objc/message.h");
|
||||||
});
|
});
|
||||||
|
|
||||||
fn printUnhandledError(_: void, typ: gpu.ErrorType, message: [*:0]const u8) void {
|
pub inline fn printUnhandledErrorCallback(typ: gpu.ErrorType, message: [*:0]const u8, _: void) 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}),
|
||||||
|
|
@ -17,7 +16,6 @@ fn printUnhandledError(_: void, typ: gpu.ErrorType, message: [*:0]const u8) void
|
||||||
}
|
}
|
||||||
std.os.exit(1);
|
std.os.exit(1);
|
||||||
}
|
}
|
||||||
pub var printUnhandledErrorCallback = gpu.ErrorCallback.init(void, {}, printUnhandledError);
|
|
||||||
|
|
||||||
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 {
|
||||||
return std.process.getEnvVarOwned(allocator, key) catch |err| switch (err) {
|
return std.process.getEnvVarOwned(allocator, key) catch |err| switch (err) {
|
||||||
|
|
@ -26,17 +24,17 @@ fn getEnvVarOwned(allocator: std.mem.Allocator, key: []const u8) error{ OutOfMem
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detectBackendType(allocator: std.mem.Allocator) !gpu.Adapter.BackendType {
|
pub 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, "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 GPU_BACKEND type");
|
@panic("unknown GPU_BACKEND type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,7 +44,26 @@ pub fn detectBackendType(allocator: std.mem.Allocator) !gpu.Adapter.BackendType
|
||||||
return .vulkan;
|
return .vulkan;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn glfwWindowHintsForBackend(backend: gpu.Adapter.BackendType) glfw.Window.Hints {
|
pub const RequestAdapterResponse = struct {
|
||||||
|
status: gpu.RequestAdapterStatus,
|
||||||
|
adapter: *gpu.Adapter,
|
||||||
|
message: ?[*:0]const u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn requestAdapterCallback(
|
||||||
|
status: gpu.RequestAdapterStatus,
|
||||||
|
adapter: *gpu.Adapter,
|
||||||
|
message: ?[*:0]const u8,
|
||||||
|
context: *?RequestAdapterResponse,
|
||||||
|
) void {
|
||||||
|
context.* = RequestAdapterResponse{
|
||||||
|
.status = status,
|
||||||
|
.adapter = adapter,
|
||||||
|
.message = message,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub 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
|
||||||
|
|
@ -70,28 +87,6 @@ pub fn glfwWindowHintsForBackend(backend: gpu.Adapter.BackendType) glfw.Window.H
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub 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 };
|
||||||
|
|
@ -103,20 +98,18 @@ 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 extension = if (glfw_options.win32) gpu.Surface.Extension{
|
||||||
.windows_hwnd = .{
|
.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.Descriptor{
|
} else if (glfw_options.x11) gpu.Surface.Extension{
|
||||||
.xlib = .{
|
.from_xlib_window = &.{
|
||||||
.label = "basic surface",
|
|
||||||
.display = glfw_native.getX11Display(),
|
.display = glfw_native.getX11Display(),
|
||||||
.window = glfw_native.getX11Window(window),
|
.window = glfw_native.getX11Window(window),
|
||||||
},
|
},
|
||||||
|
|
@ -134,17 +127,14 @@ 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.Extension{ .from_metal_layer = &.{ .layer = layer.? } };
|
||||||
.metal_layer = .{
|
|
||||||
.label = "basic surface",
|
|
||||||
.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 = extension,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Borrowed from https://github.com/hazeycode/zig-objcrt
|
// Borrowed from https://github.com/hazeycode/zig-objcrt
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,13 @@ pub const Options = struct {
|
||||||
vsync: enums.VSyncMode = .double,
|
vsync: enums.VSyncMode = .double,
|
||||||
|
|
||||||
/// GPU features required by the application.
|
/// GPU features required by the application.
|
||||||
required_features: ?[]gpu.Feature = null,
|
required_features: ?[]gpu.FeatureName = null,
|
||||||
|
|
||||||
/// GPU limits required by the application.
|
/// GPU limits required by the application.
|
||||||
required_limits: ?gpu.Limits = null,
|
required_limits: ?gpu.Limits = null,
|
||||||
|
|
||||||
/// Whether the application has a preference for low power or high performance GPU.
|
/// Whether the application has a preference for low power or high performance GPU.
|
||||||
power_preference: gpu.PowerPreference = .none,
|
power_preference: gpu.PowerPreference = .undef,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Event = union(enum) {
|
pub const Event = union(enum) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue