Uniforms
This commit is contained in:
parent
3f8b5617e0
commit
ce1b032361
17 changed files with 538 additions and 176 deletions
19
README.md
19
README.md
|
|
@ -11,5 +11,22 @@ Low cortisol crossplatform RHI (Rendering Hardware Interface)
|
|||
- Dead simple + Performance + Flexible
|
||||
- Handles
|
||||
|
||||
# Examples
|
||||
## Architecture
|
||||
```text
|
||||
examples/simple/simple.zig
|
||||
|
||||
src/gfx.zig
|
||||
└─ Selected Backend
|
||||
|
||||
src/rhi/root.zig
|
||||
└─ Common / Handles / Configs
|
||||
|
||||
src/rhi/vulkan/vulkan.zig
|
||||
└─ Vulkan Backend / RHI
|
||||
|
||||
src/rhi/vulkan/resource.zig
|
||||
└─ Adapter / Device / Shader
|
||||
```
|
||||
|
||||
## Examples
|
||||
- ```zig build run-simple```
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -1,7 +0,0 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
void main() {
|
||||
outColor = vec4(0.2, 0.2, 0.8, 1.0);
|
||||
}
|
||||
BIN
examples/assets/shaders/compiled/simple.frag.spv
Normal file
BIN
examples/assets/shaders/compiled/simple.frag.spv
Normal file
Binary file not shown.
BIN
examples/assets/shaders/compiled/simple.vert.spv
Normal file
BIN
examples/assets/shaders/compiled/simple.vert.spv
Normal file
Binary file not shown.
11
examples/assets/shaders/simple.frag
Normal file
11
examples/assets/shaders/simple.frag
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#version 450
|
||||
|
||||
layout(binding = 0) uniform UnlitMaterial {
|
||||
vec4 albedo;
|
||||
} material;
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
void main() {
|
||||
outColor = material.albedo;
|
||||
}
|
||||
|
|
@ -1,5 +1,9 @@
|
|||
#version 450
|
||||
|
||||
layout(binding = 0) uniform UnlitMaterial {
|
||||
vec4 albedo;
|
||||
} material;
|
||||
|
||||
layout(location = 0) in vec2 inPosition;
|
||||
layout(location = 1) in vec2 inNormal;
|
||||
layout(location = 2) in vec2 inUV;
|
||||
|
|
@ -5,6 +5,12 @@ const std = @import("std");
|
|||
const sdl = @import("sdl");
|
||||
const Gfx = @import("gfx");
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
const UnlitMaterial = struct {
|
||||
albedo: [4]f32 = .{ 1, 1, 1, 1 },
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
const Vertex = struct {
|
||||
|
|
@ -33,6 +39,12 @@ const indices = [_]u32{
|
|||
/// ----------------------------------------------------
|
||||
pub fn main(init: std.process.Init) !void {
|
||||
|
||||
//
|
||||
// DATA
|
||||
//
|
||||
|
||||
var material: UnlitMaterial = .{ .albedo = .{ 1.0, 0.2, 0.2, 1.0 } };
|
||||
|
||||
//
|
||||
// SDL
|
||||
//
|
||||
|
|
@ -42,7 +54,7 @@ pub fn main(init: std.process.Init) !void {
|
|||
defer sdl.SDL_Quit();
|
||||
|
||||
// --- # ---
|
||||
const window = sdl.SDL_CreateWindow("NYXGFX", 800, 600, 0) orelse return error.FailedToCreateWindow;
|
||||
const window = sdl.SDL_CreateWindow("NYXGFX", 800, 600, 0) orelse return error.FailedTomakeWindow;
|
||||
defer sdl.SDL_DestroyWindow(window);
|
||||
|
||||
// --- # ---
|
||||
|
|
@ -66,23 +78,21 @@ pub fn main(init: std.process.Init) !void {
|
|||
defer gfx.deinit();
|
||||
|
||||
// --- # ---
|
||||
const adapter = try gfx.createAdapter();
|
||||
const surface = try gfx.createSurface();
|
||||
const device = try gfx.createDevice(adapter, surface);
|
||||
const swapchain = try gfx.createSwapchain(adapter, device, surface);
|
||||
const adapter = try gfx.makeAdapter(.{});
|
||||
const surface = try gfx.makeSurface();
|
||||
const device = try gfx.makeDevice(adapter, surface);
|
||||
const swapchain = try gfx.makeSwapchain(adapter, device, surface);
|
||||
|
||||
// --- BUFFERS ---
|
||||
const vbuf = try gfx.createBuffer(vertices, .vertex, adapter, device);
|
||||
const ibuf = try gfx.createBuffer(indices, .index, adapter, device);
|
||||
const vbuf = try gfx.makeBuffer(vertices, .vertex, adapter, device);
|
||||
const ibuf = try gfx.makeBuffer(indices, .index, adapter, device);
|
||||
|
||||
// --- SHADERS ---
|
||||
const simple_shader = try gfx.createShader(
|
||||
"assets/shaders/compiled/simple.vert.spv",
|
||||
"assets/shaders/compiled/simple.frag.spv",
|
||||
device,
|
||||
);
|
||||
const simple_vert = try gfx.makeShader("examples/assets/shaders/compiled/simple.vert.spv", device);
|
||||
const simple_frag = try gfx.makeShader("examples/assets/shaders/compiled/simple.frag.spv", device);
|
||||
|
||||
const pipeline = try gfx.createPipeline(.{
|
||||
// --- PIPELINE ---
|
||||
const pipeline = try gfx.makePipeline(.{
|
||||
.vertex_attributes = &.{
|
||||
.{ .location = 0, .format = .vec2, .offset = @offsetOf(Vertex, "pos") },
|
||||
.{ .location = 1, .format = .vec2, .offset = @offsetOf(Vertex, "normal") },
|
||||
|
|
@ -90,18 +100,24 @@ pub fn main(init: std.process.Init) !void {
|
|||
},
|
||||
.vertex_binding = .{ .stride = @sizeOf(Vertex) },
|
||||
|
||||
.shader = simple_shader,
|
||||
.uniforms = &.{
|
||||
.{ .name = "material", .offset = 0, .size = @sizeOf(UnlitMaterial) },
|
||||
},
|
||||
|
||||
.vert_shader = simple_vert,
|
||||
.frag_shader = simple_frag,
|
||||
|
||||
.device = device,
|
||||
.swapchain = swapchain,
|
||||
});
|
||||
|
||||
try pipeline.setUniform("uTime", 0.1);
|
||||
try pipeline.setUniform("uTime", 0.1);
|
||||
|
||||
// --- MISC ---
|
||||
var event: sdl.SDL_Event = undefined;
|
||||
var running: bool = true;
|
||||
var i: f32 = 0;
|
||||
|
||||
while (running) {
|
||||
// --- INPUTS ---
|
||||
while (sdl.SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
sdl.SDL_EVENT_QUIT => running = false,
|
||||
|
|
@ -109,24 +125,34 @@ pub fn main(init: std.process.Init) !void {
|
|||
}
|
||||
}
|
||||
|
||||
// --- ANIMATION ---
|
||||
i += 0.001;
|
||||
i = @mod(i, 1);
|
||||
material.albedo[1] = i;
|
||||
try pipeline.setUniform("material", material);
|
||||
|
||||
// --- FRAME ---
|
||||
try gfx.beginFrame(swapchain, device);
|
||||
defer gfx.endFrame(swapchain, device) catch unreachable;
|
||||
|
||||
{
|
||||
try gfx.beginRendering(swapchain);
|
||||
defer gfx.endRendering(swapchain) catch unreachable;
|
||||
// --- NEW PASS ---
|
||||
if (gfx.beginPass(swapchain, .{
|
||||
.clear_color = .{ 0.01, 0.01, 0.01, 1.0 },
|
||||
})) |pass| {
|
||||
defer pass.end();
|
||||
|
||||
try pipeline.bind();
|
||||
try vbuf.bind();
|
||||
try ibuf.bind();
|
||||
try gfx.drawIndexed(indices.len, 1, 0, 0, 0);
|
||||
|
||||
try pipeline.bind();
|
||||
pass.drawIndexed(indices.len, 1, 0, 0, 0);
|
||||
}
|
||||
|
||||
// if (gfx.beginRendering(...)) |pass| {
|
||||
// defer pass.end();
|
||||
//
|
||||
// try pass.bindPipeline(...);
|
||||
// try pass.draw(...);
|
||||
// }
|
||||
// --- NEW PASS ---
|
||||
if (gfx.beginPass(swapchain, .{
|
||||
.load_op = .load,
|
||||
})) |pass| {
|
||||
defer pass.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
86
src/gfx.zig
86
src/gfx.zig
|
|
@ -11,8 +11,11 @@ const Handle = gtl.Handle;
|
|||
const Self = @This();
|
||||
|
||||
// --- CONFIGS ---
|
||||
const AdapterConfig = common.AdapterConfig;
|
||||
const RenderPassConfig = common.RenderPassConfig;
|
||||
const PipelineConfig = common.PipelineConfig;
|
||||
const BufferUsage = common.BufferUsage;
|
||||
const Pass = common.Pass;
|
||||
|
||||
// --- HANDLES ---
|
||||
const Window = @import("rhi/root.zig").Window;
|
||||
|
|
@ -88,21 +91,21 @@ pub fn deinit(self: *Self) void {
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn createAdapter(self: *Self) !Handle(Adapter) {
|
||||
pub fn makeAdapter(self: *Self, config: AdapterConfig) !Handle(Adapter) {
|
||||
return try switch (self.ctx) {
|
||||
.vulkan => |*v| v.createAdapter(),
|
||||
.vulkan => |*v| v.makeAdapter(config),
|
||||
};
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn createDevice(
|
||||
pub fn makeDevice(
|
||||
self: *Self,
|
||||
adapter: Handle(Adapter),
|
||||
surface: Handle(Surface),
|
||||
) !Handle(Device) {
|
||||
return try switch (self.ctx) {
|
||||
.vulkan => |*v| v.createDevice(adapter, surface),
|
||||
.vulkan => |*v| v.makeDevice(adapter, surface),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -116,7 +119,7 @@ pub fn destroyDevice(self: *Self, device: Handle(Device)) !void {
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn createBuffer(
|
||||
pub fn makeBuffer(
|
||||
self: *Self,
|
||||
value: anytype,
|
||||
usage: BufferUsage,
|
||||
|
|
@ -126,7 +129,7 @@ pub fn createBuffer(
|
|||
const size = @sizeOf(@TypeOf(value));
|
||||
|
||||
const handle = try switch (self.ctx) {
|
||||
.vulkan => |*v| v.createBuffer(size, usage, .exclusive, adapter, device),
|
||||
.vulkan => |*v| v.makeBuffer(size, usage, .exclusive, adapter, device),
|
||||
};
|
||||
|
||||
var buffer: Buffer = .{
|
||||
|
|
@ -140,45 +143,52 @@ pub fn createBuffer(
|
|||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// TODO:
|
||||
/// ----------------------------------------------------
|
||||
pub fn createSurface(self: *Self) !Handle(Surface) {
|
||||
pub fn getRawVKBuffer(self: *Self, buffer: Handle(Buffer)) !void {
|
||||
_ = self;
|
||||
_ = buffer;
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn makeSurface(self: *Self) !Handle(Surface) {
|
||||
return try switch (self.ctx) {
|
||||
.vulkan => |*v| v.createSurface(),
|
||||
.vulkan => |*v| v.makeSurface(),
|
||||
};
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn createSwapchain(
|
||||
pub fn makeSwapchain(
|
||||
self: *Self,
|
||||
adapter: Handle(Adapter),
|
||||
device: Handle(Device),
|
||||
surface: Handle(Surface),
|
||||
) !Handle(Swapchain) {
|
||||
return try switch (self.ctx) {
|
||||
.vulkan => |*v| v.createSwapchain(adapter, device, surface),
|
||||
.vulkan => |*v| v.makeSwapchain(adapter, device, surface),
|
||||
};
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn createShader(
|
||||
pub fn makeShader(
|
||||
self: *Self,
|
||||
vert_spv_path: []const u8,
|
||||
frag_spv_path: []const u8,
|
||||
spv_path: []const u8,
|
||||
device: Handle(Device),
|
||||
) !Handle(Shader) {
|
||||
return try switch (self.ctx) {
|
||||
.vulkan => |*v| v.createShader(vert_spv_path, frag_spv_path, device),
|
||||
.vulkan => |*v| v.makeShader(spv_path, device),
|
||||
};
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn createPipeline(self: *Self, config: PipelineConfig) !Pipeline {
|
||||
pub fn makePipeline(self: *Self, config: PipelineConfig) !Pipeline {
|
||||
return .{
|
||||
.handle = try switch (self.ctx) {
|
||||
.vulkan => |*v| v.createPipeline(config),
|
||||
.vulkan => |*v| v.makePipeline(config),
|
||||
},
|
||||
.device = config.device,
|
||||
.gfx = self,
|
||||
|
|
@ -211,43 +221,17 @@ pub fn endFrame(
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn beginRendering(
|
||||
pub fn beginPass(
|
||||
self: *Self,
|
||||
swapchain: Handle(Swapchain),
|
||||
) !void {
|
||||
try switch (self.ctx) {
|
||||
.vulkan => |*v| v.beginRendering(swapchain),
|
||||
};
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn endRendering(
|
||||
self: *Self,
|
||||
swapchain: Handle(Swapchain),
|
||||
) !void {
|
||||
try switch (self.ctx) {
|
||||
.vulkan => |*v| v.endRendering(swapchain),
|
||||
};
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn draw(self: *Self, vertex_count: u32, instance_count: u32, first_vertex: u32, first_instance: u32) !void {
|
||||
try switch (self.ctx) {
|
||||
.vulkan => |*v| v.draw(vertex_count, instance_count, first_vertex, first_instance),
|
||||
};
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn drawIndexed(self: *Self, index_count: u32, instance_count: u32, first_index: u32, vertex_offset: i32, first_instance: u32) !void {
|
||||
config: RenderPassConfig,
|
||||
) ?Pass {
|
||||
switch (self.ctx) {
|
||||
.vulkan => |*v| {
|
||||
const frame = v.currentFrame();
|
||||
if (frame.cmd_buf) |cmd| {
|
||||
vk.vkCmdDrawIndexed(cmd, index_count, instance_count, first_index, vertex_offset, first_instance);
|
||||
}
|
||||
},
|
||||
.vulkan => |*v| v.beginRendering(swapchain, config) catch return null,
|
||||
}
|
||||
|
||||
return .{
|
||||
.swapchain = swapchain,
|
||||
.gfx = self,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,24 @@ pub const Window = union(enum) {
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const AdapterConfig = struct {};
|
||||
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
|
||||
index: ?u32 = null,
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
|
|
@ -72,16 +89,28 @@ pub const VertexAttribute = struct {
|
|||
format: Format,
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const UniformDesc = struct {
|
||||
name: []const u8,
|
||||
offset: u32,
|
||||
size: u32,
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const PipelineConfig = struct {
|
||||
shader: Handle(Shader),
|
||||
vert_shader: Handle(Shader),
|
||||
frag_shader: Handle(Shader),
|
||||
|
||||
swapchain: Handle(Swapchain),
|
||||
device: Handle(Device),
|
||||
|
||||
vertex_binding: ?VertexBinding = null,
|
||||
vertex_attributes: []const VertexAttribute = &.{},
|
||||
|
||||
uniforms: []const UniformDesc = &.{},
|
||||
|
||||
topology: enum {
|
||||
triangle_list,
|
||||
line_list,
|
||||
|
|
@ -100,6 +129,65 @@ pub const PipelineConfig = struct {
|
|||
} = .cw,
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const Pass = struct {
|
||||
swapchain: Handle(Swapchain),
|
||||
gfx: *Gfx,
|
||||
|
||||
pub fn end(self: *const Pass) void {
|
||||
switch (self.gfx.ctx) {
|
||||
.vulkan => |*v| v.endRendering(self.swapchain),
|
||||
}
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn draw(self: *const Pass, vertex_count: u32, instance_count: u32, first_vertex: u32, first_instance: u32) void {
|
||||
switch (self.gfx.ctx) {
|
||||
.vulkan => |*v| v.draw(vertex_count, instance_count, first_vertex, first_instance) catch {},
|
||||
}
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
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) {
|
||||
.vulkan => |*v| {
|
||||
const frame = v.currentFrame();
|
||||
if (frame.cmd_buf) |cmd| {
|
||||
vk.vkCmdDrawIndexed(cmd, index_count, instance_count, first_index, vertex_offset, first_instance);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const LoadOp = enum {
|
||||
clear,
|
||||
load,
|
||||
dont_care,
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const StoreOp = enum {
|
||||
store,
|
||||
dont_care,
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const RenderPassConfig = struct {
|
||||
clear_color: [4]f32 = .{ 0.0, 0.0, 0.0, 1.0 },
|
||||
load_op: LoadOp = .clear,
|
||||
store_op: StoreOp = .store,
|
||||
width: ?u32 = null,
|
||||
height: ?u32 = null,
|
||||
};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const BufferUsage = enum {
|
||||
|
|
@ -175,8 +263,8 @@ pub const Pipeline = struct {
|
|||
}
|
||||
|
||||
pub fn setUniform(self: *const Pipeline, name: []const u8, value: anytype) !void {
|
||||
_ = self;
|
||||
_ = name;
|
||||
_ = value;
|
||||
try switch (self.gfx.ctx) {
|
||||
.vulkan => |*v| v.setUniform(self.handle, name, value),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ const std = @import("std");
|
|||
const gtl = @import("gtl");
|
||||
const vk = @import("vulkan");
|
||||
const VKBackend = @import("../vulkan.zig");
|
||||
const AdapterConfig = @import("../../root.zig").AdapterConfig;
|
||||
const GpuType = @import("../../root.zig").GpuType;
|
||||
const Self = @This();
|
||||
|
||||
//
|
||||
|
|
@ -16,7 +18,7 @@ raw: *vk.VkPhysicalDevice_T,
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn init(backend: *const VKBackend) !Self {
|
||||
pub fn init(backend: *const VKBackend, config: AdapterConfig) !Self {
|
||||
var physical: vk.VkPhysicalDevice = null;
|
||||
var count: u32 = 0;
|
||||
|
||||
|
|
@ -38,12 +40,18 @@ pub fn init(backend: *const VKBackend) !Self {
|
|||
}
|
||||
|
||||
// --- CHECK WHICH DEVICE IS SUITABLE ---
|
||||
for (devices) |device| {
|
||||
if (try isDeviceSuitable(device)) {
|
||||
for (devices, 0..) |device, i| {
|
||||
if (config.index) |index| {
|
||||
if (index != i) continue;
|
||||
}
|
||||
if (try isDeviceSuitable(device, config.gpu_type)) {
|
||||
physical = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (physical == null) {
|
||||
return error.FailedToFindSuitableDevice;
|
||||
}
|
||||
|
||||
// --- FIND GFX QUEUE FAMILY ---
|
||||
var queue_family_index: u32 = 0;
|
||||
|
|
@ -83,7 +91,7 @@ fn findGraphicsQueueFamily(
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
fn isDeviceSuitable(device: vk.VkPhysicalDevice) !bool {
|
||||
fn isDeviceSuitable(device: vk.VkPhysicalDevice, gpu_type: GpuType) !bool {
|
||||
var properties: vk.VkPhysicalDeviceProperties = .{};
|
||||
vk.vkGetPhysicalDeviceProperties(device, &properties);
|
||||
|
||||
|
|
@ -102,5 +110,12 @@ fn isDeviceSuitable(device: vk.VkPhysicalDevice) !bool {
|
|||
});
|
||||
}
|
||||
|
||||
return properties.deviceType == vk.VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU and features.geometryShader == 1;
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ pub const QueueFamilies = struct {
|
|||
//
|
||||
|
||||
raw: *vk.VkDevice_T,
|
||||
physical_device: vk.VkPhysicalDevice,
|
||||
graphics_queue: *vk.VkQueue_T,
|
||||
present_queue: *vk.VkQueue_T,
|
||||
graphics_command_pool: *vk.VkCommandPool_T,
|
||||
|
|
@ -109,6 +110,7 @@ pub fn init(
|
|||
|
||||
return .{
|
||||
.raw = device.?,
|
||||
.physical_device = adapter.raw,
|
||||
.graphics_queue = graphics_queue.?,
|
||||
.present_queue = present_queue.?,
|
||||
.graphics_command_pool = graphics_command_pool.?,
|
||||
|
|
|
|||
|
|
@ -5,55 +5,116 @@
|
|||
const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
const gtl = @import("gtl");
|
||||
const VulkanRHI = @import("../vulkan.zig");
|
||||
const Self = @This();
|
||||
|
||||
const Device = @import("device.zig");
|
||||
const Shader = @import("shader.zig");
|
||||
const Swapchain = @import("swapchain.zig");
|
||||
const Config = @import("../../root.zig").PipelineConfig;
|
||||
const UniformDesc = @import("../../root.zig").UniformDesc;
|
||||
|
||||
//
|
||||
// FIELDS
|
||||
//
|
||||
|
||||
raw: *vk.VkPipeline_T,
|
||||
layout: *vk.VkPipelineLayout_T,
|
||||
raw: vk.VkPipeline = null,
|
||||
layout: vk.VkPipelineLayout = null,
|
||||
device: *const Device,
|
||||
|
||||
descriptor_set_layout: vk.VkDescriptorSetLayout = null,
|
||||
descriptor_pool: vk.VkDescriptorPool = null,
|
||||
descriptor_set: vk.VkDescriptorSet = null,
|
||||
|
||||
uniform_buffer: vk.VkBuffer = null,
|
||||
uniform_memory: vk.VkDeviceMemory = null,
|
||||
uniforms: []UniformDesc,
|
||||
|
||||
alloc: std.mem.Allocator,
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn init(
|
||||
shader: *const Shader,
|
||||
swapchain: *const Swapchain,
|
||||
device: *const Device,
|
||||
config: Config,
|
||||
vulkan: *VulkanRHI,
|
||||
alloc: std.mem.Allocator,
|
||||
) !Self {
|
||||
var self: Self = .{
|
||||
.device = device,
|
||||
.uniforms = &.{},
|
||||
.alloc = alloc,
|
||||
};
|
||||
errdefer self.deinit();
|
||||
|
||||
// --- COMPUTE UNIFORM LAYOUT ---
|
||||
var uniform_size: u32 = 0;
|
||||
for (config.uniforms) |u| {
|
||||
uniform_size = @max(uniform_size, u.offset + u.size);
|
||||
}
|
||||
uniform_size = std.mem.alignForward(u32, uniform_size, 16);
|
||||
|
||||
// --- COPY UNIFORMS ---
|
||||
if (config.uniforms.len > 0) {
|
||||
const uniforms = try alloc.alloc(UniformDesc, config.uniforms.len);
|
||||
@memcpy(uniforms, config.uniforms);
|
||||
self.uniforms = uniforms;
|
||||
}
|
||||
|
||||
//
|
||||
// LAYOUT
|
||||
//
|
||||
|
||||
var set_layout: vk.VkDescriptorSetLayout = null;
|
||||
|
||||
if (uniform_size > 0) {
|
||||
const bindings = [_]vk.VkDescriptorSetLayoutBinding{
|
||||
.{
|
||||
.binding = 0,
|
||||
.descriptorType = vk.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk.VK_SHADER_STAGE_VERTEX_BIT | vk.VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
.pImmutableSamplers = null,
|
||||
},
|
||||
};
|
||||
|
||||
var set_layout_info: vk.VkDescriptorSetLayoutCreateInfo = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.bindingCount = bindings.len,
|
||||
.pBindings = &bindings,
|
||||
};
|
||||
|
||||
if (vk.vkCreateDescriptorSetLayout(device.raw, &set_layout_info, null, &set_layout) != vk.VK_SUCCESS) {
|
||||
return error.FailedToCreateDescriptorSetLayout;
|
||||
}
|
||||
self.descriptor_set_layout = set_layout.?;
|
||||
}
|
||||
|
||||
var pipeline_layout_info: vk.VkPipelineLayoutCreateInfo = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.setLayoutCount = if (set_layout != null) 1 else 0,
|
||||
.pSetLayouts = if (set_layout != null) @ptrCast(&set_layout) else null,
|
||||
};
|
||||
|
||||
var pipeline_layout: vk.VkPipelineLayout = null;
|
||||
if (vk.vkCreatePipelineLayout(device.raw, &pipeline_layout_info, null, &pipeline_layout) != vk.VK_SUCCESS) {
|
||||
return error.FailedToCreatePipelineLayout;
|
||||
}
|
||||
errdefer vk.vkDestroyPipelineLayout(device.raw, pipeline_layout, null);
|
||||
self.layout = pipeline_layout.?;
|
||||
|
||||
//
|
||||
// PIPELINE
|
||||
//
|
||||
|
||||
const raw_vert_shader = vulkan.resource.shaders.get(config.vert_shader) orelse return error.VertexShaderNotFound;
|
||||
const raw_frag_shader = vulkan.resource.shaders.get(config.frag_shader) orelse return error.FragmentShaderNotFound;
|
||||
|
||||
const vert_shader_stage_info: vk.VkPipelineShaderStageCreateInfo = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.stage = vk.VK_SHADER_STAGE_VERTEX_BIT,
|
||||
|
||||
.pName = "main",
|
||||
.module = shader.vert,
|
||||
.module = raw_vert_shader.raw,
|
||||
};
|
||||
|
||||
const frag_shader_stage_info: vk.VkPipelineShaderStageCreateInfo = .{
|
||||
|
|
@ -61,7 +122,7 @@ pub fn init(
|
|||
.stage = vk.VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
|
||||
.pName = "main",
|
||||
.module = shader.frag,
|
||||
.module = raw_frag_shader.raw,
|
||||
};
|
||||
|
||||
var shader_stages = [_]vk.VkPipelineShaderStageCreateInfo{
|
||||
|
|
@ -231,17 +292,167 @@ pub fn init(
|
|||
if (vk.vkCreateGraphicsPipelines(device.raw, null, 1, &pipeline_info, null, &pipeline) != vk.VK_SUCCESS) {
|
||||
return error.FailedToCreateGraphicsPipelines;
|
||||
}
|
||||
self.raw = pipeline.?;
|
||||
|
||||
return .{
|
||||
.raw = pipeline.?,
|
||||
.layout = pipeline_layout.?,
|
||||
.device = device,
|
||||
//
|
||||
// UNIFORM BUFFER + DESCRIPTORS
|
||||
//
|
||||
|
||||
if (uniform_size > 0) {
|
||||
var buffer_info: vk.VkBufferCreateInfo = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.size = uniform_size,
|
||||
.usage = vk.VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||
.sharingMode = vk.VK_SHARING_MODE_EXCLUSIVE,
|
||||
};
|
||||
|
||||
var uniform_buffer: vk.VkBuffer = null;
|
||||
if (vk.vkCreateBuffer(device.raw, &buffer_info, null, &uniform_buffer) != vk.VK_SUCCESS) {
|
||||
return error.FailedToCreateUniformBuffer;
|
||||
}
|
||||
self.uniform_buffer = uniform_buffer.?;
|
||||
|
||||
var mem_req: vk.VkMemoryRequirements = .{};
|
||||
var mem_props: vk.VkPhysicalDeviceMemoryProperties = .{};
|
||||
|
||||
vk.vkGetBufferMemoryRequirements(device.raw, uniform_buffer, &mem_req);
|
||||
vk.vkGetPhysicalDeviceMemoryProperties(device.physical_device, &mem_props);
|
||||
|
||||
var mem_type: u32 = 0;
|
||||
for (0..mem_props.memoryTypeCount) |i| {
|
||||
if ((mem_req.memoryTypeBits & (@as(u32, 1) << @intCast(i))) != 0 and
|
||||
(mem_props.memoryTypes[i].propertyFlags &
|
||||
(vk.VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
vk.VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) != 0)
|
||||
{
|
||||
mem_type = @intCast(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var alloc_info: vk.VkMemoryAllocateInfo = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.allocationSize = mem_req.size,
|
||||
.memoryTypeIndex = mem_type,
|
||||
};
|
||||
|
||||
var uniform_memory: vk.VkDeviceMemory = null;
|
||||
if (vk.vkAllocateMemory(device.raw, &alloc_info, null, &uniform_memory) != vk.VK_SUCCESS) {
|
||||
return error.FailedToAllocateUniformMemory;
|
||||
}
|
||||
self.uniform_memory = uniform_memory;
|
||||
|
||||
_ = vk.vkBindBufferMemory(device.raw, uniform_buffer, uniform_memory, 0);
|
||||
|
||||
// --- DESCRIPTOR POOL ---
|
||||
const pool_sizes = [_]vk.VkDescriptorPoolSize{
|
||||
.{
|
||||
.type = vk.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
},
|
||||
};
|
||||
|
||||
var pool_info: vk.VkDescriptorPoolCreateInfo = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.poolSizeCount = pool_sizes.len,
|
||||
.pPoolSizes = &pool_sizes,
|
||||
.maxSets = 1,
|
||||
};
|
||||
|
||||
var descriptor_pool: vk.VkDescriptorPool = null;
|
||||
if (vk.vkCreateDescriptorPool(device.raw, &pool_info, null, &descriptor_pool) != vk.VK_SUCCESS) {
|
||||
return error.FailedToCreateDescriptorPool;
|
||||
}
|
||||
self.descriptor_pool = descriptor_pool.?;
|
||||
|
||||
// --- DESCRIPTOR SET ---
|
||||
var set_alloc_info: vk.VkDescriptorSetAllocateInfo = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.descriptorPool = descriptor_pool,
|
||||
.descriptorSetCount = 1,
|
||||
.pSetLayouts = @ptrCast(&self.descriptor_set_layout),
|
||||
};
|
||||
|
||||
if (vk.vkAllocateDescriptorSets(device.raw, &set_alloc_info, &self.descriptor_set) != vk.VK_SUCCESS) {
|
||||
return error.FailedToAllocateDescriptorSets;
|
||||
}
|
||||
|
||||
// --- WRITE DESCRIPTOR SET ---
|
||||
const buffer_descriptor: vk.VkDescriptorBufferInfo = .{
|
||||
.buffer = uniform_buffer,
|
||||
.offset = 0,
|
||||
.range = uniform_size,
|
||||
};
|
||||
|
||||
const write_descriptor: vk.VkWriteDescriptorSet = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = self.descriptor_set,
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.pBufferInfo = &buffer_descriptor,
|
||||
};
|
||||
|
||||
vk.vkUpdateDescriptorSets(device.raw, 1, &write_descriptor, 0, null);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn deinit(self: *Self) void {
|
||||
vk.vkDestroyPipelineLayout(self.device.raw, self.layout, null);
|
||||
vk.vkDestroyPipeline(self.device.raw, self.raw, null);
|
||||
if (self.descriptor_set_layout) |set_layout| {
|
||||
vk.vkDestroyDescriptorSetLayout(self.device.raw, set_layout, null);
|
||||
}
|
||||
if (self.descriptor_pool) |pool| {
|
||||
vk.vkDestroyDescriptorPool(self.device.raw, pool, null);
|
||||
}
|
||||
if (self.uniform_memory) |memory| {
|
||||
vk.vkFreeMemory(self.device.raw, memory, null);
|
||||
}
|
||||
if (self.uniform_buffer) |buffer| {
|
||||
vk.vkDestroyBuffer(self.device.raw, buffer, null);
|
||||
}
|
||||
if (self.layout) |layout| {
|
||||
vk.vkDestroyPipelineLayout(self.device.raw, layout, null);
|
||||
}
|
||||
if (self.raw) |raw| {
|
||||
vk.vkDestroyPipeline(self.device.raw, raw, null);
|
||||
}
|
||||
self.alloc.free(self.uniforms);
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// Set a uniform value by name
|
||||
/// ----------------------------------------------------
|
||||
pub fn setUniform(self: *Self, name: []const u8, value: anytype) !void {
|
||||
for (self.uniforms) |uniform| {
|
||||
if (std.mem.eql(u8, uniform.name, name)) {
|
||||
if (@sizeOf(@TypeOf(value)) > uniform.size) {
|
||||
return error.UniformSizeMismatch;
|
||||
}
|
||||
|
||||
var mapped: ?*anyopaque = null;
|
||||
if (vk.vkMapMemory(
|
||||
self.device.raw,
|
||||
self.uniform_memory,
|
||||
uniform.offset,
|
||||
uniform.size,
|
||||
0,
|
||||
&mapped,
|
||||
) != vk.VK_SUCCESS) {
|
||||
return error.FailedToMapMemory;
|
||||
}
|
||||
|
||||
const dst: [*]u8 = @ptrCast(mapped.?);
|
||||
const src: [*]const u8 = @ptrCast(&value);
|
||||
@memcpy(dst[0..@sizeOf(@TypeOf(value))], src[0..@sizeOf(@TypeOf(value))]);
|
||||
|
||||
vk.vkUnmapMemory(self.device.raw, self.uniform_memory);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return error.UniformNotFound;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,31 +12,27 @@ const Self = @This();
|
|||
// FIELDS
|
||||
//
|
||||
|
||||
vert: *vk.VkShaderModule_T,
|
||||
frag: *vk.VkShaderModule_T,
|
||||
raw: *vk.VkShaderModule_T,
|
||||
device: *const Device,
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn init(
|
||||
vert_spv_path: []const u8,
|
||||
frag_spv_path: []const u8,
|
||||
spv_path: []const u8,
|
||||
device: *const Device,
|
||||
alloc: std.mem.Allocator,
|
||||
io: std.Io,
|
||||
) !Self {
|
||||
const vert_code = try readFile(vert_spv_path, alloc, io);
|
||||
defer alloc.free(vert_code);
|
||||
const code = try readFile(spv_path, alloc, io);
|
||||
defer alloc.free(code);
|
||||
|
||||
const frag_code = try readFile(frag_spv_path, alloc, io);
|
||||
defer alloc.free(frag_code);
|
||||
|
||||
const vert_module = try createModule(vert_code, device);
|
||||
const frag_module = try createModule(frag_code, device);
|
||||
const module = try createModule(
|
||||
code,
|
||||
device,
|
||||
);
|
||||
|
||||
return .{
|
||||
.vert = vert_module,
|
||||
.frag = frag_module,
|
||||
.raw = module,
|
||||
.device = device,
|
||||
};
|
||||
}
|
||||
|
|
@ -44,8 +40,7 @@ pub fn init(
|
|||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn deinit(self: *Self) void {
|
||||
vk.vkDestroyShaderModule(self.device.raw, self.vert, null);
|
||||
vk.vkDestroyShaderModule(self.device.raw, self.frag, null);
|
||||
vk.vkDestroyShaderModule(self.device.raw, self.raw, null);
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ const BufferUsage = common.BufferUsage;
|
|||
const BufferSharingMode = common.BufferSharingMode;
|
||||
|
||||
// --- CONFIGS ---
|
||||
const AdapterConfig = common.AdapterConfig;
|
||||
const RenderPassConfig = common.RenderPassConfig;
|
||||
const PipelineConfig = common.PipelineConfig;
|
||||
|
||||
// --- HANDLES ---
|
||||
|
|
@ -63,10 +65,6 @@ sync_device: ?*vk.VkDevice_T = null,
|
|||
alloc: std.mem.Allocator,
|
||||
io: std.Io,
|
||||
|
||||
pub fn currentFrame(self: *Self) *Frame {
|
||||
return &self.frames[self.current_frame];
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn init(
|
||||
|
|
@ -114,13 +112,13 @@ pub fn deinit(self: *Self) void {
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn createAdapter(self: *Self) !Handle(Adapter) {
|
||||
return try self.resource.adapters.put(try .init(self));
|
||||
pub fn makeAdapter(self: *Self, config: AdapterConfig) !Handle(Adapter) {
|
||||
return try self.resource.adapters.put(try .init(self, config));
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn createDevice(
|
||||
pub fn makeDevice(
|
||||
self: *Self,
|
||||
adapter: Handle(Adapter),
|
||||
surface: Handle(Surface),
|
||||
|
|
@ -141,13 +139,13 @@ pub fn destroyDevice(self: *Self, device: Handle(Device)) !void {
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn createSurface(self: *Self) !Handle(Surface) {
|
||||
pub fn makeSurface(self: *Self) !Handle(Surface) {
|
||||
return try self.resource.surfaces.put(try .init(&self.instance, self.config.window));
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn createSwapchain(
|
||||
pub fn makeSwapchain(
|
||||
self: *Self,
|
||||
adapter: Handle(Adapter),
|
||||
device: Handle(Device),
|
||||
|
|
@ -168,28 +166,26 @@ pub fn createSwapchain(
|
|||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn createShader(
|
||||
pub fn makeShader(
|
||||
self: *Self,
|
||||
vert_spv_path: []const u8,
|
||||
frag_spv_path: []const u8,
|
||||
spv_path: []const u8,
|
||||
device: Handle(Device),
|
||||
) !Handle(Shader) {
|
||||
const raw_device = self.resource.devices.get(device) orelse return error.DeviceNotFound;
|
||||
return try self.resource.shaders.put(try .init(vert_spv_path, frag_spv_path, raw_device, self.alloc, self.io));
|
||||
return try self.resource.shaders.put(try .init(spv_path, raw_device, self.alloc, self.io));
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn createPipeline(self: *Self, config: PipelineConfig) !Handle(Pipeline) {
|
||||
pub fn makePipeline(self: *Self, config: PipelineConfig) !Handle(Pipeline) {
|
||||
const raw_device = self.resource.devices.get(config.device) orelse return error.DeviceNotFound;
|
||||
const raw_swapchain = self.resource.swapchains.get(config.swapchain) orelse return error.SwapchainNotFound;
|
||||
const raw_shader = self.resource.shaders.get(config.shader) orelse return error.ShaderNotFound;
|
||||
return try self.resource.pipelines.put(try .init(raw_shader, raw_swapchain, raw_device, config, self.alloc));
|
||||
return try self.resource.pipelines.put(try .init(raw_swapchain, raw_device, config, self, self.alloc));
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn createBuffer(
|
||||
pub fn makeBuffer(
|
||||
self: *Self,
|
||||
size: u32,
|
||||
usage: BufferUsage,
|
||||
|
|
@ -202,25 +198,6 @@ pub fn createBuffer(
|
|||
return try self.resource.buffers.put(try .init(size, usage, sharing, raw_adapter, raw_device));
|
||||
}
|
||||
|
||||
// /// ----------------------------------------------------
|
||||
// /// ----------------------------------------------------
|
||||
// pub const AttributeDesc = struct {
|
||||
// binding: u32,
|
||||
// location: u32,
|
||||
// uniform_type: UniformType,
|
||||
// offset: u32,
|
||||
// };
|
||||
|
||||
// /// ----------------------------------------------------
|
||||
// /// ----------------------------------------------------
|
||||
// pub fn createUniform(
|
||||
// self: *Self,
|
||||
// attributes: []const AttributeDesc,
|
||||
// ) !void {
|
||||
// _ = self;
|
||||
// _ = attributes;
|
||||
// }
|
||||
|
||||
//
|
||||
// FRAME + RENDERING
|
||||
//
|
||||
|
|
@ -355,11 +332,17 @@ pub fn endFrame(
|
|||
pub fn beginRendering(
|
||||
self: *Self,
|
||||
swapchain: Handle(Swapchain),
|
||||
config: RenderPassConfig,
|
||||
) !void {
|
||||
const raw_swapchain = self.resource.swapchains.get(swapchain) orelse return error.SwapchainNotFound;
|
||||
|
||||
const frame = self.currentFrame();
|
||||
|
||||
const extent: vk.VkExtent2D = .{
|
||||
.width = config.width orelse raw_swapchain.extent.width,
|
||||
.height = config.height orelse raw_swapchain.extent.height,
|
||||
};
|
||||
|
||||
const barrier: vk.VkImageMemoryBarrier = .{
|
||||
.sType = vk.VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
|
||||
|
|
@ -405,11 +388,18 @@ pub fn beginRendering(
|
|||
.sType = vk.VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||
.imageView = raw_swapchain.image_views[frame.image_index],
|
||||
.imageLayout = vk.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.loadOp = vk.VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
.storeOp = vk.VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.loadOp = switch (config.load_op) {
|
||||
.clear => vk.VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
.load => vk.VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
.dont_care => vk.VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
},
|
||||
.storeOp = switch (config.store_op) {
|
||||
.store => vk.VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.dont_care => vk.VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
},
|
||||
.clearValue = .{
|
||||
.color = .{
|
||||
.float32 = .{ 0.01, 0.01, 0.01, 1.0 },
|
||||
.float32 = config.clear_color,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -421,7 +411,7 @@ pub fn beginRendering(
|
|||
.x = 0,
|
||||
.y = 0,
|
||||
},
|
||||
.extent = raw_swapchain.extent,
|
||||
.extent = extent,
|
||||
},
|
||||
.layerCount = 1,
|
||||
.colorAttachmentCount = 1,
|
||||
|
|
@ -436,8 +426,8 @@ pub fn beginRendering(
|
|||
const viewport: vk.VkViewport = .{
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = @floatFromInt(raw_swapchain.extent.width),
|
||||
.height = @floatFromInt(raw_swapchain.extent.height),
|
||||
.width = @floatFromInt(extent.width),
|
||||
.height = @floatFromInt(extent.height),
|
||||
.minDepth = 0.0,
|
||||
.maxDepth = 1.0,
|
||||
};
|
||||
|
|
@ -447,7 +437,7 @@ pub fn beginRendering(
|
|||
.x = 0,
|
||||
.y = 0,
|
||||
},
|
||||
.extent = raw_swapchain.extent,
|
||||
.extent = extent,
|
||||
};
|
||||
|
||||
vk.vkCmdSetViewport(frame.cmd_buf, 0, 1, &viewport);
|
||||
|
|
@ -459,8 +449,8 @@ pub fn beginRendering(
|
|||
pub fn endRendering(
|
||||
self: *Self,
|
||||
swapchain: Handle(Swapchain),
|
||||
) !void {
|
||||
const raw_swapchain = self.resource.swapchains.get(swapchain) orelse return error.SwapchainNotFound;
|
||||
) void {
|
||||
const raw_swapchain = self.resource.swapchains.get(swapchain) orelse return;
|
||||
|
||||
const frame = self.currentFrame();
|
||||
|
||||
|
|
@ -512,7 +502,27 @@ pub fn endRendering(
|
|||
/// ----------------------------------------------------
|
||||
pub fn bindPipeline(self: *Self, pipeline: Handle(Pipeline)) !void {
|
||||
const raw_pipeline = self.resource.pipelines.get(pipeline) orelse return error.PipelineNotFound;
|
||||
vk.vkCmdBindPipeline(self.currentFrame().cmd_buf, vk.VK_PIPELINE_BIND_POINT_GRAPHICS, raw_pipeline.raw);
|
||||
const frame = self.currentFrame();
|
||||
vk.vkCmdBindPipeline(frame.cmd_buf, vk.VK_PIPELINE_BIND_POINT_GRAPHICS, raw_pipeline.raw.?);
|
||||
if (raw_pipeline.descriptor_set) |set| {
|
||||
vk.vkCmdBindDescriptorSets(
|
||||
frame.cmd_buf,
|
||||
vk.VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
raw_pipeline.layout.?,
|
||||
0,
|
||||
1,
|
||||
&set,
|
||||
0,
|
||||
null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn setUniform(self: *Self, pipeline: Handle(Pipeline), name: []const u8, value: anytype) !void {
|
||||
const raw_pipeline = self.resource.pipelines.get(pipeline) orelse return error.PipelineNotFound;
|
||||
try raw_pipeline.setUniform(name, value);
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
|
|
@ -522,7 +532,13 @@ pub fn draw(self: *Self, vertex_count: u32, instance_count: u32, first_vertex: u
|
|||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// Lazily create the frame sync objects (semaphores + fence)
|
||||
/// ----------------------------------------------------
|
||||
pub fn currentFrame(self: *Self) *Frame {
|
||||
return &self.frames[self.current_frame];
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// Lazily make the frame sync objects (semaphores + fence)
|
||||
/// ----------------------------------------------------
|
||||
fn ensureFrameSync(
|
||||
self: *Self,
|
||||
|
|
@ -550,7 +566,7 @@ fn ensureFrameSync(
|
|||
for (render_finished, 0..) |*semaphore, i| {
|
||||
_ = i;
|
||||
if (vk.vkCreateSemaphore(device, &semaphore_info, null, semaphore) != vk.VK_SUCCESS) {
|
||||
return error.FailedToCreateSemaphore;
|
||||
return error.FailedTomakeSemaphore;
|
||||
}
|
||||
}
|
||||
self.render_finished = render_finished;
|
||||
|
|
@ -558,13 +574,13 @@ fn ensureFrameSync(
|
|||
for (&self.frames) |*frame| {
|
||||
var image_available: vk.VkSemaphore = null;
|
||||
if (vk.vkCreateSemaphore(device, &semaphore_info, null, &image_available) != vk.VK_SUCCESS) {
|
||||
return error.FailedToCreateSemaphore;
|
||||
return error.FailedTomakeSemaphore;
|
||||
}
|
||||
|
||||
var fence: vk.VkFence = null;
|
||||
if (vk.vkCreateFence(device, &fence_info, null, &fence) != vk.VK_SUCCESS) {
|
||||
vk.vkDestroySemaphore(device, image_available, null);
|
||||
return error.FailedToCreateFence;
|
||||
return error.FailedTomakeFence;
|
||||
}
|
||||
|
||||
frame.image_available = image_available.?;
|
||||
|
|
|
|||
BIN
zig-out/bin/simple
Executable file
BIN
zig-out/bin/simple
Executable file
Binary file not shown.
Loading…
Add table
Reference in a new issue