simple triangle example working with new sdl api
This commit is contained in:
parent
86d56cf5e6
commit
373eb9600c
|
|
@ -169,6 +169,11 @@ pub fn createObject(comptime T: type, params: engine.NeonObjectParams) !*T {
|
||||||
return gEngine.createObject(T, params);
|
return gEngine.createObject(T, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn registerRendererSetup(ctx: *anyopaque, setup: engine.SetupFuncFn) void {
|
||||||
|
gEngine.rendererCtx = ctx;
|
||||||
|
gEngine.rendererSetupFunc = setup;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn setupEnginePlatform(ctx: *anyopaque, setup: engine.SetupFuncFn, poll: engine.PollFuncFn, proc: engine.ProcEventsFn) void {
|
pub fn setupEnginePlatform(ctx: *anyopaque, setup: engine.SetupFuncFn, poll: engine.PollFuncFn, proc: engine.ProcEventsFn) void {
|
||||||
gEngine.platformCtx = ctx;
|
gEngine.platformCtx = ctx;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,9 @@ pub const Engine = struct {
|
||||||
platformSetupFunc: ?PollFuncFn = null,
|
platformSetupFunc: ?PollFuncFn = null,
|
||||||
platformProcEventsFunc: ?ProcEventsFn = null,
|
platformProcEventsFunc: ?ProcEventsFn = null,
|
||||||
|
|
||||||
|
rendererCtx: *anyopaque = undefined,
|
||||||
|
rendererSetupFunc: ?PollFuncFn = null,
|
||||||
|
|
||||||
engineStartTime: f64 = 0,
|
engineStartTime: f64 = 0,
|
||||||
|
|
||||||
nfdRuntime: *nfd.NFDRuntime,
|
nfdRuntime: *nfd.NFDRuntime,
|
||||||
|
|
@ -280,6 +283,10 @@ pub const Engine = struct {
|
||||||
setupFunc(ctx.engine.platformCtx) catch unreachable;
|
setupFunc(ctx.engine.platformCtx) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctx.engine.rendererSetupFunc) |setupFunc| {
|
||||||
|
setupFunc(ctx.engine.rendererCtx) catch unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
ctx.engine.tick() catch unreachable;
|
ctx.engine.tick() catch unreachable;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ const realMain = @import("main");
|
||||||
pub const options = @import("BacklogOptions");
|
pub const options = @import("BacklogOptions");
|
||||||
|
|
||||||
pub const std_options = std.Options{
|
pub const std_options = std.Options{
|
||||||
.enable_segfault_handler = false,
|
// .enable_segfault_handler = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
//pub const build_options = @import("build_options");
|
//pub const build_options = @import("build_options");
|
||||||
|
|
@ -21,6 +21,6 @@ pub const std_options = std.Options{
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
panickers.attachSegfaultHandler();
|
// panickers.attachSegfaultHandler();
|
||||||
try realMain.main();
|
try realMain.main();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,5 @@ pub fn shutdown_module(allocator: std.mem.Allocator) void {
|
||||||
|
|
||||||
gPlatformInstance.deinit();
|
gPlatformInstance.deinit();
|
||||||
|
|
||||||
// I have a bug somewhere. need to find out where it is
|
|
||||||
allocator.destroy(gPlatformInstance);
|
allocator.destroy(gPlatformInstance);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ pub const PlatformInstance = struct {
|
||||||
.video = true,
|
.video = true,
|
||||||
.gamepad = true,
|
.gamepad = true,
|
||||||
}) catch return error.BadInit;
|
}) catch return error.BadInit;
|
||||||
self.window = sdl3.c.SDL_CreateWindow(self.windowName, self.windowExtent.x, self.windowExtent.y, 0x20).?; // resizeable
|
self.window = sdl3.c.SDL_CreateWindow(self.windowName, self.windowExtent.x, self.windowExtent.y, 0).?; // resizeable
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn registerSetupFuncs(self: *@This()) !void {
|
pub fn registerSetupFuncs(self: *@This()) !void {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const sample_vert = @import("sample.vert");
|
const sgpu_renderer = @import("sgpu/renderer.zig");
|
||||||
|
|
||||||
// controls glfw and general windowing
|
// controls glfw and general windowing
|
||||||
// graphics depends on this one
|
// graphics depends on this one
|
||||||
|
|
@ -14,11 +14,10 @@ pub fn start_module(comptime programSpec: anytype, args: anytype, allocator: std
|
||||||
_ = args;
|
_ = args;
|
||||||
_ = programSpec;
|
_ = programSpec;
|
||||||
_ = allocator;
|
_ = allocator;
|
||||||
core.engine_log("starting up [REND] module...", .{});
|
try sgpu_renderer.start();
|
||||||
core.engine_log("sample_vert.Scene size = {d}", .{@sizeOf(sample_vert.Scene)});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shutdown_module(allocator: std.mem.Allocator) void {
|
pub fn shutdown_module(allocator: std.mem.Allocator) void {
|
||||||
_ = allocator;
|
_ = allocator;
|
||||||
core.engine_log("shutting down [REND] module...", .{});
|
sgpu_renderer.shutdown();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,221 @@
|
||||||
|
// sdl3_gpu is like 8 characterso
|
||||||
|
// so instead of refering to it by it's full name every time
|
||||||
|
//
|
||||||
|
// we will just call it sgpu.
|
||||||
|
|
||||||
|
pub const Renderer = struct {
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
|
||||||
|
totalTime: f64 = 0,
|
||||||
|
|
||||||
|
device: *gpu.GPUDevice = undefined,
|
||||||
|
|
||||||
|
shaderType: []const u8 = undefined,
|
||||||
|
shaderSuffix: []const u8 = undefined,
|
||||||
|
shaderformat: gpu.GPUShaderFormat = undefined,
|
||||||
|
entrypoint: []const u8 = "main",
|
||||||
|
pipeline: *gpu.GPUGraphicsPipeline = undefined,
|
||||||
|
|
||||||
|
scissor: gpu.Rect = .{ .x = 0, .y = 0, .w = 1600, .h = 900 },
|
||||||
|
colorBuffer: *gpu.GPUBuffer = undefined,
|
||||||
|
colorBufferTransfer: *gpu.GPUTransferBuffer = undefined,
|
||||||
|
window: *sdl3.Window = undefined,
|
||||||
|
|
||||||
|
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
|
||||||
|
|
||||||
|
pub fn init(allocator: std.mem.Allocator) !*@This() {
|
||||||
|
const self = try allocator.create(@This());
|
||||||
|
|
||||||
|
self.* = .{
|
||||||
|
.allocator = allocator,
|
||||||
|
};
|
||||||
|
|
||||||
|
core.registerRendererSetup(self, engineSetup);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn engineSetup(p: *anyopaque) core.EngineDataEventError!void {
|
||||||
|
@as(*@This(), @ptrCast(@alignCast(p))).startRenderer() catch return error.BadInit;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn startRenderer(self: *@This()) !void {
|
||||||
|
self.device = gpu.createGPUDevice(.{
|
||||||
|
.shaderformatSpirv = true,
|
||||||
|
.shaderformatDxil = true,
|
||||||
|
.shaderformatMsl = true,
|
||||||
|
}, false, null);
|
||||||
|
|
||||||
|
self.window = platform.getInstance().window;
|
||||||
|
|
||||||
|
if (!self.device.claimWindowForGPUDevice(self.window))
|
||||||
|
return error.UnableToClaimGpu;
|
||||||
|
|
||||||
|
try self.discoverFormats();
|
||||||
|
|
||||||
|
core.engine_log("sgpu device created, using shader format: {s}", .{self.shaderSuffix});
|
||||||
|
|
||||||
|
try self.createPipeline();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn discoverFormats(self: *@This()) !void {
|
||||||
|
const formats = self.device.getGPUShaderFormats();
|
||||||
|
|
||||||
|
if (formats.shaderformatSpirv) {
|
||||||
|
self.shaderType = "spv"; // shaderformatSpirv
|
||||||
|
self.shaderSuffix = ".spv";
|
||||||
|
self.shaderformat = .{ .shaderformatSpirv = true };
|
||||||
|
} else if (formats.shaderformatMsl) {
|
||||||
|
self.shaderType = "msl"; // shaderformatSpirv
|
||||||
|
self.shaderSuffix = ".msl";
|
||||||
|
self.entrypoint = "main0";
|
||||||
|
self.shaderformat = .{ .shaderformatMsl = true };
|
||||||
|
} else if (formats.shaderformatDxil) {
|
||||||
|
self.shaderType = "dxil"; // shaderformatSpirv
|
||||||
|
self.shaderSuffix = ".dxil";
|
||||||
|
self.shaderformat = .{ .shaderformatDxil = true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn createPipeline(self: *@This()) !void {
|
||||||
|
const vertex = try self.loadShader("sample.vert", 0, 0, 1, 0);
|
||||||
|
const fragment = try self.loadShader("sample.frag", 0, 0, 0, 0);
|
||||||
|
|
||||||
|
var pci = std.mem.zeroes(gpu.GPUGraphicsPipelineCreateInfo);
|
||||||
|
pci.fragment_shader = fragment;
|
||||||
|
pci.vertex_shader = vertex;
|
||||||
|
|
||||||
|
pci.target_info.num_color_targets = 1;
|
||||||
|
pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{
|
||||||
|
.{
|
||||||
|
.format = self.device.getGPUSwapchainTextureFormat(self.window),
|
||||||
|
.blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pci.rasterizer_state.fill_mode = .fillmodeFill;
|
||||||
|
self.pipeline = self.device.createGPUGraphicsPipeline(&pci);
|
||||||
|
|
||||||
|
self.colorBuffer = self.device.createGPUBuffer(&.{
|
||||||
|
.usage = .{ .bufferusageVertex = true },
|
||||||
|
.size = 8192 * 2,
|
||||||
|
.props = 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
self.colorBufferTransfer = self.device.createGPUTransferBuffer(&.{
|
||||||
|
.usage = .transferbufferusageUpload,
|
||||||
|
.size = 8192 * 2,
|
||||||
|
.props = 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn loadShader(
|
||||||
|
self: *@This(),
|
||||||
|
shaderName: []const u8,
|
||||||
|
num_samplers: u32, // The number of samplers defined in the shader.
|
||||||
|
num_storage_textures: u32, // The number of storage textures defined in the shader.
|
||||||
|
num_storage_buffers: u32, // The number of storage buffers defined in the shader.
|
||||||
|
num_uniform_buffers: u32, // The number of uniform buffers defined in the shader.
|
||||||
|
) !*gpu.GPUShader {
|
||||||
|
const contentPath = try std.fmt.allocPrint(self.allocator, "_shaders/{s}/{s}{s}", .{ self.shaderType, shaderName, self.shaderSuffix });
|
||||||
|
|
||||||
|
defer self.allocator.free(contentPath);
|
||||||
|
|
||||||
|
const mapping = try core.fs().loadFile(contentPath);
|
||||||
|
defer core.fs().unmap(mapping);
|
||||||
|
|
||||||
|
var stage: gpu.GPUShaderStage = undefined;
|
||||||
|
|
||||||
|
if (std.mem.endsWith(u8, shaderName, ".vert")) {
|
||||||
|
stage = .shaderstageVertex;
|
||||||
|
} else if (std.mem.endsWith(u8, shaderName, ".frag")) {
|
||||||
|
stage = .shaderstageFragment;
|
||||||
|
} else {
|
||||||
|
return error.NotImplemented;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sci = gpu.GPUShaderCreateInfo{
|
||||||
|
.code = @ptrCast(mapping.bytes.ptr),
|
||||||
|
.entrypoint = @ptrCast(self.entrypoint.ptr),
|
||||||
|
.format = self.shaderformat,
|
||||||
|
.code_size = mapping.bytes.len - 1,
|
||||||
|
.stage = stage,
|
||||||
|
.num_samplers = num_samplers,
|
||||||
|
.num_storage_textures = num_storage_textures, // The number of storage textures defined in the shader.
|
||||||
|
.num_storage_buffers = num_storage_buffers, // The number of storage buffers defined in the shader.
|
||||||
|
.num_uniform_buffers = num_uniform_buffers, // The number of uniform buffers defined in the shader.
|
||||||
|
.props = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const rv = self.device.createGPUShader(&sci);
|
||||||
|
core.engine_log("creating shader {s} => {s} {any}", .{ shaderName, contentPath, stage });
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tick(self: *@This(), dt: f64) void {
|
||||||
|
self.totalTime += dt;
|
||||||
|
|
||||||
|
const cmd = self.device.acquireGPUCommandBuffer();
|
||||||
|
var swapchain_texture: *gpu.GPUTexture = undefined;
|
||||||
|
{
|
||||||
|
const buffer = self.device.mapGPUTransferBuffer(self.colorBufferTransfer, true);
|
||||||
|
|
||||||
|
var b: [*][4]f32 = @ptrCast(@alignCast(buffer));
|
||||||
|
|
||||||
|
b[0] = .{ @floatCast(std.math.sin(self.totalTime * 3 * 2 + 0.8) * 0.2 + 0.8), 0.4, 0.4, 1.0 };
|
||||||
|
b[1] = .{ 0.4, @floatCast(std.math.sin(self.totalTime * 2 * 2 + 0.3) * 0.2 + 0.8), 0.4, 1.0 };
|
||||||
|
b[2] = .{ 0.4, 0.4, @floatCast(std.math.sin(self.totalTime * 4 * 2) * 0.2 + 0.8), 1.0 };
|
||||||
|
|
||||||
|
self.device.unmapGPUTransferBuffer(self.colorBufferTransfer);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const copyPass = cmd.beginGPUCopyPass();
|
||||||
|
defer copyPass.endGPUCopyPass();
|
||||||
|
copyPass.uploadToGPUBuffer(&.{ .transfer_buffer = self.colorBufferTransfer, .offset = 0 }, &.{
|
||||||
|
.buffer = self.colorBuffer,
|
||||||
|
.offset = 0,
|
||||||
|
.size = 4 * 12,
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd.waitAndAcquireGPUSwapchainTexture(self.window, &swapchain_texture, null, null)) {
|
||||||
|
var targetInfo: gpu.GPUColorTargetInfo = std.mem.zeroes(gpu.GPUColorTargetInfo);
|
||||||
|
targetInfo.texture = swapchain_texture;
|
||||||
|
targetInfo.clear_color = .{ .r = 0.1, .g = 0.1, .b = 0.1, .a = 1.0 };
|
||||||
|
targetInfo.load_op = .loadopClear;
|
||||||
|
targetInfo.store_op = .storeopStore;
|
||||||
|
|
||||||
|
const renderpass = cmd.beginGPURenderPass(&targetInfo, 1, null);
|
||||||
|
renderpass.bindGPUGraphicsPipeline(self.pipeline);
|
||||||
|
renderpass.bindGPUVertexStorageBuffers(0, &self.colorBuffer, 1);
|
||||||
|
renderpass.setGPUScissor(&self.scissor);
|
||||||
|
renderpass.drawGPUPrimitives(3, 1, 0, 0);
|
||||||
|
renderpass.endGPURenderPass();
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = cmd.submitGPUCommandBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *@This()) void {
|
||||||
|
self.allocator.destroy(self);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub var gRenderer: *Renderer = undefined;
|
||||||
|
pub var gAllocator: std.mem.Allocator = undefined;
|
||||||
|
|
||||||
|
pub fn start() !void {
|
||||||
|
gRenderer = try core.createObject(Renderer, .{ .can_tick = true, .isCore = true });
|
||||||
|
gAllocator = gRenderer.allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shutdown() void {}
|
||||||
|
|
||||||
|
const rend = @import("../rend.zig");
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
const core = @import("core");
|
||||||
|
const platform = @import("platform");
|
||||||
|
const sdl3 = @import("sdl3");
|
||||||
|
const gpu = sdl3.gpu;
|
||||||
|
const SSBO_Scene = @import("sample.vert").Scene;
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
// renderer agnostic shader management
|
||||||
|
|
||||||
|
pub const loadShader = renderer.loadShader;
|
||||||
|
|
||||||
|
const renderer = @import("gpu/renderer");
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
const core = @import("core");
|
||||||
|
|
||||||
|
const rend = @import("rend.zig");
|
||||||
|
|
@ -46,7 +46,7 @@ pub fn startContext(self: *@This()) !void {
|
||||||
.shaderformatSpirv = true,
|
.shaderformatSpirv = true,
|
||||||
.shaderformatDxil = true,
|
.shaderformatDxil = true,
|
||||||
.shaderformatMsl = true,
|
.shaderformatMsl = true,
|
||||||
}, false, null);
|
}, true, null);
|
||||||
|
|
||||||
if (!self.device.claimWindowForGPUDevice(self.window))
|
if (!self.device.claimWindowForGPUDevice(self.window))
|
||||||
return error.UnableToClaimGpu;
|
return error.UnableToClaimGpu;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue