NYXEngine/src/plugins/cache/resource/pipeline_cache.zig

143 lines
4.8 KiB
Zig
Raw Normal View History

//! ----------------------------------------------------
//! ----------------------------------------------------
const std = @import("std");
const gtl = @import("gtl");
const wgpu = @import("wgpu");
const Self = @This();
const Material = @import("../../common/component/material.zig");
const ShaderCache = @import("shader_cache.zig");
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const GPUPipeline = struct {
raw: *wgpu.WGPURenderPipelineImpl,
};
//
// FIELDS
//
pipelines: gtl.KeyedSlotMap(Material.Unique, GPUPipeline),
shader_cache: *ShaderCache,
queue: *wgpu.WGPUQueueImpl,
device: *wgpu.WGPUDeviceImpl,
alloc: std.mem.Allocator,
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn init(
shader_cache: *ShaderCache,
queue: *wgpu.WGPUQueueImpl,
device: *wgpu.WGPUDeviceImpl,
alloc: std.mem.Allocator,
) Self {
return .{
.pipelines = .init(alloc),
.shader_cache = shader_cache,
.queue = queue,
.device = device,
.alloc = alloc,
};
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn deinit(self: *Self) void {
// --- FREE PIPELINES ---
for (self.pipelines.items()) |entry| {
wgpu.wgpuRenderPipelineRelease(entry.value.raw);
}
// --- # ---
self.pipelines.deinit();
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn getOrCreate(
self: *Self,
key: Material.Unique,
) !*GPUPipeline {
return try self.pipelines.getOrPut(key, .{
.raw = try self.createPipeline(key),
});
}
/// ----------------------------------------------------
/// ----------------------------------------------------
fn createPipeline(
self: *Self,
key: Material.Unique,
) !*wgpu.WGPURenderPipelineImpl {
// --- ENSURE SHADER MODULE ---
const shader_module = try self.shader_cache.getOrCreate(
key.shader,
);
// --- RESULT ---
return wgpu.wgpuDeviceCreateRenderPipeline(self.device, &wgpu.WGPURenderPipelineDescriptor{
.label = .{ .data = @tagName(key.shader), .length = wgpu.WGPU_STRLEN },
.vertex = .{
.module = shader_module.raw,
.entryPoint = .{ .data = "vs_main", .length = wgpu.WGPU_STRLEN },
2026-07-29 01:15:31 +01:00
.bufferCount = 1,
.buffers = &wgpu.WGPUVertexBufferLayout{
.attributeCount = 1,
.attributes = &wgpu.WGPUVertexAttribute{ // TODO: Use Vertex attributes instead | Mabe mabe allow for custom, mabe mabe later tho
.shaderLocation = 0,
.format = wgpu.WGPUVertexFormat_Float32x2,
.offset = 0,
},
.arrayStride = 2 * @sizeOf(f32),
.stepMode = wgpu.WGPUVertexStepMode_Vertex,
},
},
.fragment = &wgpu.WGPUFragmentState{
.module = shader_module.raw,
.entryPoint = .{ .data = "fs_main", .length = wgpu.WGPU_STRLEN },
.targetCount = 1,
.targets = &wgpu.WGPUColorTargetState{
2026-07-29 01:15:31 +01:00
.format = 28, // FIX: Use proper format
.blend = &wgpu.WGPUBlendState{
.color = .{
.srcFactor = wgpu.WGPUBlendFactor_SrcAlpha,
.dstFactor = wgpu.WGPUBlendFactor_OneMinusSrcAlpha,
.operation = wgpu.WGPUBlendOperation_Add,
},
.alpha = .{
.srcFactor = wgpu.WGPUBlendFactor_Zero,
.dstFactor = wgpu.WGPUBlendFactor_One,
.operation = wgpu.WGPUBlendOperation_Add,
},
},
.writeMask = wgpu.WGPUColorWriteMask_All,
},
},
.primitive = .{
.topology = switch (key.topology) {
.triangle_list => wgpu.WGPUPrimitiveTopology_TriangleList,
.point_list => wgpu.WGPUPrimitiveTopology_PointList,
.line_list => wgpu.WGPUPrimitiveTopology_LineList,
},
.frontFace = switch (key.front_face) {
.ccw => wgpu.WGPUFrontFace_CCW,
.cw => wgpu.WGPUFrontFace_CW,
},
.cullMode = switch (key.cull_mode) {
.back => wgpu.WGPUCullMode_Back,
.front => wgpu.WGPUCullMode_Front,
.none => wgpu.WGPUCullMode_None,
},
},
.multisample = .{
.count = 1,
.mask = ~@as(u32, 0),
.alphaToCoverageEnabled = 0,
},
}) orelse {
return error.PipelineCreationFailed;
};
}