Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ assets/shaders/ # GLSL shaders (vulkan/ contains SPIR-V)

### Naming Conventions
- **Types/Structs/Enums**: `PascalCase` (`RenderSystem`, `BufferHandle`, `BlockType`)
- **Functions/Variables**: `snake_case` (`init_renderer`, `mesh_queue`, `chunk_x`)
- **Functions**: `camelCase` following Zig stdlib convention (`initRenderer`, `meshQueue`, `chunkX`)
- **Variables**: `snake_case` (`mesh_queue`, `chunk_x`)
- **Constants/Globals**: `SCREAMING_SNAKE_CASE` (`MAX_CHUNKS`, `CHUNK_SIZE_X`)
- **Files**: `snake_case.zig`

Expand Down
480 changes: 303 additions & 177 deletions build.zig

Large diffs are not rendered by default.

40 changes: 40 additions & 0 deletions modules/engine-core/src/interfaces.zig
Original file line number Diff line number Diff line change
Expand Up @@ -26,66 +26,98 @@ pub const IRenderSettings = struct {
setMSAA: *const fn (ptr: *anyopaque, samples: u8) void,
};

/// Enables or disables wireframe rendering in the active render settings backend.
/// The setting affects subsequent frames and is typically driven by debug UI or hotkeys.
pub fn setWireframe(self: IRenderSettings, enabled: bool) void {
self.vtable.setWireframe(self.ptr, enabled);
}

/// Enables or disables vertical synchronization for presentation.
/// Backends may apply this on the next swapchain or presentation configuration update.
pub fn setVSync(self: IRenderSettings, enabled: bool) void {
self.vtable.setVSync(self.ptr, enabled);
}

/// Enables or disables material texture sampling in terrain and world rendering.
/// Disabling textures leaves geometry active while forcing fallback material colors.
pub fn setTexturesEnabled(self: IRenderSettings, enabled: bool) void {
self.vtable.setTexturesEnabled(self.ptr, enabled);
}

/// Sets the anisotropic filtering level requested for sampled textures.
/// The backend clamps unsupported levels to device capabilities.
pub fn setAnisotropicFiltering(self: IRenderSettings, level: u8) void {
self.vtable.setAnisotropicFiltering(self.ptr, level);
}

/// Enables or disables FXAA post-processing.
/// The setting affects post-process pass selection for subsequent frames.
pub fn setFXAA(self: IRenderSettings, enabled: bool) void {
self.vtable.setFXAA(self.ptr, enabled);
}

/// Enables or disables bloom post-processing.
/// When disabled, bloom extraction and composite work may be skipped by the renderer.
pub fn setBloom(self: IRenderSettings, enabled: bool) void {
self.vtable.setBloom(self.ptr, enabled);
}

/// Sets bloom strength used by the post-process composite.
/// Values are backend-defined floats, normally authored by graphics settings UI.
pub fn setBloomIntensity(self: IRenderSettings, intensity: f32) void {
self.vtable.setBloomIntensity(self.ptr, intensity);
}

/// Sets the temporal anti-aliasing blend factor.
/// Lower values favor the current frame; higher values retain more history and may increase ghosting.
pub fn setTAABlendFactor(self: IRenderSettings, value: f32) void {
self.vtable.setTAABlendFactor(self.ptr, value);
}

/// Sets how aggressively TAA rejects history using velocity differences.
/// Higher values preserve more history; lower values reduce ghosting near fast motion.
pub fn setTAAVelocityRejection(self: IRenderSettings, value: f32) void {
self.vtable.setTAAVelocityRejection(self.ptr, value);
}

/// Enables or disables vignette post-processing.
/// The setting affects only post-process composition, not scene lighting.
pub fn setVignetteEnabled(self: IRenderSettings, enabled: bool) void {
self.vtable.setVignetteEnabled(self.ptr, enabled);
}

/// Sets the vignette darkening strength used during post-processing.
/// Implementations should clamp out-of-range values to their supported range.
pub fn setVignetteIntensity(self: IRenderSettings, intensity: f32) void {
self.vtable.setVignetteIntensity(self.ptr, intensity);
}

/// Enables or disables film-grain post-processing.
/// This does not affect render targets, only final color presentation.
pub fn setFilmGrainEnabled(self: IRenderSettings, enabled: bool) void {
self.vtable.setFilmGrainEnabled(self.ptr, enabled);
}

