Major update | Cleaned up some stuff | Added makeInstance etc for allowing users to pick what type of vk API version and features they want | still f ton stuff to do
This commit is contained in:
parent
9cec2d7810
commit
814abc328d
30 changed files with 819 additions and 458 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,3 +1,2 @@
|
|||
.zig-cache/
|
||||
zig-pkg/
|
||||
zig-out/
|
||||
|
|
|
|||
|
|
@ -44,5 +44,5 @@ src/rhi/vulkan/resource.zig
|
|||
|
||||
## Examples
|
||||
- ```zig build run-simple```
|
||||
- ```zig build run-3D```
|
||||
- ```zig build run-imgui```
|
||||
- ```zig build run-3D```
|
||||
|
|
|
|||
10
build.zig
10
build.zig
|
|
@ -73,6 +73,8 @@ pub fn build(b: *std.Build) !void {
|
|||
mod.addImport("fast_obj", fast_obj.createModule());
|
||||
mod.addCSourceFiles(.{ .files = &.{"src/vendor/fast_obj/fast_obj.c"} });
|
||||
|
||||
const check_step = b.step("check", "Check if compiles");
|
||||
|
||||
//
|
||||
// EXAMPLES
|
||||
//
|
||||
|
|
@ -125,6 +127,11 @@ pub fn build(b: *std.Build) !void {
|
|||
|
||||
example.root_module.addImport("gfx", mod);
|
||||
|
||||
const common = b.addModule("common", .{
|
||||
.root_source_file = b.path("examples/common.zig"),
|
||||
});
|
||||
example.root_module.addImport("common", common);
|
||||
|
||||
const sdl = b.addTranslateC(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
|
|
@ -187,7 +194,6 @@ pub fn build(b: *std.Build) !void {
|
|||
const example_build_step = b.addInstallArtifact(example, .{});
|
||||
example_step.dependOn(&example_build_step.step);
|
||||
|
||||
// const check_step = b.step("check", "Check if compiles");
|
||||
// check_step.dependOn(&example.step);
|
||||
check_step.dependOn(&example.step);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
10
compile.sh
10
compile.sh
|
|
@ -1,10 +0,0 @@
|
|||
clear
|
||||
|
||||
glslc examples/assets/shaders/simple.vert -o examples/assets/shaders/compiled/simple.vert.spv
|
||||
glslc examples/assets/shaders/simple.frag -o examples/assets/shaders/compiled/simple.frag.spv
|
||||
|
||||
glslc examples/assets/shaders/3D.vert -o examples/assets/shaders/compiled/3D.vert.spv
|
||||
glslc examples/assets/shaders/3D.frag -o examples/assets/shaders/compiled/3D.frag.spv
|
||||
|
||||
glslc examples/assets/shaders/imgui.vert -o examples/assets/shaders/compiled/imgui.vert.spv
|
||||
glslc examples/assets/shaders/imgui.frag -o examples/assets/shaders/compiled/imgui.frag.spv
|
||||
Binary file not shown.
|
|
@ -4,8 +4,8 @@
|
|||
// IO
|
||||
//
|
||||
|
||||
layout(location = 0) in vec2 in_position;
|
||||
layout(location = 1) in vec2 in_normal;
|
||||
layout(location = 0) in vec3 in_position;
|
||||
layout(location = 1) in vec3 in_normal;
|
||||
layout(location = 2) in vec2 in_UV;
|
||||
|
||||
layout(location = 0) out vec2 out_UV;
|
||||
|
|
@ -13,6 +13,6 @@ layout(location = 0) out vec2 out_UV;
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
void main() {
|
||||
gl_Position = vec4(in_position, 0.0, 1.0);
|
||||
gl_Position = vec4(in_position, 1.0);
|
||||
out_UV = in_UV;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const UnlitMaterial = struct {
|
||||
albedo: [4]f32 = .{ 1, 1, 1, 1 },
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const Vertex = struct {
|
||||
pos: [3]f32,
|
||||
normal: [3]f32,
|
||||
uv: [2]f32,
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const Square = struct {
|
||||
pub const vertices = [_]Vertex{
|
||||
.{ .pos = .{ -0.5, -0.5, 0 }, .normal = .{ 0, 0, 0 }, .uv = .{ 0, 0 } },
|
||||
.{ .pos = .{ 0.5, -0.5, 0 }, .normal = .{ 0, 0, 0 }, .uv = .{ 1, 0 } },
|
||||
.{ .pos = .{ 0.5, 0.5, 0 }, .normal = .{ 0, 0, 0 }, .uv = .{ 1, 1 } },
|
||||
.{ .pos = .{ -0.5, 0.5, 0 }, .normal = .{ 0, 0, 0 }, .uv = .{ 0, 1 } },
|
||||
};
|
||||
|
||||
pub const indices = [_]u32{
|
||||
0, 1, 2,
|
||||
0, 2, 3,
|
||||
};
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const Cube = struct {
|
||||
pub const vertices = [_]Vertex{
|
||||
.{ .pos = .{ -0.5, -0.5, 0.5 }, .normal = .{ 0, 0, 1 }, .uv = .{ 0, 0 } },
|
||||
.{ .pos = .{ 0.5, -0.5, 0.5 }, .normal = .{ 0, 0, 1 }, .uv = .{ 1, 0 } },
|
||||
.{ .pos = .{ 0.5, 0.5, 0.5 }, .normal = .{ 0, 0, 1 }, .uv = .{ 1, 1 } },
|
||||
.{ .pos = .{ -0.5, 0.5, 0.5 }, .normal = .{ 0, 0, 1 }, .uv = .{ 0, 1 } },
|
||||
|
||||
.{ .pos = .{ 0.5, -0.5, -0.5 }, .normal = .{ 0, 0, -1 }, .uv = .{ 0, 0 } },
|
||||
.{ .pos = .{ -0.5, -0.5, -0.5 }, .normal = .{ 0, 0, -1 }, .uv = .{ 1, 0 } },
|
||||
.{ .pos = .{ -0.5, 0.5, -0.5 }, .normal = .{ 0, 0, -1 }, .uv = .{ 1, 1 } },
|
||||
.{ .pos = .{ 0.5, 0.5, -0.5 }, .normal = .{ 0, 0, -1 }, .uv = .{ 0, 1 } },
|
||||
|
||||
.{ .pos = .{ -0.5, -0.5, -0.5 }, .normal = .{ -1, 0, 0 }, .uv = .{ 0, 0 } },
|
||||
.{ .pos = .{ -0.5, -0.5, 0.5 }, .normal = .{ -1, 0, 0 }, .uv = .{ 1, 0 } },
|
||||
.{ .pos = .{ -0.5, 0.5, 0.5 }, .normal = .{ -1, 0, 0 }, .uv = .{ 1, 1 } },
|
||||
.{ .pos = .{ -0.5, 0.5, -0.5 }, .normal = .{ -1, 0, 0 }, .uv = .{ 0, 1 } },
|
||||
|
||||
.{ .pos = .{ 0.5, -0.5, 0.5 }, .normal = .{ 1, 0, 0 }, .uv = .{ 0, 0 } },
|
||||
.{ .pos = .{ 0.5, -0.5, -0.5 }, .normal = .{ 1, 0, 0 }, .uv = .{ 1, 0 } },
|
||||
.{ .pos = .{ 0.5, 0.5, -0.5 }, .normal = .{ 1, 0, 0 }, .uv = .{ 1, 1 } },
|
||||
.{ .pos = .{ 0.5, 0.5, 0.5 }, .normal = .{ 1, 0, 0 }, .uv = .{ 0, 1 } },
|
||||
|
||||
.{ .pos = .{ -0.5, 0.5, 0.5 }, .normal = .{ 0, 1, 0 }, .uv = .{ 0, 0 } },
|
||||
.{ .pos = .{ 0.5, 0.5, 0.5 }, .normal = .{ 0, 1, 0 }, .uv = .{ 1, 0 } },
|
||||
.{ .pos = .{ 0.5, 0.5, -0.5 }, .normal = .{ 0, 1, 0 }, .uv = .{ 1, 1 } },
|
||||
.{ .pos = .{ -0.5, 0.5, -0.5 }, .normal = .{ 0, 1, 0 }, .uv = .{ 0, 1 } },
|
||||
|
||||
.{ .pos = .{ -0.5, -0.5, -0.5 }, .normal = .{ 0, -1, 0 }, .uv = .{ 0, 0 } },
|
||||
.{ .pos = .{ 0.5, -0.5, -0.5 }, .normal = .{ 0, -1, 0 }, .uv = .{ 1, 0 } },
|
||||
.{ .pos = .{ 0.5, -0.5, 0.5 }, .normal = .{ 0, -1, 0 }, .uv = .{ 1, 1 } },
|
||||
.{ .pos = .{ -0.5, -0.5, 0.5 }, .normal = .{ 0, -1, 0 }, .uv = .{ 0, 1 } },
|
||||
};
|
||||
|
||||
pub const indices = [_]u32{
|
||||
0, 1, 2,
|
||||
0, 2, 3,
|
||||
|
||||
4, 5, 6,
|
||||
4, 6, 7,
|
||||
|
||||
8, 9, 10,
|
||||
8, 10, 11,
|
||||
|
||||
12, 13, 14,
|
||||
12, 14, 15,
|
||||
|
||||
16, 17, 18,
|
||||
16, 18, 19,
|
||||
|
||||
20, 21, 22,
|
||||
20, 22, 23,
|
||||
};
|
||||
};
|
||||
|
|
@ -37,19 +37,27 @@ pub fn main(init: std.process.Init) !void {
|
|||
//
|
||||
|
||||
// --- # ---
|
||||
var gfx: Gfx = try .init(.{
|
||||
.window = .{
|
||||
var gfx: Gfx = try .init(
|
||||
init.gpa,
|
||||
init.io,
|
||||
);
|
||||
defer gfx.deinit();
|
||||
|
||||
// --- # ---
|
||||
const instance = try gfx.makeInstance(.{
|
||||
.vulkan = .{
|
||||
.api_version = .v1_3,
|
||||
},
|
||||
});
|
||||
|
||||
const surface = try gfx.makeSurface(.{
|
||||
.xlib = .{
|
||||
.window = @intCast(xwindow),
|
||||
.display = display.?,
|
||||
},
|
||||
},
|
||||
}, init.gpa, init.io);
|
||||
defer gfx.deinit();
|
||||
}, instance);
|
||||
|
||||
// --- # ---
|
||||
const adapter = try gfx.makeAdapter(.{ .gpu_type = .any });
|
||||
const surface = try gfx.makeSurface();
|
||||
const adapter = try gfx.makeAdapter(.{}, instance);
|
||||
const device = try gfx.makeDevice(adapter, surface);
|
||||
const swapchain = try gfx.makeSwapchain(adapter, device, surface);
|
||||
|
||||
|
|
@ -65,6 +73,11 @@ pub fn main(init: std.process.Init) !void {
|
|||
if (!im_sdl.cImGui_ImplSDL3_InitForVulkan(@ptrCast(window))) return error.FailedToImplImGuiForSDL;
|
||||
defer im_sdl.cImGui_ImplSDL3_Shutdown();
|
||||
|
||||
// --- SET IO ---
|
||||
const io = im.ImGui_GetIO() orelse return error.FailedToGetImGuiIO;
|
||||
io.*.ConfigFlags |= im.ImGuiConfigFlags_NavEnableKeyboard;
|
||||
io.*.ConfigFlags |= im.ImGuiConfigFlags_DockingEnable;
|
||||
|
||||
// --- GET VK RAW DEVICE ---
|
||||
const raw_device = switch (try gfx.getRawDevice(device)) {
|
||||
.vulkan => |v| v,
|
||||
|
|
@ -76,7 +89,7 @@ pub fn main(init: std.process.Init) !void {
|
|||
// --- INIT IMGUI FOR VK ---
|
||||
var color_format: im_vk.VkFormat = raw_swapchain.format;
|
||||
var im_info: im_vk.ImGui_ImplVulkan_InitInfo = .{
|
||||
.Instance = @ptrCast(gfx.getRawInstance().vulkan),
|
||||
.Instance = @ptrCast((try gfx.getRawInstance(instance)).vulkan),
|
||||
.PhysicalDevice = blk: {
|
||||
switch (try gfx.getRawAdapter(adapter)) {
|
||||
.vulkan => |v| break :blk @ptrCast(v),
|
||||
|
|
|
|||
3
examples/simple/README.md
Normal file
3
examples/simple/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Simple Example
|
||||
|
||||

|
||||
BIN
examples/simple/image
Normal file
BIN
examples/simple/image
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 281 KiB |
|
|
@ -3,38 +3,9 @@
|
|||
|
||||
const std = @import("std");
|
||||
const sdl = @import("sdl");
|
||||
const cmn = @import("common");
|
||||
const Gfx = @import("gfx");
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
const UnlitMaterial = struct {
|
||||
albedo: [4]f32 = .{ 1, 1, 1, 1 },
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
const Vertex = struct {
|
||||
pos: [2]f32,
|
||||
normal: [2]f32,
|
||||
uv: [2]f32,
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
const vertices = [_]Vertex{
|
||||
.{ .pos = .{ -0.5, -0.5 }, .normal = .{ 0, 0 }, .uv = .{ 0, 0 } },
|
||||
.{ .pos = .{ 0.5, -0.5 }, .normal = .{ 0, 0 }, .uv = .{ 1, 0 } },
|
||||
.{ .pos = .{ 0.5, 0.5 }, .normal = .{ 0, 0 }, .uv = .{ 1, 1 } },
|
||||
.{ .pos = .{ -0.5, 0.5 }, .normal = .{ 0, 0 }, .uv = .{ 0, 1 } },
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
const indices = [_]u32{
|
||||
0, 1, 2,
|
||||
0, 2, 3,
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn main(init: std.process.Init) !void {
|
||||
|
|
@ -43,7 +14,7 @@ pub fn main(init: std.process.Init) !void {
|
|||
// DATA
|
||||
//
|
||||
|
||||
var material: UnlitMaterial = .{ .albedo = .{ 1.0, 0.2, 0.2, 1.0 } };
|
||||
var material: cmn.UnlitMaterial = .{ .albedo = .{ 1.0, 0.2, 0.2, 1.0 } };
|
||||
|
||||
//
|
||||
// SDL
|
||||
|
|
@ -67,21 +38,27 @@ pub fn main(init: std.process.Init) !void {
|
|||
//
|
||||
|
||||
// --- # ---
|
||||
var gfx: Gfx = try .init(.{
|
||||
.window = .{
|
||||
var gfx: Gfx = try .init(
|
||||
init.gpa,
|
||||
init.io,
|
||||
);
|
||||
defer gfx.deinit();
|
||||
|
||||
// --- # ---
|
||||
const instance = try gfx.makeInstance(.{
|
||||
.vulkan = .{
|
||||
.api_version = .v1_3,
|
||||
},
|
||||
});
|
||||
|
||||
const surface = try gfx.makeSurface(.{
|
||||
.xlib = .{
|
||||
.window = @intCast(xwindow),
|
||||
.display = display.?,
|
||||
},
|
||||
},
|
||||
}, init.gpa, init.io);
|
||||
defer gfx.deinit();
|
||||
}, instance);
|
||||
|
||||
errdefer gfx.deinit();
|
||||
|
||||
// --- # ---
|
||||
const adapter = try gfx.makeAdapter(.{ .gpu_type = .any });
|
||||
const surface = try gfx.makeSurface();
|
||||
const adapter = try gfx.makeAdapter(.{}, instance);
|
||||
const device = try gfx.makeDevice(adapter, surface);
|
||||
const swapchain = try gfx.makeSwapchain(adapter, device, surface);
|
||||
|
||||
|
|
@ -92,8 +69,8 @@ pub fn main(init: std.process.Init) !void {
|
|||
}, adapter, device);
|
||||
|
||||
// --- BUFFERS ---
|
||||
const vbuf = try gfx.makeBuffer(vertices, .vertex, adapter, device);
|
||||
const ibuf = try gfx.makeBuffer(indices, .index, adapter, device);
|
||||
const vbuf = try gfx.makeBuffer(cmn.Square.vertices, .vertex, adapter, device);
|
||||
const ibuf = try gfx.makeBuffer(cmn.Square.indices, .index, adapter, device);
|
||||
|
||||
// --- SHADERS ---
|
||||
const simple_vert = try gfx.makeShader("examples/assets/shaders/compiled/simple.vert.spv", device);
|
||||
|
|
@ -102,14 +79,14 @@ pub fn main(init: std.process.Init) !void {
|
|||
// --- PIPELINE ---
|
||||
const pipeline = try gfx.makePipeline(.{
|
||||
.vertex_attributes = &.{
|
||||
.{ .location = 0, .format = .vec2, .offset = @offsetOf(Vertex, "pos") },
|
||||
.{ .location = 1, .format = .vec2, .offset = @offsetOf(Vertex, "normal") },
|
||||
.{ .location = 2, .format = .vec2, .offset = @offsetOf(Vertex, "uv") },
|
||||
.{ .location = 0, .format = .vec3, .offset = @offsetOf(cmn.Vertex, "pos") },
|
||||
.{ .location = 1, .format = .vec3, .offset = @offsetOf(cmn.Vertex, "normal") },
|
||||
.{ .location = 2, .format = .vec2, .offset = @offsetOf(cmn.Vertex, "uv") },
|
||||
},
|
||||
.vertex_binding = .{ .stride = @sizeOf(Vertex) },
|
||||
.vertex_binding = .{ .stride = @sizeOf(cmn.Vertex) },
|
||||
|
||||
.uniforms = &.{
|
||||
.{ .name = "material", .size = @sizeOf(UnlitMaterial) },
|
||||
.{ .name = "material", .size = @sizeOf(cmn.UnlitMaterial) },
|
||||
},
|
||||
|
||||
.textures = &.{
|
||||
|
|
@ -160,7 +137,7 @@ pub fn main(init: std.process.Init) !void {
|
|||
try ibuf.bind();
|
||||
|
||||
try pipeline.bind();
|
||||
pass.drawIndexed(indices.len, 1, 0, 0, 0);
|
||||
pass.drawIndexed(cmn.Square.indices.len, 1, 0, 0, 0);
|
||||
}
|
||||
|
||||
// --- NEW PASS ---
|
||||
|
|
|
|||
|
|
@ -5,78 +5,9 @@ const vk = @import("vulkan");
|
|||
const std = @import("std");
|
||||
const sdl = @import("sdl");
|
||||
const math = @import("math");
|
||||
const cmn = @import("common");
|
||||
const Gfx = @import("gfx");
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
const UnlitMaterial = struct {
|
||||
albedo: [4]f32 = .{ 1, 1, 1, 1 },
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
const Vertex = struct {
|
||||
pos: [3]f32,
|
||||
normal: [3]f32,
|
||||
uv: [2]f32,
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
const vertices = [_]Vertex{
|
||||
.{ .pos = .{ -0.5, -0.5, 0.5 }, .normal = .{ 0, 0, 1 }, .uv = .{ 0, 0 } },
|
||||
.{ .pos = .{ 0.5, -0.5, 0.5 }, .normal = .{ 0, 0, 1 }, .uv = .{ 1, 0 } },
|
||||
.{ .pos = .{ 0.5, 0.5, 0.5 }, .normal = .{ 0, 0, 1 }, .uv = .{ 1, 1 } },
|
||||
.{ .pos = .{ -0.5, 0.5, 0.5 }, .normal = .{ 0, 0, 1 }, .uv = .{ 0, 1 } },
|
||||
|
||||
.{ .pos = .{ 0.5, -0.5, -0.5 }, .normal = .{ 0, 0, -1 }, .uv = .{ 0, 0 } },
|
||||
.{ .pos = .{ -0.5, -0.5, -0.5 }, .normal = .{ 0, 0, -1 }, .uv = .{ 1, 0 } },
|
||||
.{ .pos = .{ -0.5, 0.5, -0.5 }, .normal = .{ 0, 0, -1 }, .uv = .{ 1, 1 } },
|
||||
.{ .pos = .{ 0.5, 0.5, -0.5 }, .normal = .{ 0, 0, -1 }, .uv = .{ 0, 1 } },
|
||||
|
||||
.{ .pos = .{ -0.5, -0.5, -0.5 }, .normal = .{ -1, 0, 0 }, .uv = .{ 0, 0 } },
|
||||
.{ .pos = .{ -0.5, -0.5, 0.5 }, .normal = .{ -1, 0, 0 }, .uv = .{ 1, 0 } },
|
||||
.{ .pos = .{ -0.5, 0.5, 0.5 }, .normal = .{ -1, 0, 0 }, .uv = .{ 1, 1 } },
|
||||
.{ .pos = .{ -0.5, 0.5, -0.5 }, .normal = .{ -1, 0, 0 }, .uv = .{ 0, 1 } },
|
||||
|
||||
.{ .pos = .{ 0.5, -0.5, 0.5 }, .normal = .{ 1, 0, 0 }, .uv = .{ 0, 0 } },
|
||||
.{ .pos = .{ 0.5, -0.5, -0.5 }, .normal = .{ 1, 0, 0 }, .uv = .{ 1, 0 } },
|
||||
.{ .pos = .{ 0.5, 0.5, -0.5 }, .normal = .{ 1, 0, 0 }, .uv = .{ 1, 1 } },
|
||||
.{ .pos = .{ 0.5, 0.5, 0.5 }, .normal = .{ 1, 0, 0 }, .uv = .{ 0, 1 } },
|
||||
|
||||
.{ .pos = .{ -0.5, 0.5, 0.5 }, .normal = .{ 0, 1, 0 }, .uv = .{ 0, 0 } },
|
||||
.{ .pos = .{ 0.5, 0.5, 0.5 }, .normal = .{ 0, 1, 0 }, .uv = .{ 1, 0 } },
|
||||
.{ .pos = .{ 0.5, 0.5, -0.5 }, .normal = .{ 0, 1, 0 }, .uv = .{ 1, 1 } },
|
||||
.{ .pos = .{ -0.5, 0.5, -0.5 }, .normal = .{ 0, 1, 0 }, .uv = .{ 0, 1 } },
|
||||
|
||||
.{ .pos = .{ -0.5, -0.5, -0.5 }, .normal = .{ 0, -1, 0 }, .uv = .{ 0, 0 } },
|
||||
.{ .pos = .{ 0.5, -0.5, -0.5 }, .normal = .{ 0, -1, 0 }, .uv = .{ 1, 0 } },
|
||||
.{ .pos = .{ 0.5, -0.5, 0.5 }, .normal = .{ 0, -1, 0 }, .uv = .{ 1, 1 } },
|
||||
.{ .pos = .{ -0.5, -0.5, 0.5 }, .normal = .{ 0, -1, 0 }, .uv = .{ 0, 1 } },
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
const indices = [_]u32{
|
||||
0, 1, 2,
|
||||
0, 2, 3,
|
||||
|
||||
4, 5, 6,
|
||||
4, 6, 7,
|
||||
|
||||
8, 9, 10,
|
||||
8, 10, 11,
|
||||
|
||||
12, 13, 14,
|
||||
12, 14, 15,
|
||||
|
||||
16, 17, 18,
|
||||
16, 18, 19,
|
||||
|
||||
20, 21, 22,
|
||||
20, 22, 23,
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
const Camera = struct {
|
||||
|
|
@ -98,7 +29,7 @@ pub fn main(init: std.process.Init) !void {
|
|||
// DATA
|
||||
//
|
||||
|
||||
var material: UnlitMaterial = .{ .albedo = .{ 1.0, 0.2, 0.2, 1.0 } };
|
||||
var material: cmn.UnlitMaterial = .{ .albedo = .{ 1.0, 0.2, 0.2, 1.0 } };
|
||||
const camera: Camera = .{
|
||||
.projection = .perspective(std.math.degreesToRadians(90), 800.0 / 600.0, 0.01, 1000),
|
||||
.view = .lookAt(.new(.{ 1, 1, -2 }), .new(.{ 0, 0, 1 }), .new(.{ 0, 1, 0 })),
|
||||
|
|
@ -138,23 +69,26 @@ pub fn main(init: std.process.Init) !void {
|
|||
// GFX
|
||||
//
|
||||
|
||||
// --- # ---
|
||||
var gfx: Gfx = try .init(.{
|
||||
.window = .{
|
||||
var gfx: Gfx = try .init(
|
||||
init.gpa,
|
||||
init.io,
|
||||
);
|
||||
defer gfx.deinit();
|
||||
|
||||
const instance = try gfx.makeInstance(.{
|
||||
.vulkan = .{
|
||||
.api_version = .v1_3,
|
||||
},
|
||||
});
|
||||
|
||||
const surface = try gfx.makeSurface(.{
|
||||
.xlib = .{
|
||||
.window = @intCast(xwindow),
|
||||
.display = display.?,
|
||||
},
|
||||
},
|
||||
.backend = .vulkan,
|
||||
}, init.gpa, init.io);
|
||||
defer gfx.deinit();
|
||||
}, instance);
|
||||
|
||||
errdefer gfx.deinit();
|
||||
|
||||
// --- # ---
|
||||
const adapter = try gfx.makeAdapter(.{ .gpu_type = .any });
|
||||
const surface = try gfx.makeSurface();
|
||||
const adapter = try gfx.makeAdapter(.{}, instance);
|
||||
const device = try gfx.makeDevice(adapter, surface);
|
||||
const swapchain = try gfx.makeSwapchain(adapter, device, surface);
|
||||
|
||||
|
|
@ -169,8 +103,8 @@ pub fn main(init: std.process.Init) !void {
|
|||
}, adapter, device);
|
||||
|
||||
// --- BUFFERS ---
|
||||
const vbuf = try gfx.makeBuffer(vertices, .vertex, adapter, device);
|
||||
const ibuf = try gfx.makeBuffer(indices, .index, adapter, device);
|
||||
const vbuf = try gfx.makeBuffer(cmn.Cube.vertices, .vertex, adapter, device);
|
||||
const ibuf = try gfx.makeBuffer(cmn.Cube.indices, .index, adapter, device);
|
||||
|
||||
// --- SHADERS ---
|
||||
const simple_vert = try gfx.makeShader("examples/assets/shaders/compiled/3D.vert.spv", device);
|
||||
|
|
@ -179,11 +113,11 @@ pub fn main(init: std.process.Init) !void {
|
|||
// --- PIPELINE ---
|
||||
const pipeline = try gfx.makePipeline(.{
|
||||
.vertex_attributes = &.{
|
||||
.{ .location = 0, .format = .vec3, .offset = @offsetOf(Vertex, "pos") },
|
||||
.{ .location = 1, .format = .vec3, .offset = @offsetOf(Vertex, "normal") },
|
||||
.{ .location = 2, .format = .vec2, .offset = @offsetOf(Vertex, "uv") },
|
||||
.{ .location = 0, .format = .vec3, .offset = @offsetOf(cmn.Vertex, "pos") },
|
||||
.{ .location = 1, .format = .vec3, .offset = @offsetOf(cmn.Vertex, "normal") },
|
||||
.{ .location = 2, .format = .vec2, .offset = @offsetOf(cmn.Vertex, "uv") },
|
||||
},
|
||||
.vertex_binding = .{ .stride = @sizeOf(Vertex) },
|
||||
.vertex_binding = .{ .stride = @sizeOf(cmn.Vertex) },
|
||||
|
||||
.uniforms = &.{
|
||||
.{ .name = "camera", .size = @sizeOf(Camera) },
|
||||
|
|
@ -245,7 +179,7 @@ pub fn main(init: std.process.Init) !void {
|
|||
try ibuf.bind();
|
||||
|
||||
try pipeline.bind();
|
||||
pass.drawIndexed(indices.len, 1, 0, 0, 0);
|
||||
pass.drawIndexed(cmn.Cube.indices.len, 1, 0, 0, 0);
|
||||
}
|
||||
|
||||
// --- NEW PASS ---
|
||||
|
|
|
|||
32
imgui.ini
32
imgui.ini
|
|
@ -2,17 +2,37 @@
|
|||
Pos=60,60
|
||||
Size=400,400
|
||||
Collapsed=0
|
||||
LastUsed=20260814
|
||||
LastUsed=20260818
|
||||
|
||||
[Window][Inspector]
|
||||
Pos=25,55
|
||||
Size=341,210
|
||||
Pos=87,36
|
||||
Size=622,253
|
||||
Collapsed=0
|
||||
LastUsed=20260814
|
||||
DockId=0x00000002,0
|
||||
LastUsed=20260818
|
||||
|
||||
[Window][Dear ImGui Demo]
|
||||
Pos=416,63
|
||||
Size=305,363
|
||||
Pos=87,291
|
||||
Size=622,257
|
||||
Collapsed=0
|
||||
DockId=0x00000003,0
|
||||
LastUsed=20260818
|
||||
|
||||
[Table][0x51D6F5EA,3]
|
||||
Column 0 Weight=1.0000
|
||||
Column 1 Weight=1.0000
|
||||
Column 2 Weight=1.0000
|
||||
LastUsed=20260814
|
||||
|
||||
[Table][0xE102187A,3]
|
||||
RefScale=13
|
||||
Column 0 Width=63
|
||||
Column 1 Width=63
|
||||
Column 2 Width=63
|
||||
LastUsed=20260814
|
||||
|
||||
[Docking][Data]
|
||||
DockNode ID=0x00000001 Pos=87,36 Size=622,512 Split=Y
|
||||
DockNode ID=0x00000002 Parent=0x00000001 SizeRef=361,237 Selected=0x36DC96AB
|
||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=361,241 Selected=0x5E5F7166
|
||||
|
||||
|
|
|
|||
154
src/gfx.zig
154
src/gfx.zig
|
|
@ -13,6 +13,7 @@ const Self = @This();
|
|||
pub const Handle = gtl.Handle;
|
||||
|
||||
// --- CONFIGS ---
|
||||
pub const InstanceConfig = common.InstanceConfig;
|
||||
pub const AdapterConfig = common.AdapterConfig;
|
||||
pub const RenderPassConfig = common.RenderPassConfig;
|
||||
pub const PipelineConfig = common.PipelineConfig;
|
||||
|
|
@ -23,6 +24,7 @@ pub const SamplerConfig = common.SamplerConfig;
|
|||
pub const TextureConfig = common.TextureConfig;
|
||||
|
||||
// --- HANDLES ---
|
||||
pub const Instance = common.Instance;
|
||||
pub const Window = common.Window;
|
||||
pub const Adapter = common.Adapter;
|
||||
pub const Device = common.Device;
|
||||
|
|
@ -59,23 +61,11 @@ const BackendCTX = union(Backend) {
|
|||
vulkan: VulkanRHI,
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const Config = struct {
|
||||
app_name: []const u8 = "NYXGFX",
|
||||
engine_name: []const u8 = "NYX",
|
||||
enable_validation: bool = true,
|
||||
|
||||
window: Window,
|
||||
backend: Backend = .vulkan,
|
||||
};
|
||||
|
||||
//
|
||||
// FIELDS
|
||||
//
|
||||
|
||||
ctx: BackendCTX,
|
||||
config: Config,
|
||||
ctx: ?BackendCTX,
|
||||
|
||||
alloc: std.mem.Allocator,
|
||||
io: std.Io,
|
||||
|
|
@ -87,17 +77,11 @@ io: std.Io,
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn init(
|
||||
config: Config,
|
||||
alloc: std.mem.Allocator,
|
||||
io: std.Io,
|
||||
) !Self {
|
||||
const backend_ctx: BackendCTX = switch (config.backend) {
|
||||
.vulkan => .{ .vulkan = try .init(config, alloc, io) },
|
||||
};
|
||||
|
||||
return .{
|
||||
.config = config,
|
||||
.ctx = backend_ctx,
|
||||
.ctx = null,
|
||||
.alloc = alloc,
|
||||
.io = io,
|
||||
};
|
||||
|
|
@ -106,7 +90,7 @@ pub fn init(
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn deinit(self: *Self) void {
|
||||
switch (self.ctx) {
|
||||
switch ((self.getBackend() catch return).*) {
|
||||
.vulkan => |*v| v.deinit(),
|
||||
}
|
||||
}
|
||||
|
|
@ -117,16 +101,47 @@ pub fn deinit(self: *Self) void {
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn getRawInstance(self: *Self) RawInstance {
|
||||
return switch (self.ctx) {
|
||||
.vulkan => |*v| .{ .vulkan = v.instance.raw },
|
||||
pub fn makeInstance(self: *Self, config: InstanceConfig) !Handle(Instance) {
|
||||
switch (config) {
|
||||
.vulkan => |v| {
|
||||
self.ctx = .{
|
||||
.vulkan = .init(self.alloc, self.io),
|
||||
};
|
||||
return try self.ctx.?.vulkan.makeInstance(v);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn deleteInstance(self: *Self, instance: Handle(Instance)) void {
|
||||
switch ((self.getBackend() catch return).*) {
|
||||
.vulkan => |*v| v.deleteInstance(instance),
|
||||
}
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn releaseInstance(self: *Self, instance: Handle(Instance)) void {
|
||||
switch ((self.getBackend() catch return).*) {
|
||||
.vulkan => |*v| v.releaseInstance(instance),
|
||||
}
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn getRawInstance(self: *Self, instance: Handle(Instance)) !RawInstance {
|
||||
return switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| .{
|
||||
.vulkan = (v.resource.instances.get(instance) orelse return error.InstanceNotFound).raw,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn getRawFrame(self: *Self) !RawFrame {
|
||||
switch (self.ctx) {
|
||||
switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| {
|
||||
const raw_frame = v.currentFrame();
|
||||
return .{
|
||||
|
|
@ -147,16 +162,16 @@ pub fn getRawFrame(self: *Self) !RawFrame {
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn makeAdapter(self: *Self, config: AdapterConfig) !Handle(Adapter) {
|
||||
return try switch (self.ctx) {
|
||||
.vulkan => |*v| v.makeAdapter(config),
|
||||
pub fn makeAdapter(self: *Self, config: AdapterConfig, instance: Handle(Instance)) !Handle(Adapter) {
|
||||
return try switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.makeAdapter(config, instance),
|
||||
};
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn deleteAdapter(self: *Self, adapter: Handle(Adapter)) void {
|
||||
switch (self.ctx) {
|
||||
switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.deleteAdapter(adapter),
|
||||
}
|
||||
}
|
||||
|
|
@ -164,7 +179,7 @@ pub fn deleteAdapter(self: *Self, adapter: Handle(Adapter)) void {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn releaseAdapter(self: *Self, adapter: Handle(Adapter)) void {
|
||||
switch (self.ctx) {
|
||||
switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.releaseAdapter(adapter),
|
||||
}
|
||||
}
|
||||
|
|
@ -172,7 +187,7 @@ pub fn releaseAdapter(self: *Self, adapter: Handle(Adapter)) void {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn getAdapterInfo(self: *Self, adapter: Handle(Adapter)) ?AdapterInfo {
|
||||
return switch (self.ctx) {
|
||||
return switch ((self.getBackend() catch return null).*) {
|
||||
.vulkan => |*v| v.getAdapterInfo(adapter),
|
||||
};
|
||||
}
|
||||
|
|
@ -180,7 +195,7 @@ pub fn getAdapterInfo(self: *Self, adapter: Handle(Adapter)) ?AdapterInfo {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn getRawAdapter(self: *Self, adapter: Handle(Adapter)) !RawAdapter {
|
||||
return switch (self.ctx) {
|
||||
return switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| .{ .vulkan = try v.getRawAdapter(adapter) },
|
||||
};
|
||||
}
|
||||
|
|
@ -196,7 +211,7 @@ pub fn makeDevice(
|
|||
adapter: Handle(Adapter),
|
||||
surface: Handle(Surface),
|
||||
) !Handle(Device) {
|
||||
return try switch (self.ctx) {
|
||||
return try switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.makeDevice(adapter, surface),
|
||||
};
|
||||
}
|
||||
|
|
@ -204,7 +219,7 @@ pub fn makeDevice(
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn deleteDevice(self: *Self, device: Handle(Device)) void {
|
||||
switch (self.ctx) {
|
||||
switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.deleteDevice(device),
|
||||
}
|
||||
}
|
||||
|
|
@ -212,7 +227,7 @@ pub fn deleteDevice(self: *Self, device: Handle(Device)) void {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn releaseDevice(self: *Self, device: Handle(Device)) void {
|
||||
switch (self.ctx) {
|
||||
switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.releaseDevice(device),
|
||||
}
|
||||
}
|
||||
|
|
@ -220,12 +235,12 @@ pub fn releaseDevice(self: *Self, device: Handle(Device)) void {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn getRawDevice(self: *Self, device: Handle(Device)) !RawDevice {
|
||||
switch (self.ctx) {
|
||||
switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| {
|
||||
const raw_device = v.resource.devices.get(device) orelse return error.DeviceNotFound;
|
||||
return .{
|
||||
.vulkan = .{
|
||||
.device = raw_device.raw orelse return error.NullDevice,
|
||||
.device = raw_device.raw,
|
||||
.graphics_queue = raw_device.graphics_queue,
|
||||
.present_queue = raw_device.present_queue,
|
||||
},
|
||||
|
|
@ -237,7 +252,7 @@ pub fn getRawDevice(self: *Self, device: Handle(Device)) !RawDevice {
|
|||
// /// ----------------------------------------------------
|
||||
// /// ----------------------------------------------------
|
||||
// pub fn getRawDevice(self: *Self, device: Handle(Device)) !RawDevice {
|
||||
// return switch (self.ctx) {
|
||||
// return switch ((try self.getBackend()).*) {
|
||||
// .vulkan => |*v| .{ .vulkan = try v.getRawDevice(device) },
|
||||
// };
|
||||
// }
|
||||
|
|
@ -257,7 +272,7 @@ pub fn makeBuffer(
|
|||
) !Buffer {
|
||||
const size = @sizeOf(@TypeOf(value));
|
||||
|
||||
const handle = try switch (self.ctx) {
|
||||
const handle = try switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.makeBuffer(size, usage, .exclusive, adapter, device),
|
||||
};
|
||||
|
||||
|
|
@ -274,7 +289,7 @@ pub fn makeBuffer(
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn deleteBuffer(self: *Self, buffer: Handle(Buffer)) void {
|
||||
switch (self.ctx) {
|
||||
switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.deleteBuffer(buffer),
|
||||
}
|
||||
}
|
||||
|
|
@ -282,7 +297,7 @@ pub fn deleteBuffer(self: *Self, buffer: Handle(Buffer)) void {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn releaseBuffer(self: *Self, buffer: Handle(Buffer)) void {
|
||||
switch (self.ctx) {
|
||||
switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.releaseBuffer(buffer),
|
||||
}
|
||||
}
|
||||
|
|
@ -290,7 +305,7 @@ pub fn releaseBuffer(self: *Self, buffer: Handle(Buffer)) void {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn getRawBuffer(self: *Self, buffer: Handle(Buffer)) !RawBuffer {
|
||||
return switch (self.ctx) {
|
||||
return switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| .{ .vulkan = try v.getRawBuffer(buffer) },
|
||||
};
|
||||
}
|
||||
|
|
@ -301,9 +316,13 @@ pub fn getRawBuffer(self: *Self, buffer: Handle(Buffer)) !RawBuffer {
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn makeSurface(self: *Self) !Handle(Surface) {
|
||||
return try switch (self.ctx) {
|
||||
.vulkan => |*v| v.makeSurface(),
|
||||
pub fn makeSurface(
|
||||
self: *Self,
|
||||
window: Window,
|
||||
instance: Handle(Instance),
|
||||
) !Handle(Surface) {
|
||||
return try switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.makeSurface(instance, window),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -319,7 +338,7 @@ pub fn makeSwapchain(
|
|||
device: Handle(Device),
|
||||
surface: Handle(Surface),
|
||||
) !Handle(Swapchain) {
|
||||
return try switch (self.ctx) {
|
||||
return try switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.makeSwapchain(adapter, device, surface),
|
||||
};
|
||||
}
|
||||
|
|
@ -327,7 +346,7 @@ pub fn makeSwapchain(
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn getRawSwapchain(self: *Self, swapchain: Handle(Swapchain)) !*VKSwapchain {
|
||||
return switch (self.ctx) {
|
||||
return switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.getRawSwapchain(swapchain),
|
||||
};
|
||||
}
|
||||
|
|
@ -343,7 +362,7 @@ pub fn makeShader(
|
|||
spv_path: []const u8,
|
||||
device: Handle(Device),
|
||||
) !Handle(Shader) {
|
||||
return try switch (self.ctx) {
|
||||
return try switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.makeShader(spv_path, device),
|
||||
};
|
||||
}
|
||||
|
|
@ -351,7 +370,7 @@ pub fn makeShader(
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn deleteShader(self: *Self, shader: Handle(Shader)) void {
|
||||
switch (self.ctx) {
|
||||
switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.deleteShader(shader),
|
||||
}
|
||||
}
|
||||
|
|
@ -359,7 +378,7 @@ pub fn deleteShader(self: *Self, shader: Handle(Shader)) void {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn releaseShader(self: *Self, shader: Handle(Shader)) void {
|
||||
switch (self.ctx) {
|
||||
switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.releaseShader(shader),
|
||||
}
|
||||
}
|
||||
|
|
@ -367,7 +386,7 @@ pub fn releaseShader(self: *Self, shader: Handle(Shader)) void {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn getRawShader(self: *Self, shader: Handle(Shader)) !RawShader {
|
||||
return switch (self.ctx) {
|
||||
return switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| .{ .vulkan = try v.getRawShader(shader) },
|
||||
};
|
||||
}
|
||||
|
|
@ -379,7 +398,7 @@ pub fn getRawShader(self: *Self, shader: Handle(Shader)) !RawShader {
|
|||
/// ----------------------------------------------------
|
||||
pub fn makePipeline(self: *Self, config: PipelineConfig) !Pipeline {
|
||||
return .{
|
||||
.handle = try switch (self.ctx) {
|
||||
.handle = try switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.makePipeline(config),
|
||||
},
|
||||
.device = config.device,
|
||||
|
|
@ -390,7 +409,7 @@ pub fn makePipeline(self: *Self, config: PipelineConfig) !Pipeline {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn deletePipeline(self: *Self, pipeline: Handle(Pipeline)) void {
|
||||
switch (self.ctx) {
|
||||
switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.deletePipeline(pipeline),
|
||||
}
|
||||
}
|
||||
|
|
@ -398,7 +417,7 @@ pub fn deletePipeline(self: *Self, pipeline: Handle(Pipeline)) void {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn releasePipeline(self: *Self, pipeline: Handle(Pipeline)) void {
|
||||
switch (self.ctx) {
|
||||
switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.releasePipeline(pipeline),
|
||||
}
|
||||
}
|
||||
|
|
@ -406,18 +425,18 @@ pub fn releasePipeline(self: *Self, pipeline: Handle(Pipeline)) void {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn getRawPipeline(self: *Self, pipeline: Handle(Pipeline)) !RawPipeline {
|
||||
switch (self.ctx) {
|
||||
switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| {
|
||||
const raw_pipe = v.resource.pipelines.get(pipeline) orelse return error.PipelineNotFound;
|
||||
return .{
|
||||
.vulkan = .{
|
||||
.pipeline = raw_pipe.raw orelse return error.NullPipeline,
|
||||
.descriptor_pool = raw_pipe.descriptor_pool orelse return error.NullDescriptorPool,
|
||||
.pipeline = raw_pipe.raw,
|
||||
.descriptor_pool = raw_pipe.descriptor_pool,
|
||||
},
|
||||
};
|
||||
},
|
||||
}
|
||||
// return switch (self.ctx) {
|
||||
// return switch ((try self.getBackend()).*) {
|
||||
// .vulkan => |*v| .{ .vulkan = try v.getRawPipeline(pipeline) },
|
||||
// };
|
||||
}
|
||||
|
|
@ -434,7 +453,7 @@ pub fn makeImage(
|
|||
adapter: Handle(Adapter),
|
||||
device: Handle(Device),
|
||||
) !Handle(Image) {
|
||||
return try switch (self.ctx) {
|
||||
return try switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.makeImage(config, adapter, device),
|
||||
};
|
||||
}
|
||||
|
|
@ -446,7 +465,7 @@ pub fn makeSampler(
|
|||
config: SamplerConfig,
|
||||
device: Handle(Device),
|
||||
) !Handle(Sampler) {
|
||||
return try switch (self.ctx) {
|
||||
return try switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.makeSampler(config, device),
|
||||
};
|
||||
}
|
||||
|
|
@ -459,7 +478,7 @@ pub fn makeTexture(
|
|||
adapter: Handle(Adapter),
|
||||
device: Handle(Device),
|
||||
) !Handle(Texture) {
|
||||
return try switch (self.ctx) {
|
||||
return try switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.makeTexture(config, adapter, device),
|
||||
};
|
||||
}
|
||||
|
|
@ -475,7 +494,7 @@ pub fn beginFrame(
|
|||
swapchain: Handle(Swapchain),
|
||||
device: Handle(Device),
|
||||
) !void {
|
||||
try switch (self.ctx) {
|
||||
try switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.beginFrame(swapchain, device),
|
||||
};
|
||||
}
|
||||
|
|
@ -487,7 +506,7 @@ pub fn endFrame(
|
|||
swapchain: Handle(Swapchain),
|
||||
device: Handle(Device),
|
||||
) !void {
|
||||
try switch (self.ctx) {
|
||||
try switch ((try self.getBackend()).*) {
|
||||
.vulkan => |*v| v.endFrame(swapchain, device),
|
||||
};
|
||||
}
|
||||
|
|
@ -499,7 +518,7 @@ pub fn beginPass(
|
|||
swapchain: Handle(Swapchain),
|
||||
config: RenderPassConfig,
|
||||
) ?Pass {
|
||||
switch (self.ctx) {
|
||||
switch ((self.getBackend() catch return null).*) {
|
||||
.vulkan => |*v| v.beginPass(swapchain, config) catch return null,
|
||||
}
|
||||
|
||||
|
|
@ -508,3 +527,10 @@ pub fn beginPass(
|
|||
.gfx = self,
|
||||
};
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn getBackend(self: *Self) !*BackendCTX {
|
||||
if (self.ctx) |*ctx| return ctx;
|
||||
return error.BackendNotInitialized;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,12 +7,47 @@ const gtl = @import("gtl");
|
|||
const Gfx = @import("../gfx.zig");
|
||||
const Handle = gtl.Handle;
|
||||
|
||||
// TODO: Organize these into categories... someday
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const Backend = enum { vulkan };
|
||||
|
||||
pub const VKAPIVersion = enum {
|
||||
v1_0,
|
||||
v1_1,
|
||||
v1_2,
|
||||
v1_3,
|
||||
v1_4,
|
||||
};
|
||||
|
||||
pub const VK11Features = struct {
|
||||
shader_draw_parameters: bool = true,
|
||||
};
|
||||
|
||||
pub const VK13Features = struct {
|
||||
dynamic_rendering: bool = true,
|
||||
synchronization2: bool = true,
|
||||
};
|
||||
|
||||
pub const VK14Features = struct {
|
||||
dynamic_rendering_local_read: bool = true,
|
||||
};
|
||||
|
||||
pub const DeviceType = enum {
|
||||
discrete,
|
||||
integrated,
|
||||
software,
|
||||
};
|
||||
|
||||
pub const VKInstanceConfig = struct {
|
||||
api_version: VKAPIVersion = .v1_3,
|
||||
|
||||
vk_11_features: VK11Features = .{},
|
||||
vk_13_features: VK13Features = .{},
|
||||
vk_14_features: VK14Features = .{},
|
||||
};
|
||||
|
||||
pub const InstanceConfig = union(Backend) {
|
||||
vulkan: VKInstanceConfig,
|
||||
};
|
||||
|
||||
//
|
||||
// RAW
|
||||
//
|
||||
|
|
@ -67,7 +102,7 @@ pub const RawPipeline = union(Backend) {
|
|||
/// ----------------------------------------------------
|
||||
pub const AdapterInfo = struct {
|
||||
name: [256]u8,
|
||||
gpu_type: GPUType,
|
||||
gpu_type: DeviceType,
|
||||
|
||||
device_id: u32,
|
||||
vendor_id: u32,
|
||||
|
|
@ -97,24 +132,10 @@ pub const Window = union(enum) {
|
|||
},
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const GPUType = enum {
|
||||
any,
|
||||
discrete,
|
||||
integrated,
|
||||
software,
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const AdapterConfig = struct {
|
||||
/// Preferred class of GPU
|
||||
/// `.any` disables filtering by class
|
||||
gpu_type: GPUType = .discrete,
|
||||
|
||||
/// Select the adapter at a specific enumeration index
|
||||
/// `null` picks the first suitable one
|
||||
device_type: DeviceType = .discrete,
|
||||
index: ?u32 = null,
|
||||
};
|
||||
|
||||
|
|
@ -184,12 +205,25 @@ pub const DepthFormat = enum {
|
|||
d32_sfloat,
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// TODO: Mabe mabe use this for slang shader
|
||||
/// ----------------------------------------------------
|
||||
pub const ShaderDescriptor = struct {
|
||||
shaders: []const Handle(Shader),
|
||||
|
||||
vert_entry_point_name: ?[]const u8 = null,
|
||||
frag_entry_point_name: ?[]const u8 = null,
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const PipelineConfig = struct {
|
||||
vert_shader: Handle(Shader),
|
||||
frag_shader: Handle(Shader),
|
||||
|
||||
vert_entry_point_name: ?[]const u8 = null,
|
||||
frag_entry_point_name: ?[]const u8 = null,
|
||||
|
||||
swapchain: Handle(Swapchain),
|
||||
device: Handle(Device),
|
||||
|
||||
|
|
@ -236,7 +270,7 @@ pub const Pass = struct {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn end(self: *const Pass) void {
|
||||
switch (self.gfx.ctx) {
|
||||
switch ((self.gfx.getBackend() catch return).*) {
|
||||
.vulkan => |*v| v.endPass(self.swapchain),
|
||||
}
|
||||
}
|
||||
|
|
@ -244,7 +278,7 @@ pub const Pass = struct {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn draw(self: *const Pass, vertex_count: u32, instance_count: u32, first_vertex: u32, first_instance: u32) void {
|
||||
switch (self.gfx.ctx) {
|
||||
switch ((self.gfx.getBackend() catch return).*) {
|
||||
.vulkan => |*v| v.draw(vertex_count, instance_count, first_vertex, first_instance),
|
||||
}
|
||||
}
|
||||
|
|
@ -252,7 +286,7 @@ pub const Pass = struct {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn drawIndexed(self: *const Pass, index_count: u32, instance_count: u32, first_index: u32, vertex_offset: i32, first_instance: u32) void {
|
||||
switch (self.gfx.ctx) {
|
||||
switch ((self.gfx.getBackend() catch return).*) {
|
||||
.vulkan => |*v| v.drawIndexed(index_count, instance_count, first_index, vertex_offset, first_instance),
|
||||
}
|
||||
}
|
||||
|
|
@ -278,6 +312,9 @@ pub const StoreOp = enum {
|
|||
pub const RenderPassConfig = struct {
|
||||
clear_color: [4]f32 = .{ 0.0, 0.0, 0.0, 1.0 },
|
||||
|
||||
/// Optional texture to render into instead of the swapchain image
|
||||
render_target: ?Handle(Texture) = null,
|
||||
|
||||
depth_enabled: bool = false,
|
||||
depth_format: DepthFormat = .d32_sfloat,
|
||||
depth_load_op: LoadOp = .clear,
|
||||
|
|
@ -390,6 +427,7 @@ pub const TextureConfig = struct {
|
|||
// HANDLE TYPES
|
||||
//
|
||||
|
||||
pub const Instance = struct {};
|
||||
pub const Adapter = struct {};
|
||||
pub const Device = struct {};
|
||||
|
||||
|
|
@ -402,7 +440,7 @@ pub const Buffer = struct {
|
|||
gfx: *Gfx,
|
||||
|
||||
pub fn set(self: *const Buffer, value: anytype) !void {
|
||||
switch (self.gfx.ctx) {
|
||||
switch ((try self.gfx.getBackend()).*) {
|
||||
.vulkan => |*v| {
|
||||
const raw = v.resource.buffers.get(self.handle) orelse return error.BufferNotFound;
|
||||
try raw.set(value, @sizeOf(@TypeOf(value)));
|
||||
|
|
@ -411,7 +449,7 @@ pub const Buffer = struct {
|
|||
}
|
||||
|
||||
pub fn bind(self: *const Buffer) !void {
|
||||
switch (self.gfx.ctx) {
|
||||
switch ((try self.gfx.getBackend()).*) {
|
||||
.vulkan => |*v| try v.bindBuffer(self.handle),
|
||||
}
|
||||
}
|
||||
|
|
@ -431,13 +469,13 @@ pub const Pipeline = struct {
|
|||
gfx: *Gfx,
|
||||
|
||||
pub fn bind(self: *const Pipeline) !void {
|
||||
try switch (self.gfx.ctx) {
|
||||
try switch ((try self.gfx.getBackend()).*) {
|
||||
.vulkan => |*v| v.bindPipeline(self.handle),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn setUniform(self: *const Pipeline, name: []const u8, value: anytype) !void {
|
||||
try switch (self.gfx.ctx) {
|
||||
try switch ((try self.gfx.getBackend()).*) {
|
||||
.vulkan => |*v| v.setUniform(self.handle, name, value),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,12 @@ const vk = @import("vulkan");
|
|||
const std = @import("std");
|
||||
const gtl = @import("gtl");
|
||||
const common = @import("../common.zig");
|
||||
const Instance = @import("instance.zig");
|
||||
const Handle = gtl.Handle;
|
||||
const Self = @This();
|
||||
|
||||
const Instance = common.Instance;
|
||||
const VKInstance = @import("resource/instance.zig");
|
||||
|
||||
const Adapter = common.Adapter;
|
||||
const VKAdapter = @import("resource/adapter.zig");
|
||||
|
||||
|
|
@ -43,6 +46,8 @@ const VKTexture = @import("resource/texture.zig");
|
|||
// FIELDS
|
||||
//
|
||||
|
||||
instances: gtl.ResourceMap(Instance, VKInstance),
|
||||
|
||||
adapters: gtl.ResourceMap(Adapter, VKAdapter),
|
||||
devices: gtl.ResourceMap(Device, VKDevice),
|
||||
|
||||
|
|
@ -58,10 +63,14 @@ textures: gtl.ResourceMap(Texture, VKTexture),
|
|||
shaders: gtl.ResourceMap(Shader, VKShader),
|
||||
pipelines: gtl.ResourceMap(Pipeline, VKPipeline),
|
||||
|
||||
current_instance: ?Handle(Instance) = null,
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn init(alloc: std.mem.Allocator) Self {
|
||||
return .{
|
||||
.instances = .init(alloc),
|
||||
|
||||
.adapters = .init(alloc),
|
||||
.devices = .init(alloc),
|
||||
|
||||
|
|
@ -81,10 +90,7 @@ pub fn init(alloc: std.mem.Allocator) Self {
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn deinit(
|
||||
self: *Self,
|
||||
instance: *Instance,
|
||||
) void {
|
||||
pub fn deinit(self: *Self) void {
|
||||
{ // FREE SWAPCHAINS
|
||||
var it = self.swapchains.valueIterator();
|
||||
while (it.next()) |v| {
|
||||
|
|
@ -96,6 +102,7 @@ pub fn deinit(
|
|||
{ // FREE SURFACES
|
||||
var it = self.surfaces.valueIterator();
|
||||
while (it.next()) |v| {
|
||||
const instance = if (self.current_instance) |h| self.instances.get(h) orelse break else break;
|
||||
v.deinit(instance);
|
||||
}
|
||||
self.surfaces.deinit();
|
||||
|
|
@ -160,4 +167,12 @@ pub fn deinit(
|
|||
}
|
||||
self.devices.deinit();
|
||||
}
|
||||
|
||||
{ // FREE INSTANCES
|
||||
var it = self.instances.valueIterator();
|
||||
while (it.next()) |v| {
|
||||
v.deinit();
|
||||
}
|
||||
self.instances.deinit();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@ const vk = @import("vulkan");
|
|||
const common = @import("../../common.zig");
|
||||
const VKBackend = @import("../vulkan.zig");
|
||||
const AdapterConfig = common.AdapterConfig;
|
||||
const GPUType = common.GPUType;
|
||||
const DeviceType = common.DeviceType;
|
||||
const Self = @This();
|
||||
|
||||
const Instance = @import("instance.zig");
|
||||
|
||||
//
|
||||
// FIELDS
|
||||
//
|
||||
|
|
@ -19,49 +21,124 @@ raw: *vk.VkPhysicalDevice_T,
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn init(backend: *const VKBackend, config: AdapterConfig) !Self {
|
||||
var physical: vk.VkPhysicalDevice = null;
|
||||
pub fn init(
|
||||
config: AdapterConfig,
|
||||
instance: *const Instance,
|
||||
alloc: std.mem.Allocator,
|
||||
) !Self {
|
||||
// --- GET ADAPTER COUNT ---
|
||||
var count: u32 = 0;
|
||||
if (vk.vkEnumeratePhysicalDevices(instance.raw, &count, null) != vk.VK_SUCCESS) {}
|
||||
|
||||
// --- GET PHYSICAL DEVICES COUNT ---
|
||||
if (vk.vkEnumeratePhysicalDevices(backend.instance.raw, &count, null) != vk.VK_SUCCESS) {
|
||||
return error.FailedToEnumeratePhysicalDevices;
|
||||
}
|
||||
if (count == 0) {
|
||||
return error.FailedToFindGPUWithVKSupport;
|
||||
// --- CREATE LIST OF ADAPTERS ---
|
||||
const items = try alloc.alloc(vk.VkPhysicalDevice, count);
|
||||
defer alloc.free(items);
|
||||
|
||||
// --- POPULATE ADAPTERS LIST ---
|
||||
if (vk.vkEnumeratePhysicalDevices(instance.raw, &count, items.ptr) != vk.VK_SUCCESS) {}
|
||||
|
||||
// --- CHECK ADAPTER ---
|
||||
var raw: vk.VkPhysicalDevice = null;
|
||||
for (items) |adapter| {
|
||||
var props: vk.VkPhysicalDeviceProperties2 = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
|
||||
};
|
||||
|
||||
var features14: vk.VkPhysicalDeviceVulkan14Features = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_FEATURES,
|
||||
};
|
||||
|
||||
var features13: vk.VkPhysicalDeviceVulkan13Features = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
|
||||
.pNext = &features14,
|
||||
};
|
||||
|
||||
var features12: vk.VkPhysicalDeviceVulkan12Features = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
|
||||
.pNext = &features13,
|
||||
};
|
||||
|
||||
var features11: vk.VkPhysicalDeviceVulkan11Features = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES,
|
||||
.pNext = &features12,
|
||||
};
|
||||
|
||||
var features: vk.VkPhysicalDeviceFeatures2 = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
|
||||
.pNext = &features11,
|
||||
};
|
||||
|
||||
vk.vkGetPhysicalDeviceProperties2(adapter, &props);
|
||||
vk.vkGetPhysicalDeviceFeatures2(adapter, &features);
|
||||
|
||||
const api_version: u32 = switch (instance.api_version) {
|
||||
.v1_0 => vk.VK_API_VERSION_1_0,
|
||||
.v1_1 => vk.VK_API_VERSION_1_1,
|
||||
.v1_2 => vk.VK_API_VERSION_1_2,
|
||||
.v1_3 => vk.VK_API_VERSION_1_3,
|
||||
.v1_4 => vk.VK_API_VERSION_1_4,
|
||||
};
|
||||
|
||||
const adapter_type: DeviceType = switch (props.properties.deviceType) {
|
||||
vk.VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU => .discrete,
|
||||
vk.VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU => .integrated,
|
||||
vk.VK_PHYSICAL_DEVICE_TYPE_CPU => .software,
|
||||
else => return error.UnknownDeviceType,
|
||||
};
|
||||
|
||||
if (props.properties.apiVersion <= api_version) {
|
||||
gtl.log.warn("{s} does not support {s} Vulkan API!\n", .{
|
||||
props.properties.deviceName,
|
||||
@tagName(instance.api_version),
|
||||
}, null);
|
||||
continue;
|
||||
}
|
||||
|
||||
// --- # ---
|
||||
const devices = try backend.alloc.alloc(vk.VkPhysicalDevice, count);
|
||||
defer backend.alloc.free(devices);
|
||||
if (config.device_type != adapter_type) continue;
|
||||
|
||||
// --- GET PHYSICAL DEVICES ---
|
||||
if (vk.vkEnumeratePhysicalDevices(backend.instance.raw, &count, devices.ptr) != vk.VK_SUCCESS) {
|
||||
return error.FailedToEnumeratePhysicalDevices;
|
||||
if (instance.vk_11_features.shader_draw_parameters and features11.shaderDrawParameters != vk.VK_TRUE) {
|
||||
gtl.log.warn("{s} does not support {s} feature!\n", .{
|
||||
props.properties.deviceName,
|
||||
"shader_draw_parameters",
|
||||
}, null);
|
||||
continue;
|
||||
}
|
||||
|
||||
// --- CHECK WHICH DEVICE IS SUITABLE ---
|
||||
for (devices, 0..) |device, i| {
|
||||
if (config.index) |index| {
|
||||
if (index != i) continue;
|
||||
if (instance.vk_13_features.dynamic_rendering and features13.dynamicRendering != vk.VK_TRUE) {
|
||||
gtl.log.warn("{s} does not support {s} feature!\n", .{
|
||||
props.properties.deviceName,
|
||||
"dynamic_rendering",
|
||||
}, null);
|
||||
continue;
|
||||
}
|
||||
if (try isDeviceSuitable(device, config.gpu_type)) {
|
||||
physical = device;
|
||||
break;
|
||||
|
||||
if (instance.vk_13_features.synchronization2 and features13.synchronization2 != vk.VK_TRUE) {
|
||||
gtl.log.warn("{s} does not support {s} feature!\n", .{
|
||||
props.properties.deviceName,
|
||||
"synchronization2",
|
||||
}, null);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (instance.vk_14_features.dynamic_rendering_local_read and features14.dynamicRenderingLocalRead != vk.VK_TRUE) {
|
||||
gtl.log.warn("{s} does not support {s} feature!\n", .{
|
||||
props.properties.deviceName,
|
||||
"dynamic_rendering_local_read",
|
||||
}, null);
|
||||
continue;
|
||||
}
|
||||
if (physical == null) {
|
||||
return error.FailedToFindSuitableDevice;
|
||||
|
||||
raw = adapter;
|
||||
}
|
||||
|
||||
// --- FIND GFX QUEUE FAMILY ---
|
||||
var queue_family_index: u32 = 0;
|
||||
if (!try findGraphicsQueueFamily(physical, backend.alloc, &queue_family_index)) {
|
||||
if (!try findGraphicsQueueFamily(raw, alloc, &queue_family_index)) {
|
||||
return error.FailedToFindGraphicsQueueFamily;
|
||||
}
|
||||
|
||||
return .{
|
||||
.raw = physical.?,
|
||||
.raw = raw orelse return error.FailedToFindProperAdapter,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -89,22 +166,3 @@ fn findGraphicsQueueFamily(
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
fn isDeviceSuitable(device: vk.VkPhysicalDevice, gpu_type: GPUType) !bool {
|
||||
var properties: vk.VkPhysicalDeviceProperties = .{};
|
||||
vk.vkGetPhysicalDeviceProperties(device, &properties);
|
||||
|
||||
var features: vk.VkPhysicalDeviceFeatures = .{};
|
||||
vk.vkGetPhysicalDeviceFeatures(device, &features);
|
||||
|
||||
const matches_class = switch (gpu_type) {
|
||||
.any => true,
|
||||
.discrete => properties.deviceType == vk.VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
|
||||
.integrated => properties.deviceType == vk.VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
|
||||
.software => properties.deviceType == vk.VK_PHYSICAL_DEVICE_TYPE_CPU,
|
||||
};
|
||||
|
||||
return matches_class and features.geometryShader == 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@ pub const QueueFamilies = struct {
|
|||
// FIELDS
|
||||
//
|
||||
|
||||
raw: vk.VkDevice,
|
||||
physical_device: vk.VkPhysicalDevice,
|
||||
raw: *vk.VkDevice_T,
|
||||
physical_device: *vk.VkPhysicalDevice_T,
|
||||
graphics_queue: *vk.VkQueue_T,
|
||||
present_queue: *vk.VkQueue_T,
|
||||
graphics_command_pool: vk.VkCommandPool,
|
||||
graphics_command_pool: *vk.VkCommandPool_T,
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
|
|
@ -109,26 +109,19 @@ pub fn init(
|
|||
vk.vkGetDeviceQueue(device, queue_families.present.?, 0, &present_queue);
|
||||
|
||||
return .{
|
||||
.raw = device,
|
||||
.raw = device.?,
|
||||
.physical_device = adapter.raw,
|
||||
.graphics_queue = graphics_queue.?,
|
||||
.present_queue = present_queue.?,
|
||||
.graphics_command_pool = graphics_command_pool,
|
||||
.graphics_command_pool = graphics_command_pool.?,
|
||||
};
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn deinit(self: *Self) void {
|
||||
if (self.graphics_command_pool) |raw| {
|
||||
vk.vkDestroyCommandPool(self.raw, raw, null);
|
||||
self.graphics_command_pool = null;
|
||||
}
|
||||
|
||||
if (self.raw) |raw| {
|
||||
vk.vkDestroyDevice(raw, null);
|
||||
self.raw = null;
|
||||
}
|
||||
vk.vkDestroyCommandPool(self.raw, self.graphics_command_pool, null);
|
||||
vk.vkDestroyDevice(self.raw, null);
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -44,10 +44,13 @@ pub fn init(
|
|||
errdefer self.deinit();
|
||||
|
||||
// --- DECODE PIXELS ---
|
||||
var pixels: ?[]const u8 = null;
|
||||
var loaded: ?[*]u8 = null;
|
||||
var pixels: []const u8 = undefined;
|
||||
var tex_size: [2]i32 = .{ 0, 0 };
|
||||
|
||||
const needs_pixels = config.usage == .texture;
|
||||
|
||||
if (needs_pixels) {
|
||||
if (config.path) |path| {
|
||||
var tex_channel: i32 = 0;
|
||||
stb.stbi_set_flip_vertically_on_load(@intFromBool(config.vertical_flip));
|
||||
|
|
@ -61,13 +64,18 @@ pub fn init(
|
|||
} else {
|
||||
return error.MissingImageSource;
|
||||
}
|
||||
}
|
||||
defer if (loaded) |data| stb.stbi_image_free(data);
|
||||
|
||||
// --- SIZE ---
|
||||
const size: [2]u32 = blk: {
|
||||
if (needs_pixels) {
|
||||
if (config.path) |_| break :blk .{ @intCast(tex_size[0]), @intCast(tex_size[1]) };
|
||||
if (config.size) |size| break :blk size;
|
||||
return error.SizeRequired;
|
||||
}
|
||||
if (config.size) |size| break :blk size;
|
||||
return error.SizeRequired;
|
||||
};
|
||||
|
||||
self.width = size[0];
|
||||
|
|
@ -132,7 +140,9 @@ pub fn init(
|
|||
_ = vk.vkBindImageMemory(device.raw, self.raw, self.memory, 0);
|
||||
|
||||
// --- UPLOAD ---
|
||||
try uploadPixels(&self, pixels);
|
||||
if (needs_pixels) {
|
||||
try uploadPixels(&self, pixels.?);
|
||||
}
|
||||
|
||||
// --- DEFAULT IMAGE VIEW ---
|
||||
var view_create_info: vk.VkImageViewCreateInfo = .{
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
//! `🗲` Vulkan Instance `🗲`
|
||||
//! ----------------------------------------------------
|
||||
|
||||
const std = @import("std");
|
||||
const gtl = @import("gtl");
|
||||
const vk = @import("vulkan");
|
||||
const Resource = @import("resource.zig");
|
||||
const Window = @import("../common.zig").Window;
|
||||
const MainConfig = @import("../../gfx.zig").Config;
|
||||
const std = @import("std");
|
||||
const cmn = @import("../../common.zig");
|
||||
const gtl = @import("gtl");
|
||||
const Self = @This();
|
||||
|
||||
const Window = cmn.Window;
|
||||
|
||||
//
|
||||
// FIELDS
|
||||
//
|
||||
|
|
@ -18,26 +18,39 @@ raw: *vk.VkInstance_T,
|
|||
messenger: ?vk.VkDebugUtilsMessengerEXT = null,
|
||||
pfn_destroy_debug_utils_messenger: vk.PFN_vkDestroyDebugUtilsMessengerEXT = null,
|
||||
|
||||
api_version: cmn.VKAPIVersion,
|
||||
vk_11_features: cmn.VK11Features,
|
||||
vk_13_features: cmn.VK13Features,
|
||||
vk_14_features: cmn.VK14Features,
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn init(
|
||||
config: MainConfig,
|
||||
alloc: std.mem.Allocator,
|
||||
) !Self {
|
||||
pub fn init(config: cmn.VKInstanceConfig, alloc: std.mem.Allocator) !Self {
|
||||
const validation_layers: []const [*:0]const u8 = &.{
|
||||
"VK_LAYER_KHRONOS_validation",
|
||||
};
|
||||
|
||||
const extensions = getWindowExtensions(
|
||||
config.window,
|
||||
config.enable_validation,
|
||||
);
|
||||
const extensions: []const [*:0]const u8 = &.{
|
||||
"VK_KHR_surface", "VK_KHR_xlib_surface", "VK_EXT_debug_utils",
|
||||
};
|
||||
|
||||
// const extensions = getWindowExtensions(
|
||||
// config.window,
|
||||
// config.enable_validation,
|
||||
// );
|
||||
|
||||
var app_info: vk.VkApplicationInfo = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||
.pApplicationName = config.app_name.ptr,
|
||||
.pEngineName = config.engine_name.ptr,
|
||||
.apiVersion = vk.VK_API_VERSION_1_3,
|
||||
// TODO:
|
||||
// .pApplicationName = config.app_name.ptr,
|
||||
// .pEngineName = config.engine_name.ptr,
|
||||
.apiVersion = switch (config.api_version) {
|
||||
.v1_0 => vk.VK_API_VERSION_1_0,
|
||||
.v1_1 => vk.VK_API_VERSION_1_1,
|
||||
.v1_2 => vk.VK_API_VERSION_1_2,
|
||||
.v1_3 => vk.VK_API_VERSION_1_3,
|
||||
.v1_4 => vk.VK_API_VERSION_1_4,
|
||||
},
|
||||
};
|
||||
|
||||
var messenger_info: vk.VkDebugUtilsMessengerCreateInfoEXT = undefined;
|
||||
|
|
@ -49,7 +62,7 @@ pub fn init(
|
|||
.ppEnabledExtensionNames = extensions.ptr,
|
||||
};
|
||||
|
||||
if (config.enable_validation) {
|
||||
// if (config.enable_validation) {
|
||||
if (!try checkValidationLayerSupport(validation_layers, alloc)) {
|
||||
return error.ValidationLayerNotAvailable;
|
||||
}
|
||||
|
|
@ -59,7 +72,7 @@ pub fn init(
|
|||
|
||||
messenger_info = makeMessengerInfo();
|
||||
create_info.pNext = &messenger_info;
|
||||
}
|
||||
// }
|
||||
|
||||
var instance: vk.VkInstance = null;
|
||||
if (vk.vkCreateInstance(&create_info, null, &instance) != vk.VK_SUCCESS) {
|
||||
|
|
@ -69,7 +82,7 @@ pub fn init(
|
|||
|
||||
var messenger: vk.VkDebugUtilsMessengerEXT = null;
|
||||
var pfn_destroy: vk.PFN_vkDestroyDebugUtilsMessengerEXT = null;
|
||||
if (config.enable_validation) {
|
||||
// if (config.enable_validation) {
|
||||
const pfn_create: vk.PFN_vkCreateDebugUtilsMessengerEXT = @ptrCast(
|
||||
vk.vkGetInstanceProcAddr(instance.?, "vkCreateDebugUtilsMessengerEXT"),
|
||||
);
|
||||
|
|
@ -80,12 +93,17 @@ pub fn init(
|
|||
if (pfn_create.?(instance.?, &messenger_info, null, &messenger) != vk.VK_SUCCESS) {
|
||||
return error.FailedToCreateDebugUtilsMessenger;
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
return .{
|
||||
.raw = instance.?,
|
||||
.messenger = messenger,
|
||||
.pfn_destroy_debug_utils_messenger = pfn_destroy,
|
||||
|
||||
.api_version = config.api_version,
|
||||
.vk_11_features = config.vk_11_features,
|
||||
.vk_13_features = config.vk_13_features,
|
||||
.vk_14_features = config.vk_14_features,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -23,8 +23,8 @@ const MAX_WRITES = MAX_BINDINGS;
|
|||
// FIELDS
|
||||
//
|
||||
|
||||
raw: vk.VkPipeline = null,
|
||||
layout: vk.VkPipelineLayout = null,
|
||||
raw: *vk.VkPipeline_T,
|
||||
layout: *vk.VkPipelineLayout_T,
|
||||
device: *const Device,
|
||||
|
||||
descriptor_set_layout: vk.VkDescriptorSetLayout = null,
|
||||
|
|
@ -50,6 +50,9 @@ pub fn init(
|
|||
alloc: std.mem.Allocator,
|
||||
) !Self {
|
||||
var self: Self = .{
|
||||
.raw = undefined,
|
||||
.layout = undefined,
|
||||
|
||||
.device = device,
|
||||
.uniforms = &.{},
|
||||
.uniform_offsets = &.{},
|
||||
|
|
@ -59,10 +62,6 @@ pub fn init(
|
|||
errdefer self.deinit();
|
||||
|
||||
// --- COMPUTE UNIFORM LAYOUT ---
|
||||
// Each uniform block gets its own descriptor binding. Blocks are packed
|
||||
// into a single per-frame buffer, each at a `minUniformBufferOffsetAlignment`
|
||||
// aligned offset so the same layout maps to `glBindBufferRange` (GL) and
|
||||
// CBV offsets (D3D12) unchanged.
|
||||
var uniform_size: u32 = 0;
|
||||
if (config.uniforms.len > 0) {
|
||||
var props: vk.VkPhysicalDeviceProperties = .{};
|
||||
|
|
@ -158,7 +157,7 @@ pub fn init(
|
|||
.sType = vk.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.stage = vk.VK_SHADER_STAGE_VERTEX_BIT,
|
||||
|
||||
.pName = "main",
|
||||
.pName = if (config.vert_entry_point_name) |v| v.ptr else "main",
|
||||
.module = raw_vert_shader.raw,
|
||||
};
|
||||
|
||||
|
|
@ -166,7 +165,7 @@ pub fn init(
|
|||
.sType = vk.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.stage = vk.VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
|
||||
.pName = "main",
|
||||
.pName = if (config.frag_entry_point_name) |v| v.ptr else "main",
|
||||
.module = raw_frag_shader.raw,
|
||||
};
|
||||
|
||||
|
|
@ -545,12 +544,10 @@ pub fn deinit(self: *Self) void {
|
|||
vk.vkDestroyBuffer(self.device.raw, b, null);
|
||||
}
|
||||
}
|
||||
if (self.layout) |layout| {
|
||||
vk.vkDestroyPipelineLayout(self.device.raw, layout, null);
|
||||
}
|
||||
if (self.raw) |raw| {
|
||||
vk.vkDestroyPipeline(self.device.raw, raw, null);
|
||||
}
|
||||
|
||||
vk.vkDestroyPipelineLayout(self.device.raw, self.layout, null);
|
||||
vk.vkDestroyPipeline(self.device.raw, self.raw, null);
|
||||
|
||||
self.alloc.free(self.uniforms);
|
||||
self.alloc.free(self.uniform_offsets);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ const Self = @This();
|
|||
// FIELDS
|
||||
//
|
||||
|
||||
raw: vk.VkShaderModule,
|
||||
raw: *vk.VkShaderModule_T,
|
||||
device: *const Device,
|
||||
|
||||
/// ----------------------------------------------------
|
||||
|
|
@ -40,10 +40,7 @@ pub fn init(
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn deinit(self: *Self) void {
|
||||
if (self.raw) |raw| {
|
||||
vk.vkDestroyShaderModule(self.device.raw, raw, null);
|
||||
self.raw = null;
|
||||
}
|
||||
vk.vkDestroyShaderModule(self.device.raw, self.raw, null);
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@
|
|||
|
||||
const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
const Instance = @import("../instance.zig");
|
||||
const Window = @import("../../common.zig").Window;
|
||||
const Self = @This();
|
||||
|
||||
const Instance = @import("instance.zig");
|
||||
|
||||
//
|
||||
// FIELDS
|
||||
//
|
||||
|
|
@ -17,7 +18,7 @@ raw: *vk.VkSurfaceKHR_T,
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn init(
|
||||
instance: *Instance,
|
||||
instance: *const Instance,
|
||||
window: Window,
|
||||
) !Self {
|
||||
const surface: *vk.VkSurfaceKHR_T = blk: {
|
||||
|
|
@ -48,6 +49,6 @@ pub fn init(
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn deinit(self: *Self, instance: *Instance) void {
|
||||
pub fn deinit(self: *Self, instance: *const Instance) void {
|
||||
vk.vkDestroySurfaceKHR(instance.raw, self.raw, null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,12 +27,15 @@ pub fn init(
|
|||
adapter: *const Adapter,
|
||||
device: *const Device,
|
||||
) !Self {
|
||||
var image = try VKImage.init(config.image, adapter, device);
|
||||
var image: VKImage = try .init(config.image, adapter, device);
|
||||
errdefer image.deinit();
|
||||
|
||||
var sampler: VKSampler = try .init(config.sampler, device);
|
||||
errdefer sampler.deinit();
|
||||
|
||||
return .{
|
||||
.image = image,
|
||||
.sampler = try VKSampler.init(config.sampler, device),
|
||||
.sampler = sampler,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//! ----------------------------------------------------
|
||||
//! `🗲` Vulkan RHI `🗲`
|
||||
//! `🗲` Vulkan RHI 1.4 `🗲`
|
||||
//! 😭 Send Help 😭
|
||||
//! ----------------------------------------------------
|
||||
|
||||
|
|
@ -8,9 +8,9 @@ const vk = @import("vulkan");
|
|||
const gtl = @import("gtl");
|
||||
const common = @import("../common.zig");
|
||||
|
||||
const Instance = @import("instance.zig");
|
||||
const Resource = @import("resource.zig");
|
||||
const SwapchainResource = @import("resource/swapchain.zig");
|
||||
const VKImage = @import("resource/image.zig");
|
||||
|
||||
const MainConfig = @import("../../gfx.zig").Config;
|
||||
const Handle = gtl.Handle;
|
||||
|
|
@ -49,16 +49,6 @@ const AdapterInfo = common.AdapterInfo;
|
|||
// --- # ---
|
||||
pub const MAX_FRAMES_IN_FLIGHT: usize = 3;
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn depthFormatToVk(format: common.DepthFormat) vk.VkFormat {
|
||||
return switch (format) {
|
||||
.d16_unorm => vk.VK_FORMAT_D16_UNORM,
|
||||
.d24_unorm_s8 => vk.VK_FORMAT_D24_UNORM_S8_UINT,
|
||||
.d32_sfloat => vk.VK_FORMAT_D32_SFLOAT,
|
||||
};
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
const Frame = struct {
|
||||
|
|
@ -74,13 +64,13 @@ const Frame = struct {
|
|||
// FIELDS
|
||||
//
|
||||
|
||||
instance: Instance,
|
||||
resource: Resource,
|
||||
config: MainConfig,
|
||||
|
||||
frames: [MAX_FRAMES_IN_FLIGHT]Frame = .{ .{}, .{}, .{} },
|
||||
current_frame: usize = 0,
|
||||
|
||||
active_pass_target: ?Handle(Texture) = null,
|
||||
|
||||
render_finished: []vk.VkSemaphore = &.{},
|
||||
|
||||
sync_device: ?*vk.VkDevice_T = null,
|
||||
|
|
@ -94,19 +84,9 @@ io: std.Io,
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn init(
|
||||
config: MainConfig,
|
||||
alloc: std.mem.Allocator,
|
||||
io: std.Io,
|
||||
) !Self {
|
||||
// --- INSTANCE ---
|
||||
var instance: Instance = try .init(config, alloc);
|
||||
errdefer instance.deinit();
|
||||
|
||||
pub fn init(alloc: std.mem.Allocator, io: std.Io) Self {
|
||||
return .{
|
||||
.instance = instance,
|
||||
.resource = .init(alloc),
|
||||
.config = config,
|
||||
.alloc = alloc,
|
||||
.io = io,
|
||||
};
|
||||
|
|
@ -133,8 +113,36 @@ pub fn deinit(self: *Self) void {
|
|||
}
|
||||
}
|
||||
|
||||
self.resource.deinit(&self.instance);
|
||||
self.instance.deinit();
|
||||
self.resource.deinit();
|
||||
}
|
||||
|
||||
//
|
||||
// INSTANCE
|
||||
//
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn makeInstance(self: *Self, config: common.VKInstanceConfig) !Handle(common.Instance) {
|
||||
const h = try self.resource.instances.put(try .init(config, self.alloc));
|
||||
self.resource.current_instance = h;
|
||||
return h;
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn deleteInstance(self: *Self, instance: Handle(common.Instance)) void {
|
||||
if (self.resource.instances.get(instance)) |_| {
|
||||
self.resource.instances.remove(instance) catch unreachable;
|
||||
self.resource.current_instance = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn releaseInstance(self: *Self, instance: Handle(common.Instance)) void {
|
||||
if (self.resource.instances.get(instance)) |v| {
|
||||
v.deinit();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -143,8 +151,9 @@ pub fn deinit(self: *Self) void {
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn makeAdapter(self: *Self, config: AdapterConfig) !Handle(Adapter) {
|
||||
return try self.resource.adapters.put(try .init(self, config));
|
||||
pub fn makeAdapter(self: *Self, config: AdapterConfig, instance: Handle(common.Instance)) !Handle(Adapter) {
|
||||
const raw_instance = self.resource.instances.get(instance) orelse return error.InstanceNotFound;
|
||||
return try self.resource.adapters.put(try .init(config, raw_instance, self.alloc));
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
|
|
@ -175,7 +184,7 @@ pub fn getAdapterInfo(self: *Self, adapter: Handle(Adapter)) ?AdapterInfo {
|
|||
vk.VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU => .discrete,
|
||||
vk.VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU => .integrated,
|
||||
vk.VK_PHYSICAL_DEVICE_TYPE_CPU => .software,
|
||||
else => .any,
|
||||
else => .discrete,
|
||||
},
|
||||
.device_id = props.deviceID,
|
||||
.vendor_id = props.vendorID,
|
||||
|
|
@ -225,7 +234,7 @@ pub fn releaseDevice(self: *Self, device: Handle(Device)) void {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn getRawDevice(self: *Self, device: Handle(Device)) !*vk.VkDevice_T {
|
||||
if (self.resource.devices.get(device)) |raw| return raw.raw orelse return error.NullDevice;
|
||||
if (self.resource.devices.get(device)) |raw| return raw.raw;
|
||||
return error.DeviceNotFound;
|
||||
}
|
||||
|
||||
|
|
@ -235,8 +244,13 @@ pub fn getRawDevice(self: *Self, device: Handle(Device)) !*vk.VkDevice_T {
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn makeSurface(self: *Self) !Handle(Surface) {
|
||||
return try self.resource.surfaces.put(try .init(&self.instance, self.config.window));
|
||||
pub fn makeSurface(
|
||||
self: *Self,
|
||||
instance: Handle(common.Instance),
|
||||
window: Window,
|
||||
) !Handle(Surface) {
|
||||
const raw_instance = self.resource.instances.get(instance) orelse return error.InstanceNotFound;
|
||||
return try self.resource.surfaces.put(try .init(raw_instance, window));
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -305,7 +319,7 @@ pub fn releaseShader(self: *Self, shader: Handle(Shader)) void {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn getRawShader(self: *Self, shader: Handle(Shader)) !*vk.VkShaderModule_T {
|
||||
if (self.resource.shaders.get(shader)) |raw| return raw.raw orelse return error.NullShader;
|
||||
if (self.resource.shaders.get(shader)) |raw| return raw.raw;
|
||||
return error.ShaderNotFound;
|
||||
}
|
||||
|
||||
|
|
@ -341,7 +355,7 @@ pub fn releasePipeline(self: *Self, pipeline: Handle(Pipeline)) void {
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn getRawPipeline(self: *Self, pipeline: Handle(Pipeline)) !*vk.VkPipeline_T {
|
||||
if (self.resource.pipelines.get(pipeline)) |raw| return raw.raw orelse return error.NullPipeline;
|
||||
if (self.resource.pipelines.get(pipeline)) |raw| return raw.raw;
|
||||
return error.PipelineNotFound;
|
||||
}
|
||||
|
||||
|
|
@ -438,7 +452,7 @@ pub fn bindBuffer(self: *Self, buffer: Handle(Buffer)) !void {
|
|||
switch (raw.usage) {
|
||||
.vertex => vk.vkCmdBindVertexBuffers(cmd, 0, 1, &buffers, &offsets),
|
||||
.index => vk.vkCmdBindIndexBuffer(cmd, raw.raw, 0, vk.VK_INDEX_TYPE_UINT32),
|
||||
.image => {}, // TODO:
|
||||
.image => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -457,7 +471,10 @@ pub fn beginFrame(
|
|||
const raw_device = self.resource.devices.get(device) orelse return error.DeviceNotFound;
|
||||
const raw_swapchain = self.resource.swapchains.get(swapchain) orelse return error.SwapchainNotFound;
|
||||
|
||||
try self.ensureFrameSync(raw_device.raw.?, raw_swapchain.raw);
|
||||
try self.ensureFrameSync(
|
||||
raw_device.raw,
|
||||
raw_swapchain.raw,
|
||||
);
|
||||
|
||||
const frame = self.currentFrame();
|
||||
|
||||
|
|
@ -583,9 +600,17 @@ pub fn beginPass(
|
|||
|
||||
const frame = self.currentFrame();
|
||||
|
||||
// --- RENDER TO OFFSCREEN TARGET INSTEAD OF THE SWAPCHAIN ---
|
||||
const target_image: ?*VKImage = if (config.render_target) |target| blk: {
|
||||
const raw_texture = self.resource.textures.get(target) orelse return error.TextureNotFound;
|
||||
break :blk &raw_texture.image;
|
||||
} else null;
|
||||
|
||||
self.active_pass_target = config.render_target;
|
||||
|
||||
const extent: vk.VkExtent2D = .{
|
||||
.width = config.width orelse raw_swapchain.extent.width,
|
||||
.height = config.height orelse raw_swapchain.extent.height,
|
||||
.width = config.width orelse if (target_image) |img| img.width else raw_swapchain.extent.width,
|
||||
.height = config.height orelse if (target_image) |img| img.height else raw_swapchain.extent.height,
|
||||
};
|
||||
|
||||
const barrier: vk.VkImageMemoryBarrier = .{
|
||||
|
|
@ -600,7 +625,7 @@ pub fn beginPass(
|
|||
.srcQueueFamilyIndex = vk.VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = vk.VK_QUEUE_FAMILY_IGNORED,
|
||||
|
||||
.image = raw_swapchain.images[frame.image_index],
|
||||
.image = if (target_image) |img| img.raw else raw_swapchain.images[frame.image_index],
|
||||
|
||||
.subresourceRange = .{
|
||||
.aspectMask = vk.VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -704,7 +729,7 @@ pub fn beginPass(
|
|||
|
||||
const color_attachment: vk.VkRenderingAttachmentInfo = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||
.imageView = raw_swapchain.image_views[frame.image_index],
|
||||
.imageView = if (target_image) |img| img.raw_view else raw_swapchain.image_views[frame.image_index],
|
||||
.imageLayout = vk.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.loadOp = switch (config.load_op) {
|
||||
.clear => vk.VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
|
|
@ -777,6 +802,100 @@ pub fn endPass(
|
|||
|
||||
vk.vkCmdEndRendering(frame.cmd_buf);
|
||||
|
||||
const target = self.active_pass_target;
|
||||
self.active_pass_target = null;
|
||||
|
||||
if (target) |t| {
|
||||
// --- TARGET ---
|
||||
const raw_texture = self.resource.textures.get(t) orelse return;
|
||||
|
||||
const target_barrier: vk.VkImageMemoryBarrier = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
|
||||
.srcAccessMask = vk.VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
.dstAccessMask = vk.VK_ACCESS_SHADER_READ_BIT,
|
||||
|
||||
.oldLayout = vk.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.newLayout = vk.VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
|
||||
.srcQueueFamilyIndex = vk.VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = vk.VK_QUEUE_FAMILY_IGNORED,
|
||||
|
||||
.image = raw_texture.image.raw,
|
||||
|
||||
.subresourceRange = .{
|
||||
.aspectMask = vk.VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
};
|
||||
|
||||
vk.vkCmdPipelineBarrier(
|
||||
frame.cmd_buf,
|
||||
|
||||
vk.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
vk.VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
|
||||
0,
|
||||
|
||||
0,
|
||||
null,
|
||||
|
||||
0,
|
||||
null,
|
||||
|
||||
1,
|
||||
&target_barrier,
|
||||
);
|
||||
|
||||
// --- SWAPCHAIN ---
|
||||
const swapchain_barrier: vk.VkImageMemoryBarrier = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
|
||||
.srcAccessMask = 0,
|
||||
.dstAccessMask = 0,
|
||||
|
||||
.oldLayout = vk.VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = vk.VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
|
||||
.srcQueueFamilyIndex = vk.VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = vk.VK_QUEUE_FAMILY_IGNORED,
|
||||
|
||||
.image = raw_swapchain.images[frame.image_index],
|
||||
|
||||
.subresourceRange = .{
|
||||
.aspectMask = vk.VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
};
|
||||
|
||||
vk.vkCmdPipelineBarrier(
|
||||
frame.cmd_buf,
|
||||
|
||||
vk.VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
vk.VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
|
||||
0,
|
||||
|
||||
0,
|
||||
null,
|
||||
|
||||
0,
|
||||
null,
|
||||
|
||||
1,
|
||||
&swapchain_barrier,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// --- SWAPCHAIN ONLY ---
|
||||
const barrier: vk.VkImageMemoryBarrier = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
|
||||
|
|
@ -824,12 +943,12 @@ pub fn endPass(
|
|||
pub fn bindPipeline(self: *Self, pipeline: Handle(Pipeline)) !void {
|
||||
const raw_pipeline = self.resource.pipelines.get(pipeline) orelse return error.PipelineNotFound;
|
||||
const frame = self.currentFrame();
|
||||
vk.vkCmdBindPipeline(frame.cmd_buf, vk.VK_PIPELINE_BIND_POINT_GRAPHICS, raw_pipeline.raw.?);
|
||||
vk.vkCmdBindPipeline(frame.cmd_buf, vk.VK_PIPELINE_BIND_POINT_GRAPHICS, raw_pipeline.raw);
|
||||
if (raw_pipeline.descriptor_sets[self.current_frame]) |set| {
|
||||
vk.vkCmdBindDescriptorSets(
|
||||
frame.cmd_buf,
|
||||
vk.VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
raw_pipeline.layout.?,
|
||||
raw_pipeline.layout,
|
||||
0,
|
||||
1,
|
||||
&set,
|
||||
|
|
@ -921,3 +1040,14 @@ fn ensureFrameSync(
|
|||
frame.fence = fence.?;
|
||||
}
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// TODO: Create vk helper
|
||||
/// ----------------------------------------------------
|
||||
pub fn depthFormatToVk(format: common.DepthFormat) vk.VkFormat {
|
||||
return switch (format) {
|
||||
.d16_unorm => vk.VK_FORMAT_D16_UNORM,
|
||||
.d24_unorm_s8 => vk.VK_FORMAT_D24_UNORM_S8_UINT,
|
||||
.d32_sfloat => vk.VK_FORMAT_D32_SFLOAT,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
53
tools/shaders.bash
Executable file
53
tools/shaders.bash
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
#!/bin/bash
|
||||
|
||||
clear
|
||||
|
||||
# --- GET ARGS ---
|
||||
while getopts "i:o:" opt; do
|
||||
case $opt in
|
||||
i)
|
||||
input="$OPTARG"
|
||||
;;
|
||||
o)
|
||||
output="$OPTARG"
|
||||
;;
|
||||
*)
|
||||
echo "[USAGE] $0 -i <input_path> -o <output_path>"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# --- CHECK INPUT ---
|
||||
if [[ -z "$input" ]]; then
|
||||
echo -e "\x1b[31m[ERROR]\x1b[0m input path is required."
|
||||
echo -e "\x1b[33m[USAGE]\x1b[0m $0 -i <input_path> -o <output_path>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- CHECK OUTPUT ---
|
||||
if [[ -z "$output" ]]; then
|
||||
echo -e "\x1b[31m[ERROR]\x1b[0m output path is required."
|
||||
echo -e "\x1b[33m[USAGE]\x1b[0m $0 -i <input_path> -o <output_path>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- ENSURE OUTPUT PATH ---
|
||||
mkdir -p "$output"
|
||||
|
||||
# --- COMPILE EACH FILE IN INPUT ---
|
||||
for file in "$input"/*; do
|
||||
if [[ ! -f "$file" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
filename=$(basename "$file")
|
||||
output_file="$output/$filename.spv"
|
||||
|
||||
if [[ ! -f "$output_file" || "$file" -nt "$output_file" ]]; then
|
||||
echo -e "\x1b[32m[COMPILING]\x1b[0m $filename"
|
||||
glslc "$file" -o "$output_file"
|
||||
else
|
||||
echo -e "\x1b[90m[SKIPPING]\x1b[0m $filename"
|
||||
fi
|
||||
done
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn main(init: std.process.Init) !void {
|
||||
_ = init;
|
||||
}
|
||||
BIN
zig-out/bin/3D
Executable file
BIN
zig-out/bin/3D
Executable file
Binary file not shown.
BIN
zig-out/bin/imgui
Executable file
BIN
zig-out/bin/imgui
Executable file
Binary file not shown.
Binary file not shown.
Loading…
Add table
Reference in a new issue