Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
9f86883
feat(resources): begin implementing resource management utilities suc…
JohnSmoit Aug 10, 2025
0b4f78e
feat(reg): fleshed out registry with radix sorted entry table
JohnSmoit Aug 11, 2025
23855c0
feat(res): implemented pool allocator and tests save for individual f…
JohnSmoit Aug 13, 2025
7f05193
feat(reg): implemented a cursed type registry system... we'll see if …
JohnSmoit Aug 16, 2025
a181579
fix(imports): Slightly clean up the file structure (more work needs t…
JohnSmoit Aug 16, 2025
3ac83fe
chore(pool_allocator): update pool allocator with spec for handle-bas…
JohnSmoit Aug 16, 2025
4951574
feat(vulkan): added a descriptor pool manager with configurable pools…
JohnSmoit Aug 18, 2025
4a88cf2
feat(config): worked out an API for sensible defaults
JohnSmoit Aug 18, 2025
a6bfce3
feat(config): updated config registry to validate parapoly'd types
JohnSmoit Aug 18, 2025
af5d496
feat(config): implemented first pass of config registry type with com…
JohnSmoit Aug 19, 2025
a53c7d3
test(config): added basic unit test coverage for sensible defaults us…
JohnSmoit Aug 19, 2025
4410cc7
fix(config): fixed various compile time errors so that test cases pass
JohnSmoit Aug 19, 2025
7bea560
refactor(ray): updated ray module code to include common.zig as a module
JohnSmoit Aug 19, 2025
ee30325
fix(config): fixed struct union by ensuring only non-default values o…
JohnSmoit Aug 19, 2025
ef06591
Merge pull request #19 from JohnSmoit/feature/sensible-defaults
JohnSmoit Aug 19, 2025
6e481ef
Merge branch 'feature/resource-manager' into feature/vulkan-pools
JohnSmoit Aug 20, 2025
458bab5
feat(api): implement descriptor pool with allocations based on usage …
JohnSmoit Aug 23, 2025
98ac7f2
feat(vulkan): implemented vulkan pools and reworked descriptor creati…
JohnSmoit Aug 24, 2025
d623a0a
fix(res): fixed a minor usage issue involving the constness of a regi…
JohnSmoit Aug 24, 2025
450c230
feat(context): added descriptor pool manager to app context
JohnSmoit Aug 24, 2025
6819150
Merge pull request #20 from JohnSmoit/feature/vulkan-pools
JohnSmoit Aug 24, 2025
f3be4d9
fix: minor compilation errors for DescriptorUsageInfo
JohnSmoit Aug 24, 2025
f2b751f
fix(pool): fixed alignment and slot sizing issues by enforcing a mini…
JohnSmoit Aug 24, 2025
9014678
feat(sample): updated samples to use new descriptor initialization
JohnSmoit Aug 24, 2025
3f13daa
fix(descriptor): explicitly initialize p_immutable_samplers since a s…
JohnSmoit Aug 25, 2025
21b260e
feat(api): begun work on GPU memory virtualization system and accompa…
JohnSmoit Sep 2, 2025
d87871f
refactor(pool): refactored pools to work using handle indexing
JohnSmoit Sep 3, 2025
b34a325
feat(pool): finished implementing a handle-based object pool
JohnSmoit Sep 5, 2025
1acfef6
fix(pool): pool complies with basic test coverage including memory in…
JohnSmoit Sep 6, 2025
eee4951
feat(virtual_allocator): virtualized GPU memory and begin scaffolding…
JohnSmoit Sep 10, 2025
e342bfc
fml
JohnSmoit Sep 13, 2025
2314af5
fix (heap): at least it compiles now... Actually working is tommorw's…
JohnSmoit Sep 13, 2025
f957cf3
fix(heap): Fixed heap identification based on supported memory types …
JohnSmoit Sep 13, 2025
89aa725
fix(heap): properly freed allocated device memory in test
JohnSmoit Sep 13, 2025
4119fd6
feat(vulkan): blocked out a design for device memory pools although t…
JohnSmoit Sep 14, 2025
c50a859
chore(allocator): figure out how tf I'm gonna implement this thing
JohnSmoit Sep 17, 2025
3597eda
feat: changed something I guess
JohnSmoit Oct 7, 2025
2ea676c
feat(sample): created a fragment shader viewer
JohnSmoit Oct 8, 2025
7f5af6f
feat(sample): mandelbulb with shitty skybox
JohnSmoit Oct 9, 2025
8c919b7
feat(sampler): added a bunch of shaders and added optional texture su…
JohnSmoit Oct 10, 2025
dbd4f23
Merge pull request #22 from JohnSmoit/feature/device-allocator
JohnSmoit Oct 10, 2025
28faa9f
feat(api): merge build system and upstream main changes into latest d…
JohnSmoit Oct 10, 2025
18ad42d
feat(sample): Merge branch 'feature/raymarched-fractals' into feature…
JohnSmoit Oct 10, 2025
8880471
feat(factory): implemented some of the infastructure required to get …
JohnSmoit Oct 16, 2025
da55c00
feat(factory): Comptime resolution works end to end at least in typic…
JohnSmoit Oct 18, 2025
163f9e8
feat(crapi): added some additional getter functions for the comptime …
JohnSmoit Oct 19, 2025
2600ccf
feat(factory): creation API finished and comptime side works
JohnSmoit Oct 20, 2025
389642c
fix(env): questioning whether the empty env is even necessary at all...
JohnSmoit Oct 20, 2025
1179940
feat: improved testing context to be incremental in its initialization
JohnSmoit Oct 24, 2025
9d77a55
fix(test): fixed various issues in the initialization process for the…
JohnSmoit Oct 25, 2025
3cc5db0
feat(factory): Implemented factory initializers at least to the point…
JohnSmoit Oct 27, 2025
a481179
build: make samples and test building optional
JohnSmoit Oct 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 79 additions & 29 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const Dependencies = struct {
rshc: *Module,
vulkan: *Module,
glfw: *Module,
common: *Module,
};

fn resolveGLFWSystemDeps(m: *Module) void {
Expand Down Expand Up @@ -48,10 +49,17 @@ fn buildDeps(b: *Build, opts: BuildOpts) Dependencies {

resolveGLFWSystemDeps(glfw_mod);

const common_mod = b.createModule(.{
.optimize = opts.optimize,
.target = opts.target,
.root_source_file = b.path("src/common/common.zig"),
});

return .{
.rshc = rshc_mod,
.vulkan = vulkan_mod,
.glfw = glfw_mod,
.common = common_mod,
};
}

Expand All @@ -69,6 +77,9 @@ fn buildLibrary(
});

lib_mod.addImport("vulkan", deps.vulkan);
lib_mod.addImport("common", deps.common);

// Temporary for development
lib_mod.addImport("rshc", deps.rshc);
lib_mod.addImport("glfw", deps.glfw);

Expand All @@ -85,16 +96,34 @@ fn buildLibrary(

const SampleEntry = struct {
name: []const u8,
path: []const u8,
desc: []const u8,
path: []const u8 = "(no description)",

// these get populated later
mod: *Module = undefined,
exe: *Compile = undefined,
};
var sample_files = [_]SampleEntry{
.{ .name = "basic_planes", .path = "basic_planes.zig" },
.{ .name = "compute_drawing", .path = "compute_drawing/main.zig" },
.{ .name = "test_sample", .path = "test_sample.zig" },
.{
.name = "basic-planes",
.path = "basic_planes.zig",
.desc = "basic showcase of bootstrapping vulkan up to 3d rendering",
},
.{
.name = "compute-drawing",
.path = "compute_drawing/main.zig",
.desc = "drawing using compute shaders",
},
.{
.name = "test-sample",
.path = "test_sample.zig",
.desc = "test to see if the sample build steps work correctly",
},
.{
.name = "raymarch-fractals",
.path = "raymarch_fractals/main.zig",
.desc = "pick from a selection of raymarched fractals, all programmed within fragment shaders",
},
};

fn populateSampleModules(
Expand Down Expand Up @@ -149,39 +178,48 @@ fn buildSamples(
) void {
populateSampleModules(b, lib_mod, deps, opts);

const build_sample = b.option(
[]const u8,
"sample",
"specify sample to build and run",
);
if (build_sample) |sample_name| {
var entry: ?*SampleEntry = null;

for (&sample_files) |*f| {
if (std.mem.order(u8, sample_name, f.name) == .eq) {
entry = f;
break;
}
}

if (entry == null) return;
for (sample_files) |entry| {
b.installArtifact(entry.exe);

b.installArtifact(entry.?.exe);
const run_step = b.addRunArtifact(entry.exe);
run_step.addArgs(b.args orelse &.{});

const run_step = b.addRunArtifact(entry.?.exe);
run_step.step.dependOn(b.getInstallStep());

const run_cmd = b.step("run", "run a sample executable");
const step_name = std.fmt.allocPrint(
b.allocator,
"run-{s}",
.{entry.name},
) catch @panic("Achievement Get: How did we get here?");

const run_cmd = b.step(step_name, entry.desc);
run_cmd.dependOn(&run_step.step);
}
}

/// adds a single module and compile step containing
/// all included tests (based on specified options)
fn buildTests(b: *Build, lib_mod: *Module, deps: Dependencies) void {
_ = b;
_ = lib_mod;
_ = deps;
fn buildTests(b: *Build, lib_mod: *Module, deps: Dependencies, opts: BuildOpts) void {
const test_comp = b.addTest(.{
.name = "unit_tests",
.root_module = lib_mod,
.target = opts.target,
});

const common_tests = b.addTest(.{
.name = "common_unit_tests",
.root_module = deps.common,
.target = opts.target,
});
b.installArtifact(test_comp);
b.installArtifact(common_tests);

const test_step = b.addRunArtifact(test_comp);
const common_test_step = b.addRunArtifact(common_tests);
const test_cmd = b.step("test", "run all unit tests");

test_cmd.dependOn(&test_step.step);
test_cmd.dependOn(&common_test_step.step);
}
// Although this function looks imperative, note that its job is to
// declaratively construct a build graph that will be executed by an external
Expand All @@ -192,12 +230,24 @@ pub fn build(b: *Build) void {
.optimize = b.standardOptimizeOption(.{}),
};

const opt_build_samples = b.option(
bool,
"build_samples",
"whether or not to build sample executables (defaults: true)",
) orelse true;

const opt_build_tests = b.option(
bool,
"build_tests",
"whether or not to build sample executables (defaults: true)",
) orelse true;

const deps = buildDeps(b, opts);
const lib_mod, const lib_exe = buildLibrary(b, deps, opts);

// handle samples and testing if specified
buildSamples(b, lib_mod, deps, opts);
buildTests(b, lib_mod, deps);
if (opt_build_samples) buildSamples(b, lib_mod, deps, opts);
if (opt_build_tests) buildTests(b, lib_mod, deps, opts);

// zls-friendly check step
// (which made all the rest of the code way grosser)
Expand Down
4 changes: 2 additions & 2 deletions samples/basic_planes.zig
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ pub fn main() !void {
defer window.destroy();

glfw.vulkanSupported() catch |err| {
std.debug.print("Could not load Vulkan\n", .{});
std.log.err("Could not load Vulkan", .{});
return err;
};

Expand All @@ -400,5 +400,5 @@ pub fn main() !void {
try mainLoop();
}

std.debug.print("You win!\n", .{});
std.log.info("You win!\n", .{});
}
5 changes: 3 additions & 2 deletions samples/common/render_quad.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const std = @import("std");
const ray = @import("ray");
const api = ray.api;
const math = ray.math;

const Allocator = std.mem.Allocator;

Expand Down Expand Up @@ -81,7 +82,7 @@ pub fn initSelf(self: *Self, ctx: *const Context, allocator: Allocator, config:
},
.viewport = .{ .Swapchain = config.swapchain },
.descriptors = if (config.frag_descriptors) |fd| &.{
fd.h_desc_layout,
fd.vkLayout(),
} else &.{},
});
defer fixed_functions_config.deinit();
Expand Down Expand Up @@ -119,7 +120,7 @@ pub fn drawOneShot(self: *const Self, cmd_buf: *const CommandBuffer, framebuffer
self.renderpass.begin(cmd_buf, framebuffer, image_index);

if (self.desc) |d| {
d.bind(cmd_buf, self.pipeline.h_pipeline_layout, .{});
d.use(cmd_buf, self.pipeline.h_pipeline_layout, .{});
}

self.dev.draw(cmd_buf, 6, 1, 0, 0);
Expand Down
76 changes: 45 additions & 31 deletions samples/compute_drawing/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const GraphicsPipeline = api.GraphicsPipeline;
const RenderPass = api.RenderPass;
const FixedFunctionState = api.FixedFunctionState;
const Descriptor = api.Descriptor;
const DescriptorBinding = api.ResolvedDescriptorBinding;
const DescriptorLayout = api.DescriptorLayout;
const CommandBuffer = api.CommandBuffer;

const Semaphore = api.Semaphore;
Expand Down Expand Up @@ -141,6 +141,10 @@ const SampleState = struct {
.inst_extensions = helpers.glfwInstanceExtensions(),
.loader = glfw.glfwGetInstanceProcAddress,
.window = &self.window,
.management = .{
.allocator = self.allocator,
.pool_sizes = 1024,
},
});
}

Expand Down Expand Up @@ -177,19 +181,28 @@ const SampleState = struct {
try self.gpu_state.uniforms.setData(&self.gpu_state.host_uniforms);

// create fragment-specific descriptors
self.graphics.descriptor = try Descriptor.init(self.ctx, self.allocator, .{
.bindings = &.{ .{
.data = .{ .Uniform = self.gpu_state.uniforms.buffer() },
.stages = .{ .fragment_bit = true },
}, DescriptorBinding{
.data = .{ .Sampler = .{
.sampler = self.gpu_state.render_sampler,
.view = self.gpu_state.render_view.h_view,
} },
.stages = .{ .fragment_bit = true },
} },
var frag_desc_layout = try DescriptorLayout.init(self.ctx, self.allocator, 2);
frag_desc_layout.addDescriptors(&.{
.{ 0, "FragUniforms", .Uniform, .{ .fragment_bit = true } },
.{ 1, "MainTex", .Sampler, .{ .fragment_bit = true } },
});
try frag_desc_layout.resolve();

self.graphics.descriptor = try Descriptor.init(self.ctx, .{
.layout = frag_desc_layout,
.usage = .{
.lifetime_bits = .Static,
},
});

self.graphics.descriptor.bindUniformsNamed(
"FragUniforms",
self.gpu_state.uniforms.buffer(),
);
self.graphics.descriptor.bindSamplerNamed("MainTex", self.gpu_state.render_sampler, self.gpu_state.render_view);

self.graphics.descriptor.update();

try self.graphics.render_quad.initSelf(self.ctx, self.allocator, .{
.frag_shader = &frag_shader,
.frag_descriptors = &self.graphics.descriptor,
Expand Down Expand Up @@ -243,26 +256,27 @@ const SampleState = struct {
self.gpu_state.compute_uniforms = try UniformBuffer(ComputeUniforms).create(self.ctx);
self.gpu_state.particles = try StorageBuffer(Particle).create(self.ctx, PARTICLE_COUNT);

const descriptors: []const DescriptorBinding = &.{
.{
.data = .{ .Uniform = self.gpu_state.compute_uniforms.buffer() },
.stages = .{ .compute_bit = true },
},
.{
.data = .{ .StorageBuffer = self.gpu_state.particles.buffer() },
.stages = .{ .compute_bit = true },
},
.{
.data = .{ .Image = .{
.img = &self.gpu_state.render_target,
.view = self.gpu_state.render_view.h_view,
} },
.stages = .{ .compute_bit = true },
},
};
self.compute.pipeline = try Compute.init(self.ctx, self.allocator, .{
var compute_desc_layout = try DescriptorLayout.init(self.ctx, self.allocator, 3);
compute_desc_layout.addDescriptors(&.{
.{ 0, "Uniforms", .Uniform, .{ .compute_bit = true } },
.{ 1, "Particles", .StorageBuffer, .{ .compute_bit = true } },
.{ 2, "RenderTarget", .Image, .{ .compute_bit = true } },
});
try compute_desc_layout.resolve();

var compute_descriptor = try Descriptor.init(self.ctx, .{
.layout = compute_desc_layout,
.usage = .{ .lifetime_bits = .Static },
});

compute_descriptor.bindUniformsNamed("Uniforms", self.gpu_state.compute_uniforms.buffer());
compute_descriptor.bindBufferNamed("Particles", self.gpu_state.particles.buffer());
compute_descriptor.bindImageNamed("RenderTarget", &self.gpu_state.render_target, self.gpu_state.render_view);
compute_descriptor.update();

self.compute.pipeline = try Compute.init(self.ctx, .{
.shader = &shader,
.desc_bindings = descriptors,
.desc = compute_descriptor,
});
}

Expand Down
Loading
Loading