/// Sets the film-grain strength used by the post-process pass.
/// Backends may quantize or clamp this setting to their shader-supported range.
pub fn setFilmGrainIntensity(self: IRenderSettings, intensity: f32) void {
self.vtable.setFilmGrainIntensity(self.ptr, intensity);
}

/// Sets volumetric effect density for fog/cloud/atmosphere style rendering.
/// The value is consumed by later frames and may be clamped by the backend.
pub fn setVolumetricDensity(self: IRenderSettings, density: f32) void {
self.vtable.setVolumetricDensity(self.ptr, density);
}

/// Enables or disables the debug shadow-map visualization path.
/// Intended for diagnostics; normal gameplay rendering should leave this disabled.
pub fn setDebugShadowView(self: IRenderSettings, enabled: bool) void {
self.vtable.setDebugShadowView(self.ptr, enabled);
}

/// Sets the requested MSAA sample count.
/// The backend may recreate render targets or clamp unsupported sample counts.
pub fn setMSAA(self: IRenderSettings, samples: u8) void {
self.vtable.setMSAA(self.ptr, samples);
}
Expand All @@ -109,18 +141,26 @@ pub const IScreenManager = struct {
drawParentScreen: *const fn (ptr: *anyopaque, current_ptr: *anyopaque, ui: *anyopaque) anyerror!void,
};

/// Pushes a screen onto the navigation stack.
/// Ownership and lifetime of `screen` are defined by the concrete screen manager implementation.
pub fn pushScreen(self: IScreenManager, screen: ScreenHandle) void {
self.vtable.pushScreen(self.ptr, screen);
}

/// Pops the current screen from the navigation stack.
/// Implementations decide how to handle an empty or root-only stack.
pub fn popScreen(self: IScreenManager) void {
self.vtable.popScreen(self.ptr);
}

/// Replaces the active screen with `screen`.
/// This is used for hard navigation transitions such as leaving a modal flow.
pub fn setScreen(self: IScreenManager, screen: ScreenHandle) void {
self.vtable.setScreen(self.ptr, screen);
}

/// Draws the parent screen behind the current screen when overlays need backdrop rendering.
/// Propagates drawing errors from the concrete UI implementation.
pub fn drawParentScreen(self: IScreenManager, current_ptr: *anyopaque, ui: *anyopaque) !void {
try self.vtable.drawParentScreen(self.ptr, current_ptr, ui);
}
Expand Down
18 changes: 9 additions & 9 deletions modules/engine-graphics/src/vulkan/culling_system.zig
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ pub const CullingSystem = struct {
};
}

pub fn update_aabb_data(self: *CullingSystem, frame_index: usize, chunks: []const ChunkCullData) void {
pub fn updateAABBData(self: *CullingSystem, frame_index: usize, chunks: []const ChunkCullData) void {
const buf = &self.aabb_buffers[frame_index];
if (buf.mapped_ptr == null) return;
const copy_len = @min(chunks.len, self.max_chunks) * @sizeOf(ChunkCullData);
Expand Down Expand Up @@ -220,14 +220,14 @@ pub const CullingSystem = struct {
self.copyCounterToReadback(cmd, fi);
}

pub fn read_visible_count(self: *CullingSystem, frame_index: usize) u32 {
pub fn readVisibleCount(self: *CullingSystem, frame_index: usize) u32 {
const buf = &self.counter_readback_buffers[frame_index];
if (buf.mapped_ptr == null) return 0;
const ptr: *align(1) u32 = @ptrCast(@alignCast(buf.mapped_ptr.?));
return ptr.*;
}

pub fn read_visible_indices(self: *CullingSystem, frame_index: usize, count: u32, out: []u32) void {
pub fn readVisibleIndices(self: *CullingSystem, frame_index: usize, count: u32, out: []u32) void {
if (count == 0) return;
const buf = &self.visible_index_buffers[frame_index];
if (buf.mapped_ptr == null) return;
Expand Down Expand Up @@ -462,9 +462,9 @@ pub const CullingSystem = struct {

const interface_vtable = culling.ICullingSystem.VTable{
.deinit = interfaceDeinit,
.update_aabb_data = interfaceUpdateAabbData,
.read_visible_count = interfaceReadVisibleCount,
.read_visible_indices = interfaceReadVisibleIndices,
.updateAABBData = interfaceUpdateAabbData,
.readVisibleCount = interfaceReadVisibleCount,
.readVisibleIndices = interfaceReadVisibleIndices,
.dispatch = interfaceDispatch,
};

Expand All @@ -475,17 +475,17 @@ fn interfaceDeinit(ptr: *anyopaque) void {

fn interfaceUpdateAabbData(ptr: *anyopaque, frame_index: usize, chunks: []const ChunkCullData) void {
const self: *CullingSystem = @ptrCast(@alignCast(ptr));
self.update_aabb_data(frame_index, chunks);
self.updateAABBData(frame_index, chunks);
}

fn interfaceReadVisibleCount(ptr: *anyopaque, frame_index: usize) u32 {
const self: *CullingSystem = @ptrCast(@alignCast(ptr));
return self.read_visible_count(frame_index);
return self.readVisibleCount(frame_index);
}

fn interfaceReadVisibleIndices(ptr: *anyopaque, frame_index: usize, count: u32, out: []u32) void {
const self: *CullingSystem = @ptrCast(@alignCast(ptr));
self.read_visible_indices(frame_index, count, out);
self.readVisibleIndices(frame_index, count, out);
}

fn interfaceDispatch(ptr: *anyopaque, config: culling.DispatchConfig) void {
Expand Down
28 changes: 19 additions & 9 deletions modules/engine-rhi/src/culling.zig
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,38 @@ pub const ICullingSystem = struct {

pub const VTable = struct {
deinit: *const fn (ptr: *anyopaque) void,
update_aabb_data: *const fn (ptr: *anyopaque, frame_index: usize, chunks: []const ChunkCullData) void,
read_visible_count: *const fn (ptr: *anyopaque, frame_index: usize) u32,
read_visible_indices: *const fn (ptr: *anyopaque, frame_index: usize, count: u32, out: []u32) void,
updateAABBData: *const fn (ptr: *anyopaque, frame_index: usize, chunks: []const ChunkCullData) void,
readVisibleCount: *const fn (ptr: *anyopaque, frame_index: usize) u32,
readVisibleIndices: *const fn (ptr: *anyopaque, frame_index: usize, count: u32, out: []u32) void,
dispatch: *const fn (ptr: *anyopaque, config: DispatchConfig) void,
};

/// Releases backend culling buffers, pipelines, and readback resources.
/// No dispatch or readback methods may be used after this returns.
pub fn deinit(self: ICullingSystem) void {
self.vtable.deinit(self.ptr);
}

pub fn update_aabb_data(self: ICullingSystem, frame_index: usize, chunks: []const ChunkCullData) void {
self.vtable.update_aabb_data(self.ptr, frame_index, chunks);
/// Uploads chunk AABB data for the selected frame-in-flight slot.
/// `chunks` is copied or staged by the backend and must match the dispatch chunk count used for that frame.
pub fn updateAABBData(self: ICullingSystem, frame_index: usize, chunks: []const ChunkCullData) void {
self.vtable.updateAABBData(self.ptr, frame_index, chunks);
}

pub fn read_visible_count(self: ICullingSystem, frame_index: usize) u32 {
return self.vtable.read_visible_count(self.ptr, frame_index);
/// Reads the visible chunk count produced by a previous culling dispatch.
/// The returned value is valid only after the backend has completed the corresponding frame's compute work.
pub fn readVisibleCount(self: ICullingSystem, frame_index: usize) u32 {
return self.vtable.readVisibleCount(self.ptr, frame_index);
}

pub fn read_visible_indices(self: ICullingSystem, frame_index: usize, count: u32, out: []u32) void {
self.vtable.read_visible_indices(self.ptr, frame_index, count, out);
/// Copies visible chunk indices from backend readback storage into `out`.
/// `count` should come from `readVisibleCount`; the implementation clamps writes to `out.len`.
pub fn readVisibleIndices(self: ICullingSystem, frame_index: usize, count: u32, out: []u32) void {
self.vtable.readVisibleIndices(self.ptr, frame_index, count, out);
}

/// Dispatches GPU frustum/occlusion culling for the configured chunk set.
/// Must run on the render thread with current-frame AABB data already uploaded.
pub fn dispatch(self: ICullingSystem, config: DispatchConfig) void {
self.vtable.dispatch(self.ptr, config);
}
Expand Down
Loading
Loading