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);
|
||||
}
|
||||
|
||||
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 {
|
||||
gEngine.platformCtx = ctx;
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,9 @@ pub const Engine = struct {
|
|||
platformSetupFunc: ?PollFuncFn = null,
|
||||
platformProcEventsFunc: ?ProcEventsFn = null,
|
||||
|
||||
rendererCtx: *anyopaque = undefined,
|
||||
rendererSetupFunc: ?PollFuncFn = null,
|
||||
|
||||
engineStartTime: f64 = 0,
|
||||
|
||||
nfdRuntime: *nfd.NFDRuntime,
|
||||
|
|
@ -280,6 +283,10 @@ pub const Engine = struct {
|
|||
setupFunc(ctx.engine.platformCtx) catch unreachable;
|
||||
}
|
||||
|
||||
if (ctx.engine.rendererSetupFunc) |setupFunc| {
|
||||
setupFunc(ctx.engine.rendererCtx) catch unreachable;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
ctx.engine.tick() catch unreachable;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const realMain = @import("main");
|
|||
pub const options = @import("BacklogOptions");
|
||||
|
||||
pub const std_options = std.Options{
|
||||
.enable_segfault_handler = false,
|
||||
// .enable_segfault_handler = false,
|
||||
};
|
||||
|
||||
//pub const build_options = @import("build_options");
|
||||
|
|
@ -21,6 +21,6 @@ pub const std_options = std.Options{
|
|||
// }
|
||||
|
||||
pub fn main() !void {
|
||||
panickers.attachSegfaultHandler();
|
||||
// panickers.attachSegfaultHandler();
|
||||
try realMain.main();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,5 @@ pub fn shutdown_module(allocator: std.mem.Allocator) void {
|
|||
|
||||
gPlatformInstance.deinit();
|
||||
|
||||
// I have a bug somewhere. need to find out where it is
|
||||
allocator.destroy(gPlatformInstance);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ pub const PlatformInstance = struct {
|
|||
.video = true,
|
||||
.gamepad = true,
|
||||
}) 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 {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
const std = @import("std");
|
||||
const core = @import("core");
|
||||
const sample_vert = @import("sample.vert");
|
||||
const sgpu_renderer = @import("sgpu/renderer.zig");
|
||||
|
||||
// controls glfw and general windowing
|
||||
// graphics depends on this one
|
||||
|
|
@ -14,11 +14,10 @@ pub fn start_module(comptime programSpec: anytype, args: anytype, allocator: std
|
|||
_ = args;
|
||||
_ = programSpec;
|
||||
_ = allocator;
|
||||
core.engine_log("starting up [REND] module...", .{});
|
||||
core.engine_log("sample_vert.Scene size = {d}", .{@sizeOf(sample_vert.Scene)});
|
||||
try sgpu_renderer.start();
|
||||
}
|
||||
|
||||
pub fn shutdown_module(allocator: std.mem.Allocator) void {
|
||||
_ = 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,
|
||||
.shaderformatDxil = true,
|
||||
.shaderformatMsl = true,
|
||||
}, false, null);
|
||||
}, true, null);
|
||||
|
||||
if (!self.device.claimWindowForGPUDevice(self.window))
|
||||
return error.UnableToClaimGpu;
|
||||
|
|
|
|||
Loading…
Reference in New Issue