src/gpu: move github.com/hexops/mach-gpu here
This moves github.com/hexops/mach-gpu@528dad0823dafeae5d474c88cc658b091bf2e605 to
this repository in the src/gpu directory. It can be imported via `@import("mach").gpu`.
Soon we will move away from mach-gpu entirely as part of #1166 - but in the meantime
I am giving a workshop at https://sycl.it and it would be nice for people using the
`mach.gpu.*` API to be able to search the API in this single repository.
There's not much harm to moving this code here.
Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
c45606c290
commit
2cf68adcc7
38 changed files with 8123 additions and 18 deletions
62
build.zig
62
build.zig
|
|
@ -1,8 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const glfw = @import("mach_glfw");
|
const glfw = @import("mach_glfw");
|
||||||
const gpu = @import("mach_gpu");
|
|
||||||
const sysgpu = @import("mach_sysgpu");
|
|
||||||
|
|
||||||
pub const SysgpuBackend = enum {
|
pub const SysgpuBackend = enum {
|
||||||
default,
|
default,
|
||||||
|
|
@ -101,12 +99,6 @@ pub fn build(b: *std.Build) !void {
|
||||||
try buildExamples(b, optimize, target, module);
|
try buildExamples(b, optimize, target, module);
|
||||||
}
|
}
|
||||||
if (want_core) {
|
if (want_core) {
|
||||||
const mach_gpu_dep = b.dependency("mach_gpu", .{
|
|
||||||
.target = target,
|
|
||||||
.optimize = optimize,
|
|
||||||
});
|
|
||||||
module.addImport("mach-gpu", mach_gpu_dep.module("mach-gpu"));
|
|
||||||
|
|
||||||
if (target.result.cpu.arch == .wasm32) {
|
if (target.result.cpu.arch == .wasm32) {
|
||||||
const sysjs_dep = b.dependency("mach_sysjs", .{
|
const sysjs_dep = b.dependency("mach_sysjs", .{
|
||||||
.target = target,
|
.target = target,
|
||||||
|
|
@ -265,6 +257,37 @@ pub fn build(b: *std.Build) !void {
|
||||||
b.installArtifact(lib);
|
b.installArtifact(lib);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (true) { // want_gpu
|
||||||
|
const gpu_dawn = @import("mach_gpu_dawn");
|
||||||
|
gpu_dawn.addPathsToModule(b, module, .{});
|
||||||
|
module.addIncludePath(.{ .path = sdkPath("/src/gpu") });
|
||||||
|
|
||||||
|
const example_exe = b.addExecutable(.{
|
||||||
|
.name = "dawn-gpu-hello-triangle",
|
||||||
|
.root_source_file = .{ .path = "src/gpu/example/main.zig" },
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
example_exe.root_module.addImport("mach", module);
|
||||||
|
link(b, example_exe, &example_exe.root_module);
|
||||||
|
|
||||||
|
const mach_glfw_dep = b.dependency("mach_glfw", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
example_exe.root_module.addImport("mach-glfw", mach_glfw_dep.module("mach-glfw"));
|
||||||
|
|
||||||
|
const example_compile_step = b.step("dawn-gpu-hello-triangle", "Install 'dawn-gpu-hello-triangle'");
|
||||||
|
example_compile_step.dependOn(b.getInstallStep());
|
||||||
|
|
||||||
|
const example_run_cmd = b.addRunArtifact(example_exe);
|
||||||
|
example_run_cmd.step.dependOn(b.getInstallStep());
|
||||||
|
if (b.args) |args| example_run_cmd.addArgs(args);
|
||||||
|
|
||||||
|
const example_run_step = b.step("run-dawn-gpu-hello-triangle", "Run 'dawn-gpu-hello-triangle' example");
|
||||||
|
example_run_step.dependOn(&example_run_cmd.step);
|
||||||
|
}
|
||||||
|
|
||||||
if (target.result.cpu.arch != .wasm32) {
|
if (target.result.cpu.arch != .wasm32) {
|
||||||
// Creates a step for unit testing. This only builds the test executable
|
// Creates a step for unit testing. This only builds the test executable
|
||||||
// but does not run it.
|
// but does not run it.
|
||||||
|
|
@ -288,7 +311,7 @@ pub fn build(b: *std.Build) !void {
|
||||||
const test_step = b.step("test", "Run unit tests");
|
const test_step = b.step("test", "Run unit tests");
|
||||||
test_step.dependOn(&run_unit_tests.step);
|
test_step.dependOn(&run_unit_tests.step);
|
||||||
|
|
||||||
if (want_sysgpu) linkSysgpu(b, &unit_tests.root_module);
|
if (want_sysgpu) linkSysgpu(b, &unit_tests.root_module) else link(b, unit_tests, &unit_tests.root_module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -507,10 +530,23 @@ pub const CoreApp = struct {
|
||||||
|
|
||||||
// TODO(sysgpu): remove this once we switch to sysgpu fully
|
// TODO(sysgpu): remove this once we switch to sysgpu fully
|
||||||
pub fn link(mach_builder: *std.Build, step: *std.Build.Step.Compile, mod: *std.Build.Module) void {
|
pub fn link(mach_builder: *std.Build, step: *std.Build.Step.Compile, mod: *std.Build.Module) void {
|
||||||
gpu.link(mach_builder.dependency("mach_gpu", .{
|
const gpu_dawn = @import("mach_gpu_dawn");
|
||||||
.target = step.root_module.resolved_target orelse mach_builder.host,
|
const Options = struct {
|
||||||
.optimize = step.root_module.optimize.?,
|
gpu_dawn_options: gpu_dawn.Options = .{},
|
||||||
}).builder, step, mod, .{}) catch unreachable;
|
};
|
||||||
|
const options: Options = .{};
|
||||||
|
|
||||||
|
gpu_dawn.link(
|
||||||
|
mach_builder.dependency("mach_gpu_dawn", .{
|
||||||
|
.target = step.root_module.resolved_target.?,
|
||||||
|
.optimize = step.root_module.optimize.?,
|
||||||
|
}).builder,
|
||||||
|
step,
|
||||||
|
mod,
|
||||||
|
options.gpu_dawn_options,
|
||||||
|
);
|
||||||
|
step.addCSourceFile(.{ .file = .{ .path = sdkPath("/src/gpu/mach_dawn.cpp") }, .flags = &.{"-std=c++17"} });
|
||||||
|
step.addIncludePath(.{ .path = sdkPath("/src/gpu") });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn linkSysgpu(b: *std.Build, module: *std.Build.Module) void {
|
fn linkSysgpu(b: *std.Build, module: *std.Build.Module) void {
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,9 @@
|
||||||
.url = "https://pkg.machengine.org/mach-sysjs/eeef024f79beae189b7a4ed85e64ed076e76d538.tar.gz",
|
.url = "https://pkg.machengine.org/mach-sysjs/eeef024f79beae189b7a4ed85e64ed076e76d538.tar.gz",
|
||||||
.hash = "1220db6845ce34743ae2a1ab0222efc942496adde2736c20e3443d4fde4ef64b11b9",
|
.hash = "1220db6845ce34743ae2a1ab0222efc942496adde2736c20e3443d4fde4ef64b11b9",
|
||||||
},
|
},
|
||||||
.mach_gpu = .{
|
.mach_gpu_dawn = .{
|
||||||
.url = "https://pkg.machengine.org/mach-gpu/528dad0823dafeae5d474c88cc658b091bf2e605.tar.gz",
|
.url = "https://pkg.machengine.org/mach-gpu-dawn/cce4d19945ca6102162b0cbbc546648edb38dc41.tar.gz",
|
||||||
.hash = "1220fe2e555ca66741539bc0f97769b2513c5e609c968d27eb8997f577a1d195f048",
|
.hash = "1220a6e3f4772fed665bb5b1792cf5cff8ac51af42a57ad8d276e394ae19f310a92e",
|
||||||
},
|
},
|
||||||
.mach_glfw = .{
|
.mach_glfw = .{
|
||||||
.url = "https://pkg.machengine.org/mach-glfw/26e8af73d7d4fbdac3ff60492c44294fc0d139b7.tar.gz",
|
.url = "https://pkg.machengine.org/mach-glfw/26e8af73d7d4fbdac3ff60492c44294fc0d139b7.tar.gz",
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ pub const options = if (@hasDecl(@import("root"), "mach_core_options"))
|
||||||
else
|
else
|
||||||
ComptimeOptions{};
|
ComptimeOptions{};
|
||||||
|
|
||||||
pub const wgpu = @import("mach-gpu");
|
pub const wgpu = @import("../gpu/main.zig");
|
||||||
|
|
||||||
pub const gpu = if (options.use_sysgpu) sysgpu.sysgpu else wgpu;
|
pub const gpu = if (options.use_sysgpu) sysgpu.sysgpu else wgpu;
|
||||||
|
|
||||||
|
|
@ -154,7 +154,9 @@ pub const Options = struct {
|
||||||
power_preference: gpu.PowerPreference = .undefined,
|
power_preference: gpu.PowerPreference = .undefined,
|
||||||
required_features: ?[]const gpu.FeatureName = null,
|
required_features: ?[]const gpu.FeatureName = null,
|
||||||
required_limits: ?gpu.Limits = null,
|
required_limits: ?gpu.Limits = null,
|
||||||
swap_chain_usage: gpu.Texture.UsageFlags = .{ .render_attachment = true, },
|
swap_chain_usage: gpu.Texture.UsageFlags = .{
|
||||||
|
.render_attachment = true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(options_in: Options) !void {
|
pub fn init(options_in: Options) !void {
|
||||||
|
|
|
||||||
122
src/gpu/adapter.zig
Normal file
122
src/gpu/adapter.zig
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const testing = std.testing;
|
||||||
|
const dawn = @import("dawn.zig");
|
||||||
|
const Bool32 = @import("main.zig").Bool32;
|
||||||
|
const ChainedStructOut = @import("main.zig").ChainedStructOut;
|
||||||
|
const Device = @import("device.zig").Device;
|
||||||
|
const Instance = @import("instance.zig").Instance;
|
||||||
|
const FeatureName = @import("main.zig").FeatureName;
|
||||||
|
const SupportedLimits = @import("main.zig").SupportedLimits;
|
||||||
|
const RequestDeviceStatus = @import("main.zig").RequestDeviceStatus;
|
||||||
|
const BackendType = @import("main.zig").BackendType;
|
||||||
|
const RequestDeviceCallback = @import("main.zig").RequestDeviceCallback;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const Adapter = opaque {
|
||||||
|
pub const Type = enum(u32) {
|
||||||
|
discrete_gpu,
|
||||||
|
integrated_gpu,
|
||||||
|
cpu,
|
||||||
|
unknown,
|
||||||
|
|
||||||
|
pub fn name(t: Type) []const u8 {
|
||||||
|
return switch (t) {
|
||||||
|
.discrete_gpu => "Discrete GPU",
|
||||||
|
.integrated_gpu => "Integrated GPU",
|
||||||
|
.cpu => "CPU",
|
||||||
|
.unknown => "Unknown",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Properties = extern struct {
|
||||||
|
pub const NextInChain = extern union {
|
||||||
|
generic: ?*const ChainedStructOut,
|
||||||
|
dawn_adapter_properties_power_preference: *const dawn.AdapterPropertiesPowerPreference,
|
||||||
|
};
|
||||||
|
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
vendor_id: u32,
|
||||||
|
vendor_name: [*:0]const u8,
|
||||||
|
architecture: [*:0]const u8,
|
||||||
|
device_id: u32,
|
||||||
|
name: [*:0]const u8,
|
||||||
|
driver_description: [*:0]const u8,
|
||||||
|
adapter_type: Type,
|
||||||
|
backend_type: BackendType,
|
||||||
|
compatibility_mode: Bool32 = .false,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn createDevice(adapter: *Adapter, descriptor: ?*const Device.Descriptor) ?*Device {
|
||||||
|
return Impl.adapterCreateDevice(adapter, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Call once with null to determine the array length, and again to fetch the feature list.
|
||||||
|
///
|
||||||
|
/// Consider using the enumerateFeaturesOwned helper.
|
||||||
|
pub inline fn enumerateFeatures(adapter: *Adapter, features: ?[*]FeatureName) usize {
|
||||||
|
return Impl.adapterEnumerateFeatures(adapter, features);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enumerates the adapter features, storing the result in an allocated slice which is owned by
|
||||||
|
/// the caller.
|
||||||
|
pub inline fn enumerateFeaturesOwned(adapter: *Adapter, allocator: std.mem.Allocator) ![]FeatureName {
|
||||||
|
const count = adapter.enumerateFeatures(null);
|
||||||
|
const data = try allocator.alloc(FeatureName, count);
|
||||||
|
_ = adapter.enumerateFeatures(data.ptr);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getInstance(adapter: *Adapter) *Instance {
|
||||||
|
return Impl.adapterGetInstance(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getLimits(adapter: *Adapter, limits: *SupportedLimits) bool {
|
||||||
|
return Impl.adapterGetLimits(adapter, limits) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getProperties(adapter: *Adapter, properties: *Adapter.Properties) void {
|
||||||
|
Impl.adapterGetProperties(adapter, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn hasFeature(adapter: *Adapter, feature: FeatureName) bool {
|
||||||
|
return Impl.adapterHasFeature(adapter, feature) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn requestDevice(
|
||||||
|
adapter: *Adapter,
|
||||||
|
descriptor: ?*const Device.Descriptor,
|
||||||
|
context: anytype,
|
||||||
|
comptime callback: fn (
|
||||||
|
ctx: @TypeOf(context),
|
||||||
|
status: RequestDeviceStatus,
|
||||||
|
device: *Device,
|
||||||
|
message: ?[*:0]const u8,
|
||||||
|
) callconv(.Inline) void,
|
||||||
|
) void {
|
||||||
|
const Context = @TypeOf(context);
|
||||||
|
const Helper = struct {
|
||||||
|
pub fn cCallback(status: RequestDeviceStatus, device: *Device, message: ?[*:0]const u8, userdata: ?*anyopaque) callconv(.C) void {
|
||||||
|
callback(
|
||||||
|
if (Context == void) {} else @as(Context, @ptrCast(@alignCast(userdata))),
|
||||||
|
status,
|
||||||
|
device,
|
||||||
|
message,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Impl.adapterRequestDevice(adapter, descriptor, Helper.cCallback, if (Context == void) null else context);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(adapter: *Adapter) void {
|
||||||
|
Impl.adapterReference(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(adapter: *Adapter) void {
|
||||||
|
Impl.adapterRelease(adapter);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
test "Adapter.Type name" {
|
||||||
|
try testing.expectEqualStrings("Discrete GPU", Adapter.Type.discrete_gpu.name());
|
||||||
|
}
|
||||||
88
src/gpu/bind_group.zig
Normal file
88
src/gpu/bind_group.zig
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
const Buffer = @import("buffer.zig").Buffer;
|
||||||
|
const Sampler = @import("sampler.zig").Sampler;
|
||||||
|
const TextureView = @import("texture_view.zig").TextureView;
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const BindGroupLayout = @import("bind_group_layout.zig").BindGroupLayout;
|
||||||
|
const ExternalTexture = @import("external_texture.zig").ExternalTexture;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const BindGroup = opaque {
|
||||||
|
pub const Entry = extern struct {
|
||||||
|
pub const NextInChain = extern union {
|
||||||
|
generic: ?*const ChainedStruct,
|
||||||
|
external_texture_binding_entry: *const ExternalTexture.BindingEntry,
|
||||||
|
};
|
||||||
|
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
binding: u32,
|
||||||
|
buffer: ?*Buffer = null,
|
||||||
|
offset: u64 = 0,
|
||||||
|
size: u64,
|
||||||
|
sampler: ?*Sampler = null,
|
||||||
|
texture_view: ?*TextureView = null,
|
||||||
|
|
||||||
|
/// Helper to create a buffer BindGroup.Entry.
|
||||||
|
pub fn buffer(binding: u32, buf: *Buffer, offset: u64, size: u64) Entry {
|
||||||
|
return .{
|
||||||
|
.binding = binding,
|
||||||
|
.buffer = buf,
|
||||||
|
.offset = offset,
|
||||||
|
.size = size,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper to create a sampler BindGroup.Entry.
|
||||||
|
pub fn sampler(binding: u32, _sampler: *Sampler) Entry {
|
||||||
|
return .{
|
||||||
|
.binding = binding,
|
||||||
|
.sampler = _sampler,
|
||||||
|
.size = 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper to create a texture view BindGroup.Entry.
|
||||||
|
pub fn textureView(binding: u32, texture_view: *TextureView) Entry {
|
||||||
|
return .{
|
||||||
|
.binding = binding,
|
||||||
|
.texture_view = texture_view,
|
||||||
|
.size = 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
layout: *BindGroupLayout,
|
||||||
|
entry_count: usize = 0,
|
||||||
|
entries: ?[*]const Entry = null,
|
||||||
|
|
||||||
|
/// Provides a slightly friendlier Zig API to initialize this structure.
|
||||||
|
pub inline fn init(v: struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
layout: *BindGroupLayout,
|
||||||
|
entries: ?[]const Entry = null,
|
||||||
|
}) Descriptor {
|
||||||
|
return .{
|
||||||
|
.next_in_chain = v.next_in_chain,
|
||||||
|
.label = v.label,
|
||||||
|
.layout = v.layout,
|
||||||
|
.entry_count = if (v.entries) |e| e.len else 0,
|
||||||
|
.entries = if (v.entries) |e| e.ptr else null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn setLabel(bind_group: *BindGroup, label: [*:0]const u8) void {
|
||||||
|
Impl.bindGroupSetLabel(bind_group, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(bind_group: *BindGroup) void {
|
||||||
|
Impl.bindGroupReference(bind_group);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(bind_group: *BindGroup) void {
|
||||||
|
Impl.bindGroupRelease(bind_group);
|
||||||
|
}
|
||||||
|
};
|
||||||
131
src/gpu/bind_group_layout.zig
Normal file
131
src/gpu/bind_group_layout.zig
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
const Bool32 = @import("main.zig").Bool32;
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const ShaderStageFlags = @import("main.zig").ShaderStageFlags;
|
||||||
|
const Buffer = @import("buffer.zig").Buffer;
|
||||||
|
const Sampler = @import("sampler.zig").Sampler;
|
||||||
|
const Texture = @import("texture.zig").Texture;
|
||||||
|
const TextureView = @import("texture_view.zig").TextureView;
|
||||||
|
const StorageTextureBindingLayout = @import("main.zig").StorageTextureBindingLayout;
|
||||||
|
const StorageTextureAccess = @import("main.zig").StorageTextureAccess;
|
||||||
|
const ExternalTexture = @import("external_texture.zig").ExternalTexture;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const BindGroupLayout = opaque {
|
||||||
|
pub const Entry = extern struct {
|
||||||
|
pub const NextInChain = extern union {
|
||||||
|
generic: ?*const ChainedStruct,
|
||||||
|
external_texture_binding_layout: *const ExternalTexture.BindingLayout,
|
||||||
|
};
|
||||||
|
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
binding: u32,
|
||||||
|
visibility: ShaderStageFlags,
|
||||||
|
buffer: Buffer.BindingLayout = .{},
|
||||||
|
sampler: Sampler.BindingLayout = .{},
|
||||||
|
texture: Texture.BindingLayout = .{},
|
||||||
|
storage_texture: StorageTextureBindingLayout = .{},
|
||||||
|
|
||||||
|
/// Helper to create a buffer BindGroupLayout.Entry.
|
||||||
|
pub fn buffer(
|
||||||
|
binding: u32,
|
||||||
|
visibility: ShaderStageFlags,
|
||||||
|
binding_type: Buffer.BindingType,
|
||||||
|
has_dynamic_offset: bool,
|
||||||
|
min_binding_size: u64,
|
||||||
|
) Entry {
|
||||||
|
return .{
|
||||||
|
.binding = binding,
|
||||||
|
.visibility = visibility,
|
||||||
|
.buffer = .{
|
||||||
|
.type = binding_type,
|
||||||
|
.has_dynamic_offset = Bool32.from(has_dynamic_offset),
|
||||||
|
.min_binding_size = min_binding_size,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper to create a sampler BindGroupLayout.Entry.
|
||||||
|
pub fn sampler(
|
||||||
|
binding: u32,
|
||||||
|
visibility: ShaderStageFlags,
|
||||||
|
binding_type: Sampler.BindingType,
|
||||||
|
) Entry {
|
||||||
|
return .{
|
||||||
|
.binding = binding,
|
||||||
|
.visibility = visibility,
|
||||||
|
.sampler = .{ .type = binding_type },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper to create a texture BindGroupLayout.Entry.
|
||||||
|
pub fn texture(
|
||||||
|
binding: u32,
|
||||||
|
visibility: ShaderStageFlags,
|
||||||
|
sample_type: Texture.SampleType,
|
||||||
|
view_dimension: TextureView.Dimension,
|
||||||
|
multisampled: bool,
|
||||||
|
) Entry {
|
||||||
|
return .{
|
||||||
|
.binding = binding,
|
||||||
|
.visibility = visibility,
|
||||||
|
.texture = .{
|
||||||
|
.sample_type = sample_type,
|
||||||
|
.view_dimension = view_dimension,
|
||||||
|
.multisampled = Bool32.from(multisampled),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper to create a storage texture BindGroupLayout.Entry.
|
||||||
|
pub fn storageTexture(
|
||||||
|
binding: u32,
|
||||||
|
visibility: ShaderStageFlags,
|
||||||
|
access: StorageTextureAccess,
|
||||||
|
format: Texture.Format,
|
||||||
|
view_dimension: TextureView.Dimension,
|
||||||
|
) Entry {
|
||||||
|
return .{
|
||||||
|
.binding = binding,
|
||||||
|
.visibility = visibility,
|
||||||
|
.storage_texture = .{
|
||||||
|
.access = access,
|
||||||
|
.format = format,
|
||||||
|
.view_dimension = view_dimension,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
entry_count: usize = 0,
|
||||||
|
entries: ?[*]const Entry = null,
|
||||||
|
|
||||||
|
/// Provides a slightly friendlier Zig API to initialize this structure.
|
||||||
|
pub inline fn init(v: struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
entries: ?[]const Entry = null,
|
||||||
|
}) Descriptor {
|
||||||
|
return .{
|
||||||
|
.next_in_chain = v.next_in_chain,
|
||||||
|
.label = v.label,
|
||||||
|
.entry_count = if (v.entries) |e| e.len else 0,
|
||||||
|
.entries = if (v.entries) |e| e.ptr else null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn setLabel(bind_group_layout: *BindGroupLayout, label: [*:0]const u8) void {
|
||||||
|
Impl.bindGroupLayoutSetLabel(bind_group_layout, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(bind_group_layout: *BindGroupLayout) void {
|
||||||
|
Impl.bindGroupLayoutReference(bind_group_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(bind_group_layout: *BindGroupLayout) void {
|
||||||
|
Impl.bindGroupLayoutRelease(bind_group_layout);
|
||||||
|
}
|
||||||
|
};
|
||||||
166
src/gpu/buffer.zig
Normal file
166
src/gpu/buffer.zig
Normal file
|
|
@ -0,0 +1,166 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const Bool32 = @import("main.zig").Bool32;
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const dawn = @import("dawn.zig");
|
||||||
|
const MapModeFlags = @import("main.zig").MapModeFlags;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const Buffer = opaque {
|
||||||
|
pub const MapCallback = *const fn (status: MapAsyncStatus, userdata: ?*anyopaque) callconv(.C) void;
|
||||||
|
|
||||||
|
pub const BindingType = enum(u32) {
|
||||||
|
undefined = 0x00000000,
|
||||||
|
uniform = 0x00000001,
|
||||||
|
storage = 0x00000002,
|
||||||
|
read_only_storage = 0x00000003,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MapState = enum(u32) {
|
||||||
|
unmapped = 0x00000000,
|
||||||
|
pending = 0x00000001,
|
||||||
|
mapped = 0x00000002,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MapAsyncStatus = enum(u32) {
|
||||||
|
success = 0x00000000,
|
||||||
|
validation_error = 0x00000001,
|
||||||
|
unknown = 0x00000002,
|
||||||
|
device_lost = 0x00000003,
|
||||||
|
destroyed_before_callback = 0x00000004,
|
||||||
|
unmapped_before_callback = 0x00000005,
|
||||||
|
mapping_already_pending = 0x00000006,
|
||||||
|
offset_out_of_range = 0x00000007,
|
||||||
|
size_out_of_range = 0x00000008,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const UsageFlags = packed struct(u32) {
|
||||||
|
map_read: bool = false,
|
||||||
|
map_write: bool = false,
|
||||||
|
copy_src: bool = false,
|
||||||
|
copy_dst: bool = false,
|
||||||
|
index: bool = false,
|
||||||
|
vertex: bool = false,
|
||||||
|
uniform: bool = false,
|
||||||
|
storage: bool = false,
|
||||||
|
indirect: bool = false,
|
||||||
|
query_resolve: bool = false,
|
||||||
|
|
||||||
|
_padding: u22 = 0,
|
||||||
|
|
||||||
|
comptime {
|
||||||
|
std.debug.assert(
|
||||||
|
@sizeOf(@This()) == @sizeOf(u32) and
|
||||||
|
@bitSizeOf(@This()) == @bitSizeOf(u32),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const none = UsageFlags{};
|
||||||
|
|
||||||
|
pub fn equal(a: UsageFlags, b: UsageFlags) bool {
|
||||||
|
return @as(u10, @truncate(@as(u32, @bitCast(a)))) == @as(u10, @truncate(@as(u32, @bitCast(b))));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const BindingLayout = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
type: BindingType = .undefined,
|
||||||
|
has_dynamic_offset: Bool32 = .false,
|
||||||
|
min_binding_size: u64 = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
pub const NextInChain = extern union {
|
||||||
|
generic: ?*const ChainedStruct,
|
||||||
|
dawn_buffer_descriptor_error_info_from_wire_client: *const dawn.BufferDescriptorErrorInfoFromWireClient,
|
||||||
|
};
|
||||||
|
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
usage: UsageFlags,
|
||||||
|
size: u64,
|
||||||
|
mapped_at_creation: Bool32 = .false,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn destroy(buffer: *Buffer) void {
|
||||||
|
Impl.bufferDestroy(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getMapState(buffer: *Buffer) MapState {
|
||||||
|
return Impl.bufferGetMapState(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default `offset_bytes`: 0
|
||||||
|
/// Default `len`: `gpu.whole_map_size` / `std.math.maxint(usize)` (whole range)
|
||||||
|
pub inline fn getConstMappedRange(
|
||||||
|
buffer: *Buffer,
|
||||||
|
comptime T: type,
|
||||||
|
offset_bytes: usize,
|
||||||
|
len: usize,
|
||||||
|
) ?[]const T {
|
||||||
|
const size = @sizeOf(T) * len;
|
||||||
|
const data = Impl.bufferGetConstMappedRange(
|
||||||
|
buffer,
|
||||||
|
offset_bytes,
|
||||||
|
size + size % 4,
|
||||||
|
);
|
||||||
|
return if (data) |d| @as([*]const T, @ptrCast(@alignCast(d)))[0..len] else null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default `offset_bytes`: 0
|
||||||
|
/// Default `len`: `gpu.whole_map_size` / `std.math.maxint(usize)` (whole range)
|
||||||
|
pub inline fn getMappedRange(
|
||||||
|
buffer: *Buffer,
|
||||||
|
comptime T: type,
|
||||||
|
offset_bytes: usize,
|
||||||
|
len: usize,
|
||||||
|
) ?[]T {
|
||||||
|
const size = @sizeOf(T) * len;
|
||||||
|
const data = Impl.bufferGetMappedRange(
|
||||||
|
buffer,
|
||||||
|
offset_bytes,
|
||||||
|
size + size % 4,
|
||||||
|
);
|
||||||
|
return if (data) |d| @as([*]T, @ptrCast(@alignCast(d)))[0..len] else null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getSize(buffer: *Buffer) u64 {
|
||||||
|
return Impl.bufferGetSize(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getUsage(buffer: *Buffer) Buffer.UsageFlags {
|
||||||
|
return Impl.bufferGetUsage(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn mapAsync(
|
||||||
|
buffer: *Buffer,
|
||||||
|
mode: MapModeFlags,
|
||||||
|
offset: usize,
|
||||||
|
size: usize,
|
||||||
|
context: anytype,
|
||||||
|
comptime callback: fn (ctx: @TypeOf(context), status: MapAsyncStatus) callconv(.Inline) void,
|
||||||
|
) void {
|
||||||
|
const Context = @TypeOf(context);
|
||||||
|
const Helper = struct {
|
||||||
|
pub fn cCallback(status: MapAsyncStatus, userdata: ?*anyopaque) callconv(.C) void {
|
||||||
|
callback(if (Context == void) {} else @as(Context, @ptrCast(@alignCast(userdata))), status);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Impl.bufferMapAsync(buffer, mode, offset, size, Helper.cCallback, if (Context == void) null else context);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setLabel(buffer: *Buffer, label: [*:0]const u8) void {
|
||||||
|
Impl.bufferSetLabel(buffer, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn unmap(buffer: *Buffer) void {
|
||||||
|
Impl.bufferUnmap(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(buffer: *Buffer) void {
|
||||||
|
Impl.bufferReference(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(buffer: *Buffer) void {
|
||||||
|
Impl.bufferRelease(buffer);
|
||||||
|
}
|
||||||
|
};
|
||||||
21
src/gpu/command_buffer.zig
Normal file
21
src/gpu/command_buffer.zig
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const CommandBuffer = opaque {
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn setLabel(command_buffer: *CommandBuffer, label: [*:0]const u8) void {
|
||||||
|
Impl.commandBufferSetLabel(command_buffer, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(command_buffer: *CommandBuffer) void {
|
||||||
|
Impl.commandBufferReference(command_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(command_buffer: *CommandBuffer) void {
|
||||||
|
Impl.commandBufferRelease(command_buffer);
|
||||||
|
}
|
||||||
|
};
|
||||||
111
src/gpu/command_encoder.zig
Normal file
111
src/gpu/command_encoder.zig
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const ComputePassEncoder = @import("compute_pass_encoder.zig").ComputePassEncoder;
|
||||||
|
const RenderPassEncoder = @import("render_pass_encoder.zig").RenderPassEncoder;
|
||||||
|
const CommandBuffer = @import("command_buffer.zig").CommandBuffer;
|
||||||
|
const Buffer = @import("buffer.zig").Buffer;
|
||||||
|
const QuerySet = @import("query_set.zig").QuerySet;
|
||||||
|
const RenderPassDescriptor = @import("main.zig").RenderPassDescriptor;
|
||||||
|
const ComputePassDescriptor = @import("main.zig").ComputePassDescriptor;
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const ImageCopyBuffer = @import("main.zig").ImageCopyBuffer;
|
||||||
|
const ImageCopyTexture = @import("main.zig").ImageCopyTexture;
|
||||||
|
const Extent3D = @import("main.zig").Extent3D;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
const dawn = @import("dawn.zig");
|
||||||
|
|
||||||
|
pub const CommandEncoder = opaque {
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
pub const NextInChain = extern union {
|
||||||
|
generic: ?*const ChainedStruct,
|
||||||
|
dawn_encoder_internal_usage_descriptor: *const dawn.EncoderInternalUsageDescriptor,
|
||||||
|
};
|
||||||
|
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn beginComputePass(command_encoder: *CommandEncoder, descriptor: ?*const ComputePassDescriptor) *ComputePassEncoder {
|
||||||
|
return Impl.commandEncoderBeginComputePass(command_encoder, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn beginRenderPass(command_encoder: *CommandEncoder, descriptor: *const RenderPassDescriptor) *RenderPassEncoder {
|
||||||
|
return Impl.commandEncoderBeginRenderPass(command_encoder, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default `offset`: 0
|
||||||
|
/// Default `size`: `gpu.whole_size`
|
||||||
|
pub inline fn clearBuffer(command_encoder: *CommandEncoder, buffer: *Buffer, offset: u64, size: u64) void {
|
||||||
|
Impl.commandEncoderClearBuffer(command_encoder, buffer, offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn copyBufferToBuffer(command_encoder: *CommandEncoder, source: *Buffer, source_offset: u64, destination: *Buffer, destination_offset: u64, size: u64) void {
|
||||||
|
Impl.commandEncoderCopyBufferToBuffer(command_encoder, source, source_offset, destination, destination_offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn copyBufferToTexture(command_encoder: *CommandEncoder, source: *const ImageCopyBuffer, destination: *const ImageCopyTexture, copy_size: *const Extent3D) void {
|
||||||
|
Impl.commandEncoderCopyBufferToTexture(command_encoder, source, destination, copy_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn copyTextureToBuffer(command_encoder: *CommandEncoder, source: *const ImageCopyTexture, destination: *const ImageCopyBuffer, copy_size: *const Extent3D) void {
|
||||||
|
Impl.commandEncoderCopyTextureToBuffer(command_encoder, source, destination, copy_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn copyTextureToTexture(command_encoder: *CommandEncoder, source: *const ImageCopyTexture, destination: *const ImageCopyTexture, copy_size: *const Extent3D) void {
|
||||||
|
Impl.commandEncoderCopyTextureToTexture(command_encoder, source, destination, copy_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn finish(command_encoder: *CommandEncoder, descriptor: ?*const CommandBuffer.Descriptor) *CommandBuffer {
|
||||||
|
return Impl.commandEncoderFinish(command_encoder, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn injectValidationError(command_encoder: *CommandEncoder, message: [*:0]const u8) void {
|
||||||
|
Impl.commandEncoderInjectValidationError(command_encoder, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn insertDebugMarker(command_encoder: *CommandEncoder, marker_label: [*:0]const u8) void {
|
||||||
|
Impl.commandEncoderInsertDebugMarker(command_encoder, marker_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn popDebugGroup(command_encoder: *CommandEncoder) void {
|
||||||
|
Impl.commandEncoderPopDebugGroup(command_encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn pushDebugGroup(command_encoder: *CommandEncoder, group_label: [*:0]const u8) void {
|
||||||
|
Impl.commandEncoderPushDebugGroup(command_encoder, group_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn resolveQuerySet(command_encoder: *CommandEncoder, query_set: *QuerySet, first_query: u32, query_count: u32, destination: *Buffer, destination_offset: u64) void {
|
||||||
|
Impl.commandEncoderResolveQuerySet(command_encoder, query_set, first_query, query_count, destination, destination_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setLabel(command_encoder: *CommandEncoder, label: [*:0]const u8) void {
|
||||||
|
Impl.commandEncoderSetLabel(command_encoder, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn writeBuffer(
|
||||||
|
command_encoder: *CommandEncoder,
|
||||||
|
buffer: *Buffer,
|
||||||
|
buffer_offset_bytes: u64,
|
||||||
|
data_slice: anytype,
|
||||||
|
) void {
|
||||||
|
Impl.commandEncoderWriteBuffer(
|
||||||
|
command_encoder,
|
||||||
|
buffer,
|
||||||
|
buffer_offset_bytes,
|
||||||
|
@as([*]const u8, @ptrCast(std.mem.sliceAsBytes(data_slice).ptr)),
|
||||||
|
@as(u64, @intCast(data_slice.len)) * @sizeOf(std.meta.Elem(@TypeOf(data_slice))),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn writeTimestamp(command_encoder: *CommandEncoder, query_set: *QuerySet, query_index: u32) void {
|
||||||
|
Impl.commandEncoderWriteTimestamp(command_encoder, query_set, query_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(command_encoder: *CommandEncoder) void {
|
||||||
|
Impl.commandEncoderReference(command_encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(command_encoder: *CommandEncoder) void {
|
||||||
|
Impl.commandEncoderRelease(command_encoder);
|
||||||
|
}
|
||||||
|
};
|
||||||
64
src/gpu/compute_pass_encoder.zig
Normal file
64
src/gpu/compute_pass_encoder.zig
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
const Buffer = @import("buffer.zig").Buffer;
|
||||||
|
const BindGroup = @import("bind_group.zig").BindGroup;
|
||||||
|
const ComputePipeline = @import("compute_pipeline.zig").ComputePipeline;
|
||||||
|
const QuerySet = @import("query_set.zig").QuerySet;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const ComputePassEncoder = opaque {
|
||||||
|
/// Default `workgroup_count_y`: 1
|
||||||
|
/// Default `workgroup_count_z`: 1
|
||||||
|
pub inline fn dispatchWorkgroups(compute_pass_encoder: *ComputePassEncoder, workgroup_count_x: u32, workgroup_count_y: u32, workgroup_count_z: u32) void {
|
||||||
|
Impl.computePassEncoderDispatchWorkgroups(compute_pass_encoder, workgroup_count_x, workgroup_count_y, workgroup_count_z);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn dispatchWorkgroupsIndirect(compute_pass_encoder: *ComputePassEncoder, indirect_buffer: *Buffer, indirect_offset: u64) void {
|
||||||
|
Impl.computePassEncoderDispatchWorkgroupsIndirect(compute_pass_encoder, indirect_buffer, indirect_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn end(compute_pass_encoder: *ComputePassEncoder) void {
|
||||||
|
Impl.computePassEncoderEnd(compute_pass_encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn insertDebugMarker(compute_pass_encoder: *ComputePassEncoder, marker_label: [*:0]const u8) void {
|
||||||
|
Impl.computePassEncoderInsertDebugMarker(compute_pass_encoder, marker_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn popDebugGroup(compute_pass_encoder: *ComputePassEncoder) void {
|
||||||
|
Impl.computePassEncoderPopDebugGroup(compute_pass_encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn pushDebugGroup(compute_pass_encoder: *ComputePassEncoder, group_label: [*:0]const u8) void {
|
||||||
|
Impl.computePassEncoderPushDebugGroup(compute_pass_encoder, group_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default `dynamic_offsets`: null
|
||||||
|
pub inline fn setBindGroup(compute_pass_encoder: *ComputePassEncoder, group_index: u32, group: *BindGroup, dynamic_offsets: ?[]const u32) void {
|
||||||
|
Impl.computePassEncoderSetBindGroup(
|
||||||
|
compute_pass_encoder,
|
||||||
|
group_index,
|
||||||
|
group,
|
||||||
|
if (dynamic_offsets) |v| v.len else 0,
|
||||||
|
if (dynamic_offsets) |v| v.ptr else null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setLabel(compute_pass_encoder: *ComputePassEncoder, label: [*:0]const u8) void {
|
||||||
|
Impl.computePassEncoderSetLabel(compute_pass_encoder, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setPipeline(compute_pass_encoder: *ComputePassEncoder, pipeline: *ComputePipeline) void {
|
||||||
|
Impl.computePassEncoderSetPipeline(compute_pass_encoder, pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn writeTimestamp(compute_pass_encoder: *ComputePassEncoder, query_set: *QuerySet, query_index: u32) void {
|
||||||
|
Impl.computePassEncoderWriteTimestamp(compute_pass_encoder, query_set, query_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(compute_pass_encoder: *ComputePassEncoder) void {
|
||||||
|
Impl.computePassEncoderReference(compute_pass_encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(compute_pass_encoder: *ComputePassEncoder) void {
|
||||||
|
Impl.computePassEncoderRelease(compute_pass_encoder);
|
||||||
|
}
|
||||||
|
};
|
||||||
30
src/gpu/compute_pipeline.zig
Normal file
30
src/gpu/compute_pipeline.zig
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const ProgrammableStageDescriptor = @import("main.zig").ProgrammableStageDescriptor;
|
||||||
|
const PipelineLayout = @import("pipeline_layout.zig").PipelineLayout;
|
||||||
|
const BindGroupLayout = @import("bind_group_layout.zig").BindGroupLayout;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const ComputePipeline = opaque {
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
layout: ?*PipelineLayout = null,
|
||||||
|
compute: ProgrammableStageDescriptor,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn getBindGroupLayout(compute_pipeline: *ComputePipeline, group_index: u32) *BindGroupLayout {
|
||||||
|
return Impl.computePipelineGetBindGroupLayout(compute_pipeline, group_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setLabel(compute_pipeline: *ComputePipeline, label: [*:0]const u8) void {
|
||||||
|
Impl.computePipelineSetLabel(compute_pipeline, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(compute_pipeline: *ComputePipeline) void {
|
||||||
|
Impl.computePipelineReference(compute_pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(compute_pipeline: *ComputePipeline) void {
|
||||||
|
Impl.computePipelineRelease(compute_pipeline);
|
||||||
|
}
|
||||||
|
};
|
||||||
75
src/gpu/dawn.zig
Normal file
75
src/gpu/dawn.zig
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
const Bool32 = @import("main.zig").Bool32;
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const ChainedStructOut = @import("main.zig").ChainedStructOut;
|
||||||
|
const PowerPreference = @import("main.zig").PowerPreference;
|
||||||
|
const Texture = @import("texture.zig").Texture;
|
||||||
|
pub const Interface = @import("dawn_impl.zig").Interface;
|
||||||
|
|
||||||
|
pub const CacheDeviceDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .dawn_cache_device_descriptor },
|
||||||
|
isolation_key: [*:0]const u8 = "",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const EncoderInternalUsageDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .dawn_encoder_internal_usage_descriptor },
|
||||||
|
use_internal_usages: Bool32 = .false,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultisampleStateRenderToSingleSampled = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .dawn_multisample_state_render_to_single_sampled },
|
||||||
|
enabled: Bool32 = .false,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const RenderPassColorAttachmentRenderToSingleSampled = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .dawn_render_pass_color_attachment_render_to_single_sampled },
|
||||||
|
implicit_sample_count: u32 = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const TextureInternalUsageDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .dawn_texture_internal_usage_descriptor },
|
||||||
|
internal_usage: Texture.UsageFlags = Texture.UsageFlags.none,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const TogglesDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .dawn_toggles_descriptor },
|
||||||
|
enabled_toggles_count: usize = 0,
|
||||||
|
enabled_toggles: ?[*]const [*:0]const u8 = null,
|
||||||
|
disabled_toggles_count: usize = 0,
|
||||||
|
disabled_toggles: ?[*]const [*:0]const u8 = null,
|
||||||
|
|
||||||
|
/// Provides a slightly friendlier Zig API to initialize this structure.
|
||||||
|
pub inline fn init(v: struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .dawn_toggles_descriptor },
|
||||||
|
enabled_toggles: ?[]const [*:0]const u8 = null,
|
||||||
|
disabled_toggles: ?[]const [*:0]const u8 = null,
|
||||||
|
}) TogglesDescriptor {
|
||||||
|
return .{
|
||||||
|
.chain = v.chain,
|
||||||
|
.enabled_toggles_count = if (v.enabled_toggles) |e| e.len else 0,
|
||||||
|
.enabled_toggles = if (v.enabled_toggles) |e| e.ptr else null,
|
||||||
|
.disabled_toggles_count = if (v.disabled_toggles) |e| e.len else 0,
|
||||||
|
.disabled_toggles = if (v.disabled_toggles) |e| e.ptr else null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ShaderModuleSPIRVOptionsDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .dawn_shader_module_spirv_options_descriptor },
|
||||||
|
allow_non_uniform_derivatives: Bool32 = .false,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const AdapterPropertiesPowerPreference = extern struct {
|
||||||
|
chain: ChainedStructOut = .{
|
||||||
|
.next = null,
|
||||||
|
.s_type = .dawn_adapter_properties_power_preference,
|
||||||
|
},
|
||||||
|
power_preference: PowerPreference = .undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const BufferDescriptorErrorInfoFromWireClient = extern struct {
|
||||||
|
chain: ChainedStruct = .{
|
||||||
|
.next = null,
|
||||||
|
.s_type = .dawn_buffer_descriptor_error_info_from_wire_client,
|
||||||
|
},
|
||||||
|
out_of_memory: Bool32 = .false,
|
||||||
|
};
|
||||||
1270
src/gpu/dawn_impl.zig
Normal file
1270
src/gpu/dawn_impl.zig
Normal file
File diff suppressed because it is too large
Load diff
368
src/gpu/device.zig
Normal file
368
src/gpu/device.zig
Normal file
|
|
@ -0,0 +1,368 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const Adapter = @import("adapter.zig").Adapter;
|
||||||
|
const Queue = @import("queue.zig").Queue;
|
||||||
|
const BindGroup = @import("bind_group.zig").BindGroup;
|
||||||
|
const BindGroupLayout = @import("bind_group_layout.zig").BindGroupLayout;
|
||||||
|
const Buffer = @import("buffer.zig").Buffer;
|
||||||
|
const CommandEncoder = @import("command_encoder.zig").CommandEncoder;
|
||||||
|
const ComputePipeline = @import("compute_pipeline.zig").ComputePipeline;
|
||||||
|
const ExternalTexture = @import("external_texture.zig").ExternalTexture;
|
||||||
|
const PipelineLayout = @import("pipeline_layout.zig").PipelineLayout;
|
||||||
|
const QuerySet = @import("query_set.zig").QuerySet;
|
||||||
|
const RenderBundleEncoder = @import("render_bundle_encoder.zig").RenderBundleEncoder;
|
||||||
|
const RenderPipeline = @import("render_pipeline.zig").RenderPipeline;
|
||||||
|
const Sampler = @import("sampler.zig").Sampler;
|
||||||
|
const ShaderModule = @import("shader_module.zig").ShaderModule;
|
||||||
|
const Surface = @import("surface.zig").Surface;
|
||||||
|
const SwapChain = @import("swap_chain.zig").SwapChain;
|
||||||
|
const Texture = @import("texture.zig").Texture;
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const FeatureName = @import("main.zig").FeatureName;
|
||||||
|
const RequiredLimits = @import("main.zig").RequiredLimits;
|
||||||
|
const SupportedLimits = @import("main.zig").SupportedLimits;
|
||||||
|
const ErrorType = @import("main.zig").ErrorType;
|
||||||
|
const ErrorFilter = @import("main.zig").ErrorFilter;
|
||||||
|
const LoggingType = @import("main.zig").LoggingType;
|
||||||
|
const CreatePipelineAsyncStatus = @import("main.zig").CreatePipelineAsyncStatus;
|
||||||
|
const LoggingCallback = @import("main.zig").LoggingCallback;
|
||||||
|
const ErrorCallback = @import("main.zig").ErrorCallback;
|
||||||
|
const CreateComputePipelineAsyncCallback = @import("main.zig").CreateComputePipelineAsyncCallback;
|
||||||
|
const CreateRenderPipelineAsyncCallback = @import("main.zig").CreateRenderPipelineAsyncCallback;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
const dawn = @import("dawn.zig");
|
||||||
|
|
||||||
|
pub const Device = opaque {
|
||||||
|
pub const LostCallback = *const fn (
|
||||||
|
reason: LostReason,
|
||||||
|
message: [*:0]const u8,
|
||||||
|
userdata: ?*anyopaque,
|
||||||
|
) callconv(.C) void;
|
||||||
|
|
||||||
|
pub const LostReason = enum(u32) {
|
||||||
|
undefined = 0x00000000,
|
||||||
|
destroyed = 0x00000001,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
pub const NextInChain = extern union {
|
||||||
|
generic: ?*const ChainedStruct,
|
||||||
|
dawn_toggles_descriptor: *const dawn.TogglesDescriptor,
|
||||||
|
dawn_cache_device_descriptor: *const dawn.CacheDeviceDescriptor,
|
||||||
|
};
|
||||||
|
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
required_features_count: usize = 0,
|
||||||
|
required_features: ?[*]const FeatureName = null,
|
||||||
|
required_limits: ?*const RequiredLimits = null,
|
||||||
|
default_queue: Queue.Descriptor = Queue.Descriptor{},
|
||||||
|
device_lost_callback: LostCallback,
|
||||||
|
device_lost_userdata: ?*anyopaque,
|
||||||
|
|
||||||
|
/// Provides a slightly friendlier Zig API to initialize this structure.
|
||||||
|
pub inline fn init(v: struct {
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
required_features: ?[]const FeatureName = null,
|
||||||
|
required_limits: ?*const RequiredLimits = null,
|
||||||
|
default_queue: Queue.Descriptor = Queue.Descriptor{},
|
||||||
|
}) Descriptor {
|
||||||
|
return .{
|
||||||
|
.next_in_chain = v.next_in_chain,
|
||||||
|
.label = v.label,
|
||||||
|
.required_features_count = if (v.required_features) |e| e.len else 0,
|
||||||
|
.required_features = if (v.required_features) |e| e.ptr else null,
|
||||||
|
.default_queue = v.default_queue,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn createBindGroup(device: *Device, descriptor: *const BindGroup.Descriptor) *BindGroup {
|
||||||
|
return Impl.deviceCreateBindGroup(device, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createBindGroupLayout(device: *Device, descriptor: *const BindGroupLayout.Descriptor) *BindGroupLayout {
|
||||||
|
return Impl.deviceCreateBindGroupLayout(device, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createBuffer(device: *Device, descriptor: *const Buffer.Descriptor) *Buffer {
|
||||||
|
return Impl.deviceCreateBuffer(device, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createCommandEncoder(device: *Device, descriptor: ?*const CommandEncoder.Descriptor) *CommandEncoder {
|
||||||
|
return Impl.deviceCreateCommandEncoder(device, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createComputePipeline(device: *Device, descriptor: *const ComputePipeline.Descriptor) *ComputePipeline {
|
||||||
|
return Impl.deviceCreateComputePipeline(device, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createComputePipelineAsync(
|
||||||
|
device: *Device,
|
||||||
|
descriptor: *const ComputePipeline.Descriptor,
|
||||||
|
context: anytype,
|
||||||
|
comptime callback: fn (
|
||||||
|
status: CreatePipelineAsyncStatus,
|
||||||
|
compute_pipeline: ?*ComputePipeline,
|
||||||
|
message: ?[*:0]const u8,
|
||||||
|
ctx: @TypeOf(context),
|
||||||
|
) callconv(.Inline) void,
|
||||||
|
) void {
|
||||||
|
const Context = @TypeOf(context);
|
||||||
|
const Helper = struct {
|
||||||
|
pub fn cCallback(
|
||||||
|
status: CreatePipelineAsyncStatus,
|
||||||
|
compute_pipeline: ?*ComputePipeline,
|
||||||
|
message: ?[*:0]const u8,
|
||||||
|
userdata: ?*anyopaque,
|
||||||
|
) callconv(.C) void {
|
||||||
|
callback(
|
||||||
|
status,
|
||||||
|
compute_pipeline,
|
||||||
|
message,
|
||||||
|
if (Context == void) {} else @as(Context, @ptrCast(@alignCast(userdata))),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Impl.deviceCreateComputePipelineAsync(device, descriptor, Helper.cCallback, if (Context == void) null else context);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createErrorBuffer(device: *Device, descriptor: *const Buffer.Descriptor) *Buffer {
|
||||||
|
return Impl.deviceCreateErrorBuffer(device, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createErrorExternalTexture(device: *Device) *ExternalTexture {
|
||||||
|
return Impl.deviceCreateErrorExternalTexture(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createErrorTexture(device: *Device, descriptor: *const Texture.Descriptor) *Texture {
|
||||||
|
return Impl.deviceCreateErrorTexture(device, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createExternalTexture(device: *Device, external_texture_descriptor: *const ExternalTexture.Descriptor) *ExternalTexture {
|
||||||
|
return Impl.deviceCreateExternalTexture(device, external_texture_descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createPipelineLayout(device: *Device, pipeline_layout_descriptor: *const PipelineLayout.Descriptor) *PipelineLayout {
|
||||||
|
return Impl.deviceCreatePipelineLayout(device, pipeline_layout_descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createQuerySet(device: *Device, descriptor: *const QuerySet.Descriptor) *QuerySet {
|
||||||
|
return Impl.deviceCreateQuerySet(device, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createRenderBundleEncoder(device: *Device, descriptor: *const RenderBundleEncoder.Descriptor) *RenderBundleEncoder {
|
||||||
|
return Impl.deviceCreateRenderBundleEncoder(device, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createRenderPipeline(device: *Device, descriptor: *const RenderPipeline.Descriptor) *RenderPipeline {
|
||||||
|
return Impl.deviceCreateRenderPipeline(device, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createRenderPipelineAsync(
|
||||||
|
device: *Device,
|
||||||
|
descriptor: *const RenderPipeline.Descriptor,
|
||||||
|
context: anytype,
|
||||||
|
comptime callback: fn (
|
||||||
|
ctx: @TypeOf(context),
|
||||||
|
status: CreatePipelineAsyncStatus,
|
||||||
|
pipeline: ?*RenderPipeline,
|
||||||
|
message: ?[*:0]const u8,
|
||||||
|
) callconv(.Inline) void,
|
||||||
|
) void {
|
||||||
|
const Context = @TypeOf(context);
|
||||||
|
const Helper = struct {
|
||||||
|
pub fn cCallback(
|
||||||
|
status: CreatePipelineAsyncStatus,
|
||||||
|
pipeline: ?*RenderPipeline,
|
||||||
|
message: ?[*:0]const u8,
|
||||||
|
userdata: ?*anyopaque,
|
||||||
|
) callconv(.C) void {
|
||||||
|
callback(
|
||||||
|
if (Context == void) {} else @as(Context, @ptrCast(@alignCast(userdata))),
|
||||||
|
status,
|
||||||
|
pipeline,
|
||||||
|
message,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Impl.deviceCreateRenderPipelineAsync(device, descriptor, Helper.cCallback, if (Context == void) null else context);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createSampler(device: *Device, descriptor: ?*const Sampler.Descriptor) *Sampler {
|
||||||
|
return Impl.deviceCreateSampler(device, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createShaderModule(device: *Device, descriptor: *const ShaderModule.Descriptor) *ShaderModule {
|
||||||
|
return Impl.deviceCreateShaderModule(device, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper to make createShaderModule invocations slightly nicer.
|
||||||
|
pub inline fn createShaderModuleWGSL(
|
||||||
|
device: *Device,
|
||||||
|
label: ?[*:0]const u8,
|
||||||
|
wgsl_code: [*:0]const u8,
|
||||||
|
) *ShaderModule {
|
||||||
|
return device.createShaderModule(&ShaderModule.Descriptor{
|
||||||
|
.next_in_chain = .{ .wgsl_descriptor = &.{
|
||||||
|
.code = wgsl_code,
|
||||||
|
} },
|
||||||
|
.label = label,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createSwapChain(device: *Device, surface: ?*Surface, descriptor: *const SwapChain.Descriptor) *SwapChain {
|
||||||
|
return Impl.deviceCreateSwapChain(device, surface, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn createTexture(device: *Device, descriptor: *const Texture.Descriptor) *Texture {
|
||||||
|
return Impl.deviceCreateTexture(device, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn destroy(device: *Device) void {
|
||||||
|
Impl.deviceDestroy(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Call once with null to determine the array length, and again to fetch the feature list.
|
||||||
|
///
|
||||||
|
/// Consider using the enumerateFeaturesOwned helper.
|
||||||
|
pub inline fn enumerateFeatures(device: *Device, features: ?[*]FeatureName) usize {
|
||||||
|
return Impl.deviceEnumerateFeatures(device, features);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enumerates the adapter features, storing the result in an allocated slice which is owned by
|
||||||
|
/// the caller.
|
||||||
|
pub inline fn enumerateFeaturesOwned(device: *Device, allocator: std.mem.Allocator) ![]FeatureName {
|
||||||
|
const count = device.enumerateFeatures(null);
|
||||||
|
const data = try allocator.alloc(FeatureName, count);
|
||||||
|
_ = device.enumerateFeatures(data.ptr);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn forceLoss(device: *Device, reason: LostReason, message: [*:0]const u8) void {
|
||||||
|
return Impl.deviceForceLoss(device, reason, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getAdapter(device: *Device) *Adapter {
|
||||||
|
return Impl.deviceGetAdapter(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getLimits(device: *Device, limits: *SupportedLimits) bool {
|
||||||
|
return Impl.deviceGetLimits(device, limits) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getQueue(device: *Device) *Queue {
|
||||||
|
return Impl.deviceGetQueue(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn hasFeature(device: *Device, feature: FeatureName) bool {
|
||||||
|
return Impl.deviceHasFeature(device, feature) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn injectError(device: *Device, typ: ErrorType, message: [*:0]const u8) void {
|
||||||
|
Impl.deviceInjectError(device, typ, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn popErrorScope(
|
||||||
|
device: *Device,
|
||||||
|
context: anytype,
|
||||||
|
comptime callback: fn (ctx: @TypeOf(context), typ: ErrorType, message: [*:0]const u8) callconv(.Inline) void,
|
||||||
|
) void {
|
||||||
|
const Context = @TypeOf(context);
|
||||||
|
const Helper = struct {
|
||||||
|
pub fn cCallback(typ: ErrorType, message: [*:0]const u8, userdata: ?*anyopaque) callconv(.C) void {
|
||||||
|
callback(if (Context == void) {} else @as(Context, @ptrCast(@alignCast(userdata))), typ, message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Impl.devicePopErrorScope(device, Helper.cCallback, if (Context == void) null else context);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn pushErrorScope(device: *Device, filter: ErrorFilter) void {
|
||||||
|
Impl.devicePushErrorScope(device, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setDeviceLostCallback(
|
||||||
|
device: *Device,
|
||||||
|
context: anytype,
|
||||||
|
comptime callback: ?fn (ctx: @TypeOf(context), reason: LostReason, message: [*:0]const u8) callconv(.Inline) void,
|
||||||
|
) void {
|
||||||
|
if (callback) |cb| {
|
||||||
|
const Context = @TypeOf(context);
|
||||||
|
const Helper = struct {
|
||||||
|
pub fn cCallback(reason: LostReason, message: [*:0]const u8, userdata: ?*anyopaque) callconv(.C) void {
|
||||||
|
cb(if (Context == void) {} else @as(Context, @ptrCast(@alignCast(userdata))), reason, message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Impl.deviceSetDeviceLostCallback(device, Helper.cCallback, if (Context == void) null else context);
|
||||||
|
} else {
|
||||||
|
Impl.deviceSetDeviceLostCallback(device, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setLabel(device: *Device, label: [*:0]const u8) void {
|
||||||
|
Impl.deviceSetLabel(device, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setLoggingCallback(
|
||||||
|
device: *Device,
|
||||||
|
context: anytype,
|
||||||
|
comptime callback: ?fn (ctx: @TypeOf(context), typ: LoggingType, message: [*:0]const u8) callconv(.Inline) void,
|
||||||
|
) void {
|
||||||
|
if (callback) |cb| {
|
||||||
|
const Context = @TypeOf(context);
|
||||||
|
const Helper = struct {
|
||||||
|
pub fn cCallback(typ: LoggingType, message: [*:0]const u8, userdata: ?*anyopaque) callconv(.C) void {
|
||||||
|
cb(if (Context == void) {} else @as(Context, @ptrCast(@alignCast(userdata))), typ, message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Impl.deviceSetLoggingCallback(device, Helper.cCallback, if (Context == void) null else context);
|
||||||
|
} else {
|
||||||
|
Impl.deviceSetLoggingCallback(device, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setUncapturedErrorCallback(
|
||||||
|
device: *Device,
|
||||||
|
context: anytype,
|
||||||
|
comptime callback: ?fn (ctx: @TypeOf(context), typ: ErrorType, message: [*:0]const u8) callconv(.Inline) void,
|
||||||
|
) void {
|
||||||
|
if (callback) |cb| {
|
||||||
|
const Context = @TypeOf(context);
|
||||||
|
const Helper = struct {
|
||||||
|
pub fn cCallback(typ: ErrorType, message: [*:0]const u8, userdata: ?*anyopaque) callconv(.C) void {
|
||||||
|
cb(if (Context == void) {} else @as(Context, @ptrCast(@alignCast(userdata))), typ, message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Impl.deviceSetUncapturedErrorCallback(device, Helper.cCallback, if (Context == void) null else context);
|
||||||
|
} else {
|
||||||
|
Impl.deviceSetUncapturedErrorCallback(device, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn tick(device: *Device) void {
|
||||||
|
Impl.deviceTick(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mach WebGPU extension. Supported with mach-gpu-dawn.
|
||||||
|
//
|
||||||
|
// When making Metal interop with other APIs, we need to be careful that QueueSubmit doesn't
|
||||||
|
// mean that the operations will be visible to other APIs/Metal devices right away. macOS
|
||||||
|
// does have a global queue of graphics operations, but the command buffers are inserted there
|
||||||
|
// when they are "scheduled". Submitting other operations before the command buffer is
|
||||||
|
// scheduled could lead to races in who gets scheduled first and incorrect rendering.
|
||||||
|
pub inline fn machWaitForCommandsToBeScheduled(device: *Device) void {
|
||||||
|
Impl.machDeviceWaitForCommandsToBeScheduled(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn validateTextureDescriptor(device: *Device, descriptor: *const Texture.Descriptor) void {
|
||||||
|
Impl.deviceVlidateTextureDescriptor(device, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(device: *Device) void {
|
||||||
|
Impl.deviceReference(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(device: *Device) void {
|
||||||
|
Impl.deviceRelease(device);
|
||||||
|
}
|
||||||
|
};
|
||||||
245
src/gpu/example/main.zig
Normal file
245
src/gpu/example/main.zig
Normal file
|
|
@ -0,0 +1,245 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const util = @import("util.zig");
|
||||||
|
const glfw = @import("mach-glfw");
|
||||||
|
const gpu = @import("mach").gpu;
|
||||||
|
|
||||||
|
pub const GPUInterface = gpu.dawn.Interface;
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
|
var allocator = gpa.allocator();
|
||||||
|
|
||||||
|
try gpu.Impl.init(allocator, .{});
|
||||||
|
const setup = try setupWindow(allocator);
|
||||||
|
const framebuffer_size = setup.window.getFramebufferSize();
|
||||||
|
|
||||||
|
const window_data = try allocator.create(WindowData);
|
||||||
|
window_data.* = .{
|
||||||
|
.surface = setup.surface,
|
||||||
|
.swap_chain = null,
|
||||||
|
.swap_chain_format = undefined,
|
||||||
|
.current_desc = undefined,
|
||||||
|
.target_desc = undefined,
|
||||||
|
};
|
||||||
|
setup.window.setUserPointer(window_data);
|
||||||
|
|
||||||
|
window_data.swap_chain_format = .bgra8_unorm;
|
||||||
|
const descriptor = gpu.SwapChain.Descriptor{
|
||||||
|
.label = "basic swap chain",
|
||||||
|
.usage = .{ .render_attachment = true },
|
||||||
|
.format = window_data.swap_chain_format,
|
||||||
|
.width = framebuffer_size.width,
|
||||||
|
.height = framebuffer_size.height,
|
||||||
|
.present_mode = .fifo,
|
||||||
|
};
|
||||||
|
|
||||||
|
window_data.current_desc = descriptor;
|
||||||
|
window_data.target_desc = descriptor;
|
||||||
|
|
||||||
|
const vs =
|
||||||
|
\\ @vertex fn main(
|
||||||
|
\\ @builtin(vertex_index) VertexIndex : u32
|
||||||
|
\\ ) -> @builtin(position) vec4<f32> {
|
||||||
|
\\ var pos = array<vec2<f32>, 3>(
|
||||||
|
\\ vec2<f32>( 0.0, 0.5),
|
||||||
|
\\ vec2<f32>(-0.5, -0.5),
|
||||||
|
\\ vec2<f32>( 0.5, -0.5)
|
||||||
|
\\ );
|
||||||
|
\\ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
|
||||||
|
\\ }
|
||||||
|
;
|
||||||
|
const vs_module = setup.device.createShaderModuleWGSL("my vertex shader", vs);
|
||||||
|
|
||||||
|
const fs =
|
||||||
|
\\ @fragment fn main() -> @location(0) vec4<f32> {
|
||||||
|
\\ return vec4<f32>(1.0, 0.0, 0.0, 1.0);
|
||||||
|
\\ }
|
||||||
|
;
|
||||||
|
const fs_module = setup.device.createShaderModuleWGSL("my fragment shader", fs);
|
||||||
|
|
||||||
|
// Fragment state
|
||||||
|
const blend = gpu.BlendState{
|
||||||
|
.color = .{
|
||||||
|
.dst_factor = .one,
|
||||||
|
},
|
||||||
|
.alpha = .{
|
||||||
|
.dst_factor = .one,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const color_target = gpu.ColorTargetState{
|
||||||
|
.format = window_data.swap_chain_format,
|
||||||
|
.blend = &blend,
|
||||||
|
.write_mask = gpu.ColorWriteMaskFlags.all,
|
||||||
|
};
|
||||||
|
const fragment = gpu.FragmentState.init(.{
|
||||||
|
.module = fs_module,
|
||||||
|
.entry_point = "main",
|
||||||
|
.targets = &.{color_target},
|
||||||
|
});
|
||||||
|
const pipeline_descriptor = gpu.RenderPipeline.Descriptor{
|
||||||
|
.fragment = &fragment,
|
||||||
|
.layout = null,
|
||||||
|
.depth_stencil = null,
|
||||||
|
.vertex = gpu.VertexState{
|
||||||
|
.module = vs_module,
|
||||||
|
.entry_point = "main",
|
||||||
|
},
|
||||||
|
.multisample = .{},
|
||||||
|
.primitive = .{},
|
||||||
|
};
|
||||||
|
const pipeline = setup.device.createRenderPipeline(&pipeline_descriptor);
|
||||||
|
|
||||||
|
vs_module.release();
|
||||||
|
fs_module.release();
|
||||||
|
|
||||||
|
// Reconfigure the swap chain with the new framebuffer width/height, otherwise e.g. the Vulkan
|
||||||
|
// device would be lost after a resize.
|
||||||
|
setup.window.setFramebufferSizeCallback((struct {
|
||||||
|
fn callback(window: glfw.Window, width: u32, height: u32) void {
|
||||||
|
const pl = window.getUserPointer(WindowData);
|
||||||
|
pl.?.target_desc.width = width;
|
||||||
|
pl.?.target_desc.height = height;
|
||||||
|
}
|
||||||
|
}).callback);
|
||||||
|
|
||||||
|
const queue = setup.device.getQueue();
|
||||||
|
while (!setup.window.shouldClose()) {
|
||||||
|
try frame(.{
|
||||||
|
.window = setup.window,
|
||||||
|
.device = setup.device,
|
||||||
|
.pipeline = pipeline,
|
||||||
|
.queue = queue,
|
||||||
|
});
|
||||||
|
std.time.sleep(16 * std.time.ns_per_ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const WindowData = struct {
|
||||||
|
surface: ?*gpu.Surface,
|
||||||
|
swap_chain: ?*gpu.SwapChain,
|
||||||
|
swap_chain_format: gpu.Texture.Format,
|
||||||
|
current_desc: gpu.SwapChain.Descriptor,
|
||||||
|
target_desc: gpu.SwapChain.Descriptor,
|
||||||
|
};
|
||||||
|
|
||||||
|
const FrameParams = struct {
|
||||||
|
window: glfw.Window,
|
||||||
|
device: *gpu.Device,
|
||||||
|
pipeline: *gpu.RenderPipeline,
|
||||||
|
queue: *gpu.Queue,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn frame(params: FrameParams) !void {
|
||||||
|
glfw.pollEvents();
|
||||||
|
params.device.tick();
|
||||||
|
const pl = params.window.getUserPointer(WindowData).?;
|
||||||
|
if (pl.swap_chain == null or !std.meta.eql(pl.current_desc, pl.target_desc)) {
|
||||||
|
pl.swap_chain = params.device.createSwapChain(pl.surface, &pl.target_desc);
|
||||||
|
pl.current_desc = pl.target_desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
const back_buffer_view = pl.swap_chain.?.getCurrentTextureView().?;
|
||||||
|
const color_attachment = gpu.RenderPassColorAttachment{
|
||||||
|
.view = back_buffer_view,
|
||||||
|
.resolve_target = null,
|
||||||
|
.clear_value = std.mem.zeroes(gpu.Color),
|
||||||
|
.load_op = .clear,
|
||||||
|
.store_op = .store,
|
||||||
|
};
|
||||||
|
|
||||||
|
const encoder = params.device.createCommandEncoder(null);
|
||||||
|
const render_pass_info = gpu.RenderPassDescriptor.init(.{
|
||||||
|
.color_attachments = &.{color_attachment},
|
||||||
|
});
|
||||||
|
const pass = encoder.beginRenderPass(&render_pass_info);
|
||||||
|
pass.setPipeline(params.pipeline);
|
||||||
|
pass.draw(3, 1, 0, 0);
|
||||||
|
pass.end();
|
||||||
|
pass.release();
|
||||||
|
|
||||||
|
var command = encoder.finish(null);
|
||||||
|
encoder.release();
|
||||||
|
|
||||||
|
params.queue.submit(&[_]*gpu.CommandBuffer{command});
|
||||||
|
command.release();
|
||||||
|
pl.swap_chain.?.present();
|
||||||
|
back_buffer_view.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Setup = struct {
|
||||||
|
instance: *gpu.Instance,
|
||||||
|
adapter: *gpu.Adapter,
|
||||||
|
device: *gpu.Device,
|
||||||
|
window: glfw.Window,
|
||||||
|
surface: *gpu.Surface,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Default GLFW error handling callback
|
||||||
|
fn errorCallback(error_code: glfw.ErrorCode, description: [:0]const u8) void {
|
||||||
|
std.log.err("glfw: {}: {s}\n", .{ error_code, description });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setupWindow(allocator: std.mem.Allocator) !Setup {
|
||||||
|
const backend_type = try util.detectBackendType(allocator);
|
||||||
|
|
||||||
|
glfw.setErrorCallback(errorCallback);
|
||||||
|
if (!glfw.init(.{})) {
|
||||||
|
std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()});
|
||||||
|
std.process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the test window and discover adapters using it (esp. for OpenGL)
|
||||||
|
var hints = util.glfwWindowHintsForBackend(backend_type);
|
||||||
|
hints.cocoa_retina_framebuffer = true;
|
||||||
|
const window = glfw.Window.create(640, 480, "mach/gpu window", null, null, hints) orelse {
|
||||||
|
std.log.err("failed to create GLFW window: {?s}", .{glfw.getErrorString()});
|
||||||
|
std.process.exit(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (backend_type == .opengl) glfw.makeContextCurrent(window);
|
||||||
|
if (backend_type == .opengles) glfw.makeContextCurrent(window);
|
||||||
|
|
||||||
|
const instance = gpu.createInstance(null);
|
||||||
|
if (instance == null) {
|
||||||
|
std.debug.print("failed to create GPU instance\n", .{});
|
||||||
|
std.process.exit(1);
|
||||||
|
}
|
||||||
|
const surface = try util.createSurfaceForWindow(instance.?, window, comptime util.detectGLFWOptions());
|
||||||
|
|
||||||
|
var response: util.RequestAdapterResponse = undefined;
|
||||||
|
instance.?.requestAdapter(&gpu.RequestAdapterOptions{
|
||||||
|
.compatible_surface = surface,
|
||||||
|
.power_preference = .undefined,
|
||||||
|
.force_fallback_adapter = .false,
|
||||||
|
}, &response, util.requestAdapterCallback);
|
||||||
|
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 = std.mem.zeroes(gpu.Adapter.Properties);
|
||||||
|
response.adapter.?.getProperties(&props);
|
||||||
|
std.debug.print("found {s} backend on {s} adapter: {s}, {s}\n", .{
|
||||||
|
props.backend_type.name(),
|
||||||
|
props.adapter_type.name(),
|
||||||
|
props.name,
|
||||||
|
props.driver_description,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a device with default limits/features.
|
||||||
|
const device = response.adapter.?.createDevice(null);
|
||||||
|
if (device == null) {
|
||||||
|
std.debug.print("failed to create GPU device\n", .{});
|
||||||
|
std.process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
device.?.setUncapturedErrorCallback({}, util.printUnhandledErrorCallback);
|
||||||
|
return Setup{
|
||||||
|
.instance = instance.?,
|
||||||
|
.adapter = response.adapter.?,
|
||||||
|
.device = device.?,
|
||||||
|
.window = window,
|
||||||
|
.surface = surface,
|
||||||
|
};
|
||||||
|
}
|
||||||
7
src/gpu/example/objc_message.zig
Normal file
7
src/gpu/example/objc_message.zig
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
// Extracted from `zig translate-c tmp.c` with `#include <objc/message.h>` in the file.
|
||||||
|
pub const SEL = opaque {};
|
||||||
|
pub const Class = opaque {};
|
||||||
|
|
||||||
|
pub extern fn sel_getUid(str: [*c]const u8) ?*SEL;
|
||||||
|
pub extern fn objc_getClass(name: [*c]const u8) ?*Class;
|
||||||
|
pub extern fn objc_msgSend() void;
|
||||||
201
src/gpu/example/util.zig
Normal file
201
src/gpu/example/util.zig
Normal file
|
|
@ -0,0 +1,201 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const glfw = @import("mach-glfw");
|
||||||
|
const gpu = @import("mach").gpu;
|
||||||
|
const objc = @import("objc_message.zig");
|
||||||
|
|
||||||
|
pub inline fn printUnhandledErrorCallback(_: void, typ: gpu.ErrorType, message: [*:0]const u8) void {
|
||||||
|
switch (typ) {
|
||||||
|
.validation => std.log.err("gpu: validation error: {s}\n", .{message}),
|
||||||
|
.out_of_memory => std.log.err("gpu: out of memory: {s}\n", .{message}),
|
||||||
|
.device_lost => std.log.err("gpu: device lost: {s}\n", .{message}),
|
||||||
|
.unknown => std.log.err("gpu: unknown error: {s}\n", .{message}),
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
std.os.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getEnvVarOwned(allocator: std.mem.Allocator, key: []const u8) error{ OutOfMemory, InvalidUtf8, InvalidWtf8 }!?[]u8 {
|
||||||
|
return std.process.getEnvVarOwned(allocator, key) catch |err| switch (err) {
|
||||||
|
error.EnvironmentVariableNotFound => @as(?[]u8, null),
|
||||||
|
else => |e| e,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn detectBackendType(allocator: std.mem.Allocator) !gpu.BackendType {
|
||||||
|
const MACH_GPU_BACKEND = try getEnvVarOwned(allocator, "MACH_GPU_BACKEND");
|
||||||
|
if (MACH_GPU_BACKEND) |backend| {
|
||||||
|
defer allocator.free(backend);
|
||||||
|
if (std.ascii.eqlIgnoreCase(backend, "null")) return .null;
|
||||||
|
if (std.ascii.eqlIgnoreCase(backend, "d3d11")) return .d3d11;
|
||||||
|
if (std.ascii.eqlIgnoreCase(backend, "d3d12")) return .d3d12;
|
||||||
|
if (std.ascii.eqlIgnoreCase(backend, "metal")) return .metal;
|
||||||
|
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 MACH_GPU_BACKEND type");
|
||||||
|
}
|
||||||
|
|
||||||
|
const target = @import("builtin").target;
|
||||||
|
if (target.isDarwin()) return .metal;
|
||||||
|
if (target.os.tag == .windows) return .d3d12;
|
||||||
|
return .vulkan;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const RequestAdapterResponse = struct {
|
||||||
|
status: gpu.RequestAdapterStatus,
|
||||||
|
adapter: ?*gpu.Adapter,
|
||||||
|
message: ?[*:0]const u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn requestAdapterCallback(
|
||||||
|
context: *RequestAdapterResponse,
|
||||||
|
status: gpu.RequestAdapterStatus,
|
||||||
|
adapter: ?*gpu.Adapter,
|
||||||
|
message: ?[*:0]const u8,
|
||||||
|
) void {
|
||||||
|
context.* = RequestAdapterResponse{
|
||||||
|
.status = status,
|
||||||
|
.adapter = adapter,
|
||||||
|
.message = message,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn glfwWindowHintsForBackend(backend: gpu.BackendType) glfw.Window.Hints {
|
||||||
|
return switch (backend) {
|
||||||
|
.opengl => .{
|
||||||
|
// Ask for OpenGL 4.4 which is what the GL backend requires for compute shaders and
|
||||||
|
// texture views.
|
||||||
|
.context_version_major = 4,
|
||||||
|
.context_version_minor = 4,
|
||||||
|
.opengl_forward_compat = true,
|
||||||
|
.opengl_profile = .opengl_core_profile,
|
||||||
|
},
|
||||||
|
.opengles => .{
|
||||||
|
.context_version_major = 3,
|
||||||
|
.context_version_minor = 1,
|
||||||
|
.client_api = .opengl_es_api,
|
||||||
|
.context_creation_api = .egl_context_api,
|
||||||
|
},
|
||||||
|
else => .{
|
||||||
|
// Without this GLFW will initialize a GL context on the window, which prevents using
|
||||||
|
// the window with other APIs (by crashing in weird ways).
|
||||||
|
.client_api = .no_api,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn detectGLFWOptions() glfw.BackendOptions {
|
||||||
|
const target = @import("builtin").target;
|
||||||
|
if (target.isDarwin()) return .{ .cocoa = true };
|
||||||
|
return switch (target.os.tag) {
|
||||||
|
.windows => .{ .win32 = true },
|
||||||
|
.linux => .{ .x11 = true, .wayland = true },
|
||||||
|
else => .{},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn createSurfaceForWindow(
|
||||||
|
instance: *gpu.Instance,
|
||||||
|
window: glfw.Window,
|
||||||
|
comptime glfw_options: glfw.BackendOptions,
|
||||||
|
) !*gpu.Surface {
|
||||||
|
const glfw_native = glfw.Native(glfw_options);
|
||||||
|
if (glfw_options.win32) {
|
||||||
|
return instance.createSurface(&gpu.Surface.Descriptor{
|
||||||
|
.next_in_chain = .{
|
||||||
|
.from_windows_hwnd = &.{
|
||||||
|
.hinstance = std.os.windows.kernel32.GetModuleHandleW(null).?,
|
||||||
|
.hwnd = glfw_native.getWin32Window(window),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else if (glfw_options.x11) {
|
||||||
|
return instance.createSurface(&gpu.Surface.Descriptor{
|
||||||
|
.next_in_chain = .{
|
||||||
|
.from_xlib_window = &.{
|
||||||
|
.display = glfw_native.getX11Display(),
|
||||||
|
.window = glfw_native.getX11Window(window),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else if (glfw_options.wayland) {
|
||||||
|
return instance.createSurface(&gpu.Surface.Descriptor{
|
||||||
|
.next_in_chain = .{
|
||||||
|
.from_wayland_surface = &.{
|
||||||
|
.display = glfw_native.getWaylandDisplay(),
|
||||||
|
.surface = glfw_native.getWaylandWindow(window),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else if (glfw_options.cocoa) {
|
||||||
|
const pool = try AutoReleasePool.init();
|
||||||
|
defer AutoReleasePool.release(pool);
|
||||||
|
|
||||||
|
const ns_window = glfw_native.getCocoaWindow(window);
|
||||||
|
const ns_view = msgSend(ns_window, "contentView", .{}, *anyopaque); // [nsWindow contentView]
|
||||||
|
|
||||||
|
// Create a CAMetalLayer that covers the whole window that will be passed to CreateSurface.
|
||||||
|
msgSend(ns_view, "setWantsLayer:", .{true}, void); // [view setWantsLayer:YES]
|
||||||
|
const layer = msgSend(objc.objc_getClass("CAMetalLayer"), "layer", .{}, ?*anyopaque); // [CAMetalLayer layer]
|
||||||
|
if (layer == null) @panic("failed to create Metal layer");
|
||||||
|
msgSend(ns_view, "setLayer:", .{layer.?}, void); // [view setLayer:layer]
|
||||||
|
|
||||||
|
// Use retina if the window was created with retina support.
|
||||||
|
const scale_factor = msgSend(ns_window, "backingScaleFactor", .{}, f64); // [ns_window backingScaleFactor]
|
||||||
|
msgSend(layer.?, "setContentsScale:", .{scale_factor}, void); // [layer setContentsScale:scale_factor]
|
||||||
|
|
||||||
|
return instance.createSurface(&gpu.Surface.Descriptor{
|
||||||
|
.next_in_chain = .{
|
||||||
|
.from_metal_layer = &.{ .layer = layer.? },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const AutoReleasePool = if (!@import("builtin").target.isDarwin()) opaque {
|
||||||
|
pub fn init() error{OutOfMemory}!?*AutoReleasePool {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn release(pool: ?*AutoReleasePool) void {
|
||||||
|
_ = pool;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else opaque {
|
||||||
|
pub fn init() error{OutOfMemory}!?*AutoReleasePool {
|
||||||
|
// pool = [NSAutoreleasePool alloc];
|
||||||
|
var pool = msgSend(objc.objc_getClass("NSAutoreleasePool"), "alloc", .{}, ?*AutoReleasePool);
|
||||||
|
if (pool == null) return error.OutOfMemory;
|
||||||
|
|
||||||
|
// pool = [pool init];
|
||||||
|
pool = msgSend(pool, "init", .{}, ?*AutoReleasePool);
|
||||||
|
if (pool == null) unreachable;
|
||||||
|
|
||||||
|
return pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn release(pool: ?*AutoReleasePool) void {
|
||||||
|
// [pool release];
|
||||||
|
msgSend(pool, "release", .{}, void);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Borrowed from https://github.com/hazeycode/zig-objcrt
|
||||||
|
pub fn msgSend(obj: anytype, sel_name: [:0]const u8, args: anytype, comptime ReturnType: type) ReturnType {
|
||||||
|
const args_meta = @typeInfo(@TypeOf(args)).Struct.fields;
|
||||||
|
|
||||||
|
const FnType = switch (args_meta.len) {
|
||||||
|
0 => *const fn (@TypeOf(obj), ?*objc.SEL) callconv(.C) ReturnType,
|
||||||
|
1 => *const fn (@TypeOf(obj), ?*objc.SEL, args_meta[0].type) callconv(.C) ReturnType,
|
||||||
|
2 => *const fn (@TypeOf(obj), ?*objc.SEL, args_meta[0].type, args_meta[1].type) callconv(.C) ReturnType,
|
||||||
|
3 => *const fn (@TypeOf(obj), ?*objc.SEL, args_meta[0].type, args_meta[1].type, args_meta[2].type) callconv(.C) ReturnType,
|
||||||
|
4 => *const fn (@TypeOf(obj), ?*objc.SEL, args_meta[0].type, args_meta[1].type, args_meta[2].type, args_meta[3].type) callconv(.C) ReturnType,
|
||||||
|
else => @compileError("Unsupported number of args"),
|
||||||
|
};
|
||||||
|
|
||||||
|
const func = @as(FnType, @ptrCast(&objc.objc_msgSend));
|
||||||
|
const sel = objc.sel_getUid(@as([*c]const u8, @ptrCast(sel_name)));
|
||||||
|
|
||||||
|
return @call(.auto, func, .{ obj, sel } ++ args);
|
||||||
|
}
|
||||||
56
src/gpu/external_texture.zig
Normal file
56
src/gpu/external_texture.zig
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
const Bool32 = @import("main.zig").Bool32;
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const TextureView = @import("texture_view.zig").TextureView;
|
||||||
|
const Origin2D = @import("main.zig").Origin2D;
|
||||||
|
const Extent2D = @import("main.zig").Extent2D;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const ExternalTexture = opaque {
|
||||||
|
pub const BindingEntry = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .external_texture_binding_entry },
|
||||||
|
external_texture: *ExternalTexture,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const BindingLayout = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .external_texture_binding_layout },
|
||||||
|
};
|
||||||
|
|
||||||
|
const Rotation = enum(u32) {
|
||||||
|
rotate_0_degrees = 0x00000000,
|
||||||
|
rotate_90_degrees = 0x00000001,
|
||||||
|
rotate_180_degrees = 0x00000002,
|
||||||
|
rotate_270_degrees = 0x00000003,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
plane0: *TextureView,
|
||||||
|
plane1: ?*TextureView = null,
|
||||||
|
visible_origin: Origin2D,
|
||||||
|
visible_size: Extent2D,
|
||||||
|
do_yuv_to_rgb_conversion_only: Bool32 = .false,
|
||||||
|
yuv_to_rgb_conversion_matrix: ?*const [12]f32 = null,
|
||||||
|
src_transform_function_parameters: *const [7]f32,
|
||||||
|
dst_transform_function_parameters: *const [7]f32,
|
||||||
|
gamut_conversion_matrix: *const [9]f32,
|
||||||
|
flip_y: Bool32,
|
||||||
|
rotation: Rotation,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn destroy(external_texture: *ExternalTexture) void {
|
||||||
|
Impl.externalTextureDestroy(external_texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setLabel(external_texture: *ExternalTexture, label: [*:0]const u8) void {
|
||||||
|
Impl.externalTextureSetLabel(external_texture, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(external_texture: *ExternalTexture) void {
|
||||||
|
Impl.externalTextureReference(external_texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(external_texture: *ExternalTexture) void {
|
||||||
|
Impl.externalTextureRelease(external_texture);
|
||||||
|
}
|
||||||
|
};
|
||||||
65
src/gpu/instance.zig
Normal file
65
src/gpu/instance.zig
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const RequestAdapterStatus = @import("main.zig").RequestAdapterStatus;
|
||||||
|
const Surface = @import("surface.zig").Surface;
|
||||||
|
const Adapter = @import("adapter.zig").Adapter;
|
||||||
|
const RequestAdapterOptions = @import("main.zig").RequestAdapterOptions;
|
||||||
|
const RequestAdapterCallback = @import("main.zig").RequestAdapterCallback;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
const dawn = @import("dawn.zig");
|
||||||
|
|
||||||
|
pub const Instance = opaque {
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
pub const NextInChain = extern union {
|
||||||
|
generic: ?*const ChainedStruct,
|
||||||
|
dawn_toggles_descriptor: *const dawn.TogglesDescriptor,
|
||||||
|
};
|
||||||
|
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn createSurface(instance: *Instance, descriptor: *const Surface.Descriptor) *Surface {
|
||||||
|
return Impl.instanceCreateSurface(instance, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn processEvents(instance: *Instance) void {
|
||||||
|
Impl.instanceProcessEvents(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn requestAdapter(
|
||||||
|
instance: *Instance,
|
||||||
|
options: ?*const RequestAdapterOptions,
|
||||||
|
context: anytype,
|
||||||
|
comptime callback: fn (
|
||||||
|
ctx: @TypeOf(context),
|
||||||
|
status: RequestAdapterStatus,
|
||||||
|
adapter: ?*Adapter,
|
||||||
|
message: ?[*:0]const u8,
|
||||||
|
) callconv(.Inline) void,
|
||||||
|
) void {
|
||||||
|
const Context = @TypeOf(context);
|
||||||
|
const Helper = struct {
|
||||||
|
pub fn cCallback(
|
||||||
|
status: RequestAdapterStatus,
|
||||||
|
adapter: ?*Adapter,
|
||||||
|
message: ?[*:0]const u8,
|
||||||
|
userdata: ?*anyopaque,
|
||||||
|
) callconv(.C) void {
|
||||||
|
callback(
|
||||||
|
if (Context == void) {} else @as(Context, @ptrCast(@alignCast(userdata))),
|
||||||
|
status,
|
||||||
|
adapter,
|
||||||
|
message,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Impl.instanceRequestAdapter(instance, options, Helper.cCallback, if (Context == void) null else context);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(instance: *Instance) void {
|
||||||
|
Impl.instanceReference(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(instance: *Instance) void {
|
||||||
|
Impl.instanceRelease(instance);
|
||||||
|
}
|
||||||
|
};
|
||||||
2702
src/gpu/interface.zig
Normal file
2702
src/gpu/interface.zig
Normal file
File diff suppressed because it is too large
Load diff
28
src/gpu/mach_dawn.cpp
Normal file
28
src/gpu/mach_dawn.cpp
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include <dawn/native/DawnNative.h>
|
||||||
|
#include "mach_dawn.h"
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
namespace dawn::native::metal {
|
||||||
|
DAWN_NATIVE_EXPORT void WaitForCommandsToBeScheduled(WGPUDevice device);
|
||||||
|
} // namespace dawn::native
|
||||||
|
#endif // defined(__APPLE__)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MACH_EXPORT const DawnProcTable machDawnGetProcTable() {
|
||||||
|
return dawn::native::GetProcs();
|
||||||
|
}
|
||||||
|
|
||||||
|
MACH_EXPORT void machDawnDeviceWaitForCommandsToBeScheduled(WGPUDevice device) {
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
return dawn::native::metal::WaitForCommandsToBeScheduled(device);
|
||||||
|
#else
|
||||||
|
return;
|
||||||
|
#endif // defined(__APPLE__)
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
36
src/gpu/mach_dawn.h
Normal file
36
src/gpu/mach_dawn.h
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef MACH_DAWN_C_H_
|
||||||
|
#define MACH_DAWN_C_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MACH_DAWN_C_SHARED_LIBRARY)
|
||||||
|
# if defined(_WIN32)
|
||||||
|
# if defined(MACH_DAWN_C_IMPLEMENTATION)
|
||||||
|
# define MACH_EXPORT __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
# define MACH_EXPORT __declspec(dllimport)
|
||||||
|
# endif
|
||||||
|
# else // defined(_WIN32)
|
||||||
|
# if defined(MACH_DAWN_C_IMPLEMENTATION)
|
||||||
|
# define MACH_EXPORT __attribute__((visibility("default")))
|
||||||
|
# else
|
||||||
|
# define MACH_EXPORT
|
||||||
|
# endif
|
||||||
|
# endif // defined(_WIN32)
|
||||||
|
#else // defined(MACH_DAWN_C_SHARED_LIBRARY)
|
||||||
|
# define MACH_EXPORT
|
||||||
|
#endif // defined(MACH_DAWN_C_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
#include <dawn/webgpu.h>
|
||||||
|
#include <dawn/dawn_proc_table.h>
|
||||||
|
|
||||||
|
MACH_EXPORT const DawnProcTable machDawnGetProcTable();
|
||||||
|
MACH_EXPORT void machDawnDeviceWaitForCommandsToBeScheduled(WGPUDevice device);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // MACH_DAWN_C_H_
|
||||||
1025
src/gpu/main.zig
Normal file
1025
src/gpu/main.zig
Normal file
File diff suppressed because it is too large
Load diff
38
src/gpu/pipeline_layout.zig
Normal file
38
src/gpu/pipeline_layout.zig
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const BindGroupLayout = @import("bind_group_layout.zig").BindGroupLayout;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const PipelineLayout = opaque {
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
bind_group_layout_count: usize = 0,
|
||||||
|
bind_group_layouts: ?[*]const *BindGroupLayout = null,
|
||||||
|
|
||||||
|
/// Provides a slightly friendlier Zig API to initialize this structure.
|
||||||
|
pub inline fn init(v: struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
bind_group_layouts: ?[]const *BindGroupLayout = null,
|
||||||
|
}) Descriptor {
|
||||||
|
return .{
|
||||||
|
.next_in_chain = v.next_in_chain,
|
||||||
|
.label = v.label,
|
||||||
|
.bind_group_layout_count = if (v.bind_group_layouts) |e| e.len else 0,
|
||||||
|
.bind_group_layouts = if (v.bind_group_layouts) |e| e.ptr else null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn setLabel(pipeline_layout: *PipelineLayout, label: [*:0]const u8) void {
|
||||||
|
Impl.pipelineLayoutSetLabel(pipeline_layout, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(pipeline_layout: *PipelineLayout) void {
|
||||||
|
Impl.pipelineLayoutReference(pipeline_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(pipeline_layout: *PipelineLayout) void {
|
||||||
|
Impl.pipelineLayoutRelease(pipeline_layout);
|
||||||
|
}
|
||||||
|
};
|
||||||
57
src/gpu/query_set.zig
Normal file
57
src/gpu/query_set.zig
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const PipelineStatisticName = @import("main.zig").PipelineStatisticName;
|
||||||
|
const QueryType = @import("main.zig").QueryType;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const QuerySet = opaque {
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
type: QueryType,
|
||||||
|
count: u32,
|
||||||
|
pipeline_statistics: ?[*]const PipelineStatisticName = null,
|
||||||
|
pipeline_statistics_count: usize = 0,
|
||||||
|
|
||||||
|
/// Provides a slightly friendlier Zig API to initialize this structure.
|
||||||
|
pub inline fn init(v: struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
type: QueryType,
|
||||||
|
count: u32,
|
||||||
|
pipeline_statistics: ?[]const PipelineStatisticName = null,
|
||||||
|
}) Descriptor {
|
||||||
|
return .{
|
||||||
|
.next_in_chain = v.next_in_chain,
|
||||||
|
.label = v.label,
|
||||||
|
.type = v.type,
|
||||||
|
.count = v.count,
|
||||||
|
.pipeline_statistics_count = if (v.pipeline_statistics) |e| e.len else 0,
|
||||||
|
.pipeline_statistics = if (v.pipeline_statistics) |e| e.ptr else null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn destroy(query_set: *QuerySet) void {
|
||||||
|
Impl.querySetDestroy(query_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getCount(query_set: *QuerySet) u32 {
|
||||||
|
return Impl.querySetGetCount(query_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getType(query_set: *QuerySet) QueryType {
|
||||||
|
return Impl.querySetGetType(query_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setLabel(query_set: *QuerySet, label: [*:0]const u8) void {
|
||||||
|
Impl.querySetSetLabel(query_set, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(query_set: *QuerySet) void {
|
||||||
|
Impl.querySetReference(query_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(query_set: *QuerySet) void {
|
||||||
|
Impl.querySetRelease(query_set);
|
||||||
|
}
|
||||||
|
};
|
||||||
101
src/gpu/queue.zig
Normal file
101
src/gpu/queue.zig
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const CommandBuffer = @import("command_buffer.zig").CommandBuffer;
|
||||||
|
const Buffer = @import("buffer.zig").Buffer;
|
||||||
|
const Texture = @import("texture.zig").Texture;
|
||||||
|
const ImageCopyTexture = @import("main.zig").ImageCopyTexture;
|
||||||
|
const ImageCopyExternalTexture = @import("main.zig").ImageCopyExternalTexture;
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const Extent3D = @import("main.zig").Extent3D;
|
||||||
|
const CopyTextureForBrowserOptions = @import("main.zig").CopyTextureForBrowserOptions;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const Queue = opaque {
|
||||||
|
pub const WorkDoneCallback = *const fn (
|
||||||
|
status: WorkDoneStatus,
|
||||||
|
userdata: ?*anyopaque,
|
||||||
|
) callconv(.C) void;
|
||||||
|
|
||||||
|
pub const WorkDoneStatus = enum(u32) {
|
||||||
|
success = 0x00000000,
|
||||||
|
err = 0x00000001,
|
||||||
|
unknown = 0x00000002,
|
||||||
|
device_lost = 0x00000003,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn copyExternalTextureForBrowser(queue: *Queue, source: *const ImageCopyExternalTexture, destination: *const ImageCopyTexture, copy_size: *const Extent3D, options: *const CopyTextureForBrowserOptions) void {
|
||||||
|
Impl.queueCopyExternalTextureForBrowser(queue, source, destination, copy_size, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn copyTextureForBrowser(queue: *Queue, source: *const ImageCopyTexture, destination: *const ImageCopyTexture, copy_size: *const Extent3D, options: *const CopyTextureForBrowserOptions) void {
|
||||||
|
Impl.queueCopyTextureForBrowser(queue, source, destination, copy_size, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: dawn: does not allow unsetting this callback to null
|
||||||
|
pub inline fn onSubmittedWorkDone(
|
||||||
|
queue: *Queue,
|
||||||
|
signal_value: u64,
|
||||||
|
context: anytype,
|
||||||
|
comptime callback: fn (ctx: @TypeOf(context), status: WorkDoneStatus) callconv(.Inline) void,
|
||||||
|
) void {
|
||||||
|
const Context = @TypeOf(context);
|
||||||
|
const Helper = struct {
|
||||||
|
pub fn cCallback(status: WorkDoneStatus, userdata: ?*anyopaque) callconv(.C) void {
|
||||||
|
callback(if (Context == void) {} else @as(Context, @ptrCast(@alignCast(userdata))), status);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Impl.queueOnSubmittedWorkDone(queue, signal_value, Helper.cCallback, if (Context == void) null else context);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setLabel(queue: *Queue, label: [*:0]const u8) void {
|
||||||
|
Impl.queueSetLabel(queue, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn submit(queue: *Queue, commands: []const *const CommandBuffer) void {
|
||||||
|
Impl.queueSubmit(queue, commands.len, commands.ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn writeBuffer(
|
||||||
|
queue: *Queue,
|
||||||
|
buffer: *Buffer,
|
||||||
|
buffer_offset_bytes: u64,
|
||||||
|
data_slice: anytype,
|
||||||
|
) void {
|
||||||
|
Impl.queueWriteBuffer(
|
||||||
|
queue,
|
||||||
|
buffer,
|
||||||
|
buffer_offset_bytes,
|
||||||
|
@as(*const anyopaque, @ptrCast(std.mem.sliceAsBytes(data_slice).ptr)),
|
||||||
|
data_slice.len * @sizeOf(std.meta.Elem(@TypeOf(data_slice))),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn writeTexture(
|
||||||
|
queue: *Queue,
|
||||||
|
destination: *const ImageCopyTexture,
|
||||||
|
data_layout: *const Texture.DataLayout,
|
||||||
|
write_size: *const Extent3D,
|
||||||
|
data_slice: anytype,
|
||||||
|
) void {
|
||||||
|
Impl.queueWriteTexture(
|
||||||
|
queue,
|
||||||
|
destination,
|
||||||
|
@as(*const anyopaque, @ptrCast(std.mem.sliceAsBytes(data_slice).ptr)),
|
||||||
|
@as(usize, @intCast(data_slice.len)) * @sizeOf(std.meta.Elem(@TypeOf(data_slice))),
|
||||||
|
data_layout,
|
||||||
|
write_size,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(queue: *Queue) void {
|
||||||
|
Impl.queueReference(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(queue: *Queue) void {
|
||||||
|
Impl.queueRelease(queue);
|
||||||
|
}
|
||||||
|
};
|
||||||
21
src/gpu/render_bundle.zig
Normal file
21
src/gpu/render_bundle.zig
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const RenderBundle = opaque {
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn setLabel(render_bundle: *RenderBundle, label: [*:0]const u8) void {
|
||||||
|
Impl.renderBundleSetLabel(render_bundle, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(render_bundle: *RenderBundle) void {
|
||||||
|
Impl.renderBundleReference(render_bundle);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(render_bundle: *RenderBundle) void {
|
||||||
|
Impl.renderBundleRelease(render_bundle);
|
||||||
|
}
|
||||||
|
};
|
||||||
122
src/gpu/render_bundle_encoder.zig
Normal file
122
src/gpu/render_bundle_encoder.zig
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
const Texture = @import("texture.zig").Texture;
|
||||||
|
const Buffer = @import("buffer.zig").Buffer;
|
||||||
|
const BindGroup = @import("bind_group.zig").BindGroup;
|
||||||
|
const RenderPipeline = @import("render_pipeline.zig").RenderPipeline;
|
||||||
|
const RenderBundle = @import("render_bundle.zig").RenderBundle;
|
||||||
|
const Bool32 = @import("main.zig").Bool32;
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const IndexFormat = @import("main.zig").IndexFormat;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const RenderBundleEncoder = opaque {
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
color_formats_count: usize = 0,
|
||||||
|
color_formats: ?[*]const Texture.Format = null,
|
||||||
|
depth_stencil_format: Texture.Format = .undefined,
|
||||||
|
sample_count: u32 = 1,
|
||||||
|
depth_read_only: Bool32 = .false,
|
||||||
|
stencil_read_only: Bool32 = .false,
|
||||||
|
|
||||||
|
/// Provides a slightly friendlier Zig API to initialize this structure.
|
||||||
|
pub inline fn init(v: struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
color_formats: ?[]const Texture.Format = null,
|
||||||
|
depth_stencil_format: Texture.Format = .undefined,
|
||||||
|
sample_count: u32 = 1,
|
||||||
|
depth_read_only: bool = false,
|
||||||
|
stencil_read_only: bool = false,
|
||||||
|
}) Descriptor {
|
||||||
|
return .{
|
||||||
|
.next_in_chain = v.next_in_chain,
|
||||||
|
.label = v.label,
|
||||||
|
.color_formats_count = if (v.color_formats) |e| e.len else 0,
|
||||||
|
.color_formats = if (v.color_formats) |e| e.ptr else null,
|
||||||
|
.depth_stencil_format = v.depth_stencil_format,
|
||||||
|
.sample_count = v.sample_count,
|
||||||
|
.depth_read_only = Bool32.from(v.depth_read_only),
|
||||||
|
.stencil_read_only = Bool32.from(v.stencil_read_only),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Default `instance_count`: 1
|
||||||
|
/// Default `first_vertex`: 0
|
||||||
|
/// Default `first_instance`: 0
|
||||||
|
pub inline fn draw(render_bundle_encoder: *RenderBundleEncoder, vertex_count: u32, instance_count: u32, first_vertex: u32, first_instance: u32) void {
|
||||||
|
Impl.renderBundleEncoderDraw(render_bundle_encoder, vertex_count, instance_count, first_vertex, first_instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default `instance_count`: 1
|
||||||
|
/// Default `first_index`: 0
|
||||||
|
/// Default `base_vertex`: 0
|
||||||
|
/// Default `first_instance`: 0
|
||||||
|
pub inline fn drawIndexed(render_bundle_encoder: *RenderBundleEncoder, index_count: u32, instance_count: u32, first_index: u32, base_vertex: i32, first_instance: u32) void {
|
||||||
|
Impl.renderBundleEncoderDrawIndexed(render_bundle_encoder, index_count, instance_count, first_index, base_vertex, first_instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn drawIndexedIndirect(render_bundle_encoder: *RenderBundleEncoder, indirect_buffer: *Buffer, indirect_offset: u64) void {
|
||||||
|
Impl.renderBundleEncoderDrawIndexedIndirect(render_bundle_encoder, indirect_buffer, indirect_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn drawIndirect(render_bundle_encoder: *RenderBundleEncoder, indirect_buffer: *Buffer, indirect_offset: u64) void {
|
||||||
|
Impl.renderBundleEncoderDrawIndirect(render_bundle_encoder, indirect_buffer, indirect_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn finish(render_bundle_encoder: *RenderBundleEncoder, descriptor: ?*const RenderBundle.Descriptor) *RenderBundle {
|
||||||
|
return Impl.renderBundleEncoderFinish(render_bundle_encoder, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn insertDebugMarker(render_bundle_encoder: *RenderBundleEncoder, marker_label: [*:0]const u8) void {
|
||||||
|
Impl.renderBundleEncoderInsertDebugMarker(render_bundle_encoder, marker_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn popDebugGroup(render_bundle_encoder: *RenderBundleEncoder) void {
|
||||||
|
Impl.renderBundleEncoderPopDebugGroup(render_bundle_encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn pushDebugGroup(render_bundle_encoder: *RenderBundleEncoder, group_label: [*:0]const u8) void {
|
||||||
|
Impl.renderBundleEncoderPushDebugGroup(render_bundle_encoder, group_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default `dynamic_offsets`: `null`
|
||||||
|
pub inline fn setBindGroup(render_bundle_encoder: *RenderBundleEncoder, group_index: u32, group: *BindGroup, dynamic_offsets: ?[]const u32) void {
|
||||||
|
Impl.renderBundleEncoderSetBindGroup(
|
||||||
|
render_bundle_encoder,
|
||||||
|
group_index,
|
||||||
|
group,
|
||||||
|
if (dynamic_offsets) |v| v.len else 0,
|
||||||
|
if (dynamic_offsets) |v| v.ptr else null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default `offset`: 0
|
||||||
|
/// Default `size`: `gpu.whole_size`
|
||||||
|
pub inline fn setIndexBuffer(render_bundle_encoder: *RenderBundleEncoder, buffer: *Buffer, format: IndexFormat, offset: u64, size: u64) void {
|
||||||
|
Impl.renderBundleEncoderSetIndexBuffer(render_bundle_encoder, buffer, format, offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setLabel(render_bundle_encoder: *RenderBundleEncoder, label: [*:0]const u8) void {
|
||||||
|
Impl.renderBundleEncoderSetLabel(render_bundle_encoder, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setPipeline(render_bundle_encoder: *RenderBundleEncoder, pipeline: *RenderPipeline) void {
|
||||||
|
Impl.renderBundleEncoderSetPipeline(render_bundle_encoder, pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default `offset`: 0
|
||||||
|
/// Default `size`: `gpu.whole_size`
|
||||||
|
pub inline fn setVertexBuffer(render_bundle_encoder: *RenderBundleEncoder, slot: u32, buffer: *Buffer, offset: u64, size: u64) void {
|
||||||
|
Impl.renderBundleEncoderSetVertexBuffer(render_bundle_encoder, slot, buffer, offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(render_bundle_encoder: *RenderBundleEncoder) void {
|
||||||
|
Impl.renderBundleEncoderReference(render_bundle_encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(render_bundle_encoder: *RenderBundleEncoder) void {
|
||||||
|
Impl.renderBundleEncoderRelease(render_bundle_encoder);
|
||||||
|
}
|
||||||
|
};
|
||||||
128
src/gpu/render_pass_encoder.zig
Normal file
128
src/gpu/render_pass_encoder.zig
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
const Buffer = @import("buffer.zig").Buffer;
|
||||||
|
const RenderBundle = @import("render_bundle.zig").RenderBundle;
|
||||||
|
const BindGroup = @import("bind_group.zig").BindGroup;
|
||||||
|
const RenderPipeline = @import("render_pipeline.zig").RenderPipeline;
|
||||||
|
const QuerySet = @import("query_set.zig").QuerySet;
|
||||||
|
const Color = @import("main.zig").Color;
|
||||||
|
const IndexFormat = @import("main.zig").IndexFormat;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const RenderPassEncoder = opaque {
|
||||||
|
pub inline fn beginOcclusionQuery(render_pass_encoder: *RenderPassEncoder, query_index: u32) void {
|
||||||
|
Impl.renderPassEncoderBeginOcclusionQuery(render_pass_encoder, query_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default `instance_count`: 1
|
||||||
|
/// Default `first_vertex`: 0
|
||||||
|
/// Default `first_instance`: 0
|
||||||
|
pub inline fn draw(render_pass_encoder: *RenderPassEncoder, vertex_count: u32, instance_count: u32, first_vertex: u32, first_instance: u32) void {
|
||||||
|
Impl.renderPassEncoderDraw(render_pass_encoder, vertex_count, instance_count, first_vertex, first_instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default `instance_count`: 1
|
||||||
|
/// Default `first_index`: 0
|
||||||
|
/// Default `base_vertex`: 0
|
||||||
|
/// Default `first_instance`: 0
|
||||||
|
pub inline fn drawIndexed(render_pass_encoder: *RenderPassEncoder, index_count: u32, instance_count: u32, first_index: u32, base_vertex: i32, first_instance: u32) void {
|
||||||
|
Impl.renderPassEncoderDrawIndexed(render_pass_encoder, index_count, instance_count, first_index, base_vertex, first_instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn drawIndexedIndirect(render_pass_encoder: *RenderPassEncoder, indirect_buffer: *Buffer, indirect_offset: u64) void {
|
||||||
|
Impl.renderPassEncoderDrawIndexedIndirect(render_pass_encoder, indirect_buffer, indirect_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn drawIndirect(render_pass_encoder: *RenderPassEncoder, indirect_buffer: *Buffer, indirect_offset: u64) void {
|
||||||
|
Impl.renderPassEncoderDrawIndirect(render_pass_encoder, indirect_buffer, indirect_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn end(render_pass_encoder: *RenderPassEncoder) void {
|
||||||
|
Impl.renderPassEncoderEnd(render_pass_encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn endOcclusionQuery(render_pass_encoder: *RenderPassEncoder) void {
|
||||||
|
Impl.renderPassEncoderEndOcclusionQuery(render_pass_encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn executeBundles(
|
||||||
|
render_pass_encoder: *RenderPassEncoder,
|
||||||
|
bundles: []*const RenderBundle,
|
||||||
|
) void {
|
||||||
|
Impl.renderPassEncoderExecuteBundles(
|
||||||
|
render_pass_encoder,
|
||||||
|
bundles.len,
|
||||||
|
bundles.ptr,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn insertDebugMarker(render_pass_encoder: *RenderPassEncoder, marker_label: [*:0]const u8) void {
|
||||||
|
Impl.renderPassEncoderInsertDebugMarker(render_pass_encoder, marker_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn popDebugGroup(render_pass_encoder: *RenderPassEncoder) void {
|
||||||
|
Impl.renderPassEncoderPopDebugGroup(render_pass_encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn pushDebugGroup(render_pass_encoder: *RenderPassEncoder, group_label: [*:0]const u8) void {
|
||||||
|
Impl.renderPassEncoderPushDebugGroup(render_pass_encoder, group_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default `dynamic_offsets_count`: 0
|
||||||
|
/// Default `dynamic_offsets`: `null`
|
||||||
|
pub inline fn setBindGroup(render_pass_encoder: *RenderPassEncoder, group_index: u32, group: *BindGroup, dynamic_offsets: ?[]const u32) void {
|
||||||
|
Impl.renderPassEncoderSetBindGroup(
|
||||||
|
render_pass_encoder,
|
||||||
|
group_index,
|
||||||
|
group,
|
||||||
|
if (dynamic_offsets) |v| v.len else 0,
|
||||||
|
if (dynamic_offsets) |v| v.ptr else null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setBlendConstant(render_pass_encoder: *RenderPassEncoder, color: *const Color) void {
|
||||||
|
Impl.renderPassEncoderSetBlendConstant(render_pass_encoder, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default `offset`: 0
|
||||||
|
/// Default `size`: `gpu.whole_size`
|
||||||
|
pub inline fn setIndexBuffer(render_pass_encoder: *RenderPassEncoder, buffer: *Buffer, format: IndexFormat, offset: u64, size: u64) void {
|
||||||
|
Impl.renderPassEncoderSetIndexBuffer(render_pass_encoder, buffer, format, offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setLabel(render_pass_encoder: *RenderPassEncoder, label: [*:0]const u8) void {
|
||||||
|
Impl.renderPassEncoderSetLabel(render_pass_encoder, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setPipeline(render_pass_encoder: *RenderPassEncoder, pipeline: *RenderPipeline) void {
|
||||||
|
Impl.renderPassEncoderSetPipeline(render_pass_encoder, pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setScissorRect(render_pass_encoder: *RenderPassEncoder, x: u32, y: u32, width: u32, height: u32) void {
|
||||||
|
Impl.renderPassEncoderSetScissorRect(render_pass_encoder, x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setStencilReference(render_pass_encoder: *RenderPassEncoder, _reference: u32) void {
|
||||||
|
Impl.renderPassEncoderSetStencilReference(render_pass_encoder, _reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default `offset`: 0
|
||||||
|
/// Default `size`: `gpu.whole_size`
|
||||||
|
pub inline fn setVertexBuffer(render_pass_encoder: *RenderPassEncoder, slot: u32, buffer: *Buffer, offset: u64, size: u64) void {
|
||||||
|
Impl.renderPassEncoderSetVertexBuffer(render_pass_encoder, slot, buffer, offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setViewport(render_pass_encoder: *RenderPassEncoder, x: f32, y: f32, width: f32, height: f32, min_depth: f32, max_depth: f32) void {
|
||||||
|
Impl.renderPassEncoderSetViewport(render_pass_encoder, x, y, width, height, min_depth, max_depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn writeTimestamp(render_pass_encoder: *RenderPassEncoder, query_set: *QuerySet, query_index: u32) void {
|
||||||
|
Impl.renderPassEncoderWriteTimestamp(render_pass_encoder, query_set, query_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(render_pass_encoder: *RenderPassEncoder) void {
|
||||||
|
Impl.renderPassEncoderReference(render_pass_encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(render_pass_encoder: *RenderPassEncoder) void {
|
||||||
|
Impl.renderPassEncoderRelease(render_pass_encoder);
|
||||||
|
}
|
||||||
|
};
|
||||||
38
src/gpu/render_pipeline.zig
Normal file
38
src/gpu/render_pipeline.zig
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const DepthStencilState = @import("main.zig").DepthStencilState;
|
||||||
|
const MultisampleState = @import("main.zig").MultisampleState;
|
||||||
|
const VertexState = @import("main.zig").VertexState;
|
||||||
|
const PrimitiveState = @import("main.zig").PrimitiveState;
|
||||||
|
const FragmentState = @import("main.zig").FragmentState;
|
||||||
|
const PipelineLayout = @import("pipeline_layout.zig").PipelineLayout;
|
||||||
|
const BindGroupLayout = @import("bind_group_layout.zig").BindGroupLayout;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const RenderPipeline = opaque {
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
layout: ?*PipelineLayout = null,
|
||||||
|
vertex: VertexState,
|
||||||
|
primitive: PrimitiveState = .{},
|
||||||
|
depth_stencil: ?*const DepthStencilState = null,
|
||||||
|
multisample: MultisampleState = .{},
|
||||||
|
fragment: ?*const FragmentState = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn getBindGroupLayout(render_pipeline: *RenderPipeline, group_index: u32) *BindGroupLayout {
|
||||||
|
return Impl.renderPipelineGetBindGroupLayout(render_pipeline, group_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setLabel(render_pipeline: *RenderPipeline, label: [*:0]const u8) void {
|
||||||
|
Impl.renderPipelineSetLabel(render_pipeline, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(render_pipeline: *RenderPipeline) void {
|
||||||
|
Impl.renderPipelineReference(render_pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(render_pipeline: *RenderPipeline) void {
|
||||||
|
Impl.renderPipelineRelease(render_pipeline);
|
||||||
|
}
|
||||||
|
};
|
||||||
52
src/gpu/sampler.zig
Normal file
52
src/gpu/sampler.zig
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const FilterMode = @import("main.zig").FilterMode;
|
||||||
|
const MipmapFilterMode = @import("main.zig").MipmapFilterMode;
|
||||||
|
const CompareFunction = @import("main.zig").CompareFunction;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const Sampler = opaque {
|
||||||
|
pub const AddressMode = enum(u32) {
|
||||||
|
repeat = 0x00000000,
|
||||||
|
mirror_repeat = 0x00000001,
|
||||||
|
clamp_to_edge = 0x00000002,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const BindingType = enum(u32) {
|
||||||
|
undefined = 0x00000000,
|
||||||
|
filtering = 0x00000001,
|
||||||
|
non_filtering = 0x00000002,
|
||||||
|
comparison = 0x00000003,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const BindingLayout = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
type: BindingType = .undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
address_mode_u: AddressMode = .clamp_to_edge,
|
||||||
|
address_mode_v: AddressMode = .clamp_to_edge,
|
||||||
|
address_mode_w: AddressMode = .clamp_to_edge,
|
||||||
|
mag_filter: FilterMode = .nearest,
|
||||||
|
min_filter: FilterMode = .nearest,
|
||||||
|
mipmap_filter: MipmapFilterMode = .nearest,
|
||||||
|
lod_min_clamp: f32 = 0.0,
|
||||||
|
lod_max_clamp: f32 = 32.0,
|
||||||
|
compare: CompareFunction = .undefined,
|
||||||
|
max_anisotropy: u16 = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn setLabel(sampler: *Sampler, label: [*:0]const u8) void {
|
||||||
|
Impl.samplerSetLabel(sampler, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(sampler: *Sampler) void {
|
||||||
|
Impl.samplerReference(sampler);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(sampler: *Sampler) void {
|
||||||
|
Impl.samplerRelease(sampler);
|
||||||
|
}
|
||||||
|
};
|
||||||
69
src/gpu/shader_module.zig
Normal file
69
src/gpu/shader_module.zig
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const CompilationInfoCallback = @import("main.zig").CompilationInfoCallback;
|
||||||
|
const CompilationInfoRequestStatus = @import("main.zig").CompilationInfoRequestStatus;
|
||||||
|
const CompilationInfo = @import("main.zig").CompilationInfo;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
const dawn = @import("dawn.zig");
|
||||||
|
|
||||||
|
pub const ShaderModule = opaque {
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
pub const NextInChain = extern union {
|
||||||
|
generic: ?*const ChainedStruct,
|
||||||
|
spirv_descriptor: ?*const SPIRVDescriptor,
|
||||||
|
wgsl_descriptor: ?*const WGSLDescriptor,
|
||||||
|
dawn_shader_module_spirv_options_descriptor: ?*const dawn.ShaderModuleSPIRVOptionsDescriptor,
|
||||||
|
};
|
||||||
|
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const SPIRVDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .shader_module_spirv_descriptor },
|
||||||
|
code_size: u32,
|
||||||
|
code: [*]const u32,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const WGSLDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .shader_module_wgsl_descriptor },
|
||||||
|
code: [*:0]const u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn getCompilationInfo(
|
||||||
|
shader_module: *ShaderModule,
|
||||||
|
context: anytype,
|
||||||
|
comptime callback: fn (
|
||||||
|
ctx: @TypeOf(context),
|
||||||
|
status: CompilationInfoRequestStatus,
|
||||||
|
compilation_info: *const CompilationInfo,
|
||||||
|
) callconv(.Inline) void,
|
||||||
|
) void {
|
||||||
|
const Context = @TypeOf(context);
|
||||||
|
const Helper = struct {
|
||||||
|
pub fn cCallback(
|
||||||
|
status: CompilationInfoRequestStatus,
|
||||||
|
compilation_info: *const CompilationInfo,
|
||||||
|
userdata: ?*anyopaque,
|
||||||
|
) callconv(.C) void {
|
||||||
|
callback(
|
||||||
|
if (Context == void) {} else @as(Context, @ptrCast(@alignCast(userdata))),
|
||||||
|
status,
|
||||||
|
compilation_info,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Impl.shaderModuleGetCompilationInfo(shader_module, Helper.cCallback, if (Context == void) null else context);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setLabel(shader_module: *ShaderModule, label: [*:0]const u8) void {
|
||||||
|
Impl.shaderModuleSetLabel(shader_module, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(shader_module: *ShaderModule) void {
|
||||||
|
Impl.shaderModuleReference(shader_module);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(shader_module: *ShaderModule) void {
|
||||||
|
Impl.shaderModuleRelease(shader_module);
|
||||||
|
}
|
||||||
|
};
|
||||||
91
src/gpu/shared_fence.zig
Normal file
91
src/gpu/shared_fence.zig
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const ChainedStructOut = @import("main.zig").ChainedStructOut;
|
||||||
|
|
||||||
|
pub const SharedFence = opaque {
|
||||||
|
pub const Type = enum(u32) {
|
||||||
|
shared_fence_type_undefined = 0x00000000,
|
||||||
|
shared_fence_type_vk_semaphore_opaque_fd = 0x00000001,
|
||||||
|
shared_fence_type_vk_semaphore_sync_fd = 0x00000002,
|
||||||
|
shared_fence_type_vk_semaphore_zircon_handle = 0x00000003,
|
||||||
|
shared_fence_type_dxgi_shared_handle = 0x00000004,
|
||||||
|
shared_fence_type_mtl_shared_event = 0x00000005,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
pub const NextInChain = extern union {
|
||||||
|
generic: ?*const ChainedStruct,
|
||||||
|
vk_semaphore_opaque_fd_descriptor: *const VkSemaphoreOpaqueFDDescriptor,
|
||||||
|
vk_semaphore_sync_fd_descriptor: *const VkSemaphoreSyncFDDescriptor,
|
||||||
|
vk_semaphore_zircon_handle_descriptor: *const VkSemaphoreZirconHandleDescriptor,
|
||||||
|
dxgi_shared_handle_descriptor: *const DXGISharedHandleDescriptor,
|
||||||
|
mtl_shared_event_descriptor: *const MTLSharedEventDescriptor,
|
||||||
|
};
|
||||||
|
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
label: ?[*]const u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DXGISharedHandleDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct,
|
||||||
|
handle: *anyopaque,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DXGISharedHandleExportInfo = extern struct {
|
||||||
|
chain: ChainedStructOut,
|
||||||
|
handle: *anyopaque,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ExportInfo = extern struct {
|
||||||
|
pub const NextInChain = extern union {
|
||||||
|
generic: ?*const ChainedStructOut,
|
||||||
|
dxgi_shared_handle_export_info: *const DXGISharedHandleExportInfo,
|
||||||
|
mtl_shared_event_export_info: *const MTLSharedEventExportInfo,
|
||||||
|
vk_semaphore_opaque_fd_export_info: *const VkSemaphoreOpaqueFDExportInfo,
|
||||||
|
vk_semaphore_sync_fd_export_info: *const VkSemaphoreSyncFDExportInfo,
|
||||||
|
vk_semaphore_zircon_handle_export_info: *const VkSemaphoreZirconHandleExportInfo,
|
||||||
|
};
|
||||||
|
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
type: Type,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MTLSharedEventDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct,
|
||||||
|
shared_event: *anyopaque,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MTLSharedEventExportInfo = extern struct {
|
||||||
|
chain: ChainedStructOut,
|
||||||
|
shared_event: *anyopaque,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const VkSemaphoreOpaqueFDDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct,
|
||||||
|
handle: c_int,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const VkSemaphoreOpaqueFDExportInfo = extern struct {
|
||||||
|
chain: ChainedStructOut,
|
||||||
|
handle: c_int,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const VkSemaphoreSyncFDDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct,
|
||||||
|
handle: c_int,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const VkSemaphoreSyncFDExportInfo = extern struct {
|
||||||
|
chain: ChainedStructOut,
|
||||||
|
handle: c_int,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const VkSemaphoreZirconHandleDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct,
|
||||||
|
handle: u32,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const VkSemaphoreZirconHandleExportInfo = extern struct {
|
||||||
|
chain: ChainedStructOut,
|
||||||
|
handle: u32,
|
||||||
|
};
|
||||||
|
};
|
||||||
124
src/gpu/shared_texture_memory.zig
Normal file
124
src/gpu/shared_texture_memory.zig
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
const Texture = @import("texture.zig").Texture;
|
||||||
|
const Bool32 = @import("main.zig").Bool32;
|
||||||
|
const Extent3D = @import("main.zig").Extent3D;
|
||||||
|
const SharedFence = @import("shared_fence.zig").SharedFence;
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const ChainedStructOut = @import("main.zig").ChainedStructOut;
|
||||||
|
|
||||||
|
pub const SharedTextureMemory = opaque {
|
||||||
|
pub const Properties = extern struct {
|
||||||
|
next_in_chain: *const ChainedStruct,
|
||||||
|
usage: Texture.UsageFlags,
|
||||||
|
size: Extent3D,
|
||||||
|
format: Texture.Format,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const VkImageDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .shared_texture_memory_vk_image_descriptor },
|
||||||
|
vk_format: i32,
|
||||||
|
vk_usage_flags: Texture.UsageFlags,
|
||||||
|
vk_extent3D: Extent3D,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const AHardwareBufferDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .shared_texture_memory_a_hardware_buffer_descriptor },
|
||||||
|
handle: *anyopaque,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const BeginAccessDescriptor = extern struct {
|
||||||
|
pub const NextInChain = extern union {
|
||||||
|
generic: ?*const ChainedStruct,
|
||||||
|
vk_image_layout_begin_state: *const VkImageLayoutBeginState,
|
||||||
|
};
|
||||||
|
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
initialized: Bool32,
|
||||||
|
fence_count: usize,
|
||||||
|
fences: *const SharedFence,
|
||||||
|
signaled_values: *const u64,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
pub const NextInChain = extern union {
|
||||||
|
generic: ?*const ChainedStruct,
|
||||||
|
a_hardware_buffer_descriptor: *const AHardwareBufferDescriptor,
|
||||||
|
dma_buf_descriptor: *const DmaBufDescriptor,
|
||||||
|
dxgi_shared_handle_descriptor: *const DXGISharedHandleDescriptor,
|
||||||
|
egl_image_descriptor: *const EGLImageDescriptor,
|
||||||
|
io_surface_descriptor: *const IOSurfaceDescriptor,
|
||||||
|
opaque_fd_descriptor: *const OpaqueFDDescriptor,
|
||||||
|
vk_dedicated_allocation_descriptor: *const VkDedicatedAllocationDescriptor,
|
||||||
|
zircon_handle_descriptor: *const ZirconHandleDescriptor,
|
||||||
|
};
|
||||||
|
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
label: ?[*]const u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DmaBufDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .shared_texture_memory_dma_buf_descriptor },
|
||||||
|
memory_fd: c_int,
|
||||||
|
allocation_size: u64,
|
||||||
|
drm_modifier: u64,
|
||||||
|
plane_count: usize,
|
||||||
|
plane_offsets: *const u64,
|
||||||
|
plane_strides: *const u32,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DXGISharedHandleDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .shared_texture_memory_dxgi_shared_handle_descriptor },
|
||||||
|
handle: *anyopaque,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const EGLImageDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .shared_texture_memory_egl_image_descriptor },
|
||||||
|
image: *anyopaque,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const EndAccessState = extern struct {
|
||||||
|
pub const NextInChain = extern union {
|
||||||
|
generic: ?*const ChainedStruct,
|
||||||
|
vk_image_layout_end_state: *const VkImageLayoutEndState,
|
||||||
|
};
|
||||||
|
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
initialized: Bool32,
|
||||||
|
fence_count: usize,
|
||||||
|
fences: *const SharedFence,
|
||||||
|
signaled_values: *const u64,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const IOSurfaceDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .shared_texture_memory_io_surface_descriptor },
|
||||||
|
ioSurface: *anyopaque,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const OpaqueFDDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .shared_texture_memory_opaque_fd_descriptor },
|
||||||
|
memory_fd: c_int,
|
||||||
|
allocation_size: u64,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const VkDedicatedAllocationDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .shared_texture_memory_vk_dedicated_allocation_descriptor },
|
||||||
|
dedicated_allocation: Bool32,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const VkImageLayoutBeginState = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .shared_texture_memory_vk_image_layout_begin_state },
|
||||||
|
old_layout: i32,
|
||||||
|
new_layout: i32,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const VkImageLayoutEndState = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .shared_texture_memory_vk_image_layout_end_state },
|
||||||
|
old_layout: i32,
|
||||||
|
new_layout: i32,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ZirconHandleDescriptor = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .shared_texture_memory_zircon_handle_descriptor },
|
||||||
|
memory_fd: u32,
|
||||||
|
allocation_size: u64,
|
||||||
|
};
|
||||||
|
};
|
||||||
72
src/gpu/surface.zig
Normal file
72
src/gpu/surface.zig
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const Surface = opaque {
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
pub const NextInChain = extern union {
|
||||||
|
generic: ?*const ChainedStruct,
|
||||||
|
from_android_native_window: *const DescriptorFromAndroidNativeWindow,
|
||||||
|
from_canvas_html_selector: *const DescriptorFromCanvasHTMLSelector,
|
||||||
|
from_metal_layer: *const DescriptorFromMetalLayer,
|
||||||
|
from_wayland_surface: *const DescriptorFromWaylandSurface,
|
||||||
|
from_windows_core_window: *const DescriptorFromWindowsCoreWindow,
|
||||||
|
from_windows_hwnd: *const DescriptorFromWindowsHWND,
|
||||||
|
from_windows_swap_chain_panel: *const DescriptorFromWindowsSwapChainPanel,
|
||||||
|
from_xlib_window: *const DescriptorFromXlibWindow,
|
||||||
|
};
|
||||||
|
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DescriptorFromAndroidNativeWindow = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .surface_descriptor_from_android_native_window },
|
||||||
|
window: *anyopaque,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DescriptorFromCanvasHTMLSelector = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .surface_descriptor_from_canvas_html_selector },
|
||||||
|
selector: [*:0]const u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DescriptorFromMetalLayer = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .surface_descriptor_from_metal_layer },
|
||||||
|
layer: *anyopaque,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DescriptorFromWaylandSurface = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .surface_descriptor_from_wayland_surface },
|
||||||
|
display: *anyopaque,
|
||||||
|
surface: *anyopaque,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DescriptorFromWindowsCoreWindow = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .surface_descriptor_from_windows_core_window },
|
||||||
|
core_window: *anyopaque,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DescriptorFromWindowsHWND = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .surface_descriptor_from_windows_hwnd },
|
||||||
|
hinstance: *anyopaque,
|
||||||
|
hwnd: *anyopaque,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DescriptorFromWindowsSwapChainPanel = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .surface_descriptor_from_windows_swap_chain_panel },
|
||||||
|
swap_chain_panel: *anyopaque,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DescriptorFromXlibWindow = extern struct {
|
||||||
|
chain: ChainedStruct = .{ .next = null, .s_type = .surface_descriptor_from_xlib_window },
|
||||||
|
display: *anyopaque,
|
||||||
|
window: u32,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn reference(surface: *Surface) void {
|
||||||
|
Impl.surfaceReference(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(surface: *Surface) void {
|
||||||
|
Impl.surfaceRelease(surface);
|
||||||
|
}
|
||||||
|
};
|
||||||
37
src/gpu/swap_chain.zig
Normal file
37
src/gpu/swap_chain.zig
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const PresentMode = @import("main.zig").PresentMode;
|
||||||
|
const Texture = @import("texture.zig").Texture;
|
||||||
|
const TextureView = @import("texture_view.zig").TextureView;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
|
||||||
|
pub const SwapChain = opaque {
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
usage: Texture.UsageFlags,
|
||||||
|
format: Texture.Format,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
present_mode: PresentMode,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn getCurrentTexture(swap_chain: *SwapChain) ?*Texture {
|
||||||
|
return Impl.swapChainGetCurrentTexture(swap_chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getCurrentTextureView(swap_chain: *SwapChain) ?*TextureView {
|
||||||
|
return Impl.swapChainGetCurrentTextureView(swap_chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn present(swap_chain: *SwapChain) void {
|
||||||
|
Impl.swapChainPresent(swap_chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(swap_chain: *SwapChain) void {
|
||||||
|
Impl.swapChainReference(swap_chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(swap_chain: *SwapChain) void {
|
||||||
|
Impl.swapChainRelease(swap_chain);
|
||||||
|
}
|
||||||
|
};
|
||||||
266
src/gpu/texture.zig
Normal file
266
src/gpu/texture.zig
Normal file
|
|
@ -0,0 +1,266 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const Bool32 = @import("main.zig").Bool32;
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const TextureView = @import("texture_view.zig").TextureView;
|
||||||
|
const Extent3D = @import("main.zig").Extent3D;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
const types = @import("main.zig");
|
||||||
|
const dawn = @import("dawn.zig");
|
||||||
|
|
||||||
|
pub const Texture = opaque {
|
||||||
|
pub const Aspect = enum(u32) {
|
||||||
|
all = 0x00000000,
|
||||||
|
stencil_only = 0x00000001,
|
||||||
|
depth_only = 0x00000002,
|
||||||
|
plane0_only = 0x00000003,
|
||||||
|
plane1_only = 0x00000004,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Dimension = enum(u32) {
|
||||||
|
dimension_1d = 0x00000000,
|
||||||
|
dimension_2d = 0x00000001,
|
||||||
|
dimension_3d = 0x00000002,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Format = enum(u32) {
|
||||||
|
undefined = 0x00000000,
|
||||||
|
r8_unorm = 0x00000001,
|
||||||
|
r8_snorm = 0x00000002,
|
||||||
|
r8_uint = 0x00000003,
|
||||||
|
r8_sint = 0x00000004,
|
||||||
|
r16_uint = 0x00000005,
|
||||||
|
r16_sint = 0x00000006,
|
||||||
|
r16_float = 0x00000007,
|
||||||
|
rg8_unorm = 0x00000008,
|
||||||
|
rg8_snorm = 0x00000009,
|
||||||
|
rg8_uint = 0x0000000a,
|
||||||
|
rg8_sint = 0x0000000b,
|
||||||
|
r32_float = 0x0000000c,
|
||||||
|
r32_uint = 0x0000000d,
|
||||||
|
r32_sint = 0x0000000e,
|
||||||
|
rg16_uint = 0x0000000f,
|
||||||
|
rg16_sint = 0x00000010,
|
||||||
|
rg16_float = 0x00000011,
|
||||||
|
rgba8_unorm = 0x00000012,
|
||||||
|
rgba8_unorm_srgb = 0x00000013,
|
||||||
|
rgba8_snorm = 0x00000014,
|
||||||
|
rgba8_uint = 0x00000015,
|
||||||
|
rgba8_sint = 0x00000016,
|
||||||
|
bgra8_unorm = 0x00000017,
|
||||||
|
bgra8_unorm_srgb = 0x00000018,
|
||||||
|
rgb10_a2_unorm = 0x00000019,
|
||||||
|
rg11_b10_ufloat = 0x0000001a,
|
||||||
|
rgb9_e5_ufloat = 0x0000001b,
|
||||||
|
rg32_float = 0x0000001c,
|
||||||
|
rg32_uint = 0x0000001d,
|
||||||
|
rg32_sint = 0x0000001e,
|
||||||
|
rgba16_uint = 0x0000001f,
|
||||||
|
rgba16_sint = 0x00000020,
|
||||||
|
rgba16_float = 0x00000021,
|
||||||
|
rgba32_float = 0x00000022,
|
||||||
|
rgba32_uint = 0x00000023,
|
||||||
|
rgba32_sint = 0x00000024,
|
||||||
|
stencil8 = 0x00000025,
|
||||||
|
depth16_unorm = 0x00000026,
|
||||||
|
depth24_plus = 0x00000027,
|
||||||
|
depth24_plus_stencil8 = 0x00000028,
|
||||||
|
depth32_float = 0x00000029,
|
||||||
|
depth32_float_stencil8 = 0x0000002a,
|
||||||
|
bc1_rgba_unorm = 0x0000002b,
|
||||||
|
bc1_rgba_unorm_srgb = 0x0000002c,
|
||||||
|
bc2_rgba_unorm = 0x0000002d,
|
||||||
|
bc2_rgba_unorm_srgb = 0x0000002e,
|
||||||
|
bc3_rgba_unorm = 0x0000002f,
|
||||||
|
bc3_rgba_unorm_srgb = 0x00000030,
|
||||||
|
bc4_runorm = 0x00000031,
|
||||||
|
bc4_rsnorm = 0x00000032,
|
||||||
|
bc5_rg_unorm = 0x00000033,
|
||||||
|
bc5_rg_snorm = 0x00000034,
|
||||||
|
bc6_hrgb_ufloat = 0x00000035,
|
||||||
|
bc6_hrgb_float = 0x00000036,
|
||||||
|
bc7_rgba_unorm = 0x00000037,
|
||||||
|
bc7_rgba_unorm_srgb = 0x00000038,
|
||||||
|
etc2_rgb8_unorm = 0x00000039,
|
||||||
|
etc2_rgb8_unorm_srgb = 0x0000003a,
|
||||||
|
etc2_rgb8_a1_unorm = 0x0000003b,
|
||||||
|
etc2_rgb8_a1_unorm_srgb = 0x0000003c,
|
||||||
|
etc2_rgba8_unorm = 0x0000003d,
|
||||||
|
etc2_rgba8_unorm_srgb = 0x0000003e,
|
||||||
|
eacr11_unorm = 0x0000003f,
|
||||||
|
eacr11_snorm = 0x00000040,
|
||||||
|
eacrg11_unorm = 0x00000041,
|
||||||
|
eacrg11_snorm = 0x00000042,
|
||||||
|
astc4x4_unorm = 0x00000043,
|
||||||
|
astc4x4_unorm_srgb = 0x00000044,
|
||||||
|
astc5x4_unorm = 0x00000045,
|
||||||
|
astc5x4_unorm_srgb = 0x00000046,
|
||||||
|
astc5x5_unorm = 0x00000047,
|
||||||
|
astc5x5_unorm_srgb = 0x00000048,
|
||||||
|
astc6x5_unorm = 0x00000049,
|
||||||
|
astc6x5_unorm_srgb = 0x0000004a,
|
||||||
|
astc6x6_unorm = 0x0000004b,
|
||||||
|
astc6x6_unorm_srgb = 0x0000004c,
|
||||||
|
astc8x5_unorm = 0x0000004d,
|
||||||
|
astc8x5_unorm_srgb = 0x0000004e,
|
||||||
|
astc8x6_unorm = 0x0000004f,
|
||||||
|
astc8x6_unorm_srgb = 0x00000050,
|
||||||
|
astc8x8_unorm = 0x00000051,
|
||||||
|
astc8x8_unorm_srgb = 0x00000052,
|
||||||
|
astc10x5_unorm = 0x00000053,
|
||||||
|
astc10x5_unorm_srgb = 0x00000054,
|
||||||
|
astc10x6_unorm = 0x00000055,
|
||||||
|
astc10x6_unorm_srgb = 0x00000056,
|
||||||
|
astc10x8_unorm = 0x00000057,
|
||||||
|
astc10x8_unorm_srgb = 0x00000058,
|
||||||
|
astc10x10_unorm = 0x00000059,
|
||||||
|
astc10x10_unorm_srgb = 0x0000005a,
|
||||||
|
astc12x10_unorm = 0x0000005b,
|
||||||
|
astc12x10_unorm_srgb = 0x0000005c,
|
||||||
|
astc12x12_unorm = 0x0000005d,
|
||||||
|
astc12x12_unorm_srgb = 0x0000005e,
|
||||||
|
r8_bg8_biplanar420_unorm = 0x0000005f,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const SampleType = enum(u32) {
|
||||||
|
undefined = 0x00000000,
|
||||||
|
float = 0x00000001,
|
||||||
|
unfilterable_float = 0x00000002,
|
||||||
|
depth = 0x00000003,
|
||||||
|
sint = 0x00000004,
|
||||||
|
uint = 0x00000005,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const UsageFlags = packed struct(u32) {
|
||||||
|
copy_src: bool = false,
|
||||||
|
copy_dst: bool = false,
|
||||||
|
texture_binding: bool = false,
|
||||||
|
storage_binding: bool = false,
|
||||||
|
render_attachment: bool = false,
|
||||||
|
transient_attachment: bool = false,
|
||||||
|
|
||||||
|
_padding: u26 = 0,
|
||||||
|
|
||||||
|
comptime {
|
||||||
|
std.debug.assert(
|
||||||
|
@sizeOf(@This()) == @sizeOf(u32) and
|
||||||
|
@bitSizeOf(@This()) == @bitSizeOf(u32),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const none = UsageFlags{};
|
||||||
|
|
||||||
|
pub fn equal(a: UsageFlags, b: UsageFlags) bool {
|
||||||
|
return @as(u6, @truncate(@as(u32, @bitCast(a)))) == @as(u6, @truncate(@as(u32, @bitCast(b))));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const BindingLayout = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
sample_type: SampleType = .undefined,
|
||||||
|
view_dimension: TextureView.Dimension = .dimension_undefined,
|
||||||
|
multisampled: Bool32 = .false,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DataLayout = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
offset: u64 = 0,
|
||||||
|
bytes_per_row: u32 = types.copy_stride_undefined,
|
||||||
|
rows_per_image: u32 = types.copy_stride_undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
pub const NextInChain = extern union {
|
||||||
|
generic: ?*const ChainedStruct,
|
||||||
|
dawn_texture_internal_usage_descriptor: *const dawn.TextureInternalUsageDescriptor,
|
||||||
|
};
|
||||||
|
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
usage: UsageFlags,
|
||||||
|
dimension: Dimension = .dimension_2d,
|
||||||
|
size: Extent3D,
|
||||||
|
format: Format,
|
||||||
|
mip_level_count: u32 = 1,
|
||||||
|
sample_count: u32 = 1,
|
||||||
|
view_format_count: usize = 0,
|
||||||
|
view_formats: ?[*]const Format = null,
|
||||||
|
|
||||||
|
/// Provides a slightly friendlier Zig API to initialize this structure.
|
||||||
|
pub inline fn init(v: struct {
|
||||||
|
next_in_chain: NextInChain = .{ .generic = null },
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
usage: UsageFlags,
|
||||||
|
dimension: Dimension = .dimension_2d,
|
||||||
|
size: Extent3D,
|
||||||
|
format: Format,
|
||||||
|
mip_level_count: u32 = 1,
|
||||||
|
sample_count: u32 = 1,
|
||||||
|
view_formats: ?[]const Format = null,
|
||||||
|
}) Descriptor {
|
||||||
|
return .{
|
||||||
|
.next_in_chain = v.next_in_chain,
|
||||||
|
.label = v.label,
|
||||||
|
.usage = v.usage,
|
||||||
|
.dimension = v.dimension,
|
||||||
|
.size = v.size,
|
||||||
|
.format = v.format,
|
||||||
|
.mip_level_count = v.mip_level_count,
|
||||||
|
.sample_count = v.sample_count,
|
||||||
|
.view_format_count = if (v.view_formats) |e| e.len else 0,
|
||||||
|
.view_formats = if (v.view_formats) |e| e.ptr else null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn createView(texture: *Texture, descriptor: ?*const TextureView.Descriptor) *TextureView {
|
||||||
|
return Impl.textureCreateView(texture, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn destroy(texture: *Texture) void {
|
||||||
|
Impl.textureDestroy(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getDepthOrArrayLayers(texture: *Texture) u32 {
|
||||||
|
return Impl.textureGetDepthOrArrayLayers(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getDimension(texture: *Texture) Dimension {
|
||||||
|
return Impl.textureGetDimension(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getFormat(texture: *Texture) Format {
|
||||||
|
return Impl.textureGetFormat(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getHeight(texture: *Texture) u32 {
|
||||||
|
return Impl.textureGetHeight(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getMipLevelCount(texture: *Texture) u32 {
|
||||||
|
return Impl.textureGetMipLevelCount(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getSampleCount(texture: *Texture) u32 {
|
||||||
|
return Impl.textureGetSampleCount(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getUsage(texture: *Texture) UsageFlags {
|
||||||
|
return Impl.textureGetUsage(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getWidth(texture: *Texture) u32 {
|
||||||
|
return Impl.textureGetWidth(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn setLabel(texture: *Texture, label: [*:0]const u8) void {
|
||||||
|
Impl.textureSetLabel(texture, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(texture: *Texture) void {
|
||||||
|
Impl.textureReference(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(texture: *Texture) void {
|
||||||
|
Impl.textureRelease(texture);
|
||||||
|
}
|
||||||
|
};
|
||||||
40
src/gpu/texture_view.zig
Normal file
40
src/gpu/texture_view.zig
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
const ChainedStruct = @import("main.zig").ChainedStruct;
|
||||||
|
const Texture = @import("texture.zig").Texture;
|
||||||
|
const Impl = @import("interface.zig").Impl;
|
||||||
|
const types = @import("main.zig");
|
||||||
|
|
||||||
|
pub const TextureView = opaque {
|
||||||
|
pub const Dimension = enum(u32) {
|
||||||
|
dimension_undefined = 0x00000000,
|
||||||
|
dimension_1d = 0x00000001,
|
||||||
|
dimension_2d = 0x00000002,
|
||||||
|
dimension_2d_array = 0x00000003,
|
||||||
|
dimension_cube = 0x00000004,
|
||||||
|
dimension_cube_array = 0x00000005,
|
||||||
|
dimension_3d = 0x00000006,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Descriptor = extern struct {
|
||||||
|
next_in_chain: ?*const ChainedStruct = null,
|
||||||
|
label: ?[*:0]const u8 = null,
|
||||||
|
format: Texture.Format = .undefined,
|
||||||
|
dimension: Dimension = .dimension_undefined,
|
||||||
|
base_mip_level: u32 = 0,
|
||||||
|
mip_level_count: u32 = types.mip_level_count_undefined,
|
||||||
|
base_array_layer: u32 = 0,
|
||||||
|
array_layer_count: u32 = types.array_layer_count_undefined,
|
||||||
|
aspect: Texture.Aspect = .all,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub inline fn setLabel(texture_view: *TextureView, label: [*:0]const u8) void {
|
||||||
|
Impl.textureViewSetLabel(texture_view, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn reference(texture_view: *TextureView) void {
|
||||||
|
Impl.textureViewReference(texture_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn release(texture_view: *TextureView) void {
|
||||||
|
Impl.textureViewRelease(texture_view);
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue