all: use new mach.Entity.Mod query API
Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
541ce9e7c0
commit
bd655828e3
13 changed files with 213 additions and 265 deletions
|
|
@ -157,27 +157,29 @@ fn tick(
|
||||||
|
|
||||||
// Query all the entities that have the .follower tag indicating they should follow the player.
|
// Query all the entities that have the .follower tag indicating they should follow the player.
|
||||||
// TODO(important): better querying API
|
// TODO(important): better querying API
|
||||||
var archetypes_iter = core.__entities.queryDeprecated(.{ .all = &.{
|
|
||||||
.{ .app = &.{.follower} },
|
// Iterate the ID and position of each follower entity
|
||||||
} });
|
var q = try entities.query(.{
|
||||||
while (archetypes_iter.next()) |archetype| {
|
.ids = mach.Entities.Mod.read(.id),
|
||||||
// Iterate the ID and position of each entity
|
.followers = Mod.read(.follower),
|
||||||
const ids = archetype.slice(.entities, .id);
|
.positions = Renderer.Mod.read(.position),
|
||||||
const positions = archetype.slice(.renderer, .position);
|
});
|
||||||
for (ids, positions) |id, position| {
|
while (q.next()) |v| {
|
||||||
|
for (v.ids, v.positions) |id, position| {
|
||||||
// Nested query to find all the other follower entities that we should move away from.
|
// Nested query to find all the other follower entities that we should move away from.
|
||||||
// We will avoid all other follower entities if we're too close to them.
|
// We will avoid all other follower entities if we're too close to them.
|
||||||
// This is not very efficient, but it works!
|
// This is not very efficient, but it works!
|
||||||
const close_dist = 1.0 / 15.0;
|
const close_dist = 1.0 / 15.0;
|
||||||
var avoidance = Vec3.splat(0);
|
var avoidance = Vec3.splat(0);
|
||||||
var avoidance_div: f32 = 1.0;
|
var avoidance_div: f32 = 1.0;
|
||||||
var archetypes_iter_2 = core.__entities.queryDeprecated(.{ .all = &.{
|
|
||||||
.{ .app = &.{.follower} },
|
var q2 = try entities.query(.{
|
||||||
} });
|
.ids = mach.Entities.Mod.read(.id),
|
||||||
while (archetypes_iter_2.next()) |archetype_2| {
|
.followers = Mod.read(.follower),
|
||||||
const other_ids = archetype_2.slice(.entities, .id);
|
.positions = Renderer.Mod.read(.position),
|
||||||
const other_positions = archetype_2.slice(.renderer, .position);
|
});
|
||||||
for (other_ids, other_positions) |other_id, other_position| {
|
while (q2.next()) |v2| {
|
||||||
|
for (v2.ids, v2.positions) |other_id, other_position| {
|
||||||
if (id == other_id) continue;
|
if (id == other_id) continue;
|
||||||
if (position.dist(&other_position) < close_dist) {
|
if (position.dist(&other_position) < close_dist) {
|
||||||
avoidance = avoidance.sub(&position.dir(&other_position, 0.0000001));
|
avoidance = avoidance.sub(&position.dir(&other_position, 0.0000001));
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,7 @@ fn deinit(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderFrame(
|
fn renderFrame(
|
||||||
|
entities: *mach.Entities.Mod,
|
||||||
core: *mach.Core.Mod,
|
core: *mach.Core.Mod,
|
||||||
renderer: *Mod,
|
renderer: *Mod,
|
||||||
) !void {
|
) !void {
|
||||||
|
|
@ -138,17 +139,13 @@ fn renderFrame(
|
||||||
defer encoder.release();
|
defer encoder.release();
|
||||||
|
|
||||||
// Update uniform buffer
|
// Update uniform buffer
|
||||||
var archetypes_iter = core.__entities.queryDeprecated(.{ .all = &.{
|
|
||||||
.{ .renderer = &.{ .position, .scale } },
|
|
||||||
} });
|
|
||||||
var num_entities: usize = 0;
|
var num_entities: usize = 0;
|
||||||
while (archetypes_iter.next()) |archetype| {
|
var q = try entities.query(.{
|
||||||
const ids = archetype.slice(.entities, .id);
|
.positions = Mod.read(.position),
|
||||||
const positions = archetype.slice(.renderer, .position);
|
.scales = Mod.read(.scale),
|
||||||
const scales = archetype.slice(.renderer, .scale);
|
});
|
||||||
for (ids, positions, scales) |id, position, scale| {
|
while (q.next()) |v| {
|
||||||
_ = id;
|
for (v.positions, v.scales) |position, scale| {
|
||||||
|
|
||||||
const ubo = UniformBufferObject{
|
const ubo = UniformBufferObject{
|
||||||
.offset = position,
|
.offset = position,
|
||||||
.scale = scale,
|
.scale = scale,
|
||||||
|
|
|
||||||
|
|
@ -165,18 +165,17 @@ fn tick(
|
||||||
const delta_time = game.state().timer.lap();
|
const delta_time = game.state().timer.lap();
|
||||||
|
|
||||||
// Animate entities
|
// Animate entities
|
||||||
var archetypes_iter = core.__entities.queryDeprecated(.{ .all = &.{
|
var q = try entities.query(.{
|
||||||
.{ .mach_gfx_sprite = &.{.transform} },
|
.ids = mach.Entities.Mod.read(.id),
|
||||||
} });
|
.transforms = gfx.Sprite.Mod.write(.transform),
|
||||||
while (archetypes_iter.next()) |archetype| {
|
});
|
||||||
const ids = archetype.slice(.entities, .id);
|
while (q.next()) |v| {
|
||||||
const transforms = archetype.slice(.mach_gfx_sprite, .transform);
|
for (v.ids, v.transforms) |id, *entity_transform| {
|
||||||
for (ids, transforms) |id, *old_transform| {
|
var location = entity_transform.translation();
|
||||||
var location = old_transform.translation();
|
|
||||||
// TODO: formatting
|
// TODO: formatting
|
||||||
// TODO(Core)
|
// TODO(Core)
|
||||||
if (location.x() < -@as(f32, @floatFromInt(mach.core.size().width)) / 1.5 or location.x() > @as(f32, @floatFromInt(mach.core.size().width)) / 1.5 or location.y() < -@as(f32, @floatFromInt(mach.core.size().height)) / 1.5 or location.y() > @as(f32, @floatFromInt(mach.core.size().height)) / 1.5) {
|
if (location.x() < -@as(f32, @floatFromInt(mach.core.size().width)) / 1.5 or location.x() > @as(f32, @floatFromInt(mach.core.size().width)) / 1.5 or location.y() < -@as(f32, @floatFromInt(mach.core.size().height)) / 1.5 or location.y() > @as(f32, @floatFromInt(mach.core.size().height)) / 1.5) {
|
||||||
try core.__entities.remove(id);
|
try entities.remove(id);
|
||||||
game.state().sprites -= 1;
|
game.state().sprites -= 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -186,10 +185,7 @@ fn tick(
|
||||||
transform = transform.mul(&Mat4x4.translate(location));
|
transform = transform.mul(&Mat4x4.translate(location));
|
||||||
transform = transform.mul(&Mat4x4.rotateZ(2 * math.pi * game.state().time));
|
transform = transform.mul(&Mat4x4.rotateZ(2 * math.pi * game.state().time));
|
||||||
transform = transform.mul(&Mat4x4.scale(Vec3.splat(@max(math.cos(game.state().time / 2.0), 0.2))));
|
transform = transform.mul(&Mat4x4.scale(Vec3.splat(@max(math.cos(game.state().time / 2.0), 0.2))));
|
||||||
|
entity_transform.* = transform;
|
||||||
// TODO: .set() API is substantially slower due to internals
|
|
||||||
// try sprite.set(id, .transform, transform);
|
|
||||||
old_transform.* = transform;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,14 +70,12 @@ fn audioStateChange(
|
||||||
app: *Mod,
|
app: *Mod,
|
||||||
) !void {
|
) !void {
|
||||||
// Find audio entities that are no longer playing
|
// Find audio entities that are no longer playing
|
||||||
var archetypes_iter = audio.__entities.queryDeprecated(.{ .all = &.{
|
var q = try entities.query(.{
|
||||||
.{ .mach_audio = &.{.playing} },
|
.ids = mach.Entities.Mod.read(.id),
|
||||||
} });
|
.playings = mach.Audio.Mod.read(.playing),
|
||||||
while (archetypes_iter.next()) |archetype| {
|
});
|
||||||
for (
|
while (q.next()) |v| {
|
||||||
archetype.slice(.entities, .id),
|
for (v.ids, v.playings) |id, playing| {
|
||||||
archetype.slice(.mach_audio, .playing),
|
|
||||||
) |id, playing| {
|
|
||||||
if (playing) continue;
|
if (playing) continue;
|
||||||
|
|
||||||
if (app.get(id, .play_after)) |frequency| {
|
if (app.get(id, .play_after)) |frequency| {
|
||||||
|
|
|
||||||
|
|
@ -85,12 +85,12 @@ fn audioStateChange(
|
||||||
app: *Mod,
|
app: *Mod,
|
||||||
) !void {
|
) !void {
|
||||||
// Find audio entities that are no longer playing
|
// Find audio entities that are no longer playing
|
||||||
var archetypes_iter = audio.__entities.queryDeprecated(.{ .all = &.{.{ .mach_audio = &.{.playing} }} });
|
var q = try entities.query(.{
|
||||||
while (archetypes_iter.next()) |archetype| {
|
.ids = mach.Entities.Mod.read(.id),
|
||||||
for (
|
.playings = mach.Audio.Mod.read(.playing),
|
||||||
archetype.slice(.entities, .id),
|
});
|
||||||
archetype.slice(.mach_audio, .playing),
|
while (q.next()) |v| {
|
||||||
) |id, playing| {
|
for (v.ids, v.playings) |id, playing| {
|
||||||
if (playing) continue;
|
if (playing) continue;
|
||||||
|
|
||||||
if (app.get(id, .is_bgm)) |_| {
|
if (app.get(id, .is_bgm)) |_| {
|
||||||
|
|
|
||||||
|
|
@ -158,26 +158,20 @@ fn tick(
|
||||||
const delta_time = game.state().timer.lap();
|
const delta_time = game.state().timer.lap();
|
||||||
|
|
||||||
// Rotate entities
|
// Rotate entities
|
||||||
var archetypes_iter = core.__entities.queryDeprecated(.{ .all = &.{
|
var q = try entities.query(.{
|
||||||
.{ .mach_gfx_sprite = &.{.transform} },
|
.transforms = gfx.Sprite.Mod.write(.transform),
|
||||||
} });
|
});
|
||||||
while (archetypes_iter.next()) |archetype| {
|
while (q.next()) |v| {
|
||||||
const ids = archetype.slice(.entities, .id);
|
for (v.transforms) |*entity_transform| {
|
||||||
const transforms = archetype.slice(.mach_gfx_sprite, .transform);
|
const location = entity_transform.*.translation();
|
||||||
for (ids, transforms) |id, *old_transform| {
|
// var transform = entity_transform.mul(&Mat4x4.translate(-location));
|
||||||
_ = id;
|
|
||||||
const location = old_transform.*.translation();
|
|
||||||
// var transform = old_transform.mul(&Mat4x4.translate(-location));
|
|
||||||
// transform = mat.rotateZ(0.3 * delta_time).mul(&transform);
|
// transform = mat.rotateZ(0.3 * delta_time).mul(&transform);
|
||||||
// transform = transform.mul(&Mat4x4.translate(location));
|
// transform = transform.mul(&Mat4x4.translate(location));
|
||||||
var transform = Mat4x4.ident;
|
var transform = Mat4x4.ident;
|
||||||
transform = transform.mul(&Mat4x4.translate(location));
|
transform = transform.mul(&Mat4x4.translate(location));
|
||||||
transform = transform.mul(&Mat4x4.rotateZ(2 * math.pi * game.state().time));
|
transform = transform.mul(&Mat4x4.rotateZ(2 * math.pi * game.state().time));
|
||||||
transform = transform.mul(&Mat4x4.scaleScalar(@min(math.cos(game.state().time / 2.0), 0.5)));
|
transform = transform.mul(&Mat4x4.scaleScalar(@min(math.cos(game.state().time / 2.0), 0.5)));
|
||||||
|
entity_transform.* = transform;
|
||||||
// TODO: .set() API is substantially slower due to internals
|
|
||||||
// try sprite.set(id, .transform, transform);
|
|
||||||
old_transform.* = transform;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -201,15 +201,12 @@ fn tick(
|
||||||
const delta_time = game.state().timer.lap();
|
const delta_time = game.state().timer.lap();
|
||||||
|
|
||||||
// Rotate entities
|
// Rotate entities
|
||||||
var archetypes_iter = core.__entities.queryDeprecated(.{ .all = &.{
|
var q = try entities.query(.{
|
||||||
.{ .mach_gfx_text = &.{.transform} },
|
.transforms = gfx.Text.Mod.write(.transform),
|
||||||
} });
|
});
|
||||||
while (archetypes_iter.next()) |archetype| {
|
while (q.next()) |v| {
|
||||||
const ids = archetype.slice(.entities, .id);
|
for (v.transforms) |*entity_transform| {
|
||||||
const transforms = archetype.slice(.mach_gfx_text, .transform);
|
const location = entity_transform.*.translation();
|
||||||
for (ids, transforms) |id, *old_transform| {
|
|
||||||
_ = id;
|
|
||||||
const location = old_transform.*.translation();
|
|
||||||
// var transform = old_transform.mul(&Mat4x4.translate(-location));
|
// var transform = old_transform.mul(&Mat4x4.translate(-location));
|
||||||
// transform = mat.rotateZ(0.3 * delta_time).mul(&transform);
|
// transform = mat.rotateZ(0.3 * delta_time).mul(&transform);
|
||||||
// transform = transform.mul(&Mat4x4.translate(location));
|
// transform = transform.mul(&Mat4x4.translate(location));
|
||||||
|
|
@ -217,10 +214,7 @@ fn tick(
|
||||||
transform = transform.mul(&Mat4x4.translate(location));
|
transform = transform.mul(&Mat4x4.translate(location));
|
||||||
transform = transform.mul(&Mat4x4.rotateZ(2 * math.pi * game.state().time));
|
transform = transform.mul(&Mat4x4.rotateZ(2 * math.pi * game.state().time));
|
||||||
transform = transform.mul(&Mat4x4.scaleScalar(@min(math.cos(game.state().time / 2.0), 0.5)));
|
transform = transform.mul(&Mat4x4.scaleScalar(@min(math.cos(game.state().time / 2.0), 0.5)));
|
||||||
|
entity_transform.* = transform;
|
||||||
// TODO: .set() API is substantially slower due to internals
|
|
||||||
// try text.set(id, .transform, transform);
|
|
||||||
old_transform.* = transform;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -268,7 +262,11 @@ fn tick(
|
||||||
game.state().time += delta_time;
|
game.state().time += delta_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn endFrame(game: *Mod, text: *gfx.Text.Mod, core: *mach.Core.Mod) !void {
|
fn endFrame(
|
||||||
|
entities: *mach.Entities.Mod,
|
||||||
|
game: *Mod,
|
||||||
|
core: *mach.Core.Mod,
|
||||||
|
) !void {
|
||||||
// Finish render pass
|
// Finish render pass
|
||||||
game.state().frame_render_pass.end();
|
game.state().frame_render_pass.end();
|
||||||
const label = @tagName(name) ++ ".tick";
|
const label = @tagName(name) ++ ".tick";
|
||||||
|
|
@ -285,14 +283,11 @@ fn endFrame(game: *Mod, text: *gfx.Text.Mod, core: *mach.Core.Mod) !void {
|
||||||
// Gather some text rendering stats
|
// Gather some text rendering stats
|
||||||
var num_texts: u32 = 0;
|
var num_texts: u32 = 0;
|
||||||
var num_glyphs: usize = 0;
|
var num_glyphs: usize = 0;
|
||||||
var archetypes_iter = text.__entities.queryDeprecated(.{ .all = &.{
|
var q = try entities.query(.{
|
||||||
.{ .mach_gfx_text = &.{
|
.built_pipelines = gfx.Text.Mod.read(.built),
|
||||||
.built,
|
});
|
||||||
} },
|
while (q.next()) |v| {
|
||||||
} });
|
for (v.built_pipelines) |built| {
|
||||||
while (archetypes_iter.next()) |archetype| {
|
|
||||||
const builts = archetype.slice(.mach_gfx_text, .built);
|
|
||||||
for (builts) |built| {
|
|
||||||
num_texts += 1;
|
num_texts += 1;
|
||||||
num_glyphs += built.glyphs.items.len;
|
num_glyphs += built.glyphs.items.len;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ fn deinit(audio: *Mod) void {
|
||||||
/// instead. At the same time, we don't want to play too far ahead as that would cause latency
|
/// instead. At the same time, we don't want to play too far ahead as that would cause latency
|
||||||
/// between e.g. user interactions and audio actually playing - so in practice the amount we play
|
/// between e.g. user interactions and audio actually playing - so in practice the amount we play
|
||||||
/// ahead is rather small and imperceivable to most humans.
|
/// ahead is rather small and imperceivable to most humans.
|
||||||
fn audioTick(audio: *Mod) !void {
|
fn audioTick(entities: *mach.Entities.Mod, audio: *Mod) !void {
|
||||||
const allocator = audio.state().allocator;
|
const allocator = audio.state().allocator;
|
||||||
const player = &audio.state().player;
|
const player = &audio.state().player;
|
||||||
const player_channels: u8 = @intCast(player.channels().len);
|
const player_channels: u8 = @intCast(player.channels().len);
|
||||||
|
|
@ -134,17 +134,15 @@ fn audioTick(audio: *Mod) !void {
|
||||||
@memset(mixing_buffer.items, 0);
|
@memset(mixing_buffer.items, 0);
|
||||||
|
|
||||||
var did_state_change = false;
|
var did_state_change = false;
|
||||||
var archetypes_iter = audio.__entities.queryDeprecated(.{ .all = &.{
|
var q = try entities.query(.{
|
||||||
.{ .mach_audio = &.{ .samples, .channels, .playing, .index } },
|
.ids = mach.Entities.Mod.read(.id),
|
||||||
} });
|
.samples_slices = Mod.read(.samples),
|
||||||
while (archetypes_iter.next()) |archetype| {
|
.channels = Mod.read(.channels),
|
||||||
for (
|
.playings = Mod.read(.playing),
|
||||||
archetype.slice(.entities, .id),
|
.indexes = Mod.read(.index),
|
||||||
archetype.slice(.mach_audio, .samples),
|
});
|
||||||
archetype.slice(.mach_audio, .channels),
|
while (q.next()) |v| {
|
||||||
archetype.slice(.mach_audio, .playing),
|
for (v.ids, v.samples_slices, v.channels, v.playings, v.indexes) |id, samples, channels, playing, index| {
|
||||||
archetype.slice(.mach_audio, .index),
|
|
||||||
) |id, samples, channels, playing, index| {
|
|
||||||
if (!playing) continue;
|
if (!playing) continue;
|
||||||
|
|
||||||
const channels_diff = player_channels - channels + 1;
|
const channels_diff = player_channels - channels + 1;
|
||||||
|
|
|
||||||
37
src/Core.zig
37
src/Core.zig
|
|
@ -131,21 +131,16 @@ fn init(entities: *mach.Entities.Mod, core: *Mod) !void {
|
||||||
mach.core.mods.send(.app, .init, .{});
|
mach.core.mods.send(.app, .init, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(core: *Mod) !void {
|
fn update(entities: *mach.Entities.Mod) !void {
|
||||||
var archetypes_iter = core.__entities.queryDeprecated(.{ .all = &.{
|
|
||||||
.{ .mach_core = &.{
|
|
||||||
.title,
|
|
||||||
} },
|
|
||||||
} });
|
|
||||||
|
|
||||||
var num_windows: usize = 0;
|
var num_windows: usize = 0;
|
||||||
while (archetypes_iter.next()) |archetype| {
|
var q = try entities.query(.{
|
||||||
for (
|
.ids = mach.Entities.Mod.read(.id),
|
||||||
archetype.slice(.entities, .id),
|
.titles = Mod.read(.title),
|
||||||
archetype.slice(.mach_core, .title),
|
});
|
||||||
) |window_id, title| {
|
while (q.next()) |v| {
|
||||||
num_windows += 1;
|
for (v.ids, v.titles) |window_id, title| {
|
||||||
_ = window_id;
|
_ = window_id;
|
||||||
|
num_windows += 1;
|
||||||
try mach.core.printTitle("{s}", .{title});
|
try mach.core.printTitle("{s}", .{title});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -169,17 +164,17 @@ fn presentFrame(core: *Mod) !void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(core: *Mod) void {
|
fn deinit(entities: *mach.Entities.Mod, core: *Mod) !void {
|
||||||
core.state().queue.release();
|
core.state().queue.release();
|
||||||
mach.core.deinit();
|
mach.core.deinit();
|
||||||
|
|
||||||
var archetypes_iter = core.__entities.queryDeprecated(.{ .all = &.{
|
var q = try entities.query(.{
|
||||||
.{ .mach_core = &.{
|
.titles = Mod.read(.title),
|
||||||
.title,
|
});
|
||||||
} },
|
while (q.next()) |v| {
|
||||||
} });
|
for (v.titles) |title| {
|
||||||
while (archetypes_iter.next()) |archetype| {
|
core.state().allocator.free(title);
|
||||||
for (archetype.slice(.mach_core, .title)) |title| core.state().allocator.free(title);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = gpa.deinit();
|
_ = gpa.deinit();
|
||||||
|
|
|
||||||
|
|
@ -42,56 +42,50 @@ pub const events = .{
|
||||||
.update = .{ .handler = update },
|
.update = .{ .handler = update },
|
||||||
};
|
};
|
||||||
|
|
||||||
fn update(core: *mach.Core.Mod, sprite: *Mod, sprite_pipeline: *gfx.SpritePipeline.Mod) !void {
|
fn update(
|
||||||
var archetypes_iter = sprite_pipeline.__entities.queryDeprecated(.{ .all = &.{
|
entities: *mach.Entities.Mod,
|
||||||
.{ .mach_gfx_sprite_pipeline = &.{
|
core: *mach.Core.Mod,
|
||||||
.built,
|
sprite_pipeline: *gfx.SpritePipeline.Mod,
|
||||||
} },
|
) !void {
|
||||||
} });
|
var q = try entities.query(.{
|
||||||
while (archetypes_iter.next()) |archetype| {
|
.ids = mach.Entities.Mod.read(.id),
|
||||||
const ids = archetype.slice(.entities, .id);
|
.built_pipelines = gfx.SpritePipeline.Mod.read(.built),
|
||||||
const built_pipelines = archetype.slice(.mach_gfx_sprite_pipeline, .built);
|
});
|
||||||
for (ids, built_pipelines) |pipeline_id, *built| {
|
while (q.next()) |v| {
|
||||||
try updatePipeline(core, sprite, sprite_pipeline, pipeline_id, built);
|
for (v.ids, v.built_pipelines) |pipeline_id, built| {
|
||||||
|
try updatePipeline(entities, core, sprite_pipeline, pipeline_id, &built);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn updatePipeline(
|
fn updatePipeline(
|
||||||
|
entities: *mach.Entities.Mod,
|
||||||
core: *mach.Core.Mod,
|
core: *mach.Core.Mod,
|
||||||
sprite: *Mod,
|
|
||||||
sprite_pipeline: *gfx.SpritePipeline.Mod,
|
sprite_pipeline: *gfx.SpritePipeline.Mod,
|
||||||
pipeline_id: mach.EntityID,
|
pipeline_id: mach.EntityID,
|
||||||
built: *gfx.SpritePipeline.BuiltPipeline,
|
built: *const gfx.SpritePipeline.BuiltPipeline,
|
||||||
) !void {
|
) !void {
|
||||||
const device = core.state().device;
|
const device = core.state().device;
|
||||||
const label = @tagName(name) ++ ".updatePipeline";
|
const label = @tagName(name) ++ ".updatePipeline";
|
||||||
const encoder = device.createCommandEncoder(&.{ .label = label });
|
const encoder = device.createCommandEncoder(&.{ .label = label });
|
||||||
defer encoder.release();
|
defer encoder.release();
|
||||||
|
|
||||||
var archetypes_iter = sprite.__entities.queryDeprecated(.{ .all = &.{
|
|
||||||
.{ .mach_gfx_sprite = &.{
|
|
||||||
.uv_transform,
|
|
||||||
.transform,
|
|
||||||
.size,
|
|
||||||
.pipeline,
|
|
||||||
} },
|
|
||||||
} });
|
|
||||||
var num_sprites: u32 = 0;
|
var num_sprites: u32 = 0;
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (archetypes_iter.next()) |archetype| {
|
var q = try entities.query(.{
|
||||||
const transforms = archetype.slice(.mach_gfx_sprite, .transform);
|
.transforms = Mod.read(.transform),
|
||||||
const uv_transforms = archetype.slice(.mach_gfx_sprite, .uv_transform);
|
.uv_transforms = Mod.read(.uv_transform),
|
||||||
const sizes = archetype.slice(.mach_gfx_sprite, .size);
|
.sizes = Mod.read(.size),
|
||||||
const pipelines = archetype.slice(.mach_gfx_sprite, .pipeline);
|
.pipelines = Mod.read(.pipeline),
|
||||||
|
});
|
||||||
|
while (q.next()) |v| {
|
||||||
|
for (v.transforms, v.uv_transforms, v.sizes, v.pipelines) |transform, uv_transform, size, sprite_pipeline_id| {
|
||||||
// TODO: currently we cannot query all sprites which have a _single_ pipeline component
|
// TODO: currently we cannot query all sprites which have a _single_ pipeline component
|
||||||
// value and get back contiguous memory for all of them. This is because all sprites with
|
// value and get back contiguous memory for all of them. This is because all sprites with
|
||||||
// possibly different pipeline component values are stored as the same archetype. If we
|
// possibly different pipeline component values are stored as the same archetype. If we
|
||||||
// introduce a new concept of tagging-by-value to our entity storage then we can enforce
|
// introduce a new concept of tagging-by-value to our entity storage then we can enforce
|
||||||
// that all entities with the same pipeline value are stored in contiguous memory, and
|
// that all entities with the same pipeline value are stored in contiguous memory, and
|
||||||
// skip this copy.
|
// skip this copy.
|
||||||
for (transforms, uv_transforms, sizes, pipelines) |transform, uv_transform, size, sprite_pipeline_id| {
|
|
||||||
if (sprite_pipeline_id == pipeline_id) {
|
if (sprite_pipeline_id == pipeline_id) {
|
||||||
gfx.SpritePipeline.cp_transforms[i] = transform;
|
gfx.SpritePipeline.cp_transforms[i] = transform;
|
||||||
gfx.SpritePipeline.cp_uv_transforms[i] = uv_transform;
|
gfx.SpritePipeline.cp_uv_transforms[i] = uv_transform;
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ pub const BuiltPipeline = struct {
|
||||||
uv_transforms: *gpu.Buffer,
|
uv_transforms: *gpu.Buffer,
|
||||||
sizes: *gpu.Buffer,
|
sizes: *gpu.Buffer,
|
||||||
|
|
||||||
pub fn deinit(p: *BuiltPipeline) void {
|
pub fn deinit(p: *const BuiltPipeline) void {
|
||||||
p.render.release();
|
p.render.release();
|
||||||
p.texture_sampler.release();
|
p.texture_sampler.release();
|
||||||
p.texture.release();
|
p.texture.release();
|
||||||
|
|
@ -123,31 +123,27 @@ fn init(sprite_pipeline: *Mod) void {
|
||||||
sprite_pipeline.init(.{});
|
sprite_pipeline.init(.{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(sprite_pipeline: *Mod) void {
|
fn deinit(entities: *mach.Entities.Mod) !void {
|
||||||
var archetypes_iter = sprite_pipeline.__entities.queryDeprecated(.{ .all = &.{
|
var q = try entities.query(.{
|
||||||
.{ .mach_gfx_sprite_pipeline = &.{
|
.built_pipelines = Mod.read(.built),
|
||||||
.built,
|
});
|
||||||
} },
|
while (q.next()) |v| {
|
||||||
} });
|
for (v.built_pipelines) |built| {
|
||||||
while (archetypes_iter.next()) |archetype| {
|
built.deinit();
|
||||||
for (archetype.slice(.mach_gfx_sprite_pipeline, .built)) |*p| p.deinit();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(core: *mach.Core.Mod, sprite_pipeline: *Mod) !void {
|
fn update(entities: *mach.Entities.Mod, core: *mach.Core.Mod, sprite_pipeline: *Mod) !void {
|
||||||
// Destroy all sprite render pipelines. We will rebuild them all.
|
// Destroy all sprite render pipelines. We will rebuild them all.
|
||||||
deinit(sprite_pipeline);
|
try deinit(entities);
|
||||||
|
|
||||||
var archetypes_iter = sprite_pipeline.__entities.queryDeprecated(.{ .all = &.{
|
var q = try entities.query(.{
|
||||||
.{ .mach_gfx_sprite_pipeline = &.{
|
.ids = mach.Entities.Mod.read(.id),
|
||||||
.texture,
|
.textures = Mod.read(.texture),
|
||||||
} },
|
});
|
||||||
} });
|
while (q.next()) |v| {
|
||||||
while (archetypes_iter.next()) |archetype| {
|
for (v.ids, v.textures) |pipeline_id, texture| {
|
||||||
const ids = archetype.slice(.entities, .id);
|
|
||||||
const textures = archetype.slice(.mach_gfx_sprite_pipeline, .texture);
|
|
||||||
|
|
||||||
for (ids, textures) |pipeline_id, texture| {
|
|
||||||
try buildPipeline(core, sprite_pipeline, pipeline_id, texture);
|
try buildPipeline(core, sprite_pipeline, pipeline_id, texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -319,19 +315,16 @@ fn buildPipeline(
|
||||||
try sprite_pipeline.set(pipeline_id, .num_sprites, 0);
|
try sprite_pipeline.set(pipeline_id, .num_sprites, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn preRender(sprite_pipeline: *Mod, core: *mach.Core.Mod) void {
|
fn preRender(entities: *mach.Entities.Mod, core: *mach.Core.Mod) !void {
|
||||||
const label = @tagName(name) ++ ".preRender";
|
const label = @tagName(name) ++ ".preRender";
|
||||||
const encoder = core.state().device.createCommandEncoder(&.{ .label = label });
|
const encoder = core.state().device.createCommandEncoder(&.{ .label = label });
|
||||||
defer encoder.release();
|
defer encoder.release();
|
||||||
|
|
||||||
var archetypes_iter = sprite_pipeline.__entities.queryDeprecated(.{ .all = &.{
|
var q = try entities.query(.{
|
||||||
.{ .mach_gfx_sprite_pipeline = &.{
|
.built_pipelines = Mod.read(.built),
|
||||||
.built,
|
});
|
||||||
} },
|
while (q.next()) |v| {
|
||||||
} });
|
for (v.built_pipelines) |built| {
|
||||||
while (archetypes_iter.next()) |archetype| {
|
|
||||||
const built_pipelines = archetype.slice(.mach_gfx_sprite_pipeline, .built);
|
|
||||||
for (built_pipelines) |built| {
|
|
||||||
// Create the projection matrix
|
// Create the projection matrix
|
||||||
// TODO(sprite): move this out of the hot codepath
|
// TODO(sprite): move this out of the hot codepath
|
||||||
const proj = math.Mat4x4.projection2D(.{
|
const proj = math.Mat4x4.projection2D(.{
|
||||||
|
|
@ -362,20 +355,17 @@ fn preRender(sprite_pipeline: *Mod, core: *mach.Core.Mod) void {
|
||||||
core.state().queue.submit(&[_]*gpu.CommandBuffer{command});
|
core.state().queue.submit(&[_]*gpu.CommandBuffer{command});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(sprite_pipeline: *Mod) !void {
|
fn render(entities: *mach.Entities.Mod, sprite_pipeline: *Mod) !void {
|
||||||
const render_pass = if (sprite_pipeline.state().render_pass) |rp| rp else std.debug.panic("sprite_pipeline.state().render_pass must be specified", .{});
|
const render_pass = if (sprite_pipeline.state().render_pass) |rp| rp else std.debug.panic("sprite_pipeline.state().render_pass must be specified", .{});
|
||||||
sprite_pipeline.state().render_pass = null;
|
sprite_pipeline.state().render_pass = null;
|
||||||
|
|
||||||
// TODO(sprite): need a way to specify order of rendering with multiple pipelines
|
// TODO(sprite): need a way to specify order of rendering with multiple pipelines
|
||||||
var archetypes_iter = sprite_pipeline.__entities.queryDeprecated(.{ .all = &.{
|
var q = try entities.query(.{
|
||||||
.{ .mach_gfx_sprite_pipeline = &.{
|
.ids = mach.Entities.Mod.read(.id),
|
||||||
.built,
|
.built_pipelines = Mod.read(.built),
|
||||||
} },
|
});
|
||||||
} });
|
while (q.next()) |v| {
|
||||||
while (archetypes_iter.next()) |archetype| {
|
for (v.ids, v.built_pipelines) |pipeline_id, built| {
|
||||||
const ids = archetype.slice(.entities, .id);
|
|
||||||
const built_pipelines = archetype.slice(.mach_gfx_sprite_pipeline, .built);
|
|
||||||
for (ids, built_pipelines) |pipeline_id, built| {
|
|
||||||
// Draw the sprite batch
|
// Draw the sprite batch
|
||||||
const total_vertices = sprite_pipeline.get(pipeline_id, .num_sprites).? * 6;
|
const total_vertices = sprite_pipeline.get(pipeline_id, .num_sprites).? * 6;
|
||||||
render_pass.setPipeline(built.render);
|
render_pass.setPipeline(built.render);
|
||||||
|
|
|
||||||
|
|
@ -58,24 +58,27 @@ const BuiltText = struct {
|
||||||
glyphs: std.ArrayListUnmanaged(gfx.TextPipeline.Glyph),
|
glyphs: std.ArrayListUnmanaged(gfx.TextPipeline.Glyph),
|
||||||
};
|
};
|
||||||
|
|
||||||
fn update(core: *mach.Core.Mod, text: *Mod, text_pipeline: *gfx.TextPipeline.Mod) !void {
|
fn update(
|
||||||
var archetypes_iter = text_pipeline.__entities.queryDeprecated(.{ .all = &.{
|
entities: *mach.Entities.Mod,
|
||||||
.{ .mach_gfx_text_pipeline = &.{
|
text: *Mod,
|
||||||
.built,
|
core: *mach.Core.Mod,
|
||||||
} },
|
text_pipeline: *gfx.TextPipeline.Mod,
|
||||||
} });
|
) !void {
|
||||||
while (archetypes_iter.next()) |archetype| {
|
var q = try entities.query(.{
|
||||||
const ids = archetype.slice(.entities, .id);
|
.ids = mach.Entities.Mod.read(.id),
|
||||||
const built_pipelines = archetype.slice(.mach_gfx_text_pipeline, .built);
|
.built_pipelines = gfx.TextPipeline.Mod.write(.built),
|
||||||
for (ids, built_pipelines) |pipeline_id, *built| {
|
});
|
||||||
try updatePipeline(core, text, text_pipeline, pipeline_id, built);
|
while (q.next()) |v| {
|
||||||
|
for (v.ids, v.built_pipelines) |pipeline_id, *built| {
|
||||||
|
try updatePipeline(entities, text, core, text_pipeline, pipeline_id, built);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn updatePipeline(
|
fn updatePipeline(
|
||||||
core: *mach.Core.Mod,
|
entities: *mach.Entities.Mod,
|
||||||
text: *Mod,
|
text: *Mod,
|
||||||
|
core: *mach.Core.Mod,
|
||||||
text_pipeline: *gfx.TextPipeline.Mod,
|
text_pipeline: *gfx.TextPipeline.Mod,
|
||||||
pipeline_id: mach.EntityID,
|
pipeline_id: mach.EntityID,
|
||||||
built: *gfx.TextPipeline.BuiltPipeline,
|
built: *gfx.TextPipeline.BuiltPipeline,
|
||||||
|
|
@ -97,28 +100,22 @@ fn updatePipeline(
|
||||||
var texture_update = false;
|
var texture_update = false;
|
||||||
var num_texts: u32 = 0;
|
var num_texts: u32 = 0;
|
||||||
var removes = try std.ArrayListUnmanaged(mach.EntityID).initCapacity(allocator, 8);
|
var removes = try std.ArrayListUnmanaged(mach.EntityID).initCapacity(allocator, 8);
|
||||||
var archetypes_iter = text.__entities.queryDeprecated(.{ .all = &.{
|
|
||||||
.{ .mach_gfx_text = &.{
|
|
||||||
.transform,
|
|
||||||
.text,
|
|
||||||
.style,
|
|
||||||
.pipeline,
|
|
||||||
} },
|
|
||||||
} });
|
|
||||||
while (archetypes_iter.next()) |archetype| {
|
|
||||||
const ids = archetype.slice(.entities, .id);
|
|
||||||
const transforms = archetype.slice(.mach_gfx_text, .transform);
|
|
||||||
const segment_slices = archetype.slice(.mach_gfx_text, .text);
|
|
||||||
const style_slices = archetype.slice(.mach_gfx_text, .style);
|
|
||||||
const pipelines = archetype.slice(.mach_gfx_text, .pipeline);
|
|
||||||
|
|
||||||
|
var q = try entities.query(.{
|
||||||
|
.ids = mach.Entities.Mod.read(.id),
|
||||||
|
.transforms = Mod.read(.transform),
|
||||||
|
.segment_slices = Mod.read(.text),
|
||||||
|
.style_slices = Mod.read(.style),
|
||||||
|
.pipelines = Mod.read(.pipeline),
|
||||||
|
});
|
||||||
|
while (q.next()) |v| {
|
||||||
|
for (v.ids, v.transforms, v.segment_slices, v.style_slices, v.pipelines) |id, transform, segments, styles, text_pipeline_id| {
|
||||||
// TODO: currently we cannot query all texts which have a _single_ pipeline component
|
// TODO: currently we cannot query all texts which have a _single_ pipeline component
|
||||||
// value and get back contiguous memory for all of them. This is because all texts with
|
// value and get back contiguous memory for all of them. This is because all texts with
|
||||||
// possibly different pipeline component values are stored as the same archetype. If we
|
// possibly different pipeline component values are stored as the same archetype. If we
|
||||||
// introduce a new concept of tagging-by-value to our entity storage then we can enforce
|
// introduce a new concept of tagging-by-value to our entity storage then we can enforce
|
||||||
// that all entities with the same pipeline value are stored in contiguous memory, and
|
// that all entities with the same pipeline value are stored in contiguous memory, and
|
||||||
// skip this copy.
|
// skip this copy.
|
||||||
for (ids, transforms, segment_slices, style_slices, pipelines) |id, transform, segments, styles, text_pipeline_id| {
|
|
||||||
if (text_pipeline_id != pipeline_id) continue;
|
if (text_pipeline_id != pipeline_id) continue;
|
||||||
|
|
||||||
gfx.TextPipeline.cp_transforms[num_texts] = transform;
|
gfx.TextPipeline.cp_transforms[num_texts] = transform;
|
||||||
|
|
|
||||||
|
|
@ -144,33 +144,31 @@ pub const BuiltPipeline = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn deinit(text_pipeline: *Mod) void {
|
fn deinit(entities: *mach.Entities.Mod, text_pipeline: *Mod) !void {
|
||||||
var archetypes_iter = text_pipeline.__entities.queryDeprecated(.{ .all = &.{
|
var q = try entities.query(.{
|
||||||
.{ .mach_gfx_text_pipeline = &.{
|
.built_pipelines = Mod.write(.built),
|
||||||
.built,
|
});
|
||||||
} },
|
while (q.next()) |v| {
|
||||||
} });
|
for (v.built_pipelines) |*built| {
|
||||||
while (archetypes_iter.next()) |archetype| {
|
built.deinit(text_pipeline.state().allocator);
|
||||||
for (archetype.slice(.mach_gfx_text_pipeline, .built)) |*p| p.deinit(text_pipeline.state().allocator);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(core: *mach.Core.Mod, text_pipeline: *Mod) !void {
|
fn update(entities: *mach.Entities.Mod, core: *mach.Core.Mod, text_pipeline: *Mod) !void {
|
||||||
text_pipeline.init(.{
|
text_pipeline.init(.{
|
||||||
.allocator = gpa.allocator(),
|
.allocator = gpa.allocator(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Destroy all text render pipelines. We will rebuild them all.
|
// Destroy all text render pipelines. We will rebuild them all.
|
||||||
deinit(text_pipeline);
|
try deinit(entities, text_pipeline);
|
||||||
|
|
||||||
var archetypes_iter = text_pipeline.__entities.queryDeprecated(.{ .all = &.{
|
var q = try entities.query(.{
|
||||||
.{ .mach_gfx_text_pipeline = &.{
|
.ids = mach.Entities.Mod.read(.id),
|
||||||
.is_pipeline,
|
.is_pipelines = Mod.read(.is_pipeline),
|
||||||
} },
|
});
|
||||||
} });
|
while (q.next()) |v| {
|
||||||
while (archetypes_iter.next()) |archetype| {
|
for (v.ids) |pipeline_id| {
|
||||||
const ids = archetype.slice(.entities, .id);
|
|
||||||
for (ids) |pipeline_id| {
|
|
||||||
try buildPipeline(core, text_pipeline, pipeline_id);
|
try buildPipeline(core, text_pipeline, pipeline_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -348,19 +346,16 @@ fn buildPipeline(
|
||||||
try text_pipeline.set(pipeline_id, .num_glyphs, 0);
|
try text_pipeline.set(pipeline_id, .num_glyphs, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn preRender(text_pipeline: *Mod, core: *mach.Core.Mod) void {
|
fn preRender(entities: *mach.Entities.Mod, core: *mach.Core.Mod) !void {
|
||||||
const label = @tagName(name) ++ ".preRender";
|
const label = @tagName(name) ++ ".preRender";
|
||||||
const encoder = core.state().device.createCommandEncoder(&.{ .label = label });
|
const encoder = core.state().device.createCommandEncoder(&.{ .label = label });
|
||||||
defer encoder.release();
|
defer encoder.release();
|
||||||
|
|
||||||
var archetypes_iter = text_pipeline.__entities.queryDeprecated(.{ .all = &.{
|
var q = try entities.query(.{
|
||||||
.{ .mach_gfx_text_pipeline = &.{
|
.built_pipelines = Mod.read(.built),
|
||||||
.built,
|
});
|
||||||
} },
|
while (q.next()) |v| {
|
||||||
} });
|
for (v.built_pipelines) |built| {
|
||||||
while (archetypes_iter.next()) |archetype| {
|
|
||||||
const built_pipelines = archetype.slice(.mach_gfx_text_pipeline, .built);
|
|
||||||
for (built_pipelines) |built| {
|
|
||||||
// Create the projection matrix
|
// Create the projection matrix
|
||||||
// TODO(text): move this out of the hot codepath
|
// TODO(text): move this out of the hot codepath
|
||||||
const proj = math.Mat4x4.projection2D(.{
|
const proj = math.Mat4x4.projection2D(.{
|
||||||
|
|
@ -391,20 +386,17 @@ fn preRender(text_pipeline: *Mod, core: *mach.Core.Mod) void {
|
||||||
core.state().queue.submit(&[_]*gpu.CommandBuffer{command});
|
core.state().queue.submit(&[_]*gpu.CommandBuffer{command});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(text_pipeline: *Mod) !void {
|
fn render(entities: *mach.Entities.Mod, text_pipeline: *Mod) !void {
|
||||||
const render_pass = if (text_pipeline.state().render_pass) |rp| rp else std.debug.panic("text_pipeline.state().render_pass must be specified", .{});
|
const render_pass = if (text_pipeline.state().render_pass) |rp| rp else std.debug.panic("text_pipeline.state().render_pass must be specified", .{});
|
||||||
text_pipeline.state().render_pass = null;
|
text_pipeline.state().render_pass = null;
|
||||||
|
|
||||||
// TODO(text): need a way to specify order of rendering with multiple pipelines
|
// TODO(text): need a way to specify order of rendering with multiple pipelines
|
||||||
var archetypes_iter = text_pipeline.__entities.queryDeprecated(.{ .all = &.{
|
var q = try entities.query(.{
|
||||||
.{ .mach_gfx_text_pipeline = &.{
|
.ids = mach.Entities.Mod.read(.id),
|
||||||
.built,
|
.built_pipelines = Mod.read(.built),
|
||||||
} },
|
});
|
||||||
} });
|
while (q.next()) |v| {
|
||||||
while (archetypes_iter.next()) |archetype| {
|
for (v.ids, v.built_pipelines) |pipeline_id, built| {
|
||||||
const ids = archetype.slice(.entities, .id);
|
|
||||||
const built_pipelines = archetype.slice(.mach_gfx_text_pipeline, .built);
|
|
||||||
for (ids, built_pipelines) |pipeline_id, built| {
|
|
||||||
// Draw the text batch
|
// Draw the text batch
|
||||||
const total_vertices = text_pipeline.get(pipeline_id, .num_glyphs).? * 6;
|
const total_vertices = text_pipeline.get(pipeline_id, .num_glyphs).? * 6;
|
||||||
render_pass.setPipeline(built.render);
|
render_pass.setPipeline(built.render);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue