add wasm support
This commit is contained in:
parent
e4000646ad
commit
099c3c0607
31
build.zig
31
build.zig
@ -26,14 +26,18 @@ pub fn build(b: *std.Build) !void {
|
|||||||
test_step.dependOn(&run_exe_tests.step);
|
test_step.dependOn(&run_exe_tests.step);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.wasm => {
|
.wasm => |build_step| {
|
||||||
// TODO:
|
b.getInstallStep().dependOn(build_step);
|
||||||
// b.getInstallStep().dependOn(build_step);
|
|
||||||
//
|
const dep_sokol = b.dependency("sokol", .{});
|
||||||
// const dep_emsdk = dep_sokol.builder.dependency("emsdk", .{});
|
const dep_emsdk = dep_sokol.builder.dependency("emsdk", .{});
|
||||||
// const emrun_step = sokol.emRunStep(b, .{ .name = "index", .emsdk = dep_emsdk });
|
const emrun_step = sokol.emRunStep(b, .{ .name = "index", .emsdk = dep_emsdk });
|
||||||
// emrun_step.step.dependOn(build_step);
|
emrun_step.step.dependOn(build_step);
|
||||||
// run_cmd_step = &emrun_step.step;
|
run_cmd_step = &emrun_step.step;
|
||||||
|
|
||||||
|
// add an emsdk install step
|
||||||
|
const emsdk_install_step = sokol.emSdkInstallStep(b, dep_sokol.builder.dependency("emsdk", .{}), .{});
|
||||||
|
b.step("install-emsdk", "Install Emscripten SDK in zig-pkg").dependOn(emsdk_install_step);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +70,10 @@ fn buildProject(ctx: Context, target: Build.ResolvedTarget, optimize: std.builti
|
|||||||
const is_debug = optimize == .debug;
|
const is_debug = optimize == .debug;
|
||||||
|
|
||||||
const has_imgui = b.option(bool, "imgui", "ImGui integration") orelse is_debug;
|
const has_imgui = b.option(bool, "imgui", "ImGui integration") orelse is_debug;
|
||||||
const assets_from_filesystem = b.option(bool, "assets-filesystem", "Allow reading assets from filesystem") orelse is_debug;
|
var assets_from_filesystem = false;
|
||||||
|
if (!is_wasm) {
|
||||||
|
assets_from_filesystem = b.option(bool, "assets-filesystem", "Allow reading assets from filesystem") orelse is_debug;
|
||||||
|
}
|
||||||
|
|
||||||
var has_tracy = false;
|
var has_tracy = false;
|
||||||
if (!is_wasm) {
|
if (!is_wasm) {
|
||||||
@ -123,6 +130,7 @@ fn buildProject(ctx: Context, target: Build.ResolvedTarget, optimize: std.builti
|
|||||||
var slang = sokol.shdc.Slang{};
|
var slang = sokol.shdc.Slang{};
|
||||||
if (is_wasm) {
|
if (is_wasm) {
|
||||||
slang.wgsl = true;
|
slang.wgsl = true;
|
||||||
|
slang.glsl300es = true;
|
||||||
} else {
|
} else {
|
||||||
slang.glsl410 = true;
|
slang.glsl410 = true;
|
||||||
slang.hlsl4 = true;
|
slang.hlsl4 = true;
|
||||||
@ -316,8 +324,9 @@ fn buildWasm(b: *std.Build, opts: BuildWasmOptions) *std.Build.Step {
|
|||||||
.emsdk = dep_emsdk,
|
.emsdk = dep_emsdk,
|
||||||
.use_webgl2 = true,
|
.use_webgl2 = true,
|
||||||
.use_emmalloc = true,
|
.use_emmalloc = true,
|
||||||
.use_filesystem = false,
|
.use_filesystem = true,
|
||||||
.shell_file_path = b.path("src/engine/shell.html"),
|
.shell_file_path = b.path("src/platform/shell.html"),
|
||||||
|
.extra_args = &.{ "-sALLOW_MEMORY_GROWTH", "-sENVIRONMENT=web" }
|
||||||
}) catch unreachable;
|
}) catch unreachable;
|
||||||
|
|
||||||
return &link_step.step;
|
return &link_step.step;
|
||||||
|
|||||||
@ -4,7 +4,7 @@ const c = @import("c");
|
|||||||
|
|
||||||
const STBRectPack = @This();
|
const STBRectPack = @This();
|
||||||
|
|
||||||
ctx: c.stbrp_context,
|
ctx: c.stbrp_context = .{},
|
||||||
|
|
||||||
pub fn init(self: *STBRectPack, width: u32, height: u32, nodes: []Node) void {
|
pub fn init(self: *STBRectPack, width: u32, height: u32, nodes: []Node) void {
|
||||||
c.stbrp_init_target(&self.ctx, @intCast(width), @intCast(height), nodes.ptr, @intCast(nodes.len));
|
c.stbrp_init_target(&self.ctx, @intCast(width), @intCast(height), nodes.ptr, @intCast(nodes.len));
|
||||||
|
|||||||
@ -164,6 +164,7 @@ pub fn init(io: Io, gpa: std.mem.Allocator, opts: InitOptions) !void {
|
|||||||
.buffer_frames = @intCast(opts.buffer_frames),
|
.buffer_frames = @intCast(opts.buffer_frames),
|
||||||
.sample_rate = g_sample_rate
|
.sample_rate = g_sample_rate
|
||||||
});
|
});
|
||||||
|
assert(saudio.isvalid());
|
||||||
|
|
||||||
if (opts.track_elapsed_time) {
|
if (opts.track_elapsed_time) {
|
||||||
const measurements_per_second: usize = @intCast(@divFloor(std.time.ns_per_s, getMaxAudioThreadDuration().nanoseconds));
|
const measurements_per_second: usize = @intCast(@divFloor(std.time.ns_per_s, getMaxAudioThreadDuration().nanoseconds));
|
||||||
|
|||||||
@ -130,7 +130,8 @@ pub fn init(gpa: std.mem.Allocator, logger: sg.Logger) !void {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const index_count = max_quads * 6;
|
const index_count = max_quads * 6;
|
||||||
var indices: [index_count]u16 = undefined;
|
var indices: []u16 = try gpa.alloc(u16, index_count);
|
||||||
|
defer gpa.free(indices);
|
||||||
for (0..max_quads) |i| {
|
for (0..max_quads) |i| {
|
||||||
indices[6*i + 0] = @intCast(4*i + 0);
|
indices[6*i + 0] = @intCast(4*i + 0);
|
||||||
indices[6*i + 1] = @intCast(4*i + 1);
|
indices[6*i + 1] = @intCast(4*i + 1);
|
||||||
@ -142,7 +143,7 @@ pub fn init(gpa: std.mem.Allocator, logger: sg.Logger) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bindings.index_buffer = sg.makeBuffer(.{
|
bindings.index_buffer = sg.makeBuffer(.{
|
||||||
.data = sg.asRange(&indices),
|
.data = sg.asRange(indices),
|
||||||
.usage = .{ .index_buffer = true, },
|
.usage = .{ .index_buffer = true, },
|
||||||
.label = "indices"
|
.label = "indices"
|
||||||
});
|
});
|
||||||
@ -997,7 +998,7 @@ fn repackSpritesheet(id: Spritesheet.Id) void {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
spritesheet.packer = undefined;
|
spritesheet.packer = .{};
|
||||||
const packer = &spritesheet.packer.?;
|
const packer = &spritesheet.packer.?;
|
||||||
|
|
||||||
for (&texture_sizes) |texture_size| {
|
for (&texture_sizes) |texture_size| {
|
||||||
|
|||||||
@ -36,7 +36,7 @@ fn PlatformType(App: type) type {
|
|||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
gpa: Allocator,
|
gpa: Allocator,
|
||||||
arena: *std.heap.ArenaAllocator,
|
arena: std.heap.ArenaAllocator,
|
||||||
io: Io,
|
io: Io,
|
||||||
cli_args: []const [:0]const u8,
|
cli_args: []const [:0]const u8,
|
||||||
|
|
||||||
@ -406,6 +406,13 @@ fn PlatformType(App: type) type {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
.KEY_DOWN => {
|
.KEY_DOWN => {
|
||||||
|
if (builtin.cpu.arch.isWasm()) {
|
||||||
|
// Pass through developer tools keybind
|
||||||
|
if (e.key_code == .I and e.modifiers & sapp.modifier_shift != 0 and e.modifiers & sapp.modifier_ctrl != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.last_key_press_is_repeat = e.key_repeat;
|
self.last_key_press_is_repeat = e.key_repeat;
|
||||||
if (!e.key_repeat) {
|
if (!e.key_repeat) {
|
||||||
self.pushEvent(.{
|
self.pushEvent(.{
|
||||||
@ -478,6 +485,8 @@ fn PlatformType(App: type) type {
|
|||||||
ImGUI.deinit();
|
ImGUI.deinit();
|
||||||
Gfx.deinit();
|
Gfx.deinit();
|
||||||
Audio.deinit(self.gpa);
|
Audio.deinit(self.gpa);
|
||||||
|
|
||||||
|
self.arena.deinit();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -609,7 +618,6 @@ pub const Frame = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn run(App: type, opts: RunOptions) void {
|
pub fn run(App: type, opts: RunOptions) void {
|
||||||
const arena = opts.init.arena.allocator();
|
|
||||||
const gpa = opts.init.gpa;
|
const gpa = opts.init.gpa;
|
||||||
const io = opts.init.io;
|
const io = opts.init.io;
|
||||||
|
|
||||||
@ -623,12 +631,14 @@ pub fn run(App: type, opts: RunOptions) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const PlatformApp = PlatformType(App);
|
const PlatformApp = PlatformType(App);
|
||||||
const plt = arena.create(PlatformApp) catch @panic("OOM");
|
|
||||||
|
var arena = std.heap.ArenaAllocator.init(gpa);
|
||||||
|
const plt = arena.allocator().create(PlatformApp) catch @panic("OOM");
|
||||||
plt.* = PlatformApp{
|
plt.* = PlatformApp{
|
||||||
.gpa = gpa,
|
.gpa = gpa,
|
||||||
.arena = opts.init.arena,
|
.arena = undefined,
|
||||||
.io = io,
|
.io = io,
|
||||||
.cli_args = opts.init.minimal.args.toSlice(arena) catch @panic("OOM"),
|
.cli_args = opts.init.minimal.args.toSlice(arena.allocator()) catch @panic("OOM"),
|
||||||
.app = undefined,
|
.app = undefined,
|
||||||
.input = undefined,
|
.input = undefined,
|
||||||
.events_buffer = undefined,
|
.events_buffer = undefined,
|
||||||
@ -643,6 +653,7 @@ pub fn run(App: type, opts: RunOptions) void {
|
|||||||
.assets = .init(gpa, io, assets_dir),
|
.assets = .init(gpa, io, assets_dir),
|
||||||
.last_mouse_position = null
|
.last_mouse_position = null
|
||||||
};
|
};
|
||||||
|
plt.arena = arena;
|
||||||
|
|
||||||
inline for (EmbeddedAssets.files) |file| {
|
inline for (EmbeddedAssets.files) |file| {
|
||||||
plt.assets.insertStaticFile(file.name, file.contents) catch @panic("OOM");
|
plt.assets.insertStaticFile(file.name, file.contents) catch @panic("OOM");
|
||||||
|
|||||||
53
src/platform/shell.html
Normal file
53
src/platform/shell.html
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en-us">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
|
||||||
|
<title>Sokol</title>
|
||||||
|
<style>
|
||||||
|
body { margin: 0; background-color: black }
|
||||||
|
.game {
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
border: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
display: block;
|
||||||
|
image-rendering: optimizeSpeed;
|
||||||
|
image-rendering: -moz-crisp-edges;
|
||||||
|
image-rendering: -o-crisp-edges;
|
||||||
|
image-rendering: -webkit-optimize-contrast;
|
||||||
|
image-rendering: optimize-contrast;
|
||||||
|
image-rendering: crisp-edges;
|
||||||
|
image-rendering: pixelated;
|
||||||
|
-ms-interpolation-mode: nearest-neighbor;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas class="game" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
var Module = {
|
||||||
|
preRun: [],
|
||||||
|
print: (function() {
|
||||||
|
return function(text) {
|
||||||
|
text = Array.prototype.slice.call(arguments).join(' ');
|
||||||
|
console.log(text);
|
||||||
|
};
|
||||||
|
})(),
|
||||||
|
printErr: function(text) {
|
||||||
|
text = Array.prototype.slice.call(arguments).join(' ');
|
||||||
|
console.error(text);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
window.onerror = function() {
|
||||||
|
console.log("onerror: " + event.message);
|
||||||
|
};
|
||||||
|
window.addEventListener("click", () => window.focus())
|
||||||
|
</script>
|
||||||
|
{{{ SCRIPT }}}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Reference in New Issue
Block a